Reputation: 7383
I've been fighting with a printing issue for a long time now, hopefully someone can help.
Background I'm creating an Aspose.Words-document from a word-template, and mail merging it, and then want to print it directly from the WPF application with a print dialog. When printing i need to be able to select all different printer settings available for my printer (what paper to use, zoom, orientation, color etc.). This last thing seems to be what keeps my Google searches from succeeding, as all examples I find is only about giving the printer name, or how many copies to print.
Test 1 - Aspose's preferred way of printing From their forum
private void Print(Document document)
{
var printDialog = new System.Windows.Forms.PrintDialog
{
AllowSomePages = true,
PrinterSettings = new PrinterSettings
{
MinimumPage = 1,
MaximumPage = document.PageCount,
FromPage = 1,
ToPage = document.PageCount
},
UseEXDialog = true
};
var result = printDialog.ShowDialog();
if (result.Equals(DialogResult.OK))
document.Print(printDialog.PrinterSettings);
}
Now this seems to be perfect! But I get two one issue(s).
Test 2 - Print with process (PDF)
private void Print(Document document)
{
var savePath = String.Format("C:\\temp\\a.pdf");
document.Save(savePath, SaveFormat.Pdf);
var myProcess = new Process();
myProcess.StartInfo.FileName = savePath;
myProcess.StartInfo.Verb = "Print";
//myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
myProcess.WaitForExit();
}
This would be a nice solution, but it doesn't give me the dialog (I can use word PrintTo and give some arguments, like printer name etc. But not for my special requirements, right?)
Test 3 - Print with Word Automation
private void Print(Document document)
{
object nullobj = Missing.Value;
var savePath = String.Format("C:\\temp\\a.docx");
document.Save(savePath, SaveFormat.Docx);
var wordApp = new Microsoft.Office.Interop.Word.Application();
wordApp.DisplayAlerts = Microsoft.Office.Interop.Word.WdAlertLevel.wdAlertsNone;
wordApp.Visible = false;
Microsoft.Office.Interop.Word.Document doc = null;
Microsoft.Office.Interop.Word.Documents docs = null;
Microsoft.Office.Interop.Word.Dialog dialog = null;
try
{
docs = wordApp.Documents;
doc = docs.Open(savePath);
doc.Activate();
dialog = wordApp.Dialogs[Microsoft.Office.Interop.Word.WdWordDialog.wdDialogFilePrint];
var dialogResult = dialog.Show(ref nullobj);
if (dialogResult == 1)
{
doc.PrintOut(false);
}
}catch(Exception)
{
throw;
}finally
{
Thread.Sleep(3000);
if (dialog != null) Marshal.FinalReleaseComObject(dialog);
if (doc != null) Marshal.FinalReleaseComObject(doc);
if (docs != null) Marshal.FinalReleaseComObject(docs);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
doc = null;
wordApp.Quit(false, ref nullobj, ref nullobj);
}
}
Ok, so should I use Automation? It prints fine, but when it comes to closing the word-app and document I get trouble. For example I sometimes get the dialog "Margins outside printable area", and woops, the code cannot quit the process and leaves it. You see the Thread.Sleep? If I dont have it there, Word will be quitted before the printing has finished.
You see, I fall short in all my tries. What is the best way to go about this?
Thanks for your time!
Upvotes: 3
Views: 7032
Reputation: 7383
OK, I found a proper WPF-solution, converting the document to XPS and loading it into a DocumentViewer, from which I can use the native print functionality.
View.xaml
<DocumentViewer Document="{Binding XpsFixedDocumentSequence}"/>
ViewModel.cs
using System.Windows.Xps.Packaging;
...
private void PrepareDocument(Document document)
{
var xpsDoc = GetDocumentAsXps(document);
XpsFixedDocumentSequence = xpsDoc.GetFixedDocumentSequence();
}
private XpsDocument GetDocumentAsXps(Document document)
{
var savePath = "C:\\temp\\doc.xps";
document.Save(savePath, SaveFormat.Xps);
var xpsDoc = new XpsDocument(savePath, FileAccess.Read);
return xpsDoc;
}
/* Property XpsFixedDocumentSequence */
public const string XpsFixedDocumentSequencePropertyName = "XpsFixedDocumentSequence";
private FixedDocumentSequence _xpsFixedDocumentSequence;
public FixedDocumentSequence XpsFixedDocumentSequence
{
get { return _xpsFixedDocumentSequence; }
set
{
if (_xpsFixedDocumentSequence == value) return;
_xpsFixedDocumentSequence = value;
RaisePropertyChanged(XpsFixedDocumentSequencePropertyName);
}
}
Note to self: reference the ReachFramework dll
Upvotes: 2