Unknown
Unknown

Reputation: 33

Python win32api keybd_event: How do I input a string of characters?

I used the below to get the Window Handle of an app and bring it to be the focus. I want to type in a string of characters into the app. But using win32api.keybd_event, I am able to type in only single characters? Is there a way to type in a string of characters?

Eg, "I am happy"

Thank you

import win32gui
import win32api
import win32con

hld = win32gui.FindWindow (None, "UNTITLED") # Returns the handle of the window titled UNTITLED

if hld>0:

    win32gui.SetForegroundWindow(hld)
    win32api.keybd_event(0x46, 0, ) # F

Upvotes: 1

Views: 2820

Answers (1)

Zeus
Zeus

Reputation: 3890

You can use the SendInput function to achieve this. Send the string you need to send to the corresponding window once through this function.

I created a sample as follows:

import ctypes as ct
from win32con import SW_MINIMIZE, SW_RESTORE
from win32ui import FindWindow, error as ui_err
from time import sleep

class cls_KeyBdInput(ct.Structure):
    _fields_ = [
        ("wVk", ct.c_ushort),
        ("wScan", ct.c_ushort),
        ("dwFlags", ct.c_ulong),
        ("time", ct.c_ulong),
        ("dwExtraInfo", ct.POINTER(ct.c_ulong) )
    ]

class cls_HardwareInput(ct.Structure):
    _fields_ = [
        ("uMsg", ct.c_ulong),
        ("wParamL", ct.c_short),
        ("wParamH", ct.c_ushort)
    ]

class cls_MouseInput(ct.Structure):
    _fields_ = [
        ("dx", ct.c_long),
        ("dy", ct.c_long),
        ("mouseData", ct.c_ulong),
        ("dwFlags", ct.c_ulong),
        ("time", ct.c_ulong),
        ("dwExtraInfo", ct.POINTER(ct.c_ulong) )
    ]

class cls_Input_I(ct.Union):
    _fields_ = [
        ("ki", cls_KeyBdInput),
        ("mi", cls_MouseInput),
        ("hi", cls_HardwareInput)
    ]

class cls_Input(ct.Structure):
    _fields_ = [
        ("type", ct.c_ulong),
        ("ii", cls_Input_I)
    ]

def make_input_objects( l_keys ):
    p_ExtraInfo_0 = ct.pointer(ct.c_ulong(0))
    l_inputs = [ ]
    for n_key, n_updown in l_keys:
        ki = cls_KeyBdInput( n_key, 0, n_updown, 0, p_ExtraInfo_0 )
        ii = cls_Input_I()
        ii.ki = ki
        l_inputs.append( ii )
    n_inputs = len(l_inputs)
    l_inputs_2=[]
    for ndx in range( 0, n_inputs ):
        s2 = "(1, l_inputs[%s])" % ndx
        l_inputs_2.append(s2)
    s_inputs = ', '.join(l_inputs_2)

    cls_input_array = cls_Input * n_inputs
    o_input_array = eval( "cls_input_array( %s )" % s_inputs )
    p_input_array = ct.pointer( o_input_array )
    n_size_0 = ct.sizeof( o_input_array[0] )
    return ( n_inputs, p_input_array, n_size_0 )

def send_input( window1, t_inputs,):

    tpl1 = window1.GetWindowPlacement()
    window1.SetForegroundWindow()
    sleep(0.2)
    window1.SetFocus()
    sleep(0.2)
    rv = ct.windll.user32.SendInput( *t_inputs )
    return rv

def test():
    #t_hello is "hello\n"
    t_hello = ( ( 0x48, 0 ), ( 0x45, 0 ), ( 0x4C, 0 ), ( 0x4C, 0 ),  ( 0x4F, 0 ), ( 0x0D, 0 ), )
    l_keys = [ ]
    l_keys.extend( t_hello )
    s_app_name = "Notepad"
    window1 = FindWindow( s_app_name, None )
    if window1 == None:
        print( "%r has no window." % s_app_name )
        input( 'press enter to close' )
        exit()
    t_inputs = make_input_objects( l_keys )
    n = send_input( window1, t_inputs )

if __name__ == '__main__':
    test()

This sample implements sending the string "hello" to the notepad. And it works fine for me.

Upvotes: 1

Related Questions