C# 如何创建非窗口绑定的键盘快捷键

C# 如何创建非窗口绑定的键盘快捷键,c#,windows,keyboard-shortcuts,global,C#,Windows,Keyboard Shortcuts,Global,我正在创建一个C#应用程序,可以是WinForm,但最好是控制台应用程序,它需要捕获键盘快捷键,即使应用程序不在前台。一个人如何做到这一点,我知道这是可能的,因为鸣鸟可以做到这一点 此键盘快捷键的格式为ctrl+-> 到目前为止,我还没有任何代码,因为我甚至不知道如何全局注册键盘快捷键。这可以通过Windows钩子的低级键盘钩子来完成 下面是一个示例,演示了整个过程。这可以通过Windows钩子捕获通过低级键盘钩子完成 下面是一个演示整个过程的示例。一种可能的方法是使用Windows挂钩。 但为

我正在创建一个C#应用程序,可以是WinForm,但最好是控制台应用程序,它需要捕获键盘快捷键,即使应用程序不在前台。一个人如何做到这一点,我知道这是可能的,因为鸣鸟可以做到这一点

此键盘快捷键的格式为ctrl+->
到目前为止,我还没有任何代码,因为我甚至不知道如何全局注册键盘快捷键。

这可以通过Windows钩子的低级键盘钩子来完成


下面是一个示例,演示了整个过程。

这可以通过Windows钩子捕获通过低级键盘钩子完成


下面是一个演示整个过程的示例。

一种可能的方法是使用Windows挂钩。 但为了做到这一点,您需要创建一个本机DLL,并在其中编写回调函数作为钩子安装


查找起点。还有很多关于如何使用它的在线示例。

一种可能的方法是使用Windows挂钩。 但为了做到这一点,您需要创建一个本机DLL,并在其中编写回调函数作为钩子安装

查找起点。还有很多关于如何使用它的在线示例。

你应该使用而不是键盘挂钩

当您只需要一个全局热键时,使用全局键盘挂钩是对api的滥用。它也会对性能产生负面影响,因为每个键在到达目标程序之前都需要由您的程序进行处理。

您应该使用而不是键盘挂钩


当您只需要一个全局热键时,使用全局键盘挂钩是对api的滥用。它也会对性能产生负面影响,因为每个密钥在到达目标程序之前都需要由您的程序进行处理。

这里是一个示例代码,希望对您有所帮助。。。(祝你好运!!!)

用法:

            _hotKey0 = new HotKey(Key.F9, KeyModifier.Shift | KeyModifier.Win, OnHotKeyHandler);

类别:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Mime;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;

namespace UnManaged
{
    public class HotKey : IDisposable
    {
        private static Dictionary<int, HotKey> _dictHotKeyToCalBackProc;

        [DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, UInt32 fsModifiers, UInt32 vlc);

        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        public const int WmHotKey = 0x0312;

        private bool _disposed = false;

        public Key Key { get; private set; }
        public KeyModifier KeyModifiers { get; private set; }
        public Action<HotKey> Action { get; private set; }
        public int Id { get; set; }

        // ******************************************************************
        public HotKey(Key k, KeyModifier keyModifiers, Action<HotKey> action, bool register = true)
        {
            Key = k;
            KeyModifiers = keyModifiers;
            Action = action;
            if (register)
            {
                Register();
            }
        }

        // ******************************************************************
        public bool Register()
        {
            int virtualKeyCode = KeyInterop.VirtualKeyFromKey(Key);
            Id = virtualKeyCode + ((int)KeyModifiers * 0x10000);
            bool result = RegisterHotKey(IntPtr.Zero, Id, (UInt32)KeyModifiers, (UInt32)virtualKeyCode);

            if (_dictHotKeyToCalBackProc == null)
            {
                _dictHotKeyToCalBackProc = new Dictionary<int, HotKey>();
                ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
            }

            _dictHotKeyToCalBackProc.Add(Id, this);

            Debug.Print(result.ToString() + ", " + Id + ", " + virtualKeyCode);
            return result;
        }

        // ******************************************************************
        public void Unregister()
        {
            HotKey hotKey;
            if (_dictHotKeyToCalBackProc.TryGetValue(Id, out hotKey))
            {
                UnregisterHotKey(IntPtr.Zero, Id);
            }
        }

