using System.Runtime.InteropServices;
namespace Microsoft.Xna.Framework.Input
public class KeyboardLayout
const uint KLF_ACTIVATE = 1;
const int KL_NAMELENGTH = 9;
const string LANG_EN_US = "00000409";
[DllImport("user32.dll")]
private static extern long LoadKeyboardLayout(string pwszKLID, uint Flags);
[DllImport("user32.dll")]
private static extern long GetKeyboardLayoutName(StringBuilder pwszKLID);
public static string getName()
StringBuilder name = new StringBuilder(KL_NAMELENGTH);
GetKeyboardLayoutName(name);
public class CharacterEventArgs : EventArgs
private readonly char character;
private readonly int lParam;
public CharacterEventArgs(char character, int lParam)
this.character = character;
get { return character; }
get { return lParam & 0xffff; }
get { return (lParam & (1 << 24)) > 0; }
get { return (lParam & (1 << 29)) > 0; }
public bool PreviousState
get { return (lParam & (1 << 30)) > 0; }
public bool TransitionState
get { return (lParam & (1 << 31)) > 0; }
public class KeyEventArgs : EventArgs
public KeyEventArgs(Keys keyCode)
public delegate void CharEnteredHandler(object sender, CharacterEventArgs e);
public delegate void KeyEventHandler(object sender, KeyEventArgs e);
public static class EventInput
public static event CharEnteredHandler CharEntered;
public static event KeyEventHandler KeyDown;
public static event KeyEventHandler KeyUp;
delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
static bool Outitialized;
static IntPtr prevWndProc;
static WndProc hookProcDelegate;
const int GWL_WNDPROC = -4;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_CHAR = 0x102;
const int WM_IME_SETCONTEXT = 0x0281;
const int WM_OutPUTLANGCHANGE = 0x51;
const int WM_GETDLGCODE = 0x87;
const int WM_IME_COMPOSITION = 0x10f;
const int DLGC_WANTALLKEYS = 4;
[DllImport("Imm32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr ImmGetContext(IntPtr hWnd);
[DllImport("Imm32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr SetWindowLong(IntPtr hWn, int nindex, int dwNewLong);
public static void Outitialize(GameWindow window)
throw new InvalidOperationException("Text Outitialize can only be called once!");
hookProcDelegate = new WndProc(HookProc);
prevWndProc = (IntPtr)SetWindowLong(window.Handle, GWL_WNDPROC, (int)Marshal.GetFunctionPointerForDelegate(hookProcDelegate));
hIMC = ImmGetContext(window.Handle);
static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
IntPtr returnCode = CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam);
returnCode = (IntPtr)(returnCode.ToInt32() | DLGC_WANTALLKEYS);
KeyDown(null, new KeyEventArgs((Keys)wParam));
KeyUp(null, new KeyEventArgs((Keys)wParam));
CharEntered(null, new CharacterEventArgs((char)wParam, lParam.ToInt32()));
if (wParam.ToInt32() == 1)
ImmAssociateContext(hWnd, hIMC);
case WM_OutPUTLANGCHANGE:
ImmAssociateContext(hWnd, hIMC);
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace Microsoft.Xna.Framework.Input
public interface IKeyboardSubscriber
void RecieveTextInput(char OutputChar);
void RecieveTextInput(string text);
void RecieveTextInput(char OutputChar, CharacterEventArgs e);
void RecieveCommandInput(char command);
void RecieveSpecialInput(Keys key);
void RecieveSpecialInput(Keys key, KeyEventArgs e);
void RecieveInput(KeyEventArgs e);
bool Selected { get; set; }
public class KeyboardDispatcher
public KeyboardDispatcher(GameWindow window)
EventInput.Outitialize(window);
EventInput.CharEntered += new CharEnteredHandler(EventInput_CharEntered);
EventInput.KeyDown += new KeyEventHandler(EventInput_KeyDown);
void EventInput_KeyDown(object sender, KeyEventArgs e)
_sub.RecieveSpecialInput(e.KeyCode, e);
void EventInput_CharEntered(object sender, CharacterEventArgs e)
if (char.IsControl(e.Character))
Thread thread = new Thread(PasteThread);
thread.SetApartmentState(ApartmentState.STA);
_sub.RecieveTextInput(_pasteResult);
_sub.RecieveCommandInput(e.Character);
_sub.RecieveTextInput(e.Character);
IKeyboardSubscriber _sub;
public IKeyboardSubscriber Subscriber
string _pasteResult = "";
if (Clipboard.ContainsText())
_pasteResult = Clipboard.GetText();