нужно сделать нотификацию метода используя connection point.
Создаю COM обьект на ATL, при воздании инерфейса выбираю connection point. А дальше как? Искал по поиску ничего толком не нашел.. есть описания только с использованием MFC, а с ATL как?
Если у меня есть метод Func(...), я передаю некоторые параметры и хочу узнать когда эти данные обработаються.
Подскажите, если можно с примером. Или дайте ссылки, где можно почитать..
Здравствуйте, atrofa, Вы писали:
A>нужно сделать нотификацию метода используя connection point. A>Создаю COM обьект на ATL, при воздании инерфейса выбираю connection point. А дальше как?
— раз при создании поставил галочку на connection point у тебя в ClassView вместе с твоим интерфейсом IMyIntrf должен появится _IMyIntrfEvent
— вызываешь для него контекстное меню, потом Add-Add Method и добавляешь метод, например FirstMethod( BSTR str )
— компилируешь проект
— вызываешь контекстное меню в том же ClassView, только уже для класса (CMyIntrf)
— Add — Add Connection Point
— в форме увидишь слева свой _IMyIntrfEvent, перенесешь его кнопкой > в правое поле, Finish
— в CProxy_IMyIntrfEvent добавится метод Fire_FirstMethod( BSTR str )
A>Если у меня есть метод Func(...), я передаю некоторые параметры и хочу узнать когда эти данные обработаються.
вызывай в этом месте Fire_FirstMethod
Как в ATL клиенте подписываться на события надо объяснять?
Здравствуйте, Odi$$ey, Вы писали:
OE>- раз при создании поставил галочку на connection point у тебя в ClassView вместе с твоим интерфейсом IMyIntrf должен появится _IMyIntrfEvent OE>- вызываешь для него контекстное меню, потом Add-Add Method и добавляешь метод, например FirstMethod( BSTR str ) OE>- компилируешь проект OE>- вызываешь контекстное меню в том же ClassView, только уже для класса (CMyIntrf) OE>- Add — Add Connection Point OE>- в форме увидишь слева свой _IMyIntrfEvent, перенесешь его кнопкой > в правое поле, Finish OE>- в CProxy_IMyIntrfEvent добавится метод Fire_FirstMethod( BSTR str )
A>>Если у меня есть метод Func(...), я передаю некоторые параметры и хочу узнать когда эти данные обработаються.
OE>вызывай в этом месте Fire_FirstMethod
OE>Как в ATL клиенте подписываться на события надо объяснять
Спасибо , с этим уже разобрался.. работает.. только мне нужно в клиент воза\вращать структуру RequestData:
Метод вызываеться а вот в структуре находиться какойто мусор.
Да и еще, мне нужно реализовать только С интерефейс, так что переводить структуру в SAFEARRAY не обязательно.
я тут подумал.. можно возвращать не структуру, а массив BSTR, только у меня всеравно не работает.. а использовать SAFEARRAY не желательно.
Можно вернуть массив BSTR??
типа так:
[id(1), helpstring("method SynchronizeClear")] HRESULT SynchronizeClear([out] BSTR* respData);
Здравствуйте, Odi$$ey, Вы писали:
OE>Здравствуйте, atrofa, Вы писали:
A>>нужно сделать нотификацию метода используя connection point. A>>Создаю COM обьект на ATL, при воздании инерфейса выбираю connection point. А дальше как?
OE>- раз при создании поставил галочку на connection point у тебя в ClassView вместе с твоим интерфейсом IMyIntrf должен появится _IMyIntrfEvent OE>- вызываешь для него контекстное меню, потом Add-Add Method и добавляешь метод, например FirstMethod( BSTR str ) OE>- компилируешь проект OE>- вызываешь контекстное меню в том же ClassView, только уже для класса (CMyIntrf) OE>- Add — Add Connection Point OE>- в форме увидишь слева свой _IMyIntrfEvent, перенесешь его кнопкой > в правое поле, Finish OE>- в CProxy_IMyIntrfEvent добавится метод Fire_FirstMethod( BSTR str )
A>>Если у меня есть метод Func(...), я передаю некоторые параметры и хочу узнать когда эти данные обработаються.
OE>вызывай в этом месте Fire_FirstMethod
OE>Как в ATL клиенте подписываться на события надо объяснять?
ДА!
Здравствуйте, atrofa, Вы писали:
A>Спасибо , с этим уже разобрался.. работает.. только мне нужно в клиент воза\вращать структуру RequestData:
A>Сейчас пишу так:
A> dispinterface _IDataEvents A> { A> properties: A> methods: A> [id(1), helpstring("method OnSynchronize")] HRESULT OnSynchronize([out] RequestData* respData); A> };
A>Метод вызываеться а вот в структуре находиться какойто мусор. A>Да и еще, мне нужно реализовать только С интерефейс, так что переводить структуру в SAFEARRAY не обязательно.
A>Почему не передаеться структура?
Структура передается, только не в ту сторону.
Для твоего СОМ объекта интерфейс _IDataEvents является внешним, следовательно параметры передаются от СОМ объекта к клиенту.
А для клиента параметр будет входящим, т.е. [in].
Здравствуйте, Odi$$ey, Вы писали:
OE>Здравствуйте, Esperar, Вы писали:
OE>>>Как в ATL клиенте подписываться на события надо объяснять? E>>ДА!
OE>Ok, например в клиенте есть диалог, в котором нужно ловить события от COM-сервера:
если нет в клиенте диалога, если клиент — это плагин, то где там ловить события?
OE>
OE>class CMainDlg : public CAxDialogImpl<CMainDlg>
OE> , public CDialogResize<CMainDlg>
OE>{
OE>
OE>добавляем туда следующие вещи (см. выделенное):
OE>
OE>#import"MyCOM.dll" no_namespace, named_guids
OE>// произвольное число, удобно когда подключение идет к событиям сразу нескольких компонент
OE>#define IMYINTRFID 1
OE>class CMainDlg : public CAxDialogImpl<CMainDlg>
OE> , public CDialogResize<CMainDlg>
OE> , public IDispEventImpl<IMYINTRFID, CMainDlg, &DIID___IMyIntrfEvent, &LIBID_MYCOMLib, 1, 0>
OE>{
OE> IMyIntrfPtr pMyIntrfPtr;
OE> // номер метода-события (0x1) смотрим в idl сервера или в
OE> // mycom.tli, который создаст #import
OE> BEGIN_SINK_MAP( CMainDlg )
OE> SINK_ENTRY_EX( IMYINTRFID, DIID___IMyIntrfEvent, 0x1, OnFirstMethod )
OE> END_SINK_MAP()
OE> // этот метод будет вызван при возникновении события
OE> HRESULT __stdcall OnFirstMethod( BSTR str )
OE> {
OE> // получили строку str
OE> return S_OK;
OE> }
OE>
OE> // функция для подписки на события, вызывается где удобно, например
OE> // в OnInitDialog() после загрузки pMyIntrfPtr
OE> BOOL Advise2MyCOMEvent()
OE> {
OE> _ASSERTE( pMyIntrfPtr != NULL );
OE> if ( pMyIntrfPtr )
OE> {
OE> HRESULT hr = _IDispEventLocator<IMYINTRFID, &DIID___IMyIntrfEvent>::DispEventAdvise( pMyIntrfPtr, &DIID___IMyIntrfEvent );
OE> if ( FAILED( hr ) )
OE> {
OE> // ошибка, код в hr
OE> return FALSE;
OE> }
OE> else
OE> return TRUE;
OE> }
OE> else
OE> {
OE> // ошибка - компонент не загружен, подписка невозможна
OE> return FALSE;
OE> }
OE> }
OE>
OE> // функция для отписки от событий, вызывается где удобно,
OE> // например в OnDestroy()
OE> BOOL UnAdvise2MyCOMEvent()
OE> {
OE> if ( pMyIntrfPtr )
OE> {
OE> HRESULT hr = _IDispEventLocator<IMYINTRFID, &DIID___IMyIntrfEvent>::DispEventUnadvise( pMyIntrfPtr, &DIID___IMyIntrfEvent );
OE> if ( FAILED( hr ) )
OE> {
OE> // ошибка, код в hr
OE> return FALSE;
OE> }
OE> else
OE> return TRUE;
OE> }
OE> else
OE> return FALSE;
OE> }
OE>
OE> LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
OE> {
OE> ...
OE> HRESULT hr = pMyIntrfPtr.CreateInstance( "MyCom.MyIntrf" );
OE> if ( SUCCEEDED( hr ) )
OE> {
OE> Advise2MyCOMEvent();
OE> }
OE> else
OE> {
OE> // ошибка
OE> }
OE> ...
OE> }
OE> LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
OE> {
OE> ...
OE> UnAdvise2MyCOMEvent();
OE> pMyIntrfPtr = NULL;
OE> ...
OE> }
OE>};
OE>
Здравствуйте, Odi$$ey, Вы писали:
OE>Ok, например в клиенте есть диалог, в котором нужно ловить события от COM-сервера:
OE>
OE>class CMainDlg : public CAxDialogImpl<CMainDlg>
OE> , public CDialogResize<CMainDlg>
OE>{
OE>
Кажется (не уверен что прав) тут есть одна ошибка, класс CMainDlg не наследник IDispatch.
И вызов Invoke
IDispatch* pConnection = static_cast<IDispatch *>(punkConnection.p);
pConnection->Invoke(...);
Не совсем правильный...
Здравствуйте, Odi$$ey, Вы писали:
A>>Кажется (не уверен что прав) тут есть одна ошибка, класс CMainDlg не наследник IDispatch.
OE>и?
A>>И вызов Invoke A>> IDispatch* pConnection = static_cast<IDispatch *>(punkConnection.p); A>> pConnection->Invoke(...); A>>Не совсем правильный...
OE>а это где такой? я такого не писал
Вот тут и есть тот самый каст к IDispatch.
IDispatch* pConnection = static_cast<IDispatch*>(punkConnection.p); // punkConnection.p содержит IUnknown от объекта класса CMainDlg
Имхо имеет смысл добавить к классу CMainDlg в базы такую туповатую строчку —
, public IDispatchImpl<IDispatch, &__uuidof(IDispatch), &LIBID_....>
Тогда этот каст будет логически обоснован, хоть както .
Но может я и ошибаюсь и гдето чего то просмотрел...