В современных интерфейсах мы привыкли к тому, что при вводе первых букв в строке поиска система мгновенно предлагает варианты или фильтрует список. Однако в платформе 1С:Предприятие 7.7 штатные средства не позволяют реализовать такое поведение. Стандартное событие ПриИзменении срабатывает только после нажатия клавиши Enter или при потере фокуса элементом управления. В этой статье мы подробно разберем, как обойти это ограничение, используя мощные инструменты расширения платформы, такие как FormEx, 1C++ и специализированные библиотеки.
Разберем ситуацию: когда пользователь вводит текст в текстовое поле, данные сначала попадают во внутренний буфер Windows-элемента управления (Edit control). 1С «узнает» о том, что данные изменились, только в определенные моменты, диктуемые логикой ее движка. Попытка использовать процедуру ПриНажатииКнопкиКлавиатуры из библиотеки FormEx сталкивается с тем, что в момент нажатия переменная, связанная с полем ввода, еще содержит старое значение. Чтобы реализовать «живой» отбор, нам нужно научиться извлекать текст непосредственно из графического элемента в реальном времени.
Первый и наиболее гибкий способ — это использование функций Windows API для прямого обращения к текстовому полю. Рассмотрим этот метод по шагам. Нам необходимо получить дескриптор окна (hWnd) активного элемента и отправить ему системное сообщение.
Для начала проанализируем алгоритм. В процедуре перехвата клавиатуры мы не можем просто прочитать значение переменной. Вместо этого мы используем сообщение WM_GETTEXT. Проанализируем пример логики:
ПриНажатииКнопкиКлавиатуры проверяем, что фокус находится на нужном нам реквизите.Сервис из FormEx для получения доступа к низкоуровневым функциям.SendMessage для получения текущего содержимого поля ввода, которое еще не записано в переменную 1С.Рассмотрим пример кода, который иллюстрирует этот подход:
Процедура ПриНажатииКнопкиКлавиатуры(Конт, КодКл, Альт, Шифт, Контрл, Символ, ФлагСтандартнойОбработки)
// Проверяем, в каком элементе мы находимся
АктивныйЭлемент = Форма.АктивныйЭлемент();
Если АктивныйЭлемент = "НайтиТекст" Тогда
// ИспользуемSendMessage для получения текста из Edit-контрола
// Это позволяет увидеть символ сразу после нажатия
ТекстПоля = глПолучитьТекстОкна(АктивныйЭлемент);
// Здесь можно вызвать процедуру отбора
ВыполнитьПоиск(ТекстПоля);
КонецЕсли;
КонецПроцедуры
Важно понимать, что поиск при каждом нажатии клавиши может сильно замедлить работу интерфейса, особенно если база данных большая. Рассмотрим, как оптимизировать этот процесс с помощью таймера. Выясним причину: если пользователь печатает быстро, нам нет смысла искать «М», потом «Ма», потом «Мам» — лучше дождаться, пока он закончит вводить слово «Мама».
Для этого мы применим концепцию таймера ожидания. Проанализируем шаги реализации:
Форма.ОбработкаОжидания или через объект Таймер в FormEx.Это позволяет сделать интерфейс отзывчивым и избежать «зависаний» при быстром наборе текста.
Для наиболее опытных разработчиков существует метод субклассинга (Subclassing). Это подмена процедуры обработки сообщений окна. В 1С 7.7 это реализуется с помощью внешней компоненты svcsvc.dll.
Разберем, как это работает:
Каждый элемент управления в Windows (кнопка, текстовое поле) получает сообщения от операционной системы. Одно из таких сообщений — EN_CHANGE. Оно отправляется родительскому окну всякий раз, когда текст в поле изменился (неважно, нажата ли клавиша, вставлен текст из буфера или удален). Перехватив это сообщение, мы получаем идеальную точку входа для нашего динамического поиска.
Преимущества этого метода:
Если стандартное текстовое поле 1С 7.7 кажется слишком ограниченным, мы можем рассмотреть вариант замены его на полноценный ActiveX-контрол. Например, из библиотеки VBCCR (Visual Basic Common Controls Replacement).
Посмотрим на последовательность действий:
Change, которое пробрасывается в 1С.ПриВнешнемСобытии мы ловим сигнал от этого объекта и выполняем поиск.Важный нюанс: при использовании ActiveX необходимо убедиться, что соответствующая библиотека (DLL/OCX) зарегистрирована на всех клиентских машинах. Это может потребовать дополнительных усилий от системного администратора, но дает самый профессиональный результат в плане UI/UX.
Когда мы научились перехватывать ввод, нужно правильно организовать сам отбор. Проанализируем ситуацию, когда данных много. В 1С 7.7 для динамического обновления списков лучше всего использовать УстановитьФильтр() для справочников или работу с объектом ТаблицаЗначений, если данные выводятся в виде таблицы на форме.
Пример оптимизированного поиска в таблице значений:
Процедура ВыполнитьПоиск(СтрокаПоиска)
// Очищаем текущий список
СписокРезультатов.УдалитьСтроки();
// Перебираем исходные данные
ИсходныеДанные.ВыбратьСтроки();
Пока ИсходныеДанные.ПолучитьСтроку() = 1 Цикл
Если Найти(НРег(ИсходныеДанные.Наименование), НРег(СтрокаПоиска)) > 0 Тогда
// Добавляем подходящие строки в отображаемую таблицу
СписокРезультатов.НоваяСтрока();
СписокРезультатов.Наименование = ИсходныеДанные.Наименование;
// Копируем остальные реквизиты...
КонецЕсли;
КонецЦикла;
// Обновляем форму
Форма.Обновить();
КонецПроцедуры
В этом примере мы используем функцию НРег, чтобы поиск был регистронезависимым, что критически важно для удобства пользователя. Также помните, что если вы используете 1С++, то запросы через Direct SQL к базе данных будут работать в десятки раз быстрее, чем перебор справочника в цикле.
Мы рассмотрели несколько способов реализации динамического ввода. Подведем итоги: FormEx с WinAPI — самый распространенный и надежный метод для обычных задач. svcsvc.dll — выбор профессионалов для максимально быстрого отклика. ActiveX — радикальное решение, если нужны дополнительные свойства оформления поля ввода. Использование таймеров — обязательное условие для комфортной работы пользователя без «тормозов» интерфейса.
Выбирайте метод исходя из ваших навыков и доступности внешних компонент в вашей организации. Каждый из этих подходов превращает старую добрую «семерку» в современный и удобный инструмент для работы с данными.