CefSharp中ChromiumWebBrowser打开新页面处理(_blank)

简介: 原文:CefSharp中ChromiumWebBrowser打开新页面处理(_blank) 版权声明:欢迎转载,但是请保留出处说明 https://blog.csdn.net/lanwilliam/article/details/79640954 CefSharp的Browser怎么说也是嵌入了Chromium的浏览器,所以碰到标签“_blank”这样的时候,都是弹出新窗体打开新页面。
原文: CefSharp中ChromiumWebBrowser打开新页面处理(_blank)

版权声明:欢迎转载,但是请保留出处说明 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<NewWindowEventArgs> 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好友的这么多,暂时不接受好友申请了,上限了。大家 还是留言吧。

目录
相关文章
|
Prometheus 监控 Kubernetes
Prometheus + Grafana安装
Prometheus + Grafana安装
|
canal 消息中间件 存储
DDD领域驱动设计实战(六)-理解领域事件(Domain Event)(中)
DDD领域驱动设计实战(六)-理解领域事件(Domain Event)(中)
1451 0
|
8月前
|
存储 算法 C#
C# 哈希值计算:MD5/SHA256 加密
本示例展示了C#中使用MD5和SHA256算法生成哈希值的方法,适用于密码加密与数据校验。MD5安全性较低,建议仅用于非敏感场景;密码存储推荐使用SHA256配合盐值以增强安全性。
|
人工智能 开发者
通义千问三款主力模型再降价,最高降幅85%
通义千问三款主力模型再降价,最高降幅85%
9464 12
通义千问三款主力模型再降价,最高降幅85%
|
人工智能
巧妙构建歌词结构:写歌词的技巧和方法之关键,妙笔生词AI智能写歌词软件
在音乐世界里,歌词是灵魂的载体,构建其结构至关重要。优秀的歌词需有引人入胜的开头、条理清晰且富变化的主体,以及深刻难忘的结尾。《妙笔生词智能写歌词软件》提供多种功能,帮助创作者克服结构难题,激发灵感,助你写出打动人心的歌词,开启音乐创作的新篇章。
|
人工智能 供应链 数据可视化
低代码开发平台与零代码平台的区别?国内主流平台介绍与深度对比
本文深入解析低代码与零代码开发平台的技术特性与适用场景,盘点Zoho Creator、织信、OutSystems、简道云、钉钉宜搭等国内主流平台,对比其功能优势与典型案例,为企业数字化转型选型提供参考。
798 1
|
数据采集 存储 监控
Python 原生爬虫教程:网络爬虫的基本概念和认知
网络爬虫是一种自动抓取互联网信息的程序,广泛应用于搜索引擎、数据采集、新闻聚合和价格监控等领域。其工作流程包括 URL 调度、HTTP 请求、页面下载、解析、数据存储及新 URL 发现。Python 因其丰富的库(如 requests、BeautifulSoup、Scrapy)和简洁语法成为爬虫开发的首选语言。然而,在使用爬虫时需注意法律与道德问题,例如遵守 robots.txt 规则、控制请求频率以及合法使用数据,以确保爬虫技术健康有序发展。
1702 31
|
监控 前端开发 安全
C#一分钟浅谈:文件上传与下载功能实现
【10月更文挑战第2天】在Web应用开发中,文件的上传与下载是常见需求。本文从基础入手,详细讲解如何在C#环境下实现文件上传与下载。首先介绍前端表单设计及后端接收保存方法,使用`&lt;input type=&quot;file&quot;&gt;`与`IFormFile`接口;接着探讨错误处理与优化策略,如安全性验证和路径管理;最后讲解文件下载的基本步骤,包括确定文件位置、设置响应头及发送文件流。此外,还提供了进阶技巧,如并发处理、大文件分块上传及进度监控,帮助开发者构建更健壮的应用系统。
1117 16
|
Ubuntu 关系型数据库 MySQL
Ubuntu彻底卸载MySQL,彻底!亲测!
Ubuntu彻底卸载MySQL,彻底!亲测!
2251 0
|
存储
如何对局域网共享文件设置访问权限、如何对不同电脑设置不同权限
?例如只允许某个用户读取而不允许其上传、删除文件要如何实现呢?
2557 3

热门文章

最新文章