寄宿WebBrowser 控件
我們現在開始在VB和VC中創建一些程序來寄宿(Host)WebBrowser控件。在你完成本部分的樣本,你將對如何創建寄宿一個WebBrowser控件的應用程序又一個基本的了解。當你看到如此容易的加入Web瀏覽功能加入到你的應用程序,我相信你會立即開始實踐的。
使用VB
在VB中,你可以在5分鐘內開發一個全功能的自己的web瀏覽 。以下步驟為建立一個web瀏覽器程序:
1. 啟動VB.
2. 選擇“Standard EXE“ ,進入設計模式。
3. WebBrowser 控件未自動化包含到控件工具箱(Control Toolbox)。 要增加 WebBrowser 控件到 控件工具箱,選擇 Project 菜單下的Components. ,如下對話將顯示:
.jpg)
Figure 6-3. 組件對話框.
4. 如果Controls TAB頁未顯示,點擊 Controls TAB頁 。然后勾選中列表中的“ Microsoft Internet Controls”,點擊OK關閉對話框。Vb將會增加WebBrowser 控件到控件工具箱,如圖所示:
Figure 6-4. Visual Basic 控件工具條在增加了WebBrowser 控件后的圖標
5. 為增加 WebBrowser 控件至窗體,點擊WebBrowser 控件,然后確定在窗體中的大小。一旦你增加了一個控件到表單,Visual Basic 將指派其名稱為 WebBrowser1.
6. 調整表單的尺寸一邊導航時候可看到更多的web內容。預留一些空間給地址欄。表單看起來如 Figure 6-5.
7. 雙擊空區域以增加Load 事件。為了能夠使WebBrowser 導航到一個web頁,你僅需要調用如GoHome, GoSearch, Navigate, 或者 Navigate2.等導航方法。
8. 調用GoHome 方法到用戶主頁。代碼如下:
Private Sub Form_Load() WebBrowser1.GoHome End Sub |

