【发布时间】:2015-05-07 11:58:34
【问题描述】:
编辑:完全重写问题并增加赏金。
基于许多教程和 stackoverflow 问题,我现在可以:
- 将多页作为一个文档一起打印。
- 打印实际内容。
- 在页面上正确对齐内容。
- 打印正确尺寸的文档。
解决方案要求HTML文档底部有一些空白,样式标签html{overflow:hidden; } - 隐藏滚动条并允许滚动用于分页 - 但我可以接受。
唯一剩下的问题是 WPF 不会渲染不在屏幕上的网页浏览器部分。
这意味着如果我倾斜我的电脑屏幕,我可以正确打印,但如果我不这样做,文档会切断下部。
我尝试渲染为位图,但是当我将生成的图像作为视觉对象打印时,页面是空的。
如果您知道如何强制 WPF 完全渲染或如何正确渲染为位图,请帮助我。
打印窗口 XAML:(打印 WPF 仅适用于 UI 线程,否则不会呈现任何内容...)
<Window x:Class="CardLoader2000.PrintWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PrintWindow" Height="1139" Width="820">
<Grid x:Name="grid">
<!--The alignment and size of the webbrowser is reflected in the print. If larger than document
it will be cut. The width here corresponds to A4 paper width with a little margin-->
<WebBrowser x:Name="webBrowser" Height="1089" Width="770" VerticalAlignment="Top" Margin="0,10,0,0"/>
</Grid>
</Window>
打印窗口代码隐藏:
public partial class PrintWindow : Window
{
public PrintWindow(string path)
{
InitializeComponent();
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
webBrowser.NavigateToStream(fs);
ContentRendered += OnContentRendered;
}
private void OnContentRendered(object sender, EventArgs eventArgs)
{
PrintDialog pd = new PrintDialog
{
PrintTicket = new PrintTicket
{
Duplexing = Duplexing.TwoSidedLongEdge,
OutputColor = OutputColor.Monochrome,
PageOrientation = PageOrientation.Portrait,
PageMediaSize = new PageMediaSize(794, 1122),
InputBin = InputBin.AutoSelect
}
};
//Ok, final TODO: Page only renders what is on the PC screen...
WebPaginator paginator = new WebPaginator(webBrowser, 1089, 1122, 794);
pd.PrintDocument(paginator, "CustomerLetter");
Close();
}
}
自定义分页器:
public class WebPaginator : DocumentPaginator
{
private readonly WebBrowser webBrowser;
private readonly int pageScroll;
private Size pageSize;
public WebPaginator(WebBrowser webBrowser, int pageScroll, double pageHeight, double pageWidth)
{
this.webBrowser = webBrowser;
this.pageScroll = pageScroll;
pageSize = new Size(pageWidth, pageHeight);
}
public override DocumentPage GetPage(int pageNumber)
{
HTMLDocument htmlDoc = webBrowser.Document as HTMLDocument;
if (htmlDoc != null) htmlDoc.parentWindow.scrollTo(0, pageScroll * pageNumber);
Rect area = new Rect(pageSize);
return new DocumentPage(webBrowser, pageSize, area, area);
}
public override bool IsPageCountValid
{
get { return true; }
}
/// <summary>
/// Returns one less than actual length.
/// Last page should be whitespace, used for scrolling.
/// </summary>
public override int PageCount
{
get
{
var doc = (IHTMLDocument2)webBrowser.Document;
var height = ((IHTMLElement2)doc.body).scrollHeight;
int tempVal = height*10/pageScroll;
tempVal = tempVal%10 == 0
? Math.Max(height/pageScroll, 1)
: height/pageScroll + 1;
return tempVal > 1 ? tempVal-1 : tempVal;
}
}
public override Size PageSize
{
get
{
return pageSize;
}
set
{
pageSize = value;
}
}
/// <summary>
/// Can be null.
/// </summary>
public override IDocumentPaginatorSource Source
{
get
{
return null;
}
}
}
【问题讨论】:
-
使用 IHTMLDocument2 打印也会给出一个空文档并始终提示用户,即使您在 execCommand 调用中将 ShowUI 设置为 false。
-
直接从 UI 打印是绝对要求吗?我的意思是来自WebBrowser?您是否考虑过将相同的 URL 独立地传递给为此目的而设计得更好的工具?比如princexml.com/doc/dotnet?最终,从 PDF 打印到纸张后会产生更加一致的结果...
-
嗯,不,我开始意识到网络浏览器控制方法是完全不可能的。它不是真正的 WPF 控件,而是包装的 COM 控件。这意味着它不会做你告诉它做的事情。我设法让它认为屏幕比它大,但由于它是一个 COM 控件,它无论如何都没有渲染 - 只是黑色。我还尝试了 RenderRotateTransform,但控件中的内容保持未旋转。我会考虑你的链接/解决方案,但我现在有点厌倦了尝试随机的东西。我可能会完全改变我的方法。
标签: c# html wpf printing wpf-controls