我正在构建一个WPF应用程序,在该应用程序中,我需要显示文档预览,比如使用DocumentViewer和DocumentPaginator可以实现什么。但是,当报告很大时,将报告转换为XPS并将其加载到DocumentViewer中是非常缓慢的(作为我需要显示的常见报告)。
这让我开始思考,在报告的前几页被“加载”到DocumentViewer中时,可能有某种方式开始显示报告的前几页-- 基本上是在加载/显示创建时的页面()。
有人知道这样的事情是否可能发生吗?如果是的话,你怎么建议我开始试着让它起作用呢?我花了几个小时在网上寻找一个更快地显示报告的解决方案,但没有想出任何办法。
为了完全公开,在这种情况下,我需要显示的报告是用HTML创建的。我知道,为了使用DocumentViewer,我需要把它转换成XPS,但是我提到了这一点,因为如果有人有快速显示HTML的方法,请您也提出来。我不能使用WebBrowser控件,因为我必须在“打印预览”模式下显示。-一个很好的算法来决定如何‘分页’一个HTML可能会引导我找到一个解决这个问题的方法,然后我可以创建一个自定义控件来显示它。我会使用DocumentPaginator,但是输出的文件是XPS,然后再回到DocumentViewer问题上。
再一次,任何帮助都是非常感谢的。谢谢!
发布于 2011-04-21 19:18:53
好吧,我想我有东西.
再一次,我找到了一个更好的参考URL。这个不是直接为我加载的,所以我从Google缓存中抓取了它:http://webcache.googleusercontent.com/search?q=cache:LgceMCkJBrsJ:joshclose.net/%3Fp%3D247
如每一篇文章所述定义IViewObject接口:
[ComVisible(true), ComImport()]
[GuidAttribute("0000010d-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IViewObject
{
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int Draw(
[MarshalAs(UnmanagedType.U4)] UInt32 dwDrawAspect,
int lindex,
IntPtr pvAspect,
[In] IntPtr ptd,
IntPtr hdcTargetDev,
IntPtr hdcDraw,
[MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcBounds,
[MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcWBounds,
IntPtr pfnContinue,
[MarshalAs(UnmanagedType.U4)] UInt32 dwContinue);
[PreserveSig]
int GetColorSet([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect,
int lindex, IntPtr pvAspect, [In] IntPtr ptd,
IntPtr hicTargetDev, [Out] IntPtr ppColorSet);
[PreserveSig]
int Freeze([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect,
int lindex, IntPtr pvAspect, [Out] IntPtr pdwFreeze);
[PreserveSig]
int Unfreeze([In, MarshalAs(UnmanagedType.U4)] int dwFreeze);
void SetAdvise([In, MarshalAs(UnmanagedType.U4)] int aspects,
[In, MarshalAs(UnmanagedType.U4)] int advf,
[In, MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink);
void GetAdvise([In, Out, MarshalAs(UnmanagedType.LPArray)] int[] paspects,
[In, Out, MarshalAs(UnmanagedType.LPArray)] int[] advf,
[In, Out, MarshalAs(UnmanagedType.LPArray)] IAdviseSink[] pAdvSink);
}创建一个HtmlPaginator类,用于截图浏览器的文档(如所述),然后将其裁剪到页面/框架中:
class HtmlPaginator
{
public event EventHandler<PageImageEventArgs> PageReady;
protected virtual void OnPageReady(PageImageEventArgs e)
{
EventHandler<PageImageEventArgs> handler = this.PageReady;
if (handler != null)
handler(this, e);
}
public class PageImageEventArgs : EventArgs
{
public Image PageImage { get; set; }
public int PageNumber { get; set; }
}
public void GeneratePages(string doc)
{
Bitmap htmlImage = RenderHtmlToBitmap(doc);
int pageWidth = 800;
int pageHeight = 600;
int xLoc = 0;
int yLoc = 0;
int pages = 0;
do
{
int remainingHeightOrPageHeight = Math.Min(htmlImage.Height - yLoc, pageHeight);
int remainingWidthOrPageWidth = Math.Min(htmlImage.Width - xLoc, pageWidth);
Rectangle cropFrame = new Rectangle(xLoc, yLoc, remainingWidthOrPageWidth, remainingHeightOrPageHeight);
Bitmap page = htmlImage.Clone(cropFrame, htmlImage.PixelFormat);
pages++;
PageImageEventArgs args = new PageImageEventArgs { PageImage = page, PageNumber = pages };
OnPageReady(args);
yLoc += pageHeight;
if (yLoc > htmlImage.Height)
{
xLoc += pageWidth;
if (xLoc < htmlImage.Width)
{
yLoc = 0;
}
}
}
while (yLoc < htmlImage.Height && xLoc < htmlImage.Width);
}
private static Bitmap RenderHtmlToBitmap(string doc)
{
Bitmap htmlImage = null;
using (var webBrowser = new WebBrowser())
{
webBrowser.ScrollBarsEnabled = false;
webBrowser.ScriptErrorsSuppressed = true;
webBrowser.DocumentText = doc;
while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
webBrowser.Width = webBrowser.Document.Body.ScrollRectangle.Width;
webBrowser.Height = webBrowser.Document.Body.ScrollRectangle.Height;
htmlImage = new Bitmap(webBrowser.Width, webBrowser.Height);
using (Graphics graphics = Graphics.FromImage(htmlImage))
{
var hdc = graphics.GetHdc();
var rect1 = new Rectangle(0, 0, webBrowser.Width, webBrowser.Height);
var rect2 = new Rectangle(0, 0, webBrowser.Width, webBrowser.Height);
var viewObject = (IViewObject)webBrowser.Document.DomDocument;
viewObject.Draw(1, -1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, hdc, ref rect1, ref rect2, IntPtr.Zero, 0);
graphics.ReleaseHdc(hdc);
}
}
return htmlImage;
}
}就这么说吧:
WebBrowser browser = new WebBrowser();
browser.Navigate("http://www.stackoverflow.com");
while (browser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
HtmlPaginator pagr = new HtmlPaginator();
pagr.PageReady += new EventHandler<HtmlPaginator.PageImageEventArgs>(pagr_PageReady);
pagr.GeneratePages(browser.DocumentText);为了测试它,我用一个按钮、一个图片框和一个列表集合实现了一个基本表单。当页面从HtmlPaginator中准备好时,我将页面添加到集合中,并使用按钮将下一个图像添加到picturebox中。
神奇的数字是你想要的宽度和高度。我用了800x600,但是你可能有不同的尺寸。
这里的缺点是,您仍然在等待WebBrowser呈现HTML,但我真的不知道替代解决方案将如何减少时间--首先需要解释和绘制HTML。写你自己的网页浏览器吧。:)
我确实试着玩IViewObject.Draw,看看它是否可以直接呈现页面框架,而不是使用裁剪循环,但它对我没有用。
https://stackoverflow.com/questions/5745182
复制相似问题