【问题标题】:Is it possible to send data to a minimized window use pywinauto?是否可以使用 pywinauto 将数据发送到最小化窗口?
【发布时间】:2011-06-16 17:28:30
【问题描述】:

几个月前,我编写了一个 Python GUI 应用程序,用于读取包含车辆数据的文件。然后它使用 sendkeys 模块在温室气体模型应用程序中输入数据。我已将代码转换为使用 pywinauto 并使用 pywinauto 中的应用程序模块来启动温室气体应用程序。

我希望在后台显示温室气体应用程序窗口,或者在向其发送数据时将其最小化。我担心用户会尝试关闭窗口或想知道如果显示温室气体窗口会发生什么。

我在 python win32gui 模块中使用以下函数来最小化温室气体应用程序窗口:

hndl 是我使用 win32gui.EnumWindows() 找到的温室气体窗口的句柄

win32gui.ShowWindow(hndl,win32con.SW_MINIMIZE)

设置焦点

win32gui.SetForegroundWindow(hndl)

当我添加上面的代码时,温室气体应用程序窗口被最小化。不幸的是,pywinauto 中的 SendKeys 模块不会将信息发送到最小化窗口。

有没有办法解决这个问题?感谢您的帮助。

【问题讨论】:

    标签: pywinauto


    【解决方案1】:

    TypeKeys()SendKeysCtypes()(当前版本的pywinauto 使用此模块发送按键)模块无法使用。这是因为他们使用SendInput win API,该 API 仅适用于活动应用程序(如果最小化,应用程序将不会处于活动状态。

    也就是说,以下内容可能有用: 更改编辑文本:

    app.Dialog.Edit.SetEditText("Your Text")
    

    单击按钮或复选框等:

    app.Dialog.ButtonEtc.Click()
    

    这些可以与处于后台的应用程序一起使用。我尝试隐藏窗口 - 但上述方法不起作用:((因为默认情况下,大多数 pywinauto 都试图确保窗口可见 + 已启用。

    要获得隐藏窗口,您可以使用:

    hidden_win = app.window_(title = "Untitled - Notepad", visible_only = False)
    

    并获得一个子窗口 - 类似于:

    edit_control = hidden_win.ChildWindow(visible_only = False, class_name = "Edit")
    

    但不幸的是 - 你在使用 pywinauto 时有点卡住了(因为edit_control.SetEditText(...) 会检查窗口是否可见:()

    这里是一些被破解的代码,它们或多或少可以设置编辑文本的值(注意 SetEditText 和 Select 都是从 pywinauto 复制的 - 并稍作更改,以便:

    1. 他们不检查控件是否可见

    2. 它们是独立的函数

    代码:

    import win32gui
    import win32con
    import sys
    import os
    sys.path.append(os.path.abspath('.'))
    print sys.path[-1]
    from pywinauto import application
    from pywinauto import win32defines
    from pywinauto import win32functions
    from pywinauto.timings import Timings
    import time
    import ctypes
    
    #-----------------------------------------------------------
    def Select(win, start = 0, end = None):
        "Set the edit selection of the edit control"
    
        # if we have been asked to select a string
        if isinstance(start, basestring):
            string_to_select = start
            #
            start = win.TextBlock().index(string_to_select)
    
            if end is None:
                end = start + len(string_to_select)
    
        if end is None:
            end = -1
    
        win.SendMessageTimeout(win32defines.EM_SETSEL, start, end)
    
        # give the control a chance to catch up before continuing
        win32functions.WaitGuiThreadIdle(win)
    
        time.sleep(Timings.after_editselect_wait)
    
        # return this control so that actions can be chained.
        return win
    
    #-----------------------------------------------------------
    def SetEditText(win, text, pos_start = None, pos_end = None):
        "Set the text of the edit control"
        # allow one or both of pos_start and pos_end to be None
        if pos_start is not None or pos_end is not None:
    
            # if only one has been specified - then set the other
            # to the current selection start or end
            start, end = win.SelectionIndices()
            if pos_start is None:
                pos_start = start
            if pos_end is None:
                pos_end = end
    
            # set the selection if either start or end has
            # been specified
            win.Select(pos_start, pos_end)
        else:
            Select(win)
    
        # replace the selection with
        text = ctypes.c_wchar_p(unicode(text))
        win.SendMessageTimeout(win32defines.EM_REPLACESEL, True, text)
    
        win32functions.WaitGuiThreadIdle(win)
        time.sleep(Timings.after_editsetedittext_wait)
    
        # return this control so that actions can be chained.
        return win
    
    # this may be useful if you just want to send a keydown/keyup combination
    def keystroke(hwnd, key):
        win32gui.PostMessage(hwnd, win32con.WM_KEYDOWN, key, 0)
        win32gui.PostMessage(hwnd, win32con.WM_KEYUP, key, 3 < 30)
    
    
    app = application.Application.start('notepad')
    
    # hide the window
    win32gui.ShowWindow(app.window_(title = "Untitled - Notepad", visible_only = False).handle, win32defines.SW_HIDE)
    print "See it is hidden :)"
    time.sleep(2)
    
    # get tehe edit control and set it's text
    edit = app.window_(title = "Untitled - Notepad", visible_only = False).ChildWindow(visible_only = False, class_name = "Edit")
    SetEditText(edit, "The edit text has been set")
    
    # show the window again
    win32gui.ShowWindow(app.window_(title = "Untitled - Notepad", visible_only = False).handle, win32defines.SW_SHOW)
    

    这是如何改进 pywinauto 的一个很好的例子(通过提供一个较低级别的库,这样可以更容易地做这样的事情)

    【讨论】:

    • 感谢马克的快速回复。
    猜你喜欢
    • 1970-01-01
    • 2012-09-02
    • 2015-12-27
    • 2021-08-21
    • 2016-04-28
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多