HRESULT CViewSource::Connect(void) { HRESULT hr; CComPtr spCP; //為Web瀏覽器事件而接收(receive)連接點 hr = m_spCPC->FindConnectionPoint(DIID_DWebBrowserEvent2, &spCP); if (FAILED(hr)) return hr; // 把事件處理器傳遞到容器。每次事件發生容器都將啟用我們實現的IDispatch介面上的相應的函數。 hr = spCP->Advise( reinterpret_cast(this), &m_dwCookie); return hr; } 通過調用介面IConnectionPoint的Advise() 方法, BHO告訴瀏覽器它對它產生的事件高度興趣。 由於COM事件處理機制,所有這些意味著BHO把IDispatch介面指標提供給瀏覽器。瀏覽器將回調IDispatch介面的Invoke() 方法,以事件的ID值作為第一參數: HRESULT CViewSource::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) { if (dispidMember == DISPID_DOCUMENTCOMPLETE) { OnDocumentComplete(); m_bDocumentCompleted = true; } : } 切記,當事件不再需要時,應該使之與瀏覽器分離。如果你忘記了做這件事情,BHO對象將被鎖定,即使在你關閉瀏覽器視窗之後。很明顯,實現分離的最佳時機是收到事件OnQuit時。 十、存取文檔對象 此時,該BHO已經有一個參照指向Internet Explorer的Web瀏覽器控制項並被串連到瀏覽器控制項以接收所有它產生的事件。當網頁被全部下載並正確初始化後,我們就可以通過DHTML文檔模型存取它。Web瀏覽器的文件屬性返回一個指向文檔對象的IDispatch介面的指標: CComPtr pDisp; HRESULT hr = m_spWebBrowser2->get_Document(&pDisp); get_Document() 方法取得的僅僅是一個介面指標。我們要進一步確定在IDispatch 指標背後存在一個HTML文檔對象。用VB實現的話,可以用下面代碼: Dim doc As Object Set doc = WebBrowser1.Document If TypeName(doc)="HTMLDocument" Then '' 擷取文檔內容並予以顯示 Else '' Disable the display dialog End If 現在要瞭解一下get_Document()返回的IDispatch指標 。Internet Explorer不僅僅是一個HTML瀏覽器,而且還是一個ActiveX文檔容器。 這樣一來,難以保證當前瀏覽對象就是一個HTML文檔。不過辦法還是有的――你想,如果IDispatch指標真正指向一個HTML文檔,查詢IHTMLDocument2 介面一定成功。 IHTMLDocument2介面封裝了DHTML物件模型用來展現HTML頁面的所有功能。下面代碼實現這些功能: CComPtr pDisp; HRESULT hr = m_spWebBrowser2->get_Document(&pDisp); CComQIPtr spHTML; spHTML = pDisp; if (spHTML) { // 擷取文檔內容並予以顯示 } else { // disable the Code Window controls } 如果IHTMLDocument2介面查詢失敗,spHTML指標將是NULL。 現在考慮如何獲得當前顯示視窗的原始碼。正如一個HTML頁把它所有的內容封裝在標籤中,DHTML物件模型要求你取得一個指向Body對象的指標: CComPtr m_pBody; hr = spHTML->get_body(&m_pBody); 奇怪的是,DHTML物件模型不讓你取得標籤之前的原始內容,如。其內容被處理並存於一些屬性中,但你還是不能從HTML原始檔案中提取這部分的RAW文本。這過,僅從BODY部分取得的內容足夠了。為了取得包含在…間的HTML代碼部分,可以把outerHTML 屬性內容讀取到一個BSTR變數中: BSTR bstrHTMLText; hr = m_pBody->get_outerHTML(&bstrHTMLText); 在此基礎上,在代碼視窗中顯示源碼就是一種簡單的事情了:產生一個視窗,進行字元的UNICODE至ANSI轉化和設定編輯框控制項的問題。下面代碼實現這些功能: HRESULT CViewSource::GetDocumentContent() { USES_CONVERSION; // 擷取 WebBrowser的文檔對象 |