Handling Com Events in Python (was Python and Windows Scripting Host)

Alex Martelli alex at magenta.com
Fri Aug 11 11:35:04 EDT 2000


"Mark Hammond" <MarkH at ActiveState.com> wrote in message
news:DHHk5.1080$gP5.11250 at news-server.bigpond.net.au...
> > I'd like to understand why the REAL OnDocumentComplete does not
> > happen, if Mark Hammond or somebody else who is really an expert
> > can explain (& maybe help us find a better workaround...?),
>
> NFI.  Do we have proof that IE actually fires it?  Maybe it only does
> on idle, or something strange?

Fair enough!  So I whipped out my old trusty AuHelp.Listener object
(one can hardly develop general-purpose COM event handling
mechanisms without such a generic listener to help keep track of
the players...) and reproduced the situation in C++.  Here's the
output...:

Caught innocuous com error: The object invoked has disconnected from its
clients.
Seen 89 events:
112 250 106 112 105 105 254 105 102 108 102 102 108 102 102 270 104 102 105
105
108 106 102 102 102 105 113 252 102 108 108 104 113 102 108 259 108 105 105
108
105 102 108 108 102 102 105 102 102 105 102 102 105 105 102 250 102 106 105
113
108 112 112 112 112 102 252 102 102 108 108 104 113 102 108 259 105 105 105
108
108 102 102 102 102 105 102 105 253
Press any key to continue

DocumentComplete is the event of id 259.  As we can see, it happens
twice, just as predicted.  You can check dispinterface IWebBrowserEvents2
in shdocvw.dll ("Microsoft Interrnet Controls" being the tlb's displayname)
for the other various codes (253, hex fd in OleView, is the Quit event of
course).

I can send, and/or place somewhere downloadable, the Auhelp.Listener
DLL and/or the little console EXE I use to test Internet Explorer's events
here.  But there's nothing surprising about it: it gets an object reference,
gets its iconnectionpointcontainer, enums the connection points, gets
the very first one, fakes the queryinterface to say it supports that source
interface's IID, advises to it, implements Invoke to just stash away the
event's dispid in an array, returns that array when queried by the driving
application.  A couple hours' worth of ATL/VC++ coding, at most.


> > but even
> > more I'd like to do something about the *Before* events -- and in
> > particular to understand how, assuming I manage to get them called,
> > I can use their input/output Cancel argument: there seems to be no
>
> All BYREF args can be returned.  In the case of a "void" function with
> a single byref, you simply return the new value for this byref.

Ah yes, I _had_ read about it somewhere -- that this is how you
map [out] args (and a good idea too!); I should have thought that
it would apply to [in, out] as well.  Thanks!


> From the tutorial I gave at the last conference (powerpoint slides
> available from my starship page):

I briefly looked around but can't find it -- got the URL please...?

> # Demonstrate COM events using Excel
> class ExcelEvents:
>     def OnSheetBeforeDoubleClick(self, Sh, Target, Cancel):
>         if Target.Column % 2 == 0:
>             print "You can double-click there..."
>             Cancel = 0 # Not setting the ByRef here!
>         else:
>             print "You can not double-click there..."
>             Cancel = 1
>         # This function is a void, so the result ends up in
>         # the only ByRef - Cancel.
>         return Cancel


Alex






More information about the Python-list mailing list