赞
踩
众所周知,Windows应用程序都是消息(事件)驱动的,任何一个窗口都能够接收消息,并对消息进行处理,处理完成后进入下一轮循环。
通常情况下,程序员可以在窗口过程中处理接收到的消息,但是在一些应用中常常需要获取和处理另外应用程序的消息,而实现此类功能的技术也就本文要讨论的主题――消息拦截技术。
Windows应用程序的消息来源有4种:输入消息,控制消息、系统消息、用户消息。
而根据消息产生的方式又可以分为两大类,即硬件消息和软件消息。
硬件消息,常指由硬件所产生的事件,通过系统消息队列中转,再转发给应用程序消息队列。
软件消息,常指由系统或其它应用程序发送的信息,它直接发送到应用程序消息队列。
一个消息由一个消息名称[UINT],和两个参数[WPARAM, LPARAM]。不同的消息,对应的参数含义也不一致。
所有系统消息的定义在Winuser.h中都可以找到。常用消息参考
一个消息通常必须由一个窗口接收。而窗口程序本身也会实现窗口过程函数来处理接收的消息。函数原型如下:
LRESULT Wndproc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
当然,程序也可以使用GetMessage
直接从消息队列中获取消息进行处理。
wParam | 含义 | lParam |
---|---|---|
如果消息由当前线程发送,则为非零;否则为零 | 指向 CWPSTRUCT 结构的指针 |
LRESULT(CALLBACK HOOK_CALLWNDPROC)(int code, WPARAM wParam, LPARAM lParam) {
Ud_Print(L"[Hook] process = %ld, res = %ld\n", (DWORD)wParam,
(DWORD)((PCWPRETSTRUCT)lParam)->lResult);
return CallNextHookEx(NULL, code, wParam, lParam);
}
功能:当窗口过程接收到系统事件消息调用
参数:
nCode | 含义 | wParam | lParam |
---|---|---|---|
HCBT_MOVESIZE | 即将移动窗口或调整其大小 | 指定要移动或调整大小的窗口的句柄 | 指定指向包含窗口坐标的 RECT 结构的指针 |
HCBT_MINMAX | 窗口即将最小化或最大化 | 指定要最小化或最大化的窗口的句柄 | 在低序字中,指定一个显示窗口值 (SW_) 指定操作 |
HCBT_QS | 系统已从系统消息队列中检索WM_QUEUESYNC消息 | 必须为零 | 必须为零 |
HCBT_CREATEWND | 即将创建一个窗口 | 指定新窗口的句柄 | 指向包含窗口初始化参数 的CBT_CREATEWND 结构的指针 |
HCBT_DESTROYWND | 窗口即将被销毁 | 指定要销毁的窗口的句柄 | 必须设置为零 |
HCBT_ACTIVATE | 系统即将激活窗口 | 指定要激活的窗口的句柄 | 指向 CBTACTIVATESTRUCT 结构的指针 |
HCBT_CLICKSKIPPED | 系统已从系统消息队列中删除鼠标消息 | 指定从系统消息队列中删除的鼠标消息 | 指向 MOUSEHOOKSTRUCT 结构的指针 |
HCBT_KEYSKIPPED | 系统已从系统消息队列中删除键盘消息 | 指定虚拟密钥代码 | 指定重复计数、扫描代码、键转换代码、以前的键状态和上下文代码 |
HCBT_SYSCOMMAND | 即将执行系统命令 | 指定系统命令值 | 包含与WM_SYSCOMMAND消息的 lParam 值相同的数据 |
HCBT_SETFOCUS | 窗口即将接收键盘焦点 | 指定获得键盘焦点的窗口的句柄 | 指定失去键盘焦点的窗口的句柄 |
示例:
LRESULT(CALLBACK HOOK_CBT)(int code, WPARAM wParam, LPARAM lParam) { wchar_t* event = UnKnown; switch (code) { case HCBT_CLICKSKIPPED: { event = str(HCBT_CLICKSKIPPED); Ud_Print(L"[Hook] message = %s, wParam = %ld, point = (%d, %d)\n", event, (DWORD)wParam, ((PMOUSEHOOKSTRUCT)lParam)->pt.x, ((PMOUSEHOOKSTRUCT)lParam)->pt.y); return 0; } case HCBT_KEYSKIPPED: event = str(HCBT_KEYSKIPPED); break; case HCBT_QS: event = str(HCBT_QS); break; // allow the action with 0, otherwise forbidden case HCBT_ACTIVATE: { event = str(HCBT_ACTIVATE); Ud_Print(L"[Hook] message = %s, Wnd = %ld, mouse = %d\n", event, (DWORD)wParam, ((LPCBTACTIVATESTRUCT)lParam)->fMouse); return 0; } case HCBT_CREATEWND: { event = str(HCBT_CREATEWND); Ud_Print(L"[Hook] message = %s, Name = %s, (x,y,l,h) = (%d,%d),(%d,%d)\n", event, ((LPCBT_CREATEWND)lParam)->lpcs->lpszName, ((LPCBT_CREATEWND)lParam)->lpcs->x, ((LPCBT_CREATEWND)lParam)->lpcs->y, ((LPCBT_CREATEWND)lParam)->lpcs->cx, ((LPCBT_CREATEWND)lParam)->lpcs->cy); return 0; } case HCBT_MOVESIZE: { event = str(HCBT_MOVESIZE); Ud_Print(L"[Hook] message = %s, Wnd = %ld, Point = (%d,%d), (%d,%d)\n", event, (DWORD)wParam, ((PRECTL)lParam)->left, ((PRECTL)lParam)->top, ((PRECTL)lParam)->right, ((PRECTL)lParam)->bottom); return 0; } case HCBT_SYSCOMMAND: { event = str(HCBT_SYSCOMMAND); Ud_Print(L"[Hook] message = %s, event = %ld, point = (%d, %d)\n", event, (DWORD)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); return 0; } case HCBT_DESTROYWND: event = str(HCBT_DESTROYWND); break; case HCBT_MINMAX: event = str(HCBT_MINMAX); break; case HCBT_SETFOCUS: event = str(HCBT_SETFOCUS); break; default: return CallNextHookEx(NULL, code, wParam, lParam); } Ud_Print(L"[Hook] message = %s, wParam = %ld, lParam = %ld\n", event, (DWORD)wParam, (DWORD)lParam); return 0; }
功能:当有挂钩过程创建时调用
参数:
wParam | lParam |
---|---|
即将调用的挂钩类型 | 指向 DEBUGHOOKINFO 结构的指针 |
示例:
LRESULT(CALLBACK HOOK_DEBUG)(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
Ud_Print(L"[Hook] message = %s, hook type = %ld\n", str(HC_ACTION),
(DWORD)wParam);
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
功能:当有前台线程空闲时调用
参数:
示例:
LRESULT(CALLBACK HOOK_FOREGROUNDIDLE)(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
Ud_Print(L"[Hook] message = %s\n", str(HC_ACTION));
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
功能:当消息发布到消息队列时调用
参数:
wParam | lParam |
---|---|
指定是否已从队列中删除消息 | 指向包含消息详细信息的 MSG 结构的指针 |
示例:
LRESULT(CALLBACK HOOK_GETMESSAGE)(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
Ud_Print(L"[Hook] message = %s, event = %ld, msg = %d\n", str(HC_ACTION),
(DWORD)wParam, ((PMSG)lParam)->message);
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
功能:记录和回放消息调用
参数:
示例:
void DO_JOURNALRECORD(bool); void DO_JOURNALPLAYBACK(bool); bool end_ = false; int cur_ = 0; bool flag = false; LRESULT(CALLBACK HOOK_JOURNALPLAYBACK) (int code, WPARAM wParam, LPARAM lParam) { wchar_t* event = UnKnown; if (code == HC_GETNEXT) { event = str(HC_GETNEXT); } else if (code == HC_SKIP) { event = str(HC_SKIP); } else if (code == HC_NOREMOVE) { event = str(HC_NOREMOVE); } else if (code == HC_SYSMODALOFF) { event = str(HC_SYSMODALOFF); } else if (code == HC_SYSMODALON) { event = str(HC_SYSMODALON); } Ud_Print(L"[Hook] message = %s, wParam = %ld, lParam = %ld\n", event, (DWORD)wParam, (DWORD)lParam); if (code == HC_SKIP) { flag = true; if (++cur_ >= ev_record_.size()) { std::cout << "DO_JOURNALPLAYBACK Empty!" << std::endl; DO_JOURNALPLAYBACK(false); PostQuitMessage(0); end_ = true; } return 0; } else if (code == HC_GETNEXT) { DWORD time = 0; PEVENTMSG pEv = (PEVENTMSG)lParam; if (cur_ < ev_record_.size() && pEv) { *pEv = ev_record_[cur_]; if (flag) { time = ev_record_[cur_ + 1 >= ev_record_.size() ? cur_ : cur_ + 1].time - ev_record_[cur_].time; flag = false; } } if (time < 0) time = 1; return time; } else if (code == HC_NOREMOVE) { return 0; } return CallNextHookEx(NULL, code, wParam, lParam); } bool stop_ = false; LRESULT(CALLBACK HOOK_JOURNALRECORD) (int code, WPARAM wParam, LPARAM lParam) { wchar_t* event = UnKnown; if (code == HC_ACTION) { event = str(HC_ACTION); } else if (code == HC_SYSMODALOFF) { event = str(HC_SYSMODALOFF); stop_ = false; } else if (code == HC_SYSMODALON) { event = str(HC_SYSMODALON); stop_ = true; } PEVENTMSG pEv = (PEVENTMSG)lParam; Ud_Print(L"[Hook] message = %s, wParam = %ld, lParam = %ld\n", event, (DWORD)wParam, (DWORD)(code == HC_ACTION ? pEv->message : lParam)); if (!stop_ && !end_) { // https://learn.microsoft.com/zh-cn/windows/win32/inputdev/keyboard-input-notifications // https://learn.microsoft.com/zh-cn/windows/win32/inputdev/mouse-input-notifications if (pEv->message == WM_KEYDOWN) { if (LOBYTE(pEv->paramL) == VK_CANCEL) { std::cout << "DO_JOURNALRECORD VK_CANCEL!" << std::endl; DO_JOURNALRECORD(false); PostQuitMessage(0); return 0; } } ev_record_.push_back(*pEv); } return CallNextHookEx(NULL, code, wParam, lParam); } void DO_MONITOR_JOURNAL() { MSG msg; BOOL bRet; while (!end_) { // The call is made by sending a message to the thread that installed the // hook. Therefore, the thread that installed the hook must have a message // loop. if ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (bRet == -1) { std::cout << "GetMessage Error = " << GetLastError() << std::endl; break; } else { TranslateMessage(&msg); if (msg.message == WM_CANCELJOURNAL) { std::cout << "DO_JOURNALRECORD WM_CANCELJOURNAL!" << std::endl; hook_playback_ = NULL; hook_record_ = NULL; end_ = true; } DispatchMessage(&msg); } } } }
功能:当窗口接收到键盘消息时调用
参数:
nCode | wParam | lParam |
---|---|---|
HC_ACTION | HC_NOREMOVE | 生成 击键 消息的密钥的虚拟密钥代码 | 重复计数、扫描代码、扩展键标志、上下文代码、以前的键状态标志和转换状态标志 |
示例:
LRESULT(CALLBACK HOOK_KEYBOARD)(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
Ud_Print(L"[Hook] message = %s, key event = (%ld, %ld)\n", str(HC_ACTION),
(DWORD)wParam, (DWORD)lParam);
} else if (code == HC_NOREMOVE) {
Ud_Print(L"[Hook] message = %s, key event = (%ld, %ld)\n", str(HC_NOREMOVE),
(DWORD)wParam, (DWORD)lParam);
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
功能:当窗口接收到鼠标消息时调用
参数:
nCode | wParam | lParam |
---|---|---|
HC_ACTION | HC_NOREMOVE | 鼠标消息的标识符 | 指向 MOUSEHOOKSTRUCT 结构的指针 |
示例:
LRESULT(CALLBACK HOOK_MOUSE)(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
Ud_Print(L"[Hook] message = %s, event = %ld, point = (%d, %d)\n",
str(HC_ACTION), (DWORD)wParam, ((PMOUSEHOOKSTRUCT)lParam)->pt.x,
((PMOUSEHOOKSTRUCT)lParam)->pt.y);
} else if (code == HC_NOREMOVE) {
Ud_Print(L"[Hook] message = %s, event = %ld, point = (%d, %d)\n",
str(HC_NOREMOVE), (DWORD)wParam, ((PMOUSEHOOKSTRUCT)lParam)->pt.x,
((PMOUSEHOOKSTRUCT)lParam)->pt.y);
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
功能:当系统接收到键盘消息时调用
参数:
nCode | wParam | lParam |
---|---|---|
HC_ACTION | 键盘消息的标识符 | 指向 KBDLLHOOKSTRUCT 结构的指针 |
示例:
static bool end_ = false; LRESULT(CALLBACK HOOK_KEYBOARD_LL)(int code, WPARAM wParam, LPARAM lParam) { if (code == HC_ACTION) { Ud_Print(L"[Hook] message = %s, event = %ld, key event = (%d, %d)\n", str(HC_ACTION), (DWORD)wParam, ((PKBDLLHOOKSTRUCT)lParam)->vkCode, ((PKBDLLHOOKSTRUCT)lParam)->flags); if (wParam == WM_KEYDOWN) { if (((PKBDLLHOOKSTRUCT)lParam)->vkCode == VK_CANCEL) { end_ = true; return 1; } } } return CallNextHookEx(NULL, code, wParam, lParam); }
功能:当系统接收到鼠标消息时调用
参数:
nCode | wParam | lParam |
---|---|---|
HC_ACTION | 鼠标消息的标识符 | 指向 MSLLHOOKSTRUCT 结构的指针 |
示例:
static bool end_ = false;
LRESULT(CALLBACK HOOK_MOUSE_LL)(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
Ud_Print(L"[Hook] message = %s, event = %ld, point = (%d, %d)\n",
str(HC_ACTION), (DWORD)wParam, ((PMSLLHOOKSTRUCT)lParam)->pt.x,
((PMSLLHOOKSTRUCT)lParam)->pt.y);
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
功能:当系统接收到键盘消息时调用
参数:
示例:
LRESULT(CALLBACK HOOK_MSGFILTER)(int code, WPARAM wParam, LPARAM lParam) { wchar_t* event = UnKnown; switch (code) { case MSGF_DDEMGR: // DDEML event event = str(MSGF_DDEMGR); break; case MSGF_DIALOGBOX: // dialog event event = str(MSGF_DIALOGBOX); break; case MSGF_MENU: // menu event event = str(MSGF_MENU); case MSGF_SCROLLBAR: // scrollbar event event = str(MSGF_SCROLLBAR); break; default: return CallNextHookEx(NULL, code, wParam, lParam); } Ud_Print(L"[Hook] message = %s, event = %d\n", event, ((PMSG)lParam)->message); return CallNextHookEx(NULL, code, wParam, lParam); }
功能:当系统接收到键盘消息时调用
参数:
示例:
LRESULT(CALLBACK HOOK_SYSMSGFILTER)(int code, WPARAM wParam, LPARAM lParam) { wchar_t* event = UnKnown; switch (code) { case MSGF_DIALOGBOX: // dialog event event = str(MSGF_DIALOGBOX); break; case MSGF_MENU: // menu event event = str(MSGF_MENU); break; case MSGF_SCROLLBAR: // scrollbar event event = str(MSGF_SCROLLBAR); break; default: return CallNextHookEx(NULL, code, wParam, lParam); } Ud_Print(L"[Hook] message = %s, event = %d\n", event, ((PMSG)lParam)->message); return CallNextHookEx(NULL, code, wParam, lParam); }
功能:当系统接收到Shell事件时调用
参数:
nCode | 含义 | wParam | lParam |
---|---|---|---|
HSHELL_WINDOWCREATED | 已创建顶级的无所有者窗口 | 所创建窗口的句柄 | |
HSHELL_WINDOWDESTROYED | 一个顶级的、无所有者的窗口即将被销毁 | 已销毁窗口的句柄 | |
HSHELL_ACTIVATESHELLWINDOW | shell 应激活其main窗口 | ||
HSHELL_WINDOWACTIVATED | 激活已更改为其他顶级的无所有者窗口 | 已激活窗口的句柄 | 如果窗口处于全屏模式,则值为 TRUE,否则值为 FALSE |
HSHELL_GETMINRECT | 窗口正在最小化或最大化 | 最小化或最大化窗口的句柄 | 指向 RECT 结构的指针 |
HSHELL_REDRAW | 任务栏中窗口的标题已重绘 | 重绘窗口的句柄 | 如果窗口闪烁,则值为 TRUE,否则值为 FALSE |
HSHELL_TASKMAN | 用户已选择任务列表 | ||
HSHELL_LANGUAGE | 键盘语言已更改或加载了新的键盘布局 | 窗口的句柄 | 键盘布局的句柄 |
HSHELL_ACCESSIBILITYSTATE | 辅助功能状态已更改 | 指示哪个辅助功能已更改状态 | |
HSHELL_APPCOMMAND | 用户完成了输入事件 | 指示最初发送WM_APPCOMMAND消息的位置 | 包含与WM_APPCOMMAN消息的 lParam 值相同的数据 |
HSHELL_WINDOWREPLACED | 正在替换顶级窗口 | 要替换的窗口的句柄 | 新窗口的句柄 |
示例:
LRESULT(CALLBACK HOOK_SHELL)(int code, WPARAM wParam, LPARAM lParam) { wchar_t* event = UnKnown; switch (code) { case HSHELL_ACCESSIBILITYSTATE: // The accessibility state has changed. event = str(HSHELL_ACCESSIBILITYSTATE); break; case HSHELL_ACTIVATESHELLWINDOW: // The shell should activate its main // window event = str(HSHELL_ACTIVATESHELLWINDOW); break; case HSHELL_TASKMAN: // The user has selected the task list event = str(HSHELL_TASKMAN); break; case HSHELL_LANGUAGE: // Keyboard language was changed event = str(HSHELL_LANGUAGE); break; case HSHELL_REDRAW: // The title of a window in the task bar has been // redrawn. event = str(HSHELL_REDRAW); break; case HSHELL_WINDOWACTIVATED: // The activation has changed to a // different top-level, unowned window. event = str(HSHELL_WINDOWACTIVATED); break; case HSHELL_WINDOWCREATED: // A top-level, unowned window has been // created. event = str(HSHELL_WINDOWCREATED); break; case HSHELL_WINDOWDESTROYED: // A top-level, unowned window is about to be // destroyed. event = str(HSHELL_WINDOWDESTROYED); break; case HSHELL_WINDOWREPLACED: // A top-level window is being replaced. event = str(HSHELL_WINDOWREPLACED); break; case HSHELL_GETMINRECT: // A window is being minimized or maximized. { PRECT pRect = (PRECT)lParam; Ud_Print( L"[Hook] message = %s, Wnd = %ld, Point = (%d,%d), " L"(%d,%d)\n", str(HSHELL_GETMINRECT), (DWORD)wParam, pRect->left, pRect->top, pRect->right, pRect->bottom); return 0; } case HSHELL_APPCOMMAND: { Ud_Print(L"[Hook] message = %s, Cmd = %d, Device = %d, KeyState = %d\n", str(HSHELL_APPCOMMAND), GET_APPCOMMAND_LPARAM(lParam), GET_DEVICE_LPARAM(lParam), GET_KEYSTATE_LPARAM(lParam)); return 0; }; default: return CallNextHookEx(NULL, code, wParam, lParam); } Ud_Print(L"[Hook] message = %s, wParam = %ld, lParam = %ld\n", event, (DWORD)wParam, (DWORD)lParam); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。