pywinauto send key down to application - python

I want to send key down events to game applications using pywinauto. I get the application like this:
from pywinauto.application import Application
app = Application()
app.connect(title='Adobe Flash Player 29')
win = app.window_(title_re = "Adobe Flash Player 29")
This allows me to send things like mouse clicks to the application:
win.Click(coords=(300,330))
This works fine, and I can also send "TypeKeys" events to the application:
while True:
win.TypeKeys("w")
However, instead of holding the key down, it repeatedly sends single letters to the game. I need a way to hold the key down instead (and this must be in context of an application, not just a raw keyboard input).
EDIT: I mean I want to send held key presses to applications other than the active window

from pywinauto.keyboard import SendKeys
<...code>
SendKeys('{DOWN}') # Keyboard input
# in case of element
element.type_keys('{DOWN}')
checkout this Link, Hope this will help you.

Related

sending a keyboard input to a game running in the background [duplicate]

This question already has an answer here:
SendMessage doesn't work for some applications
(1 answer)
Closed last month.
I want to send keyboard input to a game running in the background (game: Knight Online) but the win32api.SendMessage, PostMessage methods are not working. how can I do that
I tried the code in this link
code:
from time import sleep
import win32gui
import win32con
def callback(handle, param):
s = win32gui.GetClassName(handle)
try:
print(f'Sending key to {handle}, {s}')
win32gui.SendMessage(handle, 0x0102, 0x5A, 0)
sleep(.5)
except Exception:
print('Exception sending to {handle}, {s}')
window_id = win32gui.FindWindow(None, "Knight OnLine Client")
win32gui.EnumChildWindows(window_id, callback, 0)
output:
Sending key to 23004754, Edit
Sending key to 1639850, Edit
Sending key to 10421696, Edit
the input does not work in the game
Why it doesn't work
There are many stops along the pipeline from a keypress to an application. And applications can choose where along that pipeline to receive keyboard input.
You're sending 0x0102 which is WM_CHAR. That's about as far to the end of the pipeline as you can go. It's likely the game is tapping the pipe earlier.
When you press a physical key, the keyboard driver places an input event in an input queue.
When the OS pulls that event from the input queue, it places a WM_KEYDOWN message in the message queue for the thread that owns the window with the input focus.
When the application's GUI thread pulls the message from queue, it may choose to route it through an API called TranslateMessage, which watches for low level keyboard messages like WM_KEYDOWN and WM_KEYUP.
TranslateMessage synthesizes WM_CHAR (and/or WM_UNICHAR) and sends them to the window (just before allowing the keyboard message to be processed). These messages tell the program that the user has typed a character (for example, a capital E with an acute accent) which can be done only with a series of keyboard messages.
Meanwhile, part of the system is tracking the state of the entire keyboard at different points in time.
One of those is the asynchronous keyboard state, which watches that input queue so that it knows what's happening on the keyboard right now. Games can query this with GetAsyncKeyState (and maybe with the legacy DirectInput API). A fast video game might rely on this (after checking that they are the "active" window).
There's also a synchronous keyboard state, which is tracked per GUI thread as the threads pull keyboard messages from their queues. Imagine if a thread fell behind and a lot of keyboard messages were still queued up. The synchronous keyboard state (from GetKeyState or GetKeyboardState) would indicate the keyboard state at the time the most recently processed window message was posted, which may be different that the asynchronous state which would already reflect all of the messages still in the queue.
The character input messages, like WM_CHAR, are useful for text editors, word processors, etc. But even they must tap the pipeline earlier for keystrokes like Page Up and Page Down.
Many apps work primarily with the WM_KEYDOWN and WM_KEYUP messages.
Fast video games likely use the asynchronous keyboard state or perhaps the synchronous one. And they may purposely not process any keyboard input when they are in the background.
What you can try
The easiest thing to try is to send (or better, post) WM_KEYDOWN and WM_KEYUP messages instead of WM_CHAR. That won't guarantee success.
Windows has the SendInput API for putting events in the input queue (the way the keyboard driver does). I don't know if there's a Python library that covers that. Even if there is, it's not likely to help, since the system won't send your injected keyboard input events to a background window.

Hook Mouse clicks and intercept them

I am currently trying to stop mouse clicks while my Script is running and still work with them.
If you are confused about the use case I will elaborate at the end of the question.
Currently I can get clicks like this:
import mouse
import time
def mouseHook(event):
if type(event) == mouse.ButtonEvent:
print(event)
mouse.hook(mouseHook)
while 1:
time.sleep(0.25)
But this still lets the clicks go through, how would I intercept them?
use case: simulate a monitor and while mouse is on that monitor send all movements, clicks and keypresses to MacBook (similar to Synergy, Mouse without Borders or Share Mouse)
The hook used by the application only 'hooks' into the process, which means it gets information from it, but can't insert or modify it's code.
For reference on windows that would use (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644988(v=vs.85))
The easiest way would be to have your application ignore the mouseclicks.

How to send DirectInput keys to an inactive window in Python

I would like to send DirectInput keys to an inactive window without interfering with my actual mouse. I tried using PostMessage, SendInput and SendMessage but pywin32 uses virtual keycodes while ctypes does work with DirectInput. I have no idea how I can make it send in an inactive window.
Try using this, it manages to work for me send the keystrokes to the inactive window,
Use (but add error checking) hwndMain = win32gui.FindWindow("notepad", "​prueba.txt: log keys") hwndEdit = win32gui.FindWindowEx

NSEvent global event monitoring in background

I am writing a simple Mac application designed to run in the background and perform certain actions whenever the user clicks the mouse button. The app is written in Python using PyObjC. I am using addGlobalMonitorForEventsMatchingMask to watch for NSLeftMouseDown events:
NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSLeftMouseDownMask, handler)
This code works perfectly when running in the terminal. However, when I bundle it as a standalone app (using py2app) and then launch it, the app doesn't receive any events at first. (Or at least, if it does, it doesn't run the code in my handler method.) Only when I click on the app in the Dock does it start receiving events, and after that, it continues to receive events even after it returns to the background. But it doesn't receive anything until activated once.
My question is: How can I get my app to start receiving events as soon as it is launched, without having to be activated first by clicking the Dock icon? Is this some known quirk of NSEvents, or is there perhaps something wrong with my run loop in PyObjC?
Any help or guidance is greatly appreciated!
Edit: Upon further testing, it seems that, in fact, my app spontaneously starts receiving notifications about ten seconds after launch, regardless of whether I activate it. Which is slightly annoying, but fine.
However, if I run the app with either LSUIElement = true or LSBackgroundOnly = true in my Info.plist (which I ultimately want to do, since this app should only run in the background and never appear in the Dock), I never receive notifications. So I am still stuck.
As you said "Only when I click on the app in the Dock does it start receiving events" , that means the handler gets registered after you click on the app in the Dock.
So it depends on at which point in the code you are calling this : NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSLeftMouseDownMask, handler) ,
that is registering the handler.
You should register the handler in appdidfinishlaunching function.

Send Key Event to a Child Window

I'm developing an application in python which sends keyboard events to another external application. I use the pywin32 package to set the external application and send the desired key:
import win32com.client as w32
shell = w32.Dispatch("WScript.Shell")
shell.AppActivate(desired_application)
shell.SendKeys("{ENTER}")
The external application I'm using has a virtual keyboard and a text area which receives the events of the keyboard. I want to send the key event (in this case, an 'ENTER') to the keyboard area (because the keyboard is making a scan through the letters and will select the desired letter with an Enter). However, my application is sending the key events to the text area instead of the keyboard.
I tried to get the handle of the window I want with FindWindow and EnumChildWindow from win32gui... So, is there a way to send the keys to the specific child window of the external application?
I manage to choose the specific handle with EnumChildWindow (to enumerate all the handles of the application) and send the message with PostMessage.
import win32api
win32api.PostMessage(handler, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)

Categories