Figure 6-5. Visual Basic form after adding the WebBrowser control.
如此就完成了! 你已經創建了一個全功能的web瀏覽器. 照我的時間,僅僅不好過分鐘。為確信它可工作,你可啟動進行測試。你的應用程序將裝入webbrowser控件兵導航到主頁。保存工程為VbWebHost.
盡管你已經擁有一個可工作的Internet應用程序,你仍需要做些工作視你的應用程序更像一個真實的web瀏覽器。為了可導航增加一些控件到表單。為輸入URL增加一個 label, 一個文字輸入框, Go 按鈕, Back 按鈕, Forward 按鈕, 以及Stop 按鈕. 表單應該看起來如Figure 6-6.
如 Table 6-7 分派給你的控件屬性。 
Figure 6-6. Visual Basic form after adding controls.
Table 6-7. 控件屬性
控件 | 屬性 |
Label | Caption = "Address:" |
TextBox | Name = txtAddress; Text = "" (In other words, remove the default text.) |
Go Button | Name = btnGo; Caption = "Go" |
Back Button | Name = btnBack; Caption = "< Back" |
Forward Button | Name = btnFwd; Caption = "Forward >" |
Stop Button | Name = btnStop; Caption = "Stop" |
增加一些代碼,調用WebBrowser 控件的方法使得工作正常。 舉例來說,當用戶輸入文字到文字輸入框且點擊Go 按鈕,使用 Navigate 方法處理導航。 當然,你必須缺新用戶真實輸入了一些文字到文字輸入框。
同樣, 你也可以使用GoBack, GoForward, 以及 Stop 方法以實現Back, Forward, 和 Stop 按鈕。記住 GoBack 和 GoForward 方法當前狀態下無效。Visual Basic 代碼看起來類似如下:
Option Explicit Private Sub btnBack_Click() On Error Resume Next WebBrowser1.GoBack End Sub Private Sub btnFwd_Click() On Error Resume Next WebBrowser1.GoForward End Sub Private Sub btnGo_Click() WebBrowser1.Navigate txtAddress.Text End Sub Private Sub btnStop_Click() WebBrowser1.Stop End Sub Private Sub Form_Load() WebBrowser1.GoHome End Sub |
注意 On Error Resume Next 特別用于Back 和Forward 按鈕的click事件處理. 當當前URL前后無歷史列表,這些方法將返回錯誤。Visual Basic錯誤捕獲用于處理他們。
現在測試程序,在瀏覽器完成導航到主頁,輸入URL 到文字框點擊Go 按鈕。你將有兩個 URLs 在歷史列表中。點擊 Back按鈕退回到主頁, 接著點擊 Forward 按鈕前移。在web頁轉載時候點擊 Stop 按鈕確信Stop 按鈕工作正常。
打印web頁
用為用戶經常想打印在web瀏覽器中的頁面,你可能細想加入打印功能到你的應用程序。過去打印在VB中笨重難以實現(使用sendkey),現在可以使用ExecWB方法來輕松實現,且非常可靠。
喲增加打印功能,首先加入Print 按鈕到表單。 (如前面) 命名按鈕為 btnPrint, 改變標題為Print. 看起來如Figure 6-7.
Figure 6-7. Visual Basic form after adding a Print button.
下一步, 雙擊 Print 按鈕以增加Click事件處理代碼.事件處理過程中, 調用 ExecWB 方法, 傳遞打印需要的命令ID: OLECMDID_PRINT.如果你想打印前提醒用戶, 指定OLECMDEXECOPT_PROMPTUSER; 其他情形指定OLECMDEXECOPT_DONTPROMPTUSER。 本例中,我們打印前提示 。打印命令沒有輸入輸出,所以你指定第三個和第四個參數 Null 。代碼應當如下:
Private Sub btnPrint_Click() On Error Resume Next WebBrowser1.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, _ Null, Null End Sub |
使用 Visual C++
Vc中創建瀏覽器應用程序畢vb中稍微困難。如果白手起家創建米的宿應用程序 (無MFC 或 ATL), 需要實現大量的COM接口來寄宿WebBrowser 控件。你必須還要利用COM的API CoCreateInstance 創建WebBrowser 控件的實例,指定 CLSID_WebBrowser a作為你想創建的對象的CLSID 。并且還要 將控件"site"于你的應用程序.
因為建立ActiveX 控件容器費本文討論主題,所以著重討論簡單途徑寄宿webbrowser控件。
使用 MFC
你可以創建3種類型的MFC應用程序: 單文檔接口 (SDI), 多文檔接口 (MDI), 以及基于對話框的應用程序。因為對話框MFC類似VB,所以本處將討論采用SDI來寄宿webbrowser控件。一旦你知道如何采用SDI 應用來寄宿webbrowser控件,轉為MDI 將會容易些。
在演示SDI的例子中,我將使用WebBrowser (CWebBrowser2) 包裝類MFC的內置CHtmlView 類將幫助你理解如何在MFC中寄宿WebBrowser 。
CHtmlView 類無需太多解釋。要使用它,必須在MFC AppWizard第6步中選擇你的應用程序的基類為ChtmlView, 如 Figure 6-8. 在完成 wizard后, 你的應用程序的視圖類獎派生自 CHtmlView. 然后你可以直接調用IWebBrowser2 接口的不同方法.
Figure 6-8. MFC AppWizard - Step 6 of 6 dialog box. 
為創建MFC 單文檔接口應用程序,啟動Visual C++ 新建菜單。新的對話框展示如 Figure 6-9.
Figure 6-9. Visual C++ New dialog box.
在 Projects 頁, 選擇 MFC AppWizard (exe) 項, 輸入一個項目名稱 (譬如 MfcWebHost之類), 點擊OK. MFC AppWizard is 步驟一顯示. (看 Figure 6-10.)
Figure 6-10. Step 1 of the MFC AppWizard. 
選擇 Single Document 。然后認可缺省選項,點擊完成. 要增加WebBrowser 到你的工程,選擇菜單Project/Add To Project/Components,如下圖Figure 6-11所示:

