Как программно позиционировать и закрепить печатную форму или окно в заданной области экрана 1С?

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

При разработке интерфейсов в 1С:Предприятии 8 перед программистом нередко встает задача разместить открывающуюся форму (например, печатную форму документа или специализированную панель подбора) в строго определенной части экрана. В старых обычных формах мы могли легко управлять координатами с помощью свойств Лево и Верх. Однако с переходом на управляемые формы (УФ) концепция кардинально изменилась: теперь платформа самостоятельно рассчитывает геометрию окон.

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

Почему в управляемых формах нельзя просто задать координаты X и Y?

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

Тем не менее, нам часто требуется закрепить печатную форму сбоку или снизу экрана, чтобы пользователь мог одновременно видеть и документ-источник, и результат формирования печатной формы. Давайте детально изучим доступные нам инструменты.

Метод 1. Использование штатных свойств управляемой формы

Платформа 1С предоставляет набор свойств управляемой формы, которые позволяют управлять её начальным положением и поведением на экране. Эти свойства необходимо настраивать строго до открытия формы — например, в обработчике события ПриСозданииНаСервере или передавая их в параметрах метода ОткрытьФорму.

Рассмотрим ключевые свойства, которые помогут нам решить задачу:

Проанализируем пример программной настройки формы при ее создании на сервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Задаем режим прикрепленного окна
    ЭтаФорма.СостояниеОкна = ВариантСостоянияОкна.Прикрепленное;
    
    // Прижимаем форму к нижней части экрана
    ЭтаФорма.ПоложениеПрикрепленногоОкна = ВариантПоложенияПрикрепленногоОкна.Низ;
    
    // Блокируем окно владельца, если требуется последовательная работа
    ЭтаФорма.РежимОткрытияОкна = РежимОткрытияОкнаФормы.Независимый;
    
КонецПроцедуры

Этот способ является полностью безопасным, кроссплатформенным и будет корректно работать как на тонком клиенте под Windows/Linux, так и в веб-клиенте.

Метод 2. Обход кэширования через КлючСохраненияПоложенияОкна

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

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

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

Вариант А. Динамическая генерация уникального ключа сохранения

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


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

Вариант Б. Принудительная очистка настроек окна в системном хранилище

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


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

Метод 3. Эмуляция нажатия горячих клавиш через WScript.Shell

Рассмотрим нестандартный метод, предложенный в обсуждении на форуме. Он основан на использовании Windows Script Host и COM-объекта WScript.Shell для имитации нажатий клавиш клавиатуры. Этот способ позволяет эмулировать вызов системного меню окна 1С и выбор команды «Закрепить справа/слева/снизу».

Давайте посмотрим на программную реализацию этого алгоритма:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    // Подключаем однократный обработчик ожидания, чтобы дать форме полностью отрисоваться
    ПодключитьОбработчикОжидания("ЗакрепитьФормуСправа", 0.1, Истина);
    
КонецПроцедуры

&НаКлиенте
Процедура ЗакрепитьФормуСправа()
    
    Если ЭтаФорма.ВводДоступен() Тогда
        
        Попытка
            WSHShell = Новый COMОбъект("WScript.Shell");
            
            // Активируем системное меню окна комбинацией клавиш
            WSHShell.SendKeys("%"); // Нажатие Alt
            WSHShell.SendKeys("{DOWN 5}"); // Переход по элементам системного меню
            WSHShell.SendKeys("{RIGHT}");  // Переход в подменю прикрепления
            WSHShell.SendKeys("{UP 5}");   // Выбор нужного направления закрепления
            WSHShell.SendKeys("{ENTER}");  // Подтверждение действия
        Исключение
            ЗаписьЖурналаРегистрации("ЭмуляцияИнтерфейса", УровеньЖурналаРегистрации.Предупреждение, , , 
                "Не удалось запустить скрипт эмуляции нажатий: " + ОписаниеОшибки());
        КонецПопытки;
        
        ОтключитьОбработчикОжидания("ЗакрепитьФормуСправа");
        
    КонецЕсли;
    
КонецПроцедуры

Важные ограничения и недостатки данного метода:

  1. Зависимость от операционной системы. Данный метод работает исключительно под ОС Windows и только в толстом или тонком клиенте 1С. На веб-клиенте, macOS или Linux вызов COM-объекта завершится аварийной ошибкой.
  2. Привязка к активному окну (Фокус). Метод SendKeys отправляет нажатия в текущее активное окно операционной системы. Если пользователь в момент открытия формы переключится на другое приложение (например, на документ Excel или браузер), то эмулируемые нажатия клавиш будут выполнены там, что может привести к непредсказуемым действиям в сторонних программах.
  3. Зависимость от релиза платформы 1С. Структура системного меню и горячие клавиши управления окнами могут меняться от версии к версии платформы 1С:Предприятие. Настройка, стабильно работающая на релизе 8.3.12, может перестать работать или начать выполнять другие команды на релизе 8.3.21.

Метод 4. Точное позиционирование через внешние компоненты и WinAPI

Если перед вами стоит бескомпромиссная задача поместить управляемую форму строго по пиксельным координатам (например, X: 100, Y: 150) под управлением ОС Windows, стандартных средств 1С будет недостаточно. В этом случае на помощь приходит использование WinAPI через внешние компоненты (например, Native API).

Идея метода заключается в получении системного дескриптора окна 1С (так называемого HWND) и вызове стандартных функций библиотеки user32.dll, таких как SetWindowPos или MoveWindow.

Общая схема реализации выглядит следующим образом:

  1. Разработчик регистрирует в системе или подключает непосредственно в коде 1С внешнюю компоненту, умеющую работать с окнами Windows.
  2. В обработчике события формы ПриОткрытии на клиенте компонент находит окно 1С по его уникальному заголовку (который можно временно сгенерировать уникальным на момент поиска).
  3. Через функцию SetWindowPos окну принудительно выставляются точные геометрические параметры: координаты левого верхнего угла, ширина и высота.

Этот способ требует продвинутых навыков программирования и написания/подключения внешних библиотек, однако он гарантирует абсолютно точное пиксельное позиционирование окна в обход любых внутренних ограничений платформы 1С.

Резюме и рекомендации

Подводя итоги нашего анализа, выделим оптимальные стратегии для решения задачи позиционирования форм:

← На главную