/// <summary> /// Convert wParam and lParam to a key. /// </summary> private Key TranslateKey(ulong wParam, ulong lParam) { switch (wParam) { // Control keys require special handling. case (uint)VirtualKey.CONTROL when(lParam& 0x01000000) != 0: return(Key.RightControl); case (uint)VirtualKey.CONTROL: { uint time = User32.GetMessageTime(); // HACK: Alt Gr sends Left Ctrl and then Right Alt in close sequence // We only want the Right Alt message, so if the next message is // Right Alt we ignore this (synthetic) Left Ctrl message if (!User32.PeekMessage(out Message next, IntPtr.Zero, 0, 0, PeekMessageFlags.PM_NOREMOVE)) { return(Key.LeftControl); } if (next.Value != WM.KEYDOWN && next.Value != WM.SYSKEYDOWN && next.Value != WM.KEYUP && next.Value != WM.SYSKEYUP) { return(Key.LeftControl); } if ((uint)next.WParam == (uint)VirtualKey.MENU && ((uint)next.LParam & 0x01000000) != 0 && next.Time == time) { // Next message is Right Alt down so discard this return(Key.Unknown); } return(Key.LeftControl); } // IME notifies that keys have been filtered by setting the virtual // key-code to VK_PROCESSKEY case (uint)VirtualKey.PROCESSKEY: return(Key.Unknown); } int index = NativeHelpers.HiWord(lParam) & 0x1FF; if (index < 0 || index >= _keyCodes.Length) { return(Key.Unknown); } return(_keyCodes[index]); }