Как программно переключаться между окнами в 1С 7.7 с помощью Formex на сенсорных экранах?

Программист 1С v7.7
← На главную

При разработке интерфейсов для планшетов и сенсорных терминалов на базе 1С 7.7 программисты часто сталкиваются с тем, что привычные методы эмуляции клавиатуры, такие как SendKeys через WScript.Shell, работают нестабильно. Особенно остро эта проблема проявляется в формах обработок: при нажатии пальцем на кнопку событие отрабатывает, кнопка визуально нажимается, но переключение окон (комбинация Ctrl+Tab) не происходит. Это связано с особенностями обработки системных сообщений WM_POINTER и WM_TOUCH в Windows, которые «перехватывают» фокус ввода иначе, чем обычный клик мышью.

В этой статье мы подробно рассмотрим, как реализовать надежное циклическое переключение между открытыми окнами, используя возможности внешней компоненты Formex. Мы разберем, почему стандартные методы подводят, и напишем программный код для управления фокусом окон.

Разбор проблемы: Почему SendKeys не работает на сенсоре?

Проанализируем ситуацию: когда пользователь нажимает на экран планшета, операционная система генерирует последовательность событий. В 1С 7.7 форма обработки (объект Обработка) имеет специфический цикл обработки сообщений. Эмуляция нажатия SendKeys("^({TAB})") отправляет команду в активное окно. Однако в момент касания сенсорного экрана фокус может на долю секунды «залипнуть» на самом элементе управления или уйти в системный слой обработки жестов. В результате команда уходит в пустоту, так как ни одно окно не готово принять клавиатурный ввод в этот микроинтервал времени.

Для решения этой задачи нам необходимо отказаться от эмуляции клавиатуры и перейти к прямому управлению объектами окон через программный интерфейс Formex.

Шаг 1: Получение списка открытых окон

Первым делом нам нужно понять, какие окна сейчас открыты в сеансе пользователя. Для этого в Formex существует объект Сервис и его метод СписокВсехОткрытыхФорм(). Этот метод возвращает таблицу значений, содержащую контексты всех активных окон.

Рассмотрим пример функции, которая подготавливает список окон для переключения:


Процедура ПереключитьОкноНаСледующее()
    Сервис = СоздатьОбъект("Сервис");
    ТЗ_Окна = Сервис.СписокВсехОткрытыхФорм();
    
    // ТЗ_Окна содержит колонки: "Заголовок", "Контекст", "Вид"
    КоличествоОкон = ТЗ_Окна.КоличествоСтрок();
    
    Если КоличествоОкон < 2 Тогда
        Возврат; // Переключаться некуда
    КонецЕсли;
    
    // Определяем текущее активное окно
    АктивныйКонтекст = Сервис.АктивноеОкно();
    
    НомерТекущейСтроки = 0;
    ТЗ_Окна.ВыбратьСтроки();
    Пока ТЗ_Окна.ПолучитьСтроку() = 1 Цикл
        Если ТЗ_Окна.Контекст = АктивныйКонтекст Тогда
            НомерТекущейСтроки = ТЗ_Окна.НомерСтроки;
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Шаг 2: Реализация циклической логики («Листание по кругу»)

Выясним, какое окно должно стать следующим. Если текущее окно — последнее в списке, нам нужно вернуться в начало. Если мы не смогли определить текущее окно (например, фокус был на рабочем столе программы), выберем первое доступное.

Продолжим наш код, добавив логику выбора следующего индекса:


Если НомерТекущейСтроки = 0 Тогда
    // Если фокус потерян, берем первое окно
    СледующийНомер = 1;
ИначеЕсли НомерТекущейСтроки = КоличествоОкон Тогда
    // Если мы на последнем окне, переходим к первому
    СледующийНомер = 1;
Иначе
    // Просто берем следующее по списку
    СледующийНомер = НомерТекущейСтроки + 1;
КонецЕсли;
    
ТЗ_Окна.ПолучитьСтрокуПоНомеру(СледующийНомер);
КонтекстСледующегоОкна = ТЗ_Окна.Контекст;

Шаг 3: Активация выбранного окна

Теперь самое важное — вывести выбранное окно на передний план и передать ему фокус ввода. Для этого мы будем использовать метод НаПереднийПлан(), который доступен для объектов типа «Окно» в Formex.

Важный нюанс для планшетов: просто вывести окно на передний план иногда недостаточно. Нужно принудительно заставить систему считать его активным. Рассмотрим финальную часть реализации:


    // Получаем объект окна из контекста формы
    Окно = СоздатьОбъект("Окна");
    // В Formex можно работать с окном напрямую через контекст
    Попытка
        КонтекстСледующегоОкна.Форма.НаПереднийПлан();
        
        // Для надежности на сенсорных экранах используем ВзятьВФокус
        Сервис.ВзятьВФокус(КонтекстСледующегоОкна);
    Исключение
        // Если форма была закрыта в процессе, просто вызываем процедуру еще раз
        ПереключитьОкноНаСледующее();
    КонецПопытки;
КонецПроцедуры

Альтернативный метод: Использование внешних событий

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

Логика работы следующая:

  1. Кнопка на текущей форме посылает широковещательный сигнал через Сервис.ВнешнееСобытие().
  2. В каждой форме прописана процедура ПриВнешнемСобытии.
  3. Форма-получатель анализирует, должна ли она стать активной, и если да — вызывает НаПереднийПлан() сама для себя.

Пример кода отправки события:


Процедура НажатиеКнопкиПереключения()
    Сервис = СоздатьОбъект("Сервис");
    // Отправляем источнику "Система", событие "Переключить", данные - имя следующего окна
    Сервис.ВнешнееСобытие("System", "SwitchWindow", "Next");
КонецПроцедуры

Особенности работы с масштабированием на планшетах

Поскольку мы обсуждаем сенсорные экраны, важно упомянуть масштабирование интерфейса. При переключении окон на устройствах с высоким разрешением (High DPI) элементы управления могут выглядеть мелкими. В сообщениях форума предлагалось использовать Класс Привязки и динамическое изменение шрифтов.

Проанализируем, как Formex помогает в этом: вы можете программно менять размер шрифта при открытии формы, используя метод УстановитьШрифт(). Это позволит сделать кнопки переключения окон («Домой», «Следующее окно») крупными и удобными для нажатия пальцем, независимо от физического размера дисплея.

Резюме: Для стабильной работы интерфейса на планшетах в среде 1С 7.7 следует избегать методов WScript.Shell. Использование таблицы открытых форм через Сервис.СписокВсехОткрытыхФорм() в сочетании с методом НаПереднийПлан() гарантирует, что переключение произойдет мгновенно и без потерь фокуса, что критически важно для оперативной работы пользователей.

← На главную