How can I get the main window's handle in Python? - python

In python, I enumerate top-level windows through EnumWindows, and also I enumerate the processes through EnumProcesses.
Then in the python script, I put all the window handles which belongs to the same pid into one list (I did this through GetWindowThreadProcessId).
Later I found out something: there are 3 window handles which belong to notepad.exe, but I only open one text file.
Why?
Besides, I tried to set the text window as the foreground window through SetForegroundWindow, I passed the three window handles to this function, and two work.
How could this be ?

Processes sometimes create invisible windows for their own purposes. You should ignore them (use IsWindowVisible function).

To investigate this kind of things your best friend is Spy++, that comes with several versions of Visual Studio, if you can get it.
According to it, notepad.exe creates three top-level windows:
The visible main window, class name "Notepad", overlapped.
A hidden, disabled, pop-up window, class name "MSCTFIME UI", caption "M".
Another hidden, disabled, pop-up window, class name "IME", caption "Default IME".
The two hidden windows are used internally by notepad to implement the IME (Input Method Editor), the GUI to type complex scripts.
Many programs create top-level hidden windows for a lot of things. For what you intend, you can ignore them all and use only the visible ones.

Related

Multiple conemu windows - how to differentiate?

Windows 8.1 , ConEmu 170316 [32] {Preview}
I have multiple Conemu instances running, where each instance equals one "workspace".
I would like to be able to switch to this workspaces with autohotkey or pywinauto. However they require a criterion for selecting the right window, and usually I employ a combination of window title and or window class type.
Is there any setting in conemu that can help me achieve this criterion identifiation for window selection? If there isn't, I will have to write the PID down somewhere when I start the conem windows, then read it to bring up the right window at window activation time.
I can say only about pywinauto. When you call app = Application().start('ConEmu64.exe') pywinauto already remembers process PID and every new WindowSpecification object assumes this PID. Of course, it's true only if you're controlling start of ConEmu (or any other app). More details can be found in the Getting Started Guide.
Method app.connect(title="some unique tab name") will also remember the PID in app object. But if there are few instances with the same title, you need to disambiguate it using found_index=0 criterion, for example. Or right click on the tab and choose "Rename tab..." context menu item which changes the window title.
I took a short look at ConEmu. Toolbars and tabs are visible even to Spy++. So the most of actions can be automated. Just not sure about console inside a tab. If you want to type some commands, it's much better to use standard Python module subprocess because GUI automation for console programs looks very very strange. ;)
As per faq (ty Maximus) - see option 1:
1) Use -title “Window name” switch to explicitly set window title of new ConEmu instance. The example below starts new ConEmu window with title My server and ssh to your.server.com inside. Does not matter if you run another tab, or several tabs from task, the ConEmu window title remains My server. So you may rely on the title for selecting the window with class name VirtualConsoleClass.
Option 2 is also valid. I'd have to (1) create a config, and (2) hardcode the hashed id in ahk / pywinauto. Just using the window title name seems the right thing to do in my case, the app id setup seems overkill
2) Windows 7 introduced AppUserModelID. ConEmu uses executable path name and some switches (like -config, -loadcfgfile, -quake) to create a hash to form AppID, which you may see in the About / SysInfo. Current version shows 1d5372066082f23b41ba6aa278e56e9d::163. The trailing ::163 depicts ConEmu internal protocol version which may (and most probably would) be changed in the future. The hash itself is expected to be unchanged. You may query the ID from running ConEmu process using Windows API function GetApplicationUserModelId.
Thank you Maximus!

Find new window dialogs automatically

Let's say that I open up some word file with a macro that opens up a dialog with some buttons.
Is there a way to find those buttons automatically and press them (when having only the PID)?
Currently, I'm using pywinauto to automate the GUI testing. If there's a way to do it with pywinauto that would be great.
Thanks.
To summarize all the comments:
It's possible to enumerate all the windows and their controls using methods .windows() (for top-level windows), immediate .children() and all the .descendants() (the whole subtree as a plain list). You can even filter children and descendants by class_name, control_type, content_only and/or title.
Example:
print(app.windows()[0].descendants(control_type='Edit'))

The proper way to display multiple windows in tkinter?

I am currently working on a project using Python and tkinter.
The problem is that I don't know what's the proper way to display multiple windows, or screens, I don't know how to call them. Let me explain better.
When the application starts the login screen appears. After that, if I click register, I want to go to the register screen, but I don't want it to be a separate window (I don't want to have 2 windows displayed at the same time), but rather another window with different content ?!
How should I handle properly this situation? Create a second window using Toplevel and hiding the first (can I do that?) or changing the widgets of the first?
Code I've written so far
You can do that- just call window.withdraw() on the Toplevel you need to hide after creating a new Toplevel. Changing the widgets in the first is also an option- if you like, you could always try a Notebook widget and disable manual flipping or just put each "screen" in a frame and grid_ or pack_forget them to remove them from the window.

Tell windows which monitor to display dialogs on

I've got a program which is using multiple monitors. The program is showing special visualizations on the second monitor. At one point, the program uses windows shell functions to send files to the recycle bin. However, when it does this, the delete confirmation dialog comes on top of my visualization. This is particularly problematic, as when the mouse is on the second monitor, my program uses mouse hooks to capture all mouse input, so the user cannot even click the confirmation dialog.
Is it possible to somehow tell Windows to only place dialog boxes on a particular display?
I'm using python, though if I have to call C WinAPI functions that shouldn't be a problem
which function are you using to send the files to the recycle bin? if you use SHFileOperation you can pass a parent HWND. perhaps make that an invisible WS_EX_TOOLWINDOW window on the other monitor.
i would expect the API, treating that window as a parent, would center relative to that window, but i haven't tried it.
depending on which version of Windows you are targeting, there used to be a capability to create desk bands that 'dock' to the sides of the screen. this automatically gets factored into the area returned as rcWork by GetMonitorInfo and should prevent dialogs from overlapping this space. There might be another way to declare that a region is "in use" in a way that declares space off-limits, but I don't know of it so it probably doesn't exist...
the ugly and crude thing you could do is poll and move the dialog yourself, but if this is any kind of widely deployed or commercial app that would likely cause more harm than good.

PyGTK: Embed a window into another window

I want to embed a window into another window, kind of like this:
EDIT: Screenshots deleted, sorry!
That is a wingdows program and was not made with GTK tough.
I tried using plugs and sockets, but apparently I can't put a gtk.Window (a toplevel window) on a plug.
Is it possible? If so, how? If not, what do you think I should do instead?
gtk.Window is derived from gtk.Bin, so it can only contain one single child. This again can be used in the following way:
Load both windows (e.g. from Glade files)
Remove the child from the second window, but save a reference to the child
Add the child somewhere in the first window
The second step would look like this:
childWidget = secondWindow.get_child()
secondWindow.remove(childWidget)
I'm using this approach to add plugin windows as tabs in one of my PyGTK applications. That means main window and plugins can be designed separately in Glade, and also implemented independently. Of course you're free to add the child widget anywhere you want.

Categories