小弟最近学习ATL编写Add-in,有2个困惑的地方,请高人指点:1, 创建了多个button,如果第一个button使用了 DispEventAdvise 建立连接,
    然后创建了第二个button, 使用 DispEventAdvise 建立连接, 这个时候就会报错,
    什么Cookie已经不为空。    我现在的解决办法是在第二个button调用 DispEventAdvise 前,先对前一个button调用
    DispEventUnadvise , 这样就不会报错,而且第一个button尽管已经被调用 DispEventUnadvise
    不过还是可以响应点击的,这是为什么?
2, 有多个事件源对应一个接收函数,而这个函数却一个参数也没有,比如很多控件的Close事件,(例如_Inspector的Close事件)
    如果知道到底是哪个事件源发出的消息?有没有通用的方法?
请高人赐教!
谢谢!

解决方案 »

  1.   

    对你说的问题,叙述不是很清楚,所以不好回答。
    建议你看看IDispEventSimpleImpl模板的原代码,在\MICROSOFT VISUAL STUDIO\VC98\ATL\Include\ATLCOM.H文件里。
    其实学习ATL开发COM组件,最好看看微软对ATL的封装,在\MICROSOFT VISUAL STUDIO\VC98\ATL目录下可以找到所有ATL的封装代码,如能结合<<深入解析ATL>>那本书更好理解。
      

  2.   

    class ATL_NO_VTABLE CFPAnt : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CFPAnt, &CLSID_FPAnt>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CFPAnt>,
    public IDispatchImpl<IFPAnt, &IID_IFPAnt, &LIBID_OFFICEANTLib>,
    public IDispatchImpl<AddInDesignerObjects::_IDTExtensibility2, &AddInDesignerObjects::IID__IDTExtensibility2, &AddInDesignerObjects::LIBID_AddInDesignerObjects>,
    public IDispEventSimpleImpl<1,CFPAnt,&__uuidof(Office::_CommandBarButtonEvents)>,
    public IDispEventSimpleImpl<2,CFPAnt,&__uuidof(Office::_CommandBarButtonEvents)>,
    public IDispEventSimpleImpl<3,CFPAnt,&__uuidof(Office::_CommandBarButtonEvents)>
    {
    //type defination to avoid compilation 'ambigous call' errors
    typedef IDispEventSimpleImpl</*nID =*/ 1,
    CFPAnt, &__uuidof(Office::_CommandBarButtonEvents)> ExportCHMEvents;
    typedef IDispEventSimpleImpl</*nID =*/ 2,
    CFPAnt, &__uuidof(Office::_CommandBarButtonEvents)> ImportCHMEvents;
    typedef IDispEventSimpleImpl</*nID =*/ 3,
    CFPAnt, &__uuidof(Office::_CommandBarButtonEvents)> OptionEvents;
    CFPAnt()
    {
    AfxSetResourceHandle(_Module.GetModuleInstance());
    USES_CONVERSION;
    UINT nResID[CommandIndexMax]={IDS_EXPORT_CHM,IDS_IMPORT_CHM,IDS_OPTION};
    CString str,strsub;
    for(int i=0;i<CommandIndexMax;i++)
    {
    str.LoadString(nResID[i]);
    AfxExtractSubString(strsub,str,0,_T('\n'));
    m_bstrCaption[i] =T2OLE((LPCTSTR)strsub);
    AfxExtractSubString(strsub,str,1,_T('\n'));
    m_bstrTipText[i] =T2OLE((LPCTSTR)strsub);
    AfxExtractSubString(strsub,str,2,_T('\n'));
    m_bstrTag[i] =T2OLE((LPCTSTR)strsub); }
    }
    STDMETHOD(OnDisconnection)(AddInDesignerObjects::ext_DisconnectMode RemoveMode, SAFEARRAY * * custom)
    {
    ExportCHMEvents::DispEventUnadvise((IDispatch*)m_spCmdButtons[CommandIndexExportCHM]);
    ImportCHMEvents::DispEventUnadvise((IDispatch*)m_spCmdButtons[CommandIndexImportCHM]);
    OptionEvents::DispEventUnadvise((IDispatch*)m_spCmdButtons[CommandIndexOption]);
    for(int i=0;i<CommandIndexMax;i++)
    {
    m_spCmdButtons[i].Release();
    }
    m_spApp.Release();
    return S_OK;
    }
    BEGIN_SINK_MAP(CFPAnt)
    SINK_ENTRY_INFO(1, __uuidof(Office::_CommandBarButtonEvents),
    /*dispid*/0x01, OnClickButtonExportCHM, &OnClickButtonInfo)
    SINK_ENTRY_INFO(2, __uuidof(Office::_CommandBarButtonEvents),
    /*dispid*/0x01, OnClickButtonImportCHM, &OnClickButtonInfo)
    SINK_ENTRY_INFO(3, __uuidof(Office::_CommandBarButtonEvents),
    /*dispid*/0x01, OnClickButtonOption, &OnClickButtonInfo)
    END_SINK_MAP()
      

  3.   

    对于第一个问题,举个简单例子例如一个outlook的add-in,对于每个新打开的 inspector  ,加一个button到工具栏。
    如果打开多个 inspector ,就有多个button。建立第一个button的时候,使用 DispEventAdvise 给button建立接收命令的连接
    建立第二个button的时候,我先使用DispEventUnadvise 给第一个button断开连接,然后给第二个button用DispEventAdvise 建立事件连接。
    这个时候,虽然第一个button看似已经断开连接,不过点击那个button,还是可以接受到消息的。请问这是为什么?ps ATL的书我一本都买不到,感觉ATL是不是过时了,我才刚刚开始学习!
      

  4.   

    谢谢yjyzxyjy(星星) 和蒋老大的例子,不过我的程序是多个button共用同一个处理函数,情况有点不一样