WPF WebBrowser control zoom in/out support?
对于WPF WebBrowser控件,是否可以复制Internet Explorer的缩放功能?
换句话说,Internet Explorer具有菜单"视图">"缩放">" 75%",该菜单以75%的比例显示网页。有没有办法使嵌入在WPF应用程序中的Web浏览器控件执行相同的操作?
我看过这篇文章:
WPF WebBrowser-如何缩放内容?
但是它似乎只能缩放页面,而不能缩放页面内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | public partial class TestWindow: UserControl { public TestWindow() { InitializeComponent(); browser.LoadCompleted += new LoadCompletedEventHandler(browser_LoadCompleted); } private void browser_LoadCompleted(object sender, NavigationEventArgs e) { try { FieldInfo webBrowserInfo = browser.GetType().GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic); object comWebBrowser = null; object zoomPercent = 120; if (webBrowserInfo != null) comWebBrowser = webBrowserInfo.GetValue(browser); if (comWebBrowser != null) { InternetExplorer ie = (InternetExplorer)comWebBrowser; ie.ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref zoomPercent, IntPtr.Zero); } } catch (Exception ex) { } } public void SetBrowser(string url) { browser.Navigate(url,null,null,null); } internal void Destroy() { try { if (browser.Parent != null) { ((Grid)browser.Parent).Children.Remove(browser); browser.Navigate("about:blank"); browser.Dispose(); browser = null; } } catch { } } } |
这是我的做法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | // Needed to expose the WebBrowser's underlying ActiveX control for zoom functionality [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"); private void ZoomListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { object zoomPercent; // A VT_I4 percentage ranging from 10% to 1000% switch(ZoomListBox.SelectedItem.ToString()) { case"System.Windows.Controls.ListBoxItem: 200%": zoomPercent = 200; break; case"System.Windows.Controls.ListBoxItem: 100%": zoomPercent = 100; break; case"System.Windows.Controls.ListBoxItem: 50%": zoomPercent = 50; break; default: zoomPercent = 100; break; } // grab a handle to the underlying ActiveX object IServiceProvider serviceProvider = null; if (m_webView.Document != null) { serviceProvider = (IServiceProvider)m_webView.Document; } Guid serviceGuid = SID_SWebBrowserApp; Guid iid = typeof(SHDocVw.IWebBrowser2).GUID; SHDocVw.IWebBrowser2 browserInst = (SHDocVw.IWebBrowser2)serviceProvider.QueryService(ref serviceGuid, ref iid); // send the zoom command to the ActiveX object browserInst.ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref zoomPercent, IntPtr.Zero); } |
由于WPF WebBrowser控件不会直接公开ActiveX,因此所有服务提供者的资料都公开了ActiveX。除此之外,它与alexei的解决方案几乎相同。
这不是一个确切的答案,因为它用于WinForms控件,但是如果您决定在WindowsFormsHost中而不是WPF控件中使用它,则可能会有用。
您可以在ActiveX实例上通过ExecWB使用OLE命令:
1 2 3 4 5 | object pvaIn = 200; // A VT_I4 percentage ranging from 10% to 1000% var browserInst = ((SHDocVw.IWebBrowser2)(browserContol.ActiveXInstance)); browserInst.ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref pvaIn, IntPtr.Zero); |
一些注意事项:
- 需要对Interop.SHDocVw程序集的引用
- 仅在加载文档后命令才能成功
-
可以通过
OLECMDID_GETZOOMRANGE 检索pvaIn的范围 - 命令参考列表在MSDN上
- 我遇到了这种奇怪的现象,似乎仅在非96 dpi时才发生。启动时,呈现的文本大小与OLECMDID_ZOOM状态下存储的文本大小不对应。将值设置为任何值并不能解决差异:渲染的大小仍然看起来像[存储的大小2]。当光学变焦设置为100%时,文本大小的差异消失了(缩放到100%后,文本大小明显缩小了)。在IE中并没有发生这种情况,也许这只是我所处环境中的一个怪异产物,但仅仅是fyi。
在使用其他解决方案时,我总是会收到类似的错误
HRESULT: 0x80040100
DRAGDROP_E_NOTREGISTERED
我在此页面上找到了一个对我有用的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var wb = webBrowser.ActiveXInstance.GetType(); object o = zoomPercentage; // Between 10 and 1000. wb.InvokeMember( @"ExecWB", BindingFlags.InvokeMethod, null, webBrowser.ActiveXInstance, new[] { OLECMDID.OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, o, o }); |