问题
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.
Thank you for any advice or tips you can provide for doing something like this!
回答1:
You might want to use the WebBrowser control and extend it using the example provided here: 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)]
The underlying control is the same - it's the ActiveX component in SHDocVw.dll.
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.
You'll need to add a reference to SHDocVw, which is under the COM reference list as "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="StackOverflowWPF.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:
SHDocVw.WebBrowser target = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
target.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINTPREVIEW, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, null, null);
来源:https://stackoverflow.com/questions/5732800/displaying-print-preview-of-html-document-without-documentviewer