青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

yehao's Blog

如何對webbrowser和IE編程(九)

目錄(?)[-]

  1. 接收事件的途徑
    1. Visual Basic 中接收事件
    2. C++中接收事件
    3. 在ATL中接收事件
    4. 在 MFC中接收事件
      1. 在MFC中自動化一個COM 對象時接收事件
      2. 在MFC中寄宿 ActiveX 控件時處理事件

接收事件的途徑

依靠開發工具你創建客戶應用程序,你可以接收事件通過不同的途徑. 顯然, 在Vb中接收事件同在VC中接收事件相比是如此不同和容易.在 C++ 應用中,你可以用不同的技術,通過使用 ATL, MFC, 或者標準C++.

Visual Basic 中接收事件

Visual Basic是創建大多數類型應用的最輕松的工具, 所以我告訴你VB是處理事件最溶的工具時也不要驚奇. ATL 和 Visual Basic 示例我們同樣的工作,但是ATL花費了我4個小時, 而 Visual Basic 例子僅僅只花20 分鐘.別說我錯了—我是ATL, 和 MFC, C++的忠實信徒,  尤其是你建立一個接口的時候.但是 Visual Basic當建立客戶應用程序從類似IE這樣的服務器接收事件時是偉大的工具.

OK,如何從Visual Basic 應用程序中接收事件?當宿主WebBrowser 控件,你不必做任何特別的事. Visual Basic 在form上為WebBrowser 控件接收事件.你所需要做的全部事情就是未你要接收的任何事件創建一個事件處理句柄.

你象創建其他事件句柄一樣創建句柄 (例如Form_Load event). 從Procedure下拉列表框中選擇你象控制的句柄, 在事件句柄中,加入任何你型在事件激發時執行的任何代碼.

當自動化服務器時候接收事件, 例如在VB應用中的Internet Explorer,過程直截了當.首先設置對服務器的類型庫的引用, 你可以訪問Project/References 菜單.之后,采用WithEvents 關鍵字聲明服務器對象的變量.舉例, 如果你自動化Internet Explorer, 你將聲明變量如下:

Dim WithEvents InternetExplorer1 As InternetExplorer

下一步,采用new或者其他 關鍵字創建實例變量 ,如下::

Set InternetExplorer1 = CreateObject("InternetExplorer.Application.1")

或者:

Set InternetExplorer1 = New InternetExplorer

當你采用以上途徑生成實例接收事件, Visual Basic 自動為你初始化和管理事件接收.你不必擔心連接點問題,VB為你處理它們.

在你輸入建立服務器的代碼之后,你插入符合服務器事件的方法調用.   舉例來說, 如果你想控制由IE激活的DownloadBegin event, 你應當聲明類似如下的方法聲明:

Private Sub InternetExplorer1_DownloadBegin()
   ' Insert your best Visual Basic code here.
End Sub

當你不再想接收來自服務器的事件,簡單設置變量為Nothing:

Set InternetExplorer1 = Nothing

 

 

C++中接收事件

C++ 應用程序中接收事件比Vb中多一些工作.但如果你在MFC對話框程序中宿主過WebBrowser控件, 你可以在classwizard中選擇你想控制的事件.使用C++的其他應用程序宿主WebBrowser 或者自動化Internet Explorer 需要多一點的工作,但是仍然不需要更多的工作.在C++客戶接收事件,僅僅需要以下5個步驟:

1.    獲取連接點容器的指針 (IConnectionPointContainer).

2.       調用IconnectionPointContainer 的方法 FindConnectionPoint 找出你想接收的事件。對 Internet Explorer來講你應當為DWebBrowserEvents2 連接點接口實現事件. (作為可選你可以調用EnumConnectionPoints 以枚舉服務器支持的全部連接點)

3.       實現接入你想接收事件的連接點的通報(Advise)。 當實現通告時,傳遞一個事件接收槽的Iunknown接口的指針。 記住,事件接收槽必須實現 IDispatch 接口以接收來自WebBrowser的事件。 Advise 方法將返回一個cookie ,該Cookie在你調用Unadvise 方法的時候攜帶上。

4.       實現 IDispatch::Invoke 以控制任何激發的事件。. (開發工具如 MFC  ATL 能夠容易為你做到.)

5.       當你不再接受事件,調用Unadvise, 并且傳遞cookie.

以上步驟如果采用VB和MFC /ATL等可能不很明顯,但是當你采用標準C++創建應用程序的時候就應當很明顯了.

以下 C++ 代碼允許你在自動化IE的時候接收事件. 留意注釋代碼實現了哪一個步驟. 假定當你想連接事件時ConnectEvents 方法被調用,且當應用程序退出時候Exit 方法被調用. 同樣的,類CSomeClass 繼承自IDispatch, m_pIE 數據成員為通過CoCreateInstance 方法創建的IE的實例

