首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

(原创) 基于Chromium构建Chrome WebBrowser for .net 控件(再有点心得体会)

2013-01-26 
(原创) 基于Chromium构建Chrome WebBrowser for .net 控件(还有点心得体会)首先向360说句sorry,在2011年36

(原创) 基于Chromium构建Chrome WebBrowser for .net 控件(还有点心得体会)

首先向360说句sorry,在2011年360极速浏览器出现的时候我去他们论坛里骂过。为什么要到歉呢,因为2012年我把我们公司使用IE WebBrowser改为Chrome控件了,中间遇到的辛酸使我明白360公司能做成产品确实不容易。言归正转,公司的壳程序是C#编写的WinForm程序,刚开始我只找到delphi的Chromium项目,然后在delphi2010中安装好控件后就生成DLL让WinForm程序调用,这种策略是我做这个控件的最大失败。因为我对delphi比较熟,很快控件就能在WinForm程序里跑起来了,很开心,立马根据壳中已经使用的事件和方法在自定义控件中实现,自测一下没有问题后就交给测试人员来试用,半天的功夫,测试员小张就来对我说:罗兄,网页中不能使用键盘上Tab键切换,回车事件响应不了......不会吧,是不是焦点没有定位到自定义控件中,我第一时间就是这样想,然后就是反复的折腾,还是不行。最后Google了一下,好不容易找到一个让自己信服的答案,就是win32的消息循环机制与.net消息机制不一样,嵌入到WinForm中的VCL控件不能得到消息。我靠,这还得了,leader还不把我劈了,leader已经吩咐美工全按chrome浏览器的样式来写了。兵来将挡,水来土淹,我火速Google一个能在.net上跑的版本“CefSharp” ,下载来看,傻眼了,是C++版的,咋办?熬夜啃吧!

我分为了两个项目,一是libfuncs,为了使DLL名称一致,我重命名了CefSharp项目,它负责提供操作浏览器的方法和触发事件;二是cwber,它是自定义的WinForm控件,用于在Form上的布局,必须引用libfuncs.dll。

源码地址:https://sourceforge.net/projects/chromewebbrowse

