在编程过程中,有时候需要捕获一些消息,来进行操作,钩子一共有14种,

  1. WH_CALLWNDPROC       当调用SendMessage时
  2. WH_CALLWNDPROCRET     当SendMessage的调用返回时
  3. WH_GETMESSAGE        当调用GetMessage 或 PeekMessage时
  4. WH_KEYBOARD         当调用GetMessage 或 PeekMessage 来从消息队列中查询WM_KEYUP 或 WM_KEYDOWN 消息时
  5. WH_MOUSE           当调用GetMessage 或 PeekMessage 来从消息队列中查询鼠标事件消息时
  6. WH_HARDWARE         当调用GetMessage 或 PeekMessage 来从消息队列种查询非鼠标、键盘消息时
  7. WH_MSGFILTER        当对话框、菜单或滚动条要处理一个消息时。该钩子是局部的。它是为那些有自己的消息处理过程的控件对象设计的。
  8. WH_SYSMSGFILTER      和WH_MSGFILTER一样,只不过是系统范围的
  9. WH_JOURNALRECORD     当WINDOWS从硬件队列中获得消息时
  10. WH_JOURNALPLAYBACK    当一个事件从系统的硬件输入队列中被请求时
  11. WH_SHELL           当关于WINDOWS外壳事件发生时,譬如任务条需要重画它的按钮.
  12. WH_CBT            当基于计算机的训练(CBT)事件发生时
  13. WH_FOREGROUNDIDLE    由WINDOWS自己使用,一般的应用程序很少使用
  14. WH_DEBUG           用来给钩子函数除错

下面总结使用钩子函数获取当前线程的鼠标消息WH_MOUSE和键盘消息WH_KEYBIARD,

新建一个MFC的对话框工程,主要代码如下
// HookTest1Dlg.cpp : 实现文件
//#include "stdafx.h"
#include "HookTest1.h"
#include "HookTest1Dlg.h"
#include "afxdialogex.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
CString str,str1;
int num=0;
HWND hwnd;
CDC *cdc;
HHOOK hmouse,hkeyboard;
LRESULT CALLBACK MouseProc(int ncode, WPARAM wParam,LPARAM lParam)
{str=_T("鼠标操作次数: ");num++;str1.Format(_T("%d"),num);str=str+str1;int s=str.GetLength();cdc->TextOut(50,50,str,s);return CallNextHookEx(hmouse, ncode, wParam, lParam);}
LRESULT CALLBACK KeyProc(int ncode,WPARAM wParam,LPARAM lParam)
{int s=0;
   if(wParam==VK_F10){::SendMessage(hwnd,WM_CLOSE,0,0);::UnhookWindowsHookEx(hmouse);::UnhookWindowsHookEx(hkeyboard);}else{switch(wParam){case VK_F2:str=_T("按键F2");s=str.GetLength();cdc->TextOut(50,150,str,s);break;case VK_F3:str=_T("按键F3");s=str.GetLength();cdc->TextOut(50,150,str,s);break;break;case 0x41:str=_T("按键A");s=str.GetLength();cdc->TextOut(50,150,str,s);break; case 0x42:str=_T("按键B");s=str.GetLength();cdc->TextOut(50,150,str,s);break;}return CallNextHookEx(hkeyboard, ncode, wParam, lParam);}
}
class CAboutDlg : public CDialogEx
{
public:CAboutDlg();// 对话框数据enum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()// CHookTest1Dlg 对话框CHookTest1Dlg::CHookTest1Dlg(CWnd* pParent /*=NULL*/): CDialogEx(CHookTest1Dlg::IDD, pParent)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CHookTest1Dlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CHookTest1Dlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDOK, &CHookTest1Dlg::OnBnClickedOk)
END_MESSAGE_MAP()// CHookTest1Dlg 消息处理程序BOOL CHookTest1Dlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);         // 设置大图标SetIcon(m_hIcon, FALSE);        // 设置小图标// TODO: 在此添加额外的初始化代码cdc=GetDC();hwnd=this->m_hWnd;hmouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId());hkeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyProc,NULL,GetCurrentThreadId());return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}void CHookTest1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}
}// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。void CHookTest1Dlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CHookTest1Dlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}void CHookTest1Dlg::OnBnClickedOk()
{// TODO: 在此添加控件通知处理程序代码
     CDialogEx::OnOK();

}

    

