#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;
}