Figure 6-11. Selecting Components And Controls.
Visual C++ 收集所有的你的系統中的組件和控件信息展示在Components 和Controls 陳列對話框,如圖Figure 6-12所示.
Figure 6-12. Components And Controls Gallery dialog box.
雙擊 Registered ActiveX Controls , 定位到并選擇Microsoft Web Browser, 點擊插入按鈕,提示你是否想加組件, 點擊 OK。wizard 顯示確認對話框如 Figure 6-13.
Figure 6-13. Confirm Classes dialog box.
缺省情況下, CWebBrowser2 將被選擇。CWebBrowser2 類是VC為你創建的WebBrowser 控件的包裝類。 因為該類特定實現于MFC, 所以你僅可在MFC項目中使用。點擊OK 按鈕增加CWebBrowser2 到項目中. 然后關閉陳列對話框
包含 WebBrowser2.h 在你的view 類的頭文件—MfcWebHostView.h中:
創建private 或者 protected 數據成員,命名為 m_webBrowser. 聲明如下:
protected: CWebBrowser2 m_webBrowser; |
為WM_CREATE 消息建立消息處理句柄. 在此事件處理中, 使用m_webBrowser的 Create 方法加入創建一個webbrowser控件的新實例。 (Create 方法是包裝類為你創建的.) OnCreate 消息處理代碼看起來如下:
int CMfcWebHostView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // Create WebBrowser control // if (!m_webBrowser.Create(NULL, WS_CHILD|WS_VISIBLE, CRect(), this, NULL)) { return -1; } return 0; } |
現在為WM_SIZE 消息創建消息處理. 當應用程序改變大小時候修改WebBrowser 控件的大小。如果你不包含以下代碼,你的View窗口永遠也不會顯示webbrowser控件。 此處展示該消息處理代碼:
void CMfcWebHostView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // Resize WebBrowser control // m_webBrowser.MoveWindow( 0, 0, cx, cy ); m_webBrowser.UpdateWindow(); } |
覆蓋OnInitialUpdate m基類的代碼在應用程序首次創建時導航到用戶主頁。此處展示OnInitialUpdate 消息處理代碼:
void CMfcWebHostView::OnInitialUpdate() { CView::OnInitialUpdate(); // Navigate to the user's home page. // m_webBrowser.GoHome(); } |
編譯且運行程序.將導航到用戶的主頁,如Figure 6-14.
Figure 6-14. MfcWebHost application.
現在加入一些訪問internet的功能。 增加 Navigate 包含一些Go Back, Go Forward, Go Home, Go Search, Go To A Web Page、Stop等子菜單, 你的菜單看起來類似Figure 6-15.
Figure 6-15. Navigate menu.
現在你可以加入快捷健到你的菜單,例如Alt-Left 組合鍵給Go Back. 你可以使用你習慣的組合健
為每一個菜單項建立實現句柄。增加菜單消息處理句柄代碼是較為容易的。舉例, GoBack 方法實現Go Back 菜單項代碼看起來如下:
void CMfcWebHostView::OnNavigateGoBack() { m_webBrowser.GoBack(); } void CMfcWebHostView::OnNavigateGoForward() { m_webBrowser.GoForward(); } void CMfcWebHostView::OnNavigateGoHome() { m_webBrowser.GoHome(); } void CMfcWebHostView::OnNavigateGoSearch() { m_webBrowser.GoSearch(); } void CMfcWebHostView::OnNavigateStop() { m_webBrowser.Stop(); } |
如上面提到,如果history列表不存在前項或者后項而用戶點擊Go Back 或者 Go Forward ,將會發生錯誤.
Go To A Web Page 菜單項是特別情形. 對此菜單項, 一個對話框將顯示詢問用戶想去的URL. (見 Figure 6-16.)
Figure 6-16. Enter A URL For Navigation dialog box.
另外的選擇,你可在工具條建立編輯框 用于導航. 在本例子中, 我選擇了對話框。當建立對話框,你可以使用ClassWizard 建立新的對話框類.命名為CAddressDlg. 對話框類應當包含名為m_strAddress 的CString ,它將控制用戶輸入的地址。如果你的ClassWizard 創建此類成員,該成員將會是public的. 改變數據成員為protected, 且建立如下的訪問存取方法:
public: const CString& GetAddress() const { return m_strAddress; } protected: CString m_strAddress; |
現在建立Go To A Web Page 菜單項的消息處理句柄.該菜單句柄將建立顯示CAddressDlg 對話框. (確信 CAddressDlg 的頭文件包含在 MfcWebHostView.cpp中.) 在用戶輸入URL 且點擊OK后, 應用程序將利用webbrowser的Navigate 方法導航到URL 。 代碼如下:
void CMfcWebHostView::OnNavigateGoToAWebPage() { CAddressDlg dlgAddr; // Show the dialog box. If the user clicks OK, // make sure a URL was entered. If one was entered, // navigate to that URL by using the Navigate method. // if (dlgAddr.DoModal() == IDOK) { CString strAddress = dlgAddr.GetAddress(); if (!strAddress.IsEmpty()) { COleVariant vtEmpty; m_webBrowser.Navigate(strAddress, &vtEmpty, &vtEmpty, &vtEmpty, &vtEmpty); } } } |
在以上代碼中, 一個CAddressDlg 類的實例被創建。DoModal 用于顯示對話框。如果用戶點擊OK 按鈕,應用程序應當檢查 URL是否合法。
使用 ATL
在過去,寄宿WebBrowser控件的ATL應用程序項比較標準的C++沒有任何優勢。但是現在,新的ATL3的ActiveX控件容器類允許你較容易創建宿主WebBrowser 控件的。
因為實現ATL用戶界面特征如菜單和工具條還是使用Win32實現,本例我將展示其本質上靈活的一面。我只想展示如何使用新的容器類寄宿webbrowser控件。我不準備實現任何用戶界面。本例子僅僅實現一個容納WebBrowser的框架。
用ATL建立一個WebBrowser 宿主應用程序, 啟動0 Visual C++, 執行以下及個步驟:
1. 新建.
2. 選擇ATL COM AppWizard, 輸入 AtlWebHost 作為工程名
3. 點擊 OK, 選擇 Executable (EXE),完成。
4. 在新建工程信息對話框點擊OK, wizard 將建立ATL可執行文件工程的基本代碼。
5. 向工程中加入宿主WebBrowser 的控件A。具體操作,在ClassView面板中右擊 AtlWebHost類
6. 從上下文菜單中選擇New ATL Object. ATL Object Wizard 對話框將顯示
7. 從面板中選擇HTML Control,如 Figure 6-17所示: 
Figure 6-17. ATL Object Wizard with HTML Control selected.
8. 點擊Next ,為控件輸入一個短小名,例如 AtlWbHost.。wizard 自動填寫其它部分
9. 保持推薦值直到OK.
wizard 將建立CAtlWbHost 類, 包含樣本代碼寄宿WebBrowser 控件.實例化WebBrowser控件的關鍵代碼在OnCreate 方法的實現代碼中, 當 WM_CREATE 消息被發送到關聯此類的windows窗體時被調用。wizard 為 OnCreate 插入的代碼如下:
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CAxWindow wnd(m_hWnd); HRESULT hr = wnd.CreateControl(IDH_ATLWBHOST); if (SUCCEEDED(hr)) hr = wnd.SetExternalDispatch(static_cast<IAtlWbHostUI*>(this)); if (SUCCEEDED(hr)) hr = wnd.QueryControl(IID_IWebBrowser2, (void**)&m_spBrowser); return SUCCEEDED(hr) ? 0 : -1; } |
在這段代碼中, 類型微CAxWindow 的windows對象被首先創建,該對象提供ActiveX 控件容器支持. 下一步, 用CAxWindow 類的CreateControl方法創建WebBrowser控件。注意傳遞給CreateControl 的是HTML頁的資源ID,所以當WebBrowser控件被創建時候HTML頁被顯示。然后SetExternalDispatch 方法被調用。該方法實現于IDocHostUIHandler 接口。
如果任何一個步驟都沒有錯誤發生, 代碼將用CAxWindow 的QueryControl 方法查詢 IWebBrowser2接口.如果一切順利, QueryControl 返回IWebBrowser2 接口的指針,存儲于m_spBrowser 成員變量. 缺省情況下, wizard 將其標記為public.
提醒
作為我所認為的良好的面向對象編程習慣, 我習慣改變m_spBrowser 成員為 protected .當然你可以決定是否也如此做
如果現在就編譯執行代碼, 什么事情也不會發生。你必須加入創建和顯示窗體的代碼。要實現,你必須首先在CAtlWbHost 類中實現Run方法. (該名字無關痛癢。 你可選擇任何你感興趣的名字.) 示例代碼如下:
STDMETHODIMP Run() { // // Create and show the window. // RECT rcClient = { CW_USEDEFAULT, 0, 0, 0 }; if (Create(GetDesktopWindow(), rcClient, _T("ATL Browser"), WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, (UINT)NULL) == NULL) { return E_FAIL; } ShowWindow(SW_SHOWNORMAL); return S_OK; } |
當 Create 方法被調用, WM_CREATE 消息發送到窗口; 因此, OnCreate 方法被調用,OnCreate中包含之前討論的寄宿WebBrowser 控件的代碼。
提醒
Create 方法屬于CWindowImpl 類,而該類是CcomControl 的基礎類。. CAtlWbHost 派生于CComControl, 這意味著你不如直接調用CWindowImpl 的方法。
下一步必須調用Run 方法以創建和顯示窗體。 此調用將被生成于AtlWebHost.cpp 文件直接存在于你的應用程序消息循環之上。但在Run 被調用之前, CAtlWbHost 類的實例必須被創建。你不可以簡單的象其他C++對象一樣簡單采用New操作符創建一個實例 。你必須采用CComObject 的CreateInstance 方法建立該類的實例。 在你的應用程序的消息泵處(CAtlWebHost.cpp中), 插入如下代碼實例化CAtlWbHost 類, 然后調用 Run 方法:
CComObject<CAtlWbHost>* pWbHost; HRESULT hr = CComObject<CAtlWbHost>::CreateInstance(&pWbHost); if (SUCCEEDED(hr)) pWbHost->Run(); // Message pump MSG msg; while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg); |
如果現在編譯執行, 它將可以工作了。它裝入WebBrowser 控件, 導航到wizard automatically 插入到你的應用程序的HTML資源頁. 你可以導航到某些有實際意義的地方. 你可在 OnCreate 函數中調用GoHome 。 在你加入調用 GoHome 之后, OnCreate 函數看起來如下:
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CAxWindow wnd(m_hWnd); HRESULT hr = wnd.CreateControl(IDH_ATLWBHOST); if (SUCCEEDED(hr)) hr = wnd.SetExternalDispatch(static_cast<IAtlWbHostUI*>(this)); if (SUCCEEDED(hr)) hr = wnd.QueryControl(IID_IWebBrowser2, (void**)&m_spBrowser); if (SUCCEEDED(hr)) m_spBrowser->GoHome(); return SUCCEEDED(hr) ? 0 : -1; } |
當你編譯執行,你的應用程序看起來類似圖Figure 6-18. 
Figure 6-18. AtlWebHost application.
打印 Web 頁
所有打印只需要調用傳遞OLECMDID_PRINT的 ExecWB 方法。
MfcWebHost 要支持打印, 應當建立一個ID_FILE_PRINT菜單的菜單句柄,在菜單句柄中調webbrowser的ExecWB ,以及傳遞 OLECMDID_PRINT. 你也可打印前提醒用戶, 僅需要我們多做少量代碼. 盡管如此,如果你想知道用戶是否按下OK按鈕或者取消按鈕, 檢查 ExecWB的返回值。針對打印命令, 如果用戶點幾OK以初始化打印, ExecWB 將返回S_OK。 如果用戶點擊取消, ExecWB 將返回 S_OK以外的值. (說 " S_OK以外的值" 是因為取消按鈕的返回值不具有典型代表性) 以下代碼為當用戶選擇文件菜單中打印命令時的調用情況。
void CMfcWebHostView::OnFilePrint() { m_webBrowser.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, NULL, NULL); } |
作為打印的附加功能, WebBrowser control 試圖提供打印頁設置功能.采用打印頁設置, 用戶可以改變例如頁頭頁腳等設置。要實現業設置功能,代碼調用 ExecWB 并且傳遞 OLECMDID_PAGESETUP. 代碼如下:
void CMfcWebHostView::OnFilePageSetup() { m_webBrowser.ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_PROMPTUSER, NULL, NULL); } |
使用 Visual C++
Vc中創建瀏覽器應用程序畢vb中稍微困難。如果白手起家創建米的宿應用程序 (無MFC 或 ATL), 需要實現大量的COM接口來寄宿WebBrowser 控件。你必須還要利用COM的API CoCreateInstance 創建WebBrowser 控件的實例,指定 CLSID_WebBrowser a作為你想創建的對象的CLSID 。并且還要 將控件"site"于你的應用程序.
因為建立ActiveX 控件容器費本文討論主題,所以著重討論簡單途徑寄宿webbrowser控件。
使用 MFC
你可以創建3種類型的MFC應用程序: 單文檔接口 (SDI), 多文檔接口 (MDI), 以及基于對話框的應用程序。因為對話框MFC類似VB,所以本處將討論采用SDI來寄宿webbrowser控件。一旦你知道如何采用SDI 應用來寄宿webbrowser控件,轉為MDI 將會容易些。
在演示SDI的例子中,我將使用WebBrowser (CWebBrowser2) 包裝類MFC的內置CHtmlView 類將幫助你理解如何在MFC中寄宿WebBrowser 。
CHtmlView 類無需太多解釋。要使用它,必須在MFC AppWizard第6步中選擇你的應用程序的基類為ChtmlView,如 Figure 6-8. 在完成 wizard后, 你的應用程序的視圖類獎派生自 CHtmlView. 然后你可以直接調用IWebBrowser2接口的不同方法.
Figure 6-8. MFC AppWizard - Step 6 of 6 dialog box. 
為創建MFC 單文檔接口應用程序,啟動Visual C++ 新建菜單。新的對話框展示如 Figure 6-9.
Figure 6-9. Visual C++ New dialog box.
在 Projects 頁, 選擇 MFC AppWizard (exe) 項, 輸入一個項目名稱 (譬如 MfcWebHost之類), 點擊OK. MFC AppWizard is 步驟一顯示. (看 Figure 6-10.)
Figure 6-10. Step 1 of the MFC AppWizard. 
選擇 Single Document 。然后認可缺省選項,點擊完成. 要增加WebBrowser 到你的工程,選擇菜單Project/Add To Project/Components,如下圖Figure 6-11所示:

