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

Figure 6-5.
Visual Basic form after adding the WebBrowser control.
如此就完成了! 你已經(jīng)創(chuàng)建了一個全功能的web瀏覽器. 照我的時間,僅僅不好過分鐘。為確信它可工作,你可啟動進行測試。你的應(yīng)用程序?qū)⒀b入webbrowser控件兵導航到主頁。保存工程為VbWebHost.
盡管你已經(jīng)擁有一個可工作的Internet應(yīng)用程序,你仍需要做些工作視你的應(yīng)用程序更像一個真實的web瀏覽器。為了可導航增加一些控件到表單。為輸入URL增加一個 label, 一個文字輸入框, Go 按鈕, Back 按鈕, Forward 按鈕, 以及Stop 按鈕. 表單應(yīng)該看起來如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"
|
增加一些代碼,調(diào)用WebBrowser 控件的方法使得工作正常。 舉例來說,當用戶輸入文字到文字輸入框且點擊Go 按鈕,使用 Navigate 方法處理導航。 當然,你必須缺新用戶真實輸入了一些文字到文字輸入框。
同樣, 你也可以使用GoBack, GoForward,以及 Stop 方法以實現(xiàn)Back, Forward, 和 Stop 按鈕。記住 GoBack 和 GoForward 方法當前狀態(tài)下無效。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錯誤捕獲用于處理他們。
現(xiàn)在測試程序,在瀏覽器完成導航到主頁,輸入URL 到文字框點擊Go 按鈕。你將有兩個 URLs 在歷史列表中。點擊 Back按鈕退回到主頁, 接著點擊 Forward 按鈕前移。在web頁轉(zhuǎn)載時候點擊 Stop 按鈕確信Stop 按鈕工作正常。
打印web頁
用為用戶經(jīng)常想打印在web瀏覽器中的頁面,你可能細想加入打印功能到你的應(yīng)用程序。過去打印在VB中笨重難以實現(xiàn)(使用sendkey),現(xiàn)在可以使用ExecWB方法來輕松實現(xiàn),且非常可靠。
喲增加打印功能,首先加入Print 按鈕到表單。 (如前面) 命名按鈕為 btnPrint, 改變標題為 Print. 看起來如Figure 6-7.
Figure 6-7.
Visual Basic form after adding a Print button.
下一步, 雙擊 Print 按鈕以增加Click事件處理代碼.事件處理過程中, 調(diào)用 ExecWB 方法, 傳遞打印需要的命令I(lǐng)D: OLECMDID_PRINT.如果你想打印前提醒用戶, 指定OLECMDEXECOPT_PROMPTUSER; 其他情形指定OLECMDEXECOPT_DONTPROMPTUSER。 本例中,我們打印前提示 。打印命令沒有輸入輸出,所以你指定第三個和第四個參數(shù) Null 。代碼應(yīng)當如下:
Private Sub btnPrint_Click()
On Error Resume Next
WebBrowser1.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, _Null, Null
End Sub
使用 Visual C++
Vc中創(chuàng)建瀏覽器應(yīng)用程序畢vb中稍微困難。如果白手起家創(chuàng)建米的宿應(yīng)用程序 (無MFC 或 ATL), 需要實現(xiàn)大量的COM接口來寄宿WebBrowser 控件。你必須還要利用COM的API CoCreateInstance 創(chuàng)建WebBrowser 控件的實例,指定 CLSID_WebBrowser a作為你想創(chuàng)建的對象的CLSID 。并且還要 將控件"site"于你的應(yīng)用程序.
因為建立ActiveX 控件容器費本文討論主題,所以著重討論簡單途徑寄宿webbrowser控件。
使用 MFC
你可以創(chuàng)建3種類型的MFC應(yīng)用程序: 單文檔接口 (SDI), 多文檔接口 (MDI), 以及基于對話框的應(yīng)用程序。因為對話框MFC類似VB,所以本處將討論采用SDI來寄宿webbrowser控件。一旦你知道如何采用SDI 應(yīng)用來寄宿webbrowser控件,轉(zhuǎn)為MDI 將會容易些。
在演示SDI的例子中,我將使用WebBrowser (CWebBrowser2) 包裝類MFC的內(nèi)置CHtmlView 類將幫助你理解如何在MFC中寄宿WebBrowser 。
CHtmlView
類無需太多解釋。要使用它,必須在MFC AppWizard第6步中選擇你的應(yīng)用程序的基類為ChtmlView, 如 Figure 6-8. 在完成 wizard后, 你的應(yīng)用程序的視圖類獎派生自 CHtmlView. 然后你可以直接調(diào)用IWebBrowser2 接口的不同方法.

