Внешняя компонента - универсальный, надежный перехватчик клавиатурных событий

21.02.23

Разработка - Разработка внешних компонент

Перехват нажатия клавиш в 1С реализован с привязкой к фокусу формы. Если форма (или главное окно процесса 1С) теряет фокус, то перехват перестает работать. Чтобы решить эту проблему, была разработана соответствующая внешняя компонента.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Внешняя компонента - универсальный, надежный перехватчик клавиатурных событий:
.zip 78,44Kb
18
18 Скачать (1 SM) Купить за 1 850 руб.

Как работает.

Использован механизм 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 байта).
    //Если ложь - системную интерпретацию названия нажатой кнопки (зависит от локализации ОС).

	Сообщить(ВК.УстановитьПерехват("string",11,28));  //установка перехвата в режиме получения данных от эмуляторов клавиатуры
    //второй параметр - целое положительное число - задает скан-код клавиши, с которой начинается накопление символов в буфере
    //третий параметр - целые положительные числа - задает скан-код клавиши, при перехвате которой накопленная последовательность символов передается в 1С.
    Сообщить(ВК.УстановитьПерехват("char",1,1));  //установка перехвата в посимвольном режиме

КонецПроцедуры

Остановка перехвата:

&НаКлиенте
Процедура СнятьКрючок(Команда)
	Сообщить(ВК.СнятьПерехват());
КонецПроцедуры

Обработка callback-вызова:

//Модуль приложения
Процедура ОбработкаВнешнегоСобытия(Источник, Событие, Данные)
	 Оповестить(Событие,Данные,Источник)
КонецПроцедуры


//Модуль формы
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
	
   //в посимвольном режиме
	ЧтениеДжей = новый ЧтениеJSON;
	ЧтениеДжей.УстановитьСтроку(Параметр);
    структура_= ПрочитатьJSON(ЧтениеДжей);
	ЧтениеДжей.Закрыть();

	ЭтаФорма.Реквизит1 = ЭтаФорма.Реквизит1 + структура_.key;
	Сообщить(Параметр);

    //в режиме перехвата эмуляции клавиатуры
	ЧтениеДжей = новый ЧтениеJSON;
	ЧтениеДжей.УстановитьСтроку(Параметр);
	массив_ = ПрочитатьJSON(ЧтениеДжей);
	ЧтениеДжей.Закрыть();

    Для каждого эм из массив_ Цикл
       Сообщить(Строка(эм.sc));             //Скан-код клавиши
    КонецЦикла;

КонецПроцедуры

Json-структура, возвращаемая в 1с компонентой:

//В режиме посимвольного перехвата
{
	"Alt" : false,
	"Ctrl" : false,
	"Key" : "0x00390001",
	"Shift" : false
}

//В режиме перехвата эмуляции клавиатуры
[
	{
		"key" : "0",       //печатный символ (если интерпретировать возможно)
		"sc" : 11,         //скан-код клавиши
		"vk" : 48          //виртуальный код клавиши
	},
	{
		"key" : "",        //ОС не смогла интерпретировать скан-код
		"sc" : 66,         //скан-код кнопки F8 (нажатие этой кнопки промулировал Honeywell 1400d при сканировании символа "29" (0х1Dh))
		"vk" : 119
	},
	{
		"key" : "\r",
		"sc" : 28,        //скан-код кнопки ENTER
		"vk" : 13
	}
]

Немного о структуре поля 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.

Самый старший байт - слева.

Режим перехвата данных от эмуляторов клавиатуры (от сканеров, кард-ридеров и т.п.).

Принцип работы.

После установки перехвата, компонента проверяет скан-код каждого введенного символа на совпадение со скан-кодом, установленным во 2м параметре функции установки перехвата (УстановитьПерехват()). 

Если скан-коды совпадают, то все последующие символы будут записываться во внутренний буфер компоненты.

Запись будет происходить до тех пор, пока скан-код входящего символа не окажется равным скан-коду третьего параметра функции установки перехвата (УстановитьПерехват()).

Если скан-коды символов совпадут, то компонента передает последовательность накопленных символов в 1с (генерируется внешнее событие), очищает буфер и снова входит в режим ожидания совпадения скан-кода входящего символа с открывающим скан-кодом.

Таким образом, запрограммировав сканер на генерацию открывающего и закрывающего символов, можно получать в 1с данные не по-символьно, а массивом.

Кроме того, передача массива происходит из другого потока, который запускается специально для генерации внешнего события 1с. Такое решение исключает задержки с точки зрения операционной системы в обработчике перехвата (если, например, мы решили поотлаживать обработку перехвата в конфигураторе). При генерации внешнего события в основном потоке 1с (в случае слишком длительной задержки обработки перехвата) ОС может исключить наш обработчик из цепочки и его придется устанавливать заново.

