title: Hooked keyboard duplicating input (c# / xna)
body: <p>I'm using a Keyboard hook in my XNA project (anyone who uses XNA knows how useless the built in keyboard class is for "text box" style typed input.</p>
  
  <p>It works just fine for use in XNA projects, until forms are introduced. If I try to implement any form in the project, be it a custom form, or even just an OpenFileDialog, any key press inside a text box of the form is doubled, making typing just about impossible.</p>
  
  <p>Does anyone know how I can stop the message from reaching the forms twice? perhaps by discarding the message when I get it? Perhaps there is a better solution? or perhaps its just something that cant be done.</p>
  
  <p>Any help is appreciated.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Below is the keyboard hooking code I'm using, It may be familiar to anyone who's gone looking for XNA keyboard hooking as it seems to crop up wherever I looked for it.</p>
  
  <pre><code>using System;
  using System.Runtime.InteropServices;
  using System.Windows.Forms; // This class exposes WinForms-style key events.
  
  namespace FatLib.Controls
  {
      class KeyboardHookInput : IDisposable
      {
          private string _buffer = "";
          private bool _backSpace = false;
          private bool _enterKey = false; // I added this to the original code
  
          public string Buffer
          {
              get { return _buffer; }
          }
          public bool BackSpace
          {
              get
              {
                  return _backSpace;
              }
          }
          public bool EnterKey
          {
              get
              {
                  return _enterKey;
              }
          }
          public void Reset()
          {
              _buffer = "";
              _backSpace = false;
              _enterKey = false;
          }
  
          public enum HookId
          {
              // Types of hook that can be installed using the SetWindwsHookEx function.
              WH_CALLWNDPROC = 4,
              WH_CALLWNDPROCRET = 12,
              WH_CBT = 5,
              WH_DEBUG = 9,
              WH_FOREGROUNDIDLE = 11,
              WH_GETMESSAGE = 3,
              WH_HARDWARE = 8,
              WH_JOURNALPLAYBACK = 1,
              WH_JOURNALRECORD = 0,
              WH_KEYBOARD = 2,
              WH_KEYBOARD_LL = 13,
              WH_MAX = 11,
              WH_MAXHOOK = WH_MAX,
              WH_MIN = -1,
              WH_MINHOOK = WH_MIN,
              WH_MOUSE_LL = 14,
              WH_MSGFILTER = -1,
              WH_SHELL = 10,
              WH_SYSMSGFILTER = 6,
          };
          public enum WindowMessage
          {
              // Window message types.
              WM_KEYDOWN = 0x100,
              WM_KEYUP = 0x101,
              WM_CHAR = 0x102,
          };
  
          // A delegate used to create a hook callback.
          public delegate int GetMsgProc(int nCode, int wParam, ref Message msg);
  
          /// &lt;summary&gt;
          /// Install an application-defined hook procedure into a hook chain.
          /// &lt;/summary&gt;
          /// &lt;param name="idHook"&gt;Specifies the type of hook procedure to be installed.&lt;/param&gt;
          /// &lt;param name="lpfn"&gt;Pointer to the hook procedure.&lt;/param&gt;
          /// &lt;param name="hmod"&gt;Handle to the DLL containing the hook procedure pointed to by the lpfn parameter.&lt;/param&gt;
          /// &lt;param name="dwThreadId"&gt;Specifies the identifier of the thread with which the hook procedure is to be associated.&lt;/param&gt;
          /// &lt;returns&gt;If the function succeeds, the return value is the handle to the hook procedure. Otherwise returns 0.&lt;/returns&gt;
          [DllImport("user32.dll", EntryPoint = "SetWindowsHookExA")]
          public static extern IntPtr SetWindowsHookEx(HookId idHook, GetMsgProc lpfn, IntPtr hmod, int dwThreadId);
  
          /// &lt;summary&gt;
          /// Removes a hook procedure installed in a hook chain by the SetWindowsHookEx function. 
          /// &lt;/summary&gt;
          /// &lt;param name="hHook"&gt;Handle to the hook to be removed. This parameter is a hook handle obtained by a previous call to SetWindowsHookEx.&lt;/param&gt;
          /// &lt;returns&gt;If the function fails, the return value is zero. To get extended error information, call GetLastError.&lt;/returns&gt;
          [DllImport("user32.dll")]
          public static extern int UnhookWindowsHookEx(IntPtr hHook);
  
          /// &lt;summary&gt;
          /// Passes the hook information to the next hook procedure in the current hook chain.
          /// &lt;/summary&gt;
          /// &lt;param name="hHook"&gt;Ignored.&lt;/param&gt;
          /// &lt;param name="ncode"&gt;Specifies the hook code passed to the current hook procedure.&lt;/param&gt;
          /// &lt;param name="wParam"&gt;Specifies the wParam value passed to the current hook procedure.&lt;/param&gt;
          /// &lt;param name="lParam"&gt;Specifies the lParam value passed to the current hook procedure.&lt;/param&gt;
          /// &lt;returns&gt;This value is returned by the next hook procedure in the chain.&lt;/returns&gt;
          [DllImport("user32.dll")]
          public static extern int CallNextHookEx(int hHook, int ncode, int wParam, ref Message lParam);
  
          /// &lt;summary&gt;
          /// Translates virtual-key messages into character messages.
          /// &lt;/summary&gt;
          /// &lt;param name="lpMsg"&gt;Pointer to an Message structure that contains message information retrieved from the calling thread's message queue.&lt;/param&gt;
          /// &lt;returns&gt;If the message is translated (that is, a character message is posted to the thread's message queue), the return value is true.&lt;/returns&gt;
          [DllImport("user32.dll")]
          public static extern bool TranslateMessage(ref Message lpMsg);
  
  
          /// &lt;summary&gt;
          /// Retrieves the thread identifier of the calling thread.
          /// &lt;/summary&gt;
          /// &lt;returns&gt;The thread identifier of the calling thread.&lt;/returns&gt;
          [DllImport("kernel32.dll")]
          public static extern int GetCurrentThreadId();
  
          // Handle for the created hook.
          private readonly IntPtr HookHandle;
  
          private readonly GetMsgProc ProcessMessagesCallback;
  
          public KeyboardHookInput()
          {
              // Create the delegate callback:
              this.ProcessMessagesCallback = new GetMsgProc(ProcessMessages);
              // Create the keyboard hook:
              this.HookHandle = SetWindowsHookEx(HookId.WH_KEYBOARD, this.ProcessMessagesCallback, IntPtr.Zero, GetCurrentThreadId());
          }
  
          public void Dispose()
          {
              // Remove the hook.
              if (HookHandle != IntPtr.Zero) UnhookWindowsHookEx(HookHandle);
          }
  
          // comments found in this region are all from the original author: Darg.
          private int ProcessMessages(int nCode, int wParam, ref Message msg)
          {
              // Check if we must process this message (and whether it has been retrieved via GetMessage):
              if (nCode == 0 &amp;&amp; wParam == 1)
              {
                  // We need character input, so use TranslateMessage to generate WM_CHAR messages.
                  TranslateMessage(ref msg);
  
                  // If it's one of the keyboard-related messages, raise an event for it:
                  switch ((WindowMessage)msg.Msg)
                  {
                      case WindowMessage.WM_CHAR:
                          this.OnKeyPress(new KeyPressEventArgs((char)msg.WParam));
                          break;
                      case WindowMessage.WM_KEYDOWN:
                          this.OnKeyDown(new KeyEventArgs((Keys)msg.WParam));
                          break;
                      case WindowMessage.WM_KEYUP:
                          this.OnKeyUp(new KeyEventArgs((Keys)msg.WParam));
                          break;
                  }
              }
              // Call next hook in chain:
              return CallNextHookEx(0, nCode, wParam, ref msg);
          }
  
          public event KeyEventHandler KeyUp;
          protected virtual void OnKeyUp(KeyEventArgs e)
          {
              if (KeyUp != null) KeyUp(this, e);
          }
  
          public event KeyEventHandler KeyDown;
          protected virtual void OnKeyDown(KeyEventArgs e)
          {
              if (KeyDown != null) KeyDown(this, e);
          }
  
          public event KeyPressEventHandler KeyPress;
          protected virtual void OnKeyPress(KeyPressEventArgs e)
          {
              if (KeyPress != null) KeyPress(this, e);
              if (e.KeyChar.GetHashCode().ToString() == "524296")
              {
                  _backSpace = true;
              }
              else if (e.KeyChar == (char)Keys.Enter)
              {
                  _enterKey = true;
              }
              else
              {
                  _buffer += e.KeyChar;
              }
          }
      }
  }
  </code></pre>