Sign in to follow this  
Juergen_80

COM Connection Points: Problem to call an function out of an sink class

Recommended Posts

Hi All, I’m an absolutely newbie in the COM technology and I have a little tricky question. I hope there’s someone out there who can help me with my problem. I have an .idl / .h / .c file and I integrated them in my VisualStudio 2005 C++ project. After that I’ve searched on the MSDN Library how I can connect an COM Server from my project. I’ve found a little example (http://msdn.microsoft.com/en-us/magazine/cc163361.aspx) and tried to do it on the same way. I’ve created an Csink class and tried to create an instance of this sink object to pass to the server. Now I want to call an function „ OnShowMessageDlg “ out of this Csink class and after that I’ll become the following error message from my compiler: Linker error: LNK2001: unresolved external symbol public: __thiscall ""public: void __thiscall CSink::OnShowMessageDlg(struct IMsgDlg *,short *)" (?OnShowMessageDlg@CSink@@QAEXPAUIMsgDlg@@PAF@Z)". Can someone give me a hint what there could be wrong? Or what I must do to use these function? Is the .idl file and the .h file correct? I didn’t find the functions OnShowMessageDlg and OnConfigurationApply in the .h file? I know, this should be basics I must know. I hope the two books I’ve ordered will arrive as soon as possible. Please let me know if you need any other information. Thanks for ANY help. Juergen ************************************************************************************************* .idl file . . . // TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046} importlib("stdole2.tlb"); // Forward declare all types defined in this typelib interface ITEST2; dispinterface ITESTEvents; . . . [ uuid(6775FB91-B5BE-11D6-A996-0050BA24C7B9), version(1.1), helpstring("Event dispatch interface for TEST") ] dispinterface ITESTEvents { properties: methods: [id(0x00000001)] void OnConfigurationApply([in, out] VARIANT_BOOL* pAccept); [id(0x00000002)] void OnShowMessageDlg( [in] IMsgDlg* pIMsg, [out, retval] VARIANT_BOOL* Result); }; . . . . coclass TESTv2 { [default] interface ITEST2; [default, source] dispinterface ITESTEvents; }; ************************************************************************************************* .h file . . . EXTERN_C const IID DIID_ITESTEvents; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("6775FB91-B5BE-11D6-A996-0050BA24C7B9") ITESTEvents : public IDispatch { }; #else /* C style interface */ typedef struct ITESTEventsVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ITESTEvents * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppvObject); . . . ************************************************************************************************* .c file . . . MIDL_DEFINE_GUID(IID, IID_ITEST2,0xF560F761,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9); MIDL_DEFINE_GUID(IID, DIID_ITESTEvents,0x6775FB91,0xB5BE,0x11D6,0xA9,0x96,0x00,0x50,0xBA,0x24,0xC7,0xB9); MIDL_DEFINE_GUID(CLSID, CLSID_TESTv2,0xF560F763,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9); . . . ************************************************************************************************* .c++ file class CSink : public ITESTEvents { public: CSink::CSink() {m_cRef = 0;} CSink::~CSink() {} HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) { *ppvObject = NULL; if (IsEqualGUID(riid, IID_IUnknown)) *ppvObject = reinterpret_cast<void **> (this); if (IsEqualGUID(riid, DIID_ITESTEvents)) *ppvObject = reinterpret_cast<void **> (this); if (*ppvObject) { ((IUnknown*)*ppvObject)->AddRef(); return S_OK; } else return E_NOINTERFACE; } DWORD __stdcall AddRef() { return InterlockedIncrement(&m_cRef); } DWORD __stdcall Release() { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return m_cRef; } STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo) { return E_NOTIMPL; } STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo) { return E_NOTIMPL; } STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId) { return S_OK; } STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO * pExcepInfo, UINT * puArgErr) { return S_OK; } public: void OnConfigurationApply(VARIANT_BOOL *pAccept); void OnShowMessageDlg(IMsgDlg *pIMsg, VARIANT_BOOL *Result); private: DISPID m_id; long m_cRef; }; void main(){ . . . CComPtr<ITEST2> tTEST; HRESULT hr; hr = CoInitialize(0); if(FAILED(hr)){ CoUninitialize(); return false; } hr = CoCreateInstance(CLSID_TESTv2, 0, CLSCTX_LOCAL_SERVER, IID_ITEST2, (void**)&tTEST); IConnectionPointContainer * ICPointContainer; hr = tTEST->QueryInterface(IID_IConnectionPointContainer,(void **)&ICPointContainer); if(SUCCEEDED(hr)){ //CComPtr<IConnectionPoint> ICPoint; hr = ICPointContainer->FindConnectionPoint(DIID_ITESTEvents, &ICPoint); if(SUCCEEDED(hr)){ ICPointContainer->Release(); CSink *pSink; IUnknown *pSinkUnk; pSink = new CSink; hr = pSink->QueryInterface (IID_IUnknown,(void **)&pSinkUnk); hr = ICPoint->Advise(pSinkUnk,&dwAdvise); VARIANT_BOOL *tDLGResult; pSink->AddRef(); pSink->OnShowMessageDlg(tMsgDlg, tDLGResult); // ERROR MESSAGE . . } *************************************************************************************************

Share this post


Link to post
Share on other sites
Hm, in your code I saw only the declaration of that callback-method:

class CSink : public ITESTEvents
{
public:
CSink::CSink() {m_cRef = 0;}
CSink::~CSink() {}

HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject)
{
*ppvObject = NULL;

if (IsEqualGUID(riid, IID_IUnknown))
*ppvObject = reinterpret_cast<void **> (this);

if (IsEqualGUID(riid, DIID_ITESTEvents))
*ppvObject = reinterpret_cast<void **> (this);

if (*ppvObject)
{
((IUnknown*)*ppvObject)->AddRef();
return S_OK;
}
else return E_NOINTERFACE;
}

DWORD __stdcall AddRef()
{
return InterlockedIncrement(&m_cRef);
}

DWORD __stdcall Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}

STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo){ return E_NOTIMPL; }
STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid,ITypeInfo FAR* FAR* ppTInfo)
{ return E_NOTIMPL; }
STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames,
unsigned int cNames, LCID lcid, DISPID FAR* rgDispId)
{ return S_OK; }
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO * pExcepInfo, UINT * puArgErr)
{
return S_OK;
}

public:
void OnConfigurationApply(VARIANT_BOOL *pAccept);

// -> Only declared, but no method body
void OnShowMessageDlg(IMsgDlg *pIMsg, VARIANT_BOOL *Result);

private:
DISPID m_id;
long m_cRef;
};




Are you sure you have an implementation for this?

Kimmi

P.S.:
You can use the code tags: FAQ about code tags.

Share this post


Link to post
Share on other sites
I thought the message body is in the COM Server and I can call this function from the COM Server? In the .idl file you can see this OnShowMessageDlg function? How can I call this function? This is what I need. I thought this is the way to do that?

Share this post


Link to post
Share on other sites
In your code you are creating a new instance from your class CSink and after a while you are trying to call OnShowMessageDlg. So you have to implement this method in your class definition, too.

In your IDL file you are just declaring a COM-compatible interface. Here you will not find any implementations. Its a way for COM to call your stuff from different languages like VisualBasic for instance.

Kimmi

Share this post


Link to post
Share on other sites
I've read your hint with the tags and will do that if I post once more some code. Thanks. :-).


OK, please forget the code out of the c++ file for a moment. I'll try to explain what I need. Maybe I'm on the wrong way??


I've got from an .exe file the .idl/.h / .c files. With these files I can now create an Instance

CComPtr<ITEST2> tTEST;
HRESULT hr;
hr = CoInitialize(0);
if(FAILED(hr)){
CoUninitialize();
return false;
}

hr = CoCreateInstance(CLSID_TESTv2, 0, CLSCTX_LOCAL_SERVER, IID_ITEST2, (void**)&tTEST);


and with tTEST I can call directly some functions(to open an program(.exe) and do something in it). This works perfect.

My problem now is that this program (.exe file / the com server) opens sometimes an dialog and I don't want that. To prevent now that this dialog will come up there is an Event OnShowMessageDlg with that I can do that. And because of that I must find a way to call this event. I don't know if I'm on the correct way to do that? Maybe you can give me some help?

Share this post


Link to post
Share on other sites
You can try to connect your own EventSink, implement the Invoke-method and return False ( or something similar to kill the message, which opened the Dialog ) to catch that event. I tried something similar to catch events from an Internet-Explorer and it worked.
And you can also try to install your own Hook ( just search for Hooks Windows ) to catch that event, if its supported. But I haven't done this for a COM-Application.

Good luck!

Kimmi

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this