Проверьте, нажата ли горячая клавиша в Winforms

#winforms #hotkeys

#winforms #горячие клавиши

Вопрос:

Чтобы перехватить горячую клавишу Ctrl A , мы можем использовать следующий оператор в Form1_KeyDown .

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

Чтобы перехватить Ctrl Alt A , мы можем использовать:

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

Вопрос в том, как поймать горячую клавишу, например Ctrl A B ?

Комментарии:

1. Вы имеете в виду Ctrl A, CTRL B ( CTRL A за которым следует, B пока CTRL клавиша все еще нажата — или, CTRL клавиша не была отпущена).

2. @Jimi все еще нажат

3. В WinForms нет простого способа сделать это. вам нужно будет вести словарь bools и отслеживать, какие клавиши были нажаты. Или вы можете импортировать среды выполнения WPF и использовать Keyboard.IsKeyDown их в сочетании с KeyDown событием. Вы также можете прибегнуть к Win32 API и использовать такие вещи, как GetKeyState

4. Должна ли эта «горячая клавиша» работать только в ВАШЕМ приложении?

Ответ №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 amp;amp; keyA amp;amp; 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;
    }

}
  

Комментарии:

1. Как насчет Ctrl J E или любой другой комбинации? Должны ли мы объявлять переменную для каждого?

2. Это либо так, либо создайте какой Dictionary<Keys, bool> -то, чтобы вы могли искать и переключать определенные значения. В любом случае это приведет к беспорядку…

3. хм, я так не думаю, если вы мне позволите. Достаточно одной переменной. Что-то вроде другого ответа. Работает для любого Ctrl Any Any . Попробуйте это независимо от голосования. Спасибо за ваше время.

4. @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;
}