По-хорошему, генерацию внешнего события в режиме по-символьного перехвата, тоже нужно реализовать в отдельном потоке.

 

Тестировалось на:

технологические платформы версии: 8.3.18.1334, 8.3.20.1674

ОС: Windows 10

Исходники: https://github.com/KotVezdehod/KbdHook

SetWindowsHookEx перехват клавиатуры внешняя компонента сканер

См. также

Разработка внешних компонент POS терминал Рабочее место Розничная торговля Программист Пользователь Платформа 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление торговлей 10 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Розничная и сетевая торговля (FMCG) Рестораны, кафе и фаст-фуд Реклама, PR и маркетинг Управленческий учет Платные (руб)

Медиадисплей покупателя может отображать текущую покупку на кассовом месте, показывать видеорекламу, баннеры, во время простоя разворачивать рекламу на весь экран. Экран можно использовать в качестве графического меню-борда в кафе и видеовывески. В качестве устройства отображения можно использовать Android-планшеты, смарт-телевизоры с Android, мониторы или проекторы под управлением Windows или Linux-компьютера. Linux-версия успешно запускается на одноплатных компьютерах Raspberri Pi и Orange Pi. Настраивается ЛЮБОЙ ДИЗАЙН экрана при помощи встроенного графического редактора! Решение можно масштабировать от одного экрана до тысяч экранов с централизованным управлением.

18000 руб.

30.05.2017    53879    9    69    

46

Разработка внешних компонент Телефония, SIP Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Платные (руб)

Внешняя компонента выполнена по технологии Native API для 1С 8.х, обеспечивает доступ к программным АТС Asterisk (FreePBX, Elastix) через AMI интерфейс. Через него можно управлять многими функциями Asterisk (определение номеров, перевод звонков, набор телефона и т. д.)

2400 руб.

04.05.2018    47115    123    66    

67

Разработка внешних компонент Программист Платформа 1С v8.3 Платформа 1C v8.2 Платные (руб)

Внешняя компонента, позволяющая посылать команды и получать ответы по GraphQL протоколу из 1С.Может быть использована при интеграции. В 1С работает на стороне "клиента".

4600 руб.

27.06.2023    3523    3    0    

5

Разработка внешних компонент Программист Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Платные (руб)

Внешняя компонента для конвертации PDF файлов в картинки без использования дополнительных программ. Работает на сервере и в тонком клиенте.

2400 руб.

25.06.2024    1042    2    4    

3

Разработка внешних компонент Программист Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Внешняя компонента в виде библиотеки (.dll файл), позволяющая посылать команды и получать ответы по протоколу WebSocket из 1С. Компонента работает только на стороне "клиента".

4440 руб.

22.06.2020    18320    18    33    

22

Разработка внешних компонент Программист Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Позволяет автоматизировать работу с картинками. С помощью компоненты можно измерять размер изображений, поворачивать их, наносить водяные знаки, конвертировать из одного формата в другой. Будет очень полезна для интернет-магазинов и всех, кому постоянно требуется работать с различными графическими форматами. Выполнена по технологии NativeAPI. Работает с форматами: jpg (jpeg), png, bmp, gif, tif

3600 руб.

02.09.2010    77407    72    257    

191

Разработка внешних компонент Программист Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 Платные (руб)

Внешняя компонента позволяет работать c TWAIN-совместимым оборудованием (сканерами, камерами) . Полностью совместима со стандартной TWAIN-компонентой из БСП и может применяться как ее замена без изменения вызовов, при этом может работать с 64-разрядной платформой, а так же имеет расширенную функциональность, например, сохранение результата непосредственно в PDF без использования сторонних утилит. Прекрасно работает на сервере, тонком клиенте и веб-клиенте (проверена работа в браузерах Google Chrome, Mozilla Firefox и Microsoft Internet Explorer).

3000 руб.

12.05.2020    28509    138    100    

91

Разработка внешних компонент Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

В статье описывается приложение-конструктор внешних компонент (native API). Конструктор упрощает процесс разработки за счет удобного добавления всех нужных функций и процедур в графическом режиме, с указанием их параметров и типов параметров. На выходе приложение генерирует готовый код на С++ и Rust и позволяет сразу приступить к реализации, без настройки API компоненты вручную.

04.12.2024    4391    kovalevdmv    26    

