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

时间:2019-02-26 09:54:18

标签: python windows user-interface winapi automation

此代码(从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可能会打开对话框,关闭对话框,打开其他窗口的情况,因此解决方案应该能够将击键发送给进程的活动窗口。因此,具有固定here的hWnd的解决方案无法直接使用。

1 个答案:

答案 0 :(得分:1)

为了将击键发送到任何应用程序窗口,而无需激活应用程序以获取输入焦点。我们必须先获取Windows处理程序。这需要Windows API FindWindowFindWindowsEx。首先,通过FindWindow获取应用程序顶级窗口的句柄。然后使用FindWindowsEx获取子窗口的句柄或控件以接收键。 由于应用程序的顶部窗口并不总是接受按键的窗口(例如notepad.exe,实际上接受按键的窗口是记事本主窗口下的Edit控件),因此可以通过ClassID或Caption找到它。

假设目标窗口的句柄已被获取(hwnd),则密钥消息将通过PostMessage发送到窗口。

对于普通的字符键,最简单的直接使用WM_CHAR消息的方法如下:

PostMessage(hwnd, WM_CHAR, 'a', 0);

对于非正常的字符键,例如功能键,方向键等,应按以下方式使用WM_KEYDOWNWM_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);

您可以参考msdn的最后一个参数(lParam)的详细信息。

对于键“ 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。