2010-09-05 6 views
15

मैं कस्टम गेम नियंत्रक एप्लिकेशन के लिए कीबोर्ड कमांड अनुकरण करने की कोशिश कर रहा हूं। क्योंकि मुझे डायरेक्ट इनपुट वातावरण में कमांड अनुकरण करने की आवश्यकता होगी क्योंकि अधिकांश सामान्य तरीके काम नहीं करते हैं। मुझे पता है कि एक हुक का उपयोग 100% काम करेगा लेकिन मैं एक आसान कार्यान्वयन खोजने की कोशिश कर रहा हूं।DirectInput अनुप्रयोगों में SendInput API के साथ कीबोर्ड सिम्युलेटिंग

मैंने काफी कुछ खोज किया है और पाया है कि वर्चुअल कुंजियों के बजाय स्कैनकोड के साथ SendInput API का उपयोग करके काम करना चाहिए, लेकिन ऐसा लगता है कि कुंजी "चिपकने" की तरह व्यवहार करती है। मैंने दोनों कुंजीपटल और KEYUP ईवेंट भेजे हैं, लेकिन जब मैं डायरेक्टइनपूट वातावरण में संदेश भेजने का प्रयास करता हूं, तो गेम कार्य करता है जैसे कि कुंजी दबाई जा रही है।

उदाहरण के लिए, यदि मैं एक "डब्ल्यू" कुंजीपटल अनुकरण करता हूं और उस कुंजी को पहले व्यक्ति शूटर में "आगे बढ़ने" क्रिया में मैप किया जाता है, एक बार जब मैं गेम में हूं, तो नीचे दिया गया कार्य चरित्र को आगे बढ़ने का कारण बनता है । हालांकि, केवल एक बार आदेश जारी करके, यह चरित्र को अनिश्चित काल तक आगे बढ़ाएगा।

यहाँ SendInput समारोह मैं फोन कर रहा हूँ के लिए एक कोड का टुकड़ा (सी # में) है: अगर इस विधि को खोए हुए कारण है, या

[DllImport("user32.dll")] 
static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize); 

public static void Test_KeyDown() 
{ 
    INPUT[] InputData = new INPUT[2]; 
    Key ScanCode = Microsoft.DirectX.DirectInput.Key.W; 

    InputData[0].type = 1; //INPUT_KEYBOARD 
    InputData[0].wScan = (ushort)ScanCode; 
    InputData[0].dwFlags = (uint)SendInputFlags.KEYEVENTF_SCANCODE; 

    InputData[1].type = 1; //INPUT_KEYBOARD 
    InputData[1].wScan = (ushort)ScanCode; 
    InputData[1].dwFlags = (uint)(SendInputFlags.KEYEVENTF_KEYUP | SendInputFlags.KEYEVENTF_UNICODE); 

    // send keydown 
    if (SendInput(2, InputData, Marshal.SizeOf(InputData[1])) == 0) 
    { 
     System.Diagnostics.Debug.WriteLine("SendInput failed with code: " + 
     Marshal.GetLastWin32Error().ToString()); 
    } 
} 

मुझे यकीन है कि नहीं कर रहा हूँ अगर वहाँ बस कुछ मूर्खतापूर्ण मैं है मैं याद कर रहा हूँ मुझे अपने कोड को जटिल करने से नफरत है अगर मुझे हुक का उपयोग करके नहीं करना है, लेकिन यह मेरे लिए भी नया क्षेत्र है।

कोई भी मदद जो कोई भी दे सकता है उसकी बहुत सराहना की जाती है।

धन्यवाद!

+4

'INPUT []' क्या है? क्या यह 'user32.dll" से आया था? –

उत्तर

21

मुझे अपनी समस्या का समाधान मिला है। इसलिए, मैंने सोचा कि मैं यहां किसी ऐसे व्यक्ति की मदद करने के लिए पोस्ट करूंगा जो भविष्य में समान मुद्दों का हो।

कुंजीपटल कमांड ठीक से काम नहीं कर रहा था क्योंकि केवल स्कैन कोड भेजते समय, कुंजीपटल को SendInput() API को बताने के लिए स्कैन कोड ध्वज (प्रभावी रूप से दोनों झंडे को सक्षम करने) के साथ किया जाना चाहिए कि यह दोनों एक है KEYUP और एक स्कैनकोडे कमांड।

उदाहरण के लिए निम्नलिखित कोड को ठीक से स्कैन कोड कुंजी-अप जारी करेगा: प्रतिक्रिया के लिए हंस को

