В современных версиях платформы 1С:Предприятие 8.3, использующих интерфейс «Такси», появилась замечательная возможность — одновременное отображение нескольких окон. Пользователь может вручную закрепить форму справа, слева, сверху или снизу, чтобы видеть несколько отчетов или справочников одновременно. Однако разработчики часто сталкиваются с задачей: как сделать это программно? Например, чтобы при открытии базы у менеджера всегда был закреплен отчет по продажам, и он не мог его случайно открепить или закрыть.
На сегодняшний день в стандартном объектном языке 1С нет прямого метода вроде ЭтаФорма.Закрепить(). Тем не менее, решение существует. Мы проанализируем ситуацию и разберем несколько способов реализации этой «хотелки» — от простых скриптов до использования WinAPI.
Разберем самый популярный метод, основанный на эмуляции нажатий клавиш. Идея заключается в том, что после открытия формы мы программно имитируем действия пользователя по вызову системного меню окна и выбору пункта «Закрепить».
Важный нюанс: Непосредственно в процедуре ПриОткрытии или ПриСозданииНаСервере вызывать скрипт бесполезно, так как окно еще не отображено и не получило фокус. Нам потребуется использовать ПодключитьОбработчикОжидания.
Рассмотрим пример кода для формы, которую нужно закрепить справа:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Устанавливаем параметры, чтобы окно не закрывалось случайно
ЗакрыватьПриВыборе = Ложь;
ЗакрыватьПриЗакрытииВладельца = Истина;
// Вызываем обработчик с небольшой задержкой (0.1 - 0.5 сек)
ПодключитьОбработчикОжидания("ЗакрепитьОкноСправа", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ЗакрепитьОкноСправа()
Если ЭтаФорма.ВводДоступен() Тогда
Попытка
WSHShell = Новый COMОбъект("WScript.Shell");
// Имитируем нажатие Alt + "минус" для вызова системного меню окна
WSHShell.SendKeys("%(-)");
// Перемещаемся по меню вниз к пункту "Закрепить"
WSHShell.SendKeys("{DOWN 2}");
// Переходим в подменю выбора стороны закрепления
WSHShell.SendKeys("{RIGHT}");
// Выбираем "Справа" (в списке это обычно 4-й пункт, поэтому 3 нажатия вниз)
WSHShell.SendKeys("{DOWN 3}");
// Подтверждаем выбор
WSHShell.SendKeys("{ENTER}");
Исключение
// Обработка ошибки, если COM-объект недоступен
КонецПопытки;
ОтключитьОбработчикОжидания("ЗакрепитьОкноСправа");
КонецЕсли;
КонецПроцедуры
Обратите внимание на строку WSHShell.SendKeys("%(-)"). В разных релизах платформы (например, в 8.3.15 против 8.3.17+) комбинации клавиш могут меняться. Если приведенный выше код не срабатывает, попробуйте заменить последовательность нажатий на ту, которая актуальна для вашего интерфейса при ручном управлении.
Проанализируем ситуацию с обновлением платформы. Выясним причину, почему в новых релизах (начиная с 8.3.15) старые скрипты могут давать сбой. Платформа изменила структуру системных меню. Рассмотрим уточненный алгоритм для последних релизов:
Alt + Shift + W для вызова списка окон, если стандартное меню не поддается.%(-) (Alt + минус), затем навигация.ПодключитьОбработчикОжидания до 0.5.Посмотрим на пример для закрепления сверху:
&НаКлиенте
Процедура ЗакрепитьСверху()
Если ЭтаФорма.ВводДоступен() Тогда
WSHShell = Новый COMОбъект("WScript.Shell");
WSHShell.SendKeys("%"); // Нажатие Alt
WSHShell.SendKeys("{RIGHT 12}"); // Переход к меню "Окно"
WSHShell.SendKeys("{DOWN 5}"); // Пункт закрепления
WSHShell.SendKeys("{ENTER}");
ОтключитьОбработчикОжидания("ЗакрепитьСверху");
КонецЕсли;
КонецПроцедуры
Для тех, кому недостаточно стандартных скриптов, разберем возможность использования внешних компонент. Этот метод позволяет более точно управлять окнами Windows, находя дескриптор окна 1С (HWND) и посылая ему конкретные сообщения или эмулируя клики мыши по точным координатам.
Рассмотрим логику работы такой компоненты (на примере Native C++ или использования DynamicWrapperX):
GetActiveWindowPosition.ClickRightButtonMouse.SendKeys.Этот способ крайне надежен, так как не зависит от того, какая раскладка клавиатуры включена у пользователя в данный момент, однако он требует регистрации библиотек в системе (например, regsvr32 dynwrapx.dll), что может быть затруднительно в терминальных средах без прав администратора.
Выясним еще один «чистый» программный способ, который не использует эмуляцию клавиатуры. Настройки расположения окон сохраняются платформой в системном хранилище. Мы можем попробовать скопировать эти настройки от одного «эталонного» пользователя другим.
Данные хранятся по ключу "Общее/ОкнаКлиентскогоПриложения". Если один раз настроить интерфейс вручную и сохранить эти данные в общую базу или файл, их можно подгружать при начале работы системы:
// Пример логики (упрощенно)
Настройки = ХранилищеСистемныхНастроек.Загрузить("Общее/ОкнаКлиентскогоПриложения");
// Если настройки найдены, записываем их текущему пользователю
ХранилищеСистемныхНастроек.Сохранить("Общее/ОкнаКлиентскогоПриложения", , Настройки, , ИмяПользователя);
Важное ограничение: Этот метод работает для всего интерфейса в целом, а не для конкретного открытия формы «здесь и сейчас». Он идеально подходит для первоначальной настройки рабочего места пользователя администратором.
Проанализировав все доступные методы, можно сделать следующие выводы:
WScript.Shell и SendKeys. Это «костыль», но он работает в 90% случаев на тонком клиенте под Windows.ЭтаФорма.ВводДоступен(), чтобы команды не ушли в другое открытое приложение (например, в браузер).WScript.Shell, ни WinAPI не будут работать в браузере. Для веб-клиента программное закрепление окон на текущий момент невозможно.Мы рассмотрели различные подходы к автоматизации интерфейса «Такси». Выбор конкретного метода зависит от ваших технических возможностей и требований к стабильности системы. Надеемся, эти примеры помогут вам сделать работу ваших пользователей более продуктивной!