CefSharp中ChromiumWebBrowser打开新页面时使用自己定义的窗体

文章介绍了如何在使用CefSharp的ChromiumWebBrowser时,阻止<a>标签_blank弹出新窗口,而是通过自定义的TabForm控件来承载新页面。关键在于实现ILifeSpanHandler接口的OnBeforePopup事件,拦截新窗口打开并在TabForm中创建新的Tab页展示。
摘要由CSDN通过智能技术生成

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

————————————————

版权声明:本文为CSDN博主「b哈利路亚d」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/lanwilliam/article/details/79640954

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值