2014-04-12 77 views
10

我一直在Python環境中使用Python,並且編寫了一個腳本來自動完成已知遊戲中的一些任務。 該任務涉及大量使用鼠標和鍵盤輸入。使用Python將擊鍵發送到Windows中的遊戲?

然而,說腳本只有一個問題:它不能發送擊鍵到應用程序。我已經試過了,我將在下面發佈至少3種不同的方法和一些變化(也看過類似的問題/回答的十分之一,但無濟於事)

首先一個,使用win32api模塊:

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 

沒有什麼特別的,在任何文本編輯器,瀏覽器中完美地工作(打出「f」)然而,如果我打開一個像Counter-Strike這樣的遊戲,那麼擊鍵就會「丟失」沒有發生。另一方面,如果我打開Counter-Strike的控制檯,則按鍵獲得註冊(如在記事本中)。 在另一款遊戲中測試過,英雄聯盟的行爲完全一樣。在實際的遊戲中,沒有檢測到擊鍵。但是,如果我打開聊天(仍然遊戲內幕)並重新運行該腳本,則會通過聊天進行註冊。

在第二方法:

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

完全一樣上述行爲。在除了遊戲之外的所有遊戲中都能正常工作,並且只能在聊天中使用。

第三種方法(相當於將其發佈到另一個堆棧溢出線程的人),更高級的(調用SendInput())與​​模塊。理論上,這三者中最接近模擬實際的物理按鍵:

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 

......它也不起作用。奇怪的是,它顯示精確行爲與前三個相同:在任何文本編輯器/簡單應用程序中工作,被遊戲忽略或僅在遊戲聊天部分註冊。

如果我猜測我會說這些遊戲以其他方式獲取他們的鍵盤事件,但我沒有用這三種方法中的任何一種來覆蓋,因此忽略了這些。

我很感激任何幫助。如果可能的話,在CS,LoL或類似遊戲中使用代碼的具體示例,以便我有一個出發點。

+0

對於基於瀏覽器的遊戲,我發現上面介紹的基本按鍵是在Firefox瀏覽器上工作的,但沒有用於Chrome瀏覽器。 – Oleksiy

回答

1

您可以嘗試使用EnumWindows()來枚舉應用程序的窗口,並直接致電SendMessage()到遊戲的主窗口。

+0

不起作用。 PostMessage()失敗。 –