我正在尝试仅通过键盘激活鼠标。
但是我的代码让我的电脑出错了。执行它的时间不长,它运行良好,但几分钟后,所有鼠标输入都无法很好地接受。例如,我无法单击任务栏上的程序,也无法单击 Windows 开始按钮,不仅通过我的程序(键盘)而且通过我的真实鼠标。即使在退出我的程序后,也可以脱钩。
这是代码。由 C 编写,由 cl.exe 编译
如果我按A或S,然后SendInput分别发送鼠标左键或右键单击,并通过返回1忽略所有其他钩子。(我还添加了鼠标移动的方法,但我认为它没有问题)
#include <windows.h>
#pragma comment(lib, "User32")
#define HKPARAM_ON 30
#define HKPARAM_OFF 31
#define HKPARAM_EXIT 32
#define LCLICK_KEY 'A'
#define RCLICK_KEY 'S'
#define MOVE_INITIAL 1
#define MOVE_DELTA 2
HHOOK hook_id;
int curMode = 0;
int repeat = MOVE_INITIAL;
BOOL isActive = FALSE;
int l_isUP = TRUE;
int r_isUP = TRUE;
void moveCursor( int x, int y ){
INPUT input = {0};
DWORD flag = MOUSEEVENTF_MOVE;
if( GetAsyncKeyState( LCLICK_KEY ) ){ flag |= MOUSEEVENTF_LEFTDOWN; }
if( GetAsyncKeyState( RCLICK_KEY ) ){ flag |= MOUSEEVENTF_RIGHTDOWN; }
input.type = INPUT_MOUSE;
input.mi.dx = x;
input.mi.dy = y;
input.mi.dwFlags = flag;
input.mi.dwExtraInfo = GetMessageExtraInfo();
SendInput( 1, &input, sizeof( INPUT ) );
}
LRESULT CALLBACK HOOKFUNC( int nCode, WPARAM wParam, LPARAM lParam ){
if(nCode < 0){ return CallNextHookEx(0, nCode, wParam, lParam); }
KBDLLHOOKSTRUCT *kbdstru;
DWORD flag;
INPUT input;
if( isActive ){
kbdstru = (KBDLLHOOKSTRUCT *) lParam;
if( wParam == WM_KEYDOWN ){
switch( kbdstru->vkCode ){
case LCLICK_KEY: if( l_isUP ){ l_isUP = FALSE; flag = MOUSEEVENTF_LEFTDOWN; goto call_input; } goto ignore_next_hook;
case RCLICK_KEY: if( r_isUP ){ r_isUP = FALSE; flag = MOUSEEVENTF_RIGHTDOWN; goto call_input; } goto ignore_next_hook;
case VK_LEFT:
if( curMode == VK_LEFT ) repeat += MOVE_DELTA;
else{ curMode = VK_LEFT; repeat = 1; }
moveCursor(-repeat, 0); goto ignore_next_hook;
case VK_RIGHT:
if( curMode == VK_RIGHT ) repeat += MOVE_DELTA;
else{ curMode = VK_RIGHT; repeat = 1; }
moveCursor(repeat, 0); goto ignore_next_hook;
case VK_UP:
if( curMode == VK_UP ) repeat += MOVE_DELTA;
else{ curMode = VK_UP; repeat = 1; }
moveCursor(0, -repeat); goto ignore_next_hook;
case VK_DOWN:
if( curMode == VK_DOWN ) repeat += MOVE_DELTA;
else{ curMode = VK_DOWN; repeat = 1; }
moveCursor(0, repeat); goto ignore_next_hook;
}
}
else if( wParam == WM_KEYUP ){
switch( kbdstru->vkCode ){
case LCLICK_KEY: if( !l_isUP ){ l_isUP = TRUE; flag = MOUSEEVENTF_LEFTUP; goto call_input; } goto ignore_next_hook;
case RCLICK_KEY: if( !r_isUP ){ r_isUP = TRUE; flag = MOUSEEVENTF_RIGHTUP; goto call_input; } goto ignore_next_hook;
}
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
call_input:
FillMemory( &input, sizeof(INPUT), 0 );
input.type = INPUT_MOUSE;
input.mi.dwFlags = flag;
input.mi.dwExtraInfo = GetMessageExtraInfo();
SendInput( 1, &input, sizeof(INPUT) );
ignore_next_hook:
return 1;
}
int main(){
// ON with CTRL+SHIFT+X
// OFF with CTRL+SHIFT+C
// EXIT with CTRL+SHIFT+V
if( !RegisterHotKey( NULL, HKPARAM_ON, MOD_CONTROL | MOD_SHIFT, (int)'X' ) ){
MessageBox( NULL, "ctrl + shift + X error", NULL, MB_OK | MB_ICONSTOP);
return 0;
}
if( !RegisterHotKey( NULL, HKPARAM_OFF, MOD_CONTROL | MOD_SHIFT, (int)'C' ) ){
MessageBox( NULL, "ctrl + shift + C error", NULL, MB_OK | MB_ICONSTOP);
return 0;
}
if( !RegisterHotKey( NULL, HKPARAM_EXIT, MOD_CONTROL | MOD_SHIFT, (int)'V' ) ){
MessageBox( NULL, "ctrl + shift + V error", NULL, MB_OK | MB_ICONSTOP);
return 0;
}
hook_id = SetWindowsHookEx( WH_KEYBOARD_LL, HOOKFUNC, (HINSTANCE) GetModuleHandle(NULL), 0 );
printf("hooked keyboard with hookid = 0x%X\n", hook_id);
MSG msg;
while( GetMessage(&msg, NULL, 0, 0) != 0 ){
switch( msg.wParam ){
case HKPARAM_ON:
isActive = TRUE;
printf("ON\n");
break;
case HKPARAM_OFF:
isActive = FALSE;
printf("OFF\n");
break;
case HKPARAM_EXIT:
UnhookWindowsHookEx( hook_id );
UnregisterHotKey( NULL, HKPARAM_ON );
UnregisterHotKey( NULL, HKPARAM_OFF );
UnregisterHotKey( NULL, HKPARAM_EXIT );
return 0;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}