.. Автор: Артур Аюханов aka artbear, mailto: artbear@inbox.ru

.. include:: commonchm.txt


#####################################################################
Перехватчик
#####################################################################
..	<chminfo>
		<insert nodes="//common/maininfo/*"/>
		<alinks>_1cpp_hooker_</alinks>
		<klinks>
			Перехватчик
			Hooker
		</klinks>
	</chminfo>

.. contents:: Содержание
	:backlinks: none

**Класс "Перехватчик" / "Hooker".**

Специальный класс, предназначенный для перехвата предопределенных событий
1С и ВК FormEx, вызываемых для групповых контекстов и/или глобального модуля,
с помощью специальных объектов пользовательских классов 1С++.

**Версия: релиз 2.5 и выше.**

**Общая схема перехвата:**

0. Для использования перехвата должна быть включена настройка 1С++
" **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
См. `SettingsManager <SettingsManager.chm::/SettingsManager0.html>`_

1. Необходимо использовать пользовательский класс 1С++, в котором должны
быть определены **обработчики соответствующих событий с названием события**
(ПриЗакрытии, ПриНачалеВыбораЗначения, ПриНажатииКнопкиКлавиатуры) или
**со специальным названием в виде Событие_НаименованиеСобытия**
(Событие_ПриЗакрытии, Событие_ПриНачалеВыбораЗначения, СобытиеГМ_ПриНажатииКнопкиКлавиатуры)

1.1 Для событий глобального модуля **всегда используется префикс СобытиеГМ_ **
(СобытиеГМ_ПриЗавершенииРаботыСистемы, СобытиеГМ_ПриНажатииКнопкиКлавиатуры)

2. Каждый обработчик должен быть определен **с атрибутом Экспорт**, иначе
перехват указанного события будет невозможен.

Например, для перехвата событий ПриЗакрытии и ПриНачалеВыбораЗначения в
классе-перехватчике необходимо написать

	Процедура ПриЗакрытии() Экспорт
	 	// текст обработчика события

	КонецПроцедуры

	Процедура Событие_ПриНачалеВыбораЗначения(НужныеПараметры и т.д.) Экспорт
	 	// текст обработчика события

	КонецПроцедуры

Или для перехвата события ПриЗавершенииРаботыСистемы в
классе-перехватчике необходимо написать

	Процедура СобытиеГМ_ПриЗавершенииРаботыСистемы() Экспорт
		// текст обработчика события

	КонецПроцедуры

3. Для включения перехвата конкретного контекста формы нужно использовать
код

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

	или

	+ Перехватчик. ПерехватитьСобытияГлобальногоМодуля_ (ОбъектПерехватчикГМ);

	или

	+ ПредОбработчик = Перехватчик. ПерехватитьСобытияГК_ (ОбъектПерехватчикГК);
    + ПредОбработчик = Перехватчик. ПерехватитьСобытияГлобальногоМодуля_ (ОбъектПерехватчикГМ);

4. В перехваченном контексте или перехваченном глобальном модуле
**обработчики событий могут вообще отсутствовать или быть определены без
атрибута Экспорт**.

5. После установки перехвата при вызове системой события
управление   будет   передано   в   соответствующий   обработчик   события    в
классе-перехватчике.
В этом случае встроенные обработчики предопределенных событий в
перехваченном контексте или глобальном модуле автоматически вызываться не
будут.
Разработчик сам должен вызвать данные обработчики (см. п.7), когда это
необходимо.

6. Для включения перехвата событий глобального модуля необходимо
использовать код

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

7. При необходимости вызова обработчиков событий, которые определены в контексте
или в глобальном модуле, в обработчике события внутри пользовательского класса
нужно использовать код

	Процедура Событие_ПриЗакрытии() Экспорт

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

	КонецПроцедуры

или

	Процедура СобытиеГМ_ПриЗавершенииРаботыСистемы() Экспорт

	+	Перехватчик = СоздатьОбъект("Перехватчик");
	+	Перехватчик. ВыполнитьОригинальноеСобытиеГлобальногоМодуля_ ("ПриЗавершенииРаботыСистемы");
	+	или для вызова предыдущего сохраненного обработчика
    +   Перехватчик. ВыполнитьСобытиеГлобальногоМодуля_ ("ПриЗавершенииРаботыСистемы", ПредыдущийОбработчик);

	КонецПроцедуры

