6

In my keyboard hook, each keypress gets a flag that states if it was injected or not. http://msdn.microsoft.com/en-us/library/ms644967(VS.85).aspx

I've distilled a KBDLLHOOKSTRUCT from the lParam. I can access kbd.flags.XXX. I just don't know how to convert this 8bit flag into an if (injected) {... type conditional that I know how to use.

If one of you smart computer-science types would help me out I'd really appreciate it.

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

        //if (injected) {...

Cheers!

ck_
  • 3,719
  • 10
  • 49
  • 76

5 Answers5

11

.NET supports this with the [Flags] attribute:

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

Sample usage:

  KBDLLHOOKSTRUCT info = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
  if ((info.flags & KbdHookFlags.Released) == KbdHookFlags.Released) {
    // Key was released
    // etc..
  }
itowlson
  • 73,686
  • 17
  • 161
  • 157
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
7

You need to bitwise-and it with a mask. For example, the injected bit is bit 4. That's binary 00010000, hex 0x10. So you bitwise-and it with 0x10, and see if anything's left:

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

(Of course, as per Andrew's answer, it would be a good idea to define a LLKHF_INJECTED constant for this rather than including the hex value directly in your code!)

itowlson
  • 73,686
  • 17
  • 161
  • 157
  • This (and others here that I've tried) is throwing a `A first chance exception of type 'System.ArgumentException' occurred in foofoo.exe` Seems to be messing up the previous keyboard hook code I had as well. What gives? It's also not compiling unless I add parentheses: `bool isInjected = ((kbd.flags & LLKHF_INJECTED) != 0);`... is that changing the code? – ck_ Jan 16 '10 at 02:14
  • The extra parens aren't changing the code -- they just fix my silly precedence error. Answer updated. – itowlson Jan 16 '10 at 02:52
  • No idea where the ArgumentException is coming from, as you are only reading from the flags field. Is an exception actually being thrown or is it just a debug message about a first-chance exception (i.e. caught and handled internally within the CLR)? If the former, what's the stack trace of the exception? Do you still get it if you just Console.WriteLine(kbd.flags)? Once you've looked into these, you might want to create a separate question because it's probably not related to the pure bit-twiddling question "how do I use bitwise flags in C#?", more likely a marshalling issue. – itowlson Jan 16 '10 at 02:58
  • Also, you'll probably need to post your KBDLLHOOKSTRUCT declaration for us to figure out the exception and hook code issue. – itowlson Jan 16 '10 at 02:59
  • ooo I think I figured out where it is... I have that KBD struct declaration and PtrToStruct Marshalling up in the original question, and then later have `int trueKeyPressed = Marshal.ReadInt32(lParam);`... I think the two Marshal commands on lParam are messing each other up or something. Does that make sense? Removing the first one makes the second one work again. Anyway, I'll try to figure this out later tonight. Thanks! – ck_ Jan 16 '10 at 03:08
  • Hmm, I don't see why a Marshal.ReadInt32(lParam) would mess up the Marshal.PtrToStructure. But you can't argue with a fix that works! \*grin\* Besides, the ReadInt32 is redundant once you've read the whole block into a struct: you can get the value direct from the struct. Congratulations on figuring it out! – itowlson Jan 16 '10 at 03:20
  • Yeah, it's weird... it's not that it's like overwriting the lParam or anything, but rather that the statement `Marshal.PtrToStructure(lParam, kbd);` is what's causing the error. If I have that line in there, 2 exceptions are thrown per key press and none of my event code that the keyboard hook is feeding is executed at all. – ck_ Jan 17 '10 at 02:47
  • New question for this problem: http://stackoverflow.com/questions/2079868/marshal-ptrtostructure-throwing-system-argumentexception-error – ck_ Jan 17 '10 at 03:47
2

Use the bitwise AND operator to check if the relevant bit is set in the flags variable:

if (kbd.flags & LLKHF_INJECTED)
{
    ...
}
nobody
  • 19,814
  • 17
  • 56
  • 77
  • 1
    Won't compile. In C#, the `if` expression has to be a bool; kbd.flags & LLKHF_INJECTED is an int. (It would work in C/C++ though.) – itowlson Jan 16 '10 at 01:23
2

You need to check that the bitflag is set. Easy to do with bitwise operations. The documentation states that bit four is used for the injected flag, bit 4 (or 5 if you count the first bit as 1) equals 16, so you can do a bitwise AND against the flag.

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

You can learn more about bitwise operations here:

Community
  • 1
  • 1
Skurmedel
  • 21,515
  • 5
  • 53
  • 66
2

The reason everyone is saying to use a bitwise & and then compare to zero or the flag:

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