捕获键盘快捷键并转发

我需要做什么 :

我需要从特定应用程序中捕获所有快捷键,例如Ctrl + S. 任何关键组合,即使它不是该应用程序的快捷方式。

然后我的中途应用程序捕获这些密钥需要validation这些密钥组合,并检查我们正在运行的另一个应用程序是否可以响应该密钥,以及是否可以将命令发送给它。

到目前为止我所拥有的:

由于我们编写了其他应用程序,因此我们可以轻松发送要处理的密钥,这不是问题。 我可以得到应用程序的窗口句柄。 我需要捕获快捷键。 这个应用程序我知道它是用C ++构建的。 我希望找到一种方法来捕获Winforms中的以下事件的等价物:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 

现在一切都在前进关键部分按预期工作。 我只是错过了该句柄上的键的捕获。 我真的不想冒险自己勾住整个键盘并检测是否在我的应用程序中完成击键,我是否需要取消键或继续该过程。 我也希望只获得关键组合事件。 当他输入一个文本框或任何东西时,我宁愿不接收那个人按下的所有字母。 我真的在寻找以CTRLALTSHIFT或它们的任意组合开头的任何东西

我想做的例子:

不受控制的应用程序:Notepad.exe我的中途应用程序:ShortcutHandler.exe我的目标应用程序:A.exe,B.exe

ShortcutHandler.exe将侦听Notepad.Exe快捷方式,然后将它们转发到A.exe和B.exe

情况:

 1 - in Notepad.exe press CTRL+H for replace 2 - ShortcutHandler.exe detect CTRL+H pressed on Notepad.exe 3 - ShortcutHandler.exe Analyse CTRL+H and knows it need to do some task 4 - ShortcutHandler.exe call Save on A.exe in reaction to CTRL+H in Notepad.exe 5 - ShortcutHandler.exe call Print report in B.exe in reaction to CTRL+H in Notepad.exe 

前段时间我必须做一些像你这样的事情,所以我找到了这篇文章: 一个简单的C#Keyboard Hook ,有了这个我能够做我需要的东西。

但这是一个复杂的代码,正如你所说,你不希望得到所有的密钥。 对于我的程序,我创建了一个KeyboardHook类,可以轻松使用上一篇文章中获得的代码。

所以你可以用KeyboardHook类做一个代码片段:

 // Put this on the begin of your form (like the constructor on FormLoad). var hook = new KeyboardHook(); hook.KeyDown += (sender, e) => { // e.Control is a bool property if true Control is press. // e.Shift is a bool property if true Shift is press. // e.Key has a key that was press. // This if ignores anything that don't begin with Control or Shift. if(!e.Control && !e.Shift) return; // your code below: if(e.Control && e.Key == Keys.H) { // do your code here. // like: Analyse CTRL+H and knows it need to do some task. } }; hook.Start(); // Until here goes in the begin of your form. // Put this on the end of your form (like in the Dispose or FormClose). hook.Release(); hook.Dispose(); 

PS:如果你把它放在你的ShortcutHandler应用程序上,应用程序仍会获得密钥。

以下是KeyboardHook代码:

 using System.Runtime.InteropServices; using System.Windows.Forms; public class KeyboardHook : IDisposable { #region Fields private bool _lControlKeyIsDown; private bool _rControlKeyIsDown; private bool _lShiftKeyIsDown; private bool _rShiftKeyIsDown; #endregion #region Properties private bool ControlIsDown { get { return _lControlKeyIsDown || _rControlKeyIsDown; } } private bool ShiftIsDown { get { return _lShiftKeyIsDown || _rShiftKeyIsDown; } } #endregion #region Constructors public KeyboardHook() { _proc = HookCallback; } #endregion #region Events public event HookKeyDownHandler KeyDown; #endregion #region Methods public void Start() { _hookID = SetHook(_proc); } private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (var curProcess = Process.GetCurrentProcess()) using (var curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0) { var vkCode = Marshal.ReadInt32(lParam); var key = (Keys)vkCode; if (wParam == (IntPtr)WM_KEYDOWN) { switch (key) { case Keys.LControlKey: _lControlKeyIsDown = true; break; case Keys.RControlKey: _rControlKeyIsDown = true; break; case Keys.LShiftKey: _lShiftKeyIsDown = true; break; case Keys.RShiftKey: _rShiftKeyIsDown = true; break; default: if (KeyDown != null) { var args = new HookKeyDownEventArgs((Keys)vkCode, ShiftIsDown, ControlIsDown); KeyDown(this, args); } break; } } if (wParam == (IntPtr)WM_KEYUP) { switch (key) { case Keys.LControlKey: _lControlKeyIsDown = false; break; case Keys.RControlKey: _rControlKeyIsDown = false; break; case Keys.LShiftKey: _lShiftKeyIsDown = false; break; case Keys.RShiftKey: _rShiftKeyIsDown = false; break; } } } return CallNextHookEx(_hookID, nCode, wParam, lParam); } public void Release() { UnhookWindowsHookEx(_hookID); } public void Dispose() { Release(); } #endregion #region Interoperability private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private const int WM_KEYUP = 0x0101; private readonly LowLevelKeyboardProc _proc; private IntPtr _hookID = IntPtr.Zero; private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); #endregion } public class HookKeyDownEventArgs : EventArgs { #region Fields private readonly Keys _key; private readonly bool _shift; private readonly bool _control; #endregion #region Properties public Keys Key { get { return _key; } } public bool Shift { get { return _shift; } } public bool Control { get { return _control; } } #endregion #region Constructors public HookKeyDownEventArgs(Keys key, bool shift, bool control) { _key = key; _shift = shift; _control = control; } #endregion } public delegate void HookKeyDownHandler(object sender, HookKeyDownEventArgs e);