#include <Windows.h>
HINSTANCE gl_hThisInstance = NULL;
HHOOK hHook = NULL;
LRESULT CALLBACK KeyHit(int code,WPARAM wParam,LPARAM lParam);
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
gl_hThisInstance = (HINSTANCE)hModule;
hHook = SetWindowsHookExA(
WH_KEYBOARD,
KeyHit,
//(HWND)gl_hThisInstance//not working
0,//not working
//(DWORD)gl_hThisInstance//not working
//GetCurrentThreadId()//even not working with this
0//not working
);
break;
}
return TRUE;
}
LRESULT CALLBACK KeyHit(int code,WPARAM wParam,LPARAM lParam)
{
MessageBox(0,"PRESSED","PRESSED",0);
return CallNextHookEx(hHook,code,wParam,lParam);
}
我以前遇到了问题。并不是一个问题,但是我不应该这样做的方式。 首先,您应该有2个来自DLL,
SetHook
和SetHook
函数将从那里调用
SetWindowsHookEx()
。如果您尝试从线程或DLL的线程或
SetWindowsHookEx()
中调用
DLLMain
,则该函数不会返回任何错误,但是将永远不会调用回调函数。有时我花了我弄清楚。这里是我要捕获的工作代码,您可以从这里引用。
我从dll的工作导出了sethook()函数。
WH_GETMESSAGE
bool __declspec(dllexport) __stdcall SetHook(DWORD myWnd)
{
mySavedHook = SetWindowsHookEx(WH_GETMESSAGE,
GetMsgProc,
infoContainer.DllHModule,
myWnd);
int errorID = GetLastError();
if (errorID != 0)
{
MessageBoxA(NULL, "Failed to implement hook", "Failed", 0);
MessageBoxA(NULL, to_string(errorID).c_str(), "Error ID", 0);
return false;
}
else
{
return true;
}
}
:DLL的实例,这是
infoContainer.DllHModule
的第一个参数。
DllMain()
是我的线程ID(不处理ID) - 从
myWnd:
获取。要实现全局钩,请使用0为
GetWindowThreadProcessId(window_handle, NULL)
.
。这是我的回调函数。
myWnd
回调函数必须具有
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_CALLFUNCTION)
{
MessageBoxA(NULL, "Receive WM_CALLFUNTION", "Good news", 0);
}
}
//Doesn't matter, just call this function and return it.
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
关键字可以工作。从外部应用程序,从dll调用
CALLBACK
,然后将线程ID用作其参数。
我知道这是超级旧的,但是我前几天我自己遇到了这个问题,正如其他答案所建议的那样,您无法从dllmain函数或其他线程中调用
SetHook()
。
,但这是因为DLL主函数在其自己的线程中运行,与主线程分开。 这是相关的,因为显然,当您打电话
SetWindowsHookEx()
时,一旦您wed the the the the the ture the ture the Ever ture the Ever ture the the the the the the the,然后由于某种原因而自动解开(我找不到Internet上任何地方都记录下来的线程)
因此,如果您从目标过程的主要一个线程(假设您可以做到)以外的任何线程调用SetWindowsHookEx()
,那么总是有可能在主过程本身到期之前撤消钩子。 在这种情况下,一旦dllmain函数返回,它将终止线程并因此删除钩子。为了修复此问题,我从一个新线程中调用钩子,然后我无限期地悬挂该线程,这应该意味着只有在过程本身关闭时才删除钩子。 问题的固定版本可能看起来像这样的东西
作为一个奖励,我实际上读了这一点,我将另一个小函数汇总在一起,以获取该过程的
A窗口的线程ID(不是主要的窗口,如果是主要的)为了获得
HHOOK hHook = NULL;
LRESULT CALLBACK KeyHit(int code, WPARAM wParam, LPARAM lParam){
// replace with whatever logic you want to run in the target process when keyboard event is called
cout << "keyboard event detected.\n";
return CallNextHookEx(hHook, code, wParam, lParam);
}
void ThreadHookEvents() {
DWORD thread_id = 0; // set this to the thread id of your main/hwnd thread
HHOOK hHook = SetWindowsHookExA(WH_KEYBOARD, (HOOKPROC)KeyHit, 0, thread_id);
// then pause the thread so the hook never expires
SuspendThread(GetCurrentThread());
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){
switch (ul_reason_for_call){
case DLL_PROCESS_ATTACH:
CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)ThreadHookEvents, 0, 0, 0);
break;
}
return TRUE;
}
thread_id