Книга знаний

1С:Предприятие / v8 / Приемы программирования / Формы

v8: Тест

ТестАвтор статьи: TormozIT | Редакторы: Гений 1С,
Последняя редакция №2 от 04.07.06 | История
URL: http://kb.mista.ru/article.php?id=268

Выражаю большу признательность одному из умнейших, Гению 1С, за использование его материалов.

 Например, есть конфигурация, которая является доработанной типовой. Вы ее постоянно обновляете и добавляете все больше своих изменений. Обновлять в общем случае с каждым разом становится все труднее и дольше. Значительную часть ваший доработок составляют вставки в начало и конец обработчиков событий формы и элементов формы. А также новые обработчики, которые некоторые еще и назначают в режиме редактирования конфигурации (статически), что дополнительно затрудняет процесс обновления.
 
 Предлагаемый метод состоит в том, чтобы объявить в модуле формы свои обработчики событий, которые будут вызывать старые обработчики и выполнять нужный код до и после этого вызова. Установка новых обработчиков будет производиться в разделе операторов основной программы формы путем вызова общей процедуры, скажем "УстановитьДействиеФормы". Эта процедура в динамически добавленном невидимом элементе формы будет сохранять все старые обработчики для каждого переопределенного события, что позволит довольно просто вызывать их через общую функцию, скажем "ПолучитьДействиеФормы". Следуя рекомендациям 1С, а также для удобства возьмем за правило:<b>имена новых обработчиков следует формировать как <Префикс>[<ИмяЭлементаФормы>]<ИмяСобытия></b>.


Случай 1. Добавляем вставку в начало и конец имеющегося в типовой обработчика события формы и элемента формы.



Обычно делают примерно так.

// Процедура - обработчик события "ПередОткрытием" формы.
//
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)

   // {{Добавил TormozIT 23.03.2006
   <Текст вставки в начало обработчика>
   //  }}Добавил TormozIT 23.03.2006

   //Видимость автоматических скидок.
   ИспользованиеСкидок = РегистрыСведений.УчетнаяПолитика.ПолучитьПоследнее(ДокументОбъект.Дата);
   Если ИспользованиеСкидок.ИспользоватьСкидкиПоКоличествуТовара
    Или ИспользованиеСкидок.ИспользоватьСкидкиПоСуммеДокумента
    Или ИспользованиеСкидок.ИспользоватьСкидкиПоВидуОплаты
    Или ИспользованиеСкидок.ИспользоватьСкидкиПоДисконтнойКарте Тогда
       мРассчитыватьАвтоматическиеСкидки = Истина;
   Иначе
       мРассчитыватьАвтоматическиеСкидки = Ложь;
   КонецЕсли;

   // {{Добавил TormozIT 23.03.2006
   <Текст вставки в конец обработчика>
   //  }}Добавил TormozIT 23.03.2006

КонецПроцедуры // ПередОткрытием()

// Процедура - обработчик события "НачалоВыбора" поля ввода Склад
//
Процедура СкладНачалоВыбора(Элемент, СтандартнаяОбработка)

   // {{Добавил TormozIT 23.03.2006
   <Текст вставки в начало обработчика>
   //  }}Добавил TormozIT 23.03.2006
   НачалоВыбораСкладаНТТ(ЭтотОбъект, ЭтаФорма, Элемент, Склад, ВидСравнения.НеРавно, СтандартнаяОбработка);
   // {{Добавил TormozIT 23.03.2006
   <Текст вставки в конец обработчика>
   //  }}Добавил TormozIT 23.03.2006

КонецПроцедуры // СкладНачалоВыбора()

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

Теперь следует делать так.

// {{Добавил TormozIT 23.03.2006

// Процедура - обработчик события "ПередОткрытием" формы
//
Процедура ЛксПередОткрытием(Отказ, СтандартнаяОбработка)
   
   <Текст вставки в начало обработчика>
   Выполнить(ПолучитьДействиеФормы(ЭтаФорма, "ПередОткрытием"));
   <Текст вставки в конец обработчика>
   
КонецПроцедуры // ЛксПередОткрытием()

