|
|
|
Отловить событие | ☑ | ||
|---|---|---|---|---|
|
0
sakhru
01.08.10
✎
08:58
|
Здравствуйте ВСЕ. С помощью внешних компонент можно сгенерировать событие и обработать его в 1с, а можно ли отловить во внешней компоненте событие 1с (например проведение документа)?
|
|||
|
1
Amiralnar
01.08.10
✎
09:38
|
Да, можно. 1С предприятие, как Com объект предоставляет интерфейс для подписки на события.
Например, так: Процедура ПередЗаписьюСправочника() Сообщить("Документ изменен"); КонецПроцедуры // Создание объекта-коннектора cntr = Новый COMObject("V81.COMConnector"); // создается объект COM-соединение connection = cntr.Connect("File=""c:\InfoBases\Trade""; Usr=""Director"";") СпрКонтрагенты = connection.Справочники.Контрагенты; СпрОбъект = СпрКонтрагенты.НайтиПоКоду().ПолучитьОбъект(); ДобавитьОбработчик СпрОбъект.ПередЗаписью, ПередЗаписьюСправочника; Единственное, с параметрами я не знаю как дело обстоит. |
|||
|
2
sakhru
01.08.10
✎
10:04
|
TO Amiralnar. Не то. Уменя компонента на C# я после cntr = Новый COMObject("МояКомпонента")в 1, хочу внутри компоненты обрабатывать (синхронно с 1с) события типа вводновог, проведение и т.д.
|
|||
|
3
Rie
01.08.10
✎
10:28
|
(2) IMHO, аналогично. Вторым параметром указываешь ссылку на твой объект, затем через точку - имя метода (у которого должно быть соответствующее событию количество параметров).
|
|||
|
4
sakhru
01.08.10
✎
10:31
|
TO Amiralnar А как я увижу объект обработки внутри метода?
|
|||
|
5
Amiralnar
01.08.10
✎
10:53
|
(4) Попробуйте поэкспериментировать с параметрами. Я не знаю, где это описано, и не уверен, что так оно и есть, но по логике объект должен передаваться первым параметром. А еще "Отказ" передается.
(3) В данном случае указывать можно только процедуры 1С, т.к. это она подписывается на события. Если подписываешься из Ворда на 1С, то указываешь обработчиками подписок суброуты в своей области видимости. (2) Вам лучше всего организовать подписку в обработке, вызывающей вашу компоненту. А в процедурах обработчиках вызывать методы компоненты, передавая ей любые парамерты. А в общем, если вам приспичило подписаться на события именно из обработки, то последовательность действий та-же самая. Единственное, я не знаю, как в C# выглядит оператор "ДобавитьОбработчик" - это уже ваша проблема. Также рекомендую ознакомиться с СП, в частности там описаны доступные события объектов. Обратите внимание, ввод нового в событиях не перечислен. |
|||
|
6
Amiralnar
01.08.10
✎
10:58
|
И вообще, на мой взгляд, "внутри компоненты обрабатывать (синхронно с 1с) события типа вводновог, проведение и т.д." - это гнилая тема, т.к. у вас транзакция открыта, а что там будет делать ваша компонента, и сколько у неё времени уйдет - не известно.
Задайте вопрос, описав задачу, а не предлагая ваш способ решения. |
|||
|
7
Rie
01.08.10
✎
11:07
|
(5) Можно указывать и методы объекта. Вот тестовый пример:
НоваяВалюта = Справочники.Валюты.СоздатьЭлемент(); НоваяВалюта.Код = "ZZZ"; НоваяВалюта.Записать(); НоваяСсылка = НоваяВалюта.Ссылка; МойОбъект = Новый COMОбъект("testEV.evproc"); ДобавитьОбработчик НоваяВалюта.ПередЗаписью, МойОбъект.Proc; НоваяВалюта.Записать(); |
|||
|
8
Rie
01.08.10
✎
11:11
|
+(7) На всякий случай - код объекта:
unit evproc; {$WARN SYMBOL_PLATFORM OFF} interface uses ComObj, ActiveX, AxCtrls, Classes, testEv_TLB, StdVcl; type TEvProc = class(TAutoObject, IConnectionPointContainer, IEvProc) private { Private declarations } FConnectionPoints: TConnectionPoints; FConnectionPoint: TConnectionPoint; FEvents: IEvProcEvents; { note: FEvents maintains a *single* event sink. For access to more than one event sink, use FConnectionPoint.SinkList, and iterate through the list of sinks. } public procedure Initialize; override; protected { Protected declarations } property ConnectionPoints: TConnectionPoints read FConnectionPoints implements IConnectionPointContainer; procedure EventSinkChanged(const EventSink: IUnknown); override; procedure Proc(const Source: IDispatch; var Refuse: WordBool); safecall; end; implementation uses ComServ , Windows; procedure TEvProc.EventSinkChanged(const EventSink: IUnknown); begin FEvents := EventSink as IEvProcEvents; end; procedure TEvProc.Initialize; begin inherited Initialize; FConnectionPoints := TConnectionPoints.Create(Self); if AutoFactory.EventTypeInfo <> nil then FConnectionPoint := FConnectionPoints.CreateConnectionPoint( AutoFactory.EventIID, ckSingle, EventConnect) else FConnectionPoint := nil; end; procedure TEvProc.Proc(const Source: IDispatch; var Refuse: WordBool); begin MessageBox(0,'!!!','',0) end; initialization TAutoObjectFactory.Create(ComServer, TEvProc, Class_EvProc, ciMultiInstance, tmApartment); end. |
|||
|
9
Amiralnar
01.08.10
✎
11:11
|
(7) СП:
Обработчиком события может являться метод объекта встроенного языка. ... Также в качестве обработчика события может быть задана процедура/функция, находящаяся в области видимости. В этом случае обработчик события задается как имя процедуры/функции. Если под 2 понимается абсолютно любая процедура, которую можно выполнить, то вы правы. |
|||
|
10
Rie
01.08.10
✎
11:13
|
(9) Пример из (7)+(8) - работает. В качестве обработчика события назначается (и исполняется при возникновении события) метод COM-объекта.
Как это соотносится с СП - это уже дело десятое. Возможно, авторы СП чего-то недоговаривают. |
|||
|
11
Amiralnar
01.08.10
✎
11:15
|
(7) Сколько экземпляров объекта "testEV.evproc" создаст 1С при выполнении на сервере в многопользовательской среде? Если два пользователя одновременно запишут такой документ, что происходит в объекте "testEV.evproc"?
|
|||
|
12
Rie
01.08.10
✎
11:19
|
(11) Сколько будет создано (Новы COMобъект) - столько и создаст.
Как два пользователя _одновременно_ будут записывать один и тот же элемент справочника - хотел бы полюбоваться на это зрелище. (Но если будет назначено несколько обработчиков одному событию - выполнятся все). |
|||
|
13
Amiralnar
01.08.10
✎
11:22
|
(12) Это где-то описано, или ваш личный опыт? Размеется, такое поведение наиболее логично, но мало-ли.
Два пользователя одновременно будут записывать разные элементы справочников, однако код у вас вас один для всех. |
|||
|
14
Rie
01.08.10
✎
11:34
|
(13) В (7)+(8) приведен _работающий_ код. Любой желающий может сам убедиться в этом.
То, что будут исполняться все назначенные обработчики - это стандартное поведение делегата. Слегка модифицировав код в (7) - можно легко в этом убедиться. Что касается записи элементов разными пользователями - назначенный обработчик существует только в пределах создавшего его процесса. Со всеми отсюда вытекающими. |
|||
|
15
Rie
01.08.10
✎
11:39
|
+(14) Насчёт делегатов - в принципе существуют две их разновидности: "ёмкостью" на один метод и на множество методов. Но для обработчиков событий используется второй вариант.
|
|||
|
16
sakhru
02.08.10
✎
03:10
|
Пишу так:
Процедура ПриОткрытии() Я=новый COMОбъект("AGComObject.CComObject"); ДобавитьОбработчик ПередЗаписью,Я.EventTest; КонецПроцедуры Ругается так : {Справочник.Справочник1.Форма.ФормаЭлемента(5,34)}: Неправильное описание события ДобавитьОбработчик ПередЗаписью<<?>>,Я.EventTest; Может вопрос и глповатый, но извините с 8 недавно. Как-то всю жизнь 7.5-7.7 ну и компиляторы |
|||
|
17
Amiralnar
02.08.10
✎
05:01
|
Пиши так:
Процедура ПриОткрытии() Я=новый COMОбъект("AGComObject.CComObject"); //Обратите внимание, именно для таких случаев придумано свойство "this" ДобавитьОбработчик ЭтотОбъект.ПередЗаписью,Я.EventTest; КонецПроцедуры |
|||
|
18
sakhru
02.08.10
✎
08:36
|
Да нормально вроде, но что первым параметром передаётся:
public void EventTest(IDispatchImplAttribute H, bool p) { System.Windows.Forms.MessageBox.Show(""); } Так? "Неизвестная ошибка" |
|||
|
19
sakhru
02.08.10
✎
09:45
|
Всё разобрался. Вопрос другой, могу ли я при старте системы, сразу установить перехватчики проведения документов, записи и т.д.
ДобавитьОбработчик <Любые документы>.ПередЗаписью,Я.EventTest; |
|||
|
20
sakhru
02.08.10
✎
09:47
|
И ещё как потом уничтожить объект (процесс висит даже после закрытия окна 1С)
|
|||
|
21
Rie
02.08.10
✎
09:52
|
(19) Установи, если надо.
В ПриНачалеРаботыСистемы, например (только этих ПриНачалеРаботыСистемы несколько - для разных видов приложения). По разным документам - пробегись по метаданным. Но если ты всё равно конфигурацию правишь - может, лучше использовать подписки на события, в которых и вызывать методы твоего объекта? (20) Уничтожить - присвой пустое значение. Но может быть, у тебя в самом объекте что-то не так, раз сборщик мусора его видит как используемый? |
|||
|
22
sakhru
02.08.10
✎
09:55
|
Можно пример кода, как установить обработчик при проведение определённого вида документа, но чтобы и стандартная процедура тоже отрабатывалась
|
|||
|
23
sakhru
02.08.10
✎
09:57
|
Ещё. Пишу в модуле формы вот так:
Процедура ПриОткрытии() сообщить("№№№ссссссссс"); Я=новый COMОбъект("AGComObject.CComObject"); ДобавитьОбработчик ЭтотОбъект.ПередЗаписью,Я.EventTest; КонецПроцедуры Процедура вообще не отрабатывается (даже сообщить не видно) |
|||
|
24
Rie
02.08.10
✎
09:58
|
(23) Процедуру ПриОткрытии с событием ПриОткрытии связал?
(Например, в свойствах формы, которую открываешь). (22) Стандартная процедура так и будет отрабатываться (если ей это специально не запретить). |
|||
|
25
sakhru
02.08.10
✎
10:01
|
Конечно не связал! Совсем с 8 плохо. А пример кода например перехват обработки проведения для документа Реализация можно
|
|||
|
26
Rie
02.08.10
✎
10:05
|
(25) Чтобы не мучиться - посмотри подписки на события. Добавь новую. В ней укажи документ Реализация в качестве источника и ОбработкаПроведения в качестве события.
Ну и впиши в соответствующую процедуру нужный тебе код (например, вызов нужного метода твоего объекта). Такой способ будет удобнее, IMHO, чем мучиться с ДобавитьОбработчик. |
|||
|
27
sakhru
02.08.10
✎
10:09
|
Дело в том что не хочется лезть в обработки проведения документов, хотелось бытак;
В глобальном написать типа Подписаться Реализация,Я.First Подписаться Поступление,Я.Second Подписаться Реализация,Я.Thirst |
|||
|
28
Rie
02.08.10
✎
10:16
|
(27) Вот чтобы не влезать в обработки проведения документов - как раз и придуманы подписки на события (Конфигурация - Общие - Подписки на события).
|
|||
|
29
sakhru
02.08.10
✎
10:33
|
Круто! Пиво как выслать?
|
|||
|
30
sakhru
02.08.10
✎
22:13
|
Первым параметром в COM объект передаётся IDispatch. Кто нибудь знает как сним там работать чтобы видеть его как 1с
|
|||
|
31
sakhru
02.08.10
✎
22:16
|
To Rie: У тебя в поцедуру const Source: IDispatch передаётся если состороны 1с это документ, как ты с ним в delphi работаешь?
|
|||
|
32
Rie
02.08.10
✎
22:28
|
(31) Так же, как и в 1С. Интерфейс - он и в Африке интерфейс.
Как пример кода на Delphi (тот же пример, что и в (8) с небольшими изменениями): procedure TEvProc.Proc(const Source: IDispatch; var Refuse: WordBool); var V: Variant; s: string; begin V := Source; s := V.Code; MessageBox(0,PChar(s),'',0) end; выводит код записываемого элемента. (Можно даже написать s := V.Код;). (В Delphi есть хитрость - присвоить IDispatch переменной типа Variant, тогда Delphi само оттранслирует V.Code в соответствующие вызовы; если пишешь на C# - придётся явно выписывать все вызовы). |
|||
|
33
Rie
02.08.10
✎
22:34
|
+(32) Под рукой C# сейчас нет - но поищи по форуму, была тема о том, как из C# обращаться к 1C-объектам.
|
| Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |