ActiveX controls, exiting and onexit

Hi again

In my previous post I said that I had couple of frames working well
together, well they aren't anymore. I wonder if somebody could give
me some insight into how wx python tides up when it exits and what
might might be going on with the following.

I create my application like this

class soasApp( wx.App ):
    def OnInit( self ):
        self.controlFrame = mainFrm( None, -1, "" )
        self.SetTopWindow( self.controlFrame )
        self.controlFrame.Show( True )
        secondDisplay = wx.Display( 1 )
        dispGeometry = secondDisplay.GetGeometry()
        self.retCam = imageFrame( None, "Image frame", ( -1300, 0 ),
( 1300, 1000 ),
                          style = wx.DEFAULT_FRAME_STYLE |
wx.TINY_CAPTION_HORIZ )
        self.retCam.Show( True )
        self.retCam.camera.Acquire = True
        self.retCam.camera.Display = True
        return True

    def OnExit( self ):
        print 'Exiting'
        self.retCam.Destroy()

if __name__ == '__main__':
        # initialise the GUI
    soasGUI = soasApp( 0 )
    wx.InitAllImageHandlers()
    soasGUI.MainLoop()

The imageFrame class contains an actives control which is created like
this.
        self.dcamModule =
gencache.EnsureModule( '{6B9BD678-9710-44D9-9282-A088094E4214}', 0, 1,
0 )
        dcamClass = MakeActiveXClass( self.dcamModule.ActiveDcam,
eventObj = self )
        self.camera = dcamClass( self, -1 )

I created the OnExit method to destroy the second frame as it was not
automatically destroyed, however it is not called when I expected. If
I close the the second frame using the Window control then I get an
error invoking a com method followed by many errors generated by the
activex wrapper module which only stop when I exceed possible
recursion depth, like this.

pythoncom error: Python error invoking COM method.

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\win32com\server\policy.py", line
277, in _Invoke_
    return self._invoke_(dispid, lcid, wFlags, args)
  File "C:\Python27\lib\site-packages\win32com\server\policy.py", line
282, in _invoke_
    return S_OK, -1, self._invokeex_(dispid, lcid, wFlags, args, None,
None)
  File "C:\Python27\lib\site-packages\win32com\server\policy.py", line
579, in _invokeex_
    func = getattr(self._obj_, funcname)
  File "C:\Python27\lib\site-packages\wx\lib\activexwrapper.py", line
129, in axw__getattr__
    return pywin.mfc.activex.Control.__getattr__(self, attr)
  File "C:\Python27\lib\site-packages\Pythonwin\pywin\mfc\activex.py",
line 47, in __getattr__
    return getattr(self._dispobj_, attr)
  File "C:\Python27\lib\site-packages\wx\lib\activexwrapper.py", line
129, in axw__getattr__
    return pywin.mfc.activex.Control.__getattr__(self, attr)
  File "C:\Python27\lib\site-packages\Pythonwin\pywin\mfc\activex.py",
line 47, in __getattr__

Finally the OnExit method is called. With this error

Traceback (most recent call last):
  File "C:\Users\peter\workspace\SAOS\src\SAOS2.py", line 380, in
OnExit
Exiting
    self.retCam.Destroy()
  File "C:\Python27\lib\site-packages\wx\_core.py", line 14568, in
__getattr__
    raise PyDeadObjectError(self.attrStr % self._name)
wx._core.PyDeadObjectError: The C++ part of the imageFrame object has
been deleted, attribute access no longer allowed.

I've tried searching for information about the order in which events
occur when wx exits but I clearly don't understand what is going on.

Thanks for any help.

Hi again

In my previous post I said that I had couple of frames working well
together, well they aren't anymore. I wonder if somebody could give
me some insight into how wx python tides up when it exits and what
might might be going on with the following.

I create my application like this

[...]

I've tried searching for information about the order in which events
occur when wx exits but I clearly don't understand what is going on.

wx.App.OnExit is called as MainLoop is exiting. By default the MainLoop exits when there are no more top level windows left (including any that might have just been hidden, or dialogs that were not explicitly destroyed). So by definition is too late to access any window attributes from OnExit.

