Как на форме РМК предотвратить повторное срабатывание кнопки при быстром нажатии Enter?

Программист 1С v8.3 (Управляемые формы) 1С:Розница Торговля и дистрибуция
← На главную

В процессе работы с интерфейсом «Рабочего места кассира» (РМК), особенно в конфигурации 1С:Розница, специалисты и пользователи часто сталкиваются с неприятным эффектом. При оформлении оплаты, когда кассир быстро нажимает клавишу Enter несколько раз подряд, система может инициировать повторное открытие формы оплаты или попытаться дважды пробить чек. Это происходит из-за того, что после первого нажатия кнопка остается активной (в фокусе), а пока программа занята обработкой данных или печатью на фискальном регистраторе, последующие нажатия накапливаются в буфере и «выстреливают» сразу после завершения первой операции.

В этой статье мы подробно разберем, как технически ограничить такое поведение системы, проанализируем причины возникновения очереди сообщений и рассмотрим несколько надежных способов программной защиты от «лишних» нажатий.

Причина возникновения проблемы: очередь сообщений и фокус

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

Основные факторы, влияющие на проблему:

  1. Фокус на элементе: При нажатии на кнопку «Наличные» мышью или через Enter, эта кнопка становится текущим элементом формы. Если форма оплаты закрывается быстро, а фокус возвращается на основную форму, кнопка «Наличные» все еще может оставаться активной.
  2. Задержка оборудования: Печать чека занимает от 1 до 3 секунд. В этот момент интерфейс может выглядеть «замершим», но клавиатура продолжает фиксировать нажатия.
  3. Свойство «Кнопка по умолчанию»: Если кнопка оплаты помечена в свойствах как кнопка по умолчанию, любое нажатие Enter на форме будет приводить к её срабатыванию, даже если фокус находится на неинтерактивном объекте.

Рассмотрим пошагово способы решения этой задачи, начиная от самых простых и заканчивая более сложными архитектурными подходами.

Способ 1: Программный перевод фокуса (решение из темы)

Самый простой и эффективный метод, предложенный в обсуждении, заключается в принудительной смене текущего элемента формы сразу после того, как код обработки нажатия начал выполняться. Выясним причину, почему это помогает: если мы перенесем фокус на поле ввода штрихкода, то последующие нажатия Enter будут восприниматься системой как попытка поиска пустого штрихкода, что совершенно безопасно и не вызывает открытия новых окон.

Рассмотрим пример кода, который следует разместить в обработчике нажатия кнопки оплаты:


&НаКлиенте
Процедура ОплатаНаличными(Команда)
    
    // Переводим фокус на безопасный элемент (например, поле ввода штрихкода)
    ЭтаФорма.ТекущийЭлемент = Элементы.ПолеВводаШтрихкода;
    
    // Далее следует основной код обработки оплаты
    ОткрытьФормуОплаты("Наличные");
    
КонецПроцедуры

Важно помнить, что в управляемом приложении обращение к ТекущийЭлемент работает мгновенно на стороне клиента, что позволяет «обезвредить» кнопку еще до того, как начнется серверный вызов или обращение к торговому оборудованию.

Способ 2: Использование логического флага блокировки

Разберем еще один надежный метод, который часто применяется в профессиональной разработке — использование переменной-флага. Этот метод гарантирует, что даже если фокус не перевелся, повторный вход в процедуру будет заблокирован на программном уровне.

Для этого в модуле формы необходимо объявить переменную, которая будет хранить состояние процесса:


&НаКлиенте
Перем ОбработкаОплатыВыполняется;

&НаКлиенте
Процедура ОплатаНаличными(Команда)
    
    // Проверяем, не запущена ли уже процедура
    Если ОбработкаОплатыВыполняется = Истина Тогда
        Возврат; // Выходим, если нажатие повторное
    КонецЕсли;
    
    // Устанавливаем блокировку
    ОбработкаОплатыВыполняется = Истина;
    
    Попытка
        // Выполняем логику оплаты и печати
        ВыполнитьОплатуЧека();
    Исключение
        // В случае ошибки важно вернуть возможность нажатия
        ОбработкаОплатыВыполняется = Ложь;
        ВызватьИсключение;
    КонецПопытки;
    
    // После успешного завершения флаг можно не сбрасывать, 
    // если форма РМК переоткрывается или очищается для нового чека
    ОбработкаОплатыВыполняется = Ложь;
    
КонецПроцедуры

Этот подход предотвращает выполнение тяжелого кода несколько раз, защищая базу данных от дублирования документов.

Способ 3: Управление доступностью кнопок

Проанализируем ситуацию, когда нам нужно визуально показать пользователю, что нажимать кнопки больше не стоит. В начале процесса мы можем сделать кнопки оплаты недоступными. Это не только предотвращает срабатывание Enter, но и отключает возможность клика мышью.

Рассмотрим, как это реализовать:


&НаКлиенте
Процедура ОбработатьНажатиеОплаты()
    
    // Отключаем кнопки
    Элементы.КнопкаНаличные.Доступность = Ложь;
    Элементы.КнопкаКарта.Доступность = Ложь;
    
    // Принудительно обновляем отображение, чтобы кнопки "посерели" сразу
    ЭтаФорма.ОбновитьОтображениеДанных();
    
    // Выполняем длительную операцию
    ЗавершитьОформлениеЧека();
    
    // Возвращаем доступность
    Элементы.КнопкаНаличные.Доступность = Истина;
    Элементы.КнопкаКарта.Доступность = Истина;
    
КонецПроцедуры

Использование метода ОбновитьОтображениеДанных() здесь критически важно, так как без него форма может не успеть перерисоваться до начала выполнения синхронного серверного вызова.

Способ 4: Настройка свойств «Кнопка по умолчанию» и «Горячие клавиши»

Иногда проблема кроется в самих настройках элементов формы. Посмотрим на свойства кнопок в конфигураторе:

  1. Кнопка по умолчанию: Если у вас есть кнопка, которая «ловит» все нажатия Enter, проверьте свойство КнопкаПоУмолчанию у формы и у самой кнопки. Если оно установлено в значение Да, попробуйте его отключить.
  2. Сочетание клавиш: В ритейле хорошим тоном считается назначение кнопкам оплаты функциональных клавиш (например, F6 для наличных, F7 для карты). Это разделяет поток ввода: Enter используется для подтверждения ввода количества или цены, а функциональные клавиши — для завершения чека.

Рекомендации по работе с очередью сообщений

Если ни один из вышеперечисленных методов не помогает (что бывает при очень медленных драйверах торгового оборудования), можно прибегнуть к использованию обработчика ожидания. Это позволит «разорвать» поток выполнения и дать системе время очистить очередь сообщений клавиатуры.

Рассмотрим схему реализации:

  1. В процедуре нажатия кнопки мы только устанавливаем флаг и вызываем ПодключитьОбработчикОжидания("ВыполнитьПечать", 0.1, Истина).
  2. Процедура ВыполнитьПечать запускается через долю секунды, когда нажатия клавиш уже «пролетели».

Подведем итог. Для решения проблемы с «лишним» Enter наиболее эффективным и простым в реализации является комбинированный подход: перевод фокуса на нейтральный элемент (поле ввода штрихкода) в сочетании с проверкой логического флага блокировки. Это обеспечит стабильную работу РМК даже при очень высокой скорости работы кассира и задержках оборудования.

← На главную