// Процедура - обработчик события "НачалоВыбора" элемента формы "Склад"
//
Процедура ЛксСкладНачалоВыбора(Элемент, СтандартнаяОбработка)
   
   <Текст вставки в начало обработчика>
   Выполнить(ПолучитьДействиеФормы(ЭтаФорма, "НачалоВыбора", "Склад"));
   <Текст вставки в конец обработчика>
   
КонецПроцедуры // ЛксСкладНачалоВыбора()

//  }}Добавил TormozIT 23.03.2006

////////////////////////////////////////////////////////////////////////////////
// ОПЕРАТОРЫ ОСНОВНОЙ ПРОГРАММЫ

// {{Добавил TormozIT 23.03.2006
УстановитьДействиеФормы(ЭтаФорма, "ПередОткрытием");
УстановитьДействиеФормы(ЭтаФорма, "НачалоВыбора"  , "Склад");
//  }}Добавил TormozIT 23.03.2006

Таким образом при обновлении нам нужно будет всего лишь добавить один блок (по одной строке для каждого переопределенного события) в начало раздела операторов основной программы.


Случай 2. Добавляем новый обработчик события формы и элемента формы (включая новые элементы формы!).



Обычно делают примерно так.

// {{Добавил TormozIT 23.03.2006

// Процедура - обработчик события "ПриИзменении" элемента формы "Склад"
//
Процедура СкладПриИзменении(Элемент, СтандартнаяОбработка)
   
   <Текст начала обработчика>
   <Текст конца обработчика>
   
КонецПроцедуры // СкладПриИзменении()

//  }}Добавил TormozIT 23.03.2006

Все работает и выглядит хорошо.
Но подумайте, что будет, если в новом релизе будет добавлен в режиме редактирования конфигурации (статически) связанный обработчик для того же события и, возможно, что еще хуже, с таким же именем!
Будет неприятно.

Как следует поступать в этом случае?
Опять по той же схеме.

// {{Добавил TormozIT 23.03.2006

// Процедура - обработчик события "ПриИзменении" элемента формы "Склад"
//
Процедура ЛксСкладПриИзменении(Элемент, СтандартнаяОбработка)
   
   <Текст начала обработчика>
   Выполнить(ПолучитьДействиеФормы(ЭтаФорма, "ПриИзменении", "Склад"));
   <Текст конца обработчика>
   
КонецПроцедуры // ЛксСкладПриИзменении()

//  }}Добавил TormozIT 23.03.2006
...
////////////////////////////////////////////////////////////////////////////////
// ОПЕРАТОРЫ ОСНОВНОЙ ПРОГРАММЫ

// {{Добавил TormozIT 23.03.2006
УстановитьДействиеФормы(ЭтаФорма, "ПриИзменении"  , "Склад");
//  }}Добавил TormozIT 23.03.2006

Теперь уже нам не страшны добавленные в типовую обработчики событий и их имена!

Необходимые процедуры и функции общего модуля



Сначала процедура переопределения события.
Для хранения старых обработчиков событий мы используем хитрость предложенную Гением 1С.
Суть ее состоит в динамическом добавлении нулевых размеров служебного элемента формы для хранения в нем списка значений в свойстве СписокВыбора. Т.е. сначала проверяем есть ли элемент формы с заданным именем (в примере "общСтарыеОбработчики"). Если его нет, то создаем. Затем получаем обработчик нужного действия формы или элемента формы. Сохраняем его в СпискеВыбора служебного элемента формы. Устанавливаем новый обработчик, имя которого формируем по правилу "Лкс" + <пИмяЭлементаФормы> + <пИмяСобытия>.