INPUT[] InputData = new INPUT[1]; 

InputData[0].Type = (UInt32)InputType.KEYBOARD; 
//InputData[0].Vk = (ushort)DirectInputKeyScanCode; //Virtual key is ignored when sending scan code 
InputData[0].Scan = (ushort)DirectInputKeyScanCode; 
InputData[0].Flags = (uint)KeyboardFlag.KEYUP | (uint)KeyboardFlag.SCANCODE; 
InputData[0].Time = 0; 
InputData[0].ExtraInfo = IntPtr.Zero; 

// Send Keyup flag "OR"ed with Scancode flag for keyup to work properly 
SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT))) 

धन्यवाद। मैंने कुछ जांच की और मूल संदेश की तरह दो संदेशों को वापस भेजने के लिए वास्तव में एक "कीप्रेस" अनुकरण किया लेकिन यह बहुत तेज़ है। यह एक आंदोलन कमांड के लिए अच्छा काम नहीं करेगा, लेकिन आदर्श होगा जब एक्शन कुंजियों को "टैप" किया जाना चाहिए और नीचे नहीं रखा जाना चाहिए।

इसके अलावा, वर्चुअल कुंजी फ़ील्ड को स्कैन कोड भेजते समय अनदेखा किया जाता है। एमएसडीएन ने इस विषय पर निम्नलिखित कहने के लिए निम्नलिखित किया था:

"स्कैन कोड के संदर्भ में कीबोर्ड इनपुट को परिभाषित करने के लिए KEYEVENTF_SCANCODE ध्वज सेट करें। यह एक भौतिक कीस्ट्रोक अनुकरण करने के लिए उपयोगी है, भले ही कौन सा कीबोर्ड वर्तमान में उपयोग किया जा रहा हो। वर्चुअल कुंजी किसी कुंजी का मान वर्तमान कीबोर्ड लेआउट या अन्य कुंजियों को दबाए जाने के आधार पर बदल सकता है, लेकिन स्कैन कोड हमेशा एक जैसा होगा। "

http://msdn.microsoft.com/en-us/library/ms646271%28v=VS.85%29.aspx

+3

आपके समाधान में आपने एक DirectInputKeyScanCode का उल्लेख किया है, कि मैं इसे उपयोग में नहीं ला सकता, क्या आप मेरी मदद कर सकते हैं? – Fede

+0

क्या आप एक कुंजी डाउन करने और कुंजी अप करने के लिए एक पूर्ण समाधान पोस्ट कर सकते हैं? मुझे यकीन नहीं है कि मैं क्या गलत कर रहा हूं और मुझे आपके द्वारा भेजे गए पहले कोड स्निपेट में प्रतिस्थापित करने की आवश्यकता है। धन्यवाद! –

3

मैं फ्लैश में एक प्रस्तुति के लिए कीबोर्ड अनुकरण करने के लिए कोशिश कर रहा था, और यह भी एक ही समस्या हो रही थी। यह नोटपैड जैसे ऐप्स के लिए काम करता था, लेकिन फ्लैश के लिए नहीं। गुगलिंग के घंटों के बाद मैंने अंततः इसे काम किया:

public static void GenerateKey(int vk, bool bExtended) 
    { 
     INPUT[] inputs = new INPUT[1]; 
     inputs[0].type = INPUT_KEYBOARD; 

     KEYBDINPUT kb = new KEYBDINPUT(); //{0}; 
     // generate down 
     if (bExtended) 
      kb.dwFlags = KEYEVENTF_EXTENDEDKEY; 

     kb.wVk = (ushort)vk; 
     inputs[0].ki = kb; 
     SendInput(1, inputs, System.Runtime.InteropServices.Marshal.SizeOf(inputs[0])); 

     // generate up 
     //ZeroMemory(&kb, sizeof(KEYBDINPUT)); 
     //ZeroMemory(&inputs,sizeof(inputs)); 
     kb.dwFlags = KEYEVENTF_KEYUP; 
     if (bExtended) 
      kb.dwFlags |= KEYEVENTF_EXTENDEDKEY; 

     kb.wVk = (ushort)vk; 
     inputs[0].type = INPUT_KEYBOARD; 
     inputs[0].ki = kb; 
     SendInput(1, inputs, System.Runtime.InteropServices.Marshal.SizeOf(inputs[0])); 
    } 
संबंधित मुद्दे