牵着老婆满街逛

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

如何对webbrowser和IE编程(六)

使用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_pInetExplorerNULL 。你必须也初始化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的实例还未创建, CoCreateInstanceCLSID_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. AllocSysStringCString 的方法,返回一个Cstring对象中值的 BSTR 类型。BSTR 返回自 AllocSysString 存储于_bstr_t类型的变量, 一个 COM 编译器支持的Visual C++类。为了使用此类,你必须包含comdef.h 头文件,置于对话框实现文件CMfcAutoIEDlg—MfcAutoIEDlg.cpp. 该类将小心处理BSTR 离开当前范围的状况,所以你不需要调用SysFreeStringWin32 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 实例,测试。

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


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