// Переопределяет обработчик события формы или элемента формы.
// Сохраняет штатный обработчик события внутри формы и устанавливает новый.
//
// Параметры:
//  пФорма       – Форма – форма;
//  пИмяСобытия  – Строка – имя события;
//  *пИмяЭлементаФормы – Строка – имя элемента формы.
//
Процедура УстановитьДействиеФормы(пФорма, пИмяСобытия, пИмяЭлементаФормы = "") Экспорт

   // Явное "определение" типа переменных.
   Если Ложь Тогда
       пФорма = ПолучитьОбщуюФорму(0);
       пЭлементФормы = пФорма.ЭлементыФормы[0];
   КонецЕсли;
   
   Если пИмяЭлементаФормы <> "" Тогда
       Объект = пФорма.ЭлементыФормы[пИмяЭлементаФормы];
   Иначе
       Объект = пФорма;
   КонецЕсли;
   
   ТекстМаркера = "общСтарыеОбработчики";
   Если пФорма.ЭлементыФормы.Найти(ТекстМаркера) = Неопределено Тогда
       ЭФ = пФорма.ЭлементыФормы.Добавить(Тип("ПолеВвода"), ТекстМаркера, Ложь);
   КонецЕсли;
   
   ПолноеИмяСобытия = пИмяЭлементаФормы + пИмяСобытия;
   СтароеДействие = Объект.ПолучитьДействие(пИмяСобытия);
   НовоеДействие = Новый Действие("Лкс" + ПолноеИмяСобытия);
   Объект.УстановитьДействие(пИмяСобытия, НовоеДействие);
   пФорма.ЭлементыФормы.общСтарыеОбработчики.СписокВыбора.Добавить(ПолноеИмяСобытия, СтароеДействие);

КонецПроцедуры // УстановитьДействиеФормы()


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

