Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема Вопрос про перехватчик ("hooker") (число прочтений - 1974 )
ZOOBR
Junior Member
**
Отсутствует



Сообщений: 22
Зарегистрирован: 17. Апреля 2008
Вопрос про перехватчик ("hooker")
15. Марта 2009 :: 19:22
Печать  
Понимаю, что вопрос неоднократно поднимался, но так как сам разобраться не смог, попрошу объяснить еще раз. Мне собственно требуется перехватывать события закрытия и открытия со всех форм. Порывшись на форуме нашел следующее:
http://www.1cpp.ru/forum/YaBB.pl?num=1186478217/1#1
Собственно по приведенной там схеме все предопределенные компонентой процедуры у меня работают(например СобытиеГМ_ПриОткрытии, СобытиеГМ_ВводНового). А вот с закрытием получаеться проблема, а точнее просто эта процедура не обрабатывается. Делаю в точности как рекомендовано. А именно:
Добавляю в глобальник следующий текст:
Код
Выбрать все
лУправлениеНастройками = СоздатьОбъект("УправлениеНастройками");
лУправлениеНастройками.Включить("ПерехватитьСобытияГК");
лПерехватчикСобытийГМ = СоздатьОбъект("ПерехватчикСобытийГМ");  
лПерехватчик = СоздатьОбъект("Перехватчик");  
лПерехватчик.ПерехватитьСобытияГлобальногоМодуля(лПерехватчикСобытийГМ);
 


Создаю класс отлавливающий открытие всех форм и задающий класс для обработка действий формы:
Код
Выбрать все
Функция СобытиеГМ_ПриОткрытии(Конт, ФлагЧтенияНастройки) Экспорт
 лПерехватчикСобытийФормы = СоздатьОбъект("ПерехватчикСобытийФормы");    
 лПерехватчикСобытийФормы.Инит(Конт);
 Сообщить("Форма открыта");
 Возврат 1;
КонецФункции
 


Создаю собственно класс определяющий обработку действий открытой до этого формы;
Код
Выбрать все
Перем КонтФормы;

Процедура Инит(Конт) Экспорт
 КонтФормы = Конт;
 лПерехватчик = СоздатьОбъект("Перехватчик");  
 лПерехватчик.ПерехватитьСобытияГК(КонтФормы, Контекст);
КонецПроцедуры

Функция Событие_ПриЗакрытии() Экспорт
 Сообщить("Форма закрыта");
 Возврат 1; // можно закрывать
КонецФункции
 



Ну и получается, что сообщение при открытии работает, а при закрытии нет. Печаль
Использую 1С++ 3.0.1.22. Может кто-нибудь пояснит в чем может быть проблема?
  
Наверх
 
IP записан
 
ZOOBR
Junior Member
**
Отсутствует



Сообщений: 22
Зарегистрирован: 17. Апреля 2008
Re: Вопрос про перехватчик ("hooker")
Ответ #1 - 15. Марта 2009 :: 21:26
Печать  
Вопрос снят! Нашел решение. Все-таки пример оказался неверным(не в обиду конечно автору). Наверное нужно исправить, чтобы в последующем люди на эти грабли не натыкались. Оказалось, что все очень просто, достаточно забыть про пример и разобраться в том как это работает. А работает это следующим образом:

У компоненты есть предопределенные процедуры "СобытиеГМ_ПриОткрытии", "СобытиеГМ_ВводНового" и "СобытиеГМ_ВводНаОсновании". С ними ни у кого проблем не возникнет. Достаточно объявить их в вашем классе и вписать действие определяющее статус возврата (т.е. продолжить открытие - Возврат 1, иначе запретить открытие Возврат 0).
А вот например предопределенной процедуры "СобытиеГМ_ПриЗакрытии" не существует, поэтому нам при открытии нужно задать еще один класс, который будет выполнять обработку предопределенных процедур выбранного контекста. Вот именно здесь в примере и была ошибка:
Вот что было в примере:

Класс ИнициализаторФормы
Код
Выбрать все
Процедура Инит(Конт) Экспорт
 КонтФормы = Конт;
 лПерехватчик = СоздатьОбъект("Перехватчик");
 лПерехватчик.ПерехватитьСобытияГК(КонтФормы, Контекст);
КонецПроцедуры

Функция Событие_ПриЗакрытии() Экспорт
 Сообщить("Форма закрыта");
 Возврат 1; // можно закрывать
КонецФункции

 



Желтым я выделил, то что является неправильным. Чтобы исправить эту ошибку нужно создать еще один класс, который будет отвечать за обработку действий контекста и вынести функцию Событие_ПриЗакрытии() в него,  т.е получим такой простой класс:

Класс ОбработчикДействийФормы

Код
Выбрать все
Функция Событие_ПриЗакрытии() Экспорт
 Сообщить("Форма закрыта");
 Возврат 1; // можно закрывать
КонецФункции
 



