加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#Hook全局键盘事件 – .net 4.0

发布时间:2020-12-16 03:22:37 所属栏目:百科 来源:网络整理
导读:作为我正在研究的媒体播放器应用程序的一部分,我想要连接媒体控制键的全局按键(播放,跳过,跳回等). 我一直在寻找大约2个小时试图寻找解决方案 – 但我找不到一个有效的方法.我发现了几个关于同一件事的Stackoverflow答案,但没有一个有效. 我尝试了 MouseKeyH
作为我正在研究的媒体播放器应用程序的一部分,我想要连接媒体控制键的全局按键(播放,跳过,跳回等).

我一直在寻找大约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);
    }
}

它可以用一些代码清理,但我没有打扰,因为它的工作原理.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读