При этом неважно, существует ли обработчик в модуле формы или глобальном модуле.

**Таким образом, для обработки цепочки из нескольких перехватчиков существуют методы**
ВыполнитьСобытиеГК_
ВыполнитьСобытиеГлобальногоМодуля_

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

Например, код

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

не вызывет деструктор немедленно!

9. **Метод-обработчик события может возвращать необходимый статус возврата.**
Для этого обработчик нужно определить как функцию

	Функция ПриЗакрытии() Экспорт
	 	// текст обработчика события
        Возврат 0; // т.е. фактически СтатусВозврата(0) и форма не будет закрыта.
	КонецФункции

10. **Все вышесказанное относится также и к предопределенным событиям ВК FormEx.**

11. **В добавление ко всем стандартным событиям 1С и ВК FormEx добавлено
событие "СобытиеГМ_ПриОткрытии" для перехвата глобального модуля.**
Если есть обработчик этого события, то она будет вызван раньше системного
обработчика ПриОткрытии в модуле формы контекста.
Если обработчик вернет 0,  то  форма  не  будет  открыта  и  вызов  обработчика
ПриОткрытии из модуля формы контекста не будет выполнен.

Формат: СобытиеГМ_ПриОткрытии(КонтФормы)

	Функция СобытиеГМ_ПриОткрытии(КонтФормы) Экспорт
	 	// текст обработчика события
        Возврат 0; // т.е. фактически СтатусВозврата(0) и форма не будет открыта.
        или
        Возврат 1; // т.е. фактически СтатусВозврата(1) и форма будет открыта.
	КонецФункции

Если в глобальнике просто определить функцию  СобытиеГМ_ПриОткрытии(КонтФормы),
то она работать не будет. Данная функция сделана только для перехвата в классах перехвата.

12. **В добавление ко всем стандартным событиям 1С и ВК FormEx добавлено
событие "СобытиеГМ_ВводНового(КонтФормы, флагКопирования)" для перехвата
глобального модуля.**
Событие работает аналогично событию СобытиеГМ_ПриОткрытии

=====================================================================
Методы
=====================================================================
..	<chminfo split="0" splitchild="1">
		<insert nodes="//common/propsmethods/*"/>
	</chminfo>

.. _ПерехватитьСобытияГК:

ПерехватитьСобытияГК / HookEventsOfGroupContext
------------------------------------------------

    **Синтаксис:** ПерехватитьСобытияГК(ГрупповойКонтекстФормы, ОбъектПользовательскогоКлассаОбработчикаПерехвата)

	**Возвращает:** тип: Объект или пустое значение.

	**Параметры:**
		- **ГрупповойКонтекстФормы** - тип: ГрупповойКонтекст.
        - **ОбъектПользовательскогоКлассаОбработчикаПерехвата**  -  тип:  Класс КОП.

        Пользовательский класс, в котором определены обработчики событий
        контекста формы.

    **Описание:** Перехватывает любые предопределенные события контекста формы, как 1С, так и FormEx.
    Снять перехват можно с использованием метода СнятьПерехватСобытийГK_ .

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.
    В случае, если первый параметр не является групповым контекстом, выдается исключение.
    В случае, если второй параметр не является пользовательским классом, выдается исключение.

.. _ВыполнитьСобытиеГК:

ВыполнитьСобытиеГК / RunEventOfGroupContext
---------------------------------------------------------------
    **Синтаксис:** ВыполнитьСобытиеГК(ОбработчикСобытияИлиПустоеЗначение, ГрупповойКонтекстФормы, ИмяСобытия, ...)

	**Возвращает:** тип: Число - статус возврата модуля указанного контекста.

	**Параметры:**
        - **ОбработчикСобытияИлиПустоеЗначение**  -  тип:  класс 1С++ или
        пустое значение.
		- **ГрупповойКонтекстФормы** - тип: ГрупповойКонтекст.
        - **ИмяСобытия**  -  тип:  Строка.

    **Описание:** Вызывает соответствующий обработчик события контекста
    формы. Если обработчик не задан, просто выполняется вызов ВыполнитьОригинальноеСобытиеГК_
	Если обработчик задан, то выполняется вызов соответствующего
	метода. Если метод является функцией,  возвращает результат
	выполнения этой функции,  иначе 1
    Если метод не найден, возвращается 1 и не выдается сообщений об ошибках.