void CSomeClass::ConnectEvents()
{
   IConnectionPointContainer* pCPContainer;
 

 

   // Step 1: 獲取連接點的指針.
   //
   HRESULT hr = m_pIE->QueryInterface(IID_IConnectionPointContainer, 
                                      (void**)&pCPContainer);
   if (SUCCEEDED(hr))
   {
      // m_pConnectionPoint is defined like this:
      // IConnectionPoint* m_pConnectionPoint;
 

 

      // Step 2: 選找連接點.
      //
      hr = pCPContainer->FindConnectionPoint(DIID_DWebBrowserEvents2, 
                                             &m_pConnectionPoint);
 

 

      if (SUCCEEDED(hr))
      {
         // Step 3: 實現連接點地事件接收
         //
         hr = m_pConnectionPoint->Advise(this, &m_dwCookie);
         if (FAILED(hr))
         {
            ::MessageBox(NULL, "Failed to Advise",
                         "C++ Event Sink", MB_OK);
         }
      }
 

 

      pCPContainer->Release();
   }
}
 

 

void CSomeClass::Exit()
{
   // Step 5: Unadvise. 注意m_pConnectionPoint 應當在CSomeClass的析構函數中釋放
   //
   if (m_pConnectionPoint)
   {
      HRESULT hr = m_pConnectionPoint->Unadvise(m_dwCookie);
      if (FAILED(hr))
      {
         ::MessageBox(NULL, "Failed to Unadvise",
                      "C++ Event Sink", MB_OK);
      }
   }
}

注意此處少了step4:客戶端的 IDispatch::Invoke 方法實現. 我將很快討論此點. 每一次服務器激發事件會調用此. 當事件被激發,服務器傳遞事件的DISPID 到Invoke. 對于 Internet Explorer 5, 以下DISPIDs 定義于ExDispID.h 頭文件.

·         DISPID_BEFORENAVIGATE2

  • DISPID_COMMANDSTATECHANGE
  • DISPID_DOCUMENTCOMPLETE
  • DISPID_DOWNLOADBEGIN
  • DISPID_DOWNLOADCOMPLETE
  • DISPID_NAVIGATECOMPLETE2
  • DISPID_NEWWINDOW2
  • DISPID_ONFULLSCREEN
  • DISPID_ONMENUBAR
  • DISPID_ONQUIT
  • DISPID_ONSTATUSBAR
  • DISPID_ONTHEATERMODE
  • DISPID_ONTOOLBAR
  • DISPID_ONVISIBLE
  • DISPID_PROGRESSCHANGE
  • DISPID_PROPERTYCHANGE
  • DISPID_STATUSTEXTCHANGE
  • DISPID_TITLECHANGE

現在我們返回討論Invoke. 該方法有8個參數, 但我們將僅僅討論其中的兩個: dispidMemberpDispParams. (其余的參見MSDN中的IDispatch::Invoke.)

dispidMember 參數將告訴你哪一個事件被激發.如果客戶應用程序接收來自Internet Explorer的事件, dispidMember 參數的值應當是DISPIDs 列表中的某個.

pDispParams 輸入參數是指向容器結構的指針, 存儲事件激發時的其他項. 傳遞到事件句柄的參數存儲在pDispParams->rgvarg ,逆序存放. 舉例來說, Internet Explorer 激發NavigateComplete2 事件如下所示:

NavigateComplete2(pDisp, URL)

當 Invoke 被調用, pDispParams->cArgs 將包含兩個值, URL 參數在 pDispParams->rgvarg[0]以及pDisp 參數存儲在 pDispParams->rgvarg[1]. 這些就是COM次序傳遞參數給Invoke 方法的方式.

以下為 NavigateComplete2 事件的處理.注意采用ATL的CComVariant 處理從 VARIANT到 BSTR包裝.

#include <strstrea.h>
STDMETHODIMP CSomeClass::Invoke(DISPID dispidMember,
                                REFIID riid,
                                LCID lcid, 
                                WORD wFlags,
                                DISPPARAMS* pDispParams,
                                VARIANT* pvarResult,
                                EXCEPINFO*  pExcepInfo,
                                UINT* puArgErr)
{
   USES_CONVERSION;
   strstream strEventInfo;
 

 

   if (!pDispParams)
      return E_INVALIDARG;
 

 

   switch (dispidMember)
   {
      // The parameters for this DISPID:
      // [0]: URL navigated to - VT_BYREF|VT_VARIANT
      // [1]: An object that evaluates to the top-level or frame
      //      WebBrowser object corresponding to the event. 
      //
      case DISPID_NAVIGATECOMPLETE2:
         // Check the argument's type.
         if (pDispParams->rgvarg[0].vt == (VT_BYREF|VT_VARIANT))
         {
            CComVariant varURL(*pDispParams->rgvarg[0].pvarVal);
            varURL.ChangeType(VT_BSTR);
 

 

            // strEventInfo is an object of type strstream.
            //
            strEventInfo << "NavigateComplete2: "
                         << OLE2T(vtURL.bstrVal)
                         << ends;
 

 

            ::MessageBox(NULL, strEventInfo.str(), "Invoke", MB_OK);
         }
         break;    
 

 

      default:
         break;
   }
 

 

   return S_OK;
}