Figure 6-11. Selecting Components And Controls.
Visual C++ 收集所有的你的系統中的組件和控件信息展示在Components 和Controls 陳列對話框,如圖Figure 6-12所示.
Figure 6-12. Components And Controls Gallery dialog box.
雙擊 Registered ActiveX Controls , 定位到并選擇Microsoft Web Browser, 點擊插入按鈕,提示你是否想加組件, 點擊 OK。wizard 顯示確認對話框如 Figure 6-13.
Figure 6-13. Confirm Classes dialog box.
缺省情況下, CWebBrowser2 將被選擇。CWebBrowser2 類是VC為你創建的WebBrowser 控件的包裝類。 因為該類特定實現于MFC, 所以你僅可在MFC項目中使用。點擊OK 按鈕增加CWebBrowser2 到項目中. 然后關閉陳列對話框
包含 WebBrowser2.h 在你的view 類的頭文件—MfcWebHostView.h中:
創建private 或者 protected 數據成員,命名為 m_webBrowser. 聲明如下:
protected: CWebBrowser2 m_webBrowser; |
為WM_CREATE 消息建立消息處理句柄. 在此事件處理中, 使用m_webBrowser的 Create 方法加入創建一個webbrowser控件的新實例。 (Create 方法是包裝類為你創建的.) OnCreate 消息處理代碼看起來如下:
int CMfcWebHostView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // Create WebBrowser control // if (!m_webBrowser.Create(NULL, WS_CHILD|WS_VISIBLE, CRect(), this, NULL)) { return -1; } return 0; } |
現在為WM_SIZE 消息創建消息處理. 當應用程序改變大小時候修改WebBrowser 控件的大小。如果你不包含以下代碼,你的View窗口永遠也不會顯示webbrowser控件。 此處展示該消息處理代碼:
void CMfcWebHostView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // Resize WebBrowser control // m_webBrowser.MoveWindow( 0, 0, cx, cy ); m_webBrowser.UpdateWindow(); } |
覆蓋OnInitialUpdate m基類的代碼在應用程序首次創建時導航到用戶主頁。此處展示 OnInitialUpdate 消息處理代碼:
void CMfcWebHostView::OnInitialUpdate() { CView::OnInitialUpdate(); // Navigate to the user's home page. // m_webBrowser.GoHome(); } |
編譯且運行程序.將導航到用戶的主頁,如Figure 6-14.
Figure 6-14. MfcWebHost application.
現在加入一些訪問internet的功能。 增加 Navigate 包含一些Go Back, Go Forward, Go Home, Go Search, Go To A Web Page、Stop等子菜單, 你的菜單看起來類似Figure 6-15.
Figure 6-15. Navigate menu.
現在你可以加入快捷健到你的菜單,例如Alt-Left 組合鍵給Go Back. 你可以使用你習慣的組合健
為每一個菜單項建立實現句柄。增加菜單消息處理句柄代碼是較為容易的。舉例, GoBack 方法實現Go Back 菜單項代碼看起來如下:
void CMfcWebHostView::OnNavigateGoBack() { m_webBrowser.GoBack(); } void CMfcWebHostView::OnNavigateGoForward() { m_webBrowser.GoForward(); } void CMfcWebHostView::OnNavigateGoHome() { m_webBrowser.GoHome(); } void CMfcWebHostView::OnNavigateGoSearch() { m_webBrowser.GoSearch(); } void CMfcWebHostView::OnNavigateStop() { m_webBrowser.Stop(); } |
如上面提到,如果history列表不存在前項或者后項而用戶點擊Go Back 或者 Go Forward ,將會發生錯誤.
Go To A Web Page 菜單項是特別情形. 對此菜單項, 一個對話框將顯示詢問用戶想去的URL. (見 Figure 6-16.)
Figure 6-16. Enter A URL For Navigation dialog box.
另外的選擇,你可在工具條建立編輯框 用于導航. 在本例子中, 我選擇了對話框。當建立對話框,你可以使用ClassWizard 建立新的對話框類.命名為CAddressDlg. 對話框類應當包含名為m_strAddress 的CString ,它將控制用戶輸入的地址。如果你的ClassWizard 創建此類成員,該成員將會是public的. 改變數據成員為protected, 且建立如下的訪問存取方法:
public: const CString& GetAddress() const { return m_strAddress; } protected: CString m_strAddress; |
現在建立Go To A Web Page 菜單項的消息處理句柄.該菜單句柄將建立顯示CAddressDlg 對話框. (確信CAddressDlg 的頭文件包含在 MfcWebHostView.cpp中.) 在用戶輸入URL 且點擊OK后, 應用程序將利用webbrowser的Navigate 方法導航到URL 。 代碼如下:
void CMfcWebHostView::OnNavigateGoToAWebPage() { CAddressDlg dlgAddr; // Show the dialog box. If the user clicks OK, // make sure a URL was entered. If one was entered, // navigate to that URL by using the Navigate method. // if (dlgAddr.DoModal() == IDOK) { CString strAddress = dlgAddr.GetAddress(); if (!strAddress.IsEmpty()) { COleVariant vtEmpty; m_webBrowser.Navigate(strAddress, &vtEmpty, &vtEmpty, &vtEmpty, &vtEmpty); } } } |
在以上代碼中, 一個CAddressDlg 類的實例被創建。DoModal 用于顯示對話框。如果用戶點擊OK 按鈕,應用程序應當檢查 URL是否合法。
使用 ATL
在過去,寄宿WebBrowser控件的ATL應用程序項比較標準的C++沒有任何優勢。但是現在,新的ATL3的ActiveX控件容器類允許你較容易創建宿主WebBrowser 控件的。
因為實現ATL用戶界面特征如菜單和工具條還是使用Win32實現,本例我將展示其本質上靈活的一面。我只想展示如何使用新的容器類寄宿webbrowser控件。我不準備實現任何用戶界面。本例子僅僅實現一個容納WebBrowser的框架。
用ATL建立一個WebBrowser 宿主應用程序, 啟動0 Visual C++, 執行以下及個步驟:
1. 新建.
2. 選擇ATL COM AppWizard, 輸入 AtlWebHost 作為工程名
3. 點擊 OK, 選擇 Executable (EXE),完成。
4. 在新建工程信息對話框點擊OK, wizard 將建立ATL可執行文件工程的基本代碼。
5. 向工程中加入宿主WebBrowser 的控件A。具體操作,在ClassView面板中右擊 AtlWebHost 類
6. 從上下文菜單中選擇New ATL Object. ATL Object Wizard 對話框將顯示
7. 從面板中選擇HTML Control,如 Figure 6-17所示: 
Figure 6-17. ATL Object Wizard with HTML Control selected.
8. 點擊Next ,為控件輸入一個短小名,例如 AtlWbHost.。wizard 自動填寫其它部分
9. 保持推薦值直到OK.
wizard 將建立CAtlWbHost 類, 包含樣本代碼寄宿WebBrowser 控件.實例化WebBrowser控件的關鍵代碼在OnCreate 方法的實現代碼中, 當 WM_CREATE 消息被發送到關聯此類的windows窗體時被調用。wizard 為OnCreate 插入的代碼如下:
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CAxWindow wnd(m_hWnd); HRESULT hr = wnd.CreateControl(IDH_ATLWBHOST); if (SUCCEEDED(hr)) hr = wnd.SetExternalDispatch(static_cast<IAtlWbHostUI*>(this)); if (SUCCEEDED(hr)) hr = wnd.QueryControl(IID_IWebBrowser2, (void**)&m_spBrowser); return SUCCEEDED(hr) ? 0 : -1; } |
在這段代碼中, 類型微CAxWindow 的windows對象被首先創建,該對象提供ActiveX 控件容器支持. 下一步, 用CAxWindow 類的CreateControl方法創建WebBrowser控件。注意傳遞給CreateControl 的是HTML頁的資源ID,所以當WebBrowser控件被創建時候HTML頁被顯示。然后SetExternalDispatch 方法被調用。該方法實現于IDocHostUIHandler 接口。
如果任何一個步驟都沒有錯誤發生, 代碼將用CAxWindow 的QueryControl 方法查詢 IWebBrowser2 接口.如果一切順利, QueryControl 返回IWebBrowser2 接口的指針,存儲于m_spBrowser 成員變量. 缺省情況下, wizard 將其標記為public.
提醒
作為我所認為的良好的面向對象編程習慣, 我習慣改變m_spBrowser 成員為 protected . 當然你可以決定是否也如此做
如果現在就編譯執行代碼, 什么事情也不會發生。你必須加入創建和顯示窗體的代碼。要實現,你必須首先在CAtlWbHost 類中實現Run方法. (該名字無關痛癢。 你可選擇任何你感興趣的名字.) 示例代碼如下:
STDMETHODIMP Run() { // // Create and show the window. // RECT rcClient = { CW_USEDEFAULT, 0, 0, 0 }; if (Create(GetDesktopWindow(), rcClient, _T("ATL Browser"), WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, (UINT)NULL) == NULL) { return E_FAIL; } ShowWindow(SW_SHOWNORMAL); return S_OK; } |
當 Create 方法被調用, WM_CREATE 消息發送到窗口; 因此, OnCreate 方法被調用,OnCreate中包含之前討論的寄宿WebBrowser 控件的代碼。
提醒
Create 方法屬于CWindowImpl 類,而該類是CcomControl 的基礎類。. CAtlWbHost 派生于CComControl, 這意味著你不如直接調用CWindowImpl 的方法。
下一步必須調用Run 方法以創建和顯示窗體。 此調用將被生成于AtlWebHost.cpp 文件直接存在于你的應用程序消息循環之上。但在Run 被調用之前, CAtlWbHost 類的實例必須被創建。你不可以簡單的象其他C++對象一樣簡單采用New操作符創建一個實例 。你必須采用CComObject 的CreateInstance 方法建立該類的實例。 在你的應用程序的消息泵處(CAtlWebHost.cpp中), 插入如下代碼實例化CAtlWbHost 類, 然后調用 Run 方法:
CComObject<CAtlWbHost>* pWbHost; HRESULT hr = CComObject<CAtlWbHost>::CreateInstance(&pWbHost); if (SUCCEEDED(hr)) pWbHost->Run(); // Message pump MSG msg; while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg); |
如果現在編譯執行, 它將可以工作了。它裝入WebBrowser 控件, 導航到wizard automatically 插入到你的應用程序的HTML資源頁. 你可以導航到某些有實際意義的地方. 你可在 OnCreate 函數中調用GoHome 。 在你加入調用GoHome 之后, OnCreate 函數看起來如下:
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CAxWindow wnd(m_hWnd); HRESULT hr = wnd.CreateControl(IDH_ATLWBHOST); if (SUCCEEDED(hr)) hr = wnd.SetExternalDispatch(static_cast<IAtlWbHostUI*>(this)); if (SUCCEEDED(hr)) hr = wnd.QueryControl(IID_IWebBrowser2, (void**)&m_spBrowser); if (SUCCEEDED(hr)) m_spBrowser->GoHome(); return SUCCEEDED(hr) ? 0 : -1; } |
當你編譯執行,你的應用程序看起來類似圖Figure 6-18. 
Figure 6-18. AtlWebHost application.
打印 Web 頁
所有打印只需要調用傳遞OLECMDID_PRINT的 ExecWB 方法。
MfcWebHost 要支持打印, 應當建立一個ID_FILE_PRINT菜單的菜單句柄,在菜單句柄中調webbrowser的ExecWB ,以及傳遞 OLECMDID_PRINT. 你也可打印前提醒用戶, 僅需要我們多做少量代碼. 盡管如此,如果你想知道用戶是否按下OK按鈕或者取消按鈕, 檢查 ExecWB的返回值。針對打印命令, 如果用戶點幾OK以初始化打印, ExecWB 將返回S_OK。 如果用戶點擊取消, ExecWB 將返回 S_OK以外的值. (說 " S_OK以外的值" 是因為取消按鈕的返回值不具有典型代表性) 以下代碼為當用戶選擇文件菜單中打印命令時的調用情況。
void CMfcWebHostView::OnFilePrint() { m_webBrowser.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, NULL, NULL); } |
作為打印的附加功能, WebBrowser control 試圖提供打印頁設置功能.采用打印頁設置, 用戶可以改變例如頁頭頁腳等設置。要實現業設置功能,代碼調用 ExecWB 并且傳遞 OLECMDID_PAGESETUP. 代碼如下:
void CMfcWebHostView::OnFilePageSetup() { m_webBrowser.ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_PROMPTUSER, NULL, NULL); } |