wxPython无法关闭有窗口句柄的父框架

1 投票
3 回答
2467 浏览
提问于 2025-04-15 12:00

我有一个用Python写的程序,它通过COM从另一个程序获取一个窗口的句柄(可以把这个Python程序想象成一个插件)。我把这个窗口设置为主Python窗口的父窗口,这样如果另一个程序最小化,Python窗口也会跟着最小化。问题是,当我想退出程序,尝试关闭或销毁主窗口时,frame.close这个操作总是无法完成(虽然窗口确实消失了),而且另一个程序也不愿意关闭,只有通过任务管理器强制结束。

我们大致采取的步骤如下:

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

有没有人对此有什么想法或者经验可以分享?

非常感谢任何帮助!

[编辑] 只有在我把这个句柄当作父窗口使用时才会出现这个问题,如果我只是获取句柄然后直接关闭Python程序,另一个程序就能正常关闭。

3 个回答

0

如果你只需要改变父级,可以在 frame.Close() 之前试试 frame.Reparent(None)

1

我在想,你的 Close 调用可能在关闭处理程序里卡住了。你有没有试过用 Destroy 呢?如果这样还是不行,那唯一的解决办法似乎就是“重新归属”或者“分离”你的窗口。我在 wx 里没看到有办法做到这一点,不过也许你可以直接使用 win32 API 来完成这个任务……?

0

我这个解决办法有点儿像是临时拼凑出来的,老实说也不是我想出来的最优雅的方案——不过它确实有效...

简单来说,我的步骤是启动一个线程,去检查窗口的句柄是否存在。只要它还存在,就什么都不做。如果它不再存在了,就结束这个Python应用程序,这样就能释放句柄(和主应用程序)。

class CheckingThread(threading.Thread):
    '''
    This class runs a check on Parent Window to see if it still is running
    If Parent Window closes, this class kills the Python Window application in memory
    '''
    def run(self):
        '''
        Checks Parent Window 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 Python Window 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

再次强调,这个方法感觉有点儿不太正规,但我真的想不到其他更好的办法。如果其他人有更好的解决方案,请分享一下。

撰写回答