73
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Pr-Mex 136 30.11.21 20:40 Сейчас в теме
Плюс за разработку.
VanessaExt тоже умеет перехватывать клавиши.
https://github.com/lintest/VanessaExt
Vasvas05; user1590876; shiaju; +3 Ответить
2. Prometeus2011 216 01.12.21 15:10 Сейчас в теме
(1)Хм. Спасибо. Там и другой функционал есть интересный. И код открытый.
6. zerik 12 01.02.22 12:22 Сейчас в теме
(1)Что-то уже всю документацию перерыл, не могу найти перехват клавиш, покажите как, пожалуйста.
3. ivanov660 4587 07.12.21 17:09 Сейчас в теме
Антивирус не ругается на данную компоненту?
4. Prometeus2011 216 09.12.21 15:18 Сейчас в теме
(3) Нет, конечно. Авиры ее не видят, а она, меж тем, прогрызет дыру прямо в самое чрево Вашего Касперского.
5. script 128 21.12.21 19:56 Сейчас в теме
Добавьте еще отслеживание мышки.
Перехват курсора в любой момент времени и получение го координат.
Нажатие одинарное и двойное на ЛКМ ПКМ.
Прокрутка колеса и пр.
7. Rif_md 6 03.06.22 00:18 Сейчас в теме
В описании указано, что данную ВК можно использовать для перехвата данных от сканера. Т.е., если я правильно понимаю, эту ВК можно использовать как замену стандартной ВК драйвер сканера ШК. Но я не понял как это работает, как можно получить ответ от сканера в виде строки штрихкода?
8. Prometeus2011 216 03.06.22 10:08 Сейчас в теме
(7) Для полноценного перехвата последовательного ввода символов от устройств ввода требуется в рамках компоненты ДОПОЛНИТЕЛЬНО реализовать буфер накопления получаемых от устройства ввода символов.
Также сканер должен начинать передачу с открывающего (какого-нибудь непечатаемого) символа и заканчивать передачу тоже каким-то заранее определенным символом (в настройках всех сканеров, с которыми мне приходилось иметь дело, такие возможности присутствуют - обычно это знак табуляции или Enter).

Таким образом схема работы будет такая:
1. Компонента ловит открывающий символ и начинает писать все последующие символы в буфер (можно использовать Vector).
2. Когда приходит закрывающий символ, то генерируется внешнее событие и строка, накопленная в буфере передается в 1с, а буфер очищается.

