Switching Windows with Python

16,508

Solution 1

I would strongly suggest you take a look at the pages for Swapy and for pywinauto. They can help you do some awesome things when it comes to UI Automation.

Solution 2

The way that user had defined find_window only allows you to choose by the classname of the window

The way the user defined it is to pass the two parameters class_name and window_name through, untouched, to win32gui.FindWindow (which in turn just calls the Win32 API function FindWindow). So, just do this:

windowmgr.find_window(None, 'My Window Name')

But even if that weren't true, you don't need to use his find_window function; it should be pretty obvious how to call win32gui.FindWindow yourself:

hwnd = win32gui.FindWindow(None, 'My Window Name')

And if you want a good explanation of the FindWindow/EnumWindows/etc. syntax, did you try looking at the docs for them? Is there something you didn't understand there?

Meanwhile:

… the classname of the window, which I don't know and haven't been able to find since it is just a game running in Java

What difference does it make that it's running in Java? You can enumerate the windows and print out their classnames, whether they're written in C++, Java, .NET, Python, or anything else. Or use one of the tools that comes with Visual Studio/VS Express, or any of the free improved versions you can find all over the net, like MS Spy++, which will let you point at a window and give you the caption and class name.

I don't want to enumerate the windows to find it as I'm not sure how that would work.

Just call windowmgr.find_window_wildcard(wildcard) with a regular expression, and it'll enumerate the windows and compare their titles to that regular expression.

If you want to write your own code to do it, just write a function like this:

def my_callback(hwnd, cookie):

Now, when you do this:

win32gui.EnumWindows(my_callback, some_cookie)

… it will call your my_callback function once per window, with hwnd being the window (which you can pass to win32gui functions like, e.g., GetWindowText), and cookie being the same some_cookie value you passed in. (If you don't need anything passed in, just pass None, and don't do anything with the value in your callback function. But you can see how the other answerer used it to pass the regular expression through.)

Meanwhile:

using find_window_wildcard as it's written in that script has managed to bring the window to the foreground a few times, but only if the window was already open, and it only works intermittently.

First, you can't bring a window to the foreground if it doesn't exist. How do you expect that to work?

As far as working intermittently, my guess is that there are lots of windows that match your wildcard, and the program is going to just pick one of them arbitrarily. It may not be the one you want. (It may even be a hidden window or something, so you won't see anything happen at all.)

At any rate, you don't need to use find_window_wildcard; if you know the exact name, use that. Of course it still may not be unique (whatever the game's name is, there's nothing stopping you from opening an email message or a Notepad window with the same title… which, by the way, is why you want to try class names first), but at least it's more likely to be unique than some underspecified wildcard.

So, what if the class name isn't unique (or, even worse, it's one of the special "number" classes, like #32770 for a general dialog window), and neither is the window name? You may be able to narrow things down a little better by looking at, say, the owning process or module (exe/dll), or the parent window, or whatever. You'll have to look through the win32gui and/or MSDN docs (linked above) for likely things to try, and play around through trial and error (remember the Spy tool, too) until you find some way to specify the window uniquely. Then code that up.

Share:
16,508
Admin
Author by

Admin

Updated on July 15, 2022

Comments

  • Admin
    Admin almost 2 years

    I'll preface this by saying that I'm very inexperienced with python, and I'm hoping that means the solution to my problem will be simple.

    My program will be performing simple actions in another window, so ideally I would like my script to make sure that this other window is maximized and active before it proceeds with the rest of the commands. This has proved to be much more difficult than I had expected.

    I am fairly certain that I can achieve this with win32gui using find_window and setting it to the foreground. I thought I had found my solution when I came across this previous question: Python Window Activation

    Unfortunately I was unable to use the solution code or manipulate it to solve my problem for a few reasons:

    -The way that user had defined find_window only allows you to choose by the classname of the window, which I don't know and haven't been able to find since it is just a game running in Java. I couldn't seem to change that line to work for the specific windowname (Which I do know) as it is not the "default argument".

    -I don't want to enumerate the windows to find it as I'm not sure how that would work.

    -using find_window_wildcard as it's written in that script has managed to bring the window to the foreground a few times, but only if the window was already open, and it only works intermittently.

    -set_foreground() requires one input statement and no matter how I try to set it I am always given an error that I either have the wrong number of elements or an invalid handle on the window.

    I know that I'm stupid; but a clear and concise solution to this problem or at least a good explanation of the find_window/getwindow syntax would be a godsend to myself and anyone else who's having this problem.