25

I'm trying to send some keys to an inactive window/process/program (Win32/64) using Python. Already read about pywinauto and SendKeys, but both of them activate the window before sending keys.

Is there any way to work with an inactive window without activating it?

It would be great if someone posted a simple example/snippet.

2
  • 2
    This might help: stackoverflow.com/q/5080777/1129194 Commented Oct 21, 2012 at 11:35
  • Wow, I rly missed any comments here =) your example looks like workin, will search more information about win32api.SendMessage methods. Thx! Commented Oct 23, 2012 at 18:33

3 Answers 3

46

This is a really old post but there has not been an answer here, I was looking for something exactly like this, and I had spend 6 hours going through Stackoverflow, and ended up just reading all the C documentation because it was more useful.

#you will need the win32 libraries for this snippet of code to work, Links below
import win32gui
import win32con
import win32api
from time import sleep

#[hwnd] No matter what people tell you, this is the handle meaning unique ID, 
#["Notepad"] This is the application main/parent name, an easy way to check for examples is in Task Manager
#["test - Notepad"] This is the application sub/child name, an easy way to check for examples is in Task Manager clicking dropdown arrow
#hwndMain = win32gui.FindWindow("Notepad", "test - Notepad") this returns the main/parent Unique ID
hwndMain = win32gui.FindWindow("Notepad", "test - Notepad")

#["hwndMain"] this is the main/parent Unique ID used to get the sub/child Unique ID
#[win32con.GW_CHILD] I havent tested it full, but this DOES get a sub/child Unique ID, if there are multiple you'd have too loop through it, or look for other documention, or i may edit this at some point ;)
#hwndChild = win32gui.GetWindow(hwndMain, win32con.GW_CHILD) this returns the sub/child Unique ID
hwndChild = win32gui.GetWindow(hwndMain, win32con.GW_CHILD)

#print(hwndMain) #you can use this to see main/parent Unique ID
#print(hwndChild)  #you can use this to see sub/child Unique ID

#While(True) Will always run and continue to run indefinitely
while(True):
    #[hwndChild] this is the Unique ID of the sub/child application/proccess
    #[win32con.WM_CHAR] This sets what PostMessage Expects for input theres KeyDown and KeyUp as well
    #[0x44] hex code for D
    #[0]No clue, good luck!
    #temp = win32api.PostMessage(hwndChild, win32con.WM_CHAR, 0x44, 0) returns key sent
    temp = win32api.PostMessage(hwndChild, win32con.WM_CHAR, 0x44, 0)

    #print(temp) prints the returned value of temp, into the console
    print(temp)
    #sleep(1) this waits 1 second before looping through again
    sleep(1)

I've seen posts all over to use

hwndEdit = win32gui.FindWindowEx(hwndMain, hwndChild, "Edit", "test - Notepad");

but I could never figure it out. In addition to that all documentation on Microsoft's site is vary ambiguous, So I've added my own of how I understand it.

That should get you started and should be helpful for others. If anyone else had revisions let me know.

Win32 Python Library

Sign up to request clarification or add additional context in comments.

6 Comments

Useful: here are the key codes for other keys than the "D" key: learn.microsoft.com/en-us/windows/desktop/inputdev/…
Are there similar libraries that exist for MacOS?
It seems, it is only possible to send text to inactive window. Other keys, e.g. Arrow Down, cannot be sent to inactive window.
how to send ctrl+c?
|
0

The beautiful code by mmsvsbg / Lithian Coth above is fantastic. I confirm it worked on my Windows 10 (64 bit) on Intel i7. Compiling the win32gui (which is now called pywin32) into 64 bit and few other little things too a bit of time but was do-able. For people needing to know step by step instructions to run the code by mmsvsbg/Lithian, I have it detailed out here: https://forums.whirlpool.net.au/thread/3nkwl0k9?p=-1#bottom

A quicker alternative is you can use a library already written to do the same and maybe more: It's called pywinauto: https://pywinauto.github.io/

Pywinauto pywinauto is a GUI automation library written in pure Python and well developed for Windows GUI. At its simplest it allows you to send mouse and keyboard actions to dialogs and controls on both Windows and Linux, while more complex text-based actions are supported on Windows only so far (Linux AT-SPI support is under development).

pywinauto 0.6.0 (Oct, 31) and 0.6.1 (Feb, 08) This big release introduces MS UI Automation (UIA) support (WinForms, WPF, Qt, browsers, Store apps and more). Documentation is built continuously now on ReadTheDocs. See also our improved Getting Started Guide Modules keyboard and mouse can be used out of any window context now. And they work on Linux as well! Multi-backend architecture allows to add new platforms support. Just implement two classes and register your backend! Code style is much closer to PEP8: ClickInput -> click_input. Though backend='win32' is ~80% backward compatible with pywinauto 0.5.4. Initial implementation of the win32_hooks module. Keyboard events (a.k.a hotkeys) and mouse actions handlers can be registered in the system. Example: hook_and_listen.py.

Comments

0

In most of the cases, it's trickier for background messages than just FindWindow and PostMessage, also sometimes requires keybd_event and SendMessage.

First, it's necessary to pick just the right handle, and often to find it again after every few commands. For example, in MS Excel or Notepad++ menu and contents have different handles. Finding them by caption or by process often picks the wrong top-level window. win32gui.WindowFromPoint usually catches the correct nested handle well (if it's visible).

Second, there are inconsistencies in how different programs react on messages:
Basic keys including Enter and Arrows:
Have not found an application which ignores them, but in many cases it was necessary to send a mouse click first to mimic focus.
PostMessage with WM_KEYUP and WM_KEYDOWN often produce letter twice, but for VK_RETURN just once. WM_CHAR is good for upper case symbols. Some applications like Chrome can work on background, but under very specific setup.
Mouse clicks:
They were quite reliable with

    win32api.PostMessage(hwnd, WM_LBUTTONDOWN, 1, make_lparam(cx, cy))
    # sleep(200)
    win32api.PostMessage(hwnd, WM_LBUTTONUP, 0, make_lparam(cx, cy))

Programs may have background redraw disabled, but still catch them correctly - it may require more than one click to notice any feedback. There were some cases like SourceTree when sleep delay was necessary.
Hotkeys like Ctrl+a:

    keybd_event(VK_LCONTROL, 0, KEYEVENTF_KEYDOWN, 0)
    PostMessage(hwnd, WM_KEYDOWN, code('a'), 0)
    PostMessage(hwnd, WM_KEYUP, code('a'), 0)
    keybd_event(VK_LCONTROL, 0, KEYEVENTF_KEYUP, 0)

Chrome ignores without focus, Notepad and Firefox react simultaneously with another focused window.
Excel does something, but not the hotkey. Firefox ignores the very same command when focused.

I once did a test tool specifically for these experiments (and updated it recently), it may be quite helpful to check under every specific use case. Should simplify at least the finding handle and win32gui.WindowFromPoint part.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.