Внешняя компонента — универсальный, надежный перехватчик клавиатурных событий
Перехват нажатия клавиш в 1С реализован с привязкой к фокусу формы. Если форма (или главное окно процесса 1С) теряет фокус, то перехват перестает работать.
Чтобы решить эту проблему, была разработана соответствующая внешняя компонента.
- Описание
- Подробнее
Описание
Как работает.
Использован механизм SetWindowsHookEx с флагом "WH_KEYBOARD_LL".
Механизм перехвата работает через отправку сообщений процессу приложения, установившему перехват. Это влечет за собой 2 последствия.
1.Внедрение DLL компоненты (т.е. нашего кода) для обработки callback-вызовов в адресное пространство других процессов не происходит.
2. При остановке потока 1с, установившего перехват (ошибка в коде, остановка отладчиком, зависание процесса 1с и т.д.) никаких негативных последствий ни для других процессов, ни для операционной системы не происходит. Субьективно это воспринимается пользователем как кратковременная (1-3 сек), однократная задержка реакции на нажатие кнопки. В этом случае операционка просто исключает обработчик зависшего процесса из цепочки обработчиков перехвата. Для возобновления перехвата — потребуется его перезапустить.
Механизм сильно Generic и поэтому теоретически будет работать довольно надежно на всех семействах операционок от Майки (Windows 9x, Windows NT, Windows Server) — 32 и 64-разрядных. Без каких-либо дополнительных фреймворков и сред.
Кроме очевидного использования — для перехвата нажатия кнопок в 1с — вне зависимости от положения фокуса, навскидку видятся еще следующие применения:
— в качестве перехватчика данных, получаемых от других устройств клавиатурного ввода (сканеры, ридеры и т.д.)
— иное применение :).
Установка компоненты:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
УстановитьВнешнююКомпоненту("ОбщийМакет.KbdHook");
ПодключитьВнешнююКомпоненту("ОбщийМакет.KbdHook", "СС",ТипВнешнейКомпоненты.Native);
//ПодключитьВнешнююКомпоненту("C:\C++\KbdHook\x64\Release\KbdHook64.dll", "СС", ТипВнешнейКомпоненты.Native);
ВК = Новый("AddIn.СС.KbdHook");
КонецПроцедуры
Запуск перехвата:
&НаКлиенте
Процедура УстановитьКрючок(Команда)
//Если параметр Истина, то компонента возвращает - строчное представление шестнадцатеричного значения двойного слова (4 байта).
//Если ложь - системную интерпретацию названия нажатой кнопки (зависит от локализации ОС).
Сообщить(ВК.УстановитьПерехват(истина));
КонецПроцедуры
Остановка перехвата:
&НаКлиенте
Процедура СнятьКрючок(Команда)
Сообщить(ВК.СнятьПерехват());
КонецПроцедуры
Обработка callback-вызова:
//Модуль приложения
Процедура ОбработкаВнешнегоСобытия(Источник, Событие, Данные)
Оповестить(Событие,Данные,Источник)
КонецПроцедуры
//Модуль формы
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
ЧтениеДжей = новый ЧтениеJSON;
ЧтениеДжей.УстановитьСтроку(Параметр);
стк = ПрочитатьJSON(ЧтениеДжей);
ЧтениеДжей.Закрыть();
ЭтаФорма.Реквизит1 = ЭтаФорма.Реквизит1 + стк.key;
Сообщить(Параметр);
КонецПроцедуры
Json-структура, возвращаемая в 1с компонентой:
{
"Alt" : false,
"Ctrl" : false,
"Key" : "0x00390001",
"Shift" : false
}
Немного о структуре поля Key.
Если включен режим возврата скан-кода нажатой клавиши, то возвращается строка вида:
0x00100001
Справа-налево:
байт 0: всегда = 1.
байт 1: всегда = 0.
байт 2: скан-код нажатой клавиши (https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc)
байт 3: флаг — является-ли нажатая клавиша расширенной клавишей (клавиша Windows, Системное меню и т.д.), возможные значения: 0-1.
Самый старший байт — слева.
Тестировалось на платформе версии: 8.3.18.1334
Исходники: https://github.com/KotVezdehod/KbdHook