Figure 6-8. MFC AppWizard - Step 6 of 6 dialog box.
為創(chuàng)建MFC 單文檔接口應(yīng)用程序,啟動Visual C++ 新建菜單。新的對話框展示如 Figure 6-9.

Figure 6-9.
Visual C++ New dialog box.
在 Projects 頁, 選擇 MFC AppWizard (exe) 項, 輸入一個項目名稱 (譬如 MfcWebHost之類), 點擊OK. MFC AppWizardis 步驟一顯示. (看 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++ 收集所有的你的系統(tǒng)中的組件和控件信息展示在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為你創(chuàng)建的WebBrowser 控件的包裝類。 因為該類特定實現(xiàn)于MFC, 所以你僅可在MFC項目中使用。點擊OK 按鈕增加CWebBrowser2 到項目中. 然后關(guān)閉陳列對話框
包含 WebBrowser2.h 在你的view 類的頭文件—MfcWebHostView.h中:
#include "WebBrowser2.h"
創(chuàng)建private 或者 protected 數(shù)據(jù)成員,命名為 m_webBrowser. 聲明如下:
protected:
CWebBrowser2 m_webBrowser;
為WM_CREATE 消息建立消息處理句柄. 在此事件處理中, 使用m_webBrowser的 Create 方法加入創(chuàng)建一個webbrowser控件的新實例。 (Create 方法是包裝類為你創(chuàng)建的.) 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;
}
現(xiàn)在為WM_SIZE 消息創(chuàng)建消息處理. 當應(yīng)用程序改變大小時候修改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基類的代碼在應(yīng)用程序首次創(chuàng)建時導航到用戶主頁。此處展示 OnInitialUpdate 消息處理代碼:
void CMfcWebHostView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// Navigate to the user's home page.
//
m_webBrowser.GoHome();
}
編譯且運行程序.將導航到用戶的主頁,如Figure 6-14.

Figure 6-14.
MfcWebHost application.
現(xiàn)在加入一些訪問internet的功能。 增加 Navigate包含一些Go Back, Go Forward, Go Home, Go Search, Go To A Web Page、Stop等子菜單, 你的菜單看起來類似Figure 6-15.
Figure 6-15.
Navigate menu.
現(xiàn)在你可以加入快捷健到你的菜單,例如Alt-Left 組合鍵給Go Back. 你可以使用你習慣的組合健
為每一個菜單項建立實現(xiàn)句柄。增加菜單消息處理句柄代碼是較為容易的。舉例, GoBack 方法實現(xiàn)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 ,將會發(fā)生錯誤.
Go To A Web Page 菜單項是特別情形. 對此菜單項, 一個對話框?qū)@示詢問用戶想去的URL. (見 Figure 6-16.)
Figure 6-16.
Enter A URL For Navigation dialog box.
另外的選擇,你可在工具條建立編輯框 用于導航. 在本例子中, 我選擇了對話框。當建立對話框,你可以使用ClassWizard 建立新的對話框類.命名為CAddressDlg. 對話框類應(yīng)當包含名為m_strAddress 的CString ,它將控制用戶輸入的地址。如果你的ClassWizard 創(chuàng)建此類成員,該成員將會是public的. 改變數(shù)據(jù)成員為protected, 且建立如下的訪問存取方法:
public:
const CString& GetAddress() const { return m_strAddress; }
protected:
CString m_strAddress;
現(xiàn)在建立Go To A Web Page 菜單項的消息處理句柄.該菜單句柄將建立顯示CAddressDlg 對話框. (確信 CAddressDlg 的頭文件包含在 MfcWebHostView.cpp中.) 在用戶輸入URL 且點擊OK后, 應(yīng)用程序?qū)⒗脀ebbrowser的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 類的實例被創(chuàng)建。DoModal 用于顯示對話框。如果用戶點擊OK 按鈕,應(yīng)用程序應(yīng)當檢查 URL是否合法。
使用 ATL
在過去,寄宿WebBrowser控件的ATL應(yīng)用程序項比較標準的C++沒有任何優(yōu)勢。但是現(xiàn)在,新的ATL3的ActiveX控件容器類允許你較容易創(chuàng)建宿主WebBrowser 控件的。
因為實現(xiàn)ATL用戶界面特征如菜單和工具條還是使用Win32實現(xiàn),本例我將展示其本質(zhì)上靈活的一面。我只想展示如何使用新的容器類寄宿webbrowser控件。我不準備實現(xiàn)任何用戶界面。本例子僅僅實現(xiàn)一個容納WebBrowser的框架。
用ATL建立一個WebBrowser 宿主應(yīng)用程序, 啟動0 Visual C++, 執(zhí)行以下及個步驟:
1. 新建.
2.
選擇
ATL COM AppWizard,
輸入
AtlWebHost
作為工程名
3.
點擊
OK,
選擇
Executable (EXE)
,完成。
4.
在新建工程信息對話框點擊
OK, wizard
將建立
ATL
可執(zhí)行文件工程的基本代碼。
5.
向工程中加入宿主
WebBrowser
的控件
A
。具體操作,在
ClassView
面板中右擊
AtlWebHost
類
6.
從上下文菜單中選擇
New ATL Object. ATL Object Wizard
對話框?qū)@示
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控件的關(guān)鍵代碼在OnCreate 方法的實現(xiàn)代碼中, 當 WM_CREATE 消息被發(fā)送到關(guān)聯(lián)此類的windows窗體時被調(diào)用。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對象被首先創(chuàng)建,該對象提供ActiveX 控件容器支持. 下一步, 用CAxWindow 類的CreateControl方法創(chuàng)建WebBrowser控件。注意傳遞給CreateControl 的是HTML頁的資源ID,所以當WebBrowser控件被創(chuàng)建時候HTML頁被顯示。然后SetExternalDispatch 方法被調(diào)用。該方法實現(xiàn)于IDocHostUIHandler 接口。
如果任何一個步驟都沒有錯誤發(fā)生, 代碼將用CAxWindow 的QueryControl 方法查詢 IWebBrowser2 接口.如果一切順利, QueryControl 返回IWebBrowser2 接口的指針,存儲于m_spBrowser 成員變量. 缺省情況下, wizard 將其標記為public.
提醒
作為我所認為的良好的面向?qū)ο缶幊塘晳T
,
我習慣改變
m_spBrowser
成員為
protected .
當然你可以決定是否也如此做
如果現(xiàn)在就編譯執(zhí)行代碼, 什么事情也不會發(fā)生。你必須加入創(chuàng)建和顯示窗體的代碼。要實現(xiàn),你必須首先在CAtlWbHost 類中實現(xiàn)Run方法. (該名字無關(guān)痛癢。 你可選擇任何你感興趣的名字.) 示例代碼如下:
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 方法被調(diào)用, WM_CREATE 消息發(fā)送到窗口; 因此, OnCreate 方法被調(diào)用,OnCreate中包含之前討論的寄宿WebBrowser 控件的代碼。
提醒
Create
方法屬于
CWindowImpl
類,而該類是
CcomControl
的基礎(chǔ)類。
. CAtlWbHost
派生于
CComControl
,
這意味著你不如直接調(diào)用
CWindowImpl
的方法。
下一步必須調(diào)用Run 方法以創(chuàng)建和顯示窗體。 此調(diào)用將被生成于AtlWebHost.cpp 文件直接存在于你的應(yīng)用程序消息循環(huán)之上。但在Run 被調(diào)用之前, CAtlWbHost 類的實例必須被創(chuàng)建。你不可以簡單的象其他C++對象一樣簡單采用New操作符創(chuàng)建一個實例 。你必須采用CComObject 的CreateInstance 方法建立該類的實例。 在你的應(yīng)用程序的消息泵處(CAtlWebHost.cpp中), 插入如下代碼實例化CAtlWbHost 類, 然后調(diào)用 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);
如果現(xiàn)在編譯執(zhí)行, 它將可以工作了。它裝入WebBrowser 控件, 導航到wizard automatically 插入到你的應(yīng)用程序的HTML資源頁. 你可以導航到某些有實際意義的地方. 你可在 OnCreate 函數(shù)中調(diào)用GoHome 。 在你加入調(diào)用 GoHome 之后, OnCreate 函數(shù)看起來如下:
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;
}
當你編譯執(zhí)行,你的應(yīng)用程序看起來類似圖Figure 6-18.

