Как в ATL клиенте подписываться на COM-события
21.09.2004
|
Odi$$ey |
OE>>Как в ATL клиенте подписываться на события надо объяснять?
E>ДА!
Ok, например в клиенте есть диалог, в котором нужно ловить события от COM-сервера:
добавляем туда следующие вещи (см. выделенное):
E>ДА!
Ok, например в клиенте есть диалог, в котором нужно ловить события от COM-сервера:
class CMainDlg : public CAxDialogImpl<CMainDlg>
, public CDialogResize<CMainDlg>
{
добавляем туда следующие вещи (см. выделенное):
#import "MyCOM.dll" no_namespace, named_guids
// произвольное число, удобно когда подключение идет к событиям сразу нескольких компонент
#define IMYINTRFID 1
class CMainDlg : public CAxDialogImpl<CMainDlg>
, public CDialogResize<CMainDlg>
, public IDispEventImpl<IMYINTRFID, CMainDlg, &DIID___IMyIntrfEvent, &LIBID_MYCOMLib, 1, 0>
{
IMyIntrfPtr pMyIntrfPtr;
// номер метода-события (0x1) смотрим в idl сервера или в
// mycom.tli, который создаст #import
BEGIN_SINK_MAP( CMainDlg )
SINK_ENTRY_EX( IMYINTRFID, DIID___IMyIntrfEvent, 0x1, OnFirstMethod )
END_SINK_MAP()
// этот метод будет вызван при возникновении события
HRESULT __stdcall OnFirstMethod( BSTR str )
{
// получили строку str
return S_OK;
}
// функция для подписки на события, вызывается где удобно, например
// в OnInitDialog() после загрузки pMyIntrfPtr
BOOL Advise2MyCOMEvent()
{
_ASSERTE( pMyIntrfPtr != NULL );
if ( pMyIntrfPtr )
{
HRESULT hr = _IDispEventLocator<IMYINTRFID, &DIID___IMyIntrfEvent>::DispEventAdvise( pMyIntrfPtr, &DIID___IMyIntrfEvent );
if ( FAILED( hr ) )
{
// ошибка, код в hr
return FALSE;
}
else
return TRUE;
}
else
{
// ошибка - компонент не загружен, подписка невозможна
return FALSE;
}
}
// функция для отписки от событий, вызывается где удобно,
// например в OnDestroy()
BOOL UnAdvise2MyCOMEvent()
{
if ( pMyIntrfPtr )
{
HRESULT hr = _IDispEventLocator<IMYINTRFID, &DIID___IMyIntrfEvent>::DispEventUnadvise( pMyIntrfPtr, &DIID___IMyIntrfEvent );
if ( FAILED( hr ) )
{
// ошибка, код в hr
return FALSE;
}
else
return TRUE;
}
else
return FALSE;
}
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
...
HRESULT hr = pMyIntrfPtr.CreateInstance( "MyCom.MyIntrf" );
if ( SUCCEEDED( hr ) )
{
Advise2MyCOMEvent();
}
else
{
// ошибка
}
...
}
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
...
UnAdvise2MyCOMEvent();
pMyIntrfPtr = NULL;
...
}
};
21.09.2004 5 комментариев |
OE>Здравствуйте, Esperar, Вы писали:
OE>>>Как в ATL клиенте подписываться на события надо объяснять?
E>>ДА!
OE>Ok, например в клиенте есть диалог, в котором нужно ловить события от COM-сервера:
если нет в клиенте диалога, если клиент — это плагин, то где там ловить события?
OE>
OE>добавляем туда следующие вещи (см. выделенное):
OE>
E>если нет в клиенте диалога, если клиент — это плагин, то где там ловить события?
по-барабану, совершенно аналогично прикручивается к любому классу
OE>Ok, например в клиенте есть диалог, в котором нужно ловить события от COM-сервера:
OE>
Кажется (не уверен что прав) тут есть одна ошибка, класс CMainDlg не наследник IDispatch.
И вызов Invoke
IDispatch* pConnection = static_cast<IDispatch *>(punkConnection.p);
pConnection->Invoke(...);
Не совсем правильный...
A>Кажется (не уверен что прав) тут есть одна ошибка, класс CMainDlg не наследник IDispatch.
и?
A>И вызов Invoke
A> IDispatch* pConnection = static_cast<IDispatch *>(punkConnection.p);
A> pConnection->Invoke(...);
A>Не совсем правильный...
а это где такой? я такого не писал
A>>Кажется (не уверен что прав) тут есть одна ошибка, класс CMainDlg не наследник IDispatch.
OE>и?
A>>И вызов Invoke
A>> IDispatch* pConnection = static_cast<IDispatch *>(punkConnection.p);
A>> pConnection->Invoke(...);
A>>Не совсем правильный...
OE>а это где такой? я такого не писал
А его никто не писал, его визард сам напишет
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_atl_Adding_Connection_Points_to_an_Object.asp
И класс который он сгенерирует будет выглядеть примерно так —
Вот тут и есть тот самый каст к IDispatch.
IDispatch* pConnection = static_cast<IDispatch*>(punkConnection.p); // punkConnection.p содержит IUnknown от объекта класса CMainDlg
Имхо имеет смысл добавить к классу CMainDlg в базы такую туповатую строчку —
, public IDispatchImpl<IDispatch, &__uuidof(IDispatch), &LIBID_....>
Тогда этот каст будет логически обоснован, хоть както .
Но может я и ошибаюсь и гдето чего то просмотрел...