在你的應(yīng)用程序中集成WebBrowser控件2007-2-17來源:網(wǎng)絡(luò) 作者:Sanda 點擊:
380次
口都派生自IDispatch,并且是應(yīng)用程序必須實現(xiàn)的事件處理器,,用于從一個對象接受事件,。要使用這些處理器對象,你需要對對象請求
IConnectionPointContainer接口,,在這些中的一個位置注冊,。只要你有了連接點容器,你就可以在對象和你的事件處理器之間建立連
接,。當(dāng)事件發(fā)生的時候,,對象將向提供的處理器發(fā)送事件。你至少要了解下列三個分發(fā)接口:
DIID_DWebBrowser事件2接口允許你監(jiān)控WebBrowser控件產(chǎn)生的事件,。一個特別重要的事件是 DISPID_NAVIGATECOMPLETE,,通知它的宿主文檔完全被WebBrowser控件建立。只要這個事件被觸 發(fā),,IWebBrowser2::get_Document方法就會返回一個指向合法的DHTML文檔的接口指針,。 有了DIID_HTMLDocument事件接口,一個應(yīng)用程序可以接收DHTML文檔對象觸發(fā)的事件,,例如onmouseover,、 onmousemove、或者onclick,。 第三個接口是DIID_HTMLWindow事件,。這個DIID_HTMLWindow事件提供的事件被DHTML對象模型中的窗口觸發(fā)。 這些事件的例子包含OnLoad,、 OnUnload,、 OnFocus和OnBlur。 其他兩個重要的接口ICustomDoc和IDocHostUIHandler允許你自定義Internet Explorer用戶界面的裝飾,,以及擴(kuò)展DHTML對象模型,。 ICustomDoc接口被HTML文檔對象實現(xiàn),,允許WebBrowser控件宿主設(shè)置它的IDocHostUIHandler接口。通常 Internet Explorer將調(diào)用宿主的Client Site的QueryInterface方法獲得IDocHostUIHandler接口,。但是,,如果宿主不支持IOleClientSite接口或者為 了保存這個指針以避免重復(fù)調(diào)用QueryInterface,,可以通過ICustomDoc顯式地設(shè)置HTML對象的IDocHostUIHandler 接口,。 IDocHostUIHandler 接口可選地被WebBrowser控件的宿主程序?qū)崿F(xiàn)。通過實現(xiàn)這個接口,,宿主程序可以替換Internet Explorer 4.0使用的菜單,、工具欄和上下文菜單。當(dāng)WebBrowser需要訪問用戶界面(比如窗口大?。?,或者當(dāng)它需要解析DHTML窗口對象的 External屬性的時候,WebBrowser控件將查詢宿主程序的IOleClientSite接口的這個接口(除非它已經(jīng)被顯式地設(shè)置),。
控件宿主也可以通過給腳本引擎提供一個代表宿主程序的外部的自動化對象來擴(kuò)展DHTML對象模型,。腳本中對這個外部對象的引用被腳本引擎解析,發(fā)動一個對
WebBrowser宿主應(yīng)用程序的IDocHostUIHandler接口的查詢,。然后腳本引擎調(diào)用這個接口的get_External方法,,宿主應(yīng)用
程序用這個調(diào)用返回一個自動化對象的分發(fā)接口。下一步,,腳本引擎將通過通常的COM自動化分發(fā)方法觸發(fā)這個對象的方法,。 (譯者注:MFC7中對CHtmlView的增強主要是把這兩個接口的實現(xiàn)改成虛函數(shù),并且修復(fù)了MFC6中CHtmlView的內(nèi)存泄漏 問題,,而且產(chǎn)生了比如Unicode支持之類的新的問題,,以及隱藏了大量細(xì)節(jié)而可能造成的誤解。雖然我很贊同這個對應(yīng)用程序的簡潔性大有好處的改進(jìn),,但是 如果把CDHtmlDialog里面大堆的DDX函數(shù)也包含在這個類里面會更好些)
在你的程序中完全實現(xiàn)Internet Explorer集成的萬里長征第一步是包含WebBrowser控件,。WebBrowser控件是一個ActiveX控件,所以你只需要讓你的應(yīng)用程序 能夠集成ActiveX組件,。關(guān)于提供ActiveX控件的容器支持的完整討論超出了本文的范圍,,但是你應(yīng)該很容易找到大量合適的文檔。在示例程序 中,,ActiveX控件容器接口的支持由MFC處理,。 (譯者注:不管你喜不喜歡MFC,它的源代碼都值得一看,。查看MFC的源代碼有助于了解細(xì)節(jié)性問題) 本文的示例實現(xiàn)了一個基于表單的應(yīng)用程序,,提供給用戶兩個屏幕。第一個表單允許用戶輸入屬性和值,,提供用戶一個 選擇,,按一個按鈕瀏覽到一個顯示前面輸入的屬性的表單,。這個報表表單有一個功能是點擊一個按鈕,返回數(shù)據(jù)輸入表單,。 輸入表單的基本功能是通過DHTML和一些內(nèi)嵌VBScript實現(xiàn)的,。應(yīng)用程序本身提供DHTML對象模型的一個擴(kuò)展,表示兩個DHTML表單,。這個擴(kuò) 展允許表單中的腳本從應(yīng)用程序中保存和獲取屬性/值的配對,。這是應(yīng)用程序中一個比較有趣的部分,因為腳本擴(kuò)展使得一個基于Web的應(yīng)用程序用這個客戶端環(huán) 境來在服務(wù)器 端保存的網(wǎng)頁之間保持狀態(tài),。 示例應(yīng)用程序演示了如何從底層DHTML文檔對象截獲事件,,跟蹤用戶和DHTML表單上的元素的交互。用戶在文檔上移動鼠標(biāo)的時候,,應(yīng)用程序截獲onmouseover和onmouseout事件來顯示當(dāng)前鼠標(biāo)下面HTML元素的的標(biāo)簽名和值,。 示例還應(yīng)用程序演示了如何截獲Internet Explorer的默認(rèn)行為來在用戶右擊表單時顯示一個自定義的上下文菜單。應(yīng)用程序捕獲了這個事件,,并且“短路”了菜單的顯示,,有效 地對用戶隱藏了Internet Explorer正被用于提供顯示的事實。 一個最后的架構(gòu)問題包含在示例的解釋中,。和Microsoft Outlook
98一樣,,本示例應(yīng)用程序顯示HTML,但是不真正從一個Web服務(wù)器獲得內(nèi)容,。實際上,,示例應(yīng)用程序(而且,我假定Outlook
98)從資源獲得它的表單,。WebBrowser控件能夠通過一個簡單的目標(biāo)URL改變,,從Win32映像文件提取資源。作為的URL的以http://
開始的替代品,,一個示例應(yīng)用程序請求的URL以res://開始,。
這通知WebBrowser控件在一個可執(zhí)行文件內(nèi)查找資源數(shù)據(jù)。示例應(yīng)用程序使用的URL格式是http://<exepath>
/<資源名>(譯者注:原文有誤,,應(yīng)為res://<exepath>/<資源名>,,更多信息可以在
Internet Development SDK中的Predefined
Protocols部分找到),這里<exepath>是應(yīng)用程序通過GetModuleFileName在初始化的時候獲得的,。HTML表
單是簡單的ASCII文件,,作為自定義資源包含在資源中。資源可以用任何方式命名,,不必和實際上的文件名字一致,。 圖10顯示了用戶輸入一些屬性/值的配對之后,,按下列表屬性按鈕的結(jié)果,。當(dāng)按鈕被按下時,主表單的腳本捕獲了按鈕的onclick事件,,并且調(diào)用window.navigate方法移動WebBrowser控件到屬性報告表單,。 屬性報告頁面由圖11所示的HTML產(chǎn)生的,。這個表單包含一個加載時執(zhí)行的內(nèi)嵌腳本,。腳本在示例中調(diào)用,并且基于用戶輸入的數(shù)據(jù),,動態(tài)產(chǎn)生一個表格,。 在這些接口上建立事件處理器遵循標(biāo)準(zhǔn)的建立連接點的COM過程。例如,,示例程序通過IHTMLDocument2 建立了一個到HTML文檔對象的連接,。圖12顯示了本示例的代碼片斷,連接事件處理器到HTML文檔對象(IHTMLDocument2),,可以處理來自 HTML文檔對象的事件,。這個代碼 在WebBrowser 組件觸發(fā)NavigateComplete事件時執(zhí)行,意味著一個新的HTML文檔對象可用,。 對com_util::establish_connection_point的調(diào)用做了建立連接點的工作,。這個函數(shù)嘗試用4個參數(shù)——一個需要連接到的 對象的接口指針、想建立的連接的類型,,實際上的處理器的指針,,以及一個用于設(shè)置表示這個連接的Cookie的地方——來建立連接。 一旦連接點被建立,,事件將從文檔對象流動到指定的處理器,。圖13顯示了html_document的處理器的Invoke方法,以及它如何映射 DISPID到C++ html_document對象的方法調(diào)用。html_document基類的所有事件處理方法最初都返回E_NOTIMPL,。你必須重載這個類的成員函 數(shù)來提供需要的功能,。 (譯者注:MFC中CHtmlView的虛函數(shù)成員基本上就是干這個的,但是有時候可能吃力不討好,,比如DownloadComplete事件的虛函數(shù)方式缺少事件的一個參數(shù),,以至于我經(jīng)常自己捕獲這個事件,而覆蓋掉CHtmlView的事件處理)
這正好就是my_document類作的事情,。my_document重載了來自于底層的DHTML文檔對象的onmouseover和
onmouseout事件,。my_document::onmouseover方法(參見圖14)最重要,因為它顯示了如何獲得顯示文檔的窗口,。它也顯示
了如何從窗口獲得描述onmouseover事件的事件對象,。從這個事件對象,可以獲得表示文檔中鼠標(biāo)移動到的真正的html_element對象,。從
html_element對象,,示例應(yīng)用程序獲得了元素的標(biāo)簽名字和ID,而且在狀態(tài)欄顯示它,。 window對象具有一個名字是exte |
|