原文: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好友的这么多,暂时不接受好友申请了,上限了。大家 还是留言吧。

CefSharp中ChromiumWebBrowser打开新页面处理(_blank)的更多相关文章

  1. Web设计中打开新页面或页面跳转的方法 js跳转页面

    Web设计中打开新页面或页面跳转的方法 一.asp.net c# 打开新页面或页面跳转 1. 最常用的页面跳转(原窗口被替代):Response.Redirect("newpage.aspx ...

  2. Web设计中打开新页面或页面跳转的方法

    一.asp.net c# 打开新页面或页面跳转 1. 最常用的页面跳转(原窗口被替代):Response.Redirect("newpage.aspx"); 2. 利用url地址打 ...

  3. jq中打开新页面 并获取携带值

    打开新页面:window.location.href = "./index.html?id=1"获取携带值: function GetRequest() { var url = l ...

  4. 模态对话框中的window.close关闭时会打开新页面

    在模态对话框的页面的<head></head>加上<base target="_self"> 就不会打开新页面了.

  5. JavaScript关闭窗口的同时打开新页面的方法

    做网页的时候需要弹出一个小窗口,然后要实现一个功能就是鼠标点击超链接关闭小窗口并打开一个新页面,就如同下图: 这是一个小窗口,点击超链接这个窗口会关闭并且会正常在浏览器打开新页面,首先写js关闭窗口的 ...

  6. DTcms手机版使用余额支付 提示信息跳转到PC版的错误。以及提交订单不打开新页面

    手机版使用余额支付 提示信息跳转到PC版的错误 引起错误的原因是中间需要提交到DTcms.Web\api\payment\balance\index.aspx去处理 导致BasePage.cs中的li ...

  7. ASP.NET 后台打开新页面

    [TOC] Response.Write 这是最常见的后台打开新页面的方法. Response.Write("<script>window.open('~/FileView.as ...

  8. 点击iframe窗口里的超链接,打开新页面的方式

    点击iframe窗口里的超链接打开新页面的方式: a标签中设置按钮点击事件,事件调用的方法使用如下方法跳转链接:  window.open('url链接', '_blank');

  9. 如何使a标签打开新页面并阻止刷新当前页面

    错误: HTML中,使用href属性时,当前页面和新页面均跳转到URL指定的页面,即当前页面也刷新: <li id='goToBack'><a href='**.action' ta ...

随机推荐

  1. matplotlib学习之颜色样式

    一.颜色 1.内建八种默认颜色 蓝色 - 'b' 绿色 - 'g' 红色 - 'r' 青色 - 'c' 品红 - 'm' 黄色 - 'y' 黑色 - 'k' 白色 - 'w' 2.灰度 plt.plo ...

  2. 使用perl读取Excel

    使用perl读取Excel 环境 windows 7 ActiveState Perl Win32::OLE[perl package] 基本功能 循环处理多个sheet 读取Excel单元,提取in ...

  3. Effective Java读书笔记——第三章 对于全部对象都通用的方法

    第8条:覆盖equals时请遵守通用的约定 设计Object类的目的就是用来覆盖的,它全部的非final方法都是用来被覆盖的(equals.hashcode.clone.finalize)都有通用约定 ...

  4. Scrapy系列教程(1)------命令行工具

    默认的Scrapy项目结构 在開始对命令行工具以及子命令的探索前,让我们首先了解一下Scrapy的项目的文件夹结构. 尽管能够被改动,但全部的Scrapy项目默认有类似于下边的文件结构: scrapy ...

  5. .netcore consul实现服务注册与发现-单节点部署

    原文:.netcore consul实现服务注册与发现-单节点部署 一.Consul的基础介绍     Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其他分 ...

  6. RoundingMode 几个参数详解

    第一版 java.math.RoundingMode 几个参数详解 java.math.RoundingMode里面有几个参数搞得我有点晕,现以个人理解对其一一进行总结: 为了能更好理解,我们可以画一 ...

  7. 【t033】单位unit

    Time Limit: 1 second Memory Limit: 64 MB [问题描述] 某星球上有很多计量系统,之间的计量单位的转换很繁琐.希望你能编程解决这个问题. 现有N (1 <= ...

  8. QT类库与Delphi VCL类库的体系结构对比——两者十分类似!

    今天在看QT对象内存管理的一篇文章时:http://blog.csdn.net/dbzhang800/article/details/6300025想到了一个问题:就是QT类库体系结构与Delphi类 ...

  9. 作为电磁波的 Wi-Fi 信号

    常用 WiFi:2.4 GHz,而同样是电磁波的可将光,频率是 WiFi 的十几万倍: 如何让家里的 WiFi 信号变得更好,移动路由器到合适位置: 1. Wi-Fi:穿墙有术还是穿墙无术? 我们都会 ...

  10. 实践-Task

    实践-Task 上篇博文中,我们介绍了Thread和ThreadPool: 多线程异步编程示例和实践-Thread和ThreadPool 本文中我们继续,说一下TPL(Task Parallel Li ...