Платформа 1С:Предприятие 7.7, несмотря на свой солидный возраст, до сих пор используется во многих организациях. Одной из частых проблем, с которой сталкиваются разработчики (особенно те, кто привык к логике событийной модели 1С 8.х), является отсутствие явных обработчиков событий для элементов формы, таких как «ПриИзменении» или «ПриВыходе».
Рассмотрим подробно задачу: как отловить момент, когда пользователь закончил ввод данных в поле (нажал Enter, Tab или кликнул мышкой в другое место), чтобы проверить введенное значение. Разберем как штатные способы, так и продвинутые методы с использованием внешних компонент.
В современных версиях 1С (8.2, 8.3) у поля ввода есть событие ПриИзменении, которое срабатывает после окончания редактирования, и событие ПриОкончанииВводаТекста. В версии 7.7 все устроено иначе. Нам необходимо реализовать валидацию данных сразу после того, как курсор покидает поле, не дожидаясь нажатия кнопки «ОК» или записи документа.
Это самое простое и надежное решение, которое не требует использования внешних компонент. В свойствах любого элемента диалога (поля ввода) есть вкладка Дополнительно (или строка формулы внизу свойств, в зависимости от режима редактора), где можно указать вызов функции.
Проанализируем, как это работает. Функция, указанная в формуле, выполняется в тот момент, когда элемент управления теряет фокус, но только при условии, что значение в поле было изменено интерактивно.
Если пользователь зашел в поле, ничего не менял и вышел — формула не сработает. Если изменил и нажал Enter или Tab — формула сработает.
Алгоритм действий:
ПроверитьАртикул().Далее в модуле формы опишем логику проверки. Важный момент: если проверка не прошла, мы хотим запретить пользователю покидать поле. Для этого в 1С 7.7 используется системная функция СтатусВозврата(0).
Рассмотрим пример кода:
Процедура ПроверитьАртикул()
// Получаем текущее значение реквизита, связанного с полем
ТекАртикул = Артикул;
// Простейшая проверка: артикул не должен быть короче 3 символов
Если СтрДлина(СокрЛП(ТекАртикул)) < 3 Тогда
Предупреждение("Артикул слишком короткий! Введите минимум 3 символа.");
// Эта команда отменяет событие выхода из поля.
// Фокус вернется обратно в поле ввода.
СтатусВозврата(0);
КонецЕсли;
// Также здесь можно выполнить поиск в базе данных
СпрТовары = СоздатьОбъект("Справочник.Номенклатура");
Если СпрТовары.НайтиПоРеквизиту("Артикул", ТекАртикул, 1) = 1 Тогда
Предупреждение("Товар с таким артикулом уже существует: " + СпрТовары.Наименование);
// Не обязательно запрещать выход, можно просто предупредить
КонецЕсли;
КонецПроцедуры
Преимущества метода:
Недостатки:
Если нам необходимо отлавливать сам факт перехода фокуса (даже если данные не менялись), штатная формула не поможет. В этом случае применим классический лайфхак для 1С 7.7 — мониторинг активного элемента через таймер.
Суть метода заключается в том, что мы запоминаем имя текущего активного элемента и постоянно сравниваем его с новым значением. Как только они начинают различаться — значит, фокус перешел на другой элемент.
Разберем реализацию по шагам:
ПриОткрытии запустим ОбработкаОжидания.Рассмотрим код решения:
Перем ПредЭлемент; // Глобальная переменная модуля формы
Процедура ПриСменеАктивногоЭлемента(ИмяСтарого, ИмяНового)
// Здесь пишем логику обработки события
// Например, если мы ушли из поля "Контрагент"
Если ИмяСтарого = "Контрагент" Тогда
// Выполняем действия при потере фокуса полем Контрагент
Сообщить("Вы покинули поле выбора контрагента");
КонецЕсли;
// Например, если мы пришли в поле "Сумма"
Если ИмяНового = "Сумма" Тогда
Сообщить("Вы активировали поле Сумма");
КонецЕсли;
КонецПроцедуры
Процедура МенеджерФокуса()
// Получаем имя текущего элемента формы, на котором стоит курсор
ТекЭлемент = Форма.АктивныйЭлемент();
// Если элемент изменился по сравнению с прошлым замером
Если ТекЭлемент <> ПредЭлемент Тогда
ПриСменеАктивногоЭлемента(ПредЭлемент, ТекЭлемент);
ПредЭлемент = ТекЭлемент; // Запоминаем новое состояние
КонецЕсли;
КонецПроцедуры
Процедура ПриОткрытии()
ПредЭлемент = Форма.АктивныйЭлемент();
// Запускаем проверку каждые 0.1 - 0.2 секунды
ОбработкаОжидания("МенеджерФокуса", 1);
КонецПроцедуры
Важные нюансы:
ОбработкаОжидания в 7.7 принимает время в секундах. Минимальное целое значение — 1 секунда, что слишком медленно для интерфейса. Однако, с использованием внешних компонент (например, FormEx) можно задавать интервалы в миллисекундах (через Сервис.ОбработкаОжидания).Для профессиональной разработки на 1С 7.7 стандартом де-факто стало использование библиотеки FormEx. Она позволяет перехватывать системные события Windows и сообщения форме.
С помощью FormEx можно реализовать полноценные события, аналогичные современным OnExit (ПриВыходе) или OnFocus (ПриПолученииФокуса).
Для этого используется механизм перехвата событий клавиатуры и мыши. Обычно это делается через загрузку компоненты и включение режима перехвата.
Рассмотрим концептуальный пример с использованием FormEx (требует наличия FormEx.dll в папке базы или bin):
Перем Сервис;
Процедура ПриОткрытии()
Если ЗагрузитьВнешнююКомпоненту("FormEx.dll") = 0 Тогда
Сообщить("Не удалось загрузить FormEx!", "!");
Возврат;
КонецЕсли;
Сервис = СоздатьОбъект("Сервис");
// Включаем расширенную обработку событий формы
Сервис.Включить("Events");
КонецПроцедуры
// Предопределенная процедура FormEx, перехватывающая нажатия клавиш
Процедура ПриНажатииКнопкиКлавиатуры(КодКлавиши, Альт, Шифт, Контрл, Символ, ФлагОстановить)
// Коды клавиш: 13 - Enter, 9 - Tab
Если (КодКлавиши = 13) ИЛИ (КодКлавиши = 9) Тогда
ТекЭлемент = Форма.АктивныйЭлемент();
Если ТекЭлемент = "МоеПолеВвода" Тогда
// Здесь выполняем проверку ПЕРЕД выходом
Если Не ПроверитьЗначение() Тогда
Предупреждение("Значение некорректно!");
ФлагОстановить = 1; // Запрещаем выход (отменяем нажатие клавиши)
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот метод намного мощнее, так как позволяет отменить само действие выхода из поля (через флаг остановки события), анализируя нажатую клавишу.
В теме также обсуждалась задача проверки введенного значения непосредственно в процессе ввода (при нажатии каждой буквы), например, для реализации «живого поиска» в справочнике или подбора номенклатуры.
Стандартные поля 1С 7.7 не умеют генерировать событие при вводе каждого символа. Решение заключается в подмене стандартного поля ввода на ActiveX компонент (обычно из библиотеки Microsoft Forms 2.0 — FM20.DLL, которая входит в состав MS Office).
Рассмотрим логику реализации:
Microsoft Forms 2.0 TextBox.У объекта TextBox из этой библиотеки есть событие Change (Изменение), которое срабатывает при каждом нажатии клавиши, и событие Exit (Выход).
// Примерный обработчик события Change для ActiveX поля
Процедура ActiveXПоле_Change()
ТекстПоиска = ActiveXПоле.Text; // Получаем текущий текст
// Выполняем поиск по подстроке прямо во время ввода
Если СтрДлина(ТекстПоиска) > 2 Тогда
ОбновитьСписокНайденного(ТекстПоиска);
КонецЕсли;
КонецПроцедуры
Риски использования ActiveX:
Подведем итог. Для большинства задач проверки введенных данных в 1С 7.7 достаточно использовать стандартный механизм: вкладка «Формула» в свойствах элемента + функция в модуле формы с использованием СтатусВозврата(0). Это работает стабильно и не требует внешних библиотек.
Если же задача стоит шире — например, отслеживать перемещение фокуса без изменения данных или реагировать на ввод каждого символа — необходимо использовать внешние компоненты (FormEx, 1C++) или ActiveX элементы, принимая во внимание усложнение поддержки такой конфигурации.