SendKeys para Python 3.1 en Windows

El último módulo de Python Sendkeys es para Python 2.6. No puedo actualizarlo yo mismo ya que necesita el módulo C para ser recomstackdo.

¿Alguien sabe de una manera alternativa bastante fácil de enviar llaves a una ventana?

Usando win32ui.FindWindow () puedo encontrar la ventana correcta, luego activarla con PyCWnd.SetActiveWindow (), por lo que todo lo que se necesita es una forma sencilla de enviar pulsaciones de teclas a la ventana activa.

El propósito es ejecutar un elemento del menú.

La aplicación fue escrita en Delphi y no tiene ninguna interfaz entre procesos que yo sepa.

    Aquí hay un módulo de trabajo que llama a user32.SendInput ().

    No es perfecto, pero utilizable.

    Editar:

    Ayer hice una versión con una clase y la estoy usando en una aplicación tkinter que funciona. Lo pondré aquí cuando tenga tiempo de limpiarlo.

    He añadido esto en la cadena de documentos a continuación:

    [Está bien si trabajo desde una carpeta dentro de mi perfil.
    Estos problemas ocurrieron al trabajar en otra partición.
    Los permisos de archivo estaban bien, así que no sé qué bloqueó SendInput. ]

    SciTE todavía necesita el título exacto de la ventana.

    #!/usr/bin/python # -*- coding: utf-8 -*- ''' send_input for python 3, from jh45dev@gmail.com code from Daniel F is adapted here. The original is at: http://mail.python.org/pipermail/python-win32/2005-April/003131.html SendInput sends to the window that has the keyboard focus. That window must not be minimized. There seem to be some strange limitations with user32.SendInput() Here is what happened in my testing (on Vista sp2). [edit: It is OK if I work from a folder within my profile. These problems happened when working on another partition. File permissions were OK, so do not know what blocked SendInput.] 1 I opened Notepad from the Start menu, then in Notepad opened test.txt, and all worked fine. 2 I opened Notepad by opening test.txt in Explorer. find_window() found Notepad, but user32.SendInput() had no effect. If Notepad was minimized, it did not get restred or focussed. The same happened with SciTE and Notepad2. Another strangeness: For SciTE I had to put in the whole window title, eg "test.txt - SciTE", but for Notepad and Notepad2, only the app name, eg "Notepad". ''' 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 find_window( s_app_name ): try: window1 = FindWindow( None, s_app_name,) return window1 except ui_err: pass except: raise try: window1 = FindWindow( s_app_name, None, ) return window1 except ui_err: return None except: raise 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] ) # these are the args for user32.SendInput() return ( n_inputs, p_input_array, n_size_0 ) '''It is interesting that o_input_array has gone out of scope by the time p_input_array is used, but it works.''' def send_input( window1, t_inputs, b_minimize=True ): tpl1 = window1.GetWindowPlacement() was_min = False if tpl1[1] == 2: was_min = True window1.ShowWindow(SW_RESTORE) sleep(0.2) window1.SetForegroundWindow() sleep(0.2) window1.SetFocus() sleep(0.2) rv = ct.windll.user32.SendInput( *t_inputs ) if was_min and b_minimize: sleep(0.3) # if the last input was Save, it may need time to take effect window1.ShowWindow(SW_MINIMIZE) return rv # define some commonly-used key sequences t_ctrl_s = ( # save in many apps ( 0x11, 0 ), ( 0x53, 0 ), ( 0x11, 2 ), ) t_ctrl_r = ( # reload in some apps ( 0x11, 0 ), ( 0x52, 0 ), ( 0x11, 2 ), ) def test(): # file > open; a non-invasive way to test t_ctrl_o = ( ( 0x11, 0 ), ( 0x4F, 0 ), ( 0x11, 2 ), ) # writes "Hello\n" # 0x10 is shift. note that to repeat a key, as with 4C here, you have to release it after the first press t_hello = ( ( 0x10, 0 ), ( 0x48, 0 ), ( 0x10, 2 ), ( 0x45, 0 ), ( 0x4C, 0 ), ( 0x4C, 2 ), ( 0x4C, 0 ), ( 0x4F, 0 ), ( 0x0D, 0 ), ) l_keys = [ ] ## l_keys.extend( t_ctrl_o ) l_keys.extend( t_hello ) l_keys.extend( t_ctrl_s ) ## s_app_name = "SciTE" ## s_app_name = "(Untitled) - SciTE" s_app_name = "test.txt - SciTE" ## s_app_name = "Notepad2" ## s_app_name = "Notepad" window1 = find_window( s_app_name ) 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 ) ## print( "SendInput returned: %r" % n ) ## print( "GetLastError: %r" % ct.windll.kernel32.GetLastError() ) ## input( 'press enter to close' ) if __name__ == '__main__': test() 

    Reescribí los bits C de sendkeys en ctypes hace un tiempo … https://bitbucket.org/markm/sendkeysctypes y veo que alguien más lo hizo también: http://code.google.com/p/sendkeys-ctypes /

    Si recuerdo que debería haber una caída en el reemplazo de las claves de envío (solo la línea de importación debe cambiar)

    Tengo algo que funciona, usando win32api.keybd_event.

    Parece que SendInput sería más seguro, pero pywin32 no lo incluye.

    [editar: vea una versión de SendInput en la respuesta aceptada a continuación. Dejo este mensaje aquí en caso de que alguien prefiera usar sendkeys. J h ]

    Esta página ayudó a: http://social.msdn.microsoft.com/Search/en-us/?Query=keybd_event

    Código que funciona:

    import win32api; import win32ui

     PyCWnd1 = win32ui.FindWindow( None, "an_app" ) PyCWnd1.SetForegroundWindow() PyCWnd1.SetFocus() win32api.keybd_event(0x12, 0, ) # Alt win32api.keybd_event(0x12, 0, 2 ) # Alt release win32api.keybd_event(0x46, 0, ) # F win32api.keybd_event(0x52, 0, ) # R 

    Esto hace Archivo> Recargar en la aplicación. No funciona si la aplicación está minimizada

    Sin soltar Alt, después de ejecutar esto, ¡el teclado se comportó como si estuviera sosteniendo la tecla Alt! No parece que necesites soltar las otras llaves.

    Quieres la API keybd_event. El progtwig My PushKeys es compatible con la syntax de SendKeys y tiene una función de suspensión incorporada. Aunque no está en Python, debería ser traducible fácilmente (se ha traducido a muchos idiomas, al menos debería mostrarle la API que debe usar) . Está disponible aquí en una variedad de idiomas.