Ну и естественно удалить этот текст из предыдущего класса. Также в предыдущий классе желтым выделено слово "Контекст", сюда нужно указать название класса, который мы сделали до этого, т.е. ОбработчикДействийФормы. Поличится следующее:
Класс ИнициалиаторФормы (исправленный)
Код
Выбрать все
Перем КонтФормы;
Процедура Инит(Конт) Экспорт
	КонтФормы = Конт;
	ПерехватчикФормы=СоздатьОбъект("ОбработчикДействийФормы");
		лПерехватчик = СоздатьОбъект("Перехватчик");
	лПерехватчик.ПерехватитьСобытияГК(КонтФормы, ПерехватчикФормы);
	лПерехватчик = 0;
КонецПроцедуры
 



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

test_013.rar ( 17 KB | Загрузки )
Наверх
 
IP записан
 
slider26
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 256
Зарегистрирован: 01. Июня 2006
Re: Вопрос про перехватчик ("hooker")
Ответ #2 - 16. Марта 2009 :: 03:08
Печать  
Вот как сделано у меня:
Гл.модуль
Код
Выбрать все
Перем глПерехватчикСобытий;

Процедура ПриНачалеРаботыСистемы()
    
	глПерехватчикСобытий=СоздатьОбъект("ПерехватчикГМ");
	глПерехватчикСобытий.ВключитьПерехватСобытий();

КонецПроцедуры //ПриНачалеРаботыСистемы 


Класс "ПерехватчикГМ"
Код
Выбрать все
Перем _Перехватчик Экспорт;
Перем МИК;

//_____________________________________________________________________________
Процедура ВключитьПерехватСобытий() Экспорт
	Перем лУправлениеНастройками;

	МИК = СоздатьОбъект("MetaInfoClasses");

	лУправлениеНастройками = СоздатьОбъект("УправлениеНастройками");
	Если (лУправлениеНастройками.Получить("ПерехватитьСобытияГК") = 0) Тогда
		лУправлениеНастройками.Включить("ПерехватитьСобытияГК");
	КонецЕсли;

	_Перехватчик = СоздатьОбъект("Перехватчик");    
	_Перехватчик.ПерехватитьСобытияГлобальногоМодуля(Контекст);
КонецПроцедуры // ВключитьПерехватСобытий

//_____________________________________________________________________________
Процедура ПерехватитьСобытияКонтекста(Конт)
	Перем ПерехватчикСобытий, рФорма, ТипОбъекта, ИмяКласса;

	Если ПустоеЗначение(Конт) = 0 Тогда
		ПерехватчикСобытий = _Перехватчик.ПолучитьПерехватчикСобытийГК(Конт);
		Если ПустоеЗначение(ПерехватчикСобытий) = 1 Тогда
			рФорма = СоздатьОбъект("РасширениеФормы");
			рФорма.УстановитьФорму(Конт.Форма);
			ТипОбъекта = рФорма.ТипОбъекта();
			рФорма = "";

			Если ((ТипОбъекта = "Справочник") или (ТипОбъекта = "Документ")) Тогда
				ИмяКласса = "ПерехватчикиСобытийФормы" + ТипОбъекта + "а" + Конт.Вид();
				Если (МИК.КлассСуществует(ИмяКласса) = 0) Тогда
					ИмяКласса = "ПерехватчикиСобытийФормы" + ТипОбъекта + "а";
				КонецЕсли;
			Иначе
				ИмяКласса = СтрЗаменить(ТипОбъекта,"Внешний","Внешнего");
				Если (Прав(ИмяКласса,1) = "а") Тогда
					ИмяКласса = "ПерехватчикиСобытийФормы" + Лев(ИмяКласса,СтрДлина(ИмяКласса)-1) + "и";
				Иначе
					ИмяКласса = "ПерехватчикиСобытийФормы" + ИмяКласса + "а";
				КонецЕсли;
				Если (МИК.КлассСуществует(ИмяКласса) = 0) Тогда
					ИмяКласса = "ПерехватчикиСобытийФормы";
				КонецЕсли;
			КонецЕсли;

			ПерехватчикСобытий = СоздатьОбъект(ИмяКласса);
			ПерехватчикСобытий.Инициализация(Конт);
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры

//_____________________________________________________________________________
Функция СобытиеГМ_ПриОткрытии(Конт, ФлагЧтенияНастройки) Экспорт
	ПерехватитьСобытияКонтекста(Конт);
	Возврат 1; // Можно открывать форму
КонецФункции

//_____________________________________________________________________________
Функция СобытиеГМ_ВводНового(Конт, ФлагКопирования) Экспорт
	ПерехватитьСобытияКонтекста(Конт);
	Возврат 1; // Можно открывать форму
КонецФункции

//_____________________________________________________________________________
Функция СобытиеГМ_ВводНаОсновании(Конт, ДокументОснование) Экспорт
	ПерехватитьСобытияКонтекста(Конт);
	Возврат 1; // Можно открывать форму
КонецФункции

//_____________________________________________________________________________
 


Класс "ПерехватчикиСобытийФормы":
Код
Выбрать все
Перем _Перехватчик Экспорт;
Перем _КонтФормы Экспорт;
Перем рФорма Экспорт;

