此代码(灵感来自 Which is the easiest way to simulate keyboard and mouse on Python?)打开记事本并每秒发送键 A、B、C、D、...、Z:
import win32com.client, time
shell = win32com.client.Dispatch("WScript.Shell")
shell.Run('Notepad')
time.sleep(1)
shell.AppActivate("Notepad")
for i in range(65,91):
shell.SendKeys(chr(i))
time.sleep(1)
我想让这个操作在后台继续,继续我在计算机上的工作,并将击键发送到记事本(在后台)。
问题:如果我同时打开另一个应用程序(例如:浏览器),击键会发送到...到当前事件的窗口,这是我不想要的!
问题:即使此应用程序不在前台,如何让 Python 仅将击键发送到 notepad.exe?
上下文:我正在自动执行一些较长的任务,要求我的 Python 脚本在大约 15 分钟内将击键发送到 app.exe
(在后台),但我想用同时使用计算机。
注意:更一般地说,我感兴趣的用例是进程 app.exe 可能打开对话框、关闭对话框、打开其他窗口的情况,因此解决方案应该能够将击键发送到 进程的事件窗口。因此,具有固定 hWnd 的解决方案如 here不直接工作。
为了向任何应用程序窗口发送击键,而不激活应用程序以获得输入焦点。我们必须先获取窗口处理程序。这需要 Windows API FindWindow
和 FindWindowsEx
。首先,通过FindWindow
获取应用程序顶级窗口的句柄。然后使用 FindWindowsEx
获取子窗口或控件的句柄以接收键。
因为应用程序的顶层窗口并不总是接受Keystroke的窗口(比如notepad.exe,真正接受Keystroke的窗口是记事本主窗口下的Edit控件),可以通过ClassID或者Caption找到。
假设已经得到了目标窗口的句柄(hwnd),则通过PostMessage
向窗口发送按键消息。
对于普通的字符键,直接使用WM_CHAR消息最简单,如下:
PostMessage(hwnd, WM_CHAR, 'a', 0);
对于非普通字符键,如功能键、方向键等,WM_KEYDOWN
和WM_KEYUP
消息应按如下方式使用:
VirtualKey = MapVirtualKeyA(VK_RIGHT, 0);
PostMessage(hwnd, WM_KEYDOWN, VK_RIGHT, 0x0001|VirtualKey<<16);
PostMessage(hwnd, WM_KEYUP, VK_RIGHT, 0x0001|VirtualKey<<16|0xC0<<24);
最后一个参数(lParam
)的详细信息可以引用msdn .
对于“Shift/Ctrl”键,示例:
keybd_event(VK_SHIFT, 0, 0, 0);
PostMessage(hwnd, WM_KEYDOWN, 0x41, 0x001E0001);
PostMessage(hwnd, WM_KEYUP, 0x41, 0xC01E0001);
keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
对于“Alt”键,属于系统键,使用WM_SYSKEYDOWN
/WM_SYSKEYUP
消息。示例:
PostMessage(hwnd, WM_SYSKEYDOWN, VK_F4, 0x003E0001 |0x20000000);
PostMessage(hwnd, WM_SYSKEYUP, VK_F4, 0xC03E0001 | 0x20000000);
0x20000000
表示上下文代码,如果“Alt”键按下则值为1。