牵着老婆满街逛

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

如何对webbrowser和IE编程(十一)

仅仅用于Internet Explorer的事件

有些是仅仅可用于自动化 Internet Explorer,:

·         OnQuit

  • OnVisible
  • OnToolBar
  • OnMenuBar
  • OnStatusBar
  • OnFullScreen
  • OnTheaterMode

大多数这些事件属于浏览器用户接口. 另外一些必须要先是或者关闭Internet Explorer才发生. 一些情形中,这些事件将在你宿主webbrowser空间的时候发生. 举例来讲,当你在你的应用程序设置MenuBar 属性,尽管你的WebBrowser control 并没有菜单条, OnMenuBar 事件将被激发, 但是如果你显示或者隐藏你的应用程序菜单条,OnMenuBar 事件不会激发.为什么?因为你的菜单条由你控制,webbrowser对这些用户接口项一无所知. 很长时间以来,这些相互矛盾的功能是一些混乱的根源。

其中一个事件OnQuit—将永远不会在你的应用程序中激发.举个例子, 察看表 Table 7-6. 注意到OnQuit 事件当用户关闭 Internet Explorer 或者当Quit 方法被调用时激发.如果你宿主改控件且用户关闭你的应用程序,  OnQuit 事件不会激发.它仅仅在你自动化Internet Explorer 且用户手动关闭浏览器时候发生.另外,如果你在宿主一个webbrowser控件时试图调用Quit 方法,一个自动化错误将会发生.

ActiveX控件中控制Internet Explorer 事件

通过 IWebBrowser2 接口你可以在利用vc++在ActiveX 控件中接受事件.

你可能疑惑为什么要在ActiveX控件中接受 Internet Explorer事件.之前介绍"DocumentComplete," 事件时候,我提到过你不可以在DocumentComplete event 事件被触发前安全存取文档.在Activex控件中获知DocumentComplete 事件被触发的途径是ActiveX 控件接收 Internet Explorer并处理 DocumentComplete 事件.

除了你必须接收Internet Explorer 事件外, 你可以开发一个可导航的类浏览器的应用于公司intranet或者学校网络.你可以在ActiveX control中自动化Internet Explorer并接受其事件。.

当你刷新一个页面 , 也许 DocumentComplete 事件并不激发 . DocumentComplete 事件并未触发 ,  ProgressChange 事件被用来控制以检测某页是否完成加载 . 载一个简单的 web 页或者没有嵌入帧时 ProgressChange 工作的很好 .

记住 ProgressChange 右两个参数告诉你下载操作的进度.第一个参数当下在完成时候设定为-1, 者可以帮助你检测是否可做类打印等操作

让我们学习一个打印控active控件,为从Internet Explorer接收事件,你必须设置事件接收,意味着你必须通过IWebBrowser2  接口以获得实现,如下实现:

												
														protected:
												
										
												
														
																
																		   CComPtr<IWebBrowser2> m_spWebBrowser;
														
												
										

.

接下来覆盖IOleObjectImpl 的SetClientSite方法的实现. SetClientSite 放方法是在Internet Explorer通知气客户区的控件的时候被调用.你可用客户区的site指针 (m_spClientSite) 存取容器并且得到IWebBrowser2 接口指针. 在SetClientSite 实现中, 你必须首先调用其基类版本,就想如下:

												
														IOleObjectImpl<CPrintCtl>::SetClientSite(pClientSite);
												
										

