捕获键盘快捷键并转发

本文关键字:转发 快捷键 键盘 | 更新日期: 2023-09-27 18:10:25

我需要做的事情:

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

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

到目前为止我所拥有的:

由于我们编写了其他应用程序,我们可以很容易地发送要处理的密钥,这不是问题。我可以得到应用程序的窗口句柄。我需要捕捉快捷键。我知道这个应用程序是用C++构建的。我正在寻找一种方法来捕捉Winforms中的以下事件:

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

目前,前锋关键部分的一切都在按预期进行。我只是错过了那个把手上的钥匙。我真的不想冒险钩住整个键盘,检测按键是否在我的应用程序中完成,我需要取消按键还是继续这个过程。我更希望只参加关键组合赛事。我宁愿不要收到那个家伙在输入文本框或其他东西时按下的所有信件。我真的在寻找任何以CTRLALTHIFT或它们的任何组合开头的东西

我想做的事情示例:

不受控制的应用程序: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#键盘挂钩,有了它,我可以做我需要的事情。

但这是一个复杂的代码,正如你所说,你不想把所有的键都按下。对于我的程序,我创建了一个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();

附言:如果你把这个放在你的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);