我終於明白,有一個選項可以解決將矢量格式嵌入到打印作業中的一般要求,但它不適用於基於GDI的打印。
可以使用.NET中包含的ReachFramework.dll從WPF打印由Microsoft XPS Writer打印驅動程序創建的XPS文件格式。通過使用WPF進行打印而不是GDI,可以將XPS文檔頁面嵌入到較大的打印文檔中。
不足之處在於,WPF打印的工作方式有點不同,因此所有直接使用Sytem.Drawing命名空間中的東西的支持代碼都必須重新編寫。
下面是如何嵌入XPS文檔的基本輪廓:
打開文檔:
XpsDocument xpsDoc = new XpsDocument(filename, System.IO.FileAccess.Read);
var document = xpsDoc.GetFixedDocumentSequence().DocumentPaginator;
// pass the document into a custom DocumentPaginator that will decide
// what order to print the pages:
var mypaginator = new myDocumentPaginator(new DocumentPaginator[] { document });
// pass the paginator into PrintDialog.PrintDocument() to do the actual printing:
new PrintDialog().PrintDocument(mypaginator, "printjobname");
然後創建DocumentPaginator的後代,會做你的實際打印。重寫抽象方法,特別是GetPage應該以正確的順序返回DocumentPages。這裏是我的概念證明代碼,演示瞭如何自定義內容追加到XPS文檔的列表:
public override DocumentPage GetPage(int pageNumber)
{
for (int i = 0; i < children.Count; i++)
{
if (pageNumber >= pageCounts[i])
pageNumber -= pageCounts[i];
else
return FixFixedPage(children[i].GetPage(pageNumber));
}
if (pageNumber < PageCount)
{
DrawingVisual dv = new DrawingVisual();
var dc = dv.Drawing.Append();
dc = dv.RenderOpen();
DoRender(pageNumber, dc); // some method to render stuff to the DrawingContext
dc.Close();
return new DocumentPage(dv);
}
return null;
}
當試圖打印到另一XPS文件,它提供了一個異常「的FixedPage不能包含另一個固定頁」和發佈者H.Alipourian演示如何解決它:http://social.msdn.microsoft.com/Forums/da/wpf/thread/841e804b-9130-4476-8709-0d2854c11582
private DocumentPage FixFixedPage(DocumentPage page)
{
if (!(page.Visual is FixedPage))
return page;
// Create a new ContainerVisual as a new parent for page children
var cv = new ContainerVisual();
foreach (var child in ((FixedPage)page.Visual).Children)
{
// Make a shallow clone of the child using reflection
var childClone = (UIElement)child.GetType().GetMethod(
"MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic
).Invoke(child, null);
// Setting the parent of the cloned child to the created ContainerVisual
// by using Reflection.
// WARNING: If we use Add and Remove methods on the FixedPage.Children,
// for some reason it will throw an exception concerning event handlers
// after the printing job has finished.
var parentField = childClone.GetType().GetField(
"_parent", BindingFlags.Instance | BindingFlags.NonPublic);
if (parentField != null)
{
parentField.SetValue(childClone, null);
cv.Children.Add(childClone);
}
}
return new DocumentPage(cv, page.Size, page.BleedBox, page.ContentBox);
}
比較遺憾的是它不完全編譯代碼,我只是想提供必要的代碼片段概觀,使工作給其他人一個頭從所有需要共同努力的不同部分開始工作。試圖創建一個更通用的解決方案將比這個答案的範圍複雜得多。
我們做了類似的事情,但首先將PDF渲染爲位圖 - 當使用高質量庫和高DPI值(最少305,最佳1200)進行渲染時,會產生質量問題,這會降低一些內存/性能... – Yahia
我注意到有一天,PDFCreator(http://sourceforge.net/projects/pdfcreator/)雖然主要針對PDF創建,但實際上可以用來將PDF文檔打印成各種格式,包括SVG和位圖圖像。也許值得一瞧。 –
這些PDF往往是一些線條藝術的文字。他們也會在一次運行中打印1000次以上。將30 KB PDF轉換爲5 MB位圖可能會使整個打印隊列癱瘓。 –