CHtmlView中实时获取鼠标指针位置坐标

CHtmlView中无法直接响应OnLButtonDown等一系列函数。以下方法是一种实现思路。


在前面的《CHtmlView 和 Webbrowser 控件中超链接点击事件的获取与检测》一文中演示了如何截获并响应超链接单击事件。用类似的方法还可以在 VC++ 中处理很多其他的网页事件,例如实时的在状态栏上显示鼠标正在指向的网页元素或鼠标指针相对于网页原点的位置。

这次需要响应的是 DISPID_HTMLELEMENTEVENTS2_ONMOUSEMOVE 消息,因此,Event handler 需要改成下面的样子:

// DocEvtHandler.h
// SDocEvtHandler 消息处理类声明 by 旧日重来

#pragma once
#import 

class SDocEvtHandler : public CCmdTarget
{
  DECLARE_DYNAMIC(SDocEvtHandler)
public:
  SDocEvtHandler();
  virtual ~SDocEvtHandler();

  // 消息处理函数
  void OnMouseMove(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_ONMOUSEMOVE",
  DISPID_HTMLELEMENTEVENTS2_ONMOUSEMOVE, OnMouseMove,
  VT_EMPTY, VTS_DISPATCH)
END_DISPATCH_MAP()

BEGIN_INTERFACE_MAP(SDocEvtHandler, CCmdTarget)
  INTERFACE_PART(SDocEvtHandler,
  DIID_HTMLButtonElementEvents2, Dispatch)
END_INTERFACE_MAP()

void SDocEvtHandler::OnMouseMove(MSHTML::IHTMLEventObjPtr pEvtObj)
{
  // 事件处理代码...详见下节
}

下面需要在 DocumentComplete 时安装网页事件响应函数,并在适当的时候释放,这部分与前文基本一致,详情可以猛击这里。

现在,当鼠标在网页上移动时,就会触发相应网页元素的 ONMOUSEMOVE 事件,而回调的参数就是鼠标指针正在指向的网页元素指针 IHTMLEventObj。更进一步,我们可以通过目标 IHTMLEventObj 得到当前鼠标相对于网页原点(左上角)的坐标。这里需要注意两点:

  1. 直接在 IHTMLEventObj 上得到的是鼠标相对于网页控件窗口左上角的坐标,因此需要通过窗口的滚动状态换算到整个网页的左上角
  2. 网页窗口有2个像素的 border,计算坐标时需要把它们考虑进去。

具体代码如下:

void SDocEvtHandler::OnMouseMove(MSHTML::IHTMLEventObjPtr pEvtObj)
{
  // 获取鼠标坐标
  long nOffsetX = pEvtObj->Getx();
  long nOffsetY = pEvtObj->Gety();

  // 处理 Webbrowser 控件的滚动信息
  MSHTML::IHTMLDocument3Ptr pDoc3 = m_pDocument;
  MSHTML::IHTMLElement2Ptr pDocEle = pDoc3->GetdocumentElement();
  MSHTML::IHTMLElement2Ptr pBody = m_pDocument->Getbody();
  long nScrollLeft = pDocEle->GetscrollLeft();
  long nScrollTop = pDocEle->GetscrollTop();
  if(!nScrollLeft)
    nScrollLeft = pBody->GetscrollLeft();
  if(!nScrollTop)
    nScrollTop = pBody->GetscrollTop();

  // 处理 Webbrowser 控件的边框
  nOffsetX += nScrollLeft - 2;
  nOffsetY += nScrollTop - 2;

你可能感兴趣的:(MFC基础)