作为我正在研究的媒体播放器应用程序的一部分,我想要连接媒体控制键的全局按键(播放,跳过,跳回等).
我一直在寻找大约2个小时试图寻找解决方案 - 但我找不到一个有效的方法.我找到了几个关于同一件事的Stackoverflow答案,但没有一个有效.
我尝试了MouseKeyHook
NuGet包,但它永远不会触发事件.我也试过了这个FMUtils.KeyboardHook
包,但是同样的事情发生了,除了它在控制台中打印出它在启动后立即关闭了钩子 - 我不知道为什么,查看源代码后的事件.
我试图得到这个代码项目项目http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H但我甚至无法运行演示,这两个演示只是抛出了我无法追查的奇怪错误.
我的问题是,在我的Winforms应用程序没有聚焦时,我可以用来捕获键盘按下的.net 4.0中的键盘按键的工作方式是什么?
以下是我过去十年中用于多个项目的代码.应该没有问题(对于Windows上的任何.Net版本).希望它能帮到你.
public class KeyboardHook : IDisposable { bool Global = false; public delegate void LocalKeyEventHandler(Keys key, bool Shift, bool Ctrl, bool Alt); public event LocalKeyEventHandler KeyDown; public event LocalKeyEventHandler KeyUp; public delegate int CallbackDelegate(int Code, int W, int L); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct KBDLLHookStruct { public Int32 vkCode; public Int32 scanCode; public Int32 flags; public Int32 time; public Int32 dwExtraInfo; } [DllImport("user32", CallingConvention = CallingConvention.StdCall)] private static extern int SetWindowsHookEx(HookType idHook, CallbackDelegate lpfn, int hInstance, int threadId); [DllImport("user32", CallingConvention = CallingConvention.StdCall)] private static extern bool UnhookWindowsHookEx(int idHook); [DllImport("user32", CallingConvention = CallingConvention.StdCall)] private static extern int CallNextHookEx(int idHook, int nCode, int wParam, int lParam); [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)] private static extern int GetCurrentThreadId(); public enum HookType : int { WH_JOURNALRECORD = 0, WH_JOURNALPLAYBACK = 1, WH_KEYBOARD = 2, WH_GETMESSAGE = 3, WH_CALLWNDPROC = 4, WH_CBT = 5, WH_SYSMSGFILTER = 6, WH_MOUSE = 7, WH_HARDWARE = 8, WH_DEBUG = 9, WH_SHELL = 10, WH_FOREGROUNDIDLE = 11, WH_CALLWNDPROCRET = 12, WH_KEYBOARD_LL = 13, WH_MOUSE_LL = 14 } private int HookID = 0; CallbackDelegate TheHookCB = null; //Start hook public KeyboardHook(bool Global) { this.Global = Global; TheHookCB = new CallbackDelegate(KeybHookProc); if (Global) { HookID = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, TheHookCB, 0, //0 for local hook. eller hwnd til user32 for global 0); //0 for global hook. eller thread for hooken } else { HookID = SetWindowsHookEx(HookType.WH_KEYBOARD, TheHookCB, 0, //0 for local hook. or hwnd to user32 for global GetCurrentThreadId()); //0 for global hook. or thread for the hook } } bool IsFinalized = false; ~KeyboardHook() { if (!IsFinalized) { UnhookWindowsHookEx(HookID); IsFinalized = true; } } public void Dispose() { if (!IsFinalized) { UnhookWindowsHookEx(HookID); IsFinalized = true; } } //The listener that will trigger events private int KeybHookProc(int Code, int W, int L) { KBDLLHookStruct LS = new KBDLLHookStruct(); if (Code < 0) { return CallNextHookEx(HookID, Code, W, L); } try { if (!Global) { if (Code == 3) { IntPtr ptr = IntPtr.Zero; int keydownup = L >> 30; if (keydownup == 0) { if (KeyDown != null) KeyDown((Keys)W, GetShiftPressed(), GetCtrlPressed(), GetAltPressed()); } if (keydownup == -1) { if (KeyUp != null) KeyUp((Keys)W, GetShiftPressed(), GetCtrlPressed(), GetAltPressed()); } //System.Diagnostics.Debug.WriteLine("Down: " + (Keys)W); } } else { KeyEvents kEvent = (KeyEvents)W; Int32 vkCode = Marshal.ReadInt32((IntPtr)L); //Leser vkCode som er de første 32 bits hvor L peker. if (kEvent != KeyEvents.KeyDown && kEvent != KeyEvents.KeyUp && kEvent != KeyEvents.SKeyDown && kEvent != KeyEvents.SKeyUp) { } if (kEvent == KeyEvents.KeyDown || kEvent == KeyEvents.SKeyDown) { if (KeyDown != null) KeyDown((Keys)vkCode, GetShiftPressed(), GetCtrlPressed(), GetAltPressed()); } if (kEvent == KeyEvents.KeyUp || kEvent == KeyEvents.SKeyUp) { if (KeyUp != null) KeyUp((Keys)vkCode, GetShiftPressed(), GetCtrlPressed(), GetAltPressed()); } } } catch (Exception) { //Ignore all errors... } return CallNextHookEx(HookID, Code, W, L); } public enum KeyEvents { KeyDown = 0x0100, KeyUp = 0x0101, SKeyDown = 0x0104, SKeyUp = 0x0105 } [DllImport("user32.dll")] static public extern short GetKeyState(System.Windows.Forms.Keys nVirtKey); public static bool GetCapslock() { return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.CapsLock)) & true; } public static bool GetNumlock() { return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.NumLock)) & true; } public static bool GetScrollLock() { return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.Scroll)) & true; } public static bool GetShiftPressed() { int state = GetKeyState(System.Windows.Forms.Keys.ShiftKey); if (state > 1 || state < -1) return true; return false; } public static bool GetCtrlPressed() { int state = GetKeyState(System.Windows.Forms.Keys.ControlKey); if (state > 1 || state < -1) return true; return false; } public static bool GetAltPressed() { int state = GetKeyState(System.Windows.Forms.Keys.Menu); if (state > 1 || state < -1) return true; return false; } }
测试应用:
static class Program { [STAThread] static void Main() { var kh = new KeyboardHook(true); kh.KeyDown += Kh_KeyDown; Application.Run(); } private static void Kh_KeyDown(Keys key, bool Shift, bool Ctrl, bool Alt) { Debug.WriteLine("The Key: " + key); } }
它可以用一些代码清理,但我没有打扰,因为它的工作原理.