// Получаем текст для выполнения вызова штатного обработчика события формы или элемента формы.
//
// Параметры:
//  пФорма       – Форма – форма;
//  пИмяСобытия  – Строка – имя события;
//  *пИмяЭлементаФормы – Строка – имя элемента формы.
//
// Возвращаемое значение:
//               – Строка – текст для выполнения.
//
Функция ПолучитьДействиеФормы(пФорма, пИмяСобытия, пИмяЭлементаФормы = "") Экспорт

   // Явное "определение" типа переменных.
   Если Ложь Тогда
       пФорма = ПолучитьОбщуюФорму(0);
   КонецЕсли;
   
   ПолноеИмяСобытия = пИмяЭлементаФормы + пИмяСобытия;
   СтарыйОбработчик = "";
   ЭлементСписка = пФорма.ЭлементыФормы.общСтарыеОбработчики.СписокВыбора.НайтиПоЗначению(ПолноеИмяСобытия);
   Если ЭлементСписка <> Неопределено Тогда
       СтарыйОбработчик = ЭлементСписка.Представление;
   КонецЕсли;
   Если СтарыйОбработчик <> "" Тогда
       Аргументы = "";
       Если пИмяЭлементаФормы <> "" Тогда
           // Это событие элемента формы
           Если      пИмяСобытия = "ПроверкаПеретаскивания" Тогда
               Аргументы = "(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Колонка)";
           ИначеЕсли пИмяСобытия = "НачалоПеретаскивания" Тогда
               Аргументы = "(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "ОкончаниеПеретаскивания" Тогда
               Аргументы = "(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "Перетаскивание" Тогда
               Аргументы = "(Элемент, Параметры перетаскивания, СтандартнаяОбработка, Область)";
           ИначеЕсли пИмяСобытия = "АвтоПодборТекста" Тогда
               Аргументы = "(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "Выбор" Тогда
               Аргументы = "(Элемент, Область, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "НачалоВыбора" Тогда
               Аргументы = "(Элемент, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "ОбработкаВыбора" Тогда
               Аргументы = "(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "ОбработкаЗаписиНовогоОбъекта" Тогда
               Аргументы = "(Элемент, Объект, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "ОбработкаРасшифровки" Тогда
               Аргументы = "(Элемент, Расшифровка, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "ОкончаниеВводаТекста" Тогда
               Аргументы = "(Элемент, Текст, Значение, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "Открытие" Тогда
               Аргументы = "(Элемент, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "Очистка" Тогда
               Аргументы = "(Элемент, СтандартнаяОбработка)";
           ИначеЕсли пИмяСобытия = "ПередНачаломДобавления" Тогда
               Аргументы = "(Элемент, Отказ, Копирование)";
           ИначеЕсли пИмяСобытия = "ПередНачаломИзменения" Тогда
               Аргументы = "(Элемент, Отказ)";
           ИначеЕсли пИмяСобытия = "ПередОкончаниемРедактирования" Тогда
               Аргументы = "(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)";
           ИначеЕсли пИмяСобытия = "ПередУдалением" Тогда
               Аргументы = "(Элемент, Отказ)";
           ИначеЕсли пИмяСобытия = "ПриВыводеСтроки" Тогда
               Аргументы = "(Элемент, ОформлениеСтроки, ДанныеСтроки)";
           ИначеЕсли пИмяСобытия = "ПриИзмененииСодержимогоОбласти" Тогда
               Аргументы = "(Элемент, Область)";
           ИначеЕсли пИмяСобытия = "ПриНачалеРедактирования" Тогда
               Аргументы = "(Элемент, НоваяСтрока, Копирование)";
           ИначеЕсли пИмяСобытия = "ПриОкончанииРедактирования" Тогда
               Аргументы = "(Элемент, НоваяСтрока, Отмена редактирования)";
           ИначеЕсли пИмяСобытия = "ПриОкончанииРедактированияИнтервала" Тогда
               Аргументы = "(Элемент, Интервал, Отмена)";
           ИначеЕсли пИмяСобытия = "ПриПолученииДанных" Тогда
               Аргументы = "(Элемент, ОформленияСтрок)";
           ИначеЕсли пИмяСобытия = "ПриСменеСтраницы" Тогда
               Аргументы = "(Элемент, ТекущаяСтраница)";
           ИначеЕсли пИмяСобытия = "ПроверкаПеретаскивания" Тогда
               Аргументы = "(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Область)";
           ИначеЕсли пИмяСобытия = "Регулирование" Тогда
               Аргументы = "(Элемент, Направление, СтандартнаяОбработка)";
           Иначе
               Аргументы = "(Элемент)";
           КонецЕсли;
       Иначе
           // Это событие формы
           Попытка
               Если    Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(пФорма.Объект)) Тогда
                   // Это форма элемента справочника
                   Если      пИмяСобытия = "ПередЗаписью" Тогда
                       Аргументы = "(Отказ)";
                   КонецЕсли;
               ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(пФорма.Объект)) Тогда
                   // Это форма элемента документа
                   Если      пИмяСобытия = "ПередЗаписью" Тогда
                       Аргументы = "(Отказ, РежимЗаписи, РежимПроведения)";
                   КонецЕсли;
               КонецЕсли;
           Исключение
           КонецПопытки;
           Если Аргументы = "" Тогда
               Если      пИмяСобытия = "ПриЗаписи" Тогда
                   Аргументы = "(Отказ)";
               ИначеЕсли пИмяСобытия = "ПередОткрытием" Тогда
                   Аргументы = "(Отказ, СтандартнаяОбработка)";
               ИначеЕсли пИмяСобытия = "ПередЗакрытием" Тогда
                   Аргументы = "(Отказ, СтандартнаяОбработка)";
               ИначеЕсли пИмяСобытия = "ОбработкаВыбора" Тогда
                   Аргументы = "(ЗначениеВыбора, Источник)";
               ИначеЕсли пИмяСобытия = "ОбработкаАктивизацииОбъекта" Тогда
                   Аргументы = "(АктивныйОбъект, Источник)";
               ИначеЕсли пИмяСобытия = "ОбработкаЗаписиНовогоОбъекта" Тогда
                   Аргументы = "(Объект, Источник)";
               ИначеЕсли пИмяСобытия = "ОбработкаОповещения" Тогда
                   Аргументы = "(ИмяСобытия, Параметр, Источник)";
               ИначеЕсли пИмяСобытия = "ПриПовторномОткрытии" Тогда
                   Аргументы = "(СтандартнаяОбработка)";
               ИначеЕсли пИмяСобытия = " ВнешнееСобытие" Тогда
                   Аргументы = "(Источник, Событие, Данные)";
               Иначе
                   Аргументы = "()";
               КонецЕсли;
           КонецЕсли;
       КонецЕсли;
       СтарыйОбработчик = СтарыйОбработчик + Аргументы;
   КонецЕсли;
   Возврат СтарыйОбработчик;

КонецФункции // ПолучитьДействиеФормы()

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика