IDispEventImplDbg
cheztabor
Last Updated January 31, 2001

www.cheztabor.com | tltabor@nyc.rr.com
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.

Use

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);
...

Download

dumpauto.zip (5k).

Changes January 31, 2001

License

Copyright© 2001 Tim Tabor. All rights reserved. No warrantees extended.

Contact

Please report bugs and feature requests to me.

Enjoy.

Tim Tabor