views:

211

answers:

5

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!

+5  A: 

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
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 `... is that changing the code?
cksubs
The extra parens aren't changing the code -- they just fix my silly precedence error. Answer updated.
itowlson
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
Also, you'll probably need to post your KBDLLHOOKSTRUCT declaration for us to figure out the exception and hook code issue.
itowlson
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!
cksubs
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
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.
cksubs
New question for this problem: http://stackoverflow.com/questions/2079868/marshal-ptrtostructure-throwing-system-argumentexception-error
cksubs
+2  A: 

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

if (kbd.flags & LLKHF_INJECTED)
{
    ...
}
Andrew Medico
itowlson
+1  A: 

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:

Skurmedel
Bit 4 equals 16. (Bit 4 is the fifth bit, counting from 0 to 7.)
LukeH
Good call, didn't see that they were zero indexed in the docs.
Skurmedel
+7  A: 

.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..
  }
Hans Passant
+1  A: 

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)
Courtney de Lautour