2009-09-17 3 views
4

Я работаю над своим регистратором нажатия клавиш для личных интересов и задал вопрос, связанный с этим вчера; While loop using a lot of CPU.События клавиатуры C++ Win32

Проблема с программой состояла в том, что потребовалось слишком много использования ЦП, и люди предложили сделать входные данные основаны на ключевых событиях.

Поскольку я новичок в API Win32, я стараюсь искать ссылки и руководства, которые расскажут мне, как создавать входы на клавиатуре как основанные на событиях, а не на основе опросов. Но проблемы в том, что я не мог найти каких-либо твердых примеров или ссылок, поскольку это было довольно сложно понять для новичков.

Большинство из них отметили, что программирование на основе событий находится в приложении GUI, но я хочу, чтобы это приложение регистрации ключей было консольным приложением.

Мои два основных вопроса из всего этого:

  • Могу ли я написать событийно-консоль клавиатурный шпион с Win32 API? Если нет, каковы мои варианты?

и

  • Кто-нибудь есть какие-либо справочные сайты, которые помогут мне понять, как записывать нажатия клавиш на основе событий?

Если необходима дополнительная информация, я использую блоки кода в Windows XP с компилятором GCC.

ответ

7

Ключевые приложения для использования в регистраторе используют такие механизмы, как Win32 Hooks. В частности, вам необходимо установить крючок WH_KEYBOARD.

Есть продвинутые методы, такие как создание собственного драйвера клавиатуры, но для стартовых крюков - хороший выбор.

Редактировать: Чтобы понять, как выглядит процедура крючка, я размещаю фрагмент из своей личной утилиты.

// ... 
thehook = SetWindowsHookEx(WH_KEYBOARD_LL, hook_proc, hwnd, 0); 
// ... 

/** 
* 
* wParam, one of the: WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP 
    lParam: pointer to a KBDLLHOOKSTRUCT structure 

    (*) "The hook procedure should process a message in less time than the 
    data entry specified in the LowLevelHooksTimeout value in the following registry key: 
    HKEY_CURRENT_USER\Control Panel\Desktop 

    The value is in milliseconds. If the hook procedure does not 
    return during this interval, the system will pass the message to the next hook." 

* 
*/ 
LRESULT CALLBACK 
hook_proc(int code, WPARAM wParam, LPARAM lParam) 
{ 
    static long ctrl_cnt = 0; 
    static bool mmode = false; 
    static DWORD time; 

    KBDLLHOOKSTRUCT* kbd = (KBDLLHOOKSTRUCT*)lParam; 

    if ( code < 0 
    || (kbd->flags & 0x10) // ignore injected events 
    ) return CallNextHookEx(thehook, code, wParam, lParam); 

    long ret = 1; // by default I swallow the keys 
    if ( mmode ) { // macro mode is ON 
    if ( WM_KEYDOWN == wParam ) 
     PostMessage(mainwnd, WM_MCR_ACCUM, kbd->vkCode, 0); 

    if ( WM_KEYUP == wParam ) 
     switch (kbd->vkCode) { 
     case VK_ESCAPE: 
      mmode = false; 
      keys.removeall(); 
      PostMessage(mainwnd, WM_MCR_HIDE, 0, 0); 
      break; 

     case VK_RETURN: 
      PostMessage(mainwnd, WM_MCR_EXEC, 0, 0); 
      break; 

     case VK_LCONTROL: 
      mmode = false; 
      PostMessage(mainwnd, WM_MCR_HIDE, 0, 0); 
      PostMessage(mainwnd, WM_MCR_EXEC, 0, 0); 
      break; 
     } 

    /* Which non printable keys allow passing? */ 
    switch(kbd->vkCode) { 
     case VK_LCONTROL: 
     case VK_CAPITAL: 
     case VK_LSHIFT: 
     case VK_RSHIFT: 
     ret = CallNextHookEx(thehook, code, wParam, lParam); 
    } 
    } 
    else { // macro mode is OFF 
    /* Ctrl pressed */ 
    if ( kbd->vkCode == VK_LCONTROL && WM_KEYDOWN == wParam ) { 
     ctrl_cnt = 1; 
     time = kbd->time; 
    } 

    /* Prevent ctrl combinations to activate macro mode */ 
    if ( kbd->vkCode != VK_LCONTROL ) 
     ctrl_cnt = 0; 

    /* Ctrl released */ 
    if ( ctrl_cnt == 1 && WM_KEYUP == wParam ) { 
     if ( kbd->time - time > 40 ) { 
     mmode = true; 
     PostMessage(mainwnd, WM_MCR_SHOW, 0, 0); 
     } 
    } 

    ret = CallNextHookEx(thehook, code, wParam, lParam); // let it pass 
    } 

    return ret; 
} 
+0

Как вы получаете ПОЕЗДКУ другой программы? –

+0

@ MatoušVrba, вам не нужно обращаться к другим программам. –

+0

Да, теперь я понимаю, спасибо! –

5

Посмотрите на API SetWindowsHookEx.

Вы можете сделать это консольное приложение, а также оконное приложение. Вам нужно будет поместить ваш крючок для клавиатуры в DLL, чтобы вы могли захватывать нажатия клавиш в процессах, отличных от ваших собственных.

Есть пример кода here.

+0

Просто любопытно, что делает крючок именно так? Я читал, что он вводит себя в другую программу, или это может меня понять. Кроме того, это уменьшит объем использования ЦП, который хранит нажатие клавиши? – 2009-09-17 07:19:41

+1

Крючок добавляет обратный вызов вашей функции, когда происходит выбранное событие. Вам не понадобится цикл, который будет постоянно проверять клавиатуру. Вы выполняете код только в случае необходимости. – Ferruccio

+0

См. Также эту дискуссию http://stackoverflow.com/questions/3134183/understanding-the-low-level-mouse-and-keyboard-hook-win32/3134570#comment27597902_3134570 (Я считаю, что exe может работать для сообщений * _LL, но dll требуется для чего-либо еще). – rogerdpack

Смежные вопросы