作者:-刘耀宗_690 | 来源:互联网 | 2023-05-16 10:21
上一篇文章已经写了基于普通键盘钩子(单线程+DLL)来实现dota改键。http:blog.csdn.neta576323437articledetails8037138这一次,
上一篇文章已经写了基于 普通键盘钩子(单线程+DLL)来实现dota改键。http://blog.csdn.net/a576323437/article/details/8037138
这一次,基于 低级键盘钩子 (全局 + 免DLL注入)来实现。先看下总结:
低级键盘钩子,截取操作系统发向任何进程消息队列的按键消息,在本线程回调函数里处理,
任一按键消息 -> 被安装低级键盘钩子线程截获(在函数中处理)-> 根据键盘消息目标分到各进程消息队列 -> 进程GetMessage对其处理
安装低级钩子时 有一种 粘在操作系统的感觉有没有 要接收所有按键消息,第四个参数为 NULL。
普通键盘钩子,按键消息先分发到各进程的消息队列,进程 GetMessage前 钩子函数被调用。
任一按键消息 -> 分发到各个进程消息队列 -> 钩子回调函数对消息处理 -> 进程GetMessage处理
安装普通钩子时 有一种 粘在进程消息队列上的感觉有木有 只监听一个线程,第四参数就为该线程ID,要监听所有线程,就设置为NULL。
不需要DLL原因,是因为对于目标进程来说,消息在进入其进程消息队列前已经被处理过。 只要正常GetMessage就行了。
主要是两个地方。
1.安装钩子,第四个参数必须为NULL,上面总结解释了。
void C_LLChangeKeyDlg::SetHook()
{
m_hLLKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, AfxGetApp()->m_hInstance,NULL);
g_hLLKeyboard = m_hLLKeyboard;
}
2. 因为是监听全局所有线程,所以要对目标进程的消息进行区分。 刚开始以为消息里面会有目标进程ID,后来找不到。。最后想出一个办法,用判断桌面活动窗口是否为dota窗口来实现。
LRESULT CALLBACK LowLevelKeyboardProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // message data
)
{
DWORD VKey=0;
if( nCode == HC_ACTION)
{
// GetForegroundWindow() 获得前台窗口
// GetActiveWindow() 获得“调用该函数的线程(即 用GetMessage()获取消息的线程相关的窗口)”的窗口
HWND hwndCurrent = ::GetForegroundWindow();
if( hwndWar == hwndCurrent ) ....
主要就是以上两部分,其它见源码注释吧。。
源码下载地址:http://download.csdn.net/detail/a576323437/4613761