为啥按下热键组合时没有触发我的注册热键

Posted

技术标签:

【中文标题】为啥按下热键组合时没有触发我的注册热键【英文标题】:Why is my Registered Hotkey not triggered when pressing the hotkey combination为什么按下热键组合时没有触发我的注册热键 【发布时间】:2020-05-16 22:44:24 【问题描述】:

我已经实现了 user32.dll 注册和注销热键方法,但是在注册热键后,按下热键时我从未收到WndProc 消息0x0312。有人可以查看我的代码并帮助我了解为什么我从未收到 0x0312 消息。

到目前为止我尝试过的热键组合:

Ctrl + Shift + F12 F12 F9

我的实现只是最常见的实现:

[DllImport("c:\\windows\\system32\\user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[DllImport("c:\\windows\\system32\\user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
protected override void WndProc(ref Message m) 
    if(m.Msg == 0x0312) 
        int id = m.WParam.ToInt32();
        switch(id) 
            case 0:
                MessageBox.Show("Ctrl + Shift + F12 HotKey Pressed ! Do something here ... ");
                break;
        
    

我创建了一个单例类来处理热键的注册和注销:

public class HotKeyHandler 

    //Hotkey register and unregister.
    [DllImport("c:\\windows\\system32\\user32.dll")]
    public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
    [DllImport("c:\\windows\\system32\\user32.dll")]
    public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    public const int MOD_ALT = 0x0001;
    public const int MOD_CONTROL = 0x0002;
    public const int MOD_SHIFT = 0x0004;
    public const int MOD_WIN = 0x0008;

    byte ID = 0;

    /// <summary>
    /// Keep the constructor private due to singleton implementation
    /// </summary>
    private HotKeyHandler()  
    public static HotKeyHandler Instance = new HotKeyHandler();

    public bool RegisterHotKey(IntPtr handle, int modifier, Key key) 
        bool returnVal = RegisterHotKey(handle, ID, modifier, (int) key);
        ID++;
        return returnVal;
    

    public void UnregisterAllHotKeys(IntPtr handle) 
        for(short s = 0; s <= ID; s++) 
            UnregisterHotKey(handle, s);
        
    

最后我像这样注册热键:

HotKeyHandler.Instance.RegisterHotKey(this.Handle, HotKeyHandler.MOD_CONTROL | HotKeyHandler.MOD_SHIFT, Key.F12);

【问题讨论】:

多种可能的原因。 1:根本没有错误检查,所以看不到 pinvoke 调用失败。 2:this.Handle失效,很容易发生在Winforms应用程序中,必须从OnHandleCreated()调用。 3:当提升的应用程序在前台时按下键。 4:没有激活调度程序循环(Application.Run),因此根本不会调用 WndProc()。 我的 HotKeyHandler 的 RegisterHotKey 方法中的断点显示它返回 true,这应该意味着它注册时没有错误。我的表单中的一些断点表明,从创建热键到调用 WndProc 时,Handle 没有改变。 HandleCreated += MethodThatCreatesHotKey;已经尝试过,不幸的是没有改变任何东西。 Application.Run 存在并调用了 WndProc(),WndProc() 处的断点清楚地表明它被调用了。 【参考方案1】:

我想花时间回答我自己的问题,以防其他人可能会发现自己处于同样的境地......相当恼人的情况......

所以经过一番挖掘和刺激后,我终于发现了问题所在,我查看了传递给 RegisterHotKey 方法的 Key ID 的值,发现我得到的值与实际 ID 不匹配钥匙。 原来存在两种类型的 Key 枚举,有 System.Windows.Input.KeySystem.Windows.Forms.Keys。我没有意识到这一点,并且正在使用 Input.Key,它的值与 Forms.Keys 不同

TL:DR 将Forms.Keys 用于RegisterHotKey() 而不是Input.Key

【讨论】:

以上是关于为啥按下热键组合时没有触发我的注册热键的主要内容,如果未能解决你的问题,请参考以下文章

运行时检测 Visual Studio 热键

仅触发一次热键/快捷方式事件

Windows Forms .NET 中的热键(非全局)

替换全局热键

关闭f4的热键功能

HotKey 触发 Ant Design Select 开始搜索