2014-08-27 20 views
5

Sto utilizzando un gancio per tastiera di basso livello su Windows. Funziona come un vero fascino, nonostante il fatto che attualmente non sia in grado di dire se il tasto è stato inizialmente premuto o premuto di nuovo. Lo documentation (+ here) dice che il bit 7 contiene lo stato di transizione. Ma questo sembra essere vero solo quando viene rilasciata la chiave. Il bit 7 non è impostato con esitazione quando preme il tasto per la prima volta.Utilizzo di KBDLLHOOKSTRUCT per determinare la prima pressione del tasto

C'è un modo per dire se il tasto viene premuto inizialmente?

+0

Uno dei molti problemi con gli hook per tastiera, lo stato della tastiera è una proprietà per processo. Quindi, ciò che si ottiene interamente dipende da quale processo avviene per possedere la finestra in primo piano e se * ha * visto la chiave prima. –

+0

Lo so, ma non mi interessa in questo caso. Mi aspetto che l'utente focalizzi solo il mio processo, ma sono consapevole del rischio, grazie! –

+3

@Hans Lo stato della tastiera è controllato per thread (o gruppo di thread, se più thread sono legati insieme come risultato della chiamata di 'AttachThreadInput'). Sostituire tutte le occorrenze di * process * con * thread o thread group * corregge il tuo commento. – IInspectable

risposta

1

Mi capita di imbattersi in questo problema di recente. Non riesco a trovare alcuna soluzione valida, ma alla fine ho utilizzato una bandiera e un GetAsyncKeyState prima dello SetWindowHookEx.

BOOL wasDown; 

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { 
    if (nCode == HC_ACTION) { 
     LPKBDLLHOOKSTRUCT key = (LPKBDLLHOOKSTRUCT) lParam; 
     if (key->vkCode == VK_SOMETHING) { 
      switch (wParam) { 
       case WM_KEYDOWN: 
       case WM_SYSKEYDOWN: 
        if (!wasDown) { 
         // Processing on first key down 
         wasDown = true; 
        } 
        break; 
       case WM_KEYUP: 
       case WM_SYSKEYUP: 
        // Processing on key up 
        wasDown = FALSE; 
        break; 
      } 
    } 
    return CallNextHookEx(NULL, nCode, wParam, lParam); 
} 

wasDown = GetAsyncKeyState(VK_SOMETHING) < 0; 
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0); 

Ovviamente, questo codice lo fa solo per una chiave. È possibile utilizzare una serie di flag per eseguire più chiavi. A seconda dell'applicazione, è inoltre possibile impostare incondizionatamente il flag su false se si desidera la prima pressione dopo aver impostato il proprio hook.

+0

Questo è esattamente ciò che faccio attualmente fino a quando qualcuno non pubblicherà una soluzione migliore. Grazie! –

Problemi correlati