用键盘钩子定义全局快捷键
折腾了很久终于通过键盘钩子解决了按ESC键响应事件,把关键的两个类贴出来供大家使用.QQ:570869611public class Win32Api
{
public const int WM_KEYDOWN = 0x100;
public const int WM_KEYUP = 0x101;
public const int WM_SYSKEYDOWN = 0x104;
public const int WM_SYSKEYUP = 0x105;
public const int WH_KEYBOARD_LL = 13;
public class KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
public static extern bool UnhookWindowsHookEx(int idHook);
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
public static extern int GetKeyboardState(byte[] pbKeyState);
public static extern IntPtr GetModuleHandle(string lpModuleName);
} public class KeyboardHook
{
int hHook;
Win32Api.HookProc KeyboardHookDelegate;
public event KeyEventHandler OnKeyDownEvent;
public event KeyEventHandler OnKeyUpEvent;
public event KeyPressEventHandler OnKeyPressEvent;
public KeyboardHook() { }
public void SetHook()
{
KeyboardHookDelegate = new Win32Api.HookProc(KeyboardHookProc);
Process cProcess = Process.GetCurrentProcess();
ProcessModule cModule = cProcess.MainModule;
var mh = Win32Api.GetModuleHandle(cModule.ModuleName);
hHook = Win32Api.SetWindowsHookEx(Win32Api.WH_KEYBOARD_LL, KeyboardHookDelegate, mh, 0);
}
public void UnHook()
{
Win32Api.UnhookWindowsHookEx(hHook);
}
private List<Keys> preKeysList = new List<Keys>();
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))
{
Win32Api.KeyboardHookStruct KeyDataFromHook = (Win32Api.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.KeyboardHookStruct));
Keys keyData = (Keys)KeyDataFromHook.vkCode;
if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN))
{
if (IsCtrlAltShiftKeys(keyData) && preKeysList.IndexOf(keyData) == -1)
{
preKeysList.Add(keyData);
}
}
if (OnKeyDownEvent != null && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN))
{
KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));
OnKeyDownEvent(this, e);
}
if (OnKeyPressEvent != null && wParam == Win32Api.WM_KEYDOWN)
{
byte[] keyState = new byte;
Win32Api.GetKeyboardState(keyState);
byte[] inBuffer = new byte;
if (Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1)
{
KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer);
OnKeyPressEvent(this, e);
}
}
if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
{
if (IsCtrlAltShiftKeys(keyData))
{
for (int i = preKeysList.Count - 1; i >= 0; i--)
{
if (preKeysList == keyData) { preKeysList.RemoveAt(i); }
}
}
}
if (OnKeyUpEvent != null && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
{
KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));
OnKeyUpEvent(this, e);
}
}
return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
}
private Keys GetDownKeys(Keys key)
{
Keys rtnKey = Keys.None;
foreach (Keys i in preKeysList)
{
if (i == Keys.LControlKey || i == Keys.RControlKey) { rtnKey = rtnKey | Keys.Control; }
if (i == Keys.LMenu || i == Keys.RMenu) { rtnKey = rtnKey | Keys.Alt; }
if (i == Keys.LShiftKey || i == Keys.RShiftKey) { rtnKey = rtnKey | Keys.Shift; }
}
return rtnKey | key;
}
private Boolean IsCtrlAltShiftKeys(Keys key)
{
if (key == Keys.LControlKey || key == Keys.RControlKey || key == Keys.LMenu || key == Keys.RMenu || key == Keys.LShiftKey || key == Keys.RShiftKey) { return true; }
return false;
}
}调用方法
static KeyboardHook hook;
public static void CommandName()
{
hook = new KeyboardHook();
hook.SetHook();
hook.OnKeyDownEvent += Hook_OnKeyDownEvent;
}
private static void Hook_OnKeyDownEvent(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Escape)
{
System.Windows.Forms.MessageBox.Show("你按了ESC键");
}
}
多谢分享,谢谢! 多谢分享,仅Esc键没意思,如何响应其他按键?例如单字母按键a,b,组合键Ctrl+a,shift+b,下箭头等等 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 如果只是在cad里用,建议用cad自带的钩子,dllimport不稳定
页:
[1]