Win32: ByRef equivalent in pythoncom for function callbacks?

Mike Fletcher mfletch at tpresence.com
Fri Oct 6 03:01:36 EDT 2000


Okay, I've spent a bit of time trying to do this right with "for demand" to
make a quick demo for DOM access via IE, and I got it working for two or
three runs.  Then somehow the world went screwy and the same code stopped
functioning as it should.  It's possible that I clobbered the working
version with an older version, but I don't see any problem with my current
code.

I'm creating a Dispatch object for the IHTMLTextContainer interface of the
DOM Body element, and this appears to be correct.  This interface does
define a scrollTop property (both put and get), but when I attempt to access
the property, I get a com_error.  Any pointers or slaps upside the head for
obvious problems would be appreciated.  Note: my original code using solely
Dispatch objects with no type library was able to directly take
self.Document.body.scrollTop, so I suppose it's possible that the dispatch
object was on one run not able to get the IHTMLTextContainer module, and in
using base Dispatch might have been able to do the same trick.  To show
this, replace the Dispatch call with:

self.body = Dispatch(
	body._oleobj_,
##	"HTMLBody",
##	IHTMLTextContainer_CLSID,
)

And you'll see that the body becomes a DispHTMLBody instance, which works
properly, allowing you to use scrollTop as a property.  From what I
understand, however, this is not the proper way to get an interface handle.
On the other hand, it works :o) .

For the simplified demo, I'm just importing directly in the pythonwin
interactive environment.  The current (nonfunctional) code with traceback
follows.

Enjoy yourselves,
Mike

8<____________ htmlwindow.py _________
'''Demo getting the IHTMLWindow2 pointer from a WebBrowser control
'''
# from portals.htmldemo import htmlwindow
from win32com.client import *
from win32com.server import util, policy
from win32com.client import gencache
from pywin.tools.browser import Browse
from pywin.debugger import set_trace
##from pdb import set_trace
import pythoncom, traceback

HTMLLib_CLSID = '{3050F1C5-98B5-11CF-BB82-00AA00BDCE0B}'
IHTMLTextContainer_CLSID = '{3050F230-98B5-11CF-BB82-00AA00BDCE0B}'
IHTMLBody2_CLSID = '{332C4425-26CB-11D0-B483-00C04FD90119}'

try:
	htmlmodule = gencache.EnsureModule(
		HTMLLib_CLSID, 0, 4, 0,
		bForDemand=1
	)
##	print dir( iemodule)
##	print iemodule.DispHTMLBody
except (ImportError, pythoncom.error):
	raise SystemExit( '''this demo requires IE 5.0 or above''' )


class IEEvents:
##	def OnVisible( self, visible ):
##		print 'visible', visible
	def OnDownloadComplete( self, *args):
		print 'NavigateComplete'
		try:
			print 'self.Document', self.Document
			body = self.Document.body
			print 'body', body
			if body:
##				set_trace()
				self.body = Dispatch(
					body._oleobj_,
					"HTMLBody",
					IHTMLTextContainer_CLSID,
				)
				print 'body is', self.body
				self.htmlwindow = self.Document.parentWindow
				self.SinkTest()
		except:
			traceback.print_exc()
		return 1
	def SinkTest( self ):
		print 'SinkTest'
		sink = Sink(self.htmlwindow, self.body )

def transformarg(arg):
	if type(arg)==dispatchType:
		return Dispatch(arg)
	elif type(arg)==UnicodeType:
		return str(arg)
	return arg
arg_transformer = lambda object, args: map(transformarg, args)
class Sink: # as in Kitchen ;o)
	CLSID = CLSID_Sink =
pythoncom.MakeIID('{3050F625-98B5-11CF-BB82-00AA00BDCE0B}')
	_arg_transformer_ = arg_transformer
	_public_methods_ = [
##		"Ononscroll",
	]
	_dispid_to_func_ = {
		 1016 : "Ononresize",
		 1025 : "Ononafterprint",
	-2147418102 : "Ononhelp",
	-2147418112 : "Ononblur",
	-2147418111 : "Ononfocus",
		 1002 : "Ononerror",
		 1017 : "Ononbeforeunload",
		 1024 : "Ononbeforeprint",
		 1008 : "Ononunload",
		 1003 : "Ononload",
		 1014 : "Ononscroll",
	}
	def __init__( self, window, body ):
		self.window = window
		self.body = body
		advise( self.window, self)
		
	def Ononscroll( self, *args):
		try:
			event = self.window.event
##			set_trace()
			print 'body', self.body
			print 'scroll', self.body.scrollTop
		except:
			traceback.print_exc()
		return 1
		
def advise( window, sink ):
	cpc = window._oleobj_.QueryInterface(
		pythoncom.IID_IConnectionPointContainer
	)
	cp = cpc.FindConnectionPoint(
		# this is the clsID of the IHTMLWindow2 interface
		sink.CLSID_Sink,
	)
	cookie=cp.Advise(
		util.wrap(sink)
	)
	sink._olecp,sink._olecp_cookie = cp,cookie


ie = DispatchWithEvents("InternetExplorer.Application", IEEvents)
ie.Visible = 1
ie.Navigate( 'www.tpresence.com' )


8<________________ traceback __________
...
body <win32com.gen_py.Microsoft HTML Object Library.IHTMLTextContainer>
scrollTraceback (innermost last):
  File "/portals\htmldemo\htmlwindow.py", line 89, in Ononscroll
    except:
  File "D:\bin\lang\Python\win32com\client\__init__.py", line 347, in
__getattr__
    return apply(self._ApplyTypes_, args)
  File "D:\bin\lang\Python\win32com\client\__init__.py", line 341, in
_ApplyTypes_
    return self._get_good_object_(apply(self._oleobj_.InvokeTypes, (dispid,
0, wFlags, retType, argTypes) + args), user, resultCLSID)
com_error: (-2147352573, 'Member not found.', None, None)
 body <win32com.gen_py.Microsoft HTML Object Library.IHTMLTextContainer>


-----Original Message-----
From: Mark Hammond
To: Mike  Fletcher; python-list at python.org
Sent: 10/4/2000 9:07 AM
Subject: RE: Win32: ByRef equivalent in pythoncom for function callbacks?

> What I did was strip the particular event handler class out of the
mshtml
> Makepy interface file (which will not import, likely because
> it's 1.9 MB),

Note there is a new "for demand" option that will create a package, and
only generate the specific interfaces when actually needed - for exactly
this reason!  Most of the gencache functions have a bForDemand param...

Python talking to a DOM - that seems to be happening a bit, recently ;-)

Mark.




More information about the Python-list mailing list