捕获键盘快捷键并转发

Fra*_*nck 6 c#

我需要做什么 :

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

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

到目前为止我所拥有的:

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

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
Run Code Online (Sandbox Code Playgroud)

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

我想做的例子:

不受控制的应用程序: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
Run Code Online (Sandbox Code Playgroud)

Jon*_*zzi 3

前段时间我必须做像你一样的事情,所以我找到了这篇文章:A Simple 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();
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)