Use | Download | Changes | License | Contact
IDispEventImpl makes me nuts. Some of the problems with the class have been documented:
Q237771 - BUG: Events Fail in ATL Containers when Enum Used as Event Parameter
Q241810 - BUG: IDispEventImpl Event Handlers May Give Strange Values for Parameters
Q244204 - BUG: ATL Events Don't Fire If Defined With Interface Alias
But still, it's nice to get in there and see what's going on. So I wrote a wrapper called IDispEventImplDbg. One additional ATL bug I've found with my debug wrapper involves the handling of typedef-ed parameters. In <atlcom.h>, the following fragment from GetUserDefinedType will fail with an E_INVALIDARG if the parameter is a typedef (even after correcting the bug described in Q77731).
if(pta && pta->typekind == TKIND_ALIAS)
{
if (pta->tdescAlias.vt == VT_USERDEFINED)
GetUserDefinedType(spTypeInfo,pta->tdescAlias.hreftype);
else
vt = pta->tdescAlias.vt;
}
This code needs to be changed to:
if (pta && pta->typekind == TKIND_ALIAS)
{
if (pta->tdescAlias.vt == VT_USERDEFINED)
return GetUserDefinedType(spTypeInfo,pta->tdescAlias.hreftype);
else
vt = pta->tdescAlias.vt;
}
In addition to finding bugs in ATL, I've used the wrapper for:
Now that I have a pretty good understanding about IDispEventImpl's shortcomings, I don't use it that much. Sometimes I use IDispEventSimpleImpl, which avoids some trips to the typelib and gives me better control of the parameter typing for Invoke. And sometimes I use the excellent technique developed by Developmentor's Jason Whittington and described in his article Doing away with IDispEventImpl.
IDispEventImplDbg takes the same template parameters as the underlying Impl, so you set it up like this:
#include "dumpauto.h"
class CMainFrame;
typedef IDispEventImplDbg<1, CMainFrame, &DIID_DWebBrowserEvents2,
&LIBID_SHDocVw, 1, 0> CWB2Events;
class CMainFrame : public CFrameWindowImpl,
public CWB2Events
{
...
And then run the client in the debugger. The first thing you'll see in the output window is a dump of the source interface. Note that these are the signatures from the typelib, not the signatures of your actual handlers. If your handlers don't look like these, perhaps they should. Keep in mind that if you're #import-ing a typelib, that the registered typelib rather than the imported typelib drives IDispEventImpl.
--> SHDocVw(1.1)::DWebBrowserEvents2 <-- Desc: Microsoft Internet Controls Path: C:\WINNT\System32\shdocvw.dll [id(0x00000066)] void __stdcall StatusTextChange(BSTR Text); [id(0x0000006c)] void __stdcall ProgressChange(long Progress, long ProgressMax); [id(0x00000069)] void __stdcall CommandStateChange(long Command, VARIANT_BOOL Enable); [id(0x0000006a)] void __stdcall DownloadBegin(); ...
Then, you'll see the events fire. For each event, you'll see:
[id(0x00000068)]
typelib - [noargs]
Invoke - [noargs]
handler - void __stdcall DownloadComplete();
[id(0x00000066)]
typelib - VT_BSTR:BSTR
Invoke - VT_BSTR:BSTR
handler - void __stdcall StatusTextChange(BSTR Text);
[id(0x0000006c)]
typelib - VT_I4:long, VT_I4:long
Invoke - VT_I4:long, VT_I4:long
handler - void __stdcall ProgressChange(long Progress, long ProgressMax);
...
dumpauto.zip (5k).
Changes January 31, 2001
Enjoy.