【问题标题】:Check if hot key pressed in Winforms检查是否在 Winforms 中按下热键
【发布时间】:2021-02-25 02:14:26
【问题描述】:

要获取热键Ctrl+A,我们可以在Form1_KeyDown中使用以下语句。

if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
{
    MessageBox.Show("Test");
}

要捕获Ctrl+Alt+A,我们可以使用:

if (e.Control && e.Alt)
{
    if (e.KeyCode == Keys.A)
    {
        // Your code goes here
    }
}

问题是如何捕捉Ctrl+A+B这样的热键?

【问题讨论】:

  • 您的意思是 Ctrl+A, CTRL+BCTRL+A 后跟 B,而 CTRL 键仍被按下 - 或者,CTRL 键尚未释放)。
  • @Jimi 仍然按下
  • 在 WinForms 中没有简单的方法可以做到这一点。您必须保留布尔字典并跟踪按下的键。或者,您可以导入 WPF 运行时并将Keyboard.IsKeyDownKeyDown 事件结合使用。你也可以求助于 Win32 API 并使用 GetKeyState
  • 这个“热键”是否应该只在您的应用程序中有效?

标签: winforms hotkeys


【解决方案1】:

这里有一些东西可以帮助您开始使用IMessageFilter

这将在按下 Ctrl-A-B 时触发,而不是在释放时触发。它目前还会在按住这些键时重复触发。这可以通过混合中的另一个布尔变量来改变。这绝对不是完美的……

public partial class Form1 : Form
{   

    public Form1()
    {
        InitializeComponent();
    }

    private MyFilter mf = new MyFilter();

    private void Form1_Load(object sender, EventArgs e)
    {
        mf.Ctrl_A_B += Mf_Ctrl_A_B;
        Application.AddMessageFilter(mf);
    }

    private void Mf_Ctrl_A_B()
    {
        Console.WriteLine("Ctrl-A-B was held down!");
    }

}

public class MyFilter : IMessageFilter
{

    private bool keyCtrl;
    private bool keyA;
    private bool keyB;

    private const int WM_KEYDOWN = 0x100;
    private const int WM_KEYUP = 0x101;

    public delegate void dlg_Ctrl_A_B();
    public event dlg_Ctrl_A_B Ctrl_A_B;

    public bool PreFilterMessage(ref Message m)
    {
        Keys keyData;
        switch (m.Msg)
        {
            case WM_KEYDOWN:
                keyData = (Keys)((int)m.WParam);
                switch (keyData)
                {
                    case Keys.ControlKey:
                        keyCtrl = true;
                        break;

                    case Keys.A:
                        keyA = true;
                        break;

                    case Keys.B:
                        keyB = true;
                        break;
                }
                if (keyCtrl && keyA && keyB)
                {
                    Ctrl_A_B?.Invoke();
                }
                break;

            case WM_KEYUP:
                keyData = (Keys)((int)m.WParam);
                switch (keyData)
                {
                    case Keys.ControlKey:
                        keyCtrl = false;
                        break;

                    case Keys.A:
                        keyA = false;
                        break;

                    case Keys.B:
                        keyB = false;
                        break;
                }
                break;
        }

        return false;
    }

}

【讨论】:

  • Ctrl+J+E 或任何其他组合怎么样?我们应该为每个声明一个变量吗?
  • 就是这样,或者创建某种Dictionary<Keys, bool>,以便您可以查找和切换特定值。无论哪种方式都会变得一团糟......
  • 嗯,我不这么认为,如果你允许的话。只需一个变量就足够了。类似于另一个答案。适用于任何Ctrl+Any+Any。不管投票的事情,试试吧。感谢您的宝贵时间。
  • @dr.null Dictionary 方法将是最灵活的。如果明天他们要求 Ctrl-A-B-C,即使您的方法也需要修改。
【解决方案2】:

您可以将第一个键视为附加或自定义修饰符以扩展快捷键的范围。

声明一个类变量来保存该修饰符:

private Keys KeyModifier = Keys.None;

如下处理KeyDown事件:

private void FormWhatEver_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control)
    {
        switch (e.KeyCode)
        {
            case Keys.B:
                if (KeyModifier == Keys.A)
                {
                    // Handle Ctrl+AB
                }
                else
                {
                    // Handle Ctrl+B
                }
                break;
            case Keys.C:
                if (KeyModifier == Keys.A)
                {
                    // Handle Ctrl+AC
                }
                else
                {
                    // Handle Ctrl+C
                }
                break;
            default:
                // Otherwise set the pressed key as a key modifier.
                KeyModifier = e.KeyCode;
                break;
        }
    }
}

释放Control 键时重置修饰符。这对于使上述工作正常工作很重要。

private void FormWhatEver_KeyUp(object sender, KeyEventArgs e)
{
    if (!e.Control) KeyModifier = Keys.None;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 2019-03-10
    • 2012-11-12
    • 2022-07-26
    相关资源
    最近更新 更多