Version 14 of COM Events

Updated 2011-09-07 08:07:34 by dkf

[... COM; comparison with Tcl events; ...]

Three extensions that traffic in COM events are twapi, optcl and tcom. A "COM type library" defines COM events--roughly. Chin Huang writes, "If the application provides a type library, the class declaration for the application object may list them. For example, let's examine the type library for Internet Explorer using the type library viewer in OLE View ["OLE Object Viewer"]. Select menu item File -> View TypeLib... In the Open dialog, select the file SHDOCVW.DLL in the %WINDIR%\system32 directory.

The class declaration for the Internet Explorer application is

    coclass InternetExplorer {                                                      
        [default] interface IWebBrowser2;                                           
        interface IWebBrowserApp;                                                   
        [default, source] dispinterface DWebBrowserEvents2;                         
        [source] dispinterface DWebBrowserEvents;                                   
    };                                                                              

The [source] attribute marks interfaces that an object must implement in order to receive events from the application. The interface marked [default, source] indicates an interface that an event listener would choose by default. Each interface has an interface identifier (IID). This is the IID refered to in the tcom manual [L1 ].

Each source interface declares a set of methods. Each method corresponds to an event. To fire an event, the application invokes the corresponding method on the listener object.

So getting the class declaration is key to finding the events an application can send. If you're lucky, the application may implement the IProvideClassInfo interface, which provides exactly this information."


Here's an example of tcom usage with IE:

package require tcom

proc sink {eventName args} {
    puts "$eventName $args"
}

set application_name InternetExplorer.Application
if {[catch {
    set application [::tcom::ref getactiveobject $application_name]
}]} {
    set application [::tcom::ref createobject $application_name]
}
::tcom::bind $application sink
$application Visible 1
vwait forever

As one uses IE, a process executing this script churns out lots of reports:

    OnVisible 1
    StatusTextChange Done
        ...
    StatusTextChange Done
    CommandStateChange -1 0
        ...
    CommandStateChange -1 0
    StatusTextChange Done
    DownloadBegin
    ProgressChange 100 10000
        ....
    PropertyChange {{265b75c0-4158-11d0-90f6-00c04fd497ea}}
    PropertyChange {{265b75c1-4158-11d0-90f6-00c04fd497ea}}    PropertyChange {{118D6040-8494-11d2-BBFE-0060977B464C}}
    PropertyChange {{04AED800-8494-11d2-BBFE-0060977B464C}}
    StatusTextChange {}
    StatusTextChange {}
    StatusTextChange {}
    NavigateComplete2 ::tcom::handle0x008AF518 http://PAGE3
    StatusTextChange Done
    ProgressChange 10000 10000
    ProgressChange -1 10000
    DownloadComplete 
    TitleChange {TITLE3}
    StatusTextChange {HEAD3}
    ProgressChange 10000 10000
    DocumentComplete ::tcom::handle0x008CE880 http://PAGE3
       ...

Note that, while IE is a good application for this sort of demonstration, with an interesting object model, it also presents several problems. One, apparently, is that other applications share object models with it, and this demonstration appears to behave erratically when other applications are open. There's probably a more complete and succinct description of the behavior. For a start, though, run the script with only the Tcl instance and IE active.

To qualify the binding, something like

tcom::import "$env(WINDIR)/system32/SHDocVw.dll"
set browserEvents [::tcom::info interface ::SHDocVw::DWebBrowserEvents2]
set iid [$browserEvents iid]
# [$browserEvents methods] shows eventNames, among other things.
tcom::bind $application sink $iid

is necessary.


See Handling WMI events using TWAPI for examples of COM event handling with TWAPI.