在没有DocumentViewer的情况下显示HTML文档的打印预览

时间:2022-10-30 21:22:31

I have a C#/WPF application in which I need to display a print preview for an HTML document -- essentially just like what one would see if looking at a print preview in Firefox or even IE. I know about DocumentViewer, however, I am trying to stay away from using a DocumentViewer control as it seems to be pretty slow and some of the documents I need to display can be upwards of 450+ pages and I want to load the preview as quickly as possible. Does anyone know of an elegant way of doing something like this? I'm starting to assume I'll need to create my own control, but I'm really at a loss for where to get started.

我有一个C#/ WPF应用程序,我需要在其中显示HTML文档的打印预览 - 基本上就像在Firefox或甚至IE中查看打印预览时所看到的那样。我知道DocumentViewer,但是,我试图远离使用DocumentViewer控件,因为它看起来很慢,我需要显示的一些文档可以超过450页,我想快速加载预览尽可能。有谁知道做这样的事情的优雅方式?我开始假设我需要创建自己的控件,但我真的不知道从哪里开始。

Thank you for any advice or tips you can provide for doing something like this!

感谢您提供有关此类内容的任何建议或提示!

1 个解决方案

#1


6  

You might want to use the WebBrowser control and extend it using the example provided here: http://www.codeproject.com/KB/miscctrl/wbp.aspx

您可能希望使用WebBrowser控件并使用此处提供的示例对其进行扩展:http://www.codeproject.com/KB/miscctrl/wbp.aspx

[Edit: updated the answer to illustrate how to accomplish the same using the WPF WebBrowser control (System.Windows.Controls.WebBrowser)]

[编辑:更新答案,说明如何使用WPF WebBrowser控件(System.Windows.Controls.WebBrowser)完成相同的操作]

The underlying control is the same - it's the ActiveX component in SHDocVw.dll.

底层控件是相同的 - 它是SHDocVw.dll中的ActiveX组件。

I pulled together some better reference URL's for you. Turns out there's a pretty good lead on doing something similar from the MSDN documentation for the control: http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser(v=vs.90).aspx#4 There's also this: http://support.microsoft.com/kb/329014.

我为你拉了一些更好的参考URL。事实证明,在控件的MSDN文档中做类似的事情有很好的领先优势:http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser(v=vs.90)。 aspx#4还有这个:http://support.microsoft.com/kb/329014。

You'll need to add a reference to SHDocVw, which is under the COM reference list as "Microsoft Internet Controls"

您需要添加对SHDocVw的引用,该引用在COM引用列表下作为“Microsoft Internet Controls”

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
internal interface IServiceProvider
{
    [return: MarshalAs(UnmanagedType.IUnknown)]
    object QueryService(ref Guid guidService, ref Guid riid);
}
static readonly Guid SID_SWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");

void webBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
    IServiceProvider serviceProvider = null;
    if (webBrowser.Document != null)
    {
        serviceProvider = (IServiceProvider)webBrowser.Document;
    }

    Guid serviceGuid = SID_SWebBrowserApp;
    Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;

    object NullValue = null;

    SHDocVw.IWebBrowser2 target = (SHDocVw.IWebBrowser2)serviceProvider.QueryService(ref serviceGuid, ref iid);
    target.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINTPREVIEW, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref NullValue, ref NullValue);
}

XAML:

<Window x:Class="*WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <DockPanel LastChildFill="True">
            <WebBrowser Name="webBrowser"  Source="http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser.aspx" LoadCompleted="webBrowser_LoadCompleted">
            </WebBrowser>
        </DockPanel>
    </Grid>
</Window>

Anyone interested in the WinForms control version (System.Windows.Forms.WebBrowser) can skip all the IServiceProvider baggage and just use the ActiveXInstance property (which the WPF control doesn't expose:

任何对WinForms控件版本(System.Windows.Forms.WebBrowser)感兴趣的人都可以跳过所有IServiceProvider行李并只使用ActiveXInstance属性(WPF控件不会公开:

SHDocVw.WebBrowser target = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
target.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINTPREVIEW, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, null, null);

#1


6  

You might want to use the WebBrowser control and extend it using the example provided here: http://www.codeproject.com/KB/miscctrl/wbp.aspx

您可能希望使用WebBrowser控件并使用此处提供的示例对其进行扩展:http://www.codeproject.com/KB/miscctrl/wbp.aspx

[Edit: updated the answer to illustrate how to accomplish the same using the WPF WebBrowser control (System.Windows.Controls.WebBrowser)]

[编辑:更新答案,说明如何使用WPF WebBrowser控件(System.Windows.Controls.WebBrowser)完成相同的操作]

The underlying control is the same - it's the ActiveX component in SHDocVw.dll.

底层控件是相同的 - 它是SHDocVw.dll中的ActiveX组件。

I pulled together some better reference URL's for you. Turns out there's a pretty good lead on doing something similar from the MSDN documentation for the control: http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser(v=vs.90).aspx#4 There's also this: http://support.microsoft.com/kb/329014.

我为你拉了一些更好的参考URL。事实证明,在控件的MSDN文档中做类似的事情有很好的领先优势:http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser(v=vs.90)。 aspx#4还有这个:http://support.microsoft.com/kb/329014。

You'll need to add a reference to SHDocVw, which is under the COM reference list as "Microsoft Internet Controls"

您需要添加对SHDocVw的引用,该引用在COM引用列表下作为“Microsoft Internet Controls”

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
internal interface IServiceProvider
{
    [return: MarshalAs(UnmanagedType.IUnknown)]
    object QueryService(ref Guid guidService, ref Guid riid);
}
static readonly Guid SID_SWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");

void webBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
    IServiceProvider serviceProvider = null;
    if (webBrowser.Document != null)
    {
        serviceProvider = (IServiceProvider)webBrowser.Document;
    }

    Guid serviceGuid = SID_SWebBrowserApp;
    Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;

    object NullValue = null;

    SHDocVw.IWebBrowser2 target = (SHDocVw.IWebBrowser2)serviceProvider.QueryService(ref serviceGuid, ref iid);
    target.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINTPREVIEW, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref NullValue, ref NullValue);
}

XAML:

<Window x:Class="*WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <DockPanel LastChildFill="True">
            <WebBrowser Name="webBrowser"  Source="http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser.aspx" LoadCompleted="webBrowser_LoadCompleted">
            </WebBrowser>
        </DockPanel>
    </Grid>
</Window>

Anyone interested in the WinForms control version (System.Windows.Forms.WebBrowser) can skip all the IServiceProvider baggage and just use the ActiveXInstance property (which the WPF control doesn't expose:

任何对WinForms控件版本(System.Windows.Forms.WebBrowser)感兴趣的人都可以跳过所有IServiceProvider行李并只使用ActiveXInstance属性(WPF控件不会公开:

SHDocVw.WebBrowser target = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
target.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINTPREVIEW, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, null, null);