Based on the article here I would like to print a flow document. The first two lines are going well:
printDialog ← ⎕NEW System.Windows.Controls.PrintDialog
doc←⎕NEW FlowDocument(⎕NEW Paragraph(⎕NEW Run(⊂'Some text goes here')))
The following line does not work and cause a DOMAIN ERROR
printDialog.PrintDocument(doc.DocumentPaginator,(⊂'Hello WPF Printing')) ⍝ DOMAIN ERROR
The constructor is:
Void PrintDocument(System.Windows.Documents.DocumentPaginator, System.String)
What should I do to have the last line working ?
Thanks in advance,
Pierre Gilbert
How to Print a WPF Flow Document ?
- MikeHughes
- Posts: 86
- Joined: Thu Nov 26, 2009 9:03 am
- Location: Market Harborough, Leicestershire, UK
Re: How to Print a WPF Flow Document ?
Hi Pierre,
Try
[1] PrintDialog←⎕new PrintDialog
[2] doc←⎕NEW FlowDocument(⎕NEW Paragraph(⎕NEW Run(⊂'Some text goes here')))
[3] dps←IDocumentPaginatorSource ⎕class doc
[4] PrintDialog.PrintTicket←⎕NEW PrintTicket
[5] PrintDialog.PrintDocument(dps.DocumentPaginator'Hello WPF Printing')
Line [4] may not be needed - it depends on your printer drivers I gather. Basically if you leave them out and get an exception saying something about notbeing able to retrieve Print Ticket then you need [4]
This works for me
Try
[1] PrintDialog←⎕new PrintDialog
[2] doc←⎕NEW FlowDocument(⎕NEW Paragraph(⎕NEW Run(⊂'Some text goes here')))
[3] dps←IDocumentPaginatorSource ⎕class doc
[4] PrintDialog.PrintTicket←⎕NEW PrintTicket
[5] PrintDialog.PrintDocument(dps.DocumentPaginator'Hello WPF Printing')
Line [4] may not be needed - it depends on your printer drivers I gather. Basically if you leave them out and get an exception saying something about notbeing able to retrieve Print Ticket then you need [4]
This works for me
Re: How to Print a WPF Flow Document ?
Thanks Mike it worked for me too and without the ticket, I was not aware to use ⎕CLASS to cast a IDocumentPaginatorSource interface. Quite interesting. So the third line of the example on the web:
// Create IDocumentPaginatorSource from FlowDocument
IDocumentPaginatorSource idpSource = doc;
is translated to this with Dyalog APL:
idpSource←IDocumentPaginatorSource ⎕class doc
and the last line on the example:
// Call PrintDocument method to send document to printer
printDlg.PrintDocument(idpSource.DocumentPaginator, "Hello WPF Printing.");
becomes in Dyalog APL:
printDlg.PrintDocument(idpSource.DocumentPaginator 'Hello WPF Printing.')
This is pretty neat Dyalog, congratulations.
Pierre Gilbert
PS: Be aware that oddly there is 2 PrintDialog in .Net, one in System.Windows.Forms and one in System.Windows.Controls. If your ⎕USING point towards the 2 namespaces, you have to specify wich one you want for WPF.
PPS: The code used to setup ⎕USING as a global variable for this example is:
Setup30
⍝ Setup ⎕USING for the .Net 3.0 Framework
⍝ Value to Access the Program File Folder
⎕USING←,⊂'System'
⍝ Find the Program File Folder
progFiles←Environment.GetFolderPath Environment.SpecialFolder.ProgramFiles
⍝ Find the Path of the .Net 3.0 Framework
path30←progFiles,'\Reference Assemblies\Microsoft\Framework\v3.0\'
⍝ Add the Assemblies Used
use←'System,System.dll' 'System.IO,mscorlib.dll' 'System.Xml,system.xml.dll'
use,←'System.Drawing,system.drawing.dll' 'System.Windows.Forms,system.windows.forms.dll'
use,←'System.Text,mscorlib.dll' 'System.Collections,mscorlib.dll'
use,←⊂'System.Windows,',path30,'PresentationFramework.dll'
use,←⊂'System.Windows,',path30,'PresentationCore.dll'
use,←⊂'System.Windows,',path30,'WindowsFormsIntegration.dll'
use,←⊂'System.Windows,',path30,'PresentationCore.dll'
use,←⊂'System.Windows,',path30,'WindowsBase.dll'
use,←⊂'System.Windows.Controls'
use,←⊂'System.Windows.Markup'
use,←⊂'System.Windows.Navigation'
use,←⊂'System.Windows.Media'
use,←⊂'System.Windows.Media.Imaging'
use,←⊂'System.Windows.Documents'
use,←⊂'Dyalog'
use,←⊂''
⍝ Set ⎕USING
⎕USING,←use
// Create IDocumentPaginatorSource from FlowDocument
IDocumentPaginatorSource idpSource = doc;
is translated to this with Dyalog APL:
idpSource←IDocumentPaginatorSource ⎕class doc
and the last line on the example:
// Call PrintDocument method to send document to printer
printDlg.PrintDocument(idpSource.DocumentPaginator, "Hello WPF Printing.");
becomes in Dyalog APL:
printDlg.PrintDocument(idpSource.DocumentPaginator 'Hello WPF Printing.')
This is pretty neat Dyalog, congratulations.
Pierre Gilbert
PS: Be aware that oddly there is 2 PrintDialog in .Net, one in System.Windows.Forms and one in System.Windows.Controls. If your ⎕USING point towards the 2 namespaces, you have to specify wich one you want for WPF.
PPS: The code used to setup ⎕USING as a global variable for this example is:
Setup30
⍝ Setup ⎕USING for the .Net 3.0 Framework
⍝ Value to Access the Program File Folder
⎕USING←,⊂'System'
⍝ Find the Program File Folder
progFiles←Environment.GetFolderPath Environment.SpecialFolder.ProgramFiles
⍝ Find the Path of the .Net 3.0 Framework
path30←progFiles,'\Reference Assemblies\Microsoft\Framework\v3.0\'
⍝ Add the Assemblies Used
use←'System,System.dll' 'System.IO,mscorlib.dll' 'System.Xml,system.xml.dll'
use,←'System.Drawing,system.drawing.dll' 'System.Windows.Forms,system.windows.forms.dll'
use,←'System.Text,mscorlib.dll' 'System.Collections,mscorlib.dll'
use,←⊂'System.Windows,',path30,'PresentationFramework.dll'
use,←⊂'System.Windows,',path30,'PresentationCore.dll'
use,←⊂'System.Windows,',path30,'WindowsFormsIntegration.dll'
use,←⊂'System.Windows,',path30,'PresentationCore.dll'
use,←⊂'System.Windows,',path30,'WindowsBase.dll'
use,←⊂'System.Windows.Controls'
use,←⊂'System.Windows.Markup'
use,←⊂'System.Windows.Navigation'
use,←⊂'System.Windows.Media'
use,←⊂'System.Windows.Media.Imaging'
use,←⊂'System.Windows.Documents'
use,←⊂'Dyalog'
use,←⊂''
⍝ Set ⎕USING
⎕USING,←use
Re: How to Print a WPF Flow Document ?
Based on this article find the following code to preview a FlowDocument in a DocumentViewer window. This method use a MemoryStream to hold the required intermediary generated XPS document.
Enjoy,
Enjoy,
Code: Select all
PrintPreview flowDoc;docViewer;flowDocPaginator;NetPath30;package;packageUri;packageUriString;printDLG;progFiles;sink;wDV;xpsDoc;xpsSm;xpsStream;⎕USING
⍝ Program to Preview a FlowDocument in a DocumentViewer before Printing.
⍝ Requirement: .Net 3.0
⍝ Based On: http://khason.net/blog/printing-more-then-one-page-creation-in-memory-xps-document-and-documentviewer-customization/
⎕USING←'System,mscorlib.dll'
progFiles←Environment.GetFolderPath Environment.SpecialFolder.ProgramFiles
NetPath30←progFiles,'\Reference Assemblies\Microsoft\Framework\v3.0\'
⎕USING←'System.IO,mscorlib.dll' 'System,System.dll'
⎕USING,←⊂'System.Windows.Documents,',NetPath30,'PresentationFramework.dll'
⎕USING,←⊂'System.Windows.Controls,',NetPath30,'PresentationFramework.dll'
⎕USING,←⊂'System.Windows,',NetPath30,'PresentationFramework.dll'
⎕USING,←⊂'System.Windows.Documents,',NetPath30,'PresentationCore.dll'
⎕USING,←⊂'System.IO.Packaging,',NetPath30,'PresentationCore.dll'
⎕USING,←⊂'System.IO.Packaging,',NetPath30,'WindowsBase.dll'
⎕USING,←⊂'System.Windows.Xps.Packaging,',NetPath30,'ReachFramework.dll'
⎕USING,←⊂'System.Windows.Xps.Serialization,',NetPath30,'ReachFramework.dll'
⍝ OBTAIN THE PROPERTIES OF THE DEFAULT PRINTER
printDLG←⎕NEW PrintDialog
⍝ SET THE FlowDocument ACCORDING TO THE PROPERTIES OF THE DEFAULT PRINTER
flowDoc.PageHeight←printDLG.PrintableAreaHeight
flowDoc.PageWidth←printDLG.PrintableAreaWidth
flowDoc.Document.PagePadding←(⎕NEW Thickness 50)
flowDoc.ColumnWidth←printDLG.PrintableAreaWidth
flowDoc.Document.ColumnGap←0
⍝ GET A DocumentPaginator FROM THE FlowDocument
flowDocPaginator←(IDocumentPaginatorSource ⎕CLASS flowDoc).DocumentPaginator
⍝ PREPARE A package FROM A MemoryStream
xpsStream←⎕NEW MemoryStream
package←Package.Open(xpsStream,FileMode.Create,FileAccess.ReadWrite)
packageUriString←'memorystream://printstream'
packageUri←⎕NEW Uri(⊂packageUriString)
PackageStore.AddPackage(packageUri,package)
⍝ CREATE A XpsDocument WITH THE Package
xpsDoc←⎕NEW XpsDocument(package,(CompressionOption.SuperFast),⊂packageUriString)
xpsSm←⎕NEW XpsSerializationManager((⎕NEW XpsPackagingPolicy(xpsDoc)),0)
xpsSm.SaveAsXaml flowDocPaginator
⍝ INITIALIZE A DocumentViewer FROM THE XpsDocument
docViewer←⎕NEW DocumentViewer
docViewer.Document←xpsDoc.GetFixedDocumentSequence
⍝ ADD THE DocumentViewer TO A Window
wDV←⎕NEW Window
wDV.Title←'Print Preview'
wDV.Content←docViewer
⍝ SHOW THE Window AS MODAL
sink←wDV.ShowDialog
⍝ CLEAN-UP AFTER THE WINDOW IS CLOSED
PackageStore.RemovePackage(packageUri)
xpsDoc.Close
package.Close
xpsStream.Close
xpsStream.Dispose
- Dick Bowman
- Posts: 235
- Joined: Thu Jun 18, 2009 4:55 pm
- Contact:
Re: How to Print a WPF Flow Document ?
This series of posts is invaluable for those of us trying to make sense of WPF, I've made a small adaptation of the <PrintPreview> function to take a character vector (with embedded newlines) as argument, modified lines are...
flowDoc←⎕NEW FlowDocument(⎕NEW Paragraph(⎕NEW Run(⊂doc)))
...
flowDoc.PagePadding←⎕NEW Thickness 50 ⍝ was flowDoc.Document.PagePadding←(⎕NEW Thickness 50)
...
flowDoc.ColumnGap←0 ⍝ was flowDoc.Document.ColumnGap←0
At a guess my level of ignorance (I'm using my subtle approach of charging into the problem and seeing what goes wrong) is what's led me to needing to make the changes from flowDoc.Document (which gave me VALUE ERROR).
Should I be more subtle in the way I make the FlowDocument - my code was lifted from earlier in the thread?
The code seems to do what I want it to
flowDoc←⎕NEW FlowDocument(⎕NEW Paragraph(⎕NEW Run(⊂doc)))
...
flowDoc.PagePadding←⎕NEW Thickness 50 ⍝ was flowDoc.Document.PagePadding←(⎕NEW Thickness 50)
...
flowDoc.ColumnGap←0 ⍝ was flowDoc.Document.ColumnGap←0
At a guess my level of ignorance (I'm using my subtle approach of charging into the problem and seeing what goes wrong) is what's led me to needing to make the changes from flowDoc.Document (which gave me VALUE ERROR).
Should I be more subtle in the way I make the FlowDocument - my code was lifted from earlier in the thread?
The code seems to do what I want it to
Visit http://apl.dickbowman.com to read more from Dick Bowman
Re: How to Print a WPF Flow Document ?
Hello Dick, I think you are correct with your comments, and the code should be like you show it (without the .Document). I took my example from here and they are referencing a ScrollViewer in the code with .Document and not a FlowDocument like I do, so I did not apply their example correctly into my APL code. But why its working anyway for me and not for you, I don't know.
Thanks for sharing your observations. Here is the revised code following Dick intervention:
Thanks for sharing your observations. Here is the revised code following Dick intervention:
Code: Select all
PrintPreview flowDoc;docViewer;flowDocPaginator;NetPath30;package;packageUri;packageUriString;printDLG;progFiles;sink;wDV;xpsDoc;xpsSm;xpsStream;⎕USING
⍝ Program to Preview a FlowDocument in a DocumentViewer before Printing.
⍝ Requirement: .Net 3.0
⍝ Based On: http://khason.net/blog/printing-more-then-one-page-creation-in-memory-xps-document-and-documentviewer-customization/
⎕USING←'System,mscorlib.dll'
progFiles←Environment.GetFolderPath Environment.SpecialFolder.ProgramFiles
NetPath30←progFiles,'\Reference Assemblies\Microsoft\Framework\v3.0\'
⎕USING←'System.IO,mscorlib.dll' 'System,System.dll'
⎕USING,←⊂'System.Windows.Documents,',NetPath30,'PresentationFramework.dll'
⎕USING,←⊂'System.Windows.Controls,',NetPath30,'PresentationFramework.dll'
⎕USING,←⊂'System.Windows,',NetPath30,'PresentationFramework.dll'
⎕USING,←⊂'System.Windows.Documents,',NetPath30,'PresentationCore.dll'
⎕USING,←⊂'System.IO.Packaging,',NetPath30,'PresentationCore.dll'
⎕USING,←⊂'System.IO.Packaging,',NetPath30,'WindowsBase.dll'
⎕USING,←⊂'System.Windows.Xps.Packaging,',NetPath30,'ReachFramework.dll'
⎕USING,←⊂'System.Windows.Xps.Serialization,',NetPath30,'ReachFramework.dll'
⍝ OBTAIN THE PROPERTIES OF THE DEFAULT PRINTER
printDLG←⎕NEW PrintDialog
⍝ SET THE FlowDocument ACCORDING TO THE PROPERTIES OF THE DEFAULT PRINTER
flowDoc.PageHeight←printDLG.PrintableAreaHeight
flowDoc.PageWidth←printDLG.PrintableAreaWidth
flowDoc.PagePadding←(⎕NEW Thickness 50) ⍝ was flowDoc.Document.PagePadding←(⎕NEW Thickness 50)
flowDoc.ColumnWidth←printDLG.PrintableAreaWidth
flowDoc.ColumnGap←0 ⍝ was flowDoc.Document.ColumnGap←0
⍝ GET A DocumentPaginator FROM THE FlowDocument
flowDocPaginator←(IDocumentPaginatorSource ⎕CLASS flowDoc).DocumentPaginator
⍝ PREPARE A package FROM A MemoryStream
xpsStream←⎕NEW MemoryStream
package←Package.Open(xpsStream,FileMode.Create,FileAccess.ReadWrite)
packageUriString←'memorystream://printstream'
packageUri←⎕NEW Uri(⊂packageUriString)
PackageStore.AddPackage(packageUri,package)
⍝ CREATE A XpsDocument WITH THE Package
xpsDoc←⎕NEW XpsDocument(package,(CompressionOption.SuperFast),⊂packageUriString)
xpsSm←⎕NEW XpsSerializationManager((⎕NEW XpsPackagingPolicy(xpsDoc)),0)
xpsSm.SaveAsXaml flowDocPaginator
⍝ INITIALIZE A DocumentViewer FROM THE XpsDocument
docViewer←⎕NEW DocumentViewer
docViewer.Document←xpsDoc.GetFixedDocumentSequence
⍝ ADD THE DocumentViewer TO A Window
wDV←⎕NEW Window
wDV.Title←'Print Preview'
wDV.Content←docViewer
⍝ SHOW THE Window AS MODAL
sink←wDV.ShowDialog
⍝ CLEAN-UP AFTER THE WINDOW IS CLOSED
PackageStore.RemovePackage(packageUri)
xpsDoc.Close
package.Close
xpsStream.Close
xpsStream.Dispose