将击键发送到特定窗口(在后台),但同时执行其他操作

Bas*_*asj 5 python windows user-interface winapi automation

这段代码(灵感来自哪个是在 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)
Run Code Online (Sandbox Code Playgroud)

我想让这个操作在后台继续,继续我在计算机上的工作,并将击键发送到记事本(在后台)

问题:如果我同时打开另一个应用程序(例如:浏览器),击键将被发送到当前活动窗口,这是我不想要的!

问题:即使此应用程序不在前台,如何让 Python将击键发送到 notepad.exe ?

上下文:我正在自动化一些长期任务,要求我的 Python 脚本app.exe在大约 15 分钟内向(在后台)发送击键,但同时我想用计算机做其他事情。

注意:更一般地说,我感兴趣的用例是进程 app.exe 可能打开对话框、关闭对话框、打开其他窗口的情况,因此解决方案应该能够将击键发送到进程活动窗口. 因此,像这里这样具有固定 hWnd 的解决方案不能直接工作。

Dra*_*SFT 4

为了将击键发送到任何应用程序窗口,而无需激活应用程序来获取输入焦点。我们必须首先获得窗口处理程序。这需要 Windows APIFindWindowFindWindowsEx. 首先,通过 获取应用程序顶级窗口的句柄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);
Run Code Online (Sandbox Code Playgroud)

最后一个参数()的详细信息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);
Run Code Online (Sandbox Code Playgroud)

对于“Alt”键,它属于系统按钮,使用WM_SYSKEYDOWN/WM_SYSKEYUP消息。样本:

PostMessage(hwnd, WM_SYSKEYDOWN, VK_F4, 0x003E0001 |0x20000000);
PostMessage(hwnd, WM_SYSKEYUP, VK_F4, 0xC03E0001 | 0x20000000);
Run Code Online (Sandbox Code Playgroud)

0x20000000表示上下文代码,如果按下“Alt”键,则值为 1。