如何将键盘事件发送到 Pywin32 中的不同窗口?

Posted

技术标签:

【中文标题】如何将键盘事件发送到 Pywin32 中的不同窗口?【英文标题】:How to send a keyboard event to a different Window in Pywin32? 【发布时间】:2013-01-28 08:31:35 【问题描述】:

我必须编写一个脚本来在后台的不同程序中模拟一些键盘事件。这是我的代码:

pwin = win32ui.FindWindow(None,r'someprograme')
pwin.SendMessage(win32con.WM_KEYDOWN,18)
pwin.SendMessage(win32con.WM_KEYDOWN,68)
pwin.SendMessage(win32con.WM_KEYUP,18)
pwin.SendMessage(win32con.WM_KEYUP,68)
pwin.SendMessage(win32con.WM_KEYDOWN,13)
pwin.SendMessage(win32con.WM_KEYUP,13)

但似乎什么也没发生。那我该怎么办?我试过 PostMessage func 似乎仍然无法做到。

【问题讨论】:

首先,您确定pwin 是正确的窗口吗?其次,它有键盘焦点吗?第三,你为什么不通过两个参数? (我还没有检查文档;也许 0 总是适合 lparam?)最后,那些键是什么? (你知道WM_KEYDOWN 不能用于ALT 的大多数用途,对吧?) 另外,您要驱动什么应用程序? 看来我没有找到正确的窗口。我想向程序发送 ALT+D 以打开某事。那么如果 WM_KEYDOWN 不能使用,我怎么发送呢? 对于您的第一点:如果您没有合适的窗口,其他的东西都不重要;你显然必须先找到正确的窗口,否则你甚至无法测试。 第二个:为什么要向程序发送Alt+D?你想打开什么?通常这会弹出菜单栏中的第一个菜单,名称中带有下划线“D”。那是你想要做的吗?如果是这样,请参阅我的回答,其中我解释了为什么它在许多应用程序中不起作用,以及该怎么做。 【参考方案1】:

快速浏览一下WM_KEYDOWN docs:

当按下非系统键时,以键盘焦点发布到窗口。非系统键是在未按下 ALT 键时按下的键。

但是查找your keycodes,您正在尝试发送 ALT-D(后跟 ENTER,这很好)。听起来您正在尝试驱动菜单;如果这就是你想要做的,WM_KEYDOWN 不是这样做的方法。

问题在于键盘菜单导航是由 Windows 驱动的,而不是由应用程序驱动的(少数应用程序会覆盖正常的菜单处理,例如某些版本的 Visual Studio)。当您查看记事本并按 ALT-F 打开“文件”菜单时,记事本代码会收到一堆与菜单相关的消息(WM_INITMENU 等),而不是按键。

如果您使用 WM spy 程序(我认为免费的 Visual Studio Express 仍然带有 Spy++ 和 ManagedSpy,但如果没有,请搜索等效程序),您可以在使用键盘,然后你可以弄清楚如何从你的 Python 脚本中模拟它。

除此之外,根据程序的编写方式,它可能在没有焦点时不接受击键。

顺便说一句,如果您刚刚开始使用 Windows GUI 自动化,您可能希望查看更高级别的内容,例如 pywinauto。这样,您不必计算要发送哪些与菜单相关的消息来打开“数据”菜单;您只需执行app.Foo.MenuSelect('Data') 之类的操作即可。

【讨论】:

谢谢,我已经使用 pywinauto 完成了任务。当使用 sendkeys 而不是 keyevent 时,它可以工作

以上是关于如何将键盘事件发送到 Pywin32 中的不同窗口?的主要内容,如果未能解决你的问题,请参考以下文章

如何自动化 UI 键盘输入? pywin32 PostMessage vs Powershell SendKeys

如何使用 pywin32 在 Python 中获取特定应用程序窗口的句柄?

python如何设置按键松开

Pywinauto常用02--pywin32(Python调用win api)

pywin32 怎么获取 windows 的窗体内文本框的内容

UI自动化控制微信发送文件解决了一个无人回答的难题,Pywin32设置文件到剪切板