В принципе, я могу дописать все это через некоторое время.
9. Prometeus2011 216 03.06.22 10:46 Сейчас в теме
(7) Можно поинтересоваться, зачем вместо штатной ВК использовать стороннюю ВК?
Кроме того, в промышленном решении применять устройство, подключаемое "в разрыв клавиатуры" (которое эмулирует нажатия клавиш) - спорный вариант.
10. Rif_md 6 04.06.22 00:22 Сейчас в теме
(9) Достаточно распространены сканеры, подключаемые по USB и имитирующие ввод с клавиатуры. Со штатной ВК, принимающей штрихкод через внешнее событие 1С часто просто закрывалась, что говорит о нестабильности штатной ВК. Искал замену.
11. Prometeus2011 216 04.06.22 12:44 Сейчас в теме
12. alexnov 49 16.02.23 16:26 Сейчас в теме
Скачал, написал внешнюю обработку, но не могу настроить префикс F7, использую скан-код 65. Не реагирует (((
13. Prometeus2011 216 21.02.23 15:23 Сейчас в теме
(12) Здравствуйте! Если открывающий и закрывающий символы равны, то это вызывало логическую ошибку в алгоритме.
Пофиксил.
Новая версия лежит прямо в репозитории - можно качать без СМ.
14. alexnov 49 21.02.23 17:02 Сейчас в теме
(13) Добрый день, хотел сделать префикс F7 и суффикс Enter. Ввел первым параметром 65, кажется, если не ошибаюсь, что соответствует скан-коду клавиши F7. Соответственно второй параметр оставил без изменений. Не сработало.
15. inclodes 29 19.02.24 16:48 Сейчас в теме
в тонком клиенте не получается подключить компоненту

&НаКлиенте
Процедура ПодключитьИПоместитьВоВременноеХранилище(УстановитьЕслиНеПодключено=Истина)  экспорт
	//ПодключитьВнешнююКомпоненту("ОбщийМакет.Дор_kbdhook", "СС",ТипВнешнейКомпоненты.Native);
	
	НачатьПодключениеВнешнейКомпоненты(
	Новый ОписаниеОповещения(
	"ПослеПодключения",
	ЭтотОбъект,
	УстановитьЕслиНеПодключено),
	ИмяКомпоненты,
	"СС",ТипВнешнейКомпоненты.Native);
КонецПроцедуры   
&НаКлиенте
Процедура ПослеПодключения(Подключено, УстановитьЕслиНеПодключено) Экспорт
	Если Подключено Тогда
		ВК =  Новый("AddIn.СС.KbdHook");   
		ПоместитьВоВременноеХранилище(Новый Структура("ВК",ВК),"AddIn.СС.KbdHook");      
	ИначеЕсли УстановитьЕслиНеПодключено Тогда
		НачатьУстановкуВнешнейКомпоненты(
		Новый ОписаниеОповещения(
		"ПодключитьИПоместитьВоВременноеХранилище",
		ЭтотОбъект,
		ложь),
		ИмяКомпоненты);
	КонецЕсли;
КонецПроцедуры
Показать


установка внешней компоненты не выполнена

или я что-то делаю не так
16. Prometeus2011 216 20.02.24 17:09 Сейчас в теме
(15)
НачатьПодключениеВнешнейКомпоненты

Здравствуйте! Асинхронный метод НачатьУстановкуВнешнейКомпоненты "работает только с компонентами, хранящимися в архиве". Обратите внимание на справку к этому методу. В ней есть ремарочка в конце текста описания.
Проблема должна решиться при помещении компоненты в архив и добавлении соответствующего файла манифеста: _https://forum.mista.ru/topic.php?id=755275 - например.

Если не получится - помогу.
17. boss_kuz 106 18.10.24 07:30 Сейчас в теме
Добрый день. Не подскажите, у меня часто "зависает" перехват. Помогает только перезагрузка компьютера. Вы писали
Для возобновления перехвата - потребуется его перезапустить
. Как можно перезапустить данный процесс ?
18. Prometeus2011 216 18.10.24 10:47 Сейчас в теме
(17) Здравствуйте! Вариантов может быть 100500. Можете поподробнее описать ситуацию:
- какая ось стоит (версия и разрядность)
- какая версия и разрядность платформы 1с
- какой режим запуска клиента 1с (УФ/ОФ)
- можете привести код инициализации компоненты и что перехватываете
- как много времени проходит с момента запуска перехвата до "зависания"
- как внешне выглядит "зависание" (намертво вешается 1с, либо компонента перестает возвращать перехваченные символы или еще что-то...)
Это вот навскидку.
19. boss_kuz 106 21.10.24 05:28 Сейчас в теме
(18) Добрый день.
1. Windows 11
2. Версия 1С:Предприятие 8.3 (8.3.25.1394)
3. Тонкий клиент 64х
4.
&НаКлиенте
Процедура ВыполнитьПодключениеВнешнейКомпоненты(Параметры) Экспорт
	
	ОписаниеОповещения = Новый ОписаниеОповещения("ПодключениеВнешнейКомпонентыЗавершение", ITS_ВнешниеКомпонентыКлиент, Параметры);
	НачатьПодключениеВнешнейКомпоненты(ОписаниеОповещения, Параметры.Местоположение, Параметры.Идентификатор, ТипВнешнейКомпоненты.Native);
	
КонецПроцедуры

&НаКлиенте
Процедура ПодключениеВнешнейКомпонентыЗавершение(Подключение, Параметры) Экспорт
	
	Если Подключение Тогда
		
		Попытка
			ITS_Компоненты[Параметры.Имя] = Новый("AddIn." + Параметры.Идентификатор + "." + Параметры.Класс);
		Исключение
			ITS_ОбщегоНазначенияКлиент.СообщитьПользователю("Ошибка подключения внешней компоненты " + Параметры.Имя +
				Символы.ПС + ОписаниеОшибки());
		КонецПопытки;
				
	ИначеЕсли Не Параметры.Свойство("БылаУстановка") Тогда
		
		Параметры.Вставить("БылаУстановка", Истина);
		
		ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьПодключениеВнешнейКомпоненты", ITS_ВнешниеКомпонентыКлиент, Параметры);
		НачатьУстановкуВнешнейКомпоненты(ОписаниеОповещения, Параметры.Местоположение);
		
	КонецЕсли;
	
КонецПроцедуры
Показать

5. Пока занимаюсь разработкой приложения. Зависает примерно через 3-5 часов. Окно 1С зависаем намертво. Приходится выгружать диспечером. Примечательно, после запуска 1С компонента подключается, команды выполняет. Но внешнего события не происходит
20. Prometeus2011 216 21.10.24 09:36 Сейчас в теме
(19) Здравствуйте! Попробую поймать ошибку.
21. Prometeus2011 216 21.10.24 11:00 Сейчас в теме
(19) Перехват запускаете в строчном режиме ("string") или в посимвольном режиме ("char")?
Оставьте свое сообщение