        // ******************************************************************
        private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
        {
            if (!handled)
            {
                if (msg.message == WmHotKey)
                {
                    HotKey hotKey;

                    if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))
                    {
                        if (hotKey.Action != null)
                        {
                            hotKey.Action.Invoke(hotKey);
                        }
                        handled = true;
                    }
                }
            }
        }

        // ******************************************************************
        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // ******************************************************************
        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be _disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be _disposed.
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this._disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    Unregister();
                }

                // Note disposing has been done.
                _disposed = true;
            }
        }
    }

    // ******************************************************************
    [Flags]
    public enum KeyModifier
    {
        None = 0x0000,
        Alt = 0x0001,
        Ctrl = 0x0002,
        NoRepeat = 0x4000,
        Shift = 0x0004,
        Win = 0x0008
    }

    // ******************************************************************
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用System.Net.Mime;
使用System.Runtime.InteropServices;
使用系统文本;
使用System.Windows;
使用System.Windows.Input;
使用System.Windows.Interop;
命名空间非托管
{
公共类热键:IDisposable
{
专用静态字典_dictHotKeyToCalBackProc;
[DllImport(“user32.dll”)]
专用静态外部bool寄存器hotkey(IntPtr hWnd、int id、UInt32 fsModifiers、UInt32 vlc);
[DllImport(“user32.dll”)]
私有静态外部bool unregister热键(IntPtr hWnd,intid);
public const int WmHotKey=0x0312;
private bool_disposed=false;
公钥{get;private set;}
public KeyModifier KeyModifier{get;private set;}
公共操作操作{get;private set;}
公共int Id{get;set;}
// ******************************************************************
公用热键(键k、键修改器、键修改器、动作动作、布尔寄存器=true)
{
Key=k;
KeyModifiers=KeyModifiers;
行动=行动;
如果(注册)
{
寄存器();
}
}
// ******************************************************************
公共布尔寄存器()
{
int virtualKeyCode=KeyInterop.VirtualKeyFromKey(键);
Id=virtualKeyCode+((int)键修饰符*0x10000);
bool result=RegisterHotKey(IntPtr.Zero,Id,(UInt32)键修饰符,(UInt32)虚拟代码);
如果(_dictHotKeyToCalBackProc==null)
{
_dictHotKeyToCalBackProc=新字典();
ComponentDispatcher.ThreadFilterMessage+=新的ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
}
_dictHotKeyToCalBackProc.Add(Id,this);
Debug.Print(result.ToString()+”、“+Id+”、“+virtualKeyCode”);
返回结果;
}
// ******************************************************************
公共作废注销()
{
热键热键;
if(_dictHotKeyToCalBackProc.TryGetValue(Id,out热键))
{
取消注册热键(IntPtr.Zero,Id);
}
}
// ******************************************************************
私有静态无效组件DispatcherThreadFilterMessage(ref MSG MSG,ref bool handled)
{
如果(!已处理)
{
如果(msg.message==WmHotKey)
{
热键热键;
if(_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam,out热键))
{
if(hotKey.Action!=null)
{
hotKey.Action.Invoke(热键);
}
已处理=正确;
}
}
}
}
// ******************************************************************
//实现IDisposable。
//不要将此方法设置为虚拟。
//派生类不能重写此方法。
公共空间处置()
{
处置(真实);
//此对象将通过Dispose方法清除。
//因此,您应该调用GC.superssfalize来
//将此对象从终结队列中移除
//并阻止此对象的终结代码
//从第二次执行开始。
总干事(本);
}
// ******************************************************************
//Dispose(bool disposing)在两种不同的场景中执行。
//如果disposing等于true,则直接调用该方法
//或通过用户的代码间接执行。托管和非托管
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Mime;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;

namespace UnManaged
{
    public class HotKey : IDisposable
    {
        private static Dictionary<int, HotKey> _dictHotKeyToCalBackProc;

        [DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, UInt32 fsModifiers, UInt32 vlc);

        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        public const int WmHotKey = 0x0312;

        private bool _disposed = false;

        public Key Key { get; private set; }
        public KeyModifier KeyModifiers { get; private set; }
        public Action<HotKey> Action { get; private set; }
        public int Id { get; set; }

        // ******************************************************************
        public HotKey(Key k, KeyModifier keyModifiers, Action<HotKey> action, bool register = true)
        {
            Key = k;
            KeyModifiers = keyModifiers;
            Action = action;
            if (register)
            {
                Register();
            }
        }

        // ******************************************************************
        public bool Register()
        {
            int virtualKeyCode = KeyInterop.VirtualKeyFromKey(Key);
            Id = virtualKeyCode + ((int)KeyModifiers * 0x10000);
            bool result = RegisterHotKey(IntPtr.Zero, Id, (UInt32)KeyModifiers, (UInt32)virtualKeyCode);

            if (_dictHotKeyToCalBackProc == null)
            {
                _dictHotKeyToCalBackProc = new Dictionary<int, HotKey>();
                ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
            }

            _dictHotKeyToCalBackProc.Add(Id, this);

            Debug.Print(result.ToString() + ", " + Id + ", " + virtualKeyCode);
            return result;
        }

        // ******************************************************************
        public void Unregister()
        {
            HotKey hotKey;
            if (_dictHotKeyToCalBackProc.TryGetValue(Id, out hotKey))
            {
                UnregisterHotKey(IntPtr.Zero, Id);
            }
        }

        // ******************************************************************
        private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
        {
            if (!handled)
            {
                if (msg.message == WmHotKey)
                {
                    HotKey hotKey;

                    if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))
                    {
                        if (hotKey.Action != null)
                        {
                            hotKey.Action.Invoke(hotKey);
                        }
                        handled = true;
                    }
                }
            }
        }

        // ******************************************************************
        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // ******************************************************************
        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be _disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be _disposed.
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this._disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    Unregister();
                }

                // Note disposing has been done.
                _disposed = true;
            }
        }
    }

    // ******************************************************************
    [Flags]
    public enum KeyModifier
    {
        None = 0x0000,
        Alt = 0x0001,
        Ctrl = 0x0002,
        NoRepeat = 0x4000,
        Shift = 0x0004,
        Win = 0x0008
    }

    // ******************************************************************
}