由Internet Explorer 5激發(fā)事件
如你所知, Internet Explorer像其他COM對象一樣激發(fā)事件—通過連接點.但實際上Internet Explorer如何激發(fā)事件呢?每次 Internet Explorer需要向客戶提供關于當前活動狀態(tài)的信息, Internet Explorer 激發(fā)通過DWebBrowserEvents2 連接點激發(fā)一個事件. (之前到版本 4, Internet Explorer 通過 DWebBrowserEvents 接口激發(fā)事件.但到了版本4.x和5, Internet Explorer 通過 DWebBrowserEvents2 連接點.)
注意
如何領會到
Internet Explorer
加法那些事件
?
最佳途徑是
MSDN Online Web Workshop.
另外采用
OLE-COM Object Viewer
不像WebBrowser 控件 和 Internet Explorer的其他接口,是劍接口沒有繼承體系. DWebBrowserEvents 接口嚴格應用于Internet Explorer 3. 如果你正宿主WebBrowser 控件或者自動化Internet Explorer 5, 你可以通過此接口接收事件—但是不可掛接. DWebBrowserEvents2 接口包含的方法是為Internet Explorer 5定制的.用 DWebBrowserEvents2 替代DWebBrowserEvents ,你將有更多的控制能力. 所以不要忘記接口的最后面的2.
盡管DWebBrowserEvents2 是一個事件接口, 它其實就是像IWebBrowser2? 一樣的另外 COM 接口,所以它可以包含方法. (D 開頭的命名是表示這是派遣接口.一個派遣接口是一個IDispatch 接口.但不同于普通接口, 派遣接口沒有vtable.) 就像一個接口一樣,派遣接口只不過提供一些函數(shù)的定義—他們并不真實實現(xiàn).事件的實現(xiàn)由客戶提供.舉例來說,為了讓WebBrowser 激發(fā)一個事件, 在DWebBrowserEvents2 接口中適當定義一些方法.這些方法由客戶實現(xiàn).但WebBrowser不直接調(diào)用這些方法.換句話講, WebBrowser 并不調(diào)用DocumentComplete 方法.因為 DWebBrowserEvents2 是派遣接口, WebBrowser 通過IDispatch::Invoke調(diào)用客戶的實現(xiàn). 早期, 當WebBrowser 調(diào)用客戶的Invoke 實現(xiàn), WebBrowser 傳遞事件被激發(fā)的DISPID.
注意
某些工具如
Visual Basic, MFC,
和
ATL
提供
Invoke
實現(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, 它會自動幫助你轉換,你可以比較True和False.
現(xiàn)在來仔細看看這些事件
Table 7-6
WebBrowser 事件
私有事件
|
描述
|
BeforeNavigate2
|
在導航之前發(fā)生
. (
該事件并不在不刷新頁面的時候發(fā)生
)
|
CommandStateChange
|
當命令狀態(tài)改變時發(fā)生
.
該事件告訴你何時使能或者禁止
Back
以及
Forward
菜單像或者按鈕
.
|
DocumentComplete
|
當整個文檔完全完成裝載時發(fā)生
.
如果你刷新頁面
,
此事件并不激發(fā)
.
|
DownloadBegin
|
當一個下載項目開始時候發(fā)生
,此事件也在你刷新(
IWebBrowser2::Refresh.
)時發(fā)生
|
DownloadComplete
|
黨整個下載項目完成是發(fā)生該事件也發(fā)生在完成刷新頁面
.
|
NavigateComplete2
|
當整個導航完成
.
該事件對應于
BeforeNavigate2
.
|
NewWindow2
|
在一個新的窗口被創(chuàng)建以顯示
Web
頁或者其他資源的時候發(fā)生。譬如你在頁面中以新建窗口的方式打開一個連接
|
OnFullScreen
|
當
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
|
當
Internet Explorer
正在退出時發(fā)生
.
該事件當用戶關閉瀏覽器或者調(diào)用
Quit
方法
.
|
OnStatusBar
|
當
StatusBar
屬性被改變的時候發(fā)生。事件攜帶
VARIANT_ BOOL
類型的輸入?yún)?shù)
指示
Internet Explorer
的狀態(tài)條是否可見
(VARIANT_TRUE)
或者隱藏
(VARIANT_FALSE).
|
OnTheaterMode
|
當
TheaterMode
屬性被改變時發(fā)生
.
事件攜帶
VARIANT_ BOOL
類型的輸入?yún)?shù)
指示
Internet Explorer
的狀態(tài)條是否可見
(VARIANT_TRUE)
或者隱藏
(VARIANT_FALSE).
|
OnToolBar
|
當
ToolBar
屬性被改變時發(fā)生
.
事件攜帶
VARIANT_ BOOL
類型的輸入?yún)?shù)
指示
Internet Explorer
的狀態(tài)條是否可見
(VARIANT_TRUE)
或者隱藏
(VARIANT_FALSE).
|
OnVisible
|
當
WebBrowser
將被顯示或者隱藏時發(fā)生。
.
事件攜帶
VARIANT_ BOOL
類型的輸入?yún)?shù)
指示
Internet Explorer
的狀態(tài)條是否可見
(VARIANT_TRUE)
或者隱藏
(VARIANT_FALSE).
|
ProgressChange
|
當下載進度被更新時候發(fā)生
|
PropertyChange
|
當屬性改變時候發(fā)生。典型的
,
當
PutProperty
方法被調(diào)用時
|
StatusTextChange
|
Internet Explorer
和
WebBrowser
控件改變狀態(tài)條時候發(fā)生。即使
webbrowser
控件沒有狀態(tài)條。
StatusTextChange
給客戶一個改變狀態(tài)條的機會
|
TitleChange
|
.
當文檔對象的
title
可用或者改變的時候發(fā)生
|
BeforeNavigate2
BeforeNavigate2
就像字面上所說. 當Internet Explorer 導航到一個WEB頁是激發(fā); 因此, 當用戶輸入一個 URL, 點擊 Back 或者 Forward 按鈕, 或者處理一個導航時都會發(fā)生. BeforeNavigate2 ?也在WebBrowser 控件導航類方法調(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ā)生導航的頂級窗口或者幀的
Idispatch
接口的地址
|
URL
|
將導航至的
URL
|
Flags
|
保留
|
TargetFrameName
|
顯示資源的窗口或者幀的名字字符串,或者為
NULL
(如果沒有命名)
|
PostData
|
HTTP POST
傳輸?shù)臄?shù)據(jù)地址
|
Headers
|
增加的將要發(fā)給服務器的
HTTP
頭
.
一般
HTTP
頭指定其它的服務器要求。傳送給服務器的數(shù)據(jù)類型、狀態(tài)馬等
|
Cancel
|
cancel
標志的地址
.
設置為
TRUE
可取消導航
|
注意打所屬參數(shù)匹配于Navigate 或者 Navigate2的調(diào)用參數(shù).如果 BeforeNavigate2 由一個或者多個導航類調(diào)用激發(fā),這些導航類的方法參數(shù) 傳遞到BeforeNavigate2 方法.
在事件的句柄函數(shù)中, 你可以使用Cancel 參數(shù)取消導航, 或者你可以是用pDisp 參數(shù)修改導航目的.設置Cancel 參數(shù)為 VARIANT_TRUE 可以取消導航,如果你想,你可以通過pDisp修改參數(shù)導航信息且導航到另外的位置.舉例來說,如果我們向停止當前導航, 增加一些頭信息,且導航到原先的URL.在Visual Basic, 我們可以如下代碼實現(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
|
我們需要注意以上代碼的幾個重點.
首先你必須檢查pDisp 的類型使之確定為WebBrowser. 當頁面包含幀, pDisp 可能不是 WebBrowser 對象由此一些導航會導致錯誤.
其次你必須檢查確信Headers 參數(shù)是空字符串以避免無限循環(huán).記住BeforeNavigate2 每一次導航都會發(fā)生.因此如果你在BeforeNavigate2事件處理中調(diào)用Navigate, 另外一次 BeforeNavigate2 將被激活. 在前面的代碼中, 僅僅在Headers 參數(shù)為空才調(diào)用Navigate 避免了無限循環(huán). 如果Headers 參數(shù)是空, Navigate 將攜帶非空的 Headers 參數(shù). 下一次BeforeNavigate2 北激活, Headers 將不為空; 此時,我們千萬不可再次Navigate a,從而導致一個無限循環(huán).
第三點你必須調(diào)用pDisp 的Stop 方法.如果你沒做到這點,"about:NavigationCanceled" Web 頁將會載你首次取消掉導航時被顯示.
CommandStateChange
CommandStateChange
是當Internet Explorer 想通知一個應用程序WebBrowser 命令狀態(tài)已經(jīng)改變時激發(fā).當檢測到Forward和Back 菜單項和按鈕禁止或者使能時激發(fā)此事件.
CommandStateChange
事件有2個參數(shù), Command 和 Enable。Command 輸入?yún)?shù)將要改變狀態(tài)的按鈕的表示符,可以取值—CSC_NAVIGATEFORWARD 和 CSC_NAVIGATEBACK分別表示是Forward按鈕項和Back項,每次導航發(fā)生, CommandStateChange 事件發(fā)生并告訴你Forward 或者 Back 菜單項以及按鈕將使能或禁止. 舉例來說, 如果沒有Web頁在當前導航后發(fā)生, Command 的值應該為 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()
|
重要的一點是要通過WebBrowser控件的Create 方法來創(chuàng)建. ON_EVENT的第二個參數(shù)為你宿主的WebBrowser控件的IID.之前的例子中是NULL. 你必須為webbrowser控件聲明一個ID 且用此 ID 創(chuàng)建實例.如果不這么做,事件將不會正確工作.
你可以在工程的任何文件定義此ID. (推薦在資源頭文件resource.h.) 因為 最大的資源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)代碼中, 設定表示Go Forward 或者 Go Back 想得導航菜單項的數(shù)據(jù)成員為使能或者禁止. 該書據(jù)成員將被UPDATE_COMMAND_UI 句柄使用。以下為OnCommandStateChange 方法實現(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_fForwardEnabled 和 m_fBackEnabled 數(shù)據(jù)變量為保護成員,類型為BOOL.同樣在構造函數(shù)中誰的些數(shù)據(jù)成員為TRUE。.
現(xiàn)在當Go Forward和Go Back的菜單 UPDATE_COMMAND_UI被處理, 你可以直接進行設置. 下為示例代碼:
void CMfcWebHostView::OnUpdateNavigateGoForward(CCmdUI* pCmdUI)
{
?? pCmdUI->Enable(m_fForwardEnabled);
}
?
void CMfcWebHostView::OnUpdateNavigateGoBack(CCmdUI* pCmdUI)
{
?? pCmdUI->Enable(m_fBackEnabled);
}
|
DocumentComplete
當一個文檔完整的完成下載Internet Explorer 激發(fā)DocumentComplete 事件. 僅僅當此事件激發(fā)后 文檔對象才可安全使用.在一個無幀的Web頁情形中文檔對象是IHTMLDocument2 對象, 我們以后會討論. 當文檔對象準備好可用,他的狀態(tài)為READYSTATE_COMPLETE.
關于 DocumentComplete 事件以西擊點需要注意:
·????????
在沒有幀的web頁, DocumentComplete 事件在下載完成后激發(fā)一次.
-
在多幀的
web
頁,此事件激發(fā)多次
.
并非每一個幀激發(fā)一個事件
,
但每一個幀激發(fā)
DownloadBegin
事件將會相應激發(fā)
DocumentComplete
事件
.
-
DocumentComplete
又一個指向
IDispatch
的指針參數(shù)
,
該參數(shù)指向激發(fā)此事件的窗口
.
此窗口可以是幀中的窗口
-
頂級幀在所有子幀激發(fā)了各自的
DocumentComplete
事件后激發(fā)自己的
DocumentComplete
事件。
因此
,
,要看一個
web
頁是否完整下載完成
,
你需要從該事件的處理句柄中獲取由事件產(chǎn)地過來的
IDispatch
參數(shù)的
IUnknown
接口。下一步,比較
IUnknown
接口是否指向你正宿主的
WebBrowser
控件或者自動化的
IE
的實例的
IUnknown
接口
.
如果這兩個指針相同,這意味著全部
HTML,
圖片
images,
控件
,
以及諸如此類在頂級幀或者子幀的全部對象元素都被下載了
.
?
VB中實現(xià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
|
實現(xiàn)以上四點在Visual C++ 應用程序里較困難一點,但你可以做到! 首先在DocumentComplete 事件的宏中如下聲明:
ON_EVENT(CMfcWebHostView, IDC_WEBBROWSER, DISPID_DOCUMENTCOMPLETE,
???????? OnDocumentComplete, VTS_DISPATCH VTS_PVARIANT)
|
接下來聲明OnDocumentComplete 方法作為事件處理句柄
void OnDocumentComplete(LPDISPATCH lpDispatch, VARIANT FAR* URL);
|
最后,實現(xiàn)該方法以檢測 是否頁面已經(jīng)下載,我們得到我們宿主控制bBrowser 控件的IUnknown. (注意我們不是簡單獲取指向 IUnknown ,而是要調(diào)用GetControlUnknown 方法. GetControlUnknown方法返回的IUnknown 指針 實際上并不等于被宿主話的 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();
?? }
}
|
有一點需要注意上面的代碼我們在GetControlUnknown 返回的IUnknown 接口指針使用時并沒有進行Release ,因為b IUnknown 指針并沒有在GetControlUnknown方法中AddRef'. GetControlUnknown 方法僅僅返回一個IOleObject 數(shù)據(jù)成員的指針,該指針由控件站點類—CcontrolSite 操縱處理. 如果你釋放了IUnknown 接口指針, 載你關閉應用程序時,一個訪問違例將會發(fā)生,因為MFC 將試圖在對象被刪除時候多釋放一次.
DownloadBegin
DownloadBegin
事件通知應用程序一個導航操作開始. 一般情況下該事件在BeforeNavigate2 事件之后激發(fā), 除非導航操作在BeforeNavigate2 事件處理過程中被取消.容器應當顯示動畫或者忙指示當前正處于連接的DownloadBegin事件. 每一個 DownloadBegin 事件有一個相應的DownloadComplete 事件. 在刷新頁面的情形中, DownloadBegin 和 DownloadComplete 使唯一的被激發(fā)的導航事件.
DownloadComplete
DownloadComplete
在一個導航操作完成時候發(fā)生, 停止, 或者失敗. 不像 NavigateComplete2僅僅當成功導航才發(fā)生, DownloadComplete總是在道涵開始后激發(fā).任何在DownloadBegin 中顯示的動畫或者忙指示將會在DownloadComplete 中停止.
NavigateComplete2
NavigateComplete2
事件在導航到一個超連接整個窗口或者幀集合的元素全部完成時候發(fā)生. 第一此事件發(fā)生表示文檔document已經(jīng)準備好.在此事件發(fā)生后, 你可以通過Document 屬性存取文檔(document)而不接收到錯誤.但是能夠訪問一個文檔不意味著你訪問文檔使安全的.你可以在DocumentComplete 事件激發(fā)后安全訪問文檔.
檔你需要訪問document對象但是不需要訪問文檔內(nèi)的元素,你可以在NavigateComplete2 事件中盡可能快的處理,例如當你在文打工通過高級宿主接口. NavigateComplete2 事件有2個參數(shù)—IDispatch of 代表激發(fā)事件的對象URL 為你需要導航到的URL.
NewWindow2
NewWindow2
檔用戶顯示一個新窗口以進行新導航顯示web頁或者其他資源時發(fā)生.在WebBrowser控件響應柄進行預處理 (舉例來說, 在響應window.open 方法).
NewWindow2
也在Navigate 或者 Navigate2 方法被調(diào)用且navOpenInNewWindow 標志被設定時發(fā)生. 檔采用文件菜單中的New Window按鈕時并不發(fā)生(Internet Explorer幀不是一個 HTML 幀; 它是幀窗口.) 因此, WebBrowser 對象不知道什么時候新窗口將被打開. 因為 NewWindow2 有時候很難使用, 所以我們來檢查它的兩個參數(shù): ppDisp and Cancel.
ppDisp
參數(shù)是接口指針, 一般是接收新WebBrowser 或者 InternetExplorer 對象的IDispatch 接口指針, 是你能夠創(chuàng)建一個Internet Explorer新實例以便能夠控制來自你的應用程序?qū)Ш疆a(chǎn)生的新窗口. 該實例開始為新建的, 隱藏的, (暫時)不可導航WebBrowser 或者 InternetExplorer 對象. 在NewWindow2事件句柄函數(shù)返回之前, InternetExplorer 對象激發(fā)NewWindow2 事件將配置新WebBrowser對象的導航目標位置.
另外參數(shù), Cancel, 時取消(Cancel)標志的地址. 應用程序能夠設定此參數(shù)為TRUE 以取消導航操作或者設定為FALSE 以允許新建窗口操作. 設定Cancel 為 TRUE 完全取消新建窗口操作和導航.
如果你不在NewWindow2 事件處理過程中作任何事, 新的 InternetExplorer 對象將自動建立. 一些原因你想控制NewWindow2 事件以便控制新建InternetExplorer 對象. 為什么? 因為你想限制Internet Explorer的實例數(shù)量,或者你想控制創(chuàng)建的實例的事件.
以下 NewWindow2 事件控制函數(shù)中; 建立了一個新的, 隱藏的, 不可導航的Internet Explorer實例; 并且設定ppDisp 參數(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 事件是由于你想你應用程序在用戶選擇在新窗口打開一個url時進行控制. 如果你不進行控制NewWindow2 事件, Internet Explorer 新實例將被創(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)建, 我們建立一個新的當前窗體Form1的拷貝. 在此表單窗體, 相當于Internet Explorer的新實例,將處理導航.
在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);
|
最后實現(xiàn)OnNewWindow2 方法以創(chuàng)建一個新的MfcWebHost窗口實例:
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應用程序中控制一個WebBrowser控件,實現(xiàn)OnNewWindow2 方法是復雜的且需要知道如何解決同文檔模版如何工作. 或許, 如果你在一個給予對話框的應用程序控制一個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();
}
|
記住當你完成打開的新對話框后刪除(delete) m_dlgNewWB. 且不要在CMyDlg::OnInitDialog方法中導航, 因為這樣代碼將不會工作.
?????????????????
ProgressChange
ProgressChange
事件通告你的應用程序下在操作狀態(tài)已經(jīng)更新. ProgressChange 有兩個參數(shù):
·????????
Progress.
總計有多少進度將被展示, 如果為-1 表示整個進度已經(jīng)完成
容器可通過此事件顯示下載進度。
事件發(fā)生序列
下圖展示了IE的事件發(fā)生序列.但這僅僅為不包含幀的普通網(wǎng)頁瀏覽. (沒有包含諸如 ProgressChange, CommandStateChange, OnToolBar,等等事件.)不是所有事件都會被激發(fā). 但是 BeforeNavigate2 和DocumentComplete 每次瀏覽都會被激發(fā).
?
?
Figure 7-5.
The sequence of events fired by the WebBrowser control during a typical navigation.