COM Events

I created a control based on the DispServ ATL example. I want to extend it so that the client control is both a source for events as well as a receiver. I think I've done everything correctly but when I attempt to compile the client control, the compiler fails with the following:

------ Build started: Project: HandlerClient, Configuration: Debug Win32 ------

Compiling...

HandlerCtl.cpp

c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlcom.h(1792) : error C2259: 'ATL::CComObject<Base>' : cannot instantiate abstract class

with

[

Base=CHandlerCtl

]

due to following members:

'HRESULT ATL::__EventHandlerProxy::__eventHandlerProxy(int,...)' : is abstract

c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlevent.h(177) : see declaration of 'ATL::__EventHandlerProxy::__eventHandlerProxy'

c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlcom.h(1781) : while compiling class template member function 'HRESULT ATL::CComCreator<T1>::CreateInstance(void *,const IID &,LPVOID *)'

with

[

T1=ATL::CComObject<CHandlerCtl>

]

c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlcom.h(1872) : see reference to class template instantiation 'ATL::CComCreator<T1>' being compiled

with

[

T1=ATL::CComObject<CHandlerCtl>

]

c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlcom.h(1868) : while compiling class template member function 'HRESULT ATL::CComCreator2<T1,T2>::CreateInstance(void *,const IID &,LPVOID *)'

with

[

T1=ATL::CComCreator<ATL::CComObject<CHandlerCtl>>,

T2=ATL::CComCreator<ATL::CComAggObject<CHandlerCtl>>

]

*c:\dna2\apps\temphandlercontroller\handlerclient\debug\handlerctl.inj:5(6) : see reference to class template instantiation 'ATL::CComCreator2<T1,T2>' being compiled

with

[

T1=ATL::CComCreator<ATL::CComObject<CHandlerCtl>>,

T2=ATL::CComCreator<ATL::CComAggObject<CHandlerCtl>>

]

Build log was saved at "file://c:\dna2\Apps\TempHandlerController\HandlerClient\Debug\BuildLog.htm"

HandlerClient - 1 error(s), 0 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Furthermore, If I attempt to add methods to my client control event interface, the compiler complains that they are undefined but they're not. They're implemented within the class definition. Also, adding events to the client control method interface results in them being declared as unimplmented abstract methods even though they too are implemented within the class declaration in the CClientCtl.h file.

Is it incorrect to try to have a control that has both event_receiver(com) and event_source(com) declared

Help! - spd3001




Answer this question

