问题
I wish to know how to make another's application window be a parent to my wx window.
I know that it is possible because twain module does just that.
For instance, you can pass in pygame.display's handle and it will act as a parent of scanning dialog that will appear. You can give it a handle of your Tk() or wx.Frame() directly (but it will grab out only the handle number anyway).
Or you can pass in a handle of completely different application, notepad for example.
I would like to achieve this. So that my wx dialog or pop up window appear in Modal mode over another application.
You already deduced that I want to do it on MS Windows. Well, I'd like to do it cross-platform, but other platforms aren't so stupid to let anyone messing in other app's interface. Sure I think it is possible, but much harder. So, for now Windows only.
I guess for this I will need to emulate wx.Window or Frame or Panel or something based on a chosen window handle to pass it to my dialog. Or something like that.
Any ideas?
回答1:
I will talk in wxWidgets (C/C++ library) terminology, so, for example, my "wxFrame" will turn into yours wx.Frame.
wxWindow class has a method SetId
(http://docs.wxwidgets.org/3.1/classwx_window.html). So you may try to create wxWindow object (let's call it "ParrentWindow") with default constructor, find out id of some window of some external application, and pass this window id to SetId
method of our "ParrentWindow" object.
Then you should try to use this object as a parent of some of your own windows (wxWindow, wxFrame, wxPannel, etc.): just pass our "ParrentWindow" to the new window object's constructor.
Maybe it will work.
But remember that (in modern versions of MS Windows OS) your app can be restricted to operate only with your own windows. And if that is the case than you will need to run your app under one of the administrators accounts.
UPD:
I've just looked into MSDN and yes: you can change parent of already existing (already built) window by using SetParent()
win32 API function: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633541(v=vs.85).aspx
So you may load User32.dll into your Python code and use this win32 Api directly (by using default ctypes
module) or indirectly (by pywin32
module). Then you just need to get HWND of your child window and HWND of external parent window. And pass them into SetParent()
win32 API function. But you should remember that using win32 API bypassing wxWindows code may lead (or may not) to inconsistency in an appropriate wxWindows objects.
回答2:
I did not resolve my problem. Fortunately for me, both applications, the client one, and the one that I wanted to be its parent, were mine, so I rewrote the parent one using wxPython and added necessary interface into it, i.e. created the new application. I was unwilling to do that at first, that's why I searched for a "parenting" solution.
However, In this 2 years I happen to stumble on some useful info about it:
I found a factory function called something like _CreateWindowFromNativeWindow() or _CreateWindowFromHandle() or something like that. That was an internal function in wxPython but was callable from our code as far as I saw. But for the love of it I cannot find it again. I did not try it, so it is a tip only. Perhaps somebody can dig it out.
I found the method wx.Window.AssociateHandle() This however is real and should work. We cannot create a wx.Window() without a parent, but wx.Frame() we can. So something like this:
f = wx.Frame(None)
f.AssociateHandle(hwnd)
should work. Now f should be linked to the native window of another app, if the hwnd is right and we have appropriate permissions, and we should be able to use it as a parent for other wx windows. Whomever tries it, please post a comment to let us know whether it works as expected.
There is always a ctypes solution if we know how to make wxWidgets realise that the OS changed a handle of the window. I don't because I stopped to look in that direction. Also, there is a solution of exposing undocumented method setHWND() of wxWidgets, which should exist according to some sources, by modifying the wxPython sources and building them.
来源:https://stackoverflow.com/questions/40923352/how-to-make-a-wx-window-parent-of-another-applications-window