• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            如何對webbrowser和IE編程(十)

            Internet Explorer 5激發(fā)事件

            如你所知, Internet Explorer像其他COM對象一樣激發(fā)事件—通過連接點(diǎn).但實(shí)際上Internet Explorer如何激發(fā)事件呢?每次 Internet Explorer需要向客戶提供關(guān)于當(dāng)前活動狀態(tài)的信息, Internet Explorer 激發(fā)通過DWebBrowserEvents2 連接點(diǎn)激發(fā)一個事件. (之前到版本 4, Internet Explorer 通過 DWebBrowserEvents 接口激發(fā)事件.但到了版本4.x和5, Internet Explorer 通過 DWebBrowserEvents2 連接點(diǎn).)

            注意


            如何領(lǐng)會到 Internet Explorer 加法那些事件 ? 最佳途徑是 MSDN Online Web Workshop. 另外采用 OLE-COM Object Viewer

            不像WebBrowser 控件 和 Internet Explorer的其他接口,是劍接口沒有繼承體系. DWebBrowserEvents 接口嚴(yán)格應(yīng)用于Internet Explorer 3. 如果你正宿主WebBrowser 控件或者自動化Internet Explorer 5, 你可以通過此接口接收事件—但是不可掛接. DWebBrowserEvents2 接口包含的方法是為Internet Explorer 5定制的.用 DWebBrowserEvents2 替代DWebBrowserEvents ,你將有更多的控制能力. 所以不要忘記接口的最后面的2.

            盡管DWebBrowserEvents2 是一個事件接口, 它其實(shí)就是像IWebBrowser2? 一樣的另外 COM 接口,所以它可以包含方法. (D 開頭的命名是表示這是派遣接口.一個派遣接口是一個IDispatch 接口.但不同于普通接口, 派遣接口沒有vtable.) 就像一個接口一樣,派遣接口只不過提供一些函數(shù)的定義—他們并不真實(shí)實(shí)現(xiàn).事件的實(shí)現(xiàn)由客戶提供.舉例來說,為了讓W(xué)ebBrowser 激發(fā)一個事件, 在DWebBrowserEvents2 接口中適當(dāng)定義一些方法.這些方法由客戶實(shí)現(xiàn).但WebBrowser不直接調(diào)用這些方法.換句話講, WebBrowser 并不調(diào)用DocumentComplete 方法.因?yàn)?DWebBrowserEvents2 是派遣接口, WebBrowser 通過IDispatch::Invoke調(diào)用客戶的實(shí)現(xiàn). 早期, 當(dāng)WebBrowser 調(diào)用客戶的Invoke 實(shí)現(xiàn), WebBrowser 傳遞事件被激發(fā)的DISPID.

            注意


            某些工具如 Visual Basic, MFC, ATL 提供 Invoke 實(shí)現(xiàn)

            7-6 列出 WebBrowser 事件. (這些是WebBrowser 控件和Internet Explorer供有的事件,盡管有些事件僅僅用于自動化Internet Explorer).

            注意


            盡管有些方法為不包含 2 . 盡管 DWebBrowserEvents2 并非繼承自 WebBrowserEvents , DWebBrowserEvents2 還是 匹配 DWebBrowserEvents 中被更改的,以免混淆。

            注意表 7-6 重的參數(shù)有些值同樣有 VARIANT_ TRUE VARIANT_FALSE. 如果你使用Visual C++,確信分派使用這些值不要使用 TRUE FALSE. 如果你使用Visual Basic, 它會自動幫助你轉(zhuǎn)換,你可以比較True和False.

            現(xiàn)在來仔細(xì)看看這些事件

            Table 7-6 WebBrowser 事件

            私有事件

            描述

            BeforeNavigate2

            在導(dǎo)航之前發(fā)生 . ( 該事件并不在不刷新頁面的時候發(fā)生 )

            CommandStateChange

            當(dāng)命令狀態(tài)改變時發(fā)生 . 該事件告訴你何時使能或者禁止 Back 以及 Forward 菜單像或者按鈕 .

            DocumentComplete

            當(dāng)整個文檔完全完成裝載時發(fā)生 . 如果你刷新頁面 , 此事件并不激發(fā) .

            DownloadBegin

            當(dāng)一個下載項目開始時候發(fā)生 ,此事件也在你刷新( IWebBrowser2::Refresh. )時發(fā)生

            DownloadComplete

            黨整個下載項目完成是發(fā)生該事件也發(fā)生在完成刷新頁面 .

            NavigateComplete2

            當(dāng)整個導(dǎo)航完成 . 該事件對應(yīng)于 BeforeNavigate2 .

            NewWindow2

            在一個新的窗口被創(chuàng)建以顯示 Web 頁或者其他資源的時候發(fā)生。譬如你在頁面中以新建窗口的方式打開一個連接

            OnFullScreen

            當(dāng) FullScreen 屬性被改變時候發(fā)生 . 此事件攜帶一個 VARIANT_ BOOL 類型的 輸入?yún)?shù)指示 Internet Explorer 是否處于全屏( full-screen 模式 (VARIANT_TRUE) 或者處于普通模式 (VARIANT_FALSE).

            OnMenuBar

            菜單條 MenuBar 屬性被改變的時候發(fā)生 . 一個 VARIANT_ BOOL 類型輸入?yún)?shù)指 ?Internet Explorer 的菜單條屬性是可見 (VARIANT_TRUE) 或者隱藏 (VARIANT_ FALSE).

            OnQuit

            當(dāng) Internet Explorer 正在退出時發(fā)生 . 該事件當(dāng)用戶關(guān)閉瀏覽器或者調(diào)用 Quit 方法 .

            OnStatusBar

            當(dāng) StatusBar 屬性被改變的時候發(fā)生。事件攜帶 VARIANT_ BOOL 類型的輸入?yún)?shù) 指示 Internet Explorer 的狀態(tài)條是否可見 (VARIANT_TRUE) 或者隱藏 (VARIANT_FALSE).

            OnTheaterMode

            當(dāng) TheaterMode 屬性被改變時發(fā)生 . 事件攜帶 VARIANT_ BOOL 類型的輸入?yún)?shù) 指示 Internet Explorer 的狀態(tài)條是否可見 (VARIANT_TRUE) 或者隱藏 (VARIANT_FALSE).

            OnToolBar

            當(dāng) ToolBar 屬性被改變時發(fā)生 . 事件攜帶 VARIANT_ BOOL 類型的輸入?yún)?shù) 指示 Internet Explorer 的狀態(tài)條是否可見 (VARIANT_TRUE) 或者隱藏 (VARIANT_FALSE).

            OnVisible

            當(dāng) WebBrowser 將被顯示或者隱藏時發(fā)生。 . 事件攜帶 VARIANT_ BOOL 類型的輸入?yún)?shù) 指示 Internet Explorer 的狀態(tài)條是否可見 (VARIANT_TRUE) 或者隱藏 (VARIANT_FALSE).

            ProgressChange

            當(dāng)下載進(jìn)度被更新時候發(fā)生

            PropertyChange

            當(dāng)屬性改變時候發(fā)生。典型的 , 當(dāng) PutProperty 方法被調(diào)用時

            StatusTextChange

            Internet Explorer WebBrowser 控件改變狀態(tài)條時候發(fā)生。即使 webbrowser 控件沒有狀態(tài)條。 StatusTextChange 給客戶一個改變狀態(tài)條的機(jī)會

            TitleChange

            . 當(dāng)文檔對象的 title 可用或者改變的時候發(fā)生

            BeforeNavigate2

            BeforeNavigate2 就像字面上所說. 當(dāng)Internet Explorer 導(dǎo)航到一個WEB頁是激發(fā); 因此, 當(dāng)用戶輸入一個 URL, 點(diǎn)擊 Back 或者 Forward 按鈕, 或者處理一個導(dǎo)航時都會發(fā)生. BeforeNavigate2 ?也在WebBrowser 控件導(dǎo)航類方法調(diào)用時發(fā)生, 例如 Navigate, Navigate2, GoHome, 或者 GoSearch. 也許, 該事件不會在你刷新頁面時發(fā)生. 如果頁面上有幀, BeforeNavigate2 將像頂級窗口一樣被激發(fā). BeforeNavigate2 由7個輸入?yún)?shù), 見7-7.

            Table 7-7 Input Parameters of the BeforeNavigate2 Event

            Parameter

            Description

            pDisp

            將發(fā)生導(dǎo)航的頂級窗口或者幀的 Idispatch 接口的地址

            URL

            將導(dǎo)航至的 URL

            Flags

            保留

            TargetFrameName

            顯示資源的窗口或者幀的名字字符串,或者為 NULL (如果沒有命名)

            PostData

            HTTP POST 傳輸?shù)臄?shù)據(jù)地址

            Headers

            增加的將要發(fā)給服務(wù)器的 HTTP . 一般 HTTP 頭指定其它的服務(wù)器要求。傳送給服務(wù)器的數(shù)據(jù)類型、狀態(tài)馬等

            Cancel

            cancel 標(biāo)志的地址 . 設(shè)置為 TRUE 可取消導(dǎo)航

            注意打所屬參數(shù)匹配于Navigate 或者 Navigate2的調(diào)用參數(shù).如果 BeforeNavigate2 由一個或者多個導(dǎo)航類調(diào)用激發(fā),這些導(dǎo)航類的方法參數(shù) 傳遞到BeforeNavigate2 方法.

            在事件的句柄函數(shù)中, 你可以使用Cancel 參數(shù)取消導(dǎo)航, 或者你可以是用pDisp 參數(shù)修改導(dǎo)航目的.設(shè)置Cancel 參數(shù)為 VARIANT_TRUE 可以取消導(dǎo)航,如果你想,你可以通過pDisp修改參數(shù)導(dǎo)航信息且導(dǎo)航到另外的位置.舉例來說,如果我們向停止當(dāng)前導(dǎo)航, 增加一些頭信息,且導(dǎo)航到原先的URL.在Visual Basic, 我們可以如下代碼實(shí)現(xiàn):

            												
            														Private Sub WebBrowser1_BeforeNavigate2(ByVal pDisp As Object, _
            												
            										
            												
            														
            																
            																		??????????????????????????????????????? URL As Variant, _
            														
            												
            										
            												
            														
            																
            																		??????????????????????????????????????? Flags As Variant, _
            														
            												
            										
            												
            														
            																
            																		??????????????????????????????????????? TargetFrameName As Variant, _
            														
            												
            										
            												
            														
            																
            																		??????????????????????????????????????? PostData As Variant, _
            														
            												
            										
            												
            														
            																
            																		??????????????????????????????????????? Headers As Variant, _
            														
            												
            										
            												
            														
            																
            																		??????????????????????????????????????? Cancel As Boolean)
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? If TypeName(pDisp) = "WebBrowser" And Headers = "" Then
            														
            												
            										
            												
            														
            																
            																		????? pDisp.Stop
            														
            												
            										
            												
            														
            																
            																		????? pDisp.Navigate URL, Flags, TargetFrameName, PostData, _
            														
            												
            										
            												
            														
            																
            																		???????????????????? Headers + "MyHeaders"
            														
            												
            										
            												
            														
            																
            																		????? Cancel = True
            														
            												
            										
            												
            														
            																
            																		?? End If
            														
            												
            										
            												
            														End Sub
            												
            										

            我們需要注意以上代碼的幾個重點(diǎn).

            首先你必須檢查pDisp 的類型使之確定為WebBrowser. 當(dāng)頁面包含幀, pDisp 可能不是 WebBrowser 對象由此一些導(dǎo)航會導(dǎo)致錯誤.

            其次你必須檢查確信Headers 參數(shù)是空字符串以避免無限循環(huán).記住BeforeNavigate2 每一次導(dǎo)航都會發(fā)生.因此如果你在BeforeNavigate2事件處理中調(diào)用Navigate, 另外一次 BeforeNavigate2 將被激活. 在前面的代碼中, 僅僅在Headers 參數(shù)為空才調(diào)用Navigate 避免了無限循環(huán). 如果Headers 參數(shù)是空, Navigate 將攜帶非空的 Headers 參數(shù). 下一次BeforeNavigate2 北激活, Headers 將不為空; 此時,我們千萬不可再次Navigate a,從而導(dǎo)致一個無限循環(huán).

            第三點(diǎn)你必須調(diào)用pDisp Stop 方法.如果你沒做到這點(diǎn),"about:NavigationCanceled" Web 頁將會載你首次取消掉導(dǎo)航時被顯示.

            CommandStateChange

            CommandStateChange 是當(dāng)Internet Explorer 想通知一個應(yīng)用程序WebBrowser 命令狀態(tài)已經(jīng)改變時激發(fā).當(dāng)檢測到Forward和Back 菜單項和按鈕禁止或者使能時激發(fā)此事件.

            CommandStateChange 事件有2個參數(shù), CommandEnable。Command 輸入?yún)?shù)將要改變狀態(tài)的按鈕的表示符,可以取值—CSC_NAVIGATEFORWARDCSC_NAVIGATEBACK分別表示是Forward按鈕項和Back項,每次導(dǎo)航發(fā)生, CommandStateChange 事件發(fā)生并告訴你Forward 或者 Back 菜單項以及按鈕將使能或禁止. 舉例來說, 如果沒有Web頁在當(dāng)前導(dǎo)航后發(fā)生, Command 的值應(yīng)該為 CSC_NAVIGATEFORWARD, 并且Enable 參數(shù)將等于VARIANT_FALSE.

            第二個參數(shù), Enable,如果命令可用(使能) 則為VARIANT_TRUE,如果禁止則值為VARIANT_FALSE.

            為說明問題,我們看看代碼。一下代碼為定義事件接收的宏聲明:

            												
            														
            																?

            												
            														// Event sink map declaration for WebBrowser 
            												
            										
            												
            														// control events. This declaration goes in the
            												
            										
            												
            														// header file for CMfcWebHostView _ MfcWebHostView.h.
            												
            										
            												
            														//
            												
            										
            												
            														DECLARE_EVENTSINK_MAP()
            												
            										
            												
            														
            																?

            												
            														// Initialize the event sink map and handle the 
            												
            										
            												
            														// CommandStateChange event.
            												
            										
            												
            														BEGIN_EVENTSINK_MAP(CMfcWebHostView, CView)
            												
            										
            												
            														
            																
            																		?? ON_EVENT(CMFCIEEvtSpyDlg, IDC_WEBBROWSER, DISPID_COMMANDSTATECHANGE,
            														
            												
            										
            												
            														
            																
            																		??????????? OnCommandStateChange, VTS_I4 VTS_BOOL)
            														
            												
            										
            												
            														END_EVENTSINK_MAP()
            												
            										

            重要的一點(diǎn)是要通過WebBrowser控件的Create 方法來創(chuàng)建. ON_EVENT的第二個參數(shù)為你宿主的WebBrowser控件的IID.之前的例子中是NULL. 你必須為webbrowser控件聲明一個ID 且用此 ID 創(chuàng)建實(shí)例.如果不這么做,事件將不會正確工作.

            你可以在工程的任何文件定義此ID. (推薦在資源頭文件resource.h.) 因?yàn)?最大的資源Id是32,779, 所以你可以如下定義WebBrowser 控件的ID:

            												
            														#define IDC_WEBBROWSER? 35000
            												
            										

            此數(shù)高于resource.h中的任何資源ID, 因此可以確信ID 數(shù)字不會同采用ClassWizard添加的ID沖突.現(xiàn)在可以采用使用ID的 Create 方法來創(chuàng)建WebBrowser控件:

            												
            														if (!m_webBrowser.Create(NULL, WS_CHILD|WS_VISIBLE,
            												
            										
            												
            														
            																
            																		???????????????????????? CRect(), this, IDC_WEBBROWSER))
            														
            												
            										
            												
            														{
            												
            										
            												
            														
            																
            																		?? return -1;
            														
            												
            										
            												
            														}
            												
            										

            下一步聲明OnCommandStateChange 方法,該方法將在WebBrowser控件激發(fā)CommandStateChange 事件時被調(diào)用.可聲明 如下:

            												
            														void OnCommandStateChange(long lCommand, BOOL bEnable);
            												
            										

            OnCommandStateChange 方法的是現(xiàn)代碼中, 設(shè)定表示Go Forward 或者 Go Back 想得導(dǎo)航菜單項的數(shù)據(jù)成員為使能或者禁止. 該書據(jù)成員將被UPDATE_COMMAND_UI 句柄使用。以下為OnCommandStateChange 方法實(shí)現(xiàn):

            												
            														void CMfcWebHostView::OnCommandStateChange(long lCommand, BOOL bEnable)
            												
            										
            												
            														{
            												
            										
            												
            														
            																
            																		?? switch(lCommand)
            														
            												
            										
            												
            														
            																
            																		?? {
            														
            												
            										
            												
            														
            																
            																		????? // Forward command
            														
            												
            										
            												
            														
            																
            																		????? //
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? case CSC_NAVIGATEFORWARD:
            														
            												
            										
            												
            														
            																
            																		???????? m_fForwardEnabled = bEnable;
            														
            												
            										
            												
            														
            																
            																		???????? break;
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? // Back command
            														
            												
            										
            												
            														
            																
            																		????? //
            														
            												
            										
            												
            														
            																
            																		????? case CSC_NAVIGATEBACK:
            														
            												
            										
            												
            														
            																
            																		???????? m_fBackEnabled = bEnable;
            														
            												
            										
            												
            														
            																
            																		???????? break;
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? default:
            														
            												
            										
            												
            														
            																
            																		???????? break;
            														
            												
            										
            												
            														
            																
            																		?? }
            														
            												
            										
            												
            														}
            												
            										

            聲明m_fForwardEnabledm_fBackEnabled 數(shù)據(jù)變量為保護(hù)成員,類型為BOOL.同樣在構(gòu)造函數(shù)中誰的些數(shù)據(jù)成員為TRUE。.

            現(xiàn)在當(dāng)Go Forward和Go Back的菜單 UPDATE_COMMAND_UI被處理, 你可以直接進(jìn)行設(shè)置. 下為示例代碼:

            												
            														void CMfcWebHostView::OnUpdateNavigateGoForward(CCmdUI* pCmdUI) 
            												
            										
            												
            														{
            												
            										
            												
            														
            																
            																		?? pCmdUI->Enable(m_fForwardEnabled);
            														
            												
            										
            												
            														}
            												
            										
            												
            														
            																?

            												
            														void CMfcWebHostView::OnUpdateNavigateGoBack(CCmdUI* pCmdUI) 
            												
            										
            												
            														{
            												
            										
            												
            														
            																
            																		?? pCmdUI->Enable(m_fBackEnabled);
            														
            												
            										
            												
            														}
            												
            										

            DocumentComplete

            當(dāng)一個文檔完整的完成下載Internet Explorer 激發(fā)DocumentComplete 事件. 僅僅當(dāng)此事件激發(fā)后 文檔對象才可安全使用.在一個無幀的Web頁情形中文檔對象是IHTMLDocument2 對象, 我們以后會討論. 當(dāng)文檔對象準(zhǔn)備好可用,他的狀態(tài)為READYSTATE_COMPLETE.

            關(guān)于 DocumentComplete 事件以西擊點(diǎn)需要注意:

            ·???????? 在沒有幀的web頁, DocumentComplete 事件在下載完成后激發(fā)一次.

            • 在多幀的 web 頁,此事件激發(fā)多次 . 并非每一個幀激發(fā)一個事件 , 但每一個幀激發(fā) DownloadBegin 事件將會相應(yīng)激發(fā) DocumentComplete 事件 .
            • DocumentComplete 又一個指向 IDispatch 的指針參數(shù) , 該參數(shù)指向激發(fā)此事件的窗口 . 此窗口可以是幀中的窗口
            • 頂級幀在所有子幀激發(fā)了各自的 DocumentComplete 事件后激發(fā)自己的 DocumentComplete 事件。 因此 , ,要看一個 web 頁是否完整下載完成 , 你需要從該事件的處理句柄中獲取由事件產(chǎn)地過來的 IDispatch 參數(shù)的 IUnknown 接口。下一步,比較 IUnknown 接口是否指向你正宿主的 WebBrowser 控件或者自動化的 IE 的實(shí)例的 IUnknown 接口 . 如果這兩個指針相同,這意味著全部 HTML, 圖片 images, 控件 , 以及諸如此類在頂級幀或者子幀的全部對象元素都被下載了 .

            ?

            VB中實(shí)現(xiàn)以上四點(diǎn)及其容易.僅需要檢查發(fā)送給事件的pDisp 參數(shù)事一個WebBrowser 對象. Visual Basic小心檢查這些對象的 Iunknown否為同一個對象.此處為VB代碼::

            												
            														Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object,
            												
            										
            												
            														
            																
            																		???????????????????????????????????????? URL As Variant)
            														
            												
            										
            												
            														
            																
            																		?? If (pDisp Is WebBrowser1.Object) Then
            														
            												
            										
            												
            														
            																
            																		????? MsgBox "The document is finished loading."
            														
            												
            										
            												
            														
            																
            																		?? End If
            														
            												
            										
            												
            														End Sub
            												
            										

            實(shí)現(xiàn)以上四點(diǎn)在Visual C++ 應(yīng)用程序里較困難一點(diǎn),但你可以做到! 首先在DocumentComplete 事件的宏中如下聲明:

            												
            														ON_EVENT(CMfcWebHostView, IDC_WEBBROWSER, DISPID_DOCUMENTCOMPLETE,
            												
            										
            												
            														
            																
            																		???????? OnDocumentComplete, VTS_DISPATCH VTS_PVARIANT)
            														
            												
            										

            接下來聲明OnDocumentComplete 方法作為事件處理句柄

            												
            														void OnDocumentComplete(LPDISPATCH lpDispatch, VARIANT FAR* URL);
            												
            										

            最后,實(shí)現(xiàn)該方法以檢測 是否頁面已經(jīng)下載,我們得到我們宿主控制bBrowser 控件的IUnknown. (注意我們不是簡單獲取指向 IUnknown ,而是要調(diào)用GetControlUnknown 方法. GetControlUnknown方法返回的IUnknown 指針 實(shí)際上并不等于被宿主話的 WebBrowser控件的IUnknown. 那將返回IOleObject 接口指針.) 下一步, 獲取IUnknown 指針,如果QueryInterface 查詢得到的Dispatch 參數(shù)同Iunknown接口是同一對象,則頁面完成整個下載。.

            												
            														void CMfcWebHostView::OnDocumentComplete(LPDISPATCH lpDispatch,
            												
            										
            												
            														
            																
            																		???????????????????????????????????????? VARIANT FAR* URL)
            														
            												
            										
            												
            														{
            												
            										
            												
            														
            																
            																		?? HRESULT?? hr;
            														
            												
            										
            												
            														
            																
            																		?? LPUNKNOWN lpUnknown;
            														
            												
            										
            												
            														
            																
            																		?? LPUNKNOWN lpUnknownWB = NULL;
            														
            												
            										
            												
            														
            																
            																		?? LPUNKNOWN lpUnknownDC = NULL;
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? lpUnknown = m_webBrowser.GetControlUnknown();
            														
            												
            										
            												
            														
            																
            																		?? ASSERT(lpUnknown);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? if (lpUnknown)
            														
            												
            										
            												
            														
            																
            																		?? {
            														
            												
            										
            												
            														
            																
            																		????? // Get the pointer to the IUnknown interface of the WebBrowser 
            														
            												
            										
            												
            														
            																
            																		??????// control being hosted. The pointer to the IUnknown returned from 
            														
            												
            										
            												
            														
            																
            																		??????// GetControlUnknown is not the pointer to the IUnknown of the 
            														
            												
            										
            												
            														
            																
            																		??????// WebBrowser control. It's actually a pointer to the IOleObject.
            														
            												
            										
            												
            														
            																
            																		????? // 
            														
            												
            										
            												
            														
            																
            																		??????hr = lpUnknown->QueryInterface(IID_IUnknown,
            														
            												
            										
            												
            														
            																
            																		???????????????????????????????????? (LPVOID*)&lpUnknownWB);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? ASSERT(SUCCEEDED(hr));
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? if (FAILED(hr))
            														
            												
            										
            												
            														
            																
            																		???????? return;
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? // Get the pointer to the IUnknown of the object that fired this 
            														
            												
            										
            												
            														
            																
            																		??????// event.
            														
            												
            										
            												
            														
            																
            																		????? //
            														
            												
            										
            												
            														
            																
            																		??? 
            																		??hr = lpDispatch->QueryInterface(IID_IUnknown, 
            														
            												
            										
            												
            														
            																
            																		??????????????????????????????????????(LPVOID*)&lpUnknownDC);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? ASSERT(SUCCEEDED(hr));
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? if (SUCCEEDED(hr) && lpUnknownWB == lpUnknownDC)
            														
            												
            										
            												
            														
            																
            																		????? {
            														
            												
            										
            												
            														
            																
            																		???????? // The document has finished loading.
            														
            												
            										
            												
            														
            																
            																		??? 
            																		?????//
            														
            												
            										
            												
            														
            																
            																		???????? MessageBox("The document has finished loading.");
            														
            												
            										
            												
            														
            																
            																		????? }
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? if (lpUnknownWB)
            														
            												
            										
            												
            														
            																
            																		???????? lpUnknownWB->Release();
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		????? if (lpUnknownDC)
            														
            												
            										
            												
            														
            																
            																		???????? lpUnknownDC->Release();
            														
            												
            										
            												
            														
            																
            																		?? }
            														
            												
            										
            												
            														}
            												
            										

            有一點(diǎn)需要注意上面的代碼我們在GetControlUnknown 返回的IUnknown 接口指針使用時并沒有進(jìn)行Release ,因?yàn)閎 IUnknown 指針并沒有在GetControlUnknown方法中AddRef'. GetControlUnknown 方法僅僅返回一個IOleObject 數(shù)據(jù)成員的指針,該指針由控件站點(diǎn)類—CcontrolSite 操縱處理. 如果你釋放了IUnknown 接口指針, 載你關(guān)閉應(yīng)用程序時,一個訪問違例將會發(fā)生,因?yàn)镸FC 將試圖在對象被刪除時候多釋放一次.

            DownloadBegin

            DownloadBegin 事件通知應(yīng)用程序一個導(dǎo)航操作開始. 一般情況下該事件在BeforeNavigate2 事件之后激發(fā), 除非導(dǎo)航操作在BeforeNavigate2 事件處理過程中被取消.容器應(yīng)當(dāng)顯示動畫或者忙指示當(dāng)前正處于連接的DownloadBegin事件. 每一個 DownloadBegin 事件有一個相應(yīng)的DownloadComplete 事件. 在刷新頁面的情形中, DownloadBegin DownloadComplete 使唯一的被激發(fā)的導(dǎo)航事件.

            DownloadComplete

            DownloadComplete 在一個導(dǎo)航操作完成時候發(fā)生, 停止, 或者失敗. 不像 NavigateComplete2僅僅當(dāng)成功導(dǎo)航才發(fā)生, DownloadComplete總是在道涵開始后激發(fā).任何在DownloadBegin 中顯示的動畫或者忙指示將會在DownloadComplete 中停止.

            NavigateComplete2

            NavigateComplete2 事件在導(dǎo)航到一個超連接整個窗口或者幀集合的元素全部完成時候發(fā)生. 第一此事件發(fā)生表示文檔document已經(jīng)準(zhǔn)備好.在此事件發(fā)生后, 你可以通過Document 屬性存取文檔(document)而不接收到錯誤.但是能夠訪問一個文檔不意味著你訪問文檔使安全的.你可以在DocumentComplete 事件激發(fā)后安全訪問文檔.

            檔你需要訪問document對象但是不需要訪問文檔內(nèi)的元素,你可以在NavigateComplete2 事件中盡可能快的處理,例如當(dāng)你在文打工通過高級宿主接口. NavigateComplete2 事件有2個參數(shù)—IDispatch of 代表激發(fā)事件的對象URL 為你需要導(dǎo)航到的URL.

            NewWindow2

            NewWindow2 檔用戶顯示一個新窗口以進(jìn)行新導(dǎo)航顯示web頁或者其他資源時發(fā)生.在WebBrowser控件響應(yīng)柄進(jìn)行預(yù)處理 (舉例來說, 在響應(yīng)window.open 方法).

            NewWindow2 也在Navigate 或者 Navigate2 方法被調(diào)用且navOpenInNewWindow 標(biāo)志被設(shè)定時發(fā)生. 檔采用文件菜單中的New Window按鈕時并不發(fā)生(Internet Explorer幀不是一個 HTML 幀; 它是幀窗口.) 因此, WebBrowser 對象不知道什么時候新窗口將被打開. 因?yàn)?NewWindow2 有時候很難使用, 所以我們來檢查它的兩個參數(shù): ppDisp and Cancel.

            ppDisp 參數(shù)是接口指針, 一般是接收新WebBrowser 或者 InternetExplorer 對象的IDispatch 接口指針, 是你能夠創(chuàng)建一個Internet Explorer新實(shí)例以便能夠控制來自你的應(yīng)用程序?qū)Ш疆a(chǎn)生的新窗口. 該實(shí)例開始為新建的, 隱藏的, (暫時)不可導(dǎo)航WebBrowser 或者 InternetExplorer 對象. 在NewWindow2事件句柄函數(shù)返回之前, InternetExplorer 對象激發(fā)NewWindow2 事件將配置新WebBrowser對象的導(dǎo)航目標(biāo)位置.

            另外參數(shù), Cancel, 時取消(Cancel)標(biāo)志的地址. 應(yīng)用程序能夠設(shè)定此參數(shù)為TRUE 以取消導(dǎo)航操作或者設(shè)定為FALSE 以允許新建窗口操作. 設(shè)定CancelTRUE 完全取消新建窗口操作和導(dǎo)航.

            如果你不在NewWindow2 事件處理過程中作任何事, 新的 InternetExplorer 對象將自動建立. 一些原因你想控制NewWindow2 事件以便控制新建InternetExplorer 對象. 為什么? 因?yàn)槟阆胂拗艻nternet Explorer的實(shí)例數(shù)量,或者你想控制創(chuàng)建的實(shí)例的事件.

            以下 NewWindow2 事件控制函數(shù)中; 建立了一個新的, 隱藏的, 不可導(dǎo)航的Internet Explorer實(shí)例; 并且設(shè)定ppDisp 參數(shù)指向新實(shí)例.如果你想,你可以加入任何接收新實(shí)例事件的代碼.

            												
            														void CMyEvtSink::NewWindow2(LPDISPATCH* ppDisp, BOOL* Cancel)
            												
            										
            												
            														{
            												
            										
            												
            														
            																
            																		?? // Note that m_pIE is a class member of type IWebBrowser2*.
            														
            												
            										
            												
            														
            																
            																		?? HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL, 
            														
            												
            										
            												
            														
            																
            																		?????????????????????????????????CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, 
            														
            												
            										
            												
            														
            																
            																		?????????????????????????????????(void**)&m_pIE);
            														
            												
            										
            												
            														
            																
            																		?? if (hr == S_OK)
            														
            												
            										
            												
            														
            																
            																		????? *ppDisp = (IDispatch*)pIE;
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? // Do not set Cancel to TRUE. If you do,
            														
            												
            										
            												
            														
            																
            																		?? // the navigation will be completely canceled.
            														
            												
            										
            												
            														}
            												
            										

            另外的原因控制NewWindow2 事件是由于你想你應(yīng)用程序在用戶選擇在新窗口打開一個url時進(jìn)行控制. 如果你不進(jìn)行控制NewWindow2 事件, Internet Explorer 新實(shí)例將被創(chuàng)建.

            以下為控制新建窗口的vb代碼:

            												
            														Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
            												
            										
            												
            														
            																
            																		?? Dim frmWB As Form1
            														
            												
            										
            												
            														
            																
            																		?? Set frmWB = New Form1
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? Set ppDisp = frmWB.WebBrowser1.Object
            														
            												
            										
            												
            														
            																
            																		?? frmWB.Visible = True
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? Set frmWB = Nothing
            														
            												
            										
            												
            														End Sub
            												
            										

            在此NewWindow2事件代碼中,檔一個新常口需要被創(chuàng)建, 我們建立一個新的當(dāng)前窗體Form1的拷貝. 在此表單窗體, 相當(dāng)于Internet Explorer的新實(shí)例,將處理導(dǎo)航.

            mfc中我們需要首先加入NewWindow2 事件的映射條目到視圖類的事件映射宏. (不要忘記包含 ExDispID.h in, 那里有DISPID_NEWWINDOW2 定義.)

            												
            														ON_EVENT(CMfcWebHostView, IDC_WEBBROWSER, DISPID_NEWWINDOW2,
            												
            										
            												
            														
            																
            																		???????? OnNewWindow2, VTS_PDISPATCH VTS_PBOOL)
            														
            												
            										

            下一步聲明OnNewWindow2 方法:

            												
            														void OnNewWindow2(LPDISPATCH* ppDisp, BOOL* Cancel);
            												
            										

            最后實(shí)現(xiàn)OnNewWindow2 方法以創(chuàng)建一個新的MfcWebHost窗口實(shí)例:

            												
            														void CMfcWebHostView::OnNewWindow2(LPDISPATCH FAR* ppDisp,
            												
            										
            												
            														
            																
            																		?????????????????????????????????? BOOL FAR* Cancel)
            														
            												
            										
            												
            														{
            												
            										
            												
            														
            																
            																		?? // Ensure that ppDisp is not NULL.
            														
            												
            										
            												
            														
            																
            																		?? // If it is NULL, you probably specified
            														
            												
            										
            												
            														
            																
            																		?? // VT_DISPATCH for the first parameter in 
            														
            												
            										
            												
            														
            																
            																		???// the ON_EVENT macro for NewWindow2 in 
            														
            												
            										
            												
            														
            																
            																		???// the event sink map. The correct parameter
            														
            												
            										
            												
            														
            																
            																		?? // type is VT_PDISPATCH.
            														
            												
            										
            												
            														
            																
            																		?? //
            														
            												
            										
            												
            														
            																
            																		?? ASSERT(ppDisp);
            														
            												
            										
            												
            														
            																
            																		?? if (!ppDisp)
            														
            												
            										
            												
            														
            																
            																		????? return;
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? // Get a pointer to the application object
            														
            												
            										
            												
            														
            																
            																		?? // for this application.
            														
            												
            										
            												
            														
            																
            																		?? //
            														
            												
            										
            												
            														
            																
            																		?? CWinApp* pApp = AfxGetApp();
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? // Get the correct document template.
            														
            												
            										
            												
            														
            																
            																		?? //
            														
            												
            										
            												
            														
            																
            																		?? CDocTemplate* pDocTemplate;
            														
            												
            										
            												
            														
            																
            																		?? POSITION pos = pApp->GetFirstDocTemplatePosition();
            														
            												
            										
            												
            														
            																
            																		?? pDocTemplate = pApp->GetNextDocTemplate(pos);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? ASSERT(pDocTemplate);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? // Create the new frame.
            														
            												
            										
            												
            														
            																
            																		?? CFrameWnd* pNewFrame = pDocTemplate->CreateNewFrame(GetDocument(),
            														
            												
            										
            												
            														
            																
            																		??????????????????????????????????????????? (CFrameWnd*)AfxGetMainWnd());
            														
            												
            										
            												
            														
            																
            																		?? ASSERT(pNewFrame);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? // Activate the frame, and set its active view.
            														
            												
            										
            												
            														
            																
            																		?? //
            														
            												
            										
            												
            														
            																
            																		?? pDocTemplate->InitialUpdateFrame(pNewFrame, NULL);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? CMfcWebHostView* pWbView = 
            														
            												
            										
            												
            														
            																
            																		????????????????????(CMfcWebHostView*)pNewFrame->GetActiveView();
            														
            												
            										
            												
            														
            																?? 
            														
            												
            										
            												
            														
            																
            																		???ASSERT(pWbView);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? *ppDisp = pWbView->m_webBrowser.GetApplication();
            														
            												
            										
            												
            														}
            												
            										

            如果你在sid或者mdi應(yīng)用程序中控制一個WebBrowser控件,實(shí)現(xiàn)OnNewWindow2 方法是復(fù)雜的且需要知道如何解決同文檔模版如何工作. 或許, 如果你在一個給予對話框的應(yīng)用程序控制一個WebBrowser控件是較為容易的.此處為示例:

            												
            														void CMyDlg::OnNewWindow2(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel) 
            												
            										
            												
            														{
            												
            										
            												
            														
            																
            																		?? m_dlgNewWB = new CMyDlg;
            														
            												
            										
            												
            														
            																
            																		?? m_dlgNewWB->Create(IDD_MYDLG_DIALOG);
            														
            												
            										
            												
            														
            																?

            												
            														
            																
            																		?? *ppDisp = m_dlgNewWB->m_webBrowser.GetApplication();
            														
            												
            										
            												
            														}
            												
            										

            記住當(dāng)你完成打開的新對話框后刪除(delete) m_dlgNewWB. 且不要在CMyDlg::OnInitDialog方法中導(dǎo)航, 因?yàn)檫@樣代碼將不會工作.

            ?????????????????

            ProgressChange

            ProgressChange 事件通告你的應(yīng)用程序下在操作狀態(tài)已經(jīng)更新. ProgressChange 有兩個參數(shù):

            ·???????? Progress. 總計有多少進(jìn)度將被展示, 如果為-1 表示整個進(jìn)度已經(jīng)完成

            • ProgressMax. 最大進(jìn)度值

            容器可通過此事件顯示下載進(jìn)度。

            事件發(fā)生序列

            下圖展示了IE的事件發(fā)生序列.但這僅僅為不包含幀的普通網(wǎng)頁瀏覽. (沒有包含諸如 ProgressChange, CommandStateChange, OnToolBar,等等事件.)不是所有事件都會被激發(fā). 但是 BeforeNavigate2DocumentComplete 每次瀏覽都會被激發(fā).

            ? ?

            Figure 7-5. The sequence of events fired by the WebBrowser control during a typical navigation.

            posted on 2006-06-23 21:46 楊粼波 閱讀(6884) 評論(2)  編輯 收藏 引用 所屬分類: Windows編程

            評論

            # re: 如何對webbrowser和IE編程(十) 2009-01-18 21:28 Chocolly

            為什么你的代碼排版這么亂??  回復(fù)  更多評論   

            # re: 如何對webbrowser和IE編程(十) 2010-05-11 10:25 有vb.net的嗎

            @Chocolly
            有vb.net的嗎 QQ395824504  回復(fù)  更多評論   

            久久精品一区二区三区不卡| 久久久久久久97| 久久99精品国产麻豆不卡| 久久精品中文字幕第23页| 狠狠色丁香久久婷婷综合_中| 国内精品伊人久久久久777| www.久久热.com| 亚洲а∨天堂久久精品| 人妻少妇久久中文字幕| 国产精品99久久久久久www| 久久久噜噜噜久久中文字幕色伊伊| 精品免费tv久久久久久久| 人妻无码αv中文字幕久久琪琪布| 国产精品久久自在自线观看| 亚洲人成无码www久久久| 2020最新久久久视精品爱| 久久人人爽人人爽人人AV东京热| 久久精品国产精品亜洲毛片 | 久久丫忘忧草产品| 国产精品99久久精品爆乳| 久久精品中文字幕无码绿巨人| 日韩AV毛片精品久久久| 久久久久亚洲AV无码专区网站| 久久久久久久久久久久中文字幕| 狠狠色丁香久久婷婷综合_中| 草草久久久无码国产专区| 亚洲综合婷婷久久| 日韩亚洲欧美久久久www综合网| 国产精品久久久亚洲| 色偷偷91久久综合噜噜噜噜| 99久久精品九九亚洲精品| 一本大道久久a久久精品综合| 久久国产精品99精品国产| 日韩久久久久久中文人妻| 亚洲va久久久噜噜噜久久男同| 久久久噜噜噜久久中文字幕色伊伊 | 亚洲伊人久久综合中文成人网| 久久成人精品| 亚洲欧美日韩精品久久亚洲区 | 亚洲精品乱码久久久久久| 蜜臀av性久久久久蜜臀aⅴ麻豆|