.. _ВыполнитьОригинальноеСобытиеГК:

ВыполнитьОригинальноеСобытиеГК / RunOriginalEventOfGroupContext
---------------------------------------------------------------
    **Синтаксис:** ВыполнитьОригинальноеСобытиеГК(ГрупповойКонтекстФормы, ИмяСобытия, ...)

	**Возвращает:** тип: Число - статус возврата модуля указанного контекста.

	**Параметры:**
		- **ГрупповойКонтекстФормы** - тип: ГрупповойКонтекст.
        - **ИмяСобытия**  -  тип:  Строка.

    **Описание:** Вызывает обработчик события контекста формы, который опреден в модуле этой формы.
    Если обработчика в форме не существует, ошибки не выдается.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.
    В случае, если первый параметр не является групповым контекстом, выдается исключение.
    В случае, если второй параметр не является строкой или строка пуста, выдается исключение.

.. _ПолучитьПерехватчикСобытийГК:

ПолучитьПерехватчикСобытийГК / GetHookObjectForEventsOfGroupContext
--------------------------------------------------------------------
    **Синтаксис:** ПолучитьПерехватчикСобытийГК(ГрупповойКонтекстФормы)

	**Параметры:**
		- **ГрупповойКонтекстФормы** - тип: ГрупповойКонтекст.

	**Возвращает:** тип: объект КОП, если для данной формы был включен
	перехват или Неопределено, если нет.

    **Описание:** Возвращает объект-перехватчик событий, если для данной
    формы был включен перехват.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.
    В случае, если параметр не является групповым контекстом, выдается исключение.

.. _СнятьПерехватСобытийГK:

СнятьПерехватСобытийГK / UnHookEventsOfGroupContext
-----------------------------------------------------------------------------------
    **Синтаксис:** СнятьПерехватСобытийГK(ГрупповойКонтекстФормы)

	**Параметры:**
		- **ГрупповойКонтекстФормы** - тип: ГрупповойКонтекст.

    **Описание:** Снимает перехват событий контекста формы, если перехват был
	установлен для данной формы.

	Если на пользовательский объект-перехватчик больше нет ссылок, будет
	вызван деструктор данного объекта.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.
    В случае, если параметр не является групповым контекстом, выдается исключение.

.. _ПерехватитьСобытияГлобальногоМодуля:

ПерехватитьСобытияГлобальногоМодуля / HookEventsOfGlobalModule
--------------------------------------------------------------------
    **Синтаксис:** ПерехватитьСобытияГлобальногоМодуля(ОбъектПользовательскогоКлассаОбработчикаПерехвата)

	**Возвращает:** тип: Объект или пустое значение.

	**Параметры:**
        - **ОбъектПользовательскогоКлассаОбработчикаПерехвата**  -  тип:  Класс КОП.

        Пользовательский класс, в котором определены обработчики событий глобального модуля.

    **Описание:** Перехватывает любые предопределенные события глобального модуля, как 1С, так и FormEx.
    Снять перехват можно с использованием метода СнятьПерехватСобытийГлобальногоМодуля_ .

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.
    В случае, если переданный параметр не является пользовательским классом, выдается исключение.

.. _ВыполнитьСобытиеГлобальногоМодуля:

ВыполнитьСобытиеГлобальногоМодуля / RunEventOfGlobalModule
---------------------------------------------------------------
    **Синтаксис:** ВыполнитьСобытиеГлобальногоМодуля(ОбработчикСобытияИлиПустоеЗначение, ИмяСобытия, ...)

	**Возвращает:** тип: Число - статус возврата модуля глобального модуля.

	**Параметры:**
        - **ОбработчикСобытияИлиПустоеЗначение**  -  тип:  класс 1С++ или
        пустое значение.
        - **ИмяСобытия**  -  тип:  Строка.

    **Описание:** Вызывает соответствующий обработчик события глобального
    модуля. Если обработчик не задан, просто выполняется вызов ВыполнитьОригинальноеСобытиеГлобальногоМодуля_
	Если обработчик задан, то выполняется вызов соответствующего
	метода. Если метод является функцией,  возвращает результат
	выполнения этой функции,  иначе 1
    Если метод не найден, возвращается 1 и не выдается сообщений об ошибках.

