寄宿WebBrowser 控件
我们现在开始在VB和VC中创建一些程序来寄宿(Host)WebBrowser控件。在你完成本部分的样本,你将对如何创建寄宿一个WebBrowser控件的应用程序又一个基本的了解。当你看到如此容易的加入Web浏览功能加入到你的应用程序,我相信你会立即开始实践的。
使用VB
在VB中,你可以在5分钟内开发一个全功能的自己的web浏览 。以下步骤为建立一个web浏览器程序:
1.
启动VB.
2.
选择“
Standard EXE
“
,进入设计模式。
3.
WebBrowser
控件未自动化包含到控件工具箱(
Control Toolbox
)。
要增加
WebBrowser
控件到
控件工具箱,选择
Project
菜单下的
Components.
,如下对话将显示:
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 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++ 收集所有的你的系统中的组件和控件信息展示在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中:
#include "WebBrowser2.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 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++ 收集所有的你的系统中的组件和控件信息展示在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中:
#include "WebBrowser2.h"
创建private 或者 protected 数据成员,命名为 m_webBrowser. 声明如下:
protected:
CWebBrowser2 m_webBrowser;
为WM_CREATE 消息建立消息处理句柄. 在此事件处理中, 使用m_webBrowser的 Create 方法加入创建一个webbrowser控件的新实例。 (Create 方法是包装类为你创建的.) 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;
现在为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);
}