开源项目CuteSqlite开发笔记(八):Windows 64位/32位使用GetWindowLongPtr钩子函数

这篇具有很好参考价值的文章主要介绍了开源项目CuteSqlite开发笔记(八):Windows 64位/32位使用GetWindowLongPtr钩子函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

需求描述

在开发CuteSqlite的时候, 有一个功能需要实现,鼠标移到WTL::CStatic上后,发送消息通知CToolTipCtrl弹出。

开源项目CuteSqlite开发笔记(八):Windows 64位/32位使用GetWindowLongPtr钩子函数,开源项目CuteSqlite,开源,笔记,windows

遇到问题

WTL::CStatic控件没有相应 WM_MOUSEMOVE 消息,需要返回一个HTCLIENT消息来让窗口处理函数执行 WM_MOUSEMOVE消息,因为控件实例的鼠标消息,比如WM_MOUSEMOVE不会发送到父窗口上,只会发送到它本身,所以我们不能在父窗口的消息映射里添加处理CStatic的WM_MOUSEMOVE消息处理函数。针对这种情况,我们可以通过钩子的方式hook掉CStatic的原窗口处理内部函数。

如果是开发win 32位的应用程序,这个时候需要用到两个32位的勾子函数:GetWindowLong和SetWindowLong。

如果是开发win 64位的应用程序,这个时候需要用到两个64位的勾子函数:GetWindowLongPtr和SetWindowLongPtr。

处理64位的上述两个函数(GetWindowLongPtr和SetWindowLongPtr)兼容32位的应用程序,微软的MSDN解释如下:

GetWindowLongPtr检索有关指定窗口的信息。 该函数还会将指定偏移量的值检索到额外的窗口内存中。

注意 若要编写与 32 位和 64 位版本的 Windows 兼容的代码,请使用  GetWindowLongPtr。 为 32 位 Windows 编译时,  GetWindowLongPtr 定义为对  GetWindowLong 函数的调用。

编译错误

**特别注意的是:**如果在64位开发环境中,还使用32位的函数GetWindowLong和SetWindowLong,会发生编译错误,类似错误如下:

1>QParamElem.cpp
1>f:\project\wtlproject\cutesqlite\cutesqlite\ui\common\param\qparamelem.cpp(288): error C2065: “GWL_WNDPROC”: 未声明的标识符
1>f:\project\wtlproject\cutesqlite\cutesqlite\ui\common\param\qparamelem.cpp(291): error C2065: “GWL_USERDATA”: 未声明的标识符
1>f:\project\wtlproject\cutesqlite\cutesqlite\ui\common\param\qparamelem.cpp(292): error C2065: “GWL_WNDPROC”: 未声明的标识符

问题原因

原因是在64位开发环境中,头文件WinUser.h对宏GWL_WNDPROC,GWL_USERDATA等的声明改成了GWLP_WNDPROC,GWLP_USERDATA

开源项目CuteSqlite开发笔记(八):Windows 64位/32位使用GetWindowLongPtr钩子函数,开源项目CuteSqlite,开源,笔记,windows

解决方案

而解决的方法,64位开发环境使用函数GetWindowLongPtr和SetWindowLongPtr,替换32位的函数GetWindowLong和SetWindowLong。

实例解释

针对上述的需求:鼠标移到WTL::CStatic上后,发送消息通知CToolTipCtrl弹出。下面我们通过代码来解释这两个函数的使用。

头文件QParamElem.h声明的变量和钩子函数:

class QParamElem: public CWindowImpl<QParamElem> {
...
    CStatic desLabel; // 需要显示tooltip的文本框

    CToolTipCtrl tooltipCtrl; // tooltip提示控件
    std::pair<WNDPROC, HWND> procWndPair; // 钩子使用的变量,保存原来CStatic消息处理函数的地址和控件句柄HWND
    WNDPROC m_pWndProc; // 原来CStatic消息处理函数的地址
...
    // 初始化和绑定tooltipCtrl提示控件
    void createAndBindToolTip();
...
    // CStatic消息替换函数
    static LRESULT funcLabelProcWnd(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam);
...
}

