我有这个代码为低级事件设置键盘钩子,然后显示一个消息框。
HHOOK keyboardHook = SetWindowsHookEx (WH_KEYBOARD_LL, HookKey, hInstance, 0);
MessageBox(NULL, L"Click to exit", L"hook test", NULL);
UnhookWindowsHookEx(keyboardHook);
如何在不创建前景窗口的情况下运行应用程序的主循环,如何设置hInstance
来捕获全局事件?
答案 0 :(得分:3)
答案全部包含在the MSDN docs page for SetWindowsHookEx中。要试验示例应用程序,请创建一个新解决方案,添加两个项目,一个控制台应用程序和一个DLL。每个项目只需要一个文件。 DLL将包含钩子,控制台应用程序将安装钩子。
钩子的代码必须存在于DLL中,因为MSDN文档非常明确地说:“如果 dwThreadId 参数为零或指定由不同进程创建的线程的标识符, lpfn 参数必须指向DLL中的钩子过程。“实际上,钩子显然必须在DLL中,或者shell如何在另一个应用程序的消息循环中运行代码? DLL使用其HINSTANCE安装钩子来识别函数指针所在的位置。
主应用程序运行启动挂钩并泵送消息,再次按照MSDN文档中的说明操作:“......挂钩应用程序必须继续泵送消息,否则可能会阻止64位进程的正常运行。“
请注意,这是一个非常小众的应用程序 - 几乎不需要像这样注入DLL。拜托,请三思而后行。对于许多应用程序,没有必要捕获低级别事件,尽管抑制“开始”菜单的沉浸式应用程序是合理的用例。更重要的是,您很少需要捕获发送到其他应用程序的输入。在使用此代码之前检查您确实需要这样做。例如,只需将输入挂钩到您自己的应用程序窗口即可完成录制宏。
#include <windows.h>
#include <tchar.h>
__declspec(dllimport) void (__stdcall runHook)(BOOL startOrStop);
__declspec(dllimport) LRESULT (CALLBACK hookProc)(int code, WPARAM wParam, LPARAM lParam);
int _tmain(int argc, _TCHAR* argv[])
{
runHook(true);
MSG Msg;
while(GetMessage(&Msg, NULL, 0, 0) > 0 && Msg.message != WM_QUIT) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
runHook(false);
return 0;
}
#include <assert.h>
#include <windows.h>
static HINSTANCE dllInst = 0;
static HHOOK hookSelf = 0;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
dllInst = (HINSTANCE)dllInst;
return TRUE;
}
__declspec(dllexport) LRESULT (CALLBACK hookProc)(int code, WPARAM wParam, LPARAM lParam)
{
if (code >= 0) {
UINT msgType = wParam;
KBDLLHOOKSTRUCT* msgInfo = (KBDLLHOOKSTRUCT*)lParam;
// The msgInfo contains the VK_CODE and flags.
}
return hookSelf ? CallNextHookEx(hookSelf, code, wParam, lParam) : 0;
}
__declspec(dllexport) void (__stdcall runHook)(BOOL startOrStop)
{
assert((bool)hookSelf != (bool)startOrStop);
if (startOrStop)
hookSelf = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, dllInst, 0);
else {
UnhookWindowsHookEx(hookSelf);
hookSelf = 0;
}
}
答案 1 :(得分:1)
执行此操作的一种方法是在Windows上创建TSR(Terminate and Stay Resident)程序。
在Windows上,典型的TSR程序包含以下组件:
这是一个很好的 article ,包含代码片段和有关在Windows上编写TSR的详细说明。