Имя: Пароль:
1C
 
Отловить событие
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-объектам.