这些带吗看起来可能有些生疏, 但记住 IOleObjectImpl 是一个模版类. 为了调用它的方法, 你必须制定要求的模版参数以指示编译器哪一个类实例在调用SetClientSite 方法时被使用. 现在讲残存的访问容器和IWebBrowser2接口指针的代码从Print方法迁移到SetClientSite 方法Now move the remaining code Print 方法将看起来如下:

												
														STDMETHODIMP CPrintCtl::Print()
												
										
												
														{
												
										
												
														
																
																		   ATLASSERT(m_spWebBrowser);
														
												
										
												
														
																 

												
														
																
																		   HRESULT hr = E_FAIL;
														
												
										
												
														
																 

												
														
																
																		   if (m_spWebBrowser)
														
												
										
												
														
																
																		   {
														
												
										
												
														
																
																		      hr = m_spWebBrowser->ExecWB(OLECMDID_PRINT, 
														
												
										
												
														
																
																		                         
																		         OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
														
												
										
												
														
																
																		   }
														
												
										
												
														
																 

												
														
																
																		   return hr;
														
												
										
												
														}
												
										

SetClientSite 方法将接收事件,SetClientSite 讲看起来如下:

注意


你不能够再 FinalConstruct m 方法中接收事件因为此时客户站点还未设定。

												
														STDMETHODIMP CPrintCtl::SetClientSite(IOleClientSite* pClientSite)
												
										
												
														{
												
										
												
														
																
																		   HRESULT hr = IOleObjectImpl<CPrintCtl>::SetClientSite(pClientSite);
														
												
										
												
														
																 

												
														
																
																		   if (!pClientSite)
														
												
										
												
														
																
																		   {
														
												
										
												
														
																
																		      return hr;
														
												
										
												
														
																
																		   }
														
												
										
												
														
																 

												
														
																
																		   CComPtr<IOleContainer> spContainer;
														
												
										
												
														
																
																		   m_spClientSite->GetContainer(&spContainer);
														
												
										
												
														
																 

												
														
																
																		   ATLASSERT(spContainer);
														
												
										
												
														
																 

												
														
																
																		   if (SUCCEEDED(hr))
														
												
										
												
														
																
																		   {
														
												
										
												
														
																
																		      // Set up the event sink.
														
												
										
												
														
																
																		      //
														
												
										
												
														
																
																		      CComQIPtr<IServiceProvider, &IID_IServiceProvider>
														
												
										
												
														
																
																		         spServiceProvider(spContainer);
														
												
										
												
														
																 

												
														
																
																		      ATLASSERT(spServiceProvider);
														
												
										
												
														
																 

												
														
																
																		      if (spServiceProvider)
														
												
										
												
														
																
																		      {
														
												
										
												
														
																
																		         spServiceProvider->QueryService(SID_SInternetExplorer,
														
												
										
												
														
																
																		                                         IID_IWebBrowser2,
														
												
										
												
														
																
																		                                         (void**)&m_spWebBrowser);
														
												
										
												
														
																
																		         ATLASSERT(m_spWebBrowser);
														
												
										
												
														
																 

												
														
																
																		         if (m_spWebBrowser)
														
												
										
												
														
																
																		         {
														
												
										
												
														
																
																		            AtlAdvise(m_spWebBrowser, GetUnknown(),
														
												
										
												
														
																
																		                      DIID_DWebBrowserEvents2, &m_dwCookie);
														
												
										
												
														
																
																		         }
														
												
										
												
														
																
																		      }
														
												
										
												
														
																
																		   }
														
												
										
												
														
																 

												
														
																
																		   return hr;
														
												
										
												
														}
												
										

注意到在AtlAdvise 调用时你必须建立protected 或者private DWORD的数据成员以掌握返回自AtlAdvise 方法的cookie. CprintCtl 类的构造函数初始化改成员为0.尽管我们注意到CPrintCtl::SetClientSite 方法使用IOleObjectImpl::SetClientSite 方法的返回值. 此方法并不检查已被调用的返回值因为CPrintCtl::SetClientSi将 反射客户站点的设定状态.

最好, 我们检查pClientSite 的返回值,输入参数是NULL. 如果这样,我们当Internet Explorer 卸载这些控时, 他调用SetClientSite w设置为NULL. 或者告诉你已经从站点解除, 所以包含一个接口, IWebBrowser2 容器不需要一定执行。.

因为当你完成任务时应当关闭任务的站点, 也包含某个控件被卸载时。检查pClientSite 是否为NULL,以便放置AtlUnadvise 方法. 记住pClientSite在控件被卸载时为 NULL. 看起来如下:

												
														if (!pClientSite)
												
										
												
														{
												
										
												
														
																
																		   ATLASSERT(m_spWebBrowser);
														
												
										
												
														
																 

												
														
																
																		   if (m_spWebBrowser)
														
												
										
												
														
																
																		      AtlUnadvise(m_spWebBrowser, DIID_DWebBrowserEvents2, m_dwCookie);
														
												
										
												
														
																 

												
														
																
																		   return hr;
														
												
										
												
														}
												
										

现在你可以使用AtlAdvise接收事件,让我们控制事件.为此你必须覆盖重写IDispatchImpl 的Invoke 方法. 典型的,你将为你的时间建立一个单独的类因为 Internet Explorer 事件的DISPIDs 必须同你的控件的DISPIDs 不同.但在此你可以简单在 CPrintCtl  类中来实现.实现Invoke (入代码所示)以控制ProgressChange 事件.在事件句柄, 如果progres的总数设定为 -1,设定一个标志变量指示已被打印.

 

												
														STDMETHODIMP CPrintCtl::Invoke(DISPID dispidMember, 
												
										
												
														
																
																		                               REFIID riid, 
														
												
										
												
														
																
																		                               LCID lcid,
														
												
										
												
														
																
																		                               WORD wFlags, 
														
												
										
												
														
																
																		                               DISPPARAMS* pDispParams, 
														
												
										
												
														
																
																		                               VARIANT* pvarResult, 
														
												
										
												
														
																
																		                               EXCEPINFO* pExcepInfo,
														
												
										
												
														
																
																		                               UINT* puArgErr)
														
												
										
												
														{
												
										
												
														
																
																		   if (riid != IID_NULL)
														
												
										
												
														
																
																		      return DISP_E_UNKNOWNINTERFACE;
														
												
										
												
														
																 

												
														
																
																		   if (!pDispParams)
														
												
										
												
														
																
																		      return DISP_E_PARAMNOTOPTIONAL;
														
												
										
												
														
																 

												
														
																
																		   switch (dispidMember)
														
												
										
												
														
																
																		   {
														
												
										
												
														
																
																		      //
														
												
										
												
														
																
																		      // The parameters for this DISPID:
														
												
										
												
														
																
																		      // [0]: Maximum progress - VT_I4
														
												
										
												
														
																     // [1]: Amount of total progress - VT_I4
												
										
												
														
																
																		      //
														
												
										
												
														
																
																		      case DISPID_PROGRESSCHANGE:
														
												
										
												
														
																
																		         if (pDispParams->cArgs != 0)
														
												
										
												
														
																
																		         {
														
												
										
												
														
																
																		            // Make sure that you access the
														
												
										
												
														
																
																		            // correct data member of the rgvarg array.
														
												
										
												
														
																
																		            // To do this, check the type of data to
														
												
										
												
														
																
																		            // make sure it is correct.
														
												
										
												
														
																
																		            //
														
												
										
												
														
																
																		            if (pDispParams->cArgs > 1
														
												
										
												
														
																
																		               && pDispParams->rgvarg[1].vt == VT_I4
														
												
										
												
														
																
																		               && pDispParams->rgvarg[0].vt == VT_I4)
														
												
										
												
														
																
																		            {
														
												
										
												
														
																
																		     
																		          if (-1 == pDispParams->rgvarg[1].lVal)
														
												
										
												
														
																
																		                  m_fCanBePrinted = TRUE;
														
												
										
												
														
																
																		            }
														
												
										
												
														
																
																		         }
														
												
										
												
														
																 

												
														
																
																		         break;
														
												
										
												
														
																 

												
														
																
																		      default:
														
												
										
												
														
																
																		         // Call the base class implementation of Invoke
														
												
										
												
														
																
																		         // so that IPrintCtl methods and properties will
														
												
										
												
														
																
																		         // work correctly.
														
												
										
												
														
																
																		         //
														
												
										
												
														
																
																		         IDispatchImpl<IPrintCtl, &IID_IPrintCtl, 
														
												
										
												
														
																
																		            &LIBID_ATLPRINTLib>::Invoke(dispidMember, riid, lcid,
														
												
										
												
														
																
																		                                        wFlags, pDispParams,
														
												
										
												
														
																
																		                              
																		          pvarResult, pExcepInfo, puArgErr);
														
												
										
												
														
																 

												
														
																
																		         break;
														
												
										
												
														
																
																		   }
														
												
										
												
														
																 

												
														
																
																		   return S_OK;
														
												
										
												
														}
												
										

ProgressChange 事件处理中,当Progress 参数(pDispParams->rgvarg[1].lVal) 是-1, 我们设置一个变量告诉控件问打光在完成可以打印. FCanBePrinted 就是我们要设定的变量。

现在当用户试图调用Print 方法打印文档,你可以检查变量以确定是否可打印. 此处为 Print 方法的代码:

												
														STDMETHODIMP CPrintCtl::Print()
												
										
												
														{
												
										
												
														
																
																		   if (!m_fCanBePrinted)
														
												
										
												
														
																
																		   {
														
												
										
												
														
																
																		      ::MessageBox(NULL, _T("The page is not ready to be printed."),
														
												
										
												
														
																
																		                   _T("PrintCtl"), MB_OK);
														
												
										
												
														
																
																		      return E_FAIL;
														
												
										
												
														
																
																		   }
														
												
										
												
														
																 

												
														
																
																		   ATLASSERT(m_spWebBrowser);
														
												
										
												
														
																 

												
														
																
																		   HRESULT hr = E_FAIL;
														
												
										
												
														
																 

												
														
																
																		   if (m_spWebBrowser)
														
												
										
												
														
																
																		   {
														
												
										
												
														
																
																		      hr = m_spWebBrowser->ExecWB(OLECMDID_PRINT, 
														
												
										
												
														
																
																		                                  OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
														
												
										
												
														
																
																		   }
														
												
										
												
														
																 

												
														
																
																		   return hr;
														
												
										
												
														}
												
										

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


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