1

我正在尝试仅通过键盘激活鼠标。

但是我的代码让我的电脑出错了。执行它的时间不长,它运行良好,但几分钟后,所有鼠标输入都无法很好地接受。例如,我无法单击任务栏上的程序,也无法单击 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 );
    }
}
4

0 回答 0