zoukankan      html  css  js  c++  java
  • 记录一次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()方法到底释放了什么资源,导致输入法出错,也希望群里面大牛知道的告诉一下。

  • 相关阅读:
    AS3 判断双击事件
    php 数据类型转换与比较
    几行几列算法
    CCNode的属性说明
    bitmapdata的知识点
    addFrameScript用法
    TweenMax.allTo
    flash TweenMax用法
    flash流媒体资料
    c实现windows socket
  • 原文地址:https://www.cnblogs.com/ITCommunication/p/4063479.html
Copyright © 2011-2022 走看看