Figure 6-18.
AtlWebHost application.
打印 Web 頁
所有打印只需要調(diào)用傳遞OLECMDID_PRINT的 ExecWB 方法。
MfcWebHost 要支持打印, 應(yīng)當建立一個ID_FILE_PRINT菜單的菜單句柄,在菜單句柄中調(diào)webbrowser的ExecWB ,以及傳遞 OLECMDID_PRINT. 你也可打印前提醒用戶, 僅需要我們多做少量代碼. 盡管如此,如果你想知道用戶是否按下OK按鈕或者取消按鈕, 檢查 ExecWB的返回值。針對打印命令, 如果用戶點幾OK以初始化打印, ExecWB 將返回S_OK。 如果用戶點擊取消, ExecWB 將返回 S_OK以外的值. (說 " S_OK以外的值" 是因為取消按鈕的返回值不具有典型代表性) 以下代碼為當用戶選擇文件菜單中打印命令時的調(diào)用情況。
void CMfcWebHostView::OnFilePrint()
{
m_webBrowser.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER,
NULL, NULL);
}
作為打印的附加功能, WebBrowser control 試圖提供打印頁設(shè)置功能.采用打印頁設(shè)置, 用戶可以改變例如頁頭頁腳等設(shè)置。要實現(xiàn)業(yè)設(shè)置功能,代碼調(diào)用 ExecWB 并且傳遞 OLECMDID_PAGESETUP. 代碼如下:
void CMfcWebHostView::OnFilePageSetup()
{
m_webBrowser.ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_PROMPTUSER,
NULL, NULL);
}
使用 Visual C++
Vc中創(chuàng)建瀏覽器應(yīng)用程序畢vb中稍微困難。如果白手起家創(chuàng)建米的宿應(yīng)用程序 (無MFC 或 ATL), 需要實現(xiàn)大量的COM接口來寄宿WebBrowser 控件。你必須還要利用COM的API CoCreateInstance 創(chuàng)建WebBrowser 控件的實例,指定 CLSID_WebBrowser a作為你想創(chuàng)建的對象的CLSID 。并且還要 將控件"site"于你的應(yīng)用程序.
因為建立ActiveX 控件容器費本文討論主題,所以著重討論簡單途徑寄宿webbrowser控件。
使用 MFC
你可以創(chuàng)建3種類型的MFC應(yīng)用程序: 單文檔接口 (SDI), 多文檔接口 (MDI), 以及基于對話框的應(yīng)用程序。因為對話框MFC類似VB,所以本處將討論采用SDI來寄宿webbrowser控件。一旦你知道如何采用SDI 應(yīng)用來寄宿webbrowser控件,轉(zhuǎn)為MDI 將會容易些。
在演示SDI的例子中,我將使用WebBrowser (CWebBrowser2) 包裝類MFC的內(nèi)置CHtmlView 類將幫助你理解如何在MFC中寄宿WebBrowser 。
CHtmlView
類無需太多解釋。要使用它,必須在MFC AppWizard第6步中選擇你的應(yīng)用程序的基類為ChtmlView, 如 Figure 6-8. 在完成 wizard后, 你的應(yīng)用程序的視圖類獎派生自 CHtmlView. 然后你可以直接調(diào)用IWebBrowser2 接口的不同方法.

Figure 6-8. MFC AppWizard - Step 6 of 6 dialog box.
為創(chuàng)建MFC 單文檔接口應(yīng)用程序,啟動Visual C++ 新建菜單。新的對話框展示如 Figure 6-9.

Figure 6-9.
Visual C++ New dialog box.
在 Projects 頁, 選擇 MFC AppWizard (exe) 項, 輸入一個項目名稱 (譬如 MfcWebHost之類), 點擊OK. MFC AppWizardis 步驟一顯示. (看 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++ 收集所有的你的系統(tǒng)中的組件和控件信息展示在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為你創(chuàng)建的WebBrowser 控件的包裝類。 因為該類特定實現(xiàn)于MFC, 所以你僅可在MFC項目中使用。點擊OK 按鈕增加CWebBrowser2 到項目中. 然后關(guān)閉陳列對話框
包含 WebBrowser2.h 在你的view 類的頭文件—MfcWebHostView.h中:
#include "WebBrowser2.h"
創(chuàng)建private 或者 protected 數(shù)據(jù)成員,命名為 m_webBrowser. 聲明如下:
protected:
CWebBrowser2 m_webBrowser;
為WM_CREATE 消息建立消息處理句柄. 在此事件處理中, 使用m_webBrowser的 Create 方法加入創(chuàng)建一個webbrowser控件的新實例。 (Create 方法是包裝類為你創(chuàng)建的.) OnCreate 消息處理代碼看起來如下:
protected:
CWebBrowser2 mint 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;
}_webBrowser;
現(xiàn)在為WM_SIZE 消息創(chuàng)建消息處理. 當應(yīng)用程序改變大小時候修改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基類的代碼在應(yīng)用程序首次創(chuàng)建時導航到用戶主頁。此處展示 OnInitialUpdate 消息處理代碼:
void CMfcWebHostView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// Navigate to the user's home page.
//
m_webBrowser.GoHome();
}
編譯且運行程序.將導航到用戶的主頁,如Figure 6-14.

