http://blog.csdn.net/lllllllllluoyi/article/details/8540054web
首先向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++版的,咋辦?熬夜啃吧!chrome
我分爲了兩個項目,一是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五個文件,實現方法都在裏面,其餘的文件基本都是接口文件。我本身只根據項目實際需求來作的功能,接口沒有所有實現。這個部分你們看源代碼吧,我用到的地方都註釋了。文采不行,寫不動,你們原諒。睡了。this
最後說句,咱們公司網頁美工解脫了!lua