以上方法即可获得当前运行程序内的所有鼠标和键盘的消息,程序中只显示了部分按键消息,并未全部处理,然后介绍如何获取全部线程的鼠标和键盘消息。

通过上面的例子,也能发现,钩子其实主要是通过三个函数实现的
设置钩子 : HHOOK    SetWindowsHookEx( int ncode,HOOKPROC lpfn, HANDLE  hHandle,DWORD dThreadId)
释放钩子:: BOOL UnhookWindowsHookEx(HHOOK hhk)
继续钩子:   CallNextHookEx()
但是若要捕获全部线程的鼠标和键盘消息,就需要将钩子函数安装在动态链接库内,将SetWindowsHookEx 函数的第三个参数设置成动态链接库的模块句柄(可以通过DllMain函数获得,或者通过GetModuleHandle()获得),第四个线程ID设置为0;
以下为全局钩子函数的代码:
(1)首先创建一个放置钩子函数的动态链接库
hook.dll代码
// hook.cpp : 定义 DLL 应用程序的导出函数。
//#include "stdafx.h"
#include<Windows.h>HHOOK hmouse=NULL;
HHOOK hkeyboard=NULL;HWND hwnd =NULL;
LRESULT CALLBACK MouseProc(int ncode, WPARAM wParam,LPARAM lParam)
{return 1;
}
LRESULT CALLBACK KeyProc(int ncode,WPARAM wParam,LPARAM lParam)
{int s=0;if(wParam==VK_F10){::SendMessage(hwnd,WM_CLOSE,0,0);::UnhookWindowsHookEx(hmouse);::UnhookWindowsHookEx(hkeyboard);}else{switch(wParam){}return CallNextHookEx(hkeyboard, ncode, wParam, lParam);}
}void SetHookEx(HWND hWnd)
{hwnd=hWnd;hmouse=    SetWindowsHookEx(WH_MOUSE,MouseProc,GetModuleHandle(L"hook"),0);hkeyboard = SetWindowsHookEx(WH_KEYBOARD,KeyProc,GetModuleHandle(L"hook"),0);}

(2)然后在测试客户端内增加钩子函数

// hook.cpp : 定义 DLL 应用程序的导出函数。
//#include "stdafx.h"
#include<Windows.h>HHOOK hmouse=NULL;
HHOOK hkeyboard=NULL;
#pragma data_seg("MySeg")
HWND hwnd =NULL;
#pragma data_seg()#pragma comment (linker,"/section:MySec,RWS")
//将句柄设置成共享LRESULT CALLBACK MouseProc(int ncode, WPARAM wParam,LPARAM lParam)
{return 1;
}LRESULT CALLBACK KeyProc(int ncode,WPARAM wParam,LPARAM lParam)
{if(wParam==VK_F1){::SendMessage(hwnd,WM_CLOSE,0,0);::UnhookWindowsHookEx(hmouse);::UnhookWindowsHookEx(hkeyboard);}return 1;}void SetHookEx(HWND hWnd)
{hwnd=hWnd;hmouse=    SetWindowsHookEx(WH_MOUSE,MouseProc,GetModuleHandle(L"hook"),0);hkeyboard = SetWindowsHookEx(WH_KEYBOARD,KeyProc,GetModuleHandle(L"hook"),0);}

注:使用全局的钩子函数目的是调试,平时应该尽量避免使用全局钩子函数,因为全局钩子函数不仅会降低系统的性能,并且同一时间系统内还有其他应用也会使用相同钩子类型的应用,容易引起混乱。

