2010-01-16 5 views
6

In meinem Tastatur-Hook erhält jeder Tastendruck ein Flag, das angibt, ob es injiziert wurde oder nicht. http://msdn.microsoft.com/en-us/library/ms644967(VS.85).aspxWie verwende ich Low-Level-8-Bit-Flags als Bedingung?

Ich habe einen KBDLLHOOKSTRUCT aus dem LParam destilliert. Ich kann auf kbd.flags.XXX zugreifen. Ich weiß nur nicht, wie man dieses 8bit-Flag in einen if (injected) {...-Typ-Conditional konvertiert, den ich zu verwenden weiß.

Wenn einer von Ihnen intelligente Informatik-Typen mir helfen würde, würde ich es wirklich schätzen.

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

     //if (injected) {... 

Prost!

Antwort

7

Sie müssen bitweise - und es mit einer Maske. Zum Beispiel ist das injizierte Bit Bit 4. Das ist binär 00010000, hex 0x10. So Sie bitweise und es mit 0x10 und sehen links, wenn alles ist:

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

(natürlich per Andrew Antwort, wäre es eine gute Idee, eine LLKHF_INJECTED Konstante für diese zu definieren, anstatt mit dem Hex-Wert ! direkt im Code)

+0

Diese (und andere hier, die ich versucht habe,) wirft eine 'Eine erste Chance 'Ausnahme vom Typ' System.ArgumentException 'aufgetreten in foofoo.exe' Scheint, den vorherigen Tastatur-Hook-Code, den ich hatte, zu vermasseln. Was gibt? Es wird auch nicht kompiliert, wenn ich keine Klammern hinzufüge: 'bool isInjected = ((kbd.flags & LLKHF_INJECTED)! = 0);' ... ändert sich der Code? – cksubs

+0

Die zusätzlichen Parens ändern den Code nicht - sie beheben nur meinen albernen Präzedenzfehler. Antwort aktualisiert – itowlson

+0

Keine Ahnung, woher die ArgumentException kommt, da Sie nur aus dem Flag-Feld lesen. Wird eine Ausnahme tatsächlich ausgelöst oder handelt es sich nur um eine Debug-Meldung über eine Ausnahme der ersten Chance (d. H. Intern abgefangen und verarbeitet in der CLR)? Wenn Ersteres, was ist der Stack-Trace der Ausnahme? Erhalten Sie es immer noch, wenn Sie nur Console.WriteLine (kbd.flags)?Sobald Sie sich diese angesehen haben, möchten Sie möglicherweise eine separate Frage erstellen, da diese wahrscheinlich nicht mit der reinen Bit-Twiddling-Frage "Wie verwende ich bitweise Flags in C#?" Verbunden ist, eher ein Marshalling-Problem. – itowlson

3

Verwenden Sie den bitweisen AND-Operator zu überprüfen, ob das entsprechende Bit in den Flags Variable gesetzt ist:

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

Kompiliert nicht. In C# muss der 'if' Ausdruck ein bool sein; kbd.flags & LLKHF_INJECTED ist ein int. (Es würde jedoch in C/C++ funktionieren.) – itowlson

2

Sie müssen prüfen, dass die Bit-Flag gesetzt ist. Einfach mit bitweisen Operationen zu tun. Die Dokumentation besagt, dass Bit 4 für das injizierte Flag verwendet wird, Bit 4 (oder 5, wenn Sie das erste Bit als 1 zählen) ist gleich 16, also können Sie ein bitweises UND gegen das Flag ausführen.

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

Sie können mehr über bitweise Operationen erfahren hier:

+1

Bit 4 ist gleich 16. (Bit 4 ist das fünfte Bit, das von 0 bis 7 zählt.) – LukeH

+0

Guter Aufruf, habe nicht gesehen, dass sie in der Dokumentation nullindiziert wurden. – Skurmedel

11

.NET unterstützt dies mit dem [Flags] -Attribut:

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

Verwendungsbeispiel:

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

Der Grund jeder eine bitweise & zu verwenden, sagt, und dann vergleichen auf Null oder das Flag:

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