本文共 5203 字,大约阅读时间需要 17 分钟。
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 EventHandlerStartNewWindow; 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好友的这么多,暂时不接受好友申请了,上限了。大家 还是留言吧。