root/trunk/RBSkinning/RBSkinning/wxTools/wxActiveXWrapper.py

Revision 637, 7.3 kB (checked in by gwm, 5 years ago)

*** empty log message ***

Line 
1 #!/usr/bin/env python
2 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 ##~ License
4 ##~
5 ##- The RuneBlade Foundation library is intended to ease some
6 ##- aspects of writing intricate Jabber, XML, and User Interface (wxPython, etc.)
7 ##- applications, while providing the flexibility to modularly change the
8 ##- architecture. Enjoy.
9 ##~
10 ##~ Copyright (C) 2002  TechGame Networks, LLC.
11 ##~
12 ##~ This library is free software; you can redistribute it and/or
13 ##~ modify it under the terms of the BSD style License as found in the
14 ##~ LICENSE file included with this distribution.
15 ##~
16 ##~ TechGame Networks, LLC can be reached at:
17 ##~ 3578 E. Hartsel Drive #211
18 ##~ Colorado Springs, Colorado, USA, 80920
19 ##~
20 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21
22 """Create wxWindow's derived controls to support an ActiveX controls.
23
24 This code is heavily borrowed from Robin Dunn's wxPython.lib.activexwrapper,
25 but reorganized in order to:
26     - Support imported objects without a default_source (Adobe.SVGCtl.3)
27     - Use the pythonic mixin idiom to simplify and clarify what is happening
28     - Move to python2.2's types.ClassType(...) factory method instead of the new module
29 """
30
31 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32 #~ Imports
33 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34
35 import win32ui
36 import pywin.mfc.activex
37 import win32con
38 import win32gui
39 import win32com.server.util # we use this.  trust me.  it may not look like it.  trust me.
40 from wxPython import wx
41 import types
42 from win32com.client import gencache, dynamic
43 import pywintypes
44
45 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46 #~ Class Definitions
47 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48
49 class wxActiveXMixins(wx.wxWindow, pywin.mfc.activex.Control):
50     """pyWin and wxPython mixin to supply the envrionment for ActiveX controls"""
51
52     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53     #~ Special
54     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
55
56     def __init__(self, *args, **kw):
57         # init base classes
58         pywin.mfc.activex.Control.__init__(self)
59         wx.wxWindow.__init__(self, *args, **kw)
60
61         win32ui.EnableControlContainer()
62         self._eventObj = self._eventObj  # move from class to instance
63
64         # create a pythonwin wrapper around this wx.wxWindow
65         handle = self.GetHandle()
66         self._wnd = win32ui.CreateWindowFromHandle(handle)
67
68         # create the control
69         sz = self.GetSize()
70         self.CreateControl(self.__class__.__name__, win32con.WS_TABSTOP | win32con.WS_VISIBLE,
71             (0, 0, sz.width, sz.height), self._wnd, self.GetId())
72
73         # init the ax events part of the object
74         self._eventBase.__init__(self, self._dispobj_)
75
76         ##def SetChildWindows(handle, result):
77         ##    window = win32ui.CreateWindowFromHandle(handle)
78         ##    result.append(window )
79
80         ##self.childwnds = []
81         ##win32gui.EnumChildWindows(handle, SetChildWindows, self.childwnds)
82
83         # hook some wx events
84         wx.EVT_SIZE(self, self.OnSize)
85         wx.EVT_ERASE_BACKGROUND(self, self.OnEraseBackground)
86
87     def __getattr__(self, attr):
88         try:
89             return pywin.mfc.activex.Control.__getattr__(self, attr)
90         except AttributeError:
91             if self._eventObj:
92                 return getattr(self._eventObj, attr)
93             else: raise
94
95     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
96     #~ Public Methods
97     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98
99     def Cleanup(self):
100         del self._wnd
101         self.close()
102
103     def OnSize(self, evt):
104         # get wx.wxWindow size
105         sz = self.GetClientSize()
106         # move the AXControl
107         self.MoveWindow((0, 0, sz.width, sz.height), 1)
108
109     def OnEraseBackground(self, evt):
110         pass
111        
112 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
113
114 class _EmptyEvents:
115     """Mixin for CoClasses that do not have a "default_source" attributes, such as Adobe.SVGCtl.3"""
116
117     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118     #~ Constants / Variables / Etc.
119     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120
121     _public_methods_ = []
122     _dispid_to_func_ = {}
123
124     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125     #~ Special
126     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127
128     def __init__(self, *args, **kw):
129         pass
130
131 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
132 #~ Function Definitions
133 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134
135 def winGetAXControlCoClass(ProgOrClsID):
136     try:
137         CoClass = gencache.GetClassForProgID(ProgOrClsID)
138         if not CoClass:
139             # Well, we might not have a cached one... so lets go find the TypeLib
140             dis = dynamic.Dispatch(pywintypes.IID(ProgOrClsID))
141             tlbAttr = dis._lazydata_[0].GetContainingTypeLib()[0].GetLibAttr()
142             # Now gencache it
143             TLB = gencache.EnsureModule(tlbAttr[0], tlbAttr[1], tlbAttr[3], tlbAttr[4])
144             # And try Aagain
145             CoClass = gencache.GetClassForProgID(ProgOrClsID)
146             if not CoClass:
147                 # Dang... still didn't work
148                 raise NameError, "ActiveX class not found for %r" % (ProgOrClsID, )
149         return CoClass
150     except pywintypes.com_error:
151         raise NameError, "ActiveX class not found for %r" % (ProgOrClsID, )
152
153 def winGetAXControlModule(ProgOrClsID):
154     try:
155         module = gencache.GetModuleForProgID(ProgOrClsID)
156         if not module:
157             # Well, we might not have a cached one... so lets go find the TypeLib
158             dis = dynamic.Dispatch(pywintypes.IID(ProgOrClsID))
159             tlbAttr = dis._lazydata_[0].GetContainingTypeLib()[0].GetLibAttr()
160             # Now gencache it
161             TLB = gencache.EnsureModule(tlbAttr[0], tlbAttr[1], tlbAttr[3], tlbAttr[4])
162             # And try Aagain
163             module = gencache.GetModuleForProgID(ProgOrClsID)
164             if not module:
165                 # Dang... still didn't work
166                 raise NameError, "ActiveX class module not found for %r" % (ProgOrClsID, )
167         return module
168     except pywintypes.com_error:
169         raise NameError, "ActiveX class module not found for %r" % (ProgOrClsID, )
170
171 def wxActiveXControlFactory(CoClass, eventClasses=tuple(), eventObj=None):
172     """Creates a wxWindow's derived control to support an ActiveX control given the control's CoClass.
173    
174     Parameters:
175         - CoClases: COM CoClass from win32com.client gencache or makepy or similar
176
177         - eventClasses: a tuple of classes that the component should also derive from,
178             specifically to support event overrides
179
180         - eventObj: an instance to be searched for event callbacks (and other things...).
181             Think acquisition.  ;) 
182
183     See also -- wxPython.lib.activexwrapper.MakeActiveXClass
184     """
185     # This would be better with Python2.2's Metaclasses... but wxPython
186     # derives from classic classes which are not quite as nice; but workable ;)
187     AXEventClass = getattr(CoClass, 'default_source', _EmptyEvents)
188     if not isinstance(eventClasses, (tuple, list)): eventClasses = (eventClasses,)
189     name = 'AXControl_' + CoClass.__name__
190     bases = (wxActiveXMixins, CoClass, AXEventClass) + filter(None, eventClasses)
191     data = {'_eventObj':eventObj, '_eventBase': AXEventClass, 'default_source': AXEventClass}
192     return types.ClassType(name, bases, data)
193
Note: See TracBrowser for help on using the browser.