Problem with variant types in wxActiveX

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

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.

···

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.

--
Robin Dunn
Software Craftsman

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()

<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

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

···

On 11/13/09 4:39 PM, Howard Lightstone wrote:

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

--
Robin Dunn
Software Craftsman

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