2010-01-16 6 views
6

Nel mio aggancio della tastiera, ogni pressione di un tasto riceve un flag che indica se è stato iniettato o meno. http://msdn.microsoft.com/en-us/library/ms644967(VS.85).aspxCome si usano flag a 8 bit di basso livello come condizionali?

Ho distillato un KBDLLHOOKSTRUCT dal lParam. Posso accedere a kbd.flags.XXX. Non so proprio come convertire questo flag a 8 bit in un condizionale di tipo if (injected) {... che so come usare.

Se uno di voi tipi di computer intelligenti mi aiutasse, lo apprezzerei molto.

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
    { 
     KBDLLHOOKSTRUCT kbd = new KBDLLHOOKSTRUCT(); 
     Marshal.PtrToStructure(lParam, kbd); 

     //if (injected) {... 

Cheers!

risposta

7

È necessario bit per bit e con una maschera. Ad esempio, il bit iniettato è il bit 4. Questo è binario 00010000, hex 0x10. Così si bit a bit e con 0x10, e vediamo se sinistra di qualsiasi cosa:

bool isInjected = ((kbd.flags & 0x10) != 0); 

(Naturalmente, come per ogni risposta di Andrew, sarebbe una buona idea di definire una costante LLKHF_INJECTED per questo piuttosto che compreso il valore esadecimale ! direttamente nel codice)

+0

questo (e altri qui che ho provato) sta lanciando un 'Un'eccezione di prima possibilità di tipo 'System.ArgumentException' si è verificata in foofoo.exe. Sembra che stia incasinando il precedente codice di aggancio della tastiera che avevo anch'io. Cosa dà? Inoltre non si compila a meno che non aggiungo parentesi: 'bool isInjected = ((kbd.flags & LLKHF_INJECTED)! = 0);' ... sta cambiando il codice? – cksubs

+0

Gli extra paren non stanno cambiando il codice - riparano semplicemente il mio stupido errore di precedenza. Risposta aggiornata – itowlson

+0

Non ho idea da dove provenga ArgumentException, dato che stai leggendo solo dal campo flags. Un'eccezione viene effettivamente lanciata o è solo un messaggio di debug su un'eccezione di prima scelta (cioè catturato e gestito internamente all'interno del CLR)? Se il primo, qual è la traccia dello stack dell'eccezione? Lo ottieni ancora se solo Console.WriteLine (kbd.flags)?Una volta esaminati, è possibile che si desideri creare una domanda separata perché probabilmente non è correlata alla pura domanda di bit-twiddling "come si usano i flag bit a bit in C#?", Più probabilmente un problema di marshalling. – itowlson

3

Utilizzare l'operatore AND bit a bit per verificare se il bit corrispondente viene impostato nelle bandiere variabili:

if (kbd.flags & LLKHF_INJECTED) 
{ 
    ... 
} 
+0

Non verrà compilato. In C#, l'espressione 'if' deve essere un bool; kbd.flags e LLKHF_INJECTED è un int. (Funzionerebbe comunque in C/C++). – itowlson

2

è necessario controllare che il bitflag è impostato. Facile da fare con operazioni bit a bit. La documentazione afferma che il bit 4 è utilizzato per il flag iniettato, il bit 4 (o 5 se si considera il primo bit come 1) è uguale a 16, quindi è possibile eseguire un AND a bit contro il flag.

if ((kbd.flags & 16) == 16) 
{ 
    FireTorpedoes(); 
} 

Si può imparare di più su operazioni bit per bit qui:

+1

Il bit 4 è uguale a 16. (Il bit 4 è il quinto bit, contando da 0 a 7.) – LukeH

+0

Una buona chiamata, non si è visto che erano indicizzati a zero nei documenti. – Skurmedel

11

.NET supporta questo con il [Flags] attributo:

[Flags] 
enum KbdHookFlags { 
    Extended = 0x01, 
    Injected = 0x10, 
    AltPressed = 0x20, 
    Released = 0x80 
} 

utilizzo Esempio:

KBDLLHOOKSTRUCT info = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); 
    if ((info.flags & KbdHookFlags.Released) == KbdHookFlags.Released) { 
    // Key was released 
    // etc.. 
    } 
2

Il motivo tutti dicono di usare un bit per bit & e quindi confrontare a zero o il flag:

0111 1000  // kbd.flags 
& 0001 0000  // Injected 
      = 
    0001 0000  // (!= 0 or ==Injected)