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 .
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."
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.