【问题标题】:How to make a wx window parent of another application's window?如何使 wx 窗口成为另一个应用程序窗口的父级?
【发布时间】:2017-04-16 20:11:43
【问题描述】:

我想知道如何让别人的应用程序窗口成为我的 wx 窗口的父级。

我知道这是可能的,因为 twain 模块就是这样做的。

例如,您可以传入 pygame.display 的句柄,它将充当将出现的扫描对话框的父级。 您可以直接给它一个 Tk() 或 wx.Frame() 的句柄(但无论如何它只会抓取句柄号)。

或者你可以传入一个完全不同的应用程序的句柄,例如记事本。

我想实现这一目标。这样我的 wx 对话框或弹出窗口就会以模态模式出现在另一个应用程序上。

您已经推断出我想在 MS Windows 上执行此操作。 好吧,我想跨平台做,但其他平台并没有那么愚蠢,让任何人乱搞其他应用程序的界面。 当然,我认为这是可能的,但要困难得多。所以,目前仅限 Windows。

我想为此我需要模拟 wx.Window 或 Frame 或 Panel 或基于所选窗口句柄的东西,以将其传递给我的对话框。或者类似的东西。

有什么想法吗?

【问题讨论】:

  • 您找到解决方案了吗?为同样的问题苦苦挣扎
  • @user969068 :我发现了一些有用的信息。看看我在这里添加的答案。

标签: python user-interface wxpython


【解决方案1】:

我没有解决我的问题。对我来说幸运的是,两个应用程序,客户端应用程序和我想成为其父应用程序的应用程序都是我的,所以我使用 wxPython 重写了父应用程序并在其中添加了必要的接口,即创建了新应用程序。起初我不愿意这样做,这就是我寻找“育儿”解决方案的原因。

然而,在这 2 年里,我偶然发现了一些有用的信息:

  1. 我发现了一个工厂函数,名为 _CreateWindowFromNativeWindow() 或 _CreateWindowFromHandle() 或类似的东西。 这是 wxPython 中的一个内部函数,但据我所知,它可以从我们的代码中调用。但因为爱它,我再也找不到它了。我没有尝试过,所以这只是一个小费。也许有人可以把它挖出来。

  2. 我找到了 wx.Window.AssociateHandle() 方法,但是这是真实的,应该可以工作。我们无法创建没有父级的 wx.Window(),但我们可以创建 wx.Frame()。所以是这样的:


f = wx.Frame(None)
f.AssociateHandle(hwnd)

应该可以。现在 f 应该链接到另一个应用程序的本机窗口,如果 hwnd 是正确的并且我们有适当的权限,我们应该能够将它用作其他 wx 窗口的父级。无论谁尝试过,请发表评论,让我们知道它是否按预期工作。

如果我们知道如何让 wxWidgets 意识到操作系统改变了窗口的句柄,那么总有一个 ctypes 解决方案。我没有,因为我停下来朝那个方向看。此外,通过修改 wxPython 源代码并构建它们,有一个解决方案可以公开 wxWidgets 的未记录方法 setHWND(),根据某些来源,该方法应该存在。

【讨论】:

    【解决方案2】:

    我将使用 wxWidgets(C/C++ 库)术语,例如,我的“wxFrame”将变成你的 wx.Frame。

    wxWindow 类有一个方法SetId (http://docs.wxwidgets.org/3.1/classwx_window.html)。所以你可以尝试使用默认构造函数创建 wxWindow 对象(我们称之为“ParrentWindow”),找出某个外部应用程序的某个窗口的 id,并将这个窗口 id 传递给我们的“ParrentWindow”对象的SetId 方法。

    然后您应该尝试将此对象用作您自己的某些窗口(wxWindow、wxFrame、wxPannel 等)的父对象:只需将我们的“ParrentWindow”传递给新窗口对象的构造函数即可。

    也许它会起作用。

    但请记住(在现代版本的 MS Windows 操作系统中)您的应用程序可能会被限制为只能在您自己的窗口中运行。如果是这种情况,您将需要在其中一个管理员帐户下运行您的应用程序。

    UPD:

    我刚刚查看了 MSDN,是的:您可以使用 SetParent() win32 API 函数更改已存在(已构建)窗口的父级:https://msdn.microsoft.com/en-us/library/windows/desktop/ms633541(v=vs.85).aspx

    因此,您可以将 User32.dll 加载到您的 Python 代码中并直接(通过使用默认的 ctypes 模块)或间接(通过 pywin32 模块)使用这个 win32 Api。然后,您只需要获取子窗口的 HWND 和外部父窗口的 HWND。并将它们传递给SetParent() win32 API 函数。但您应该记住,使用 win32 API 绕过 wxWindows 代码可能会导致(或可能不会)在适当的 wxWindows 对象中出现不一致。

    【讨论】:

    • 这里有 2 个问题。 1.我不能在没有父级的情况下创建wx.Window(),wx.Frame()我可以。但是 - 2. wx.Frame.SetId() 不只是 wx 事件管理器的本地化 ID 吗?参见 wx.Frame.GetId()!=wx.Frame.GetHandle()。而且没有 wx.Frame.SetHandle()。
    • 哦,是的,我刚刚发现wxWidgets,至少新版本有一个类wxNativeWindow,它可以满足我的需要,但是wxPython还没有。我将不得不以某种方式模仿它。n
    • 我已经用一些附加信息更新了答案。 PS:我上次使用 wxWidgets 库和上次修改 wxWidgets 源代码是在 2012 年,所以目前我很难对 wxWidgets 更准确和更有帮助。对不起。
    • 谢谢,这可能有效。我稍后会检查它。我看到通过 windows 上的 ctypes 添加到 wx windows 的特殊效果,例如透明窗口的实现。所以,这可能真的有效。我会在我尝试时告诉你。
    • 好的 - 听到会很有趣
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多