Re: HOWTO set up minimal sink object in console COM client?
From: Alexander Nickolov (agnickolov_at_mvps.org)
Date: 03/10/05
- Next message: TxITGuy: "ATL component freezes after destructor"
- Previous message: Alexander Nickolov: "Re: Possibel to Store Image into an Object's Property?"
- In reply to: Mateusz Qoskot?=: "Re: HOWTO set up minimal sink object in console COM client?"
- Next in thread: Mateusz Qoskot?=: "Re: HOWTO set up minimal sink object in console COM client?"
- Reply: Mateusz Qoskot?=: "Re: HOWTO set up minimal sink object in console COM client?"
- Messages sorted by: [ date ] [ thread ]
Date: Thu, 10 Mar 2005 09:52:29 -0800
My post was mainly about regular COM interface sinks.
You can instantiate a class derived from IDispEventImpl
any way you want. And, yes, the sink is a COM object,
usually private, e.g. not publicly creatable (no class factory).
In case of IDispEvent[Simple]Impl the COM object is
entirely contained within the base class - an exampe where
you might have multiple COM objects in a single class (if
you derive multiple times from IDispEventImpl - each
derivation adds a sink - a COM object).
-- ===================================== Alexander Nickolov Microsoft MVP [VC], MCSD email: agnickolov@mvps.org MVP VC FAQ: http://www.mvps.org/vcfaq ===================================== "Mateusz Łoskot" <mateusz@loskot.net> wrote in message news:%234BO%23NSJFHA.3596@TK2MSFTNGP14.phx.gbl... > > > Hi, > > Thank you Alexander for your help. > Below I'm trying to explaining what I've done already. > > Please, let me to add a little explanation related to my objectives. > Here is my MyObject declaration: > > class ATL_NO_VTABLE CMyObject : > public CWindowImpl<CMyObject>, > public CComObjectRootEx<CComSingleThreadModel>, > public CComCoClass<CMyObject, &CLSID_MyObject>, > public ISupportErrorInfo, > public IConnectionPointContainerImpl<CMyObject>, > public CProxy_IMyObjectEvents<CMyObject>, > public IDispatchImpl<IMyObject, &IID_IMyObject, &LIBID_MYOBJECTLib, > /*wMajor =*/ 1, /*wMinor =*/ 0> > { > // .... > STDMETHOD(StartLongTask)(void); // creates worker thread > }; > > I create worker thread in StartLongTask call (I use _beginthreadex) > so I derive my CMyObject from CWindowImpl because I want to be able to > PostMessage from Thread Procedure to the COM Object in order to fire > events to client. > This is a simple architecture based on the Microsoft solution presented > in this article: > > http://support.microsoft.com/kb/q196026/ > > So, my console based COM object client should be able to response to > events fired > by the COM object above, the same way as VB client does. > > In article <ezqqRd0IFHA.1996@TK2MSFTNGP12.phx.gbl> Alexander Nickolov > wrote: >> You start a regular console project, then add minimal ATL >> support - atlbase.h and atlcom.h, with the _Module in between >> in ATL3 (ATL7 doesn't need it anymore). > > Yes, I have it declared in stdafx.h of my client project: > > #include <atlbase.h> > extern CComModule _Module; // declared in main.cpp of the client > #include <atlcom.h> > > Then in main.cpp file of my client (there is also _tmain app entry > point) > I have _Module and object map declared: > > CComModule _Module; > BEGIN_OBJECT_MAP(ObjectMap) // intencionally left empty > END_OBJECT_MAP() > > >> Then depending >> on the type of event interface you are suing you either need >> IDispEvent[Simpel]Impl for a dispinterface, or a simle ATL >> object for a COM interface. For the latter you need to derive >> from CComObjectRootEx<CComXxxThreadModel> and >> the event interface you are implementing, then add an interface >> map with that interface, and finally implement the interface >> itself. > > So, does it mean sink object is always COM object? > I think so but I'd like to be sure :-) > > OK, here is my versiom - dispinterface based (MyObject is main COM > object). > My MYOBJECT.idl contains source interface declared as follows: > > dispinterface _IMyObjectEvents > { > // metthods > [id(1)] HRESULT OnTaskStarted([in] long Counter); > } > > Then my sink class is declared this way: > > class CEventHandler : > public IDispEventImpl<0, CEventHandler, &DIID__IMyObjectEvents, > &LIBID_MYOBJECTLib, 1, 0> > { > void __stdcall OnTaskStarted(long counter) > { g_bFinish = true; // event handled - set global flag } > BEGIN_SINK_MAP(CEventHandler) > SINK_ENTRY_EX(0, DIID__IMyObjectEvents, 1, OnTaskStarted) > END_SINK_MAP() > }; > >> You use AtlAdvise/AtlUnadvise to attach/detach your >> sink object (for the dispinterface sink you use DispEventAdvise >> instead). > > Yes, I use DispEventAdvise as my sink is derived > from IDispEventImpl and dispinterface. > >> You use CComObject<your_sink>::CreateInstance >> to create an instance of your sink object. >> Beware your object >> has refernce count of zeor when created so you should imediately >> AddRef and Release after finished advising (to take care of >> proper disposal in case of failure). >> Use GetUnknown() to get >> your sink object's IUnknown pointer (to pass to AtlAdvise). >> > > Hm, in one of examples on m.p.vc.atl group I found object creation > using "new" operator withouth any refs counting (add/relese) like this: > > CEventHandler * pSink = new CEventHandler(); > pSink->DispEventAdvise(spUnk); > > But it seems very suspicious to me. > So, now I know I have to create sink object as common COM object > in COM way. Right? > > OK, thanks for giving me such great light to my COM knowledge :-) > > Below I put my _tmain() function of my console-basd COM client. > I have one more problem with message map > Could you be so kind and review my code below and explain > things marked in comments? > > // COM _Module declared above > // COM object map declared above > // > int _tmain(int argc, _TCHAR* argv[]) > { > // globals > g_hInstance = NULL; > g_bFinish = FALSE; > > std::cout << "INITIALIZE" << std::endl; > > // ##### Here I use COINIT_MULTITHREADED, is that correct for my COM > // object above? > // I think I could use apartment too, right? > HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); > _ASSERTE(SUCCEEDED(hr)); > > { // start of COM object life block > > std::cout << " INIT" << std::endl; > g_hInstance = ::GetModuleHandle(NULL); > _Module.Init(ObjectMap, g_hInstance, &GUID_NULL); > > IMyObjectPtr spMyObj; > spMyObj.CreateInstance(CLSID_MyObject); > IUnknownPtr spUnk = spMyObj; > > //CEventHandler * pSink = new CEventHandler(); // > CComObject<CEventHandler> * pSink; > hr = CComObject<CEventHandler>::CreateInstance(&pSink) > _ASSERTE(SUCCEEDED(hr)); > > pSink->AddRef(); > pSink->DispEventAdvise(spUnk); > > std::cout << " TASK" << std::endl; > spMyObj->StartLongTask(); // creates worker thread > > // ##### Here is my problem, when I uncomment > // all those *Message calls, this loop hangs in > // GetMessage. I'm really confused if I should use real message > // loop here, should I? This is console app, so it has no window :-) > // but COM object has its own message loop implemented by CWindowImpl > // so I think here should be only non-message-loop waiting for > // flag set by event handler (waiting for event). > // Is it good solution? > > MSG msg; > while (!g_bFinish) // && GetMessage(&msg, NULL, 0, 0)) > { > //TranslateMessage(&msg); > if (g_bFinish) // event handler sets this flag > std::cout << " FINISH" << std::endl; > //DispatchMessage(&msg); > } > > pSink->DispEventUnadvise(spUnk); > pSink->Release(); > std::cout << " END" << std::endl; > > _Module.Term(); > std::cout << " TERM" << std::endl; > > } // end of COM object life block > > ::CoUninitialize(); > std::cout << "UNINITIALIZE" << std::endl; > > return 0; > } // end of _tmain() > > > Uff, that was my another long post on this group> > Thank you very much for your help. > > Greets > > -- > > Mateusz Łoskot > e-mail: mateusz at loskot dot net > www: http://loskot.net/about/contact/ >
- Next message: TxITGuy: "ATL component freezes after destructor"
- Previous message: Alexander Nickolov: "Re: Possibel to Store Image into an Object's Property?"
- In reply to: Mateusz Qoskot?=: "Re: HOWTO set up minimal sink object in console COM client?"
- Next in thread: Mateusz Qoskot?=: "Re: HOWTO set up minimal sink object in console COM client?"
- Reply: Mateusz Qoskot?=: "Re: HOWTO set up minimal sink object in console COM client?"
- Messages sorted by: [ date ] [ thread ]