zoukankan      html  css  js  c++  java
  • WebBrowser与IE的关系,如何设置WebBrowser工作在IE9模式下?

    一.问题的提出


    偶然发现,Winform里的WebBrowser和IE实际安装的版本似乎并不同步,很有趣!

    下面有张图,里面一个窗口是用IE9打开某网站,另一个窗口是用Winform+WebBrowser打开同样的网站,有意思的事情出现了。

     

    在IE9窗口中,这个网站左边菜单树无法显示,原因是IE9使用的技术较新,而网站使用的技术较旧,未能及时同步更新到支持IE9所致。该如何办呢?

    微软在IE9中提供一个兼容性视图功能,只要一点击兼容性视图就可以兼容旧版本浏览器的网站。
     


    引用MSDN “To overcome potential compatibility issues, Internet Explorer supports a feature called Compatibility View that allows users to display troublesome pages in IE7 mode. “ URL: http://msdn.microsoft.com/en-us/library/dd567845(v=VS.85).aspx

    也就是说,这个兼容模式就是IE7的模式。

    又查了些ms资料,发现这个兼容性视图在IE8时首次引入,在IE9,IE10中都将继续支持。

    再翻回来看Winform+WebBrowser这个窗口,它打开同样的网站却能显示左边菜单树,这样看来,似乎WebBrowser不用设置就默认自动打开了兼容性视图模式。

    现在就去仔细查一下权威资料,核实一下两个问题:
    1.Webbrowser与IE到底是什么关系?是否确实用ie内核, 是否本质上和360安全浏览器,傲游浏览器和腾讯TT等IE内核浏览器相同。
    2.Webbrowser是否使用兼容浏览模式,以及这个模式是否能改?

    二.查询结果

    1.webbrowser调用的就是本机IE9,并且webbrowser默认就是运行在IE7 mode下,除非你改变它.

    发现一个msdn的帖子,明确表示webbrowser调用的就是本机IE9,并且webbrowser默认就是运行在IE7 mode下,除非你改变它。
    How to make c# WebBrowser equivalent to IE browser  
    http://social.msdn.microsoft.com/Forums/en/winforms/thread/2ed65b9d-c601-4ca8-bde1-64584fc87515

    摘几句:
    Wow first post with such bold claim without any source backing up. You probably should read the IE SDK (the manual you need to read if you want to use the webbrowser control) or dig through the IE programming forums (that's the place others often go when they are stuck on IE programming) if you want to use the webbrowser control.

    Webbrowser is a wrapper around IE APIs. There is no such thing as multiple versions of IE coexisting on the same computer. You will always get the one and only version of IE installed on the computer from webbrowser control.

    There are many, many documented setting differences between default IE and webbrowser. Basically you don't have to opt out new features in webbrowser that may break your app (the Visual Studio team learned a hard lesson here, when IE8 breaks Visual Studio's wizards) , you have to write code to opt in, unless the improvement is security related. That means the webbrowser will run in IE7 mode unless you change the mode in feature control.

    Note some web site declare their requirement of IE7 or IE8 mode. It may not be wise to force the IE9 mode. 

    2.微软新闻组的一个帖子,Webbrowser Control without IE,里面明确提到,不装IE,无法用webbrowser.
    http://groups.google.com/group/microsoft.public.vb.controls/browse_thread/thread/7575bd25e0730ded/aa40f3dfc799407d?lnk=gst&q=WebBrowser+ie#aa40f3dfc799407d

    IE must be installed on the machine for you to use Webbrowser Control.

    Internet Explorer MUST be installed to use the WebBrowser control.  There are simply no ifs, ands, or buts about it.  How can you expect to use IE functionality if IE is not installed?

    3.如何设置WebBrowser在IE9 mode下工作呢?
    答曰:需要修改注册表,具体看下面4,5,6,尤其6最全面,可以光看6。

    4.WPF webbrowser control using IE7 instead of IE9
    http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/4431908e-1869-4435-bcea-a3ec0820edfb

    摘抄几句:
    How do I make it so the WPF WebBrowser control will use IE9 as the browser engine instead of IE7?
    I have some HTML that is rendering differently in the WebBrowser control than in the IE9 browser. When I run the following javascript in the WebBrowser, the result is "7". as in IE7.

    I found an article by Rick Strahl that describes registry settings that will get the WebBrowser to use IE9. But I would like to avoid that. And I am interested to know how IE7 comes about being used.http://www.west-wind.com/weblog/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version
    回答:You want to avoid the only documented way to set document compatibility mode for webbrowser hosts? Why?

    5.WebBrowser and CSS3 ?
    http://social.msdn.microsoft.com/Forums/en-AU/winforms/thread/1b656af7-bda9-47d9-8f9a-1d886d3688ca
    Web browser control by default runs in compatibility mode unless you set the feature browser emulation registry key. The fact that IE9 is able to render CSS3 correctly and browser control is not seems to suggest browser control is not running in IE9 standards mode.

    You'll need to set Browser emulation feature key (FEATURE_BROWSER_EMULATION) described at this link http://msdn.microsoft.com/en-us/library/ee330730%28v=vs.85%29.aspx

    You can use 9000 value, unless you want to force IE 9 standards mode for all pages. In case of later, you need to use 9999.

    hklm

    If hklm and 64bit machine used, you need to check is Wow6432Node needs to be changed.

    And finally you need to add process name hosting browser control as value name in the registry key.

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION]
    "prevhost.exe"=dword:00001f40
    "sllauncher.exe"=dword:00001f40
    "WindowsFormsApplication1.exe"=dword:0000270f

    6.Web Browser Control – Specifying the IE Version 
    http://www.west-wind.com/weblog/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version

    I use the Internet Explorer Web Browser Control in a lot of my applications to display document type layout. HTML happens to be one of the most common document formats and displaying data in this format – even in desktop applications, is often way easier than using normal desktop technologies.

    One issue the Web Browser Control has that it’s perpetually stuck in IE 7 rendering mode by default. Even though IE 8 and now 9 have significantly upgraded the IE rendering engine to be more CSS and HTML compliant by default the Web Browser control will have none of it. IE 9 in particular – with its much improved CSS support and basic HTML 5 support is a big improvement and even though the IE control uses some of IE’s internal rendering technology it’s still stuck in the old IE 7 rendering by default.

    This applies whether you’re using the Web Browser control in a WPF application, a WinForms app, a FoxPro or VB classic application using the ActiveX control. Behind the scenes all these UI platforms use the COM interfaces and so you’re stuck by those same rules.

    Feature Delegation via Registry Hacks
    Fortunately starting with Internet Explore 8 and later there’s a fix for this problem via a registry setting. You can specify a registry key to specify which rendering mode and version of IE should be used by that application. These are not global mind you – they have to be enabled for each application individually.

    There are two different sets of keys for 32 bit and 64 bit applications.

    32 bit:

    HKEY_LOCAL_MACHINESOFTWAREMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION

    Value Key: yourapplication.exe

    64 bit:

    HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION

    Value Key: yourapplication.exe

    The value to set this key to is (taken from MSDN here) as decimal values:

    9999 (0x270F) 
    Internet Explorer 9. Webpages are displayed in IE9 Standards mode, regardless of the !DOCTYPE directive.

    9000 (0x2328) 
    Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.

    8888 (0x22B8) 
    Webpages are displayed in IE8 Standards mode, regardless of the !DOCTYPE directive.

    8000 (0x1F40) 
    Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode.

    7000 (0x1B58) 
    Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode.

     

    ok, 言尽至此,无话可说了!

    posted @ 2012-03-21 16:17 BobLiu 阅读(1380) 评论(3) 编辑
     

    最近工作需要,学习了一下winform内嵌webbrowser控件,然后与htm页面中的javascript交互调用的技术,因此有了这篇心得。

    总的来说,javascript与winform的code互相调用,和web开发中javascript与服务器端代码通过ajax互相调用有类似之处。

    下面就用三个例子来说明:

    一.将WebBrowser控件放置在winform中,然后,写一个Page1.htm,内容如下:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
     <head>
      <title></title>
            <script type="text/javascript">
                function test(message) 
                {
                    alert(message); 
                }
            </script>
     </head>
     <body>
         <button onclick="test('test called from script code')">Button</button>
     </body>
    </html>

    我将此Page1.htm显示在WebBrowser中看看,这个不难写,在winform中加上下面一句即可。
    webBrowser1.Url= new Uri("C:\workspace\WindowsFormsApp\WindowsFormsApp\Page1.htm");

    然后运行,在winform中的webbrowser显示出来这个htm了,点按钮调用javascript函数,弹出alert提示,一切都很正常,没什么稀奇。

    二.如果我把javascript中的函数挪到winform的cs代码里,htm页面还能调用的到吗?
    这有点ajax的味道了,在客户端的javascript里如何调用webpage.aspx.cs里的代码,在ajaxpro那时候,是需要在webpage.aspx.cs的代码里注册一下本页供ajax使用,在函数前也要声明一下是ajax函数的。

    再说回来,如果想调用winform中的代码,也类似的,要给winform设置一下ComVisibleAttribute(true), 并给webbrowser控件设置一下webBrowser1.ObjectForScripting属性。
    webBrowser1.Url= new Uri("C:\workspace\WindowsFormsApp\WindowsFormsApp\Page1.htm");
    webBrowser1.ObjectForScripting = this;

    其实,如果做的好,可以把这些代码专门归入一个类中,方便管理,这里就变为:webBrowser1.ObjectForScripting = new 某类()了;

    然后,再在winform里写一个函数。
            public void Test(String message)
            {
                MessageBox.Show(message, "client code");
            }

    最后,htm里调用时要用window.external前缀一下Test方法名。
    <button onclick="window.external.Test('test called from windows code')">Button</button>

    然后再运行,就发现,htm里的onclick事件,居然能调用winform里的code了,真是神奇!

    完整winform代码如下:
    using System;
    using System.Windows.Forms;
    using System.Security.Permissions;
      
    namespace WindowsFormsApp
    {
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        [System.Runtime.InteropServices.ComVisibleAttribute(true)]
        public partial class Form2 : Form
        {
            private WebBrowser webBrowser1 = new WebBrowser();

            public Form2()
            {
                InitializeComponent();

                button1.Text = "call script code from client code";
                button1.Dock = DockStyle.Top;
                button1.Click += new EventHandler(button1_Click);
                webBrowser1.Dock = DockStyle.Fill;
                Controls.Add(webBrowser1);
                Load += new EventHandler(Form2_Load);

            }

            private void Form2_Load(object sender, EventArgs e)
            {
                webBrowser1.AllowWebBrowserDrop = false;
                webBrowser1.IsWebBrowserContextMenuEnabled = false;
                webBrowser1.WebBrowserShortcutsEnabled = false;
                webBrowser1.ObjectForScripting = this;
                webBrowser1.Url= new Uri("C:\workspace\WindowsFormsApp\WindowsFormsApp\Page1.htm");
            }

            public void Test(String message)
            {
                MessageBox.Show(message, "client code");
            }      
        }
    }

    总结一下,关键的webBrowser1.ObjectForScripting属性,ComVisibleAttribute(true)和window.external。


    msdn说webBrowser1.ObjectForScripting属性的作用是:获取或设置一个对象,该对象可由显示在 WebBrowser 控件中的网页所包含的脚本代码访问。使用该属性可以启用 WebBrowser 控件承载的网页与包含 WebBrowser 控件的应用程序之间的通信。使用该属性可以将动态 HTML (DHTML) 代码与客户端应用程序代码集成在一起。为该属性指定的对象可作为 window.external 对象(用于主机访问的内置 DOM 对象)用于网页脚本。

    可以将此属性设置为希望其公共属性和方法可用于脚本代码的任何 COM 可见的对象。可以通过使用 ComVisibleAttribute 对类进行标记使其成为 COM 可见的类。
    这一步也至关重要,如果不设置ComVisibleAttribute(true),那这个程序就不能加载显示htm页面,因为htm里用了window.external.Test()方法,该方法所在的类如果不ComVisible,就无法访问到了。反过来,如果设置了ComVisible,却不设置webBrowser1.ObjectForScripting属性,那代码执行时会报错:window.external无效或找不到对象。

    而缺少了window.external,就更甭提了,因此,这三者缺一不可。

    再看看这个window.external,在常见的javascript书中不见踪影,但却非常有用,一个常见的应用是:
    <input type="button" name="Button" value="add" onclick="window.external.AddFavorite(location.href,document.title)" />

    引用别人的"在嵌入了浏览器的工程中,除了IE默认提供的外部方法之外,需要网页的脚本中能调用c++代码,要实现这种交互,就必须实现脚本扩展。实现脚本扩展就是在程序中实现一个IDispatch接口,通过CHtmlView类的OnGetExternal虚函数返回此接口指针,这样就可以在脚本中通过window.external.XXX(关键字window可以省略)来引用接口暴露的方法或属性(XXX为方法或属性名)。"

    再看看在c#中的脚本扩展,只需要webBrowser1.ObjectForScripting和ComVisibleAttribute(true)简单一设置就完事了,简单吧!幸福吧!悲催吧!


    三.再来看一个,从winform的code里,能调用html页面里的javascript吗?
    Page1.htm,删掉button,只保留javascript脚本。
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
     <head>
      <title></title>
            <script type="text/javascript">
                function test(message) 
                {
                    alert(message); 
                }
            </script>
     </head>
     <body>
        
     </body>
    </html>


    using System;
    using System.Windows.Forms;
    using System.Security.Permissions;
      
    namespace WindowsFormsApp
    {
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        [System.Runtime.InteropServices.ComVisibleAttribute(true)]
        public partial class Form2 : Form
        {
            private WebBrowser webBrowser1 = new WebBrowser();
            private Button button1 = new Button();

            public Form2()
            {
                InitializeComponent();

                button1.Text = "call script code from client code";
                button1.Dock = DockStyle.Top;
                button1.Click += new EventHandler(button1_Click);
                webBrowser1.Dock = DockStyle.Fill;
                Controls.Add(webBrowser1);
                Controls.Add(button1);
                Load += new EventHandler(Form2_Load);

            }

            private void Form2_Load(object sender, EventArgs e)
            {
                webBrowser1.AllowWebBrowserDrop = false;
                webBrowser1.IsWebBrowserContextMenuEnabled = false;
                webBrowser1.WebBrowserShortcutsEnabled = false;
                webBrowser1.ObjectForScripting = this;
                webBrowser1.Url= new Uri("C:\workspace\WindowsFormsApp\WindowsFormsApp\Page1.htm");
            }

            private void button1_Click(object sender, EventArgs e)
            {
                webBrowser1.Document.InvokeScript("test",
                    new String[] { "called from client code" });
            }

        }
    }

    这回关键的因素就是webBrowser1.Document.InvokeScript了,而webBrowser1.ObjectForScripting,ComVisible不再需要了。

    HtmlDocument.InvokeScript 方法的作用是:执行在 HTML 页面中定义的动态脚本函数。

    至此,javascript与winform的code就可以互相调用了,感觉和web开发也有些类似。

    这项技术叫在javascript(DHTML)代码和客户端应用程序代码之间实现双向通信.

  • 相关阅读:
    Html.ActionLink 几种重载方式说明及例子
    2 python 文本特征提取 CountVectorizer, TfidfVectorizer
    模型调参---GridSearchCV
    1 NLP学习大纲
    pandas.dropna/isnull/fillna/astype的用法
    激活函数总结
    LeetCode--53 最大连续子序列(总结)
    LeetCode--44 通配符匹配
    LeetCode--Two_Sum
    css 背景图片自适应元素大小
  • 原文地址:https://www.cnblogs.com/dengpeng1004/p/5432361.html
Copyright © 2011-2022 走看看