明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1972|回复: 4

用键盘钩子定义全局快捷键

[复制链接]
发表于 2018-5-3 10:09:17 | 显示全部楼层 |阅读模式
折腾了很久终于通过键盘钩子解决了按ESC键响应事件,把关键的两个类贴出来供大家使用.QQ:570869611
  1.     public class Win32Api
  2.     {
  3.         public const int WM_KEYDOWN = 0x100;
  4.         public const int WM_KEYUP = 0x101;
  5.         public const int WM_SYSKEYDOWN = 0x104;
  6.         public const int WM_SYSKEYUP = 0x105;
  7.         public const int WH_KEYBOARD_LL = 13;
  8.         [StructLayout(LayoutKind.Sequential)]
  9.         public class KeyboardHookStruct
  10.         {
  11.             public int vkCode;
  12.             public int scanCode;
  13.             public int flags;
  14.             public int time;
  15.             public int dwExtraInfo;
  16.         }
  17.         public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
  18.         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  19.         public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
  20.         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  21.         public static extern bool UnhookWindowsHookEx(int idHook);
  22.         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  23.         public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
  24.         [DllImport("user32")]
  25.         public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
  26.         [DllImport("user32")]
  27.         public static extern int GetKeyboardState(byte[] pbKeyState);
  28.         [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  29.         public static extern IntPtr GetModuleHandle(string lpModuleName);
  30.     }
复制代码
  1. public class KeyboardHook
  2.     {
  3.         int hHook;
  4.         Win32Api.HookProc KeyboardHookDelegate;
  5.         public event KeyEventHandler OnKeyDownEvent;
  6.         public event KeyEventHandler OnKeyUpEvent;
  7.         public event KeyPressEventHandler OnKeyPressEvent;
  8.         public KeyboardHook() { }
  9.         public void SetHook()
  10.         {
  11.             KeyboardHookDelegate = new Win32Api.HookProc(KeyboardHookProc);
  12.             Process cProcess = Process.GetCurrentProcess();
  13.             ProcessModule cModule = cProcess.MainModule;
  14.             var mh = Win32Api.GetModuleHandle(cModule.ModuleName);
  15.             hHook = Win32Api.SetWindowsHookEx(Win32Api.WH_KEYBOARD_LL, KeyboardHookDelegate, mh, 0);
  16.         }
  17.         public void UnHook()
  18.         {
  19.             Win32Api.UnhookWindowsHookEx(hHook);
  20.         }
  21.         private List<Keys> preKeysList = new List<Keys>();
  22.         private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
  23.         {
  24.             if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))
  25.             {
  26.                 Win32Api.KeyboardHookStruct KeyDataFromHook = (Win32Api.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.KeyboardHookStruct));
  27.                 Keys keyData = (Keys)KeyDataFromHook.vkCode;
  28.                 if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN))
  29.                 {
  30.                     if (IsCtrlAltShiftKeys(keyData) && preKeysList.IndexOf(keyData) == -1)
  31.                     {
  32.                         preKeysList.Add(keyData);
  33.                     }
  34.                 }
  35.                 if (OnKeyDownEvent != null && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN))
  36.                 {
  37.                     KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));

  38.                     OnKeyDownEvent(this, e);
  39.                 }
  40.                 if (OnKeyPressEvent != null && wParam == Win32Api.WM_KEYDOWN)
  41.                 {
  42.                     byte[] keyState = new byte[256];
  43.                     Win32Api.GetKeyboardState(keyState);

  44.                     byte[] inBuffer = new byte[2];
  45.                     if (Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1)
  46.                     {
  47.                         KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]);
  48.                         OnKeyPressEvent(this, e);
  49.                     }
  50.                 }
  51.                 if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
  52.                 {
  53.                     if (IsCtrlAltShiftKeys(keyData))
  54.                     {
  55.                         for (int i = preKeysList.Count - 1; i >= 0; i--)
  56.                         {
  57.                             if (preKeysList[i] == keyData) { preKeysList.RemoveAt(i); }
  58.                         }
  59.                     }
  60.                 }
  61.                 if (OnKeyUpEvent != null && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
  62.                 {
  63.                     KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));
  64.                     OnKeyUpEvent(this, e);
  65.                 }
  66.             }
  67.             return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
  68.         }
  69.         private Keys GetDownKeys(Keys key)
  70.         {
  71.             Keys rtnKey = Keys.None;
  72.             foreach (Keys i in preKeysList)
  73.             {
  74.                 if (i == Keys.LControlKey || i == Keys.RControlKey) { rtnKey = rtnKey | Keys.Control; }
  75.                 if (i == Keys.LMenu || i == Keys.RMenu) { rtnKey = rtnKey | Keys.Alt; }
  76.                 if (i == Keys.LShiftKey || i == Keys.RShiftKey) { rtnKey = rtnKey | Keys.Shift; }
  77.             }
  78.             return rtnKey | key;
  79.         }
  80.         private Boolean IsCtrlAltShiftKeys(Keys key)
  81.         {
  82.             if (key == Keys.LControlKey || key == Keys.RControlKey || key == Keys.LMenu || key == Keys.RMenu || key == Keys.LShiftKey || key == Keys.RShiftKey) { return true; }
  83.             return false;
  84.         }
  85.     }
调用方法

  1.         static KeyboardHook hook;

  2.         [CommandMethod("KeyboardHook")]
  3.         public static void CommandName()
  4.         {
  5.             hook = new KeyboardHook();
  6.             hook.SetHook();
  7.             hook.OnKeyDownEvent += Hook_OnKeyDownEvent;
  8.         }

  9.         private static void Hook_OnKeyDownEvent(object sender, KeyEventArgs e)
  10.         {
  11.             if (e.KeyData == Keys.Escape)
  12.             {
  13.                 System.Windows.Forms.MessageBox.Show("你按了ESC键");
  14.             }
  15.         }





发表于 2018-5-3 10:16:58 | 显示全部楼层
多谢分享,谢谢!
发表于 2022-12-7 13:39:54 来自手机 | 显示全部楼层
多谢分享,仅Esc键没意思,如何响应其他按键?例如单字母按键a,b,组合键Ctrl+a,shift+b,下箭头等等
发表于 2022-12-31 21:50:43 | 显示全部楼层
pxt2001 发表于 2022-12-7 13:39
多谢分享,仅Esc键没意思,如何响应其他按键?例如单字母按键a,b,组合键Ctrl+a,shift+b,下箭头等等

https://blog.csdn.net/ipzlkmy/article/details/7296832

https://blog.csdn.net/gaiazhang/article/details/53942531
发表于 2023-1-4 15:33:45 | 显示全部楼层
如果只是在cad里用,建议用cad自带的钩子,dllimport不稳定
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-28 22:06 , Processed in 0.256193 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表