CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测

在不同版本Python中安装PyQT5及PyQT5-Tools 阅读详情

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();
  }
}

pycharm+PyQt5+python最新开发环境配置,踩坑过程详解 安装工具:Pycharm 专业版2017.3PyQT5python3测试工程文件及所需工具:下载1、首先安装Pycharm,先前一篇介绍安装破解版的可以参考:http://www.roselady.vip/a/cangjingge/boke/2018/0204/685.html2、新建一个空的python工程,找到setting安装第三方模块PyQT5,点加号,先安PyQT5,再安装pyqt5-t... 阅读详情

相关推荐

python+pycharm+pyqt5安装教程

本文描述Windows系统下如何安装Python + PyCharm + PyQt5,并通过PyQt5 采用 两种方式设计GUI界面: 1.直接使用代码设计界面 2. 先使用QtDesigner进行可视化设计,然后将生成的.ui文件转换成.py文件 安装Python + PyCharm + PyQt5 1、安装Python 访问官网https://www.python.org/,下载并安装你的目标Python版本。 2、安装PyQt5 1)进入cmd界面。执行命令 pip install pyqt5 pyq

michaelbin2012的博客 1万+

C# 在 WebBrowse控件中捕获 MouseClick 或 MouseDown事件

在C#的WebBrowse控件中捕获 MouseClick 或 MouseDown事件的方法。

python3.6+PyQt5安装

1.安装好python3.6,可按照官网安装,此步骤略过,详细介绍PyQt5的安装 2.打开cmd,运行如下命令进行PyQt5的安装 pip install PyQt5 3.PyQt5安装完成后,发现没有Qt Designer.exe或者designer.exe文件,这时需要安装PyQt5-tools,打开cmd,运行如下命令安装PyQt5-tools pip install PyQt5-...

Code研究者 4854

MFC中用CHtmlView作的浏览器

本例子是用MFC制作一个自己的浏览器,通过这个例子可以对CHtmlView近一步的理解。希望对大家有些帮助!!

VC Webbrowser操作全解(一)

最近这段时间在研究Webbrowser控件,并使用Webbrowser控件实现了对某些网页自动化管理的功能,以下是对这段时间研究结果的总结: 一、Webbrowser控件详解: (1) 通过Webrowser 查找指定元素控件(IHTMLElement) (2) NewWindows3 多页面实现 需要实现多页面或者URL在同页面打开这个功能,需要在Invoke中响应DISPID_NEWWINDOW3这个消息。 二、对网页的操作 (1)...

huangxvhui88的专栏 1599

获取WebBrowser中的任一个Class或ID节点

我们知道,在Webbrowser代码中,如果有<div id="toolbar" style="position: fixed; top: 0px; left: 0px; width: 100%; z-index: 1993;"> </div>时 我们可以使用WebBrowser1.OleObject.Document.getElementByID(‘toolbar’)访问到这个IHTMLElement网页元素 随后就可以有WebBrowser1.OleObject.Docume

数据狂的专栏 1066

MFC VC判断鼠标左键点击在哪个控件并响应相关的处理

1、PreTranslateMessage函数里面 if(pMsg->message == WM_LBUTTONDOWN && pMsg->hwnd == GetDlgItem(IDC_STATIC_1)->GetSafeHwnd()) { //添加响应相关的处理 } 2、可以在OnLButtonDown里面 void XXView::OnLB...

weixin_40407666的博客 2468

python 3.10上安装pyqt5

现在,python3.10安不了 tools,小傻瓜,别一遍遍尝试了。

yfdgbfvd的博客 2万+

python安装pyqt5-tools

不同版本的python安装pyqt5-tools,解决版本号高的python出现报错问题

azhi_learn的博客 1万+

CHTMLView(简单浏览器)设计

CHTMLView(简单浏览器)设计,输入网站,访问,刷新,停止返回

C++实现WebBrowser控件获取鼠标点击事件链接

用一个基本窗口MFC程序实现WebBrowser控件对指定网页页面的加载、展示、点击事件响应,以及实现对鼠标在页面中点击标签事件的捕获,并且返回标签的超链接

PyQt5安装失败总结

最近在搞创新创业用到了GUI设计,闲来学了下qt,结果发现qt安装不了,搞了半天终于发现问题。 下面介绍一下失败经过,看看有没有小鼠我一样犯的错误。 1.正常安装流程: pyqt5安装 直接使用pip安装,但是需要SIP的支持,所以先安装SIP,再安装pyqt5 pip install sip pip install PyQt5 安装qt designer 同样使用pip安装 pip install PyQt5-tools 失败案例 于是换了一种思路,直接在pycha.

lishiyu0516的博客 1万+

PyQt5教程(二)——PyQt5的安装(详细)

上篇介绍了Python的安装:PyQt5教程(一)——Python的安装,本篇介绍PyQt 5的安装。 一、安装PyQt5: 1、方法一:使用pip命令在线安装。 输入以下命令可以直接安装: pip install PyQt5 由于安装默认使用国外的镜像,可能因为网络问题会导致下载慢或者失败的现象。所以我们可以使用国内的镜像,比如豆瓣提供的镜像。只需要加上“-i https://pyp...

ifeng12358的博客 17万+

Python GUI编程之PyQt5入门到实战

From:https://pythoneers.cn/gui/pyqt5.html 文章目录1. PyQt5基础1.1 GUI编程学什么1.2 PyQT是什么1.3 PyQT的优势1.4 开发环境的安装1.5 第一个pyqt5桌面应用2. QtDesigner的使用2.1 安装配置2.2 快速入门2.3 将ui文件转换成py文件2.4 水平布局2.5 垂直布局2.6 同时使用水平布局垂直布局2.7 栅格布局2.8 表单布局2.9 容器布局2.10 绝对布局2.11 布局中的间隔分割线2.12 控件最.

NiuXL的编程技术网络日志 3万+

关于Python安装PyQT5相关库PyQT5-tools安装失败版本不适配的问题

PyQT5-tools安装报错:ERROR: Could not find a version that satisfies the requirement pyqt5-tools (from versions: none)

GodofNight的博客 2万+
上一篇: WM消息及其lParam和wParam参数定义
下一篇: 判断多Frame网页是否真正加载完毕(CHtmlView)
codespad
博客等级 码龄14年 0粉丝 8原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值