使用钩子函数获取全部的鼠标消息和键盘消息相关推荐

  1. mounted钩子函数_怎样实现Vue中mounted钩子函数获取节点高度

    这次给大家带来怎样实现Vue中mounted钩子函数获取节点高度,实现Vue中mounted钩子函数获取节点高度的注意事项有哪些,下面就是实战案例,一起来看一下. 遇到的问题 最近在开发一个Vue的项 ...

  2. VC++ 获取窗体句柄,并发送键盘消息(这种方法也可以打开某些应用程序)

    当我们想得到一个窗口对象(CWnd的派生对象)指针的句柄(HWND)时,最安全的方法是使用GetSafeHwnd()函数,通过下面的例子来看其理由: CWnd *pwnd = FindWindow(_ ...

  3. vc鼠标消息与键盘消息

    在Microsoft Windows 中,键盘和鼠标是两个标准的用户输入源,在一些交叠的操作中通常相互补充使用.当然,鼠标在今天的应用程序中比10年前使用得更为广泛.甚至在一些应用程序中,我们更习惯于 ...

  4. mounted钩子函数_解决Vue中mounted钩子函数获取节点高度出错问题

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

  5. 用Delphi实现Windows的鼠标钩子函数

    用Delphi实现Windows的鼠标钩子函数 Delphi是基于PASCAL语言的Windows编程工具,功能十分强大.然而在Delphi的帮助 文件中,对Windows API函数的说明沿袭了 V ...

  6. 钩子函数和回调函数的区别

    一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同. 先说钩子函数: 钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦 ...

  7. Vue生命周期总结(四个阶段,八个钩子函数)

    生命周期就是组件或者实例,从创建到被销毁(初始化化数据.编译模板.挂载DOM.渲染一更新一渲染.卸载)的一系列过程,我们称这是Vue的生命周期 文章目录 一.Vue的生命周期阶段 二.生命周期钩子函数 ...

  8. java中钩子函数回调函数_钩子函数和回调函数

    一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同. 先说钩子函数: 钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦 ...

  9. 【vue】钩子函数和回调函数的区别

    一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同. 先说钩子函数: 钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦 ...

最新文章

  1. 【论文速读】基于图像的伪激光雷达三维目标检测
  2. vue实现上下滑动翻页_基于vue实现上下滑动翻页效果
  3. 一个项目中能提出哪些数据库优化_如何有效进行项目集管理?
  4. php日期提示警告,php程序报date()警告的处理的解决方法
  5. jpa的查询api_为JPA的本机查询API键入安全查询
  6. 数据结构和算法基础之冒泡排序
  7. 一步步编写操作系统 48 二进制程序的加载方式
  8. C#灰度图转伪彩色图
  9. mpu9250姿态融合算法_基于投票方式的机器人装配姿态估计
  10. 微信悄悄更新:朋友圈不喜欢的评论可以删除了
  11. Raptor码(一):2007RFC5053标准编解码学习
  12. 《生死疲劳》读书有感
  13. 风格迁移篇--StarGAN:用于多域图像到图像翻译的统一生成对抗网络
  14. QQ音乐、网易云音乐、酷狗音乐歌单导入到Spotify
  15. 中国Linux杰出人物
  16. infopath2007-2013直接连接数据源(Access或Sqlserver)设计表单模板
  17. 小白刷LeeCode(算法篇)2
  18. python qq群发消息_使用python发送QQ消息,QQ消息自动发送
  19. 论文分析---APP流量分类
  20. 2022年6月语音合成(TTS)和语音识别(ASR)论文月报

热门文章

  1. frp构建多级网络代理
  2. 解决连通性问题的利器:并查集
  3. windows下安装mongodb时报错verify that you have sufficient privileges to start system services解决方法
  4. 联想Y400怎么样在插入鼠标时自动禁用触摸板
  5. 爱码哥移动开发平台的4大开发环境
  6. python pandas创建excel,Python Pandas操做Excel表格文件:建立新表格,追加数据
  7. 支持linux浏览器,让 Linux web 浏览器支持 KDE 的 KParts 技术
  8. 【U盘被莫名分成两个盘我们该怎么合盘?】
  9. 智能车辆路径跟踪滑膜控制+单点预瞄
  10. 北大光华管理学院-宏观经济学