cwber比较简单,以下是它的代码:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using System.Data;using System.Text;using System.Windows.Forms;using libfuncs;namespace cwber{    public partial class ChromeWebBrowser : UserControl    {        private ChromeApp chrome = null;        ToolTip myToolTip = new ToolTip();        public ChromeWebBrowser()        {            InitializeComponent();            ChromeWebBrowser.CheckForIllegalCrossThreadCalls = false;        }                      private void ChromeWebBrowser_Load(object sender, EventArgs e)        {            if (chrome == null)            {                chrome = new ChromeApp();            }            Start();                    }        #region 外部调用方法        libfuncs.DocumentCompletedEvent elementEvent1;        libfuncs.FrameLoadStartEvent elementEvent2;        libfuncs.FrameLoadEndEvent elementEvent3;        libfuncs.FileDownloadingEvent fileDownloading;        libfuncs.FileDownloadCompletedEvent fileDownloaded;        libfuncs.ComponentInitialized componentInitialized;        libfuncs.ToolTipEventListener toolTipEvent;        public void Start()        {            if (chrome != null)            {                chrome.Dock = DockStyle.Fill;                                if (componentInitialized == null)                {                    componentInitialized = new libfuncs.ComponentInitialized(componentInitializedEvent);                    chrome.RegisterEvent(componentInitialized);                }                Controls.Add(chrome);                if (elementEvent1 == null)                {                    elementEvent1 = new libfuncs.DocumentCompletedEvent(documentComplete);                    chrome.RegisterEvent(elementEvent1);                }                if (elementEvent2 == null)                {                    elementEvent2 = new libfuncs.FrameLoadStartEvent(frameStartStart);                    chrome.RegisterEvent(elementEvent2);                }                if (elementEvent3 == null)                {                    elementEvent3 = new libfuncs.FrameLoadEndEvent(frameLoadEnd);                    chrome.RegisterEvent(elementEvent3);                }                if (fileDownloading == null)                {                    fileDownloading = new libfuncs.FileDownloadingEvent(this.downloading);                    chrome.RegisterEvent(fileDownloading);                }                if (fileDownloaded == null)                {                    fileDownloaded = new libfuncs.FileDownloadCompletedEvent(this.downloaded);                    chrome.RegisterEvent(fileDownloaded);                }                if (toolTipEvent == null)                {                    toolTipEvent = new libfuncs.ToolTipEventListener(this.ShowToolTipText);                    chrome.RegisterEvent(toolTipEvent);                }                                chrome.Visible = true;                chrome.BringToFront();            }        }        /*         * 描述:释放浏览器         */        public void Free()        {            elementEvent1 = null;            elementEvent2 = null;            elementEvent3 = null;            fileDownloading = null;            fileDownloaded = null;            componentInitialized = null;            toolTipEvent = null;            chrome.Dispose();            chrome = null;        }        /*         * 参数:Url 打开网页地址         * 描述:打开网址。         */        public void OpenUrl(string Url)        {            if (chrome != null)                chrome.Load(Url);        }        /*         * 参数:id 网页中的控件元素ID         * 描述:根据元素ID获取元素的值,适用于Input,A标签元素         */        public string GetElementValueById(string id)        {            return chrome == null ? "" : chrome.GetElementValueById(id);        }        /*         * 参数:id 网页中的控件元素ID, value 元素新值         * 描述:为页面中元素赋予新值。         */        public void SetElementValueById(string id, string value)        {            if (chrome != null)            {                chrome.SetElementValueById(id, value);            }        }        public delegate void TCallBackElementEventListener();        private List<libfuncs.ElementEventListener> elementEventList = new List<libfuncs.ElementEventListener>();        /*         * 描述:附加元素的侦听事件。当该元素触发附加事件时,则执行TCallBackElementEventListener委托方法         */        public void AppendElementEventListener(string id, string eventName, TCallBackElementEventListener callFunc)        {            libfuncs.ElementEventListener elementEvent = new libfuncs.ElementEventListener(callFunc);            elementEventList.Add(elementEvent);            chrome.AddElementEventListener(id, eventName, elementEvent);        }        /*         * 描述:向页面中注入并执行脚本。         */        public void ExecuteScript(string script)        {            if (chrome != null)                chrome.ExecuteScript(script);        }        public object EvaluateScript(string script)        {            if (chrome != null)                return chrome.EvaluateScript(script);            else                return null;        }        /*         * 描述:计算文件单位。用于文件下载。         */        private string CompareFileSize(Int64 size)        {            //计算K,M单位            string strTotalSize = string.Empty;            if (size < 1024)            {                strTotalSize = size.ToString() + " B";            }            else if (size >= 1024 && size < 1024 * 1024)            {                strTotalSize = (size / 1024).ToString() + " KB";            }            else            {                strTotalSize = (size / 1024 / 1024).ToString() + " MB";            }            return strTotalSize;        }        #endregion        #region 属性        public string Url        {            get            {                return chrome == null?"":chrome.Core.Address;            }        }        #endregion        #region 事件        /*控件初始化事件*/        public event EventHandler ComponentInitializedEventHandler;        private void componentInitializedEvent()        {            EventArgs e = new EventArgs();            if (ComponentInitializedEventHandler != null)                ComponentInitializedEventHandler(this, e);        }        /*页面加载完成事件*/        public event EventHandler DocumentCompletedEventHandler;        private void documentComplete()        {            EventArgs e = new EventArgs();            if (DocumentCompletedEventHandler != null)                DocumentCompletedEventHandler(this, e);        }        /*Frame加载完成事件,这里的Frame可以是页面本身,也是iFrame元素*/        public event EventHandler PageLoadFinishEventHandler;        private void frameLoadEnd()        {            EventArgs e = new EventArgs();            if (PageLoadFinishEventHandler != null)                PageLoadFinishEventHandler(this, e);        }        /*Frame加载开始事件,这里的Frame可以是页面本身,也是iFrame元素*/        public event EventHandler PageLoadStartEventHandler;        private void frameStartStart()        {            EventArgs e = new EventArgs();            if (PageLoadStartEventHandler != null)                PageLoadStartEventHandler(this, e);        }        /*下载中事件,不开放该事件*/        Form downloadForm = null;        private void downloading(Int64 totalSize, Int64 loadedSize)        {            string strTotalSize = CompareFileSize(totalSize);            string strLoadedSize = CompareFileSize(loadedSize);            if (downloadForm == null)            {                downloadForm = new Form();                downloadForm.Text = "下载中";                downloadForm.Width = 280;                downloadForm.Height = 150;                downloadForm.MaximizeBox = false;                downloadForm.MinimizeBox = false;                downloadForm.ControlBox = false;                downloadForm.StartPosition = FormStartPosition.CenterScreen;                                Label label = new Label();                label.Left = 20;                label.Top = 50;                label.Width = 250;                label.Text = "已下载:" + strLoadedSize + "/" + strTotalSize;                downloadForm.Controls.Add(label);            }            downloadForm.Show();            downloadForm.BringToFront();            foreach (Control c in downloadForm.Controls)            {                if (c is Label)                {                    Label label = (Label)c;                    label.Text = "已下载:" + strLoadedSize + "/" + strTotalSize;                    label.Update();                }            }            downloadForm.Update();        }        /*下载完成事件,不开放该事件*/        private void downloaded()        {            if (downloadForm != null)                downloadForm.Close();            downloadForm = null;        }        /*消息提示事件,不开放*/        private void ShowToolTipText(string text)        {            if (chrome == null) return;            if (string.IsNullOrEmpty(text))            {                myToolTip.RemoveAll();                return;            }            //保证每行40个字            int len = text.Length;            int offset = 40;            int count = len / offset;            for (int i = 1; i <= count; i++)            {                text = text.Insert(offset * i, "\n");            }            myToolTip.ShowAlways = false;            myToolTip.UseAnimation = true;            myToolTip.UseFading = true;            //t.SetToolTip(button1, text);            Point p = Control.MousePosition;            Point p1 = this.PointToClient(p);            myToolTip.Show(text, chrome, p1.X+20, p1.Y+10);        }        #endregion    }}

重点是libfuncs中的libfuncs.h、ChromeApp.h、ChromeApp.cpp、ClientAdapter.h、ClientAdapter.cpp五个文件,实现方法都在里面,其他的文件基本都是接口文件。我自己只根据项目实际需求来做的功能,接口没有全部实现。这个部分大家看源代码吧,我用到的地方都注释了。文采不行,写不动,大家原谅。睡了。

最后说句,我们公司网页美工解脱了!

热点排行