//_____________________________________________________________________________
Процедура УстановитьЗначениеРеквизита(ИмяРеквизита,Значение) Экспорт

	Перем Реквизит, Модуль;
    
	Реквизит = рФорма.ПолучитьАтрибут(ИмяРеквизита);
	Реквизит.Значение = Значение;
	Модуль = СоздатьОбъект("ВыполняемыйМодуль");
	Модуль.УстановитьМодуль(Реквизит.Формула);
	Модуль.НазначитьКонтекст(_КонтФормы);
	Модуль.КомпилироватьИВыполнитьМодуль();

	Если (_КонтФормы.Модифицированность() = 0) Тогда
	    _КонтФормы.Форма.Обновить(1);
	КонецЕсли;

КонецПроцедуры //УстановитьЗначениеРеквизита

//_____________________________________________________________________________
Процедура Инициализация(пКонт) Экспорт
	_КонтФормы=пКонт;
	_Перехватчик=СоздатьОбъект("Перехватчик");
	_Перехватчик.ПерехватитьСобытияГК(_КонтФормы,Контекст);
	рФорма=СоздатьОбъект("РасширениеФормы");
	рФорма.УстановитьФорму(_КонтФормы.Форма);
КонецПроцедуры      // Инициализация

//_____________________________________________________________________________
//Функция Событие_ОбработкаПодбора(Элемент,Конт) Экспорт
//	Возврат т,Конт);
//КонецФункции

//_____________________________________________________________________________
//Функция Событие_ОбработкаВыбораЗначения(Значение,ИЭД,ФСО) Экспорт
//	Возврат ,Значение,ИЭД,ФСО);
//КонецФункции

//_____________________________________________________________________________ 


  
Наверх
 
IP записан
 
slider26
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 256
Зарегистрирован: 01. Июня 2006
Re: Вопрос про перехватчик ("hooker")
Ответ #3 - 16. Марта 2009 :: 03:11
Печать  
Все остальные классы сделаны по сл. шаблону:
ПерехватчикиСобытийФормыДокумента; ПерехватчикиСобытийФормыСправочника; ПерехватчикиСобытийФормыЖурнала; ПерехватчикиСобытийФормыОтчета; ПерехватчикиСобытийФормыОбработки; ПерехватчикиСобытийФормыВнешнегоОтчета;
Код
Выбрать все
Перем _Перехватчик Экспорт;
Перем _КонтФормы Экспорт;
Перем рФорма Экспорт;
Перем ПерехватчикСобытийФормы Экспорт;

//_____________________________________________________________________________
Функция GetThis(Конт) Возврат Конт; КонецФункции

//_____________________________________________________________________________
Процедура Инициализация(пКонт) Экспорт
	ПерехватчикСобытийФормы = GetThis(Контекст).ПолучитьБазовыйКласс();

	ПерехватчикСобытийФормы.Инициализация(пКонт);

    _КонтФормы = ПерехватчикСобытийФормы._КонтФормы;
    _Перехватчик = ПерехватчикСобытийФормы._Перехватчик;
    рФорма = ПерехватчикСобытийФормы.рФорма;
КонецПроцедуры	// Инициализация

_
//Функция Событие_ПриОткрытии() Экспорт
//	Возврат _Перехватчик.ВыполнитьОригинальноеСобытиеГК(_КонтФормы,"ПриОткрытии");
//КонецФункции
//
//_____________________________________________________________________________
 


  
Наверх
 
IP записан
 
slider26
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 256
Зарегистрирован: 01. Июня 2006
Re: Вопрос про перехватчик ("hooker")
Ответ #4 - 16. Марта 2009 :: 03:14
Печать  
Соответственно объявляем:
Код
Выбрать все
//#класс ПерехватчикГМ = ПерехватчикГМ@MD
//#{
//#};
//#класс ПерехватчикиСобытийФормы = ПерехватчикиСобытийФормы@MD
//#{
//#};
//#класс ПерехватчикиСобытийФормыДокумента = ПерехватчикиСобытийФормыДокумента@MD : ПерехватчикиСобытийФормы
//#{
//#};
//#класс ПерехватчикиСобытийФормыСправочника = ПерехватчикиСобытийФормыСправочника@MD : ПерехватчикиСобытийФормы
//#{
//#};
//#класс ПерехватчикиСобытийФормыЖурнала = ПерехватчикиСобытийФормыЖурнала@MD : ПерехватчикиСобытийФормы
//#{
//#};
//#класс ПерехватчикиСобытийФормыОтчета = ПерехватчикиСобытийФормыОтчета@MD : ПерехватчикиСобытийФормы
//#{
//#};
//#класс ПерехватчикиСобытийФормыОбработки = ПерехватчикиСобытийФормыОбработки@MD : ПерехватчикиСобытийФормы
//#{
//#};
//#класс ПерехватчикиСобытийФормыВнешнегоОтчета = ПерехватчикиСобытийФормыВнешнегоОтчета@MD : ПерехватчикиСобытийФормы
//#{
//#};
 


И вот эта система позволяет добавлять любые события перехвата как отдельно на различные объекты (Справочники, документы, отчеты) так и вместе.
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать