键盘事件未使用pywin32发送到窗口

发布于 2021-01-29 17:02:02

我已经编写了一个代码,该代码可以从我想要的任何程序中获取HWND。因此,如果您提出要求,那就是我怎么得到的。

以下代码应调出设备管理器并将向下箭头发送到程序。

但是确实。它的确启动了设备管理器,但没有将向下箭头键发送给程序,至少没有任何反应。

如果我用记事本窗口的hwnd代码更改了hwndMain号,则该代码确实起作用并发送向下箭头键

import win32api
import win32con
import win32gui
import time

hwndMain = 133082
hwndChild = win32gui.GetWindow(hwndMain, win32con.GW_CHILD)
win32gui.SetForegroundWindow(hwndMain)
time.sleep(1)

win32api.SendMessage(hwndChild, win32con.WM_CHAR, 0x28, 0)

编辑

我试过了

win32api.SendMessage(hwndChild, win32con.WM_CHAR, win32con.WM_KEYDOWN, 0)

代替

win32api.SendMessage(hwndChild, win32con.WM_CHAR, 0x28, 0)

但这也不起作用。

我在python 2.7上

关注者
0
被浏览
46
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    每个 Win 窗口可以具有 0个
    或多
    个子窗口,并且每个子窗口也可以具有0个或多个自己的子窗口,依此类推…因此,每个窗口可能都有一整个子树。

    窗户不仅仅能吸引人的目光。用户可能会看一个(顶部)窗口,并想象它的树以某种方式看起来,而实际上树可能看起来完全不同(更复杂),因为可能有一些不可见的窗口。

    当将消息发送到窗口并期望发生某种行为时, 必须将 消息 发送到准确的窗口 (或发送给以转发它的方式设计的其祖先之一),否则消息将被忽略(因为
    错误的 窗口无法处理此类消息)。
    在我们的例子中,这意味着 WM_KEYDOWN (或 WM_CHAR )消息应该发送到:

    • 包含 记事 本文 的( 编辑 )窗口 __
    • TreeView )窗口保存 设备管理器 的设备列表 __

    您正在使用[ActiveState.Docs]:win32gui.GetWindow,其中包装了[MS.Docs]:声明(对于 GW_CHILD
    )的GetWindow函数

    如果指定的窗口是父窗口,则检索到的句柄在Z顺序的顶部标识子窗口。否则,检索到的句柄为 NULL
    。该功能仅检查指定窗口的子窗口。它不检查后代窗口。

    巧合的是 ,对于 记事本 将消息发送到其1日的孩子的作品,因为这孩子原来是非常 编辑 窗口,我上面提到的(除了那个孩子, 记事本
    只有另外一个它是 状态栏 ,就是这样,没有这些Windows拥有自己的任何子代)。

    另一方面,对于 设备管理器来说 ,事情并非如此简单。如您所见,它的结构更加复杂(例如,可见 ToolBar
    窗口)。按照建议,为了使用Windows,我正在使用[MS.Docs]:EnumChildWindows函数

    code.py

    #!/usr/bin/env python3
    
    import sys
    import pywintypes
    import win32gui
    import win32con
    
    
    def enum_child_proc(wnd, param):
        print("    Handling child 0x{:08X} - [{:}] - 0x{:08X}".format(wnd, win32gui.GetWindowText(wnd), win32gui.GetParent(wnd)))
        if param[0] >= 0:
            if param[1] == param[0]:
                win32gui.SendMessage(wnd, win32con.WM_KEYDOWN, win32con.VK_DOWN, 0)
                return 0
            param[1] += 1
    
    
    def handle_window(wnd, child_index=-1):
        print("Handling 0x{:08X} - [{:}]".format(wnd, win32gui.GetWindowText(wnd)))
        cur_child = 0
        param = [child_index, cur_child]
        try:
            win32gui.EnumChildWindows(wnd, enum_child_proc, param)
        except pywintypes.error as e:
            if child_index < 0 or e.args[0]:
                raise e
    
    
    def main():
        np_wnd = 0x01DB1EE2  # Notepad handle
        dm_wnd = 0x000E2042  # Device Manager handle
    
        handle_window(np_wnd, child_index=0)
        handle_window(dm_wnd, child_index=6)
    
    
    if __name__ == "__main__":
        print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
        main()
    

    注意事项

    • 我对2个窗口句柄( np_wnddm_wnd )进行了硬编码。显然,它们将无效(自从我关闭窗口以来,它们在我的机器上不再有效),并且它们的值需要更改
    • 为了找到窗口的句柄(及其某些子句),我使用了 Spy ++[MS.Docs]:如何:启动Spy ++),它是 VStudio的 一部分,但我确定还有很多其他类似的东西应用领域

    输出

    e:\Work\Dev\StackOverflow\q053778227>”e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe”
    code.py
    Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916
    64 bit (AMD64)] on win32

    Handling 0x01DB1EE2 - [Untitled - Notepad]
        Handling child 0x01811FA4 - [] - 0x01DB1EE2
    Handling 0x000E2042 - [Device Manager]
        Handling child 0x00621A5A - [] - 0x000E2042
        Handling child 0x01991F44 - [Device Manager] - 0x00621A5A
        Handling child 0x01691F3E - [] - 0x01991F44
        Handling child 0x000C20B0 - [] - 0x01691F3E
        Handling child 0x004D2000 - [] - 0x000C20B0
        Handling child 0x004420CA - [] - 0x004D2000
        Handling child 0x01191F20 - [] - 0x004420CA
    

    如从输出看出, 树视图 窗口是 7 个孩子(7的第的孩子:)) 设备管理器 窗口,意味着 有6中介(和不可见)之间的窗口
    (其忽略消息)。

    尽管代码可以解决上述问题, 但目前尚无适用于任何窗口的配方
    (或者,如果存在,我不知道)。我必须提到,我已经尝试通过查看树的子窗口来确定它感兴趣的子窗口:

    • 名称
    • 样式(该领域的 MS doc非常差)
      • 扩展风格
    • 位置(相对于其父对象)
    • SendMessage 的返回码

    但是我找不到任何可以将其与其他窗口区分开的东西。我注意到的唯一的事情是, 记事本 ,所需的窗口是1日孩子列举,而 设备管理器
    它是7日,所以我没滤波基于这个事实(在 CHILD_INDEX ),但我认为这是 完全不可靠的

    作为替代方案,可能根本不进行过滤,而是将消息发送到树中的所有子窗口,但这可能会产生不良影响,因为可能会有其他窗口对此消息做出响应。例如, 设备管理器
    树由 约30 个子窗口组成。

    最后,我还要提及一些窗口(例如 Chrome的 网络浏览 )具有自己的Windows系统,因此这些都不起作用。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看