MFC-KeyboardProc键盘钩子函数
// InnerHookDlg.cpp: 实现文件 // #include "pch.h" #include "framework.h" #include "InnerHook.h" #include "InnerHookDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 #ifdef AFX_DESIGN_TIME enum { IDD = IDD_ABOUTBOX }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CInnerHookDlg 对话框 CInnerHookDlg::CInnerHookDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_INNERHOOK_DIALOG, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CInnerHookDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CInnerHookDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_CLOSE() ON_BN_CLICKED(IDC_BUTTON1, &CInnerHookDlg::OnBnClickedButton1) END_MESSAGE_MAP() TCHAR szkeyValue[20] = { 0 }; int t = 11; LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam,LPARAM lParam) //键盘钩子函数 //参数1:当nCode=HC_ACTION时,wParam和lParam 包含键盘信息 // 当nCode=HC_NOREMOVE时,wParam和lParam 包含键盘信息,并且键盘消息没有从消息队列里移除 // wParam 键的虚拟键代码 // lParam 击键消息标志,包含重复计数、扫描代码、扩展键标志、上下文代码、以前的键状态标志和转换状态标志 //返回值:如果参数1:nCode小于0,则必须 返回CallNextHookEx(),也就是返回CallNextHookEx()的返回值 // 如果参数1:nCode大于等于0,并且钩子处理函数没有处理消息,强烈建议您 返回CallNextHookEx()的返回值 // 如果钩子处理了消息,您可以返回一个非0值,消息就不在向下传递了 { if (nCode == HC_ACTION) { if (wParam == '1') //如果按下了1键 { AfxMessageBox(_T("按下了1键")); } if (wParam == 'A') //如果按下了A键 //注意:不能是a { t=GetKeyNameText(lParam, szkeyValue, 50); //获取按键的名称 //其实就是获取lParam中16-23位的扫描码 //参数1:指定被处理的键盘消息的lParam参数 //参数2:指向接受键名的缓冲区的指针 //参数3:nSize指定键名的最大字符长度,包括空结束符 //返回值:若函数调用成功,将拷贝一个以空结尾的字符串的指定缓冲区中,且返回值为串的长度(字符数),不计终止的空字符。若函数调用失败,返回值为o AfxMessageBox(szkeyValue); } if (wParam == VK_ESCAPE) //如果按下了ESC键 //键盘VK键值列表:看 https://www.cnblogs.com/liwenbin/archive/2012/06/30/2571489.html { AfxMessageBox(_T("按下了ESC键")); } if (wParam == VK_SHIFT) //如果按下了SHIFT键 { t = GetKeyNameText(lParam, szkeyValue, 50); AfxMessageBox(szkeyValue); AfxMessageBox(_T("按下了SHIFT键")); } } return 1; // } HHOOK hMouseHook = NULL; //定义一个钩子句柄变量--全局变量 // CInnerHookDlg 消息处理程序 BOOL CInnerHookDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != nullptr) { 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: 在此添加额外的初始化代码 //1.设置钩子 hMouseHook=SetWindowsHookEx(WH_KEYBOARD, KeyboardProc,NULL, GetCurrentThreadId()); //参数1:WH_KEYBOARD 键盘钩子 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CInnerHookDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CInnerHookDlg::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 CInnerHookDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CInnerHookDlg::OnClose() //窗口关闭消息 { if (hMouseHook != NULL) //如果钩子句柄不等于NULL { UnhookWindowsHookEx(hMouseHook);//卸载钩子 } CDialogEx::OnClose(); } void CInnerHookDlg::OnBnClickedButton1() { AfxGetMainWnd()->SendMessage(WM_CLOSE); //退出程序 }
实例工程:
链接:https://pan.baidu.com/s/1wtWpChMWAnAUBX_FoFBSQA 提取码:6666
参数lParam的说明
32位内存,内容描述包括:指定扩展键值,扫描码,上下文,重复次数
0-15位:描述:按下键盘次数
16-23位:指定扫描码【保存键盘名】 可以用GetKeyNameText函数提取
24位:
当24位为1时候:表示按键是扩展键
当24位为0时候:表示按键是是数字键盘按键
25-28位 保留位
29位 上下文键:为1时: ALT按下,其他情况为0
30位 键的先前状态,如果键在此之前就是被按下的,此位为1,如果是松开的,此位为0
31位 转换状态,当键按下时,此位为0,松开时此位为1
参数lParam第31位实例
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) //键盘钩子函数 { if (nCode == HC_ACTION) { if (wParam == 'A') //如果按下了A键 //注意:不能是a { if (lParam>0) //判断A键什么状态发出的信息 //lParam>0 表示A键按下时发出的消息;lParam<0 表示A键抬起时发出的消息 //说明:用lParam的最高位进行判断,最高位为0就是正数,最高位为1就是负数 { AfxMessageBox(_T("A键按下")); } else { AfxMessageBox(_T("A键抬起")); } } } return 1; // }
参数lParam第30位实例
BOOL b = AllocConsole(); HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); TCHAR ch[] = _T("A键处于按下状态\r\n"); int len = lstrlen(ch); TCHAR ch1[] = _T("A键处于抬起状态\r\n"); int len1 = lstrlen(ch1); LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) //键盘钩子函数 { if (wParam == 'A') //如果按下了A键 //注意:不能是a { lParam << 1; if (lParam >= 0) { WriteConsole(hStdout, ch, len, NULL, NULL);//在控制台输出 } else { WriteConsole(hStdout, ch1, len1, NULL, NULL); } } return 1; // }
实例工程下载:链接:https://pan.baidu.com/s/1vk7ZPWYHJGZhs0KqukpBTw 提取码:6666
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
2022-02-12 halcon-dev_set_part修改图像的显示区域
2022-02-12 halcon-threshold阈值分割图像
2021-02-12 Xlsx库的使用
2021-02-12 Qt操作Excel--QtXlsx
2021-02-12 Qt操作Excel--QtXlsx--编译与安装
2019-02-12 QToolBox工具箱
2019-02-12 组合框QGroupBox