OE>>Как в ATL клиенте подписываться на события надо объяснять?
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;

        ...
    }

};
Автор: Odi$$ey    Оценить