使用WebBrowser .NET控件放大网页

20

在IE7中有一个内置的"缩放"功能(在状态栏中显示),允许您最多缩放400%。我在演示/模拟应用程序中使用WebBrowser .NET控件,并需要对网页进行缩放。这是否有可能?

(我不想简单地拍摄页面并放大它,因为我需要使用页面上的链接和按钮)。

如果有影响,我正在使用.NET 2.0。

6个回答

32

似乎有一个解决方案在IE缩放中,其中涉及重写WebBrowser中的AttachInterfacesDetachInterfaces以获取IWebBrowser2接口,然后使用OLECMDID_OPTICAL_ZOOM调用ExecWB

我已经尝试了他的示例代码,看起来是有效的;相关的类(节选)如下:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace ZoomBrowser
{
    public partial class MyBrowser : WebBrowser
    {
        #region enums
        public enum OLECMDID
        {
            // ...
            OLECMDID_OPTICAL_ZOOM = 63,
            OLECMDID_OPTICAL_GETZOOMRANGE = 64,
            // ...
        }

        public enum OLECMDEXECOPT
        {
            // ...
            OLECMDEXECOPT_DONTPROMPTUSER,
            // ...
        }

        public enum OLECMDF
        {
            // ...
            OLECMDF_SUPPORTED = 1
        }
        #endregion

        #region IWebBrowser2
        [ComImport, /*SuppressUnmanagedCodeSecurity,*/
         TypeLibType(TypeLibTypeFlags.FOleAutomation | 
                     TypeLibTypeFlags.FDual |       
                     TypeLibTypeFlags.FHidden), 
         Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")]
        public interface IWebBrowser2
        {
            [DispId(100)]  void GoBack();
            [DispId(0x65)] void GoForward();
            [DispId(0x66)] void GoHome();
            [DispId(0x67)] void GoSearch();
            [DispId(0x68)] void Navigate([In] string Url, 
                                         [In] ref object flags, 
                                         [In] ref object targetFrameName, 
                                         [In] ref object postData, 
                                         [In] ref object headers);
            [DispId(-550)] void Refresh();
            [DispId(0x69)] void Refresh2([In] ref object level);
            [DispId(0x6a)] void Stop();
            [DispId(200)]  object Application 
                           { [return: 
                              MarshalAs(UnmanagedType.IDispatch)] get; }
            [DispId(0xc9)] object Parent 
                           { [return: 
                              MarshalAs(UnmanagedType.IDispatch)] get; }
            [DispId(0xca)] object Container 
                           { [return: 
                              MarshalAs(UnmanagedType.IDispatch)] get; }
            [DispId(0xcb)] object Document 
                           { [return: 
                              MarshalAs(UnmanagedType.IDispatch)] get; }
            [DispId(0xcc)] bool TopLevelContainer { get; }
            [DispId(0xcd)] string Type { get; }
            [DispId(0xce)] int Left { get; set; }
            [DispId(0xcf)] int Top { get; set; }
            [DispId(0xd0)] int Width { get; set; }
            [DispId(0xd1)] int Height { get; set; }
            [DispId(210)]  string LocationName { get; }
            [DispId(0xd3)] string LocationURL { get; }
            [DispId(0xd4)] bool Busy { get; }
            [DispId(300)]  void Quit();
            [DispId(0x12d)] void ClientToWindow(out int pcx, out int pcy);
            [DispId(0x12e)] void PutProperty([In] string property, 
                                             [In] object vtValue);
            [DispId(0x12f)] object GetProperty([In] string property);
            [DispId(0)] string Name { get; }
            [DispId(-515)] int HWND { get; }
            [DispId(400)] string FullName { get; }
            [DispId(0x191)] string Path { get; }
            [DispId(0x192)] bool Visible { get; set; }
            [DispId(0x193)] bool StatusBar { get; set; }
            [DispId(0x194)] string StatusText { get; set; }
            [DispId(0x195)] int ToolBar { get; set; }
            [DispId(0x196)] bool MenuBar { get; set; }
            [DispId(0x197)] bool FullScreen { get; set; }
            [DispId(500)] void Navigate2([In] ref object URL, 
                                         [In] ref object flags, 
                                         [In] ref object targetFrameName, 
                                         [In] ref object postData, 
                                         [In] ref object headers);
            [DispId(0x1f5)] OLECMDF QueryStatusWB([In] OLECMDID cmdID);
            [DispId(0x1f6)] void ExecWB([In] OLECMDID cmdID, 
                                        [In] OLECMDEXECOPT cmdexecopt, 
                                        ref object pvaIn, IntPtr pvaOut);
            [DispId(0x1f7)] void ShowBrowserBar([In] ref object pvaClsid, 
                                                [In] ref object pvarShow, 
                                                [In] ref object pvarSize);
            [DispId(-525)] WebBrowserReadyState ReadyState { get; }
            [DispId(550)] bool Offline { get; set; }
            [DispId(0x227)] bool Silent { get; set; }
            [DispId(0x228)] bool RegisterAsBrowser { get; set; }
            [DispId(0x229)] bool RegisterAsDropTarget { get; set; }
            [DispId(0x22a)] bool TheaterMode { get; set; }
            [DispId(0x22b)] bool AddressBar { get; set; }
            [DispId(0x22c)] bool Resizable { get; set; }
        }
        #endregion

        private IWebBrowser2 axIWebBrowser2;

        public MyBrowser()
        {           
        }

        protected override void AttachInterfaces(
            object nativeActiveXObject)
        {
            base.AttachInterfaces(nativeActiveXObject);
            this.axIWebBrowser2 = (IWebBrowser2)nativeActiveXObject;
        }

        protected override void DetachInterfaces()
        {
            base.DetachInterfaces();
            this.axIWebBrowser2 = null;
        }

        public void Zoom(int factor)
        {
            object pvaIn = factor;
            try
            {
                this.axIWebBrowser2.ExecWB(OLECMDID.OLECMDID_OPTICAL_ZOOM,
                   OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, 
                   ref pvaIn, IntPtr.Zero);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}

有没有办法让水平滚动条不出现,而是文本自动换到下一行? - Priyank Bolia
1
谢谢你的回答。看起来只有在浏览器没有加载文档时才允许设置该属性,所以在设置缩放因子之前记得检查 IsBusy 属性。 - MartinStettner
如果你一直收到“_DRAGDROP_E_NOTREGISTERED_”错误,而不知道原因,请确保IE缩放在注册表中没有被禁用。检查是否在_HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Zoom_下有_ZoomDisabled=1_值,如果有,请将其删除。这可能会节省您的时间。 - dkozl
1
原文链接:http://web.archive.org/web/20111228094455/http://slingkid.blogsome.com/2007/04/13/ie-zoom - Charley Rathkopf
有没有一种方法可以获取缩放因子而不是设置它? - Kyle Delaney

18

小贴士:

//Zoom IN
webBrowser1.Focus();
SendKeys.Send("^{+}"); // [CTRL]+[+]

//Zoom OUT
webBrowser1.Focus();
SendKeys.Send("^-"); // [CTRL]+[-]

//Zoom 100%
webBrowser1.Focus();
SendKeys.Send("^0"); // [CTRL]+[0]

1
这在WPF/WinForms中给我一个错误,因为应用程序未处理Windows消息,所以无法在此应用程序内运行SendKeys。 - firebellys

14
这对我有效:

int zoomFactor = 300;
((SHDocVw.WebBrowser)webBrowser1.ActiveXInstance).ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM,
    SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, zoomFactor, IntPtr.Zero);

似乎这只能在文档加载后完成。

2
还需要添加一个COM引用到C:\Windows\System32\shdocvw.dll。 - Der_Meister
3
相反,应添加对“Microsoft Internet Controls”的引用。 - bluedog
2
当我尝试这样做时,出现了错误。试图撤销一个未注册的放置目标 (HRESULT 异常: 0x80040100 (DRAGDROP_E_NOTREGISTERED))。 - firebellys
3
在设置文档后立即应用缩放时,我遇到了DRAGDROP_E_NOTREGISTERED错误。如果在DocumentCompleted事件处理程序(WinForms)中调用,则可以正常工作。 - bgx

11

您可以使用CSS:

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        webBrowser1.Document.Body.Style = "zoom:50%";
    }

这是最容易的解决方案。非常好。只需将事件处理程序添加到DocumentCompleted事件并添加样式即可。像魔法一样运行。谢谢QHNPROF。 - KonaRin
这不会覆盖任何现有的样式吗? - Kyle Delaney
另外,WebBrowser.Document是一个对象。你是如何访问Body的? - Kyle Delaney

2
请注意,您传递给缩放函数的系数值假定100的值对应于网页的“正常”大小。系数值越高,意味着您正在“放大”,因此页面看起来更大。系数值越小,意味着您正在“缩小”,因此页面看起来更小。 我发现,在系数之间合理的增量为10。

1

如果有人遇到了和我一样的问题,这里是对 Gloupi 答案的修改,应该可以在更多国际系统上工作,因为加号和减号键位于不同的位置,使用小键盘符号键。这也修复了 Dvorak 布局的缩放问题。

// zoom in
webBrowser1.Focus();
SendKeys.Send("^{ADD}");

// zoom out
webBrowser1.Focus();
SendKeys.Send("^{SUBTRACT}");

// zoom reset
webBrowser1.Focus();
SendKeys.Send("^0");

"webBrowser1" 不包含 "focus" 的定义。因此,这个答案是错误的。 - Mark
你应该使用webBrowser1.Select() - Mark
@Mark 这段代码是从一个生产应用程序中复制粘贴来的。可能是版本问题,我猜测? - Polynomial
是的,我认为是这样 - 对于某些控件,Focus() 已被弃用,取而代之的是 Select()。不太确定在哪个 .NET 版本中发生了这种情况,但无论如何 :D - Mark
1
这个问题确实指定了.NET 2.0,我相信这是正确的。我发表这个答案只是为了指出在Gloupi上面的完全相同的答案中使用^{ADD}^{SUBTRACT}而不是^{+}^-,因为后者在某些非英语和非QWERTY键盘布局上会失败。 - Polynomial
你是正确的。我一定是跳过了.NET 2.0。请忽略我的愚蠢。 - Mark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接