QParamElem.cpp实现的函数如下:

// 初始化和绑定tooltipCtrl
void QParamElem::createAndBindToolTip()
{
	if (tooltipCtrl.IsWindow() || !desLabel.IsWindow() ) {
		return;
	}
	tooltipCtrl.Create(desLabel.m_hWnd, NULL, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP);
	tooltipCtrl.AddTool(desLabel.m_hWnd, data.description.c_str());
	tooltipCtrl.Activate(TRUE);		
	
	// 拦截鼠标消息.
	m_pWndProc = (WNDPROC)::GetWindowLongPtr(desLabel.m_hWnd, GWLP_WNDPROC); // 获取原窗口处理函数
	procWndPair.first = m_pWndProc; // 这个是用户定义的类型1,不重要
	procWndPair.second = tooltipCtrl.m_hWnd; // 这个是用户定义的类型2,不重要
	::SetWindowLongPtr(desLabel.m_hWnd, GWLP_USERDATA, (LONG_PTR)&procWndPair); // 设置窗口的自定义数据,用于存储原处理函数和ToolTip句柄
	::SetWindowLongPtr(desLabel.m_hWnd, GWLP_WNDPROC, (LONG_PTR)QParamElem::funcLabelProcWnd); // 自定义一个窗口处理函数,对鼠标消息预先过滤.
}

