博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CefSharp中ChromiumWebBrowser打开新页面处理(_blank)
阅读量:6328 次
发布时间:2019-06-22

本文共 5203 字,大约阅读时间需要 17 分钟。

原文:

版权声明:欢迎转载,但是请保留出处说明 https://blog.csdn.net/lanwilliam/article/details/79640954

CefSharp的Browser怎么说也是嵌入了Chromium的浏览器,所以碰到<a >标签“_blank”这样的时候,都是弹出新窗体打开新页面。

但是怎奈我使用了DevExpress控件中的TabForm这个东西来作为主窗体,所以我不希望弹出新的窗体来,那么就需要捕获打开新窗体这样一个事件来重写了。

但是你会发现,在ChromiumWebBrowser对象中,没有OnNewWindow这类的事件啊,怎么办,难道到此为止了吗?!

果然百度还是无能为力,科学上网找google查了一下。CefSharp通过另一个对象处理的这类事件。CefLifeSpanHandler,就是这个东西了。里面提供了我们要用的事件,不废话,上代码。

    public class CefLifeSpanHandler : CefSharp.ILifeSpanHandler    {        public CefLifeSpanHandler()        {        }        public bool DoClose(IWebBrowser browserControl, CefSharp.IBrowser browser)        {            if (browser.IsDisposed || browser.IsPopup)            {                return false;            }            return true;        }        public void OnAfterCreated(IWebBrowser browserControl, IBrowser browser)        {        }        public void OnBeforeClose(IWebBrowser browserControl, IBrowser browser)        {        }                public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)        {            var chromiumWebBrowser = (ExtChromiumBrowser)browserControl;            chromiumWebBrowser.Invoke(new Action(() =>            {                NewWindowEventArgs e = new NewWindowEventArgs(windowInfo, targetUrl);                chromiumWebBrowser.OnNewWindow(e);            }));            newBrowser = null;            return true;        }    }

这是Handler的实现。

然后需要封装一下ChromiumWebBrowser,提供OnNewWindow事件。

    public class ExtChromiumBrowser : ChromiumWebBrowser    {        public ExtChromiumBrowser()            : base(null)        {            this.LifeSpanHandler = new CefLifeSpanHandler();            //this.DownloadHandler = new DownloadHandler(this);        }        public ExtChromiumBrowser(string url) : base(url)        {            this.LifeSpanHandler = new CefLifeSpanHandler();        }        public event EventHandler
StartNewWindow; public void OnNewWindow(NewWindowEventArgs e) { if (StartNewWindow != null) { StartNewWindow(this, e); } } }

含有事件参数定义

    public class NewWindowEventArgs : EventArgs    {        private IWindowInfo _windowInfo;        public IWindowInfo WindowInfo        {            get { return _windowInfo; }            set { value = _windowInfo; }        }        public string url { get; set; }        public NewWindowEventArgs(IWindowInfo windowInfo, string url)        {            _windowInfo = windowInfo;            this.url = url;        }    }

然后我们用新定义的ExtChromiumBrowser替换之前的ChromiumWebBrowser,并且实现相关代码。

        public void InitBrowser()        {            Cef.Initialize(new CefSettings());            browser = new ExtChromiumBrowser("http://124.128.61.90:10080/login.html");            //this.Controls.Add(browser);            tabFormContentContainer1.Controls.Add(browser);            browser.Dock = DockStyle.Fill;            browser.StartNewWindow += Browser_StartNewWindow;            browser.TitleChanged += OnBrowserTitleChanged;            browser.FrameLoadEnd += browser_FrameLoadEnd;            CefSharpSettings.LegacyJavascriptBindingEnabled = true;            browser.RegisterJsObject("jsObj", new SendCarBillPrint());            //browser.JavascriptObjectRepository.Register("jsObj", new SendCarBillPrint(), false);        }

然后是StartNewWindow的事件实现。

        private void Browser_StartNewWindow(object sender, NewWindowEventArgs e)        {            TabFormPage tp = new TabFormPage();            tp.Text = "新窗口";            TabFormContentContainer tc1 = new TabFormContentContainer();            tp.ContentContainer = tc1;            tc1.Dock = DockStyle.Fill;            var control = new ExtChromiumBrowser(e.url);            control.Dock = DockStyle.Fill;            //control.CreateControl();            //host.Child = control;            control.Focus();            tc1.Controls.Add(control);            tabFormControl1.Pages.Add(tp);            tabFormControl1.SelectedPage = tp;            tp.Text = control.Text;            control.StartNewWindow += Browser_StartNewWindow;            control.TitleChanged += OnBrowserTitleChanged;            //e.WindowInfo.SetAsChild(control.Handle, 0, 0, (int)host.ActualWidth, (int)host.ActualHeight);        }

这样就实现了拦截打开窗口事件,并且在新tab中打开了。

需要注意的是,OnBeforePopup 事件中,return true后,ChromiumWebBrowser就不会再打开新窗口了。我这里手动创建了新的Tab页,然后添加了Browser,然后将拦截的url设置上去,实现了新tab的显示。但其实这样做并非最优,我这里是为解决DevExpress的Tab窗体控件问题才这么搞的。

注意看我之前注释的代码。

e.WindowInfo.SetAsChild(control.Handle, 0, 0, (int)host.ActualWidth, (int)host.ActualHeight);

其实这才是正确的办法。

在OnBeforePopup 事件中返回false。然后在Browser_StartNewWindow事件中,通过上面SetAsChild方法设置才是好的办法。原理是将新打开窗体的设置到Control.Handle上去了。Control可以是个窗体,也可以是个Panel之类的Control,设置好大小。这样原则上只开了一个Browser对象。道理上应该性能好一点。

但是,注意了,但是,我本来想优化一下来着,发现在windows任务管理器中,其实也是两个进程,加上DevExpress好多资料不好找,于是就先这样了。有空再说吧。

至此,基本上Winform嵌入ChromiumWebBrowser的必要功能就全了,可以应用了。

希望对大家有帮助。

抱歉,没想到加QQ好友的这么多,暂时不接受好友申请了,上限了。大家 还是留言吧。

你可能感兴趣的文章
2018-2019-2 20175311 实验一《Java开发环境的熟悉》实验报告
查看>>
修改linux最大文件句柄数
查看>>
网络编程---tcp/udp协议
查看>>
jmeter3.2 版本完美实现Load Test报表
查看>>
再看python多线程------threading模块
查看>>
R 从零开始,简单API集合
查看>>
学习react系列(八)—— mixins迁移
查看>>
《工作DNA》摘录三
查看>>
Daily Scrum 12.9
查看>>
PHP之道推荐使用PHP版本,数据库方式,以及虚拟机的创建程序
查看>>
YAML文件的使用及参数服务器
查看>>
5.7-多源复制搭建
查看>>
now()与sysdate()的区别(1)
查看>>
jmeter压力测试值之配置JDBC Connection Configuration(一)
查看>>
linux每日命令(10):touch命令
查看>>
给natp_server加缓存
查看>>
Index Generation
查看>>
多系统通讯-DotNetMQ
查看>>
java之网络编程
查看>>
iOS----应用的旋转---Orientations
查看>>