Figure 6-14.
MfcWebHost application.
現(xiàn)在加入一些訪問internet的功能。 增加 Navigate包含一些Go Back, Go Forward, Go Home, Go Search, Go To A Web Page、Stop等子菜單, 你的菜單看起來類似Figure 6-15.
Figure 6-15.
Navigate menu.
現(xiàn)在你可以加入快捷健到你的菜單,例如Alt-Left 組合鍵給Go Back. 你可以使用你習慣的組合健
為每一個菜單項建立實現(xiàn)句柄。增加菜單消息處理句柄代碼是較為容易的。舉例, GoBack 方法實現(xiàn)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 ,將會發(fā)生錯誤.
Go To A Web Page 菜單項是特別情形. 對此菜單項, 一個對話框?qū)@示詢問用戶想去的URL. (見 Figure 6-16.)
Figure 6-16.
Enter A URL For Navigation dialog box.
另外的選擇,你可在工具條建立編輯框 用于導航. 在本例子中, 我選擇了對話框。當建立對話框,你可以使用ClassWizard 建立新的對話框類.命名為CAddressDlg. 對話框類應(yīng)當包含名為m_strAddress 的CString ,它將控制用戶輸入的地址。如果你的ClassWizard 創(chuàng)建此類成員,該成員將會是public的. 改變數(shù)據(jù)成員為protected, 且建立如下的訪問存取方法:
public:
const CString& GetAddress() const { return m_strAddress; }
protected:
CString m_strAddress;
現(xiàn)在建立Go To A Web Page 菜單項的消息處理句柄.該菜單句柄將建立顯示CAddressDlg 對話框. (確信 CAddressDlg 的頭文件包含在 MfcWebHostView.cpp中.) 在用戶輸入URL 且點擊OK后, 應(yīng)用程序?qū)⒗脀ebbrowser的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 類的實例被創(chuàng)建。DoModal 用于顯示對話框。如果用戶點擊OK 按鈕,應(yīng)用程序應(yīng)當檢查 URL是否合法。
使用 ATL
在過去,寄宿WebBrowser控件的ATL應(yīng)用程序項比較標準的C++沒有任何優(yōu)勢。但是現(xiàn)在,新的ATL3的ActiveX控件容器類允許你較容易創(chuàng)建宿主WebBrowser 控件的。
因為實現(xiàn)ATL用戶界面特征如菜單和工具條還是使用Win32實現(xiàn),本例我將展示其本質(zhì)上靈活的一面。我只想展示如何使用新的容器類寄宿webbrowser控件。我不準備實現(xiàn)任何用戶界面。本例子僅僅實現(xiàn)一個容納WebBrowser的框架。
用ATL建立一個WebBrowser 宿主應(yīng)用程序, 啟動0 Visual C++, 執(zhí)行以下及個步驟:
1. 新建.
2.
選擇
ATL COM AppWizard,
輸入
AtlWebHost
作為工程名
3.
點擊
OK,
選擇
Executable (EXE)
,完成。
4.
在新建工程信息對話框點擊
OK, wizard
將建立
ATL
可執(zhí)行文件工程的基本代碼。
5.
向工程中加入宿主
WebBrowser
的控件
A
。具體操作,在
ClassView
面板中右擊
AtlWebHost
類
6.
從上下文菜單中選擇
New ATL Object. ATL Object Wizard
對話框?qū)@示
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控件的關(guān)鍵代碼在OnCreate 方法的實現(xiàn)代碼中, 當 WM_CREATE 消息被發(fā)送到關(guān)聯(lián)此類的windows窗體時被調(diào)用。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對象被首先創(chuàng)建,該對象提供ActiveX 控件容器支持. 下一步, 用CAxWindow 類的CreateControl方法創(chuàng)建WebBrowser控件。注意傳遞給CreateControl 的是HTML頁的資源ID,所以當WebBrowser控件被創(chuàng)建時候HTML頁被顯示。然后SetExternalDispatch 方法被調(diào)用。該方法實現(xiàn)于IDocHostUIHandler 接口。
如果任何一個步驟都沒有錯誤發(fā)生, 代碼將用CAxWindow 的QueryControl 方法查詢 IWebBrowser2 接口.如果一切順利, QueryControl 返回IWebBrowser2 接口的指針,存儲于m_spBrowser 成員變量. 缺省情況下, wizard 將其標記為public.
提醒
作為我所認為的良好的面向?qū)ο缶幊塘晳T
,
我習慣改變
m_spBrowser
成員為
protected .
當然你可以決定是否也如此做
如果現(xiàn)在就編譯執(zhí)行代碼, 什么事情也不會發(fā)生。你必須加入創(chuàng)建和顯示窗體的代碼。要實現(xiàn),你必須首先在CAtlWbHost 類中實現(xiàn)Run方法. (該名字無關(guān)痛癢。 你可選擇任何你感興趣的名字.) 示例代碼如下:
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 方法被調(diào)用, WM_CREATE 消息發(fā)送到窗口; 因此, OnCreate 方法被調(diào)用,OnCreate中包含之前討論的寄宿WebBrowser 控件的代碼。
提醒
Create
方法屬于
CWindowImpl
類,而該類是
CcomControl
的基礎(chǔ)類。
. CAtlWbHost
派生于
CComControl
,
這意味著你不如直接調(diào)用
CWindowImpl
的方法。
下一步必須調(diào)用Run 方法以創(chuàng)建和顯示窗體。 此調(diào)用將被生成于AtlWebHost.cpp 文件直接存在于你的應(yīng)用程序消息循環(huán)之上。但在Run 被調(diào)用之前, CAtlWbHost 類的實例必須被創(chuàng)建。你不可以簡單的象其他C++對象一樣簡單采用New操作符創(chuàng)建一個實例 。你必須采用CComObject 的CreateInstance 方法建立該類的實例。 在你的應(yīng)用程序的消息泵處(CAtlWebHost.cpp中), 插入如下代碼實例化CAtlWbHost 類, 然后調(diào)用 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);
如果現(xiàn)在編譯執(zhí)行
, 它將可以工作了。它裝入WebBrowser 控件, 導航到wizard automatically 插入到你的應(yīng)用程序的HTML資源頁. 你可以導航到某些有實際意義的地方. 你可在 OnCreate 函數(shù)中調(diào)用GoHome 。 在你加入調(diào)用 GoHome 之后, OnCreate 函數(shù)看起來如下:
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;
}
當你編譯執(zhí)行,你的應(yīng)用程序看起來類似圖Figure 6-18.

