Problem with variant types in wxActiveX

21 views
Skip to first unread message

Howard Lightstone

unread,
Nov 12, 2009, 7:55:01 PM11/12/09
to wxPython-users
I seem to be stuck with a variant type exposed by an ActiveX control.

The returned type is type 29. Examination of VARENUM from MS makes me
think there are several more variant types that need to be added to
activex_wrap.cpp.

The types themselves are reported as typedef'ed enums if I use makepy
to look at the registered type library.

Is there any way to "change" the type lookup the wrapper determines in
order to 'tweak' the types?

(When I was trying to use win32.com, I was able to set the value ok.
I just couldn't get myself connected to the event callbacks).

Robin Dunn

unread,
Nov 13, 2009, 1:53:15 PM11/13/09
to wxpytho...@googlegroups.com
On 11/12/09 4:55 PM, Howard Lightstone wrote:
>
> I seem to be stuck with a variant type exposed by an ActiveX control.
>
> The returned type is type 29. Examination of VARENUM from MS makes me
> think there are several more variant types that need to be added to
> activex_wrap.cpp.

There are lots more. So far only the basic fundamental types are
supported. Since that C++ ActiveX wrapper implementation has suffered
some bit-rot and not been maintained very well I added a new Python-only
activex module that uses ctypes and comtypes to provide a much more
full-featured implementation. See the wx.lib.activex module, and also
wx.lib.iewin and wx.lib.pdfwin for some examples of using the activex
module.


--
Robin Dunn
Software Craftsman
http://wxPython.org

Howard Lightstone

unread,
Nov 13, 2009, 2:40:58 PM11/13/09
to wxPython-users


> There are lots more.  So far only the basic fundamental types are
> supported.  Since that C++ ActiveX wrapper implementation has suffered
> some bit-rot and not been maintained very well I added a new Python-only
> activex module that uses ctypes and comtypes to provide a much more
> full-featured implementation.  See the wx.lib.activex module, and also
> wx.lib.iewin and wx.lib.pdfwin for some examples of using the activex
> module.
>
> --
> Robin Dunn
> Software Craftsmanhttp://wxPython.org

I tried this but I have a different error now :

Traceback (most recent call last):
File "newaxtest.py", line 24, in <module>
ax=AXclass(fr,clstr,size=wx.Size(640,480))
File "newaxtest.py", line 11, in __init__
ActiveXCtrl.__init__(self,self.Frame,axid,**kwargs)
File "C:\python25\lib\site-packages\wx-2.8-msw-unicode\wx\lib
\activex.py",
line 112, in__init__
self.AddEventSink(self)
File "C:\python25\lib\site-packages\wx-2.8-msw-unicode\wx\lib
\activex.py",
line 134, in AddEventSink
self._evt_connections.append(cc.GetEvents(self._ax, sink,
interface))
File "C:\python25\lib\site-packages\comtypes\client\_events.py",
line 132, in
GetEvents
interface = FindOutgoingInterface(source)
File "C:\python25\lib\site-packages\comtypes\client\_events.py",
line 72, in FindOutgoingInterface
raise TypeError("cannot determine source interface")
TypeError: cannot determine source interface

-----------------------------------------------------
The code looks like this:
import os
import wx
from wx.lib.activex import *

clstr ='{5B72F398-1C3D-4455-89E3-60081FD10090}'

class AXclass(ActiveXCtrl):
def __init__(self, parent,axid,**kwargs):
self.Frame=parent
ActiveXCtrl.__init__(self,self.Frame,axid,**kwargs)

self.Source_Mode=2 # this is one of the properties of the
control

# Stuff to do when we exit:
def OnClose(self, event):
print "deleting"
print "exiting"
os._exit(1)

app = wx.App(redirect=0)
fr=wx.Frame(None)
ax=AXclass(fr,clstr,size=wx.Size(640,480))

app.MainLoop()

Howard Lightstone

unread,
Nov 13, 2009, 7:39:41 PM11/13/09
to wxPython-users


<snip>

I am starting to see things happen. Using the wx.lib.activex logic,
it ALWAYS creates a connection to a web browser control....

I made my own copy of this file and forced it to use the axID to get a
dispatch object to the explicit control I wanted. So now, it makes
event connections to my control.

However, I also want the methods of the control available. Despite a
lot of reading in comtypes stuff, I can't seem to make that happen.
It looks like I need to specify dynamic=True when creating the object
but that fails to find a valid interface (__mro__ issue???). If I do
not specify dynamic (== False), I can't see how to access the (named)
methods.

Any help here? I have examined the comtypes client documentation and
the various source files without figuring out how the magic works.

Thanks

Robin Dunn

unread,
Nov 16, 2009, 1:32:58 PM11/16/09
to wxpytho...@googlegroups.com

It sounds like the COM object is not fully publishing its interface.

Howard Lightstone

unread,
Nov 16, 2009, 3:08:22 PM11/16/09
to wxPython-users

<snip>

>
> It sounds like the COM object is not fully publishing its interface.
>
> --
> Robin Dunn
> Software Craftsmanhttp://wxPython.org

After a lot of (logging statement) trials, I think I know what is
happening.

The comtypes lookup routine FindOutgoingInterface has a default place
to look up a source interface. It depends on having the classid in
the interface object (which is automatically set if you use the
comtypes object routines).

But it isn't set by the activex logic.

I added saving it into the activex.py routine like this:
assert res == hr.S_OK
self._ax = cc.GetBestInterface(unknown)
+ # save it in case needed
+ self._ax.__dict__['__clsid'] = str(axID)

# Fetch the interface for IOleInPlaceActiveObject. We'll use
this

After adding that line, the control source/sink logic now works!
I don't understand comtypes enough to know why but it looks like the
comtypes lookup only looks for the "default" case and not the "default
source" case for those controls that have multiple interfaces.

Of course, I still have the problem that the OLD (.pyd) activex
correctly displays the activex output and the new one doesn't display
anything but that will be the next travail to solve.

Reply all
Reply to author
Forward
0 new messages