2014-04-12 6 views
10

मैं विंडोज वातावरण में पायथन के साथ काम कर रहा हूं और मैंने एक ज्ञात गेम में कुछ कार्यों को स्वचालित करने के लिए एक स्क्रिप्ट लिखी है। कार्य में माउस और कीबोर्ड इनपुट दोनों का भारी उपयोग शामिल है।विंडोज में गेम के लिए कीस्ट्रोक भेजने के लिए पायथन का उपयोग करें?

ने कहा स्क्रिप्ट, तथापि, केवल एक ही मुद्दा है: यह आवेदन करने के लिए कीस्ट्रोक्स नहीं भेज सकते। मैं कम से कम 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 

इसके बारे में कुछ भी खास नहीं है, किसी भी पाठ संपादक, ब्राउज़र में पूरी तरह से काम करता है (एक "एफ" टाइप किया जाता है) ... हालांकि, अगर मैं एक खेल खोलता हूं, कहता हूं, काउंटर स्ट्राइक, तो कीस्ट्रोक "खो गया" - जैसा कि, कुछ भी नहीं होता है। दूसरी तरफ, यदि मैं काउंटर स्ट्राइक के कंसोल खोलता हूं, तो कीस्ट्रोक पंजीकृत है (जैसे नोटपैड में)। एक और खेल, किंवदंतियों के लीग, बिल्कुल वही व्यवहार में परीक्षण किया। वास्तविक खेल में, कोई कीस्ट्रोक नहीं पता चला है। यदि, हालांकि, मैं चैट खोलता हूं (अभी भी ingame) और स्क्रिप्ट को फिर से चलाएं, फिर यह चैट द्वारा पंजीकृत हो जाता है।

दूसरी विधि रैंप

:

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

वास्तव में एक ही जैसा कि ऊपर व्यवहार। खेल के अलावा सब कुछ ठीक काम करता है, और इसमें केवल चैट में काम करता है।

ctypes मॉड्यूल के साथ तीसरा तरीका (क्रेडिट किसी अन्य स्टैक ओवरफ्लो थ्रेड में पोस्ट किया जाता है), अधिक उन्नत (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 

... यह या तो काम नहीं करता। अजीब तरह से पर्याप्त है, यह के रूप में पिछले तीन सटीक समान व्यवहार प्रदर्शित करता है: किसी भी पाठ संपादक/सरल आवेदन में काम करता है, खेल द्वारा नजरअंदाज कर दिया जाता है या केवल खेल चैट अनुभाग में पंजीकृत है।

तो मुझे लगता है कि करने के लिए मैं कहना चाहता हूँ इन खेलों किसी अन्य तरह से है कि मैं इन 3 तरीकों से किसी के साथ कवर नहीं किया है में अपने कीबोर्ड की घटनाओं हो रही है, इस प्रकार इन लोगों की अनदेखी कर रहे थे।

मैं किसी भी मदद की सराहना करेंगे। यदि संभव हो, तो सीएस, लोएल या इसी तरह के गेम में काम करने वाले कोड के ठोस उदाहरणों के साथ, ताकि मेरे पास प्रारंभिक बिंदु हो।

+0

ब्राउज़र आधारित खेल के लिए, मैं बुनियादी कुंजी दबाएँ के रूप में आप ऊपर वर्णित Firefox ब्राउज़र पर काम किया पाया है, लेकिन क्रोम के लिए काम नहीं किया। – Oleksiy

उत्तर

1

आप EnumWindows() का उपयोग कर एप्लिकेशन की विंडोज़ का आकलन करने का प्रयास कर सकते हैं और SendMessage() को सीधे गेम की मुख्य विंडो पर कॉल कर सकते हैं।

+0

काम नहीं करता है। PostMessage() भी असफल रहता है। –

3

आपका खेल शायद DirectInput का उपयोग करें। उन तरीकों में से किसी एक के साथ DirectInput स्कैनकोड आज़माएं। एक त्वरित Googling इस वेबसाइट देता है: http://www.gamespp.com/directx/directInputKeyboardScanCodes.html

+0

यह पूरी तरह से काम करता है! –

संबंधित मुद्दे