在ATL中接收事件

連同實現了缺省的COM 接口實現, ATL提供了兩個函數—AtlAdvise 和 AtlUnadvise—使得任何課連接對象的事件接收簡單化.

AtlAdvise 函數告訴一個可連接對象客戶想從此可連接對象接收事件.該函數封裝實現接收事件的步驟1到3. AtlAdvise 理所當然省了大量的時間.就像IConnectionPoint::Advise 方法,AtlAdvise 返回一個cookie供你稍后調用 AtlUnadviseAtlUnadvise 告訴可連接對象客戶不再接收事件.

讓我們行說吧, 舉個例子, ATL應用程序自動化Internet Explorer, 所以你想知道任何IE激發的事件. 為了告知Internet Explorer客戶想接收事件,發出對AtlAdvise的以下調用:

HRESULT hr = AtlAdvise(m_spInetExplorer, GetUnknown(),
                       DIID_DWebBrowserEvents2, &m_dwCookie);

四個參數傳遞給AtlAdvise. 第一個參數是指向可連接對象的IUnknown 接口的指針.m_spInetExplorer 數據成員是一個經過我們自動化當前運行的Internet Explorer實例的指針. 因為m_spInetExplorer 指向的對象直接或者間接繼承自IUnknown, 編譯器自動轉換m_spInetExplorer 為當前運行的 IE實例的IUnknown 接口指針.

AtlAdvise 第二個參數必須指向提供事件的對象的IUnknown 接口. GetUnknown 函數返回此接口.記住,提供事件的類必須通過某種途徑實現 IDispatch in.在此例子中,該類繼承自 IDispatch.

第三個參數為你象接收的事件的IID, Internet Explorer 事件的可連接對象的IIS是DIID_DWebBrowserEvents2.

最后一個參數指向DWORD的指針,該DWORD接收返回的Cookie. 該 cookie 將用于調用AtlUnadvise.

客戶必須實現 IDispatch::Invoke 以控制Internet Explorer 激發的事件. 當你的應用程序完成從IE接收事件, 只需要調用 call AtlUnadvise, 如下:

HRESULT hr = AtlUnadvise(m_spInetExplorer,
                         DIID_DWebBrowserEvents2, 
                         m_dwCookie);

 

Figure 7-3. ATLIEEvtSpy.

以下展示如何自動化IE:

hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, 
                      IID_IWebBrowser2, (void**)&m_spInetExplorer);
