views:

694

answers:

3

I have a program in Python that gets a window handle via COM from another program (think of the Python program as an addin) I set this window to be the main Python frame's parent so that if the other program minimizes, the python frame will too. The problem is when I go to exit, and try to close or destroy the main frame, the frame.close never completes it's execution (although it does disappear) and the other program refuses to close unless killed with TaskManager.

Here are roughly the steps we take:

if we are started directly, launch other program
if not, we are called from the other program, do nothing

enter main function:
create new wx.App
set other program as frame parent:
  Get handle via COM
  create a parent using wx.Window_FromHWND
  create new frame with handle as parent
  show frame
enter main loop

App.onexit:
  close frame
  frame = None
  handle as parent = None
  handle = None

Anybody have any thoughts on this or experience with this sort of thing?

I appreciate any help with this!

[Edit] This is only the case when I use the handle as a parent, if I just get the handle and close the python program, the other program closes fine

+1  A: 

I wonder if your Close call may be hanging in the close-handler. Have you tried calling Destroy instead? If that doesn't help, then the only solution would seem to be "reparenting" or "detaching" your frame -- I don't see a way to do that in wx, but maybe you could drop down to win32 API for that one task...?

Alex Martelli
I've tried both close and destroy. I'm not sure I understand what you mean by "Dropping down to win32 API", could you elaborate?
Fry
I mean, for example, getting the HWND of the frame and trying to destroy it via DestroyWindow(hFrame); setting WM_EX_NOPARENTNOTIFY at window creation to make sure the "pseudo"-parent doesn't get involved in the destruction/closing process; and other low-level tricks that Win32 makes available but may not be surfaced by cross-platform frameworks such as wx -- see http://msdn.microsoft.com/en-us/library/aa383749(VS.85).aspx for many more details.
Alex Martelli
I can't seem to find a way to implement your suggestions in Python. Right now I've just set the handle window to be destroyed on the Python program's exit. I can't seem to find any more info anywhere else
Fry
Alex Martelli
A: 

If reparenting is all you need, you can try frame.Reparent(None) before frame.Close()

FogleBird
Thanks, but reparenting doesn't work. The earliest I know that the form is closing is in the OnClose event, which reparenting there seems to have no effect
Fry
A: 

My resolution to this is a little bit hacked, and admittedly not the most elegant solution that I've ever come up with - but it works rather effectively...

Basically my steps are to start a thread that polls to see whether the window handle is existent or not. While it's still existent, do nothing. If it no longer exists, kill the python application, allowing the handle (and main application) to be released.

class CheckingThread(threading.Thread):
    '''
    This class runs a check on Visum to see if it still is running
    If Visum closes, this class kills the Traffix application in memory
    '''
    def run(self):
        '''
        Checks Visum in 5 seconds intervals to make sure it is still alive.
        If not alive, exit application
        '''
        self.needKill = False

        while not self.needKill:
            if self.handle is not None:
                if not win32gui.IsWindow(self.handle):
                    os._exit(0)
                    break
            time.sleep(5)

    def Kill(self):
        '''
        Call from Traffix main application that causes application to exit
        '''
        self.needKill = True

    def SetHandle(self, handle):
        '''
        Sets Handle so thread can check if handle exists.
        This must be called before thread is started.
        '''
        self.handle = handle

Again, it feels a little hackish, but I don't really see another way around it. If anybody else has better resolutions, please post.

Fry