简体   繁体   English

使用Python切换Windows

[英]Switching Windows with Python

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. 首先,我将对python缺乏经验,并希望这意味着解决问题的方法很简单。

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. 我相当确定我可以使用find_window并将其设置为前台的win32gui实现此目的。 I thought I had found my solution when I came across this previous question: Python Window Activation 我以为我遇到上一个问题时找到了解决方案: Python窗口激活

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. -用户定义find_window的方式仅允许您通过窗口的类名进行选择,我不知道也无法找到它,因为它只是用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. -使用在该脚本中编写的find_window_wildcard设法将窗口置于前台几次,但前提是该窗口已经打开且只能间歇性地工作。

-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. -set_foreground()需要一个输入语句,无论我如何尝试设置它,我总是会得到一个错误,即我的元素数量错误或窗口上的句柄无效。

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. 但是对这个问题的清晰简洁的解决方案,或者至少对find_window / getwindow语法的一个很好的解释,对我自己和任何遇到这个问题的人来说都是天赐的礼物。

I would strongly suggest you take a look at the pages for Swapy and for pywinauto . 强烈建议您看一下Swapypywinauto的页面。 They can help you do some awesome things when it comes to UI Automation. 当涉及到UI自动化时,它们可以帮助您做一些很棒的事情。

The way that user had defined find_window only allows you to choose by the classname of the window 用户定义find_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 ). 用户定义它的方式是将两个参数class_namewindow_name地传递给win32gui.FindWindow (后者仅调用Win32 API函数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; 但是,即使事实并非如此,您也无需使用他的find_window函数。 it should be pretty obvious how to call win32gui.FindWindow yourself: 自己如何调用win32gui.FindWindow应该很明显:

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

And if you want a good explanation of the FindWindow / EnumWindows /etc. 如果您想对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 …窗口的类名,我不知道也找不到,因为它只是用Java运行的游戏

What difference does it make that it's running in Java? 它可以在Java中运行有什么区别? You can enumerate the windows and print out their classnames, whether they're written in C++, Java, .NET, Python, or anything else. 您可以枚举窗口并打印出它们的类名,而不管它们是用C ++,Java,.NET,Python还是其他任何语言编写的。 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. 或使用Visual Studio / VS Express附带的工具之一,或可以在网上找到的任何免费的改进版本,例如MS Spy ++ ,它将使您指向一个窗口并为您提供标题和类名。

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. 只需使用正则表达式调用windowmgr.find_window_wildcard(wildcard) ,它将枚举窗口并将其标题与该正则表达式进行比较。

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, eg, 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.) …它将在每个窗口调用一次my_callback函数,其中hwnd是窗口(您可以将其传递给win32gui函数,例如GetWindowText ),而cookie是您传递的相同some_cookie值。(如果不需要任何东西传入,只需传递None ,并且不对回调函数中的值做任何事情。但是您可以看到其他应答者如何使用它来传递正则表达式。)

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. 使用该脚本中编写的find_window_wildcard可以成功地将窗口置于前台几次,但find_window_wildcard是该窗口已经打开且只能间歇性地工作。

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 ; 无论如何,您无需使用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? 因此,如果类名不是唯一的(或者更糟的是,它是特殊的“数字”类之一,如通用对话框窗口的#32770),该窗口名也不是唯一的怎么办? 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. 通过查看拥有进程或模块(exe / dll),父窗口或其他内容,您也许可以缩小范围。 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. 您必须仔细阅读win32gui和/或MSDN文档(以上链接),以尝试可能的事情,并反复试验(请记住间谍工具),直到找到唯一指定窗口的方法。 Then code that up. 然后进行编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM