В процессе разработки на платформе 1С:Предприятие 8.2 или 8.3 (при использовании обычных форм) часто возникает задача управления геометрией окна. Например, нам может потребоваться, чтобы форма списка задач или справочника всегда открывалась в определенной части экрана (допустим, прижатой к правому краю) или корректно восстанавливала свое положение после закрытия. Несмотря на кажущуюся простоту, в обычном приложении существует ряд нюансов, связанных с тем, как платформа кэширует настройки пользователя.
В этой статье мы подробно рассмотрим, как программно управлять координатами формы, как вычислить разрешение экрана пользователя для точного позиционирования и что делать, если стандартные механизмы сохранения положения окна дают сбой.
Для начала проанализируем стандартные свойства объекта Форма, отвечающие за ее положение. Это Лево, Верх, Ширина и Высота. Казалось бы, достаточно прописать их значения в процедуре ПриОткрытии, и задача решена. Однако на практике программисты часто сталкиваются с тем, что платформа игнорирует эти установки.
Важно понимать: платформа 1С отдает приоритет сохраненным настройкам пользователя. Если пользователь хотя бы раз изменил положение окна вручную, эти данные записываются в системное хранилище настроек по ключу, соответствующему имени формы или значению свойства ИмяСохраненияПоложенияОкна. При следующем открытии 1С сначала считывает эти координаты и применяет их, игнорируя ваши программные установки в коде.
Чтобы программное управление координатами заработало стабильно, необходимо соблюсти два условия:
СоединяемоеОкно должно быть установлено в значение Ложь. Если окно является соединяемым (прикрепляемым к краям главного окна), программная установка координат Лево и Верх работать не будет.Рассмотрим пример кода, который очищает старые настройки перед тем, как задать новые:
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
// Очищаем сохраненное положение, чтобы применить свои координаты
КлючОбъекта = "Общее/НастройкиФорм/" + ИмяСохраненияПоложенияОкна;
ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, "", ИмяПользователя());
КонецПроцедуры
Разберем ситуацию, когда нам нужно расположить окно в правой части экрана, заняв всю доступную высоту. Для этого нам нужно знать разрешение монитора пользователя. Поскольку в 1С нет встроенной функции РазрешениеЭкрана(), мы воспользуемся возможностями операционной системы через COM-объекты.
Проанализируем метод с использованием HTMLDocument. Это быстрый и надежный способ получить параметры клиентской области:
Функция ПолучитьПараметрыЭкрана() Экспорт
Результат = Новый Структура("Ширина, Высота", 1024, 768); // Значения по умолчанию
Попытка
HTML = Новый COMОбъект("HTMLFile");
Экран = HTML.parentWindow.screen;
Результат.Ширина = Экран.width;
Результат.Высота = Экран.height;
Исключение
// Если COM-объект недоступен, оставляем значения по умолчанию
КонецПопытки;
Возврат Результат;
КонецФункции
Теперь, имея данные о разрешении, мы можем рассчитать положение формы. Предположим, ширина нашей формы должна быть 400 пикселей, и она должна стоять вплотную к правой границе:
Процедура ПриОткрытии()
ПараметрыЭкрана = ПолучитьПараметрыЭкрана();
// Задаем ширину формы
ЭтаФорма.Ширина = 400;
// Вычисляем координату "Лево"
ЭтаФорма.Лево = ПараметрыЭкрана.Ширина - ЭтаФорма.Ширина;
// Устанавливаем положение по вертикали
ЭтаФорма.Верх = 0;
// Растягиваем на всю высоту (учитывая панель задач, значение может быть чуть меньше)
ЭтаФорма.Высота = ПараметрыЭкрана.Высота - 40;
КонецПроцедуры
Если метод с HTML по каким-то причинам не подходит, рассмотрим более мощный инструмент — WMI (Windows Management Instrumentation). Он позволяет получить точные данные о видеоконтроллере и текущем разрешении.
Функция ПолучитьРазрешениеЧерезWMI()
Локатор = Новый COMОбъект("WbemScripting.SWbemLocator");
Сервис = Локатор.ConnectServer(".");
Объекты = Сервис.ExecQuery("SELECT CurrentHorizontalResolution, CurrentVerticalResolution FROM Win32_VideoController");
Для Каждого Объект Из Объекты Цикл
Возврат Новый Структура("Ширина, Высота", Объект.CurrentHorizontalResolution, Объект.CurrentVerticalResolution);
КонецЦикла;
КонецФункции
Этот метод особенно полезен в многомониторных конфигурациях, так как позволяет более детально проанализировать оборудование пользователя.
Иногда требуется не просто передвинуть окно, а изменить его состояние (например, максимизировать) или сымитировать нажатие системных клавиш для управления окном. В 1С это можно реализовать через объект WScript.Shell.
Рассмотрим пример, когда нам нужно программно вызвать системную команду. Например, если стандартное свойство СпособОтображенияОкна не срабатывает так, как ожидается, можно прибегнуть к посылке нажатий клавиш (SendKeys):
Процедура РазвернутьОкноПрограммно()
Shell = Новый COMОбъект("WScript.Shell");
// Пример посылки комбинации клавиш Alt + Space, затем "Развернуть"
// Но лучше использовать штатные средства:
ЭтаФорма.СпособОтображенияОкна = ВариантСпособаОтображенияОкна.Максимизированное;
КонецПроцедуры
Стоит отметить, что использование SendKeys — это крайняя мера, так как она зависит от фокуса окна и текущей раскладки клавиатуры. Однако в некоторых специфических задачах автоматизации интерфейса это остается единственным выходом.
Выясним причину, по которой свойства ИмяСохраненияПоложенияОкна или КлючСохраненияПоложенияОкна могут не работать. Чаще всего это происходит по следующим причинам:
Если вам не требуется сложная логика вычислений координат, а нужно просто закрепить окно, проанализируем возможности Конфигуратора:
СостояниеОкна. Если установить его в Прикрепленное, вы сможете задать ПоложениеПрикрепленногоОкна (Верх, Низ, Лево, Право).Подводя итог, можно сказать, что программное управление окнами в обычном приложении 1С требует комбинации штатных свойств платформы и системных вызовов Windows. Используя связку из WMI/HTML для определения разрешения и аккуратное манипулирование свойствами Лево и Верх, можно добиться идеального расположения элементов интерфейса для удобства пользователя.