作为我正在研究的媒体播放器应用程序的一部分,我想要连接媒体控制键的全局按键(播放,跳过,跳回等).
我一直在寻找大约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 for local hook. eller hwnd til user32 for global 0); //0 for global hook. eller thread for hooken } else { HookID = SetWindowsHookEx(HookType.WH_KEYBOARD,//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 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,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,GetAltPressed()); } if (kEvent == KeyEvents.KeyUp || kEvent == KeyEvents.SKeyUp) { if (KeyUp != null) KeyUp((Keys)vkCode,GetAltPressed()); } } } catch (Exception) { //Ignore all errors... } return CallNextHookEx(HookID,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 Alt) { Debug.WriteLine("The Key: " + key); } }
它可以用一些代码清理,但我没有打扰,因为它的工作原理.