当前位置: 首页 > news >正文

鼠标函数VC++全局钩子实现鼠标坐标值实时捕获

最近应用开发的进程中出现了一个小问题,顺便记录一下原因和方法--鼠标函数

    自从应用.NET WinForm后已经很长时光没用VC++ MFC写进程序了,明天一问友给出一道VC++的题。

    题目:应用钩子(HOOK)实现鼠标在屏幕上移动时实时捕获以后位置坐标,并在程序对话框的文本框中实时显示。

    要求:不是仅捕获鼠标在程序窗口客户区时的坐标值,而是当鼠标移出程序窗口客户区也能捕获到鼠标在屏幕中的位置坐标。

    实现思绪:由于局部钩子只能监视本进程内的某个指定线程的事件消息,而按照此程序要求程序窗口不是活动窗口时也能监视到鼠标位置并将坐标值传给主程序的消息处理程序停止处理,所以须要应用系统钩子(全局钩子)。又由于要捕获鼠标信息,所以要用鼠标钩子,也就是在注册钩子时将类型为WH_MOUSE。该钩子要捕获WM_MOUSEMOVE消息并将消息传递给主程序的OnMouseMove()鼠标移动消息处理函数来停止处理,并将捕获的鼠标位置坐标值显示在对话框的Edit控件中。

        实现最终效果如下图,左边的图片浏览器是活动窗口,鼠标指针也在左边的窗口中,右边的程序窗口依然能获得鼠标位置并在文本框中显示坐标。

    鼠标和函数

 

    实现步调(仅列出关键代码):

    一、编写全局钩子DLL

      全局钩子必须独自的编写成dll文件。在VC++中新建一DLL项目,命名为"hook",该钩了的dll入口函数代码就不给出了。主要看钩子安装函数InstallMyHook、卸载函数UninstallMyHook以及回调函数hookproc。

    InstallMyHook钩子安装函数代码如下:

    ----------------------------------------------------------------------------------------------------------------------
__declspec(dllexport) BOOL InstallMyHook(HWND hWnd){

         //调用SetWindowsHookEx函数注册钩子,hInst是本钩子以后实例句柄,在本DLL入口函数中被赋值
     hook = SetWindowsHookEx(WH_MOUSE,(HOOKPROC)hookproc,hInst,0);           

         if(!hook){ return FALSE;}           //如果注册失败返回FALSE

         hWndMain = hWnd;            //hWndMain保存着调用此DLL的窗口句柄,是调用DLL的时候传进来的啦。
    return TRUE;        //钩子注册成功返回TRUE
} // HOOK安装函数

    ----------------------------------------------------------------------------------------------------------------------

    该段代码的主要部分是钩子注册函数SetWindowsHookEx,它的主要框架如下:

    HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,   HINSTANCE hMod, DWORD dwThreadId);

int idHook      : 要捕获消息的类型,因为我要捕获鼠标的,所以在此处设为WH_MOUSE;
HOOKPROC lpfn        :捕获消息的处理函数,就是说捕获到消息后由哪个函数去处理;
HINSTANCE hMod        : 如果是全局函数的DLL,则此参数为DLL以后实例的句柄,否则为NULL;
DWORD dwThreadId  :与安装的钩子线程相关联的线程ID,如果是全局钩子此参数设为0;
 
UninstallMyHook钩子卸载函数代码如下:
    每日一道理