.. _ВыполнитьОригинальноеСобытиеГлобальногоМодуля:

ВыполнитьОригинальноеСобытиеГлобальногоМодуля / RunOriginalEventOfGlobalModule
------------------------------------------------------------------------------
    **Синтаксис:** ВыполнитьОригинальноеСобытиеГлобальногоМодуля(ИмяСобытия, ...)

	**Возвращает:** тип: Число - статус возврата глобального модуля.

	**Параметры:**
        - **ИмяСобытия**  -  тип:  Строка.

    **Описание:** Вызывает обработчик события глобального модуля, который опреден в глобальном модуле.
    Если обработчика в глобальном модуле не существует, ошибки не выдается.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.
    В случае, если первый параметр не является строкой или строка пуста, выдается исключение.

.. _ПолучитьПерехватчикСобытийГлобальногоМодуля:

ПолучитьПерехватчикСобытийГлобальногоМодуля / GetHookObjectForEventsOfGlobalModule
-----------------------------------------------------------------------------------
    **Синтаксис:** ПолучитьПерехватчикСобытийГлобальногоМодуля()

	**Возвращает:** тип: объект КОП, если был включен
	перехват событий глобального модуля или Неопределено, если нет.

    **Описание:** Возвращает объект-перехватчик событий, если был включен
    перехват событий глобального модуля.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.

.. _СнятьПерехватСобытийГлобальногоМодуля:

СнятьПерехватСобытийГлобальногоМодуля / UnHookEventsOfGlobalModule
-----------------------------------------------------------------------------------
    **Синтаксис:** СнятьПерехватСобытийГлобальногоМодуля()

    **Описание:** Снимает перехват событий глобального модуля, если перехват был
	установлен.

	Если на пользовательский объект-перехватчик больше нет ссылок, будет
	вызван деструктор данного объекта.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.

.. _ПодключитьСобытие_НеобработаннаяОшибка:

ПодключитьСобытие_НеобработаннаяОшибка / AddEvent_UnHandledError
-----------------------------------------------------------------------------------
    **Синтаксис:** ПодключитьСобытие_НеобработаннаяОшибка()

    **Описание:** Подключает возможность получения необработанной ошибки в обработчике
    	внутри глобального модуля Событие_НеобработаннаяОшибка()

    **Описание обработчика:**
    	Функция/Процедура Событие_НеобработаннаяОшибка(СообщениеОбОшибке, Маркер,
    		ИмяФайла, Парам4, НомерСтрокиОшибки, Парам6)

	Если обработчик является функцией, то если он возвращает 0, системное
	сообщение об ошибке не показывается. Если 1, то показывается.
	Если процедурой, системное сообщение об ошибке также показывается.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.

.. _ПодключитьСобытие_ЗаписьСобытияЖурналаРегистрации:

ПодключитьСобытие_ЗаписьСобытияЖурналаРегистрации / AddEvent_ReportEventA
-----------------------------------------------------------------------------------
    **Синтаксис:** ПодключитьСобытие_ЗаписьСобытияЖурналаРегистрации()

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

    **Описание обработчика:**
    	Функция/Процедура Событие_ЗаписьСобытияЖурналаРегистрации(EventCategory,
    		Event, EvType, comment, object, ObjDescr)

	Если обработчик является функцией, то если он возвращает 0, системная
    запись в журнал регистрации выполняться не будет. Если 1, то запись будет выполнена.
	Если процедурой, системная запись в журнал регистрации будет выполнена.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.

.. _ПодключитьСобытие_ЗаписьПользовательскогоСобытияЖурналаРегистрации:

