Горячие клавиши
Также известны как хоткеи
Что такое Keybind'ы?
Keybind'ы позволяют привязать определённую функцию к нажатию клавиши или комбинации клавиш.
Это удобно, когда нужно быстро запускать какое-то действие — например, макрос или команду.
Назначить клавишу и дождаться нажатия
Чтобы назначить горячую клавишу, используйте атрибут [Keybind]. Этот атрибут можно добавить к методу, и он будет вызываться при нажатии указанной клавиши.
Вставьте этот код в Script.csx у C# Action, запустите его и нажмите Ctrl+2:
using System.Threading.Tasks;
using EyeAuras.Scripting.Api;
Log.Info("Waiting for Ctrl+2");
var runToken = cancellationToken;
await Task.Delay(System.Threading.Timeout.Infinite, runToken);
[Keybind("Ctrl+2", SuppressKey = false)]
public void OnKey()
{
Log.Info("Ctrl+2 pressed");
}
В Event Log появится Ctrl+2 pressed; комбинация также дойдёт до других приложений. Без ожидания скрипт сразу завершится и обработчик перестанет принимать нажатия. Остановка запуска отменяет ожидание.
Runtime обнаруживает методы объекта скрипта при однократной настройке. Атрибут на методе произвольного helper-класса сам по себе не регистрирует хоткей. В текущей реализации обрабатываются клавиатурные комбинации.
Параметры атрибута Keybind
Атрибут [Keybind] поддерживает несколько параметров:
Hotkey— обязательный параметр, который задаёт горячую клавишу или комбинацию клавиш (например,Ctrl+A,Shift+X,Alt+Tab).SuppressKey— подавляет событие нажатия клавиши и не даёт ему дойти до других приложений. По умолчанию —true. Важно: подавление работает независимо от настройкиActivationType(см. ниже).IgnoreModifiers— игнорирует дополнительные клавиши-модификаторы. По умолчанию —false. Работает похоже на*в AutoHotkey (Wildcard).ActivationType— определяет, когда должен сработать метод: при KeyDown (когда клавиша нажата) или при KeyUp (когда клавиша отпущена). По умолчанию —KeyDown.
Как работает IgnoreModifiers?
Если IgnoreModifiers = true, метод сработает даже в том случае, если одновременно нажаты дополнительные клавиши-модификаторы (например, Shift, Alt, Ctrl).
По умолчанию IgnoreModifiers выключен.
Пример:
[Keybind("Ctrl+2", IgnoreModifiers = true)] // Triggers on: Ctrl+2, Ctrl+Alt+2, Ctrl+Shift+2
[Keybind("Ctrl+2", IgnoreModifiers = false)] // Triggers ONLY on Ctrl+2
Как работает ActivationType?
Параметр ActivationType задаёт, в какой момент должен вызываться ваш метод:
KeyDown— метод вызывается в момент нажатия клавиши.KeyUp— метод вызывается в момент отпускания клавиши.
Примеры:
[Keybind("F1", ActivationType = KeybindActivationType.KeyDown)] // Calls method when F1 is pressed
[Keybind("F2", ActivationType = KeybindActivationType.KeyUp)] // Calls method when F2 is released
Как работает SuppressKey?
Если SuppressKey = true, нажатие клавиши не будет передано другим приложениям. Это полезно, если вы хотите обрабатывать клавишу исключительно внутри своего скрипта.
Важно: подавление всегда работает независимо от ActivationType. Например:
[Keybind("F1", SuppressKey = true, ActivationType = KeybindActivationType.KeyUp)] // Suppresses F1 and triggers on release
[Keybind("F2", SuppressKey = true, ActivationType = KeybindActivationType.KeyDown)] // Suppresses F2 and triggers on press
Это помогает избежать «утечек» нажатий в нестандартных ситуациях.
Переназначение клавиш
Комбинируя параметры, можно отправлять R при нажатии и отпускании D. Следующие члены добавьте в тот же Script.csx, оставив ожидание из первого примера. Добавьте using System.Windows.Input; в начало файла. ISendInputScriptingApi должен быть доступен в host, а целевое окно и способ отправки ввода — настроены в EyeAuras.
При IgnoreModifiers = true дополнительные модификаторы не мешают совпадению D. SuppressKey по умолчанию подавляет исходное событие. Отправка R зависит от выбранного input simulator; это не гарантия работы в каждом приложении. Если остановить скрипт между KeyDown и KeyUp, освобождение отправленной клавиши нужно предусмотреть отдельно.
[Unity.Dependency]
public EyeAuras.Roxy.Api.ISendInputScriptingApi SendInput { get; init; }
[Keybind(Hotkey = "d", ActivationType = KeybindActivationType.KeyDown, IgnoreModifiers = true)]
public void OnKeyDownForD(){
SendInput.KeyDown(Key.R);
}
[Keybind(Hotkey = "d", ActivationType = KeybindActivationType.KeyUp, IgnoreModifiers = true)]
public void OnKeyUpForD(){
SendInput.KeyUp(Key.R);
}
Как работают обработчики Keybind
Система поддерживает параллельную обработку нажатий. Это значит, что даже если вы быстро нажимаете несколько клавиш или многократно жмёте одну и ту же клавишу, каждый обработчик выполняется независимо.
Как организовать последовательное выполнение
Ниже два варианта для того же Script.csx. Добавьте using System.Threading; и выберите один обработчик. Свойство с семафором сохраняется между вызовами, в отличие от локальной переменной внутри обработчика.
SemaphoreSlim HotkeySemaphore { get; } = new(1, 1);
[Keybind("A", SuppressKey = false)]
public async Task HandleA()
{
var runToken = cancellationToken;
await HotkeySemaphore.WaitAsync(runToken);
try
{
Log.Info("Processing key A");
await Task.Delay(1000, runToken);
}
finally
{
HotkeySemaphore.Release();
}
}
Нажатия ждут освобождения семафора. Переданный токен отменяет ожидание; уже запланированный обработчик не считается автоматически остановленным вместе со скриптом. Не делайте async void: runtime ожидает возвращённый Task.
Как пропускать лишние нажатия
Если очередь не нужна, замените обработчик на этот, оставив то же свойство HotkeySemaphore:
[Keybind("A", SuppressKey = false)]
public async Task HandleA()
{
var runToken = cancellationToken;
if (!HotkeySemaphore.Wait(0))
{
return;
}
try
{
Log.Info("Processing key A");
await Task.Delay(1000, runToken);
}
finally
{
HotkeySemaphore.Release();
}
}
Wait(0) проверяет и занимает слот одной операцией. Проверка CurrentCount перед отдельным захватом оставляет гонку: несколько обработчиков могут одновременно увидеть свободный слот.
Полезные советы
- Используйте
IgnoreModifiers = true, если хотите обрабатывать комбинации независимо от дополнительных модификаторов. - Используйте
SemaphoreSlimили другие механизмы синхронизации, если нужно не допускать одновременных вызовов одного и того же метода. - Помните, что методы могут принимать параметры — runtime разрешает их типы через Unity-контейнер при вызове (например,
IAuraEventLoggingService). Нужная регистрация должна уже существовать.Log,SleepиcancellationTokenдоступны здесь как члены host скрипта; в обычный класс зависимости передавайте явно.
Сигнатуры: KeybindAttribute. Проверяйте версию reference относительно своей сборки EyeAuras.