使用VC++和COM API
盡管使用VC不像Vb中那么容易自動化IE,但是也不太難,尤其是你理解了CON和COM API。無論你使用MFC, ATL, 或者標準 C++自動化IE,方法都是一樣—你使用COM API來實現.
VC++中創建一個Internet Explorer實例包括要調用COM API CoCreateInstance ,指定第一個參數為 CLSID_InternetExplorer 。創建IE自動化實例不像創建包含webbrowser的Activex控件困難。你不需要實現容器或者site對象的必要接口。
來看看如何容易的使用CoCreateInstance 創建IE實例吧。啟動Visual C++, 新建MFC AppWizard (exe) 應用程序命名為 MfcAutoIE.選擇dialog-based option, 認可其他缺省選項.
現在加入如VbAutoIE中的控件到表單.對話框看起來如 6-21. 分派ID到對話框的各個控件。 確信控件TAB次序如 Figure 6-22. (tab 次序影響到radio按鈕的工作)
Figure 6-21.
MfcAutoIE dialog.
Figure 6-22.
MfcAutoIE dialog tab order.
現在用右鍵菜單設置每一個隱藏radio按鈕的Group ,屬性設置如表 6-9.
Table 6-9.
Member Variables for MfcAutoIE Dialog Controls
Control
|
Type
|
Member Variable
|
Hide radio button for AddressBar
|
int
|
m_nAddressBar
|
Edit box
|
CString
|
m_strStatusText
|
Hide radio button for MenuBar
|
int
|
m_nMenuBar
|
Hide radio button for StatusBar
|
int
|
m_nStatusBar
|
Hide radio button for ToolBar
|
int
|
m_nToolBar
|
我們使用ClassWizard 為表 6-9 中的控件建立變量時,他們自動加入到 CMfcAutoIEDlg. 成員變量設置為-1.
編譯
MfcAutoIE Example
之前我們設置編譯的
Directory
次序
屬性
編譯之前,你需要處理一些重要任務:
1.
???
確信你已經從MSDN中下載IE5的頭文件和庫文件。
2.
在
Tools/Options
菜單的
Directories
頁
,
確信
lib
路徑中包含
Internet Explorer 5
和
Windows 2000
庫文件
.
載列表中。
3.
配置
Include
:
略
?
現在我們加入代碼使之工作。 首先你應當包含ExDisp.h到你的對話框頭文件—MfcAutoIEDlg.h. ExDisp.h 是包含了WebBrowser接口和類ID的頭文件.確信你已經從MSDN下載了最新的版本。
建立一個private 或者protected 的數據類型,指向IWebBrowser2 ?的指針, ?命名為 m_pInetExplorer. 如下
protected:
?? IWebBrowser2* m_pInetExplorer;
|
現在在構造函數中初始化m_pInetExplorer 為 NULL 。你必須也初始化COM. 放置一個CoInitialize 的COM API調用在構造函數。構造函數看起來應當如下:
CMfcAutoIEDlg::CMfcAutoIEDlg(CWnd* pParent /*=NULL*/)
?? : CDialog(CMfcAutoIEDlg::IDD, pParent),
???? m_pInetExplorer(NULL)
{
?? //{{AFX_DATA_INIT(CMfcAutoIEDlg)
?? m_strStatusText = _T("");
?? m_nAddressBar = -1;
?? m_nMenuBar = -1;
?? m_nStatusBar = -1;
?? m_nToolBar = -1;
?? //}}AFX_DATA_INIT
?? //Note that LoadIcon does not require a subsequent DestroyIcon
?? //in Win32.
?? m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
?
?? // Initialize COM
?? CoInitialize(NULL);
}
|
建立一個析構函數,以便調用CoUninitialize API 函數用以反初始化 COM. 此處的析構函數:
CMfcAutoIEDlg::~CMfcAutoIEDlg()
{
?? // Uninitialize COM.
?? //
?? CoUninitialize();
}
|
在預備工作之后, 讓我們開始實現具體的控制。首先為Start IE5 按鈕建立一個消息循環. 通常,你可以使用ClassWizard建立消息循環處理句柄. 在此消息句柄, 采用 CoCreateInstance API 建立一個IE實例。 此處初建的Internet Explorer實例初始化為隱藏, 所以你必須使用Visible屬性使他可見。為了導航到用戶的主頁,使用GoHome 方法。此處為消息處理句柄代碼:
void CMfcAutoIEDlg::OnStartIE5()
{
?? // If an instance of Internet Explorer has
?? // not already been created, create one.
?? // This instance will initially be hidden,
?? // so make it visible by using the Visible
?? // property. Also, navigate to the user's
?? // home page by using the GoHome method.
?? //
?? if (m_pInetExplorer)
????? MessageBox
???????? (_T("Only one instance of Internet Explorer is allowed."));
?? else
?? {
????? HRESULT hr;
????? hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_SERVER,
?????????????????????????? IID_IWebBrowser2, (LPVOID*)&m_pInetExplorer);
?
????? if (SUCCEEDED(hr))
????? {
???????? // Set the radio buttons to their correct values.
???????? SetRadioButtons();
?
???????? m_pInetExplorer->put_Visible(VARIANT_TRUE);
???????? m_pInetExplorer->GoHome();
????? }
?? }
}
|
在此代碼中,我們首先檢查是否IE的上一個實例已經建立。如果已經建立,將會顯示一個錯誤消息框。(你僅僅能夠啟動一個IE的實例,隨后你將可以看到如何檢測IE窗口被關閉以便重置IE的數據成員。)如果一個IE的實例還未創建, CoCreateInstance 將 CLSID_InternetExplorer 作為第一個參數被調用. (此類 ID 定義于ExDisp.h ,為Internet Explorer的唯一標示符.)
第二個參數我們設定為NULL ,因為我們不希望此COM對象被聚合(be aggregated). 我們希望IE運行在一個單獨的進程空間,所以我們指定第三個參數為特殊值 CLSCTX_SERVER .我們利用第四個參數指示哪一個接口我們將通過CoCreateInstance 調用創建一個COM對象后被創建。在此例中,我們將一直希望獲得IWebBrowser2, 所以我們指定IID_IWebBrowser2 為第四個參數值。最后我們傳送存儲接口指針的變量. 對于此參數,你必須采用void類型傳遞一個指針的地址 (確信你傳送的指針指向一個接口類型。)
如果一個IE實例成功創建,名為SetRadioButtons 的成員變量被創建。這是一個protected 成員函數,檢查當前地址欄、菜單條、工具條和狀態條等的狀態 ,用來設置radio 按鈕組的狀態。.為檢查每一個的狀態我們簡單的獲取屬性關聯的當前值 。
C++ 應用中使用COM 沒有包裝類, 屬性被引用為使用 get_ and put_ 方法.為檢取每一個用戶問題的狀態,我們簡單的調用每一個關聯的(UI)項目的get_ 方法 .除了 get_ToolBar外其他get_方法返回指向VARIANT_BOOL 數據類型,返回值指示用戶接口是否可見或者隱藏。如果用戶接口元素可見,將返回VARIANT_TRUE 。如果該項目是隱藏的,將返回VARIANT_FALSE 。這些值區別于TRUE 和 FALSE 的用法.
提醒
當在
Visual C++
涉及
VARIANT_BOOL
,
你必須使用
VARIANT_TRUE
或者
VARIANT_FALSE
代替
TRUE
or FALSE. VARIANT_TRUE
定義值
0xffff
,
而
TRUE
定義為
1
.
如果你比較
VARIANT_TRUE
和
TRUE
,
你將發現在
Vb
中不匹配,你可以在涉及到
VARIANT_BOOL
.
使用
true
和
false
是由于
VB
替你實現了轉換。
get
_ToolBar 方法不同于其他屬性,因為它指向一個整型指針,所以我們如果發現返回非0,工具條可見。如果整型值是0,工具條將隱藏:
提醒
如果一個屬性只讀
, put_
將不會出現。同樣,如果一個屬性只寫,將不會出現
get_
方法。
此處為 SetRadioButtons 方法的代碼:
void CMfcAutoIEDlg::SetRadioButtons()
{
?? VARIANT_BOOL vtBool = VARIANT_TRUE;
?
?? // Get the current state of the AddressBar.
?? //
?? m_pInetExplorer->get_AddressBar(&vtBool);
?? m_nAddressBar = (vtBool == VARIANT_TRUE) ? 1 : 0;
?
?? // Get the current state of the MenuBar.
?? //
?? m_pInetExplorer->get_MenuBar(&vtBool);
?? m_nMenuBar = (vtBool == VARIANT_TRUE) ? 1 : 0;
?
?? // Get the current state of the StatusBar.
?? //
?? m_pInetExplorer->get_StatusBar(&vtBool);
?? m_nStatusBar = (vtBool == VARIANT_TRUE) ? 1 : 0;
?
?? // Get the current state of the ToolBar.
?? // Unlike the other get methods, get_ToolBar
?? // takes a pointer to an integer.
?? //
?? m_pInetExplorer->get_ToolBar(&m_nToolBar);
?
?? UpdateData(FALSE);? // Initializes dialog box with changed values.
}
|
:
void CMfcAutoIEDlg::OnAddrBarShowHide()
{
?? UpdateData(TRUE);
?
?? if (m_pInetExplorer)
?? {
????? VARIANT_BOOL vtShow =
?????????m_nAddressBar ? VARIANT_TRUE : VARIANT_FALSE;
?
????? m_pInetExplorer->put_AddressBar(vtShow);
?? }
}
?
void CMfcAutoIEDlg::OnMenuBarShowHide()
{
?? UpdateData(TRUE);
?
?? if (m_pInetExplorer)
?? {
????? VARIANT_BOOL vtShow =
?????????m_nMenuBar ? VARIANT_TRUE : VARIANT_FALSE;
?
????? m_pInetExplorer->put_MenuBar(vtShow);
?? }
}
?
void CMfcAutoIEDlg::OnStatusBarShowHide()
{
?? UpdateData(TRUE);
?
?? if (m_pInetExplorer)
?? {
????? VARIANT_BOOL vtShow =
?????????m_nStatusBar ? VARIANT_TRUE : VARIANT_FALSE;
?
????? m_pInetExplorer->put_StatusBar(vtShow);
?? }
}
?
void CMfcAutoIEDlg::OnToolBarShowHide()
{
?? UpdateData(TRUE);
?
?? if (m_pInetExplorer)
????? m_pInetExplorer->put_ToolBar(m_nToolBar);
}
|
注意到OnToolBarShowHide 方法中我們將m_nToolBar 數據成員傳遞給put_ToolBar 方法替代了VARIANT_BOOL. 我們暫時不解釋為什么,就像get_ToolBar, put_ToolBar 傳遞一個整型而不是 VARIANT_BOOL.
現在利用ClassWizard 建立一個Change 按鈕的消息循環處理句柄 。此消息的句柄將在任何時候設定set Internet Explorer 的狀態條為edit 輸入框內容。 代碼看起來如下:
void CMfcAutoIEDlg::OnChangeStatusText()
{
?? UpdateData(TRUE);
?
?? if (m_pInetExplorer)
?? {
????? _bstr_t bstrStatusText = m_strStatusText.AllocSysString();
????? m_pInetExplorer->put_StatusText(bstrStatusText);
?? }
}
|
確信你在第一個任務就是調用傳遞TRUE的 UpdateData and .這樣的目的是更新對阿框中所有相關的控件, 包括 m_strStatusText. 如果m_pInetExplorer 不是NULL—那意味著 Internet Explorer一個實例已經被創建— StatusText 被設定為用戶輸入的文字。 StatusText 同樣事采用put_ 設定Visible 屬性。 該函數需要一個BSTR的入口參數,所以調用 AllocSysString 方法使得m_strStatusText 數據成員變量分派為BSTR 可以傳遞給put_StatusText. AllocSysString 是 CString 的方法,返回一個Cstring對象中值的 BSTR 類型。BSTR 返回自 AllocSysString 存儲于_bstr_t類型的變量, 一個 COM 編譯器支持的Visual C++類。為了使用此類,你必須包含comdef.h 頭文件,置于對話框實現文件CMfcAutoIEDlg—MfcAutoIEDlg.cpp. 該類將小心處理BSTR 離開當前范圍的狀況,所以你不需要調用SysFreeString的Win32 API 以釋放調用 put_StatusText.之后的BSTR.
至此,我們基本上完成了。為了使用戶輸入Enter時不關閉對話框,重寫基類對話框的OnOK方法。在此方法中,簡單的不做任何事。確信你沒有調用基類的CDialog::OnOK 方法,否則,對話框會關閉。
現在來重寫OnCancel 的基類方法, 該方法調用于用戶按下ESC或者點擊對話框的右鍵菜單的關閉或者對話框的X按鈕。在 OnCancel中,如果一個Internet Explorer 實例已經被創建, 在調用Quit 方法時關閉InternetExplorer 對象。 Quit 甚至可以在用戶默認關掉Internet Explorer. 如果出現此情形, Quit 方法將返回 RPC_S_SERVER_UNAVAILABLE, 標示Internet Explorer 不再可用.你可以簡單忽略此錯誤消息。以下為OnCancel的代碼:
void CMfcAutoIEDlg::OnCancel()
{
?? if (m_pInetExplorer)
????? m_pInetExplorer->Quit();
?
?? CDialog::OnCancel();
}
|
最后, 你必須釋放掉指向IE的IWebBrowser2 接口指針。你可以在對話框的析構函數中處理。此處為更型后的析構函數:
CMfcAutoIEDlg::~CMfcAutoIEDlg()
{
?? // Release the WebBrowser interface pointer
?? //
?? if (m_pInetExplorer)
?? {
????? m_pInetExplorer->Release();
????? m_pInetExplorer = NULL;
?? }
?
?? // Uninitialize COM
?? //
?? CoUninitialize();
}
|
現在,通常我們可以編譯運行對話框應用程序。啟動
IE
實例,測試。