Instead you could give your main window a EVT_CLOSE handler, and call retFrame.Close from there. Or make the main frame be the parent of the imageFrame, and then it will be closed automatically when the main frame is closed.

···

On 8/1/11 3:02 AM, Peter West wrote:

--
Robin Dunn
Software Craftsman

Thanks Robin

wx.App.OnExit is called as MainLoop is exiting. By default the MainLoop
exits when there are no more top level windows left (including any that
might have just been hidden, or dialogs that were not explicitly
destroyed). So by definition is too late to access any window
attributes from OnExit.

I should have realised that. Is there any documantation on the
sequence of event when wx starts and ends? (apologies if I haven't
looked hard enough)

Or make the main frame be the parent of the
imageFrame, and then it will be closed automatically when the main frame
is closed.

That works great for disposing of the Window, however when it closes I
still get the deluge of error messages. I suspect that the errors
have consequences to system stability as I'm suddenly getting a lot of
Blue screens. Any thoughts on this? Should I explicitely destroy the
wrapped axtivex control in some way? Messages below. The errors at
lines 128 and 47 continue until I exceed the recursion limit.

Thanks for all your help.

pythoncom error: Python error invoking COM method.

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\win32com\server\policy.py", line
277, in _Invoke_
    return self._invoke_(dispid, lcid, wFlags, args)
  File "C:\Python27\lib\site-packages\win32com\server\policy.py", line
282, in _invoke_
    return S_OK, -1, self._invokeex_(dispid, lcid, wFlags, args, None,
None)
  File "C:\Python27\lib\site-packages\win32com\server\policy.py", line
579, in _invokeex_
    func = getattr(self._obj_, funcname)
  File "C:\Python27\lib\site-packages\wx\lib\activexwrapper.py", line
129, in axw__getattr__
    return pywin.mfc.activex.Control.__getattr__(self, attr)
  File "C:\Python27\lib\site-packages\Pythonwin\pywin\mfc\activex.py",
line 47, in __getattr__
    return getattr(self._dispobj_, attr)
  File "C:\Python27\lib\site-packages\wx\lib\activexwrapper.py", line
129, in axw__getattr__
    return pywin.mfc.activex.Control.__getattr__(self, attr)
  File "C:\Python27\lib\site-packages\Pythonwin\pywin\mfc\activex.py",
line 47, in __getattr__
    return getattr(self._dispobj_, attr)
  File "C:\Python27\lib\site-packages\wx\lib\activexwrapper.py", line
129, in axw__getattr__
    return pywin.mfc.activex.Control.__getattr__(self, attr)
  File "C:\Python27\lib\site-packages\Pythonwin\pywin\mfc\activex.py",
line 47, in __getattr__
    return getattr(self._dispobj_, attr)

I don't know enough about COM and PyWin32 to really say for sure what is going on, but perhaps you can work-around it by blocking it in axw__getattr__ if the window has already been destroyed.

···

On 8/2/11 1:15 AM, Peter West wrote:

Thanks Robin

wx.App.OnExit is called as MainLoop is exiting. By default the MainLoop
exits when there are no more top level windows left (including any that
might have just been hidden, or dialogs that were not explicitly
destroyed). So by definition is too late to access any window
attributes from OnExit.

I should have realised that. Is there any documantation on the
sequence of event when wx starts and ends? (apologies if I haven't
looked hard enough)

Or make the main frame be the parent of the
imageFrame, and then it will be closed automatically when the main frame
is closed.

That works great for disposing of the Window, however when it closes I
still get the deluge of error messages. I suspect that the errors
have consequences to system stability as I'm suddenly getting a lot of
Blue screens. Any thoughts on this? Should I explicitely destroy the
wrapped axtivex control in some way? Messages below. The errors at
lines 128 and 47 continue until I exceed the recursion limit.

Thanks for all your help.

pythoncom error: Python error invoking COM method.

--
Robin Dunn
Software Craftsman