При разработке интерактивных интерфейсов в платформе 1С:Предприятие 7.7 часто возникает задача динамического поиска. Например, когда пользователь вводит артикул или наименование товара в поле ввода, система должна моментально отфильтровать список без необходимости нажимать клавишу Enter или дополнительную кнопку «Найти». Если ввод осуществляется поочередным нажатием клавиш на клавиатуре, задачу можно решить перехватом клавиатурных событий. Однако при попытке вставить значение из буфера обмена разработчики сталкиваются с аппаратными ограничениями платформы.
Рассмотрим, почему штатные механизмы 1С 7.7 не позволяют «из коробки» отследить факт вставки текста из буфера обмена в поле ввода:
ПриИзмененииТекста, который присутствует в более поздних версиях платформы.Форма.Модифицированность срабатывают только после фиксации введенного значения — при потере фокуса полем ввода или при нажатии Enter.Edit, полностью минуя события 1С.Проанализируем основные практические способы решения этой проблемы — от комбинации внешних компонент до альтернативных элементов управления.
Наиболее популярный и эффективный подход в среде 1С 7.7 — комбинированный перехват действий пользователя с помощью внешних компонент Formex и 1С++.
Разберем по шагам, как настроить отслеживание обоих каналов вставки (клавиатура и мышь):
ПриНажатииКнопкиКлавиатуры мы перехватываем нажатия клавиш. Если нажата комбинация вставки, извлекаем данные из буфера обмена с помощью класса БуферОбмена компоненты 1С++ и сразу вызываем процедуру поиска.ПриОтжатииЛевойКнопки (или ПриОтжатииПравойКнопки) из компоненты Formex. При отжатии кнопки проверяем, находится ли фокус в нужном реквизите поиска, после чего считываем значение и запускаем обработку.Посмотрим на пример логики обработки этих событий в модуле формы:
Процедура ПриНажатииКнопкиКлавиатуры(КодКлавиши, ФлагиShiftCtrlAlt)
// Проверяем нажатие Ctrl+V или Shift+Ins
Если ((КодКлавиши = 86) И (ФлагиShiftCtrlAlt = 2)) Или ((КодКлавиши = 45) И (ФлагиShiftCtrlAlt = 1)) Тогда
Если Форма.АктивныйРеквизит() = "ИскомыйАртикул" Тогда
// Извлекаем значение из буфера и запускаем динамический поиск
ВыполнитьДинамическийПоиск();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ПриОтжатииЛевойКнопки()
Если Форма.АктивныйРеквизит() = "ИскомыйАртикул" Тогда
// Запускаем поиск после клика мышью (например, после вставки из меню)
ВыполнитьДинамическийПоиск();
КонецЕсли;
КонецПроцедуры
Если требуется точный контроль над содержимым текстового поля без использования перехвата событий мыши и клавиатуры, стандартное поле ввода 1С 7.7 можно заменить на внешнее текстовое поле.
MSForms.TextBox. Данный элемент управления имеет встроенное событие OnChange, которое генерируется мгновенно при любом изменении текста в поле — будь то ручной ввод, вставка сочетанием клавиш или вставка через контекстное меню.WebBrowser с полем <input type="text">. На элемент навешивается JavaScript-обработчик события onpaste или oninput, который сразу передает перехваченный текст в 1С.Еще один надежный вариант — организация фонового мониторинга содержимого активного реквизита. С помощью функции ОбработкаОжидания платформы 1С или таймера компоненты Formex можно настроить периодическую проверку текста в поле поиска.
Выясним алгоритм работы таймера:
Для продвинутых разработчиков доступен вариант с перехватом системных сообщений Windows на уровне API (Low-level Hooking / Subclassing). Каждое поле ввода 1С представляет собой стандартное окно Windows класса Edit.
При вставке текста из буфера окно получает сообщение WM_PASTE, а при изменении содержимого отправляет родительскому окну извещение EN_CHANGE в составе сообщения WM_COMMAND. Перехватив эти сообщения через специализированные ВК, можно со 100% точностью отслеживать любую вставку текста независимо от того, какими средствами пользователь её выполнил.
Мы проанализировали проблему отслеживания вставки из буфера обмена в 1С 7.7. Для быстрой реализации оптимально подходит комбинация перехвата клавиш Ctrl+V / Shift+Ins и обработки событий мыши через Formex и 1С++. Если требуется абсолютная точность без привязки к кнопкам мыши, лучшими альтернативами служат опрос поля по таймеру или замена стандартного реквизита на элемент MSForms.TextBox.