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

21.02.23

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

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

Скачать файл

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

Наименование По подписке [?] Купить один файл
Внешняя компонента - универсальный, надежный перехватчик клавиатурных событий:
.zip 78,44Kb
21
21 Скачать (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    54230    9    69    

46

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

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

2400 руб.

25.06.2024    1227    3    4    

3

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

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

3600 руб.

02.09.2010    77641    73    257    

191

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

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

4600 руб.

27.06.2023    3712    3    0    

5

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

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

2400 руб.

04.05.2018    47503    124    66    

67

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

Внешняя компонента позволяет печатать PDF файлы непосредственно из 1С, не используя при этом сторонних программ. Прекрасно работает на сервере, тонком клиенте и веб-клиенте. Основана на проекте PDFium из состава проекта Chromium/Chrome

1500 руб.

17.09.2018    36899    114    127    

115

Разработка внешних компонент Системный администратор Программист Стажер Бесплатно (free)

Библиотека для работы с базами SQLite из 1С на основе внешней компоненты. Для Linux и Windows, бесплатно и с открытым исходным кодом!

14.01.2025    2461    bayselonarrend    14    

48

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

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

04.12.2024    5122    kovalevdmv    26    

75
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Pr-Mex 170 30.11.21 20:40 Сейчас в теме
Плюс за разработку.
VanessaExt тоже умеет перехватывать клавиши.
https://github.com/lintest/VanessaExt
Vasvas05; user1590876; shiaju; +3 Ответить
2. Prometeus2011 217 01.12.21 15:10 Сейчас в теме
(1)Хм. Спасибо. Там и другой функционал есть интересный. И код открытый.
6. zerik 12 01.02.22 12:22 Сейчас в теме
(1)Что-то уже всю документацию перерыл, не могу найти перехват клавиш, покажите как, пожалуйста.
22. starik-2005 3127 17.01.25 11:13 Сейчас в теме
(1) Кстати, не нашел там перехвата клавиш - нашел эмуляцию их нажатия, хотя это умеет и вбскрипт, которым пользуются для оного не только лишь все.

Но у меня такой вопрос: а могут эти компоненты перехватывать контрл+ц/в? И желательно только для окна 1С-а.
3. ivanov660 4673 07.12.21 17:09 Сейчас в теме
Антивирус не ругается на данную компоненту?
4. Prometeus2011 217 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 217 03.06.22 10:08 Сейчас в теме
(7) Для полноценного перехвата последовательного ввода символов от устройств ввода требуется в рамках компоненты ДОПОЛНИТЕЛЬНО реализовать буфер накопления получаемых от устройства ввода символов.
Также сканер должен начинать передачу с открывающего (какого-нибудь непечатаемого) символа и заканчивать передачу тоже каким-то заранее определенным символом (в настройках всех сканеров, с которыми мне приходилось иметь дело, такие возможности присутствуют - обычно это знак табуляции или Enter).

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

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

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


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

или я что-то делаю не так
16. Prometeus2011 217 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 217 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 217 21.10.24 09:36 Сейчас в теме
(19) Здравствуйте! Попробую поймать ошибку.
21. Prometeus2011 217 21.10.24 11:00 Сейчас в теме
(19) Перехват запускаете в строчном режиме ("string") или в посимвольном режиме ("char")?
Оставьте свое сообщение