2009-12-01 4 views
3

최신 Python Sendkeys 모듈은 Python 2.6 용입니다. C 모듈을 다시 컴파일해야하기 때문에 직접 업그레이드 할 수 없습니다.SendKeys for Python 3.1 for Windows

누군가가 키를 창에 보내는 아주 쉬운 대안을 알고 있습니까?

win32ui.FindWindow()를 사용하면 오른쪽 창을 찾을 수 있고 PyCWnd.SetActiveWindow()를 사용하여 활성화 할 수 있으므로 키 입력을 활성화 된 창으로 보내는 간단한 방법이 필요합니다.

목적은 메뉴 항목을 실행하는 것입니다.

이 응용 프로그램은 Delphi로 작성되었으며 내가 아는 모든 프로세스 간 인터페이스가 없습니다.

답변

9

여기 user32.SendInput()을 호출하는 작업 모듈이 있습니다.

완벽하지는 않지만 사용할 수 있습니다.

편집 :

어제는 클래스 버전을했고, 작업의 Tkinter 응용 프로그램에서 사용하고 있습니다. 내가 청소할 시간이되면 여기에 넣을거야.

[내 프로필 내 폴더에서 작업하는 경우 그것은 OK입니다 :

아래의 문서화 문자열이 추가되었습니다.
다른 파티션에서 작업 할 때 이러한 문제가 발생했습니다.
파일 권한은 OK이므로 SendInput을 차단 한 항목을 알지 못합니다. ]

SciTE는 아직이라는 제목의 을 필요로합니다.

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

''' send_input for python 3, from [email protected] 

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 restored 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() 
0

keybd_event API가 필요합니다. 내 PushKeys 프로그램은 SendKeys와 구문 호환이 가능하며 수면 기능이 내장되어 있습니다. Python에서는 아니지만 쉽게 번역 할 수 있어야합니다 (많은 언어로 번역되었으므로 적어도 사용하는 API가 표시되어야 함) . 다양한 언어의 available here입니다.

+0

감사 크리스,하지만 난 아니에요 파이썬에서 사용하는 방법을 알기에 충분히 똑똑하다.) pywin32에게 키를 보내는 방법을 알았 으면 좋겠다. pywin32의 win32ui는 HookKeyStroke()에서 WM_CHAR을 언급하지만 후크는 send의 반대 일 것 같습니다. (나는 희망이 목요일 밤까지 일할 수 있기를 바랍니다 :) – jh45dev

+0

pywin32 도움에 명백하고 loooked 했나;) win32api.keybd_event 거기, 그래서 어쩌면 내가 지금 그 일을 할 수 있습니다. 가서 가상 키 코드를 찾아 봐야합니다. – jh45dev

+0

링크의 VB 소스에서 가상 키 코드를 가져올 수 있습니다. 파이썬을 알고 있다면 그것을 번역 할 것입니다. 코드는 매우 간단합니다. –

3

win32api.keybd_event를 사용하여 작동하는 것을 얻었습니다.

SendInput은 안전하지만 pywin32에는 포함되어 있지 않습니다.

[편집 : 아래의 승인 된 답변에서 SendInput 버전을 참조하십시오. 누군가가 sendkeys를 사용하기를 원한다면이 메시지를 남겨 두십시오. JH]

이 페이지는 도움 : 작동 http://social.msdn.microsoft.com/Search/en-us/?Query=keybd_event

코드 :

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 

이것은 파일> 응용 프로그램에서 다시로드 않습니다를. 응용 프로그램이 최소화 된 경우 작동하지 않습니다

Alt 키를 누르지 않으면이 키를 실행 한 후에 Alt 키를 누른 것처럼 키보드가 작동합니다! 다른 키를 해제 할 필요가없는 것 같습니다.

+0

시간이 지나면 ctypes를 통해 SendInput을 호출 해 보겠습니다. Btw, 다른 앱에서 사용하는 파일을 수정하는 tk 앱에서 사용하겠습니다. 그것은 이전에 저장하고 나중에 다시로드하도록 다른 응용 프로그램에 알려야합니다. 파일을 잠그지 않는 앱의 멋진 점 :) – jh45dev

+0

'SetFocus()'메소드를 사용하면 오류가 발생하지만 운 좋게도 필요하지 않습니다. – hazzey

5

저는 얼마 전 ctypes에서 sendkeys의 C 비트를 다시 작성했습니다 ... https://bitbucket.org/markm/sendkeysctypes 나는 다른 사람도 그것을했다 참조 : http://code.google.com/p/sendkeys-ctypes/

나는 그것을에서 SendKeys 교체의 감소 (만 가져 오기 라인을 변경해야한다)이어야한다 기억한다면

+0

py2.7, win7 64 비트에서 작동하지 않았다. SendInput은 Run 함수에서 아무 것도하지 않았다.; ( –

+0

여기에 내 문제에 대한 새로운 질문이있다. http://stackoverflow.com/questions/10503170/how- can-i-debug-sendkeysctypes- 추가로 –