牵着老婆满街逛

严以律己,宽以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

如何对webbrowser和IE编程(四)

寄宿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 按钮。记住 GoBackGoForward 方法当前状态下无效。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_webBrowserCreate 方法加入创建一个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( 
00, 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 接口。

如果任何一个步骤都没有错误发生, 代码将用CAxWindowQueryControl 方法查询 IWebBrowser2 接口.如果一切顺利, QueryControl 返回IWebBrowser2 接口的指针,存储于m_spBrowser 成员变量. 缺省情况下, wizard 将其标记为public.

提醒


作为我所认为的良好的面向对象编程习惯 , 我习惯改变 m_spBrowser 成员为   protected . 当然你可以决定是否也如此做

如果现在就编译执行代码, 什么事情也不会发生。你必须加入创建和显示窗体的代码。要实现,你必须首先在CAtlWbHost 类中实现Run方法. (该名字无关痛痒。 你可选择任何你感兴趣的名字.) 示例代码如下:

STDMETHODIMP Run()
{
    
//
    
// Create and show the window.
    
//

    RECT rcClient 
= { CW_USEDEFAULT, 000 };

    
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, 000))
    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_PRINTExecWB 方法。

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_webBrowserCreate 方法加入创建一个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( 00, 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 接口。

如果任何一个步骤都没有错误发生, 代码将用CAxWindowQueryControl 方法查询 IWebBrowser2 接口.如果一切顺利, QueryControl 返回IWebBrowser2 接口的指针,存储于m_spBrowser 成员变量. 缺省情况下, wizard 将其标记为public.

提醒


作为我所认为的良好的面向对象编程习惯 , 我习惯改变 m_spBrowser 成员为   protected . 当然你可以决定是否也如此做

如果现在就编译执行代码, 什么事情也不会发生。你必须加入创建和显示窗体的代码。要实现,你必须首先在CAtlWbHost 类中实现Run方法. (该名字无关痛痒。 你可选择任何你感兴趣的名字.) 示例代码如下:

STDMETHODIMP Run()
{
    
//
    
// Create and show the window.
    
//

    RECT rcClient 
= { CW_USEDEFAULT, 000 };

    
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, 000))
    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_PRINTExecWB 方法。

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);
}

posted on 2006-06-23 21:42 杨粼波 阅读(7499) 评论(0)  编辑 收藏 引用 所属分类: Windows编程


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理