При разработке интерфейсов на обычных формах (ОФ) программисты часто сталкиваются с необходимостью динамического создания элементов управления. Если создание ДереваЗначений или ТабличногоПоля программно не вызывает больших затруднений, то настройка стандартного поведения кнопок командной панели может стать настоящей головоломкой. В управляемых формах мы привыкли просто выбирать стандартную команду из списка, но в обычных формах механизм работы с действиями устроен иначе.
В этой статье мы разберем, почему нельзя просто создать объект Действие со стандартным именем и как использовать хитрость с временным автозаполнением, чтобы «подсмотреть» внутренние обработчики платформы 1С и назначить их своим кнопкам.
Рассмотрим стандартную ситуацию: вы создали программно КоманднаяПанель и хотите добавить на нее кнопку «Скопировать». Казалось бы, достаточно написать следующий код:
НоваяКнопка = ЭлементыФормы.МояКоманднаяПанель.Кнопки.Добавить("КнопкаСкопировать", Тип("КнопкаКоманднойПанели"), "Скопировать", Новый Действие("Скопировать"));
Однако этот код работать не будет. Конструктор Новый Действие("ИмяПроцедуры") в обычных формах ищет экспортную процедуру именно в модуле формы. У платформы нет строковых идентификаторов для «внутренних» команд типа «Скопировать», «Добавить» или «Удалить», которые можно было бы передать в этот конструктор напрямую. Если вы не опишете процедуру Скопировать() вручную, 1С выдаст ошибку о том, что обработчик не найден. Но писать логику копирования строк дерева значений вручную (с учетом иерархии, уровней и типов данных) — задача трудоемкая и избыточная, так как платформа уже умеет это делать.
Для того чтобы командная панель «понимала», какими данными она управляет, используется свойство ИсточникДействий. Рассмотрим этот механизм подробнее. Чтобы кнопки заработали, мы должны связать панель с элементом формы, который отображает данные (например, ТабличноеПоле или ДеревоЗначений).
Проанализируем последовательность действий, которая позволяет нам достичь цели:
ИсточникДействий ссылку на наше дерево значений.АвтоЗаполнение для автоматической генерации кнопок платформой.Выясним, как реализовать этот алгоритм в коде модуля формы. Основная идея заключается в том, чтобы заставить платформу саму создать нужные действия, сохранить их в массив, а затем отключить автозаполнение, сохранив при этом доступ к «внутренним» обработчикам.
Рассмотрим пример кода:
// 1. Добавляем командную панель программно
КоманднаяПанель = ЭлементыФормы.Добавить(Тип("КоманднаяПанель"), "КП_ДеревоЗначений", Истина, ЭлементыФормы.ОсновнаяПанель);
// 2. Связываем панель с деревом значений (элементом формы)
// ТП_Дерево - это имя элемента формы типа ТабличноеПоле, отображающего дерево
КоманднаяПанель.ИсточникДействий = ЭлементыФормы.ТП_Дерево;
// 3. Настраиваем внешний вид
КоманднаяПанель.Верх = 0;
КоманднаяПанель.Высота = 22;
КоманднаяПанель.Доступность = Истина;
// 4. ВКЛЮЧАЕМ автозаполнение.
// В этот момент платформа сама создает кнопки "Добавить", "Скопировать" и т.д.
КоманднаяПанель.АвтоЗаполнение = Истина;
// 5. Теперь самое важное: копируем кнопки, созданные платформой, в массив.
// Эти кнопки уже содержат магические ссылки на внутренние действия платформы.
МассивКнопок = Новый Массив;
Для Каждого Кнопка Из КоманднаяПанель.Кнопки Цикл
МассивКнопок.Добавить(Кнопка);
КонецЦикла;
// 6. ВЫКЛЮЧАЕМ автозаполнение.
// Теперь мы можем программно управлять составом кнопок, не теряя доступа к стандартным действиям.
КоманднаяПанель.АвтоЗаполнение = Ложь;
Проанализируем ситуацию: когда платформа заполняет панель автоматически, она дает кнопкам системные имена вида Действие1, Действие2 и так далее. Эти имена могут меняться в зависимости от версии платформы или настроек элемента формы. Поэтому искать кнопку «Скопировать» лучше по ее подсказке или тексту.
Посмотрим на пример поиска конкретной кнопки:
Для Каждого Кн Из МассивКнопок Цикл
// Ищем кнопку "Скопировать" по стандартной подсказке
Если Найти(Кн.Подсказка, "Скопировать") > 0 Тогда
// Мы нашли нужную кнопку. Можем изменить её имя, положение или картинку.
Кн.Имя = "КнопкаСтандартноеСкопирование";
// Теперь эта кнопка будет работать штатно, выполняя стандартное копирование 1С
ИначеЕсли Найти(Кн.Подсказка, "Добавить") > 0 Тогда
Кн.Имя = "КнопкаСтандартноеДобавление";
КонецЕсли;
КонецЦикла;
Разберем основные преимущества такого подхода перед попытками ручного написания кода:
F9. Вам не нужно прописывать перехват нажатия клавиш в событиях формы.ДереваЗначений стандартное копирование учитывает текущий уровень иерархии. Написать универсальный код, который корректно копирует строку со всеми подчиненными узлами (если это требуется) или только текущую строку, довольно сложно. Платформа делает это оптимально.АвтоКонтекстноеМеню = Истина, те же самые действия автоматически появятся и при нажатии правой кнопкой мыши на дереве.При работе с этим методом стоит помнить о нескольких важных моментах. Выясним, что может пойти не так.
Во-первых, доступность стандартных кнопок напрямую зависит от свойств самого ДереваЗначений (как элемента формы). Если у элемента формы установлено свойство ТолькоПросмотр = Истина или снята галочка РазрешитьДобавление, то при включении АвтоЗаполнение = Истина кнопка «Скопировать» просто не будет создана платформой. Проверяйте настройки прав и правки данных в свойствах элемента управления.
Во-вторых, если вы хотите добавить свои собственные кнопки вперемешку со стандартными, делайте это после того, как отключите АвтоЗаполнение. Это позволит вам точно контролировать порядок следования элементов на панели через коллекцию КоманднаяПанель.Кнопки.
Подведем итог: использование временного включения свойства АвтоЗаполнение — это надежный и эффективный способ «эксплуатации» стандартных механизмов 1С в динамических интерфейсах. Мы не дублируем код платформы, а просто перехватываем ссылку на нужный обработчик, обеспечивая пользователю привычный функционал с минимальными затратами ресурсов разработчика.