2014-04-12 30 views
10

Windows ortamında Python ile çalışıyorum ve bilinen bir oyundaki bazı görevleri otomatikleştirmek için bir komut dosyası yazdım. Görev, hem fare hem de klavye girişlerinin ağır kullanımını gerektirir. Ancak, söz konusu betiğin sadece bir sorunu var: tuş vuruşlarını uygulamaya gönderemiyor. Ben aşağıda göndermelidir en az 3 farklı yöntem denedim ve bazı varyasyonlar win32api modülü kullanarak,Windows'ta oyunlara tuş vuruşlarını göndermek için Python'u kullanın.

İlk one (ayrıca boşuna, benzer sorular/cevaplar onda okuyun):

f = 0x46 # VirtualKey Code of the letter "F", see http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx 

win32api.keybd_event(f,0,0,0) # holds the "F" key down 
time.sleep(2) # waits 2 seconds 
win32api.keybd_event(f,0,win32con.KEYEVENTF_KEYUP,0) # releases the key 

Bu konuda özel bir şey yok, herhangi bir metin editöründe, tarayıcıda mükemmel bir şekilde ("f" yazılır) çalışıyor ... Ancak, Counter-Strike gibi bir oyun açsam, tuş vuruşu "kaybolur" - hiçbir şey olmuyor. Öte yandan, Counter-Strike'nin konsolunu açarsam, tuşlarına basıldığında kayıtlı olur (not defterinde olduğu gibi). Başka bir oyunda test edildi, League of Legends, tam olarak aynı davranış. Gerçek oyunda, hiçbir tuş vuruşu algılanmaz. Ancak, sohbeti açsam (hala ingame) ve betiği yeniden çalıştırdığımda sohbet tarafından kaydediliyor. İkinci yöntem üstüne

: Yukarıdaki

shell = win32com.client.Dispatch("WScript.Shell") 
shell.SendKeys("F") 

tam olarak aynı davranışı. Oyunda her şey iyi çalışıyor, ve oyunda sadece sohbetler halinde çalışıyor.

Üçüncü yöntem (kredi, başka bir yığın akış iş parçacığında gönderen kişiye gider), daha gelişmiş (SendInput() numaralı telefonu arayarak) ctypes modülü ile. Teorik olarak, üç, bu bir gerçek, fiziksel tuş basın simüle en yakın olan:

SendInput = ctypes.windll.user32.SendInput 

# C struct redefinitions 
PUL = ctypes.POINTER(ctypes.c_ulong) 
class KeyBdInput(ctypes.Structure): 
    _fields_ = [("wVk", ctypes.c_ushort), 
       ("wScan", ctypes.c_ushort), 
       ("dwFlags", ctypes.c_ulong), 
       ("time", ctypes.c_ulong), 
       ("dwExtraInfo", PUL)] 

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

class MouseInput(ctypes.Structure): 
    _fields_ = [("dx", ctypes.c_long), 
       ("dy", ctypes.c_long), 
       ("mouseData", ctypes.c_ulong), 
       ("dwFlags", ctypes.c_ulong), 
       ("time",ctypes.c_ulong), 
       ("dwExtraInfo", PUL)] 

class Input_I(ctypes.Union): 
    _fields_ = [("ki", KeyBdInput), 
       ("mi", MouseInput), 
       ("hi", HardwareInput)] 

class Input(ctypes.Structure): 
    _fields_ = [("type", ctypes.c_ulong), 
       ("ii", Input_I)] 

# Actuals Functions 

def PressKey(hexKeyCode): 

    extra = ctypes.c_ulong(0) 
    ii_ = Input_I() 
    ii_.ki = KeyBdInput(hexKeyCode, 0x48, 0, 0, ctypes.pointer(extra)) 
    x = Input(ctypes.c_ulong(1), ii_) 
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) 

def ReleaseKey(hexKeyCode): 

    extra = ctypes.c_ulong(0) 
    ii_ = Input_I() 
    ii_.ki = KeyBdInput(hexKeyCode, 0x48, 0x0002, 0, ctypes.pointer(extra)) 
    x = Input(ctypes.c_ulong(1), ii_) 
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) 


def KeyPress(): 
    PressKey(0x46) # press F 
    time.sleep(.5) 
    ReleaseKey(0x46) #release F 

... o da çalışmıyor. Garip bir şekilde, önceki üç ile aynı davranışı tam görüntüler: herhangi bir metin editörü/basit bir uygulama çalışır, oyunlar tarafından göz ardı edilir veya sadece oyun sohbet bölümünde kayıtlı.

Tahmin edersem, bu oyunlar klavye olaylarını, bu 3 yöntemin hiçbiriyle örtüşmediğim bir şekilde aldıklarını söylerler, böylece bunları göz ardı ederler.

Herhangi bir yardım için minnettar olurum. Mümkünse, CS, LoL ya da benzer oyunlarda çalışan kodların somut örnekleri ile bir başlangıç ​​noktam olsun.

+0

Tarayıcı tabanlı oyunlar için, Firefox tarayıcısında çalışmış olduğunuz, ancak krom için çalışmadığınız gibi temel tuşa basmayı buldum. – Oleksiy

cevap

1

Uygulamanın pencerelerini EnumWindows() kullanarak numaralandırmayı deneyebilir ve oyunun ana pencerelerine doğrudan SendMessage() numaralı telefonu arayabilirsiniz.

+0

Çalışmıyor. PostMessage() aynı zamanda başarısız olur. –