利用COM的连接点机制,直接处理html元素的事件

本文介绍如何在VB和VC中屏蔽IE浏览器的右键菜单,通过处理HTMLDocument的oncontextmenu事件并返回true或false来实现。在VC中,需实现HTMLDocumentEvents2接口并通过连接点机制订阅消息。
我们先看看在VB中想屏蔽掉右键菜单是怎么做的:

 Dim WithEvents m_doc As HTMLDocument

 Private Function m_doc_oncontextmenu() As Boolean
      m_doc_oncontextmenu = False
 End Function

 Private Sub WebBrowser1_DownloadComplete()
      Set m_doc = WebBrowser1.Document
 End Sub
 
 呵呵,非常简单吧?处理HTMLDocument的oncontextmenu事件,视具体需要弹出自己的菜单,然后返回true或false就可以了。
 同理,我们在VC中如果能响应html页面元素对象的事件并做出处理的话也可以达到屏蔽右键菜单的目的了,在VB中响应COM的事件被封装起来,用一个WithEvents关键字就轻松搞定,在VC中怎么实现??
 我们知道COM是通过连接点机制来实现事件的,VC中你得在程序中实现一个特定的接口,并把这个接口的指针通过一定的途径传送给COM对象并通知它需要订阅该对象的消息。

 下面通过处理HTMLDocument2的oncontextmenu事件来演示具体怎么在MFC程序中实现屏蔽掉右键菜单,同理你可以处理其它的像DIV,Button等元素的事件来制定相应的右键菜单。
 通过查阅MSDN,可以知道要响应HTMLDocument2的事件必须在程序中实现HTMLDocumentEvents2接口,这个接口是Dispinterface类型的,而在MFC想实现一个IDispatch接口就简单的就是从CCmdTarget类派生一个新类并用DECLARE_DISPATCH_MAP,BEGIN_DISPATCH_MAP,DISP_FUNCTION_ID,END_DISPATCH_MAP等宏来添加接口函数,由于CHtmlView或是CDialog都是间接派生自CCmdTarget的,所以直接在这些类上实现这个接口就可以了,以对话框加IE控件为例(稍微改动可用于CHtmlView),实现如下:

 1.新建基于对话框工程命名为HtmlDemoDialog,在主对话框中加入Microsoft Web Browser控件并生成包装类等。
 2.在主对话框类头文件CHtmlDemoDialogDlg.h中加入
  #include <MsHTML.h>//定义了IHTMLDocument2等接口
  #include <mshtmdid.h>//定义了HTMLDocumentEvents2接口的方法DISPID
 
  class CCHtmlDemoDialogDlg : public CDialog
  {
  ...
   DECLARE_DISPATCH_MAP()//声明dispatch map表
   
  public:
   BOOL onHtmlContextMenu(IHTMLEventObj *pEvtObj);
   //事件处理函数,原型可以参考MSDN中关于HTMLDocumentEvents2的说明
   DWORD m_dwCookie;
   //用于标记一个连接点
   IHTMLDocument2* pDoc2;
   //想要处理事件的COM对象的指针
  ...
  }
 2.在对话框类实现文件CHtmlDemoDialogDlg.cpp中加入
  #include <afxctl.h>//定义了AfxConnectionAdvise、AfxConnectionUnadvise等函数,等会连接到事件源时要用到
  ...
  //填充dispatch map表,以供Invoke()调用
  BEGIN_DISPATCH_MAP(CCHtmlDemoDialogDlg, CDialog)
   DISP_FUNCTION_ID(CCHtmlDemoDialogDlg, "oncontextmenu", DISPID_HTMLDOCUMENTEVENTS2_ONCONTEXTMENU, onHtmlContextMenu, VT_BOOL, VTS_DISPATCH)
  END_DISPATCH_MAP()
  ...

  CWebbrowserDlg::CWebbrowserDlg(CWnd* pParent /*=NULL*/)
  : CDialog(CWebbrowserDlg::IDD, pParent)
  {
   EnableAutomation();//必须有,否则等会用GetIDispatch()时会失败.
   ...
  }

  BOOL CCHtmlDemoDialogDlg::onHtmlContextMenu(IHTMLEventObj *pEvtObj)
  { 
   //在成功连接上事件源后,每次用户右击都会调用这个函数,你可以根据pEvtObj来判断当前光标位置等,然后决定是自己弹出菜单,让IE弹出菜单,还是什么都不做...
   return FALSE;
  }

  void CCHtmlDemoDialogDlg::OnDocumentCompleteExplorer1(LPDISPATCH pDisp, VARIANT FAR* URL) 
  {
   //处理WebBrowser控件的DocumentComplete事件,并初始化pDoc2指针和连接到事件源
   HRESULT hr=m_wb.GetDocument()->QueryInterface(IID_IHTMLDocument2,(void**)&pDoc2);
   BOOL Ret = AfxConnectionAdvise( 
    pDoc2,  //可连接对象的接口指针
    DIID_HTMLDocumentEvents2, //连接接口ID
    GetIDispatch(FALSE), //把内嵌的IDispatch实现类的一个对象实例m_xDispatch传了出去
    FALSE,   //donod addref
    &m_dwCookie );  //cookie to break connection later...
   if(Ret){
    AfxMessageBox("成功挂接上");
   }
  }
 3.到这里,基本步骤都以完成,运行后如果没有什么灾难发生的话可以看到"成功挂接上"的消息框,并且在IE控件中点击右键不会弹出菜单,断开事件连接的代码如下:
  AfxConnectionUnadvise(pDoc2, 
          DIID_HTMLDocumentEvents2 , 
          GetIDispatch(FALSE),  
          FALSE, 
          m_dwCookie );
其余的善后工作交给你去处理了.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值