I am using PrintDialog and PrintDocument to generate pdf reports. The files are saved to user defined paths that is set at PrintDialog.
After the print event I want to open the file using System.Diagnostics.Process.Start.
The problem is that I do not know the user defined path.
PrintDialog.Document.PrinterSettings.PrintFileName throws an exception "The given path's format is not supported.".
However the file has been created and saved correctly to the user defined path.
// Allow the user to choose the page range
ProductionPrintDialog.AllowSomePages = true;
// Show the help button.
ProductionPrintDialog.ShowHelp = true;
// Set the Document property to the PrintDocument for
// which the PrintPage Event has been handled. To display the
// dialog, either this property or the PrinterSettings property
// must be set
ProductionPrintDialog.PrintToFile = true;
ProductionPrintDialog.Document = ProductionPrintDocument;
//ProductionPrintDialog.Document.PrinterSettings.PrintFileName = "c:\\test.pdf";
DialogResult result = ProductionPrintDialog.ShowDialog();
// If the result is OK then print the document.
if (result == DialogResult.OK)
{
ProductionPrintDocument.Print();
if(ProductionPrintDialog.Document.PrinterSettings.PrinterName == "Microsoft Print to PDF")
{
System.Diagnostics.Process.Start(ProductionPrintDialog.Document.PrinterSettings.PrintFileName);
}
}
How can I get the user defined path set at PrintDialog?
Related
This question already has answers here:
Default name with OpenFileDialog C#?
(3 answers)
Closed 1 year ago.
I use the following to display an Open File dialog:
OpenFileDialog fdlg = new OpenFileDialog();
fdlg.FileName = Properties.Settings.Default.Last_competition_file;
fdlg.Filter = "FS database files (*.fsdb)|*.fsdb|All files (*.*)|*.*";
fdlg.FilterIndex = 0;
if (fdlg.ShowDialog(this) == DialogResult.Cancel) return false;
(Properties.Settings.Default.Last_competition_file contains the whole path to the last file)
Problem: For a file name "c:\data\nationals_2014.fsdb", the File name field only shows "ionals_2014.fsdb".
When clicking into the File name field, and moving the cursor to the left, the remainder of the file name & path re-appears. But I'm looking for a way to make the whole file name visible from the beginning.
Note that this is not a length issue. I also tried setting path and file name separately (through OpenFileDialog.InitialDirectory), but even then only the tail end of the (now much shorter) file name was displayed.
Any ideas how to get the Open File dialog to show the full pre-populated file name from the beginning?
Caveat: This is a Kludge, not a real answer.
OpenFileDialog fdlg = new OpenFileDialog();
fdlg.FileName = Properties.Settings.Default.Last_competition_file;
fdlg.Filter = "FS database files (*.fsdb)|*.fsdb|All files (*.*)|*.*";
fdlg.FilterIndex = 0;
fdlg.ShowHelp = true;
fdlg.HelpRequest += new System.EventHandler(HelpRequested); ;
if (fdlg.ShowDialog(this) == DialogResult.Cancel) return false;
private void HelpRequested(object sender, EventArgs e)
{
MessageBox.Show(".. is no Help", "There..");
}
The style of the Dialog reverts to an older incarnation.
Shrug. Some workarounds make me wonder about many things..
I got the same thing on windows 10 with an open file dialog set up like this:
var dialog = new OpenFileDialog{
Filter = "excel files (*.xlsx)|*.xlsx",
InitialDirectory = #"c:\temp",
FileName = #"MyFileNameExceeds14Characters.xlsx"
};
dialog.ShowDialog();
Work-arounds:
Set AutoUpgradeEnabled = false to revert to an older dialog style. But then you're stuck with the older UI.
Make sure the file name is under 14 characters long. If you don't have direct control of the file name, then run it through Path.GetFileNameWithoutExtension() to slim it down as much as possible.
Use a SaveFileDialog instead, which does not have this issue.
Inserting code:
SendKeys.Send("{HOME}");
before the line :
if (fdlg.ShowDialog(this) == DialogResult.Cancel) return false;
does the job.
Found a good answer on another thread:
c# Sending keyboard commands to another window / process
This does a good job of fixing the file name display.
I use a timer anyway in order to make sure that dialog is centered on active screen. Once the dialog is displayed:
IntPtr handle = FindWindowByCaption(IntPtr.Zero, dialogTitle));
SetForegroundWindow(handle);
SendKeys.SendWait("{HOME}");
SendKeys.Flush();
I have a pictureBox that loads an image directly from the internet. The image can change dynamically and is specified by the user in a textBox that has a TextChanged event that changes the image in pictureBox to the URL in the textBox. When user clicks the submit button, the image URL is saved in the database. But before saving I want to validate the image, that whether the image displayed successfully or the error image is displayed in place of it. So how can I validate this?
You can use the LoadComplete event to see when it has changed, and if the eventArg's error is null (successful) or not null (fail).
void pictureBox1_LoadCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
MessageBox.Show(e.Error.ToString());
}
this.pictureBox1.Validated += new EventHandler(pictureBox1_Validated);
this.pictureBox1.ImageLocation = this.textBox1.Text;
-
Edit: Just saw Dips' comment, did not use that link but is same means to answer this.
Place the code below in the function where you are retrieving the path of image from textBox ,be sure to place it before you do anything else on that path;
string path = "Path to image";
Bitmap bmp;//To validate the Image.
try
{
bmp = new Bitmap(path);//Create a Bitmap object from the given path.
if (bmp != null)
{
pictureBox1.Load(path);//Display the image to the user.
//Now it's safe to store the image path in the database,
//because we have validated it.
bmp.Dispose();//Dispose the Bitmap object to free occupied resources.
//Place you database related code here which uses the path we just validated.
}
}
catch (ArgumentException)
{
MessageBox.Show("The specified image file is invalid.");
//Show error image in PictureBox.
//(pictureBox1.Image="Path to error image").
//Don't store image path,its invalid.
}
catch (FileNotFoundException)
{
MessageBox.Show("The path to image is invalid.");
//Show error image in PictureBox.
//(pictureBox1.Image="Path to error image").
//Don't store image path,its invalid.
}
When you've done this you can place your code where I've shown the comment //Place your database....This ensures that the file path and image is validated before anything else uses them.`This method also checks if the image file is actually an image and not a .txt or .exe with its extension changed to .jpg or any other image format,as you've mentioned in your comments you need to check if the path actually points to an image file.
You can the extend the exception handling mechanism if you need something more than displaying a MessageBox with error information.One more thing that is worth to be mentioned is that,before you display any image or do anything you will have to check if the url is valid one,to simplify this step you can try to download the file(it can be anything - an image,an executable,a text file or at least a web page,when it has been downloaded pass the path to that file(relative to filesystem) to this function.
Hope it works for you.
Suppose Pic1 is name of your control. To validate then you can use simply,
if(pic1.ImageLocation.Trim().Length>4) // > 4 since a shortest valid image
file will be a.png or something
similar; length= 5
{
if(validExtensions(pic1.ImageLocation)
{
//then put the path to database
}
}
Updated
//Mehod to valid image extensions
private bool validExtensions(string url)
{
var imgs = new []{".jpg",".gif",".png",".bmp",".jpeg"};
var ext = System.IO.Path.GetFileExtention(url); // see the correct method
in intellisense
if(imgs.Contains(ext)
return false;
}
Update 2
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
dialog.InitialDirectory = #"C:\";
dialog.Title = "Please select an image file to encrypt.";
if (dialog.ShowDialog() == DialogResult.OK)
{
//Encrypt the selected file. I'll do this later. :)
}
I want to print my Crystal report direct to the printer. Currently I am having the export to PDF. But my client want this to go to Printer directly. How can I show the Print Dialog on click of Print Button to Print the report directly to Printer.
I would like to mention: I am using C# and asp.net for my project.
Thank you.
Try the following code
private void Button1_Click(object sender, EventArgs e)
{
CrystalReport1 report1 = new CrystalReport1();
PrintDialog dialog1 = new PrintDialog();
report1.SetDatabaseLogon("username", "password");
dialog1.AllowSomePages = true;
dialog1.AllowPrintToFile = false;
if (dialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
int copies = dialog1.PrinterSettings.Copies;
int fromPage = dialog1.PrinterSettings.FromPage;
int toPage = dialog1.PrinterSettings.ToPage;
bool collate = dialog1.PrinterSettings.Collate;
report1.PrintOptions.PrinterName = dialog1.PrinterSettings.PrinterName;
report1.PrintToPrinter(copies, collate, fromPage, toPage);
}
report1.Dispose();
dialog1.Dispose();
}
you will have to change the "username" and the "password" with the credentials of your database.
EDIT
This code can be used for server side printing only.
No way; Cristal Report Viewer is intended for showing and browsing a report.
It never shows all report pages.
It has no buttons or methods for direct printing.
You could, instead, export directly the report in PDF so Report Viewer is never seen by users, and printing becomes 1-click operation.
PrintButton_click Event and add following code as you ..
//show Print Dialog
PrintDialog printDialog = new PrintDialog();
DialogResult dr = printDialog.ShowDialog();
if (dr == DialogResult.OK)
{
ReportDocument crReportDocument = (ReportDocument)CrystalReportViewer1.ReportSource;
System.Drawing.Printing.PrintDocument printDocument1 = new System.Drawing.Printing.PrintDocument();
//Get the Copy times
int nCopy = printDocument1.PrinterSettings.Copies;
//Get the number of Start Page
int sPage = printDocument1.PrinterSettings.FromPage;
//Get the number of End Page
int ePage = printDocument1.PrinterSettings.ToPage;
crReportDocument.PrintOptions.PrinterName =printDocument1.PrinterSettings.PrinterName;
//Start the printing process. Provide details of the print job
crReportDocument.PrintToPrinter(nCopy, false, sPage, ePage);
// Form_Printerd = true;
}
i try to print out the content of my editor:
PrintDialog pd = new PrintDialog();
pd.PageRangeSelection = PageRangeSelection.AllPages;
pd.UserPageRangeEnabled = true;
FlowDocument fd = DocumentPrinter.CreateFlowDocumentForEditor(CurrentDocument.Editor);
DocumentPaginator dp = ((IDocumentPaginatorSource)fd).DocumentPaginator;
bool? res = pd.ShowDialog();
if (res.HasValue && res.Value)
{
fd.PageHeight = pd.PrintableAreaHeight;
fd.PageWidth = pd.PrintableAreaWidth;
fd.PagePadding = new Thickness(50);
fd.ColumnGap = 0;
fd.ColumnWidth = pd.PrintableAreaWidth;
pd.PrintDocument(dp, CurrentDocument.Editor.FileName);
}
The test-document i used has about 14 pages (with this pagesize-settings).
i tested it: the printdialog appears and I´ve chosen a pagerange (i typed "1-3" into the textbox) and clicked print. above the printdocument() I set a breakpoint and looked into the printdialog-object. it says pd.PageRangeSelection = PageRangeSelection.UserPage and pd.PageRange = {1-3}. I guess this is right, because I wanted to print out only page 1-3. then the printdocument() executed and in the output-pdf (for testing I use a pdf-printer) has 14 pages (the whole document was printed).
where is my mistake? why does the pagerange-setting not work?
thanks for your help
In your code you manually set:
pd.PageRangeSelection = PageRangeSelection.AllPages;
This is why your code prints all the pages.
The reason for this is because FlowDocument's DocumentPaginator does not handle UserPageRanges. You can see that FlowDocument implementation creates a FlowDocumentPaginator, and it doesn't take into account ranges.
If it did handle it, in FlowDocumentPaginator.(Async)GetPage you would see, code checking to see if the page requested to be printed is in an index of available pages; or maybe if a key exists in a Dictionary whose value is the DocumentPage to print.
In other words, and the reason the PrintDialog default has UserPageRangeEnabled set to false, is because in order to use that feature, you'll usually have to write your own DocumentPaginator or you have to add some logic to compile a new temporary document to hold only the pages you want to print.
Feel free to ask any questions.
I just want to know how I can print a flow document without showing Print Dialog in WPF.
Thanks for help…
You can use the PrintDialog class without showing the dialog (without calling ShowModal)
This is one of the ways you can change default printer or change other settings:
using System.Printing; //add reference to System.Printing Assembly
//if you want to modify PrintTicket, also add
//reference to ReachFramework.dll (part of .net install)
...
var dlg = new PrintDialog();
dlg.PrintQueue = printer; // this will be your printer. any of these: new PrintServer().GetPrintQueues()
dlg.PrintTicket.CopyCount = 3; // number of copies
dlg.PrintTicket.PageOrientation = PageOrientation.Landscape;
dlg.PrintVisual(canvas);
Try
PrintDialog dialog = new PrintDialog();
dialog.PrintVisual(_PrintCanvas, "My Canvas");