CefSharp 實現多標簽頁 調用ChromiumWebBrowser的SetAsPopup()后瀏覽頁卡死,的另一種解決方案


最進想使用WPF+CefSharp實現瀏覽器多標簽頁, 所以直接實現ILifeSpanHandler接口添加窗口處理,但是在OnBeforePopup方法中,設置好窗口句柄后觸發彈出新頁時發現一個尷尬的問題:

問題

OnBeforePopup方法中調用SetAsPopup()方法,會導致瀏覽器首頁卡死(僅在WPF中發現,Winform不會),新窗口頁正常操作(后續窗口頁中都不會有這個問題)。

如果不調用SetAsPopup()方法,會導致新窗口頁的事件全部失效(處理器不會),比如TitleChanged事件在瀏覽器標題更改后,需要及時更新瀏覽器標題到控件上,這樣就無法觸發瀏覽器標題更改事件(TitleChanged)。

解決辦法

既然調用SetAsPopup會卡死,那我們就不調用,但是不調用SetAsPopup會導致新打開的窗口頁事件丟失,那就想辦法手動實現這個方法的一部分功能(賦值事件、處理器等信息)。

SetAsPopup方法中最后有一個out IWebBrowser newBrowser 參數,這個參數作用是新打開窗口頁的瀏覽器對象需不需要我們提供,一般設置這個參數為null,不需要我們提供。

如果不為null時,新窗口瀏覽器對象將使用newBrowser作為新窗口頁的瀏覽器對象。

        public bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, 
out
IWebBrowser newBrowser) {

所以在方法中顯示給newBrowser賦上值,(相當於實現一部分SetAsPopup方法工作...): 

public class CefLifeSpanHandler : ILifeSpanHandler
{
    //省略其他ILifeSpanHandler接口實現方法...

//構造函數傳入窗口對象,方便控制窗口中的控件 MainWindow mainWindow; public CefLifeSpanHandler(MainWindow _mainWindow) { this.mainWindow = _mainWindow; }   //瀏覽器新窗口彈出時調用方法 public bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser) { //為新彈窗創建一個瀏覽器對象 ChromiumWebBrowser newChromeBrowser = new ChromiumWebBrowser(); //為新彈窗復制窗口處理 newBrowser.LifeSpanHandler = this; //省略賦值其他處理器... //賦值標題修改事件 newChromeBrowser.TitleChanged += mainWindow.Chrome_TitleChange; //省略賦值其他事件.... //留下創建的瀏覽器對象引用,windowList(List<ChromiumWebBrowser>)是在MainWindow下聲明的變量,窗口關閉時要釋放,不然退出程序會跨線程訪問控件錯誤 mainWindow.windowList.Add(newChromeBrowser); //為瀏覽器賦值 newBrowser = newChromeBrowser; //.... return false; } }

到這里,在新窗口頁打開時,即觸發了標題修改事件,又沒有導致瀏覽器首頁卡死,但在關閉窗口時,會報跨線程訪問錯誤,需要在窗口關閉時釋放掉創建的窗口瀏覽器對象:

private void Window_Closed(object sender, EventArgs e)
{
    //釋放每一個chrome窗口資源
    for (int i = 0; i < windowList.Count; i ++)
    {
 windowList[i].Dispatcher.Invoke(delegate { windowList[i].Dispose(); });
    }
}

到這里,基本上解決了阻止瀏覽器彈窗時調用 SetAsPopup 首頁卡死問題。

 

如果本人有理解不對的地方,希望前輩們評論區指導,非常感謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM