开发者

Is it possible to send data to a minimized window use pywinauto?

Several months ago, I wrote a Python GUI app that reads a file containing vehicle data. It then uses the sendkeys module to enter the data on a green house gas model app. I've converted the code to use pywinauto and use the application module in pywinauto to start the green house gas app.

I would like to have the green house gas applica开发者_StackOverflow社区tion window in the background or minimized when data is being sent to it. I am concerned that a user will try to close the window or wonder what is going on if the green house gas window is displayed.

I use the following functions in the python win32gui module to minimize the green house gas app window:

hndl is the handle to the green house gas window I found using win32gui.EnumWindows()

win32gui.ShowWindow(hndl,win32con.SW_MINIMIZE)

Set the focus

win32gui.SetForegroundWindow(hndl)

When I added the code above, the green house gas app window is minimized. Unfortunately, the SendKeys module in pywinauto doesn't send information to a minimized window.

Is there any way around this? Thank you for your help.


TypeKeys() or the SendKeysCtypes() (current versions of pywinauto use this module for sending key strokes) module cannot be used. This is because they use the SendInput win API which just works with the active application (and the application will not be active if it is minimized.

That said the following may be useful: Change an Edit text:

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

Click a button or Checkbox, etc:

app.Dialog.ButtonEtc.Click()

These can work with the application being in the background. I tried hiding the window - but the above didn't work :( (because by default most of pywinauto is trying to ensure that the window is visible + Enabled.

To get a hidden window you can use:

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

and to get a child window - something like:

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

But then unfortunately - you are a bit stuck when using pywinauto (because edit_control.SetEditText(...) will check that the window is visible :( )

Here is some hacked together code that will more or less work to set the value of an edit text (note SetEditText & Select are both copied from pywinauto - and changed slightly so that:

  1. they do not check that the control is visible

  2. they are standalone functions

Code:

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)

This is a great example of how pywinauto could be improved (by providing a lower level library that would make it easier to do stuff like this)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