只有启程,才会到达理想和目的地,只有拼搏,才会获得辉煌的成功,只有播种,才会有收获。只有追求,才会品味堂堂正正的人。

    ---------------------------------------------------------------------------------------------------------------------- __declspec(dllexport) BOOL UninstallMyHook(HWND hWnd) {  if(hWnd != hWndMain || hWnd == NULL) return FALSE;     BOOL unhooked = UnhookWindowsHookEx(hook);   //调用UnhookWindowsHookEx函数卸载钩子    if(unhooked) hWndMain = NULL;     return unhooked; } //Hook卸载函数

    ----------------------------------------------------------------------------------------------------------------------

 

hookproc钩子回调函数代码如下:
----------------------------------------------------------------------------------------------------------------------
static LRESULT CALLBACK hookproc(UINT nCode, WPARAM wParam, LPARAM lParam)
{
    if(wParam == WM_MOUSEMOVE)        //只处理WM_MOUSEMOVE消息
    {
       MOUSEHOOKSTRUCT *mhookstruct;   //鼠标HOOK结构体
       mhookstruct = (MOUSEHOOKSTRUCT*)lParam;
       POINT pt = mhookstruct->pt;
       //将以后鼠标坐标点的x,y坐标作为参数向主程序窗口发送消息

       PostMessage(hWndMain,WM_MOUSEMOVE,MK_CONTROL,MAKELPARAM(pt.x,pt.y));

   

    }
    return CallNextHookEx(hook,nCode,wParam,lParam);
}
----------------------------------------------------------------------------------------------------------------------
 

    二、编写主程序

    

(1)在主程序窗口的“启动”按钮单击事件中添加代码:
       hookState = InstallMyHook(m_hWnd)         //hookState是一BOOL型变量,保存钩子安装函数的返回值
       注:在程序退出时须要及时卸载钩了,调用UninstallMyHook(m_hWnd)就能够卸载钩子,在此不作具体说明。
(2)编

    写主程序OnMouseMove()消息处理函数代码

    :

----------------------------------------------------------------------------------------------------------------------
void mouseDlg::OnMouseMove(UINT nFlags, CPoint point) 
{
   if(hookState)    //判断钩子是否为开启状态
   {
      CString str;
      str.Format("X:%d  Y:%d", point.x, point.y);   //格式化鼠标坐标点信息并保存到CString型变量str中

      GetDlgItem(IDC_EDIT1)->SetWindowText(str);    //更新程序窗口Edit控件文本
   }
   CDialog::OnMouseMove(nFlags, point);  //调用基类MouseMove消息处理
}
----------------------------------------------------------------------------------------------------------------------
三、结束语
   至此应用全局钩子实现鼠标坐标值实时捕获实现进程说明终了。
   简单吧!就那么几步。当然,这个小程序太简单了,没有现实用途,只是明天正好在问问遇到了此问题,所以把我的解决方法贴出来了,希望对初学钩子应用的网友有点用途。

文章结束给大家分享下程序员的一些笑话语录: 一条狗在街上闲逛,看见橱窗里一张告示:「招聘程序员。会编程,有团队精神,至少精通两种语言。均等机会。」
  那条狗就进去申请,但是被拒绝了。
  「我不能雇一条狗在公司里做事。」经理说。
  狗不服气,指着告示上「均等机会」几字抗议。
  经理没法,叹了口气,不屑地问道:「你会编程吗?」
  那条狗默默地走到电脑前,编了个程序,运作准确。
  「你有团队精神吗?」经理问。
  那条狗掉头看了看门外,一大群野狗在外面虎视耽耽。
  「我真的不能雇狗做这份工作。」经理气急败坏地说。
  「就算会编程、有团队精神,但是我需要的雇员至少要能精通两种语言。」
  那条狗抬头看着经理说:「喵-噢。」

--------------------------------- 原创文章 By
鼠标和函数
---------------------------------

转载于:https://www.cnblogs.com/jiangu66/archive/2013/05/29/3106922.html

相关文章:

  • cut
  • 日志分析软件
  • cocos2d-x多分布率适配(iphone5、ipad、android)
  • 此版本的 SQL Server 不支持用户实例登录标志。该连接将关闭“的解决(转)
  • ASP.NET MVC 3.0(三): 初识MVC的Url映射潜规则Routing
  • C# 数据库删除操作错误报错 System.Data.SqlClient.SqlException (0x80131904)
  • vs2010的新特性(感悟var)
  • 动态规划方法之最长公共子序列
  • android19
  • 推荐系统的挑战(转载)
  • Android中获取IMEI码
  • Access数据库和SQL Server数据库在实际应用中的区别
  • SQL SERVER 驱动程序错误
  • Android屏蔽返回键
  • Error: member names cannot be the same as their enclosing type
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • 2017届校招提前批面试回顾
  • FineReport中如何实现自动滚屏效果
  • JS笔记四:作用域、变量(函数)提升
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • linux学习笔记
  • Odoo domain写法及运用
  • PHP CLI应用的调试原理
  • React as a UI Runtime(五、列表)
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • 阿里云Kubernetes容器服务上体验Knative
  • 力扣(LeetCode)21
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 深度学习在携程攻略社区的应用
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 使用权重正则化较少模型过拟合
  • 提醒我喝水chrome插件开发指南
  • 一份游戏开发学习路线
  • 用jQuery怎么做到前后端分离
  • 责任链模式的两种实现
  • 【干货分享】dos命令大全
  • 1.Ext JS 建立web开发工程
  • 大数据全解:定义、价值及挑战
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ${factoryList }后面有空格不影响
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (06)金属布线——为半导体注入生命的连接
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (九)One-Wire总线-DS18B20
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (十一)手动添加用户和文件的特殊权限
  • (四)linux文件内容查看