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

Posted

技术标签:

【中文标题】Windows Forms .NET 中的热键(非全局)【英文标题】:Hotkey (not global) in Windows Forms .NET 【发布时间】:2011-02-16 23:14:24 【问题描述】:

在我的 Windows 窗体应用程序中,我希望每次按下一个特殊按钮来运行测试。有几十个控件,因此在每个控件中实施它都需要花费太多时间。

有没有一种方法可以设置热键,所以无论我在应用程序中做什么,我都可以按下该键,它会触发我的事件?

【问题讨论】:

【参考方案1】:

您可以覆盖ProcessCmdKey 并在那里处理您的热键,无论是在控件还是表单中。

来自MSDN:

ProcessCmdKey方法先 确定控件是否具有 ContextMenu,如果是,则启用 ContextMenu 处理命令 钥匙。如果命令键不是菜单 快捷方式和控件有一个父级, 密钥被传递给父母的 ProcessCmdKey 方法。净效应 是命令键被“冒泡”了吗 控制层次结构。此外 用户按下的键,关键数据 还指示哪个修饰符(如果有) 键被同时按下 钥匙。修饰键包括 SHIFT、CTRL 和 ALT 键。

例如:

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

    // if it is a hotkey, return true; otherwise, return false
    switch (keyData)
    
        case Keys.Control | Keys.C:
            // do something
            return true;
        default:
            break;
    

    return base.ProcessCmdKey(ref msg, keyData);

【讨论】:

【参考方案2】:

您可以覆盖表单的 ProcessCmdKey() 方法,它会在表单上的任何控件看到击键之前运行。如果你真的需要它在应用程序级别(所有表单),那么你应该让你的主表单实现 IMessageFilter 接口。例如:

public partial class Form1 : Form, IMessageFilter 
    public Form1() 
        InitializeComponent();
        Application.AddMessageFilter(this);
        this.FormClosed += (o, e) => Application.RemoveMessageFilter(this);
    
    public bool PreFilterMessage(ref Message m) 
        // Catch WM_KEYDOWN message
        if (m.Msg == 0x100 && (Keys)m.WParam == Keys.F1) 
            MessageBox.Show("Help me!");
            return true;
        
        return false;
    

【讨论】:

我把这个标记为接受,但后来我看到 zach 写了return base.ProcessCmdKey(ref msg, keyData);,我觉得自己像个白痴(我曾经这样做,但这次我没有)并更新了我的代码。他得到它是因为他的回答让我想起了我的错误。虽然你有更多的答案。这是一个艰难的选择。【参考方案3】:

如果你只有一种形式。您可以设置 Form.KeyPreview=true,然后将代码添加到表单的关键事件中。

【讨论】:

以上是关于Windows Forms .NET 中的热键(非全局)的主要内容,如果未能解决你的问题,请参考以下文章

System.Windows.Forms.TextBox 中的水印

如何在非托管类中将 Tick 事件添加到 System::windows::Forms::Timer

为啥要从设计器中插入非 UI Windows.Forms 组件?

如何在 .NET Core 类库中使用 System.Windows.Forms

如何清除 System.Windows.Forms.WebBrowser 会话数据?

.net Windows Forms 应用程序的自动 CRUD 表单生成