記錄一次cefsharp1輸入法在win7下異常解決定位


  最近幾天都被基於cefSharp封裝的瀏覽器控件搞瘋了!對於cefSharp基本滿足當前所做項目的需求,但是有一個問題一直困擾我,那就是系統中偶爾會出現輸入法不能轉換到中文。而且這個問題似乎沒有什么規律。

【項目需求】

  先說一下項目對瀏覽器控件的需求,如果沒有需要做聽音這個功能,其實項目可以是一個B/S架構。但是由於現在需要聽音功能,所以決定使用C/S的架構。其中客戶端采用瀏覽器控件來實現網頁加載。客戶端主窗口內嵌一個瀏覽器控件,然后頁面有需要聽音的時候可以點擊聽音然后彈出聽音窗口。聽音窗口又是由一個音頻播放器+瀏覽器控件組成。

【最初實現】 

  最初使用的是webBrowser控件,能夠實現功能,但是webBrowser有太多坑,不斷出現內存泄露和根據客戶端IE版本進行樣式渲染,HTML5兼容性差等等,諸多問題。於是痛下狠心,決定換基於webkit的瀏覽器控件。

【痛苦的嘗試】

   .Net中 基於webKit 的瀏覽器控件還是很多,於是做了一下各個版本的嘗試:

  • webKit.Net 0.5 : 該控件內核比較老,目前最新還是2010,該控件唯一的優勢是和webBrowser使用比較接近。但是項目中使用了Angularjs,在每次取數據超過100條時,速度變慢。果斷pass。
  • OpenWebKitSharp :該項目是基於webKit.Net的一次封裝。該控件對系統的功能能很好的滿足,但是與我們的系統有一個致命的不兼容性那就是內存泄露。
  • cefSharp:基於cef1,能夠滿足項目的基本需求所以選擇了該控件。

【輸入法異常】

  選擇了cefSharp后,在使用中出現一個讓人崩潰的問題,那就是輸入法偶爾出現不能轉換到中文。而且不好定位問題出現在什么位置。褲褲折騰一周終於找到原因。

基於cefSharp1自己封裝了一個瀏覽器控件,代碼如下(有刪減):

 