Figure 6-18.
AtlWebHost application.
打印 Web 頁
所有打印只需要調(diào)用傳遞OLECMDID_PRINT的 ExecWB 方法。
MfcWebHost 要支持打印, 應(yīng)當建立一個ID_FILE_PRINT菜單的菜單句柄,在菜單句柄中調(diào)webbrowser的ExecWB ,以及傳遞 OLECMDID_PRINT. 你也可打印前提醒用戶, 僅需要我們多做少量代碼. 盡管如此,如果你想知道用戶是否按下OK按鈕或者取消按鈕, 檢查 ExecWB的返回值。針對打印命令, 如果用戶點幾OK以初始化打印, ExecWB 將返回S_OK。 如果用戶點擊取消, ExecWB 將返回 S_OK以外的值. (說 " S_OK以外的值" 是因為取消按鈕的返回值不具有典型代表性) 以下代碼為當用戶選擇文件菜單中打印命令時的調(diào)用情況。
void CMfcWebHostView::OnFilePrint()
{
m_webBrowser.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER,
NULL, NULL);
}
作為打印的附加功能, WebBrowser control 試圖提供打印頁設(shè)置功能.采用打印頁設(shè)置, 用戶可以改變例如頁頭頁腳等設(shè)置。要實現(xiàn)業(yè)設(shè)置功能,代碼調(diào)用 ExecWB 并且傳遞 OLECMDID_PAGESETUP. 代碼如下:
void CMfcWebHostView::OnFilePageSetup()
{
m_webBrowser.ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_PROMPTUSER,
NULL, NULL);
}