CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测
来源:互联网 发布:剑灵人女捏脸数据下载 编辑:程序博客网 时间:2024/05/21 21:50
本文转自:http://live.aulddays.com/tech/08/chtmlviewlinkclick/
在自己的程序中使用 CHtmlView 或直接嵌入 Webbrowser 控件显示网页时,常常需要获取网页元素的一些事件,以实现对网页显示的控制或与网页元素进行交互。最常见的莫过于获取用户对网页上超链接的所有点击事件。要实现这个需求,在MSDN 中描述了接收网页元素事件的基本方法,但这篇文章的一些细节语焉不详,让人摸不着头脑。在CodeProject 这篇文章中提出了一种替代的方法,但是存在一些小的限制。本文详细演示了如何实现在 CHtmlView 中监视链接点击的方法。
为了实现监视所有的链接点击而不是特定的超链接,第一步需要在 CHtmlView 的 IHTMLDocument 上安装全局的 EventHandler 以接收 DISPID_HTMLELEMENTEVENTS2_ONCLICK(或 DISPID_HTMLDOCUMENTEVENTS2_ONCLICK)鼠标点击事件;接下来在事件处理代码中判断是否是在超链接上发生。在处理事件响应函数的安装和卸载时要格外小心,重复安装可能导致重复接收到消息甚至程序崩溃,而忘记卸载则会导致 COM 资源泄漏。
接收网页事件
要响应网页事件,需要实现 IDispatch 接口,并在其 Invoke() 方法中处理接收到的消息。对于 MFC,因为 CCmdTarget 类已经实现了 IDispatch 接口,因此继承 CCmdTarget 并结合相关宏可以较简单的处理消息。代码如下:
// DocEvtHandler.h// SDocEvtHandler 消息处理类声明 by 旧日重来#pragma once#import <mshtml.tlb>class SDocEvtHandler : public CCmdTarget{ DECLARE_DYNAMIC(SDocEvtHandler)public: SDocEvtHandler(); virtual ~SDocEvtHandler(); // 消息处理函数 void OnClick(MSHTML::IHTMLEventObjPtr pEvtObj); DECLARE_MESSAGE_MAP() DECLARE_DISPATCH_MAP() DECLARE_INTERFACE_MAP()};// DocEvtHandler.cpp// SDocEvtHandler 消息处理类实现 by 旧日重来#include "stdafx.h"#include "DocEvtHandler.h"#include "mshtmdid.h"IMPLEMENT_DYNAMIC(SDocEvtHandler, CCmdTarget)SDocEvtHandler::SDocEvtHandler(){ EnableAutomation(); // 重要:激活 IDispatch}SDocEvtHandler::~SDocEvtHandler(){}BEGIN_MESSAGE_MAP(SDocEvtHandler, CCmdTarget)END_MESSAGE_MAP()BEGIN_DISPATCH_MAP(SDocEvtHandler, CCmdTarget) DISP_FUNCTION_ID(SDocEvtHandler,"HTMLELEMENTEVENTS2_ONCLICK", DISPID_HTMLELEMENTEVENTS2_ONCLICK, OnClick, VT_EMPTY, VTS_DISPATCH)END_DISPATCH_MAP()BEGIN_INTERFACE_MAP(SDocEvtHandler, CCmdTarget) INTERFACE_PART(SDocEvtHandler, DIID_HTMLButtonElementEvents2, Dispatch)END_INTERFACE_MAP()void SDocEvtHandler::OnClick(MSHTML::IHTMLEventObjPtr pEvtObj){ // 鼠标点击处理代码...详见下节}
接下来,在 DocumentComplete 事件中安装事件处理响应函数:
// 事件响应函数的管理 by 旧日重来///////////////////// .h //////////////////////class SWebpageView : public CHtmlView{ // 其他代码... SDocEvtHandler *m_pEventHandler; DWORD m_dwDocCookie; // 用于卸载事件响应函数 IDispatch *m_pDispDoc; // 用于卸载事件响应函数};//////////////////// .cpp ////////////////////SWebpageView::SWebpageView(): m_dwDocCookie(0), m_pDispDoc(NULL){ m_pEventHandler = new SDocEvtHandler;}// 安装响应函数。省略了一些失败判断以突出主要步骤void SWebpageView::InstallEventHandler(){ if(m_dwDocCookie) // 已安装,卸载先。最后一次安装的才有效 UninstallEventHandler(); m_pDispDoc = GetHtmlDocument(); IConnectionPointContainerPtr pCPC = m_pDispDoc; IConnectionPointPtr pCP; // 找到安装点 pCPC->FindConnectionPoint(DIID_HTMLDocumentEvents2, &pCP); IUnknown* pUnk = m_pEventHandler->GetInterface(&IID_IUnknown); //安装 HRESULT hr = pCP->Advise(pUnk, &m_dwDocCookie); if(!SUCCEEDED(hr)) // 安装失败 m_dwDocCookie = 0;}// 卸载响应函数。省略了一些失败判断以突出主要步骤void SWebpageView::UninstallEventHandler(){ if(0 == m_dwDocCookie) return; IConnectionPointContainerPtr pCPC = m_pDispDoc; IConnectionPointPtr pCP; pCPC->FindConnectionPoint(DIID_HTMLDocumentEvents2, &pCP); hr = pCP->Unadvise(m_dwDocCookie);}// 在 DocumentComplete 事件中安装响应函数void SWebpageView::OnDocumentComplete(LPCTSTR lpszURL){ // 其他代码... InstallEventHandler();}// 在 BeforeNavigate2 和 Destroy 事件中卸载响应函数void SWebpageView::OnBeforeNavigate2(/* ... */){ UninstallEventHandler(); // 其他代码...}void SWebpageView::OnDestroy(){ UninstallEventHandler(); CHtmlView::OnDestroy();}
在正确安装了事件响应函数之后,就可以接收网页事件了。
检测超链接点击事件
测超链接点击事件全局事件处理接口成功安装后,当 Webbrowser 控件中有相应的事件发生,则会自动调用事件响应函数。在上面的情况下,会接收到网页中所有的鼠标点击事件,因此我们需要判断用户是否是点击超链接对象。因为超链接内部可能还包含有子结构,例如图像,因此鼠标点击事件不一定直接发生在超链接对象,因此需要根据事件发生的对象逐级向上检查,代码如下:
void SDocEvtHandler::OnClick(MSHTML::IHTMLEventObjPtr pEvtObj){ MSHTML::IHTMLElementPtr pElement = pEvtObj->GetsrcElement(); // 事件发生的对象元素 while(pElement) // 逐层向上检查 { _bstr_t strTagname; pElement->get_tagName(&strTagname.GetBSTR()); if(_bstr_t("a") == strTagname || _bstr_t("A") == strTagname) { // 已找到 "a" 标签,在这里写相应代码 // 例1:取得目标地址: _variant_t vHref = pElement->getAttribute("href", 0); // 例2:取消点击,禁止转到目标页面 pEvtObj->put_returnValue(_variant_t(VARIANT_FALSE, VT_BOOL)); break; } pElement = pElement->GetparentElement(); }}
- CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测
- CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测
- CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测
- CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测
- CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测
- CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测
- C++实现WebBrowser控件中对鼠标点击事件的监听,并获取所点击标签的超链接
- webbrowser控制新窗口(点击超链接事件)
- Webbrowser的点击事件重复发生与点击链接下载
- 在WebBrowser控件中获取鼠标在网页上点击的位置
- WebBrowser控件的事件
- jQuery中关于超链接click点击事件的注意点
- 点击事件中获取点击的坐标
- listview或gridview中item的点击事件与控件点击事件冲突的解决
- C#点击打开webbrowser中网页中的超链接
- ListView中控件点击事件与Item点击事件冲突的问题
- 关于ListView中控件点击事件与Item点击事件冲突的问题
- 关于ListView中控件点击事件与Item点击事件冲突的问题
- uva 1382 - Distant Galaxy
- (转)Android中ListView分页加载数据
- MySQL 数据类型
- ERROR: libstagefright_h264 not found
- 判断客户端是否是手机
- CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测
- ASA、交换机、主机设备抓包
- 开发小技巧:jQuery处理自适应内容高度的iframe
- php计算月份差
- android开发环境配置
- 在列表中添加值后,无法检索出来
- 关于cisco日志的配置
- Java基于XML+FreeMarker导出Word
- 从摄像头获得图片并存储感兴趣区变化大的图片