// 钩子替换的消息处理函数
LRESULT QParamElem::funcLabelProcWnd(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	auto pp = (std::pair<WNDPROC, HWND> *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
	WNDPROC funcOld = pp->first;
	auto tooltip_hwnd = pp->second;
	if(nMsg == WM_NCHITTEST){
		// 1.static 控件没有相应 WM_MOUSEMOVE 消息,需要返回一个HTCLIENT来让窗口处理函数执行 WM_MOUSEMOVE 消息.
		// 2.就是把 WM_NCHITTEST 消息转换为 WM_MOUSEMOVE消息.
		return HTCLIENT;
	} else if(nMsg == WM_MOUSEMOVE){
		// WM_MOUSEMOVE
		// WM_NCHITTEST
		// 1.发送一格WM_MOUSEMOVE消息给tooltip控件处理.这样tooltip才会在指定位置显示.
		MSG msg = { hWnd, nMsg, wParam, lParam };
		CToolTipCtrl tip;
		tip.Attach(tooltip_hwnd);
		tip.RelayEvent(&msg);
	}
	return CallWindowProc(funcOld, hWnd, nMsg, wParam, lParam);
}

OK, 这样子就可以实现了对 CStatic消息的转换,从而实现tooltip的显示。

完整的实例源码:

GitHub:   QParamElem.h    QParamElem.cpp

Gitee:      QParamElem.h    QParamElem.cpp文章来源地址https://www.toymoban.com/news/detail-817558.html

到了这里,关于开源项目CuteSqlite开发笔记(八):Windows 64位/32位使用GetWindowLongPtr钩子函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 关于windows下的System32与SysWOW64两个文件夹

    今天编译一个简单的图形程序,编译时报错 在提示下想到需要用到windows自带的gdi32full.dll文件 想着我用的mingw64编出的是64位的程序 于是去 C:WindowsSysWOW64 目录下找到 gdi32full.dll 然后编译报  然后在这里卡了很久 各种探索尝试后发现把文件换成 C:WindowsSystem32 文件夹里面的

    2024年02月04日
    浏览(87)
  • windows10下编译32位和64位webrtc(m77)静态库

    省略挂代理下载depot_tools以及webrtc代码的过程。。。 可参考webrtc编译 务必在 cmd 终端环境下进入到 webrtcsrc 目录,再执行以下操作! 在系统环境变量下编辑PATH,将depot_tools所在路径放在PATH变量最前面。 设置环境变量 DEPOT_TOOLS_WIN_TOOLCHAIN=0 检出m77版本的webrtc m77版本对应详情:

    2024年02月03日
    浏览(45)
  • STM32基于CubeIDE和HAL库 基础入门学习笔记:物联网项目开发流程和思路

    文章目录: 第一部分:项目开始前的计划与准备 1.项目策划和开发规范  1.1 项目要求文档 1.2 技术实现文档 1.3 开发规范 2.创建项目工程与日志 第二部分:调通硬件电路与驱动程序 第三部分:编写最基础的应用程序 第四部分:完成最终要求、反复调试 第五部分:程序优化、

    2024年02月13日
    浏览(36)
  • ESP32-CAM 使用 MicroPython 进行开发 - 使用图形化工具 Thonny (Windows)

    ESP32-CAM是安信可发布小尺寸的摄像头模组。该模块可以作为最小系统独立工作,尺寸仅为2740.54.5mm。 ESP32-CAM可广泛应用于各种物联网场合,适用于家庭智能设备、工业无线控制、无线监控、人脸识别以及其它物联网应用,是物联网应用的理想解决方案。 ESP32-CAM采用DIP封装,直

    2024年02月16日
    浏览(33)
  • Linux(Ubantu)交叉编译生成windows(32位,64位)可执行程序和库

    机缘巧合下收到了这个小任务. 先是找了下资料发现过去的都是关于mingw32. 教程的做法: 增加个源 (trusty 是linux发行的版本标识,比如22.04是 jammy 更新源 下载mingw32. 结果发现在源里根本找不到 mingw32 报错 Unable to locate package mingw32 最后发现 ubantu高于15.04的版本 mingw32不可用 ,这也

    2024年01月21日
    浏览(32)
  • 一款免费、开源、可批量识别的离线OCR软件,适用于 Windows7 x64及以上平台

    免费 :本项目所有代码开源,完全免费。 方便 :解压即用,离线运行,无需网络。 高效 :自带高效率的离线OCR引擎,内置多种语言识别库。 灵活 :支持命令行、HTTP接口等外部调用方式。 功能 :截图OCR / 批量OCR / PDF识别 / 二维码 / 公式识别(测试中 ) 使用说明: 软件发

    2024年04月17日
    浏览(58)
  • 物联网开发笔记(68)- 使用Micropython开发ESP32开发板之使用官方工具esptool烧录

    一、目的         这一节我们学习如何使用我们的ESP32开发板来烧录。 二、环境         ESP32 + esptool + Win10 + python3.10 + 其他工具。 ESP32开发板购买地址: https://item.taobao.com/item.htm?spm=a1z09.2.0.0.39352e8dy0hBq0id=679204453863_u=2p01rched2a https://item.taobao.com/item.htm?spm=a1z09.2.0.0.39352e8dy0hBq0

    2024年02月05日
    浏览(35)
  • 物联网开发笔记(87)- 使用Micropython开发ESP32开发板之烧录合宙ESP32C3开发板

    一、目的         这一节我们学习如何使用我们的ESP32开发板来学习合宙ESP32C3开发板,该开发板有两种:一种是带串口通讯的,一种是通过使用USB通讯接口的。  二、环境         ESP32 + 合宙ESP32C3开发板 + USB转type-C线  + Win10 接线方法:         开发板通过USB线插到

    2024年02月14日
    浏览(33)
  • 物联网开发笔记(74)- 使用Micropython开发ESP32开发板之UART串口通信

    一、目的         这一节我们学习如何使用我们的ESP32开发板来进行串口通信,使用串口实现数据收发。 二、环境         ESP32 + USB转TTL线(3.3V) + Thonny IDE + 几根杜邦线 + Win10 接线方法:         ESP32和USB转TTL线都接在电脑USB口上,USB转TTL线的Tx接ESP32 P32,USB转TTL线

    2024年02月16日
    浏览(39)
  • 物联网开发笔记(32)- 使用Micropython开发ESP32开发板之手机扫二维码远程控制开关灯(2)

    一、目的         上一节我们测试了远程控制的环境是好的,这一节在我们的240x240的oled屏幕上显示二维码,然后用手机扫二维码,远程控制LED灯的状态。 二、环境         ESP32 + 240x240的oled彩色屏幕+ Thonny IDE + 几根杜邦线             接线方式请看上前面的章节,

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包