ПодключитьСобытие_ЗаписьПользовательскогоСобытияЖурналаРегистрации / AddEvent_ReportUserEvent
-----------------------------------------------------------------------------------
    **Синтаксис:** ПодключитьСобытие_ЗаписьПользовательскогоСобытияЖурналаРегистрации()

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

    **Описание обработчика:**
    	Функция/Процедура Событие_ЗаписьПользовательскогоСобытияЖурналаРегистрации(EventCategory,
    		Event, EvType, comment, object, ObjDescr)

	Если обработчик является функцией, то если он возвращает 0, системная
    запись в журнал регистрации выполняться не будет. Если 1, то запись будет выполнена.
	Если процедурой, системная запись в журнал регистрации будет выполнена.

    Если настройка 1С++ " **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
    не включена, будет выдано исключение.

=====================================================================
События глобального модуля
=====================================================================
..	<chminfo split="0" splitchild="1">
		<insert nodes="//common/propsmethods/*"/>
	</chminfo>

**Инструкция для использования**

1. Для использования перехвата должна быть включена настройка 1С++
" **ПерехватитьСобытияГК / EnableHookEventsGroupContext** "
с помощью встроенного класса "УправлениеНастройками"
См. `SettingsManager <SettingsManager.chm::/SettingsManager0.html>`_

2. Подключение любого из событий возможно в произвольный момент,
по умолчанию при загрузке 1С++ они выключены.

Например:
	Перехватчик = СоздатьОбъект("Перехватчик");
	Перехватчик.ПодключитьСобытие_НеобработаннаяОшибка_ ();
	Перехватчик.ПодключитьСобытие_ЗаписьСобытияЖурналаРегистрации_ ();
    Перехватчик.ПодключитьСобытие_ЗаписьПользовательскогоСобытияЖурналаРегистрации_ ();

3. При подключения в глобальнике единственный раз идет поиск соответствующих событий
	Событие_НеобработаннаяОшибка_ ()
	Событие_ЗаписьСобытияЖурналаРегистрации_ ()
	Событие_ЗаписьПользовательскогоСобытияЖурналаРегистрации_ ()

В дальнейшем повторного поиска не происходит, в отличие от ФормЕкс, что дает хорошую скорость работы.

4. Обработчики событий могут быть функциями,
в этом случае если возвращается 0, системная функция не вызывается.
Если обработчик события является процедурой, то системная функция вызывается всегда.

5. Перед подключением можно установить перехват на глобальник,
тогда указанные события будут ловиться в классах с помощью перехвата глобального модуля.

.. _Событие_НеобработаннаяОшибка:

Событие_НеобработаннаяОшибка
-----------------------------------------------------------------------------------
    **Синтаксис:** Функция/Процедура Событие_НеобработаннаяОшибка(СообщениеОбОшибке, Маркер,
    		ИмяФайла, Парам4, НомерСтрокиОшибки, Парам6)

    **Описание:** Подключает возможность получения необработанной ошибки в обработчике
    	внутри глобального модуля Событие_НеобработаннаяОшибка()

	Если обработчик является функцией, то если он возвращает 0, системное
	сообщение об ошибке не показывается. Если 1, то показывается.
	Если процедурой, системное сообщение об ошибке также показывается.

.. _Событие_ЗаписьСобытияЖурналаРегистрации:

Событие_ЗаписьСобытияЖурналаРегистрации
-----------------------------------------------------------------------------------
    **Синтаксис:** Функция/Процедура Событие_ЗаписьСобытияЖурналаРегистрации(EventCategory,
    		Event, EvType, comment, object, ObjDescr)

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

	Если обработчик является функцией, то если он возвращает 0, системная
    запись в журнал регистрации выполняться не будет. Если 1, то запись будет выполнена.
	Если процедурой, системная запись в журнал регистрации будет выполнена.

.. _Событие_ЗаписьПользовательскогоСобытияЖурналаРегистрации:

Событие_ЗаписьПользовательскогоСобытияЖурналаРегистрации
-----------------------------------------------------------------------------------
    **Синтаксис:** Функция/Процедура Событие_ЗаписьПользовательскогоСобытияЖурналаРегистрации(EventCategory,
    		Event, EvType, comment, object, ObjDescr)

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

	Если обработчик является функцией, то если он возвращает 0, системная
    запись в журнал регистрации выполняться не будет. Если 1, то запись будет выполнена.
	Если процедурой, системная запись в журнал регистрации будет выполнена.