if (SUCCEEDED(hr))
{
   m_spInetExplorer->put_Visible(TRUE);
   m_spInetExplorer->GoHome();        
 

 

接下來, AtlAdvise 調用以接收事件, 如下:

hr = AtlAdvise(m_spInetExplorer, GetUnknown(),
               DIID_DWebBrowserEvents2, &m_dwCookie);

CIEEvtObj 類繼承自IDispatch, 所以 CIEEvtObj 類可以作為事件接收對象. Invoke 實現控制事件. 每當Internet Explorer 激發一個事件, 在listBox中顯示一個消息.以西為invoke的代碼:

STDMETHODIMP CIEEvtObj::Invoke(DISPID dispidMember, 
                               REFIID riid, 
                               LCID lcid, 
                               WORD wFlags, 
                               DISPPARAMS* pDispParams, 
                               VARIANT* pvarResult,
                               EXCEPINFO* pExcepInfo,  
                               UINT* puArgErr)
{
   _ASSERT(m_spInetExplorer);
 

 

   USES_CONVERSION;
   strstream strEventInfo;
 

 

   if (!pDispParams)
      return E_INVALIDARG;
 

 

   switch (dispidMember)
   {
      //
      // The parameters for this DISPID are as follows:
      // [0]: Cancel flag  - VT_BYREF|VT_BOOL
      // [1]: HTTP headers - VT_BYREF|VT_VARIANT
      // [2]: Address of HTTP POST data  - VT_BYREF|VT_VARIANT 
      // [3]: Target frame name - VT_BYREF|VT_VARIANT 
      // [4]: Option flags - VT_BYREF|VT_VARIANT
      // [5]: URL to navigate to - VT_BYREF|VT_VARIANT
      // [6]: An object that evaluates to the top-level or frame
      //      WebBrowser object corresponding to the event 
      //
      case DISPID_BEFORENAVIGATE2:
         strEventInfo << "BeforeNavigate2: ";
 

 

         if (pDispParams->cArgs >= 5
            && pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
         {
            CComVariant vtURL(*pDispParams->rgvarg[5].pvarVal);
            vtURL.ChangeType(VT_BSTR);
 

 

            strEventInfo << OLE2T(vtURL.bstrVal);
         }
         else
            strEventInfo << "NULL";
 

 

         strEventInfo << ends;
         break;
 

 

      //
      // The parameters for this DISPID:
      // [0]: Enabled state - VT_BOOL
      // [1]: Command identifier - VT_I4
      //
      case DISPID_COMMANDSTATECHANGE:
         strEventInfo << "CommandStateChange: ";
 

 

         if (pDispParams->cArgs == 0)
            strEventInfo << "NULL";
         else
         {
            if (pDispParams->cArgs > 1 
               && pDispParams->rgvarg[1].vt == VT_I4)
            {
               strEventInfo << "Command = " 
                            << pDispParams->rgvarg[1].lVal;
            }
 

 

            if (pDispParams->rgvarg[0].vt == VT_BOOL)
            {
               strEventInfo << ", Enabled = "
                      << ((pDispParams->rgvarg[0].boolVal == VARIANT_TRUE) 
                           ? "True" : "False");
            }
         }
 

 

         strEventInfo << ends;
         break;
 

 

      case DISPID_DOCUMENTCOMPLETE:
         strEventInfo << "DocumentComplete" << ends;
         break;
 

 

      case DISPID_DOWNLOADBEGIN:
         strEventInfo << "DownloadBegin" << ends;
         break;
 

 

      case DISPID_DOWNLOADCOMPLETE:
         strEventInfo << "DownloadComplete" << ends;
         break;
 

 

      //
      // The parameters for this DISPID:
      // [0]: URL navigated to - VT_BYREF|VT_VARIANT
      // [1]: An object that evaluates to the top-level or frame
      //      WebBrowser object corresponding to the event 
      //
      case DISPID_NAVIGATECOMPLETE2:
         if (pDispParams->rgvarg[0].vt == (VT_BYREF|VT_VARIANT))
         {
            CComVariant vtURL(*pDispParams->rgvarg[0].pvarVal);
            vtURL.ChangeType(VT_BSTR);
 
            strEventInfo << "NavigateComplete2: "
                         << OLE2T(vtURL.bstrVal)
                         << ends;
         }
         break;
 

 

      //
      // The parameters for this DISPID:
      // [0]: Maximum progress - VT_I4
      // [1]: Amount of total progress - VT_I4
      //
      case DISPID_PROGRESSCHANGE:
         strEventInfo << "ProgressChange: ";
 

 

         if (pDispParams->cArgs == 0)
            strEventInfo << "NULL";
         else
         {
            if (pDispParams->cArgs > 1 
               && pDispParams->rgvarg[1].vt == VT_I4)
            {
               strEventInfo << "Progress = " 
                            << pDispParams->rgvarg[1].lVal;
            }
 

 

            if (pDispParams->rgvarg[0].vt == VT_I4)
               strEventInfo << ", ProgressMax = " 
                            << pDispParams->rgvarg[0].lVal;
         }
 

 

         strEventInfo << ends;
         break;
 

 

      //
      // The parameter for this DISPID:
      // [0]: Name of property that changed - VT_BSTR
      //
      case DISPID_PROPERTYCHANGE:
         strEventInfo << "PropertyChange: ";
 

 

         if (pDispParams->cArgs > 0 
            && pDispParams->rgvarg[0].vt == VT_BSTR)
         {
            strEventInfo << OLE2T(pDispParams->rgvarg[0].bstrVal);
         }
         else
         {
            strEventInfo << "NULL";
         }
 

 

         strEventInfo << ends;
         break;
 

 

      //
      // The parameters for this DISPID:
      // [0]: New status bar text - VT_BSTR
      //
      case DISPID_STATUSTEXTCHANGE:
         LPOLESTR lpStatusText;
 

 

         m_spInetExplorer->get_StatusText(&lpStatusText);
         strEventInfo << "StatusTextChange: ";
 

 

         if (!strcmp(OLE2T(lpStatusText), ""))
            strEventInfo << "NULL";
         else
            strEventInfo << OLE2T(lpStatusText);
 

 

         strEventInfo << ends;
         break;
 

 

      case DISPID_NEWWINDOW2:
         strEventInfo << "NewWindow2" << ends;
         break;
 

 

      //
      // The parameter for this DISPID:
      // [0]: Document title - VT_BSTR
      //
      case DISPID_TITLECHANGE:
         strEventInfo << "TitleChange: ";
 

 

         if (pDispParams->cArgs > 0 
            && pDispParams->rgvarg[0].vt == VT_BSTR)
         {
            strEventInfo << OLE2T(pDispParams->rgvarg[0].bstrVal);
         }
         else
         {
            strEventInfo << "NULL";
         }
 

 

         strEventInfo << ends;
         break;
 

 

      // The user has told Internet Explorer to close.
      //
      case DISPID_ONQUIT:
         return Stop();
 

 

      default:
         // Note: This class acts only as an event sink, so
         // there's no reason to call the base class version of Invoke.
 

 

         strEventInfo << "Unknown Event" << dispidMember << ends;
         break;
   }
 

 

   AddEventToList(strEventInfo.str());
 

 

   return S_OK;
}

請注意此使用了標準C++ 庫的 strstream 類來建立字符串.這么做是因為ATL 不提供像Cstring的類. 每一次從IE接收到事件,建立一個包含事件的名稱和參數的字符串. 然后顯示在列表框中.

退出時候調用AtlUnadvise:

STDMETHODIMP CIEEvtObj::Stop()
{
   if (m_spInetExplorer)
   {
      HRESULT hr = AtlUnadvise(m_spInetExplorer, 
                               DIID_DWebBrowserEvents2, 
                               m_dwCookie);
 

 

      if (FAILED(hr))
         ATLTRACE("Failed to Unadvise/n");
   }
 

 

   PostQuitMessage(0);
   return S_OK;
}

在 MFC中接收事件

MFC提供了數個宏使得你可以接收從自動化的對象或者宿主的控件的事件。在兩種情況中, 接收事件的類必須直接或者間接繼承自CCmdTargetCCmdTarget 實現接收事件的IDispatch 接口. 另外, 你必須在你的應用中調用EnableAutomation 初始化包含在CCmdTarget 中的IDispatch.

在MFC中自動化一個COM 對象時接收事件

在mfc中接收事件很容易.全部要做的就是在代碼中調用AfxConnectionAdvise 函數以通告連接點客戶需要接收事件.當客戶不許要接收事件,調用AfxConnectionUnadvise.  AfxConnectionAdvise AfxConnectionUnadvise 函數定義于afxctl.h 頭文件。

AfxConnectionAdvise 函數查詢連接點容器, 尋找可連接點,并且通告連接點. 函數的5個參數如下:

Table 7-3 Parameters of the AfxConnectionAdvise Function

Parameter

 

 

Description

 

 

pUnkSrc

 

 

指向激發事件的com對象的IUnknown 接口的指針pUnkSrc 是由CoCreateInstance.建立的對象的指針

 

 

pUnkSink

 

 

指向事件接收的 IUnknown 接口

 

 

iid

 

 

連接點的IID. 例如對IE來說,是DIID_DWebBrowserEvents2.

 

 

bRefCount

 

 

傳遞 TRUE 表示建立連接點將導致pUnkSink 的引用將增加。FALSE 表示不會增加.

 

 

pdwCookie

 

 

表示此連接。由AfxConnectionAdvise 將傳遞給 AfxConnectionUnadvise

 

 

 

 

 

處理事件也很容易。記住MFC事件接收類必須繼承自CCmdTargetCCmdTarget 使用派遣映射檢測當接收到事件時調用處理函數.你必須首先在頭文件中聲明派遣映射 然后再實現文件中 (.cpp) 實現. 幸運地, MFC提供了宏來幫助聲明和處理派遣映射。.

為了定義派遣映射, 首先在聲明接收事件類的頭文件中簡單定義DECLARE_DISPATCH_MAP. 這些宏聲明派遣映射和CCmdTarget 訪問的函數. 一旦你定義了派遣映射,你應當在實現文件中實現宏. 第一個宏放在BEGIN_DISPATCH_MAP 宏.它指定事件接收類的基礎類.舉例來說,如果事件類是CEventSink 繼承自 CCmdTarget, BEGIN_DISPATCH_MAP 將看起來如下:

BEGIN_DISPATCH_MAP(CEventSink, CCmdTarget)

接下來用DISP_FUNCTION_ID來聲明派遣ID。此宏的六個參數:

Table 7-4 Parameters of the DISP_FUNCTION_ID Macro

Parameter

 

 

Description

 

 

theClass

 

 

事件類的名稱

 

 

szExternalName

 

 

函數的名字.

 

 

dispid

 

 

事件的DISPID

 

 

pfnMember

 

 

指向處理事件的成員函數.

 

 

vtRetval

 

 

成員函數的返回值類型,是VARENUM 的每局類型,定義于wtypes.h 頭文件

 

 

vtsParams

 

 

空格分隔的參數類型的列表.

 

 

假設你想控制DownloadComplete 事件. 告訴CCmdTarget 你將控制處理DownloadComplete, 如下使用:

DISP_FUNCTION_ID(CIE5Events, "DownloadComplete",
                 DISPID_DOWNLOADCOMPLETE, OnDownloadComplete,
                 VT_EMPTY, VTS_NONE)

最終采用 END_DISPATCH_MAP宏關閉.完整如下:

BEGIN_DISPATCH_MAP(CEventSink, CCmdTarget)
   DISP_FUNCTION_ID(CIE5Events, "DownloadComplete",
                    DISPID_DOWNLOADCOMPLETE, OnDownloadComplete,
                    VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()

在MFC中寄宿 ActiveX 控件時處理事件

這類似于處理COM對象的事件.主要區別在于你不需要通告或者解除通告連接點. CCmdTarget 未你控制了他.

在寄宿一個Activex控件情形中, CCmdTarget 使用事件接收宏代理派遣宏.就像你猜想的一樣, MFC 提供初始化事件接收通告映射. 聲明此宏類似聲明派遣宏—派 DECLARE_EVENTSINK_MAP 宏存放在頭文件中.另外的聲明映射,  DECLARE_EVENTSINK_MAP 聲明 CCmdTarget 訪問映射的類

接下來在類中實現事件接收.開始于EGIN_EVENTSINK_MAP 宏.指定事件接收類的 和它的基類。舉例,此處為實例:

BEGIN_EVENTSINK_MAP(CMyDlg, CDialog)

現在實用ON_EVENT*宏來處理是按接收.。大多數情形,你將使用帶有5個參數的ON_EVENT.攜帶的參數如下:

ON_EVENT(CMyDlg, IDC_WEBBROWSER, DISPID_DOWNLOADCOMPLETE, 
         OnDownloadComplete, VTS_NONE)

如果你象多個成員函數處理此事件, 使用ON _EVENT_RANGE宏.

Table 7-5 Parameters of the ON_EVENT Macro

Parameter

 

 

Description

 

 

theClass

 

 

在那個類中接收事件

 

 

id

 

 

控件的資源ID

 

 

dispid

 

 

有控件激活的事件的 ID.

 

 

pfnHandler

 

 

事件的成員函數,用來處理事件句柄此函數應當有BOOL來型的返回值以及匹配事件的參數。當事件函數被處理則返回TRUE

 

 

vtsParams

 

 

 VTS_ constants 的類型

 

 

你引剛才用 END_EVENTSINK_MAP 宏.完整的定義如下:

BEGIN_EVENTSINK_MAP(CMyDlg, CDialog)
   ON_EVENT(CMyDlg, IDC_WEBBROWSER, DISPID_DOWNLOADCOMPLETE, 
            OnDownloadComplete, VTS_NONE)
END_EVENTSINK_MAP()

 

 

 

對于 DocumentComplete 事件,你應當如下聲明:

// Declare the event sink map.  This declaration goes
// in the class declaration of CMFCIEEvtSpyDlg in the 
// MFCIEEvtSpyDlg.h header file.
//
DECLARE_EVENTSINK_MAP()
 

 

// Initialize the event sink map.  These macros
// go in the implementation file _ MFCIEEvtSpyDlg.cpp.
//
BEGIN_EVENTSINK_MAP(CMFCIEEvtSpyDlg, CDialog)
   ON_EVENT(CMFCIEEvtSpyDlg, IDC_WEBBROWSER, DISPID_DOCUMENTCOMPLETE,
            OnDocumentComplete, VTS_DISPATCH VTS_PVARIANT)
END_EVENTSINK_MAP()

 

Figure 7-4. MFCIEEvtSpy.

當WebBrowser 控件基于對話框應用,你通常不需要插入默認的宏, 因為 ClassWizard 可為你做這一切.而在SDI或者MDI工程中,需要加上此宏。

現在事件接收映射已經聲明, 每當WebBrowser 控件激發了DocumentComplete 事件,OnDocumentComplete 方法將被調用.在CMFCIEEvtSpyDlg的 OnDocumentComplete 方法中, 包含URL和事件名稱的字符串被創建。之后字符串加入到列表框中展示WebBrowser 控件的事件.

以下代碼解釋如何接收處理DocumentComplete 事件.:

void CMFCIEEvtSpyDlg::OnDocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
{
   USES_CONVERSION;
 

 

   CString strEvt("DocumentComplete: ");
   strEvt += OLE2T(URL->bstrVal);
 

 

   AddEventToList(WBListBox, strEvt);
}

當啟動后,采用CoCreateInstance 創建的ie實例傳遞LSID_InternetExplorer接口..

以下為代碼:

void CMFCIEEvtSpyDlg::OnStartIE() 
{
   if (m_pInetExplorer == NULL)  // Can start only one instance
   {
      // Create an instance of Internet Explorer. 
      //
      HRESULT hr = CoCreateInstance(CLSID_InternetExplorer,
                                    NULL,
                                    CLSCTX_LOCAL_SERVER, 
                                    IID_IWebBrowser2, 
                                    (void**)&m_pInetExplorer);
      if (SUCCEEDED(hr))
      {
         // Set up the event sink.
         //
         BOOL bAdvised = AfxConnectionAdvise(m_pInetExplorer, 
                                DIID_DWebBrowserEvents2,
                                m_pIE5Events->GetInterface(&IID_IUnknown),
                                TRUE, &m_dwCookie);
 

 

         // Disable the Start IE5 button so that the 
         // user knows that only one instance of 
         // Internet Explorer can be started at a time.
         //
         m_btnStartIE.EnableWindow(FALSE);
 

 

         // Make Internet Explorer visible and go home.
         //
         m_pInetExplorer->put_Visible(VARIANT_TRUE);
         m_pInetExplorer->GoHome();
      }
   }
}

為接收Internet Explorer 的事件,你應當聲明派遣接口且在實現文中:

// Declare the dispatch map. This
// declaration is placed in the class declaration
// for the CIE5Events class, which is in the
// CIE5Events.h header file.
//
DECLARE_DISPATCH_MAP()
 

 

// Initialize the dispatch map in the
// implementation file for CIE5Events _ CIE5Events.cpp.
//
BEGIN_DISPATCH_MAP(CIE5Events, CCmdTarget)
   DISP_FUNCTION_ID(CIE5Events, "DocumentComplete", 
                    DISPID_DOCUMENTCOMPLETE, OnDocumentComplete, 
                    VT_EMPTY, VTS_DISPATCH VTS_PVARIANT)
END_DISPATCH_MAP()

現在無論如何接收到的自動化 Internet Explorer 的事件 DocumentComplete,OnDocumentComplete方法將被調用. OnDocumentComplete 方法創建一個包含事件名稱和URL的字符串,且加入到列表框通告Internet Explorer事件發生.同樣期它事件發生也會如此處理.此處為CIE5Events 類的OnDocumentComplete 方法代碼:

void CIE5Events::OnDocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
{
   USES_CONVERSION;
 

 

   CString strEvt("DocumentComplete: ");
   strEvt += OLE2T(URL->bstrVal);
 

 

   m_pParent->AddEventToList(CMFCIEEvtSpyDlg::IE5ListBox, strEvt);
}

posted on 2012-09-22 21:48 厚積薄發 閱讀(2508) 評論(0)  編輯 收藏 引用 所屬分類: Windows編程

導航

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿

隨筆分類

文章分類

文章檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产国产亚洲一二三| 亚洲激情成人网| 美女视频黄免费的久久| 欧美一区二区精品在线| 久久gogo国模裸体人体| 久久国产精品一区二区三区四区| 欧美一区二区女人| 亚洲一区二区三区在线观看视频| 亚洲丝袜av一区| 久久成人精品一区二区三区| 久久大逼视频| 欧美电影在线观看完整版| 亚洲三级影片| 亚洲男同1069视频| 美女图片一区二区| 国产精品都在这里| 136国产福利精品导航网址应用| 99ri日韩精品视频| 久久久久久久久久看片| 亚洲人成7777| 久久精品视频一| 欧美乱大交xxxxx| 国产欧美日本一区二区三区| 亚洲国产毛片完整版| 亚洲女女女同性video| 蜜桃av噜噜一区| 中文一区二区| 欧美二区在线观看| 国产一在线精品一区在线观看| 91久久黄色| 久久久噜噜噜| 亚洲视频大全| 欧美国产日韩一区| 一区二区三区在线免费观看| 亚洲无人区一区| 亚洲高清免费视频| 欧美一区二区三区在线免费观看| 欧美激情中文字幕一区二区 | 美玉足脚交一区二区三区图片| 亚洲乱码国产乱码精品精98午夜| 久久久999精品| 国产欧美日韩亚洲一区二区三区| 一区二区三区四区精品| 欧美激情bt| 久久久久久久久蜜桃| 国产午夜精品理论片a级大结局| 一本大道久久a久久精二百| 美玉足脚交一区二区三区图片| 亚洲欧美日韩国产中文在线| 欧美日韩在线一区二区| 一区二区免费在线播放| 亚洲国产日韩在线一区模特| 毛片基地黄久久久久久天堂| 影音先锋中文字幕一区| 久久男人资源视频| 久久国产乱子精品免费女| 国模私拍视频一区| 久久婷婷久久一区二区三区| 久久高清国产| 在线不卡中文字幕| 欧美激情精品久久久久| 欧美激情bt| 亚洲综合社区| 亚洲亚洲精品在线观看 | 久久免费国产精品1| 亚洲毛片播放| 欧美日韩亚洲一区二区三区在线观看 | 亚洲欧美福利一区二区| 国产精品久久久久aaaa九色| 亚洲女人小视频在线观看| 亚洲性视频网站| 国产一区二区日韩精品| 免费久久精品视频| 欧美激情一区二区三级高清视频 | 性欧美8khd高清极品| 国产亚洲一本大道中文在线| 久久一区二区三区超碰国产精品| 久久看片网站| 一区二区日韩欧美| 亚洲欧美在线x视频| 亚洲国产婷婷香蕉久久久久久99 | 国产又爽又黄的激情精品视频 | 午夜精品一区二区三区在线视| 亚洲一二三区视频在线观看| 国产亚洲免费的视频看| 欧美激情在线| 国产精品无码专区在线观看| 久久一区二区三区av| 欧美激情性爽国产精品17p| 欧美伊久线香蕉线新在线| 久久久久网址| 亚洲欧美视频| 欧美韩日高清| 久久精品国产精品亚洲综合| 欧美高清免费| 久久精品国产亚洲aⅴ| 蜜臀av性久久久久蜜臀aⅴ四虎 | 国产精品永久在线| 欧美激情91| 国产欧美日韩在线观看| 亚洲国产三级在线| 国产亚洲综合在线| 99www免费人成精品| 尹人成人综合网| 亚洲校园激情| 一区二区三区高清在线| 久久久久久久网站| 新狼窝色av性久久久久久| 欧美国产精品v| 老牛影视一区二区三区| 国产精品美女主播| 亚洲精品永久免费精品| 欧美大胆成人| 亚洲国产黄色| 亚洲女女做受ⅹxx高潮| 欧美黑人国产人伦爽爽爽| 亚洲精品久久久久久久久久久| 欧美看片网站| 亚洲欧美一区二区在线观看| 欧美**人妖| 正在播放欧美一区| 国产欧美视频一区二区| 另类图片国产| 亚洲一卡久久| 欧美激情视频在线播放 | 欧美成人精品在线播放| 9l国产精品久久久久麻豆| 国产精品午夜国产小视频| 久久免费高清| 亚洲午夜激情网站| 欧美国产另类| 欧美在线观看网站| 日韩一级视频免费观看在线| 国产亚洲成av人在线观看导航| 欧美成人亚洲成人| 欧美一区国产在线| 亚洲精品日韩久久| 久久亚洲精品一区二区| 亚洲先锋成人| 亚洲精品乱码久久久久| 国产一区二区av| 欧美午夜精品久久久久久孕妇| 久久中文久久字幕| 亚洲欧美视频在线观看| 亚洲精品久久久久久久久久久久久| 久久9热精品视频| 国产精品99久久久久久久vr| 亚洲成人影音| 国产日韩欧美一区二区| 国产精品国内视频| 欧美jjzz| 久久亚洲精品中文字幕冲田杏梨| 亚洲永久在线观看| 一区二区激情| 日韩午夜免费视频| 亚洲人成人一区二区在线观看| 久久夜色精品一区| 久久精品人人做人人爽| 亚洲综合日韩中文字幕v在线| 亚洲精品一区二区三区av| 在线观看成人一级片| 国产一区91| 国产亚洲精品久久久久婷婷瑜伽| 国产精品青草综合久久久久99 | 中文高清一区| 亚洲激情图片小说视频| 一区在线播放| 影音先锋日韩有码| 伊人久久大香线蕉av超碰演员| 国产手机视频精品| 国产欧美欧美| 国产自产高清不卡| 国产一区二区久久精品| 国产一区二区三区精品久久久 | 亚洲免费视频网站| 在线中文字幕日韩| 亚洲婷婷在线| 亚洲尤物在线| 香蕉久久国产| 国产一区二区三区成人欧美日韩在线观看| 国产精品国产成人国产三级| 欧美婷婷久久| 国产精品试看| 国产主播一区二区| 在线看欧美日韩| 亚洲激情在线观看视频免费| 亚洲韩国日本中文字幕| 亚洲精品乱码久久久久久日本蜜臀 | 亚洲激情在线激情| 99re6热只有精品免费观看| 一本久道久久综合狠狠爱| 在线视频欧美日韩| 欧美亚洲尤物久久| 麻豆国产精品777777在线| 亚洲高清在线播放| 国产精品99久久久久久久vr| 亚洲欧美日韩精品| 米奇777超碰欧美日韩亚洲| 欧美日韩在线播放一区| 国产欧美日韩一区二区三区|