自訂瀏覽器控制項

來源:互聯網
上載者:User

同自動化瀏覽器(http://blog.joycode.com/jiangsheng/archive/2005/10/20/65489.aspx)相比,自動化瀏覽器控制項(WebBrowser Control) 在應用程式中更加常用。從Outlook的預覽窗格到Maxthon這樣的基於IE引擎的瀏覽器,從無介面的HTML分析器到Norton Antivirusd的主介面,瀏覽器控制項在眾多領域被用作各種各樣的用途。這也使得有必要根據具體的使用者需求自訂瀏覽器控制項的行為。

在應用程式中加入瀏覽器控制項

整合瀏覽器控制項的最簡單的方法是找一個支援ActiveX的整合式開發環境,在工具箱中加入Microsoft Web Browser這個控制項,往表單上拖一個這個控制項就可以完成工作。你甚至可以用整合式開發環境添加ActiveX的事件處理函數。如果要直接匯入ActiveX的話,建議使用mehrcpp的vbMHWB控制項(http://www.codeproject.com/atl/vbmhwb.asp)。這個控制項在瀏覽器控制項的基礎上進行了擴充,暴露了很多底層介面。

通常匯入ActiveX就可以滿足大部分需求  ,但是有些類庫中也整合了瀏覽器控制項,並且提供了更多的功能,例如MFC的CHTMLView和CDHtmlDialog,ATL的HTML Control,以及.Net 2.0中的Windows.Forms.WebBrowser。如果使用Visual C++來進行非託管編程,那麼建議使用MFC或者ATL的封裝類,或者使用vbMHWB控制項。託管編程中當然首選Windows.Forms.WebBrowser。除非這些類的BUG影響到了應用程式的開發,否則建議使用這些功能更加強大的封裝類。

在使用瀏覽器控制項及其封裝類的時候要注意一些已知問題

  • 最後一個包含瀏覽器的視窗關閉時會話資訊可能會丟失(http://support.microsoft.com/kb/311072
  • MFC6.0版本的CHTMLView中一些方法沒有釋放獲得的BSTR字串,造成記憶體流失(http://support.microsoft.com/kb/241750)。
  • MFC6.0版本的CHTMLView缺少WS_CLIPCHILDREN風格,使得其中的瀏覽器控制項重畫不正常(http://support.microsoft.com/kb/220021
  • Windows.Forms.WebBrowser的WebBrowserSite類不能通過重載來自訂其行為(https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=115198
常見任務

在整合瀏覽器控制項之後,可以完成基本的網頁瀏覽,但是對於不同的任務,也需要進一步的處理,例如設定控制項的屬性、為控制項添加事件處理、操作HTML文檔等等。

修改瀏覽器控制項的屬性

這在整合式開發環境中可以很容易地設定,也可以自己實現容器來設定,但是CHTMLView這樣的封裝類沒有這個選項(http://support.microsoft.com/kb/197921)。

  • 連結目標解析。對於用瀏覽器控制項來做瀏覽器的場合來說,需要將瀏覽器的RegisterAsBrowser屬性設定為true。這使得Internet Explorer在解析HTML連結的target屬性指定的目標視窗時可以找到這個視窗。
  • 禁用拖放。對於使用瀏覽器控制項來做預覽窗格的場合來說,需要將瀏覽器的RegisterAsDropTarget屬性設定為false。這使得視窗不接受拖進來的檔案和連結。
  • 禁用訊息框。對於用瀏覽器控制項來做HTML分析器的場合來說,有時需要屏蔽指令碼產生的訊息框以避免阻塞程式運行。這可以通過設定瀏覽器的Silent屬性來實現,或者實現IDocHostShowUI::ShowMessage。
捕獲瀏覽器控制項的事件

整合式開發環境中可以也很容易地添加瀏覽器的事件處理函數。比較常用的事件包括

  • NewWindow2或者NewWindow3事件。預設情況下,瀏覽器控制項中建立的新視窗會是一個Internet Explorer的視窗。這通常不是預期的行為,對於瀏覽器程式來說更是這樣。需要處理瀏覽器的NewWindow2或者NewWindow3(在Windows XP SP2或者Windows 2003 SP1之後可用)事件來讓新的瀏覽器視窗在應用程式提供的視窗中運行。
  • WindowClosing事件。瀏覽器控制項需要處理WindowClosing事件來在瀏覽器控制項被指令碼關閉時關閉瀏覽器控制項的宿主視窗(http://support.microsoft.com/kb/253219)。
  • BeforeNavigate2事件。可以在自己的網頁中加入自訂的協議,之後在BeforeNavigate2事件中掃描URL來進行網頁和應用程式之間的互動(http://www.microsoft.com/msj/0100/c/c0100.aspx)。當然,自訂的網路通訊協定也可以用Asynchronous Pluggable Protocol來處理(參見http://support.microsoft.com/kb/303740),vbMHWB控制項就實現了這個功能。但是更加常用的是在彈出廣告過濾器程式中用BeforeNavigate2來判斷在NewWindow2事件中建立的視窗是否需要關閉。
操作MSHTML文檔

通常HTML分析和瀏覽器自動化程式都需要分析網頁的結構,找到需要操作的元素。這需要對網頁的結構進行分析,找到目標元素的標識方法。 一些常用的操作包括:

  • 設定HTML元素的屬性,例如html、style、value等等。注意有些屬性是唯讀,甚至是程式無法訪問的(例如input元素在類型為檔案時其value屬性不可訪問)。
  • 分析網頁的結構來儲存網頁資料,例如拆取Web 頁一文介紹的方案(http://www.microsoft.com/china/msdn/Archives/workshop/scrape.asp
  • 處理HTML元素的事件。這需要分析瀏覽器控制項中的MSHTML文檔對象,定位被操作的元素,以及在元素的連接點上掛接自訂的事件處理常式(http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/tutorials/sink.asp)。
  • 添加/刪除HTML元素。注意設定有時設定outHtml屬性並不能正確建立元素(http://support.microsoft.com/kb/185140),一個的方法是用HTMLDocument對象的CreateElememt方法。
  • 調用HTML元素的方法,這和在指令碼中操作HTML類似。可操作的元素/介面可以參考Interfaces and Scripting Objects(http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/reference/ifaces/interface.asp),操作方法可以參考Introduction to Dynamic HTML(http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/reference/ifaces/interface.asp
  • 以上的功能都可以通過直接在網頁中加入指令碼實現(http://support.microsoft.com/kb/185128),而且指令碼也可以通過應用程式實現的擴充介面來和應用程式本身互動。另外,指令碼還可以被用來自訂一些事件,例如在需要重載自訂的ShowModalDialog的時候就可以用IDispatchEx給window對象添加一個屬性,其值為一個自訂的ShowModalDialog函數(http://groups.google.com/group/microsoft.public.inetsdk.programming.webbrowser_ctl/browse_thread/thread/e5eeb4a9111b16af/4bc2709aeb2bb444?lnk=raot),也可以用加入指令碼的辦法來捕獲網頁中的錯誤(http://support.microsoft.com/kb/317024)。

 在頁麵包含架構的時候,可能需要跨架構訪問HTML文檔。可以通過查詢方塊架元素所支援的IWebBrowser2介面或者IHTMLWindow2介面來訪問架構中的文檔(http://support.microsoft.com/kb/196340),但是也有可能因為安全設定而無法訪問(http://support.microsoft.com/kb/167796)。

在瀏覽器控制項中顯示其它類型的文檔時,可以用IWebBrowser2的document屬性來訪問ActiveX文檔,例如在顯示Microsoft Word時,IWebBrowser2的document屬性就是Word的文檔對象,在顯示檔案夾的時候,IWebBrowser2的document屬性就是檔案夾對象等等。

擴充瀏覽器的宿主

瀏覽器控制項在建立時會查詢ActiveX容器的IOleClientSite的實現的如下介面:IDocHostUIHandler, IDocHostUIHandler2 and IDocHostShowUI

雖然在無法自訂ActiveX容器的情況下可以用ICustomDoc::SetUIHandler來掛接IDocHostUIHandler到瀏覽器控制項,但是這樣也會造成記憶體流失(http://support.microsoft.com/kb/893629)。一些類庫,例如MFC、ATL和.Net類庫都實現了IDocHostUIHandler介面。

除了專門用於瀏覽器用途的程式之外,通常都需要自訂瀏覽器控制項的操作功能表。這需要實現IDocHostUIHandler::ShowContextMenu。通常的實現包括完全禁用操作功能表、完全替換操作功能表、以及修改部分操作功能表。經常被從操作功能表中移除的功能表項目包含查看原始碼、重新整理和屬性。一種替代的方案是在容器中過濾右鍵訊息(http://support.microsoft.com/kb/231578)。

與瀏覽器相比,一些Internet Explorer的宿主功能在瀏覽器控制項中並不是預設啟用。在某些場合,預設啟用的宿主功能可能並非預期。這時需要實現IDocHostUIHandler::GetHostInfo。可以通過實現IDocHostUIHandler::GetHostInfo來自訂的功能包括:

  • 自動完成功能。對於用瀏覽器控制項來做瀏覽器的場合來說,這個功能是有必要啟用的。啟用的方法是設定DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE位
  • 如果瀏覽器中的連結網址包含非ASCII的字元,那麼需要實現IDocHostUIHandler::GetHostInfo,並且在返回的DOCHOSTUIINFO結構中設定dwFlags成員的DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8位。這使得網址會在發送之前用UTF-8編碼。
  • 3D邊框、捲軸,禁用文字選擇功能和禁用頁面上的指令碼。
  • 對於使用瀏覽器控制項來做HTML編輯器的場合來說,有時需要修改預設的頁面樣式。這都需要實現IDocHostUIHandler::GetHostInfo(http://support.microsoft.com/kb/328803)。注意在有些版本的IE中IDocHostUIHandler::GetHostInfo只在MSHTML被初始化的時候被調用,所以如果你需要在MSHTML被初始化之後使你的修改生效,你需要瀏覽到一個Word之類的非HTML Active document文檔,之後再瀏覽回來。

在使用瀏覽器控制項來做資料錄入介面的場合,需要更改瀏覽器控制項預設的Tab鍵處理使得使用者可以使用Tab鍵切換到容器中的其他控制項。這需要實現IDocHostUIHandler::TranslateAccelerator來自訂瀏覽器控制項的快速鍵處理。對於MFC這樣用訊息鉤子來做訊息預先處理的可自訂容器來說,也可以用PreTranslateMessage來過濾F5鍵盤訊息,而不是實現IDocHostUIHandler::TranslateAccelerator。

在指令碼中調用應用程式對瀏覽器控制項的擴充,這需要實現IDocHostUIHandler::GetExternal。使用.Net的WebBrowser控制項的話設定ObjectForScripting屬性就可以了。

對於用瀏覽器控制項來做HTML分析器的場合來說,有時需要屏蔽指令碼產生的訊息框。這需要實現IDocHostShowUI::ShowMessage,或者設定瀏覽器的Silent屬性。

另外,瀏覽器也會查詢IOleClientSite來獲得其它的服務資訊,例如

  • IOleCommandTarget,查詢控制項的容器是否提供替代的命令處理,見拙作Hook DHTML Commands一文(http://blog.joycode.com/jiangsheng/archive/2005/07/09/58754.aspx
  • IServiceProvider。此介面被用於查詢使用者對如下介面的實現:
    • IInternetSecurityManager ,使用者可實現此介面來自訂瀏覽器控制項的安全相關選項(http://msdn.microsoft.com/workshop/security/szone/overview/impl_secmanager.asp
    • IDownloadMamanger ,使用者可實現此介面來自訂瀏覽器控制項的下載過程
    • IAuthenticate,使用者可實現此介面來自訂一些登入介面(http://support.microsoft.com/kb/329802
    • INewWindowManager,使用者可實現此介面來重載Windows XP SP2和Windows 2003 SP1中新增的快顯視窗管理器的行為
其他控制

對於用瀏覽器控制項來做HTML分析器的場合來說,有時需要禁用瀏覽器的指令碼、ActiveX或者圖片下載。這可以通過在容器中實現IDispatch,處理DISPID_AMBIENT_DLCONTROL來做到(http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/overview/Overview.asp)。

看來離線瀏覽的控制並不能用這種方法來控制(http://support.microsoft.com/kb/247336)。不過你可以自己編寫一個HTTP層傳遞 BINDF_OFFLINEOPERATION標誌 (http://groups-beta.google.com/group/microsoft.public.inetsdk.programming.mshtml_hosting/msg/76bf4910a289d4b3

在瀏覽器控制項中java小程式可能不能正常運行,如果使用Sun JVM1.4之後的版本,可以用SetEnvironmentVariable 來設定JAVA_PLUGIN_WEBCONTROL_ENABLE為1來啟用Sun JVM。

預設情況下在頁面載入時會有點擊聲。屏蔽點擊聲的一個方法是在程式運行時修改註冊表鍵(http://support.microsoft.com/kb/201901),另一個方法是將瀏覽器控制項隱藏,在調用Navigate2之後再顯示,但是這也需要鎖定控制項的更新地區(LockWindowUpdate)以避免閃爍。在IE7中,也可以調用 CoInternetSetFeatureEnabled函數,傳遞FEATURE_DISABLE_NAVIGATION_SOUNDS來禁用瀏覽時的聲音。

在需要使用Proxy 伺服器時,有可能需要在應用程式中使用非預設的Proxy 伺服器設定。這可以通過調用UrlMkSetSessionOption來實現。

Overriding IInternetSecurityManager in a CComControl class
CAxWindow implements IObjectWithSite interface (get it with QueryHost
method). Call SetSite passing your implementation of IServiceProvider.
At this point, AxWin will forward all QueryService calls from hosted
WebBrowser to your implementation.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.