【问题标题】:How can I capture a global Win+* hotkey?如何捕获全局 Win+* 热键?
【发布时间】:2018-02-10 19:04:45
【问题描述】:

我知道已经有很多关于如何使用 C# 捕获全局热键的资源(使用 Ctrl、Alt 或其他任何东西),但我还没有看到任何与 Windows 键一起使用的资源。

是否可以捕获程序并响应 Win+* 全局键盘快捷键?例如,如果用户按下 Win+Z 或类似的键,则显示一个表单。

【问题讨论】:

  • 不要使用 Windows 键创建热键。它是为操作系统功能保留的,您的程序会干扰它并给用户带来极大的不便。
  • 除了我自己之外,其他任何用户都不能使用(我正在编写一个帮助程序来节省自己一些时间),并且我知道使用了哪些 Win+* 快捷方式,哪些没有使用,所以不会成为碰撞。不过,最好警告我一下? :P
  • 另外,@HansPassant,您不能注册系统已经注册的全局热键,Windows 将返回此错误:“代码:1409,错误:热键已注册”。看起来非常安全,不会干扰任何事情。

标签: c# keyboard-shortcuts windows-key


【解决方案1】:

Windows 键可以用作任何其他修饰符(const int MOD_WIN = 0x0008 根据MSDN)。我已经使用基于RegisterHotKey 的代码对此进行了测试,并且工作正常。

更新

示例代码展示了如何通过依赖 RegisterHotKey(手动收集的LParam 值)挂钩不同的键组合,包括 Windows 键:

[System.Runtime.InteropServices.DllImport("User32")] public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[System.Runtime.InteropServices.DllImport("User32")] public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

public const int MOD_SHIFT = 0x4;
public const int MOD_CONTROL = 0x2;
public const int MOD_ALT = 0x1;
public const int WM_HOTKEY = 0x312;
public const int MOD_WIN = 0x0008;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_HOTKEY && m.WParam == (IntPtr)0)
    {
        IntPtr lParamWINZ = (IntPtr)5898248;
        IntPtr lParamWINCTRLA = (IntPtr)4259850;
        if (m.LParam == lParamWINZ)
        {
            MessageBox.Show("WIN+Z was pressed");
        }
        else if (m.LParam == lParamWINCTRLA)
        {
            MessageBox.Show("WIN+CTRL+A was pressed");
        }
    }
    base.WndProc(ref m);
}

private void Form1_Load(object sender, EventArgs e)
{
    this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);

    RegisterHotKey(this.Handle, 0, MOD_WIN, (int)Keys.Z);
    RegisterHotKey(this.Handle, 0, MOD_WIN + MOD_CONTROL, (int)Keys.A);
}

private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
    UnregisterHotKey(this.Handle, 0);
}

【讨论】:

  • 因此,即使该文档说涉及 WINDOWS 键的键盘快捷键保留供操作系统使用。,如果您处理它们,它们仍然有效吗?
  • @SpikeX 这正是我所说的。我应该包含一个示例代码吗?
  • 如果您希望其他人(例如来自 Google 的人)可以包含示例代码,但我知道如何在 C# 中检查这一点。一旦我确认它有效,我会接受。
  • @SpikeX 没问题。我可能会在离开前的一段时间内添加一个示例代码。
  • 我尝试使用 Win 键修饰符 0x08 注册热键,但 Windows 返回错误 1008:“尝试引用不存在的令牌”。有什么想法吗?
【解决方案2】:

尽管上述解决方案似乎对某些人有效。它对我不起作用。使 WIN 键正常工作的唯一方法是在注册表中禁用它。

https://msdn.microsoft.com/en-us/library/bb521407(v=winembedded.51).aspx

缺点:所有 WIN 热键都被禁用。

在注册表中有两种可能的方法:

(1) 系统范围:(我没有测试过这个) HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ 键盘布局, 名称:“扫码地图”, 类型:REG_BINARY(二进制值), 数值数据:“00 00 00 00 00 00 00 00 03 00 00 00 00 00 5B E0 00 00 5C E0 00 00 00 00”

(2) 对于每个用户:(这是我用的) HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer, 名称:“NoWinKeys”, 数据类型:REG_DWORD(DWORD 值), 数值数据:0 表示禁用限制,或 1 表示启用限制

【讨论】:

  • Windows 10 一直在添加新的快捷键,如果操作系统保留了一个快捷键,那么您将无法使用它(即使它似乎没有做任何事情,它可能仍然被保留)。您需要找到一个未保留的密钥(我现在知道的唯一一个是 N,但可能还有一两个)。
  • 不幸的是 WIN + N 被“发送到 OneNote”实用程序(Office 2013 和可能所有较新版本)占用。可以在此处找到所有快捷方式的完整列表support.microsoft.com/en-my/help/12445/…。这意味着保留所有字母和数字。浏览完列表后,我只发现 F2 及以上键可用。
  • Win+N 在您关闭“发送到 OneNote”并禁止它在您的计算机上启动时变为可用。当然,如果您正在部署应用程序,这将不起作用 - 我最初的问题是关于我为自己编写的应用程序,而不是在任何地方部署。仍然认为您“不应该”编写使用 Win+_ 热键的应用程序,因为它违反了最佳实践,但如果该应用程序仅供您自己使用,它会起作用。
猜你喜欢
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 2011-06-30
  • 1970-01-01
  • 2019-06-11
  • 2013-04-17
  • 2016-02-28
相关资源
最近更新 更多