namespace XXXXXX.UserCtrol
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using CefSharp.WinForms;
    using CefSharp;
    using System.IO;

    public partial class WebKitBrowser : UserControl
    {
        #region 字段
        /// <summary>
        /// webView
        /// </summary>
        private WebView _Core;

        /// <summary>
        /// 網頁地址
        /// </summary>
        private string _Url;

        /// <summary>
        /// CEF環境設置
        /// </summary>
        private static Settings cefSettings;
        #endregion

        #region 構造函數
        /// <summary>
        /// 構造函數
        /// </summary>
        public WebKitBrowser()
            : this("about:blank")
        {

        }

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="url">地址</param>
        public WebKitBrowser(string url)
            : this(url, new BrowserSettings())
        {
        }

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="settings">瀏覽器設置</param>
        public WebKitBrowser(string url, BrowserSettings settings)
        {
            InitializeComponent();

            _Url = url;
            this._Core = new WebView(url, settings);

            this._Core.Dock = DockStyle.Fill;
            this.Controls.Add(this._Core);
            BindEvents();
        }
        #endregion

        #region 方 法

        #region 公有方法
        /// <summary>
        /// 頁面導航
        /// </summary>
        /// <param name="url">地址</param>
        public void Navigate(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                this._Core.Load("about:blank");
            }
            else
            {
                this._Core.Load(url);
            }
        }

        /// <summary>
        /// JS交互對象
        /// </summary>
        /// <param name="obj">交互對象</param>
        public void ObjectForScript(object obj)
        {
            this._Core.RegisterJsObject("external", obj);
        }

        /// <summary>
        /// 調用JS方法
        /// </summary>
        /// <param name="funcName">函數名</param>
        /// <param name="args">參數</param>
        /// <param name="isAsync">是否異步</param>
        /// <returns>返回值</returns>
        public object CallJavaScriptMethod(string funcName, object[] args, bool isAsync = false)
        {
            StringBuilder sparam = new StringBuilder();
            sparam.Append(funcName).Append("(");
            if (args != null)
            {
                for (int i = 0; i < args.Length; i++)
                {
                    object o = args[i];
                    if (i > 0)
                    {
                        sparam.Append(",");
                    }

                    if (o is string)
                    {
                        sparam.Append("\"").Append(o.ToString().Replace("\"", "'")).Append("\"");
                    }
                    else
                    {
                        sparam.Append(o);
                    }
                }
            }
            sparam.Append(")");
            try
            {
                if (isAsync)
                {
                    this._Core.ExecuteScript(sparam.ToString());
                    return null;
                }
                else
                {
                    return this._Core.EvaluateScript(sparam.ToString());
                }

            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 綁定下載控制器
        /// </summary>
        /// <param name="hanler">下載控制類</param>
        public void BindDownLoadHandler(IRequestHandler hanler)
        {
            this._Core.RequestHandler = hanler;
        }

        /// <summary>
        /// 綁定快捷鍵菜單
        /// </summary>
        /// <param name="Handler">菜單控制類</param>
        public void BindMenuHandler(IMenuHandler handler)
        {
            this._Core.MenuHandler = handler;
        }

        /// <summary>
        /// 綁定頁面加載控制器
        /// </summary>
        /// <param name="handler">控制器</param>
        public void BindLoadHandler(ILoadHandler handler)
        {
            this._Core.LoadHandler = handler;
        }


        /// <summary>
        /// 綁定JS彈出框控制器
        /// </summary>
        /// <param name="handler">控制器</param>
        public void BindJSDialogHandler(IJsDialogHandler handler)
        {
            this._Core.JsDialogHandler = handler;
        }
        
        /// <summary>
        /// 資源釋放
        /// </summary>
        public void Dispose()
        {
            if(this._Core !=null)
            {
                this._Core.Dispose();
            }
        }
      
        #endregion

        #region 私有方法
        /// <summary>
        /// 綁定事件
        /// </summary>
        private void BindEvents()
        {
            this._Core.LoadCompleted += new LoadCompletedEventHandler(_Core_LoadCompleted);
            this._Core.PropertyChanged += new PropertyChangedEventHandler(_Core_PropertyChanged);
        }
        #endregion

        #endregion

        #region 事 件
        /// <summary>
        /// 瀏覽器加載完成事件
        /// </summary>
        public EventHandler<LoadCompletedEventArgs> DocumentCompletedEvent;

        /// <summary>
        /// 屬性改變事件
        /// </summary>
        public EventHandler<PropertyChangedEventArgs> DocumentPropertyChangedEvent;


        /// <summary>
        /// 加載完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="url"></param>
        private void _Core_LoadCompleted(object sender, LoadCompletedEventArgs url)
        {
            if (DocumentCompletedEvent != null)
            {
                DocumentCompletedEvent(sender, url);
            }
        }

        /// <summary>
        /// 屬性改變事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _Core_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (DocumentPropertyChangedEvent != null)
            {
                DocumentPropertyChangedEvent(sender, e);
            }
        }

        #endregion

        #region 屬 性
        /// <summary>
        /// 獲取瀏覽器地址
        /// </summary>
        public string Url
        {
            get { return this._Url; }
        }

        /// <summary>
        /// tooltip內容
        /// </summary>
        public string TooltipText
        {
            get { return this._Core.TooltipText; }
            set { this._Core.TooltipText = value; }
        }
        #endregion

    }
}

 

主窗口使用了該控件,聽音窗口同樣使用了該控件。

【異常規律】

  在不斷測試使用系統中發現,輸入法只有在win7下出現異常,在Xp系統下正常。且出現輸入法失敗,基本都是在打開聽音窗口后關閉窗口系統就出現輸入法異常。而關閉子窗口調用了自己封裝的Dispose()方法,及:

/// <summary>
/// 資源釋放
/// </summary>
public void Dispose()
{
    if(this._Core !=null)
    {
        this._Core.Dispose();
    }
}

去除該代碼后。關閉聽音窗口調用控件自帶Dispose()方法,異常解決。O(∩_∩)O~

  至於顯示釋放資源為什么在win7系統下就出現異常,還需去看看WebView 的Dispose()方法到底釋放了什么資源,導致輸入法出錯,也希望群里面大牛知道的告訴一下。

 


免責聲明!

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



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