COM Events

  • Vincent D. - Nolme Informatique

    This forum is for general C++ compiler and IDE issues. For Win32 programming issues, please post your question in one of the MSDN discussion groups. In particular:

    http://msdn.microsoft.com/newsgroups/default.aspx dg=microsoft.public.win32.programmer.ole&lang=en&cr=US


  • BCras

    Here's the client code that won't compile. Everything else is just like the DispSink example except for the necessary corrections (check attributes box for server and client as it's not really the default). The sample project can be found at :

    ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vclib/html/6c3d27a6-80d3-4a80-833c-aa8b19487632.htm

    **********************************************

    // MyDispCtl.h : Declaration of the CMyDispCtl

    #pragma once

    #include "resource.h" // main symbols

    #include <atlctl.h>

    #import "progid:MyDispServer.MyDispServ.1" embedded_idl, no_namespace

    #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)

    #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."

    #endif

    // IMyDispCtl

    [

    object,

    uuid(787EDBCA-7FA3-4375-9214-A4C3979AA6F0),

    dual,

    helpstring("IMyDispCtl Interface"),

    pointer_default(unique)

    ]

    __interface IMyDispCtl : public IDispatch

    {

    [id(1), helpstring("method Connect")] HRESULT Connect();

    [id(2), helpstring("method Disconnect")] HRESULT Disconnect();

    [id(3), helpstring("method Send")] HRESULT Send(VARIANT data);

    };

    // _IMyDispCtlEvents

    [

    uuid("FDA3A9A2-FD09-458D-A360-8DECD4186B89"),

    dispinterface,

    helpstring("_IMyDispCtlEvents Interface")

    ]

    __interface _IMyDispCtlEvents

    {

    };

    // CMyDispCtl

    [

    coclass,

    control,

    default(IMyDispCtl, _IMyDispCtlEvents),

    threading(single),

    vi_progid("MyDispClient.MyDispCtl"),

    progid("MyDispClient.MyDispCtl.1"),

    version(1.0),

    uuid("8CE77369-8959-4FFE-8E83-DD8F7FC64C7E"),

    helpstring("MyDispCtl Class"),

    event_source(com),

    registration_script("control.rgs"),

    event_receiver(com)

    ]

    class ATL_NO_VTABLE CMyDispCtl :

    public IMyDispCtl,

    public IPersistStreamInitImpl<CMyDispCtl>,

    public IOleControlImpl<CMyDispCtl>,

    public IOleObjectImpl<CMyDispCtl>,

    public IOleInPlaceActiveObjectImpl<CMyDispCtl>,

    public IViewObjectExImpl<CMyDispCtl>,

    public IOleInPlaceObjectWindowlessImpl<CMyDispCtl>,

    #ifndef _WIN32_WCE

    public IDataObjectImpl<CMyDispCtl>,

    #endif

    #ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly

    public IObjectSafetyImpl<CMyDispCtl, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,

    #endif

    public CComControl<CMyDispCtl>

    {

    public:

    CMyDispCtl()

    {

    m_bConnected = false;

    m_OutText = L"Not connected";

    }

    ~CMyDispCtl()

    {

    Disconnect();

    }

    DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |

    OLEMISC_CANTLINKINSIDE |

    OLEMISC_INSIDEOUT |

    OLEMISC_ACTIVATEWHENVISIBLE |

    OLEMISC_SETCLIENTSITEFIRST

    )

    BEGIN_PROP_MAP(CMyDispCtl)

    PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)

    PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)

    // Example entries

    // PROP_ENTRY("Property Description", dispid, clsid)

    // PROP_PAGE(CLSID_StockColorPage)

    END_PROP_MAP()

    BEGIN_MSG_MAP(CMyDispCtl)

    CHAIN_MSG_MAP(CComControl<CMyDispCtl>)

    DEFAULT_REFLECTION_HANDLER()

    END_MSG_MAP()

    // Handler prototypes:

    // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

    // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);

    // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

    __event __interface _IMyDispCtlEvents;

    // IViewObjectEx

    DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

    // IMyDispCtl

    public:

    HRESULT OnDraw(ATL_DRAWINFO& di)

    {

    USES_CONVERSION;

    LPCTSTR text = OLE2CT(m_OutText.bstrVal);

    RECT& rc = *(RECT*)di.prcBounds;

    Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);

    SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);

    TextOut(di.hdcDraw,

    (rc.left + rc.right) / 2,

    (rc.top + rc.bottom) / 2,

    text,

    lstrlen(text));

    return S_OK;

    }

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()

    {

    return S_OK;

    }

    void FinalRelease()

    {

    }

    private:

    // Data

    bool m_bConnected;

    CComPtr<IMyDispServ> m_spIServ;

    CComVariant m_OutText;

    public:

    HRESULT Connect()

    {

    HRESULT hr;

    hr = m_spIServ.CoCreateInstance(__uuidof(CMyDispServ));

    if (SUCCEEDED(hr))

    {

    hr = __hook(&_IMyDispServEvents::Transfer, m_spIServ, &CMyDispCtl::OnTransmit);

    }

    if (hr == S_OK)

    {

    m_bConnected = true;

    m_OutText = L"Connected";

    }

    FireViewChange();

    return(hr);

    }

    HRESULT Disconnect()

    {

    if (m_bConnected)

    {

    HRESULT hr = __unhook(&_IMyDispServEvents::Transfer, m_spIServ, &CMyDispCtl::OnTransmit);

    if (SUCCEEDED(hr))

    {

    m_spIServ.Release();

    m_bConnected = false;

    m_OutText = L"Not connected";

    }

    FireViewChange();

    return(hr);

    }

    return(S_OK);

    }

    HRESULT OnTransmit(VARIANT data)

    {

    if (data.vt == VT_BSTR)

    m_OutText = data;

    FireViewChange();

    return(S_OK);

    }

    HRESULT Send(VARIANT data)

    {

    if (m_bConnected)

    m_spIServ->Send(data);

    return(S_OK);

    }

    };



  • Learning WPF

    I just wanted to add, I'm trying to do this in C++ with MVS 2005 Standard Edition. - spd3001

  • COM Events