2010-09-05 31 views
15

Tôi đang cố gắng mô phỏng các lệnh bàn phím cho một ứng dụng điều khiển trò chơi tùy chỉnh. Bởi vì tôi sẽ cần phải mô phỏng các lệnh trong môi trường DirectInput, hầu hết các phương thức thông thường đều không hoạt động. Tôi biết rằng bằng cách sử dụng một cái móc sẽ làm việc 100% nhưng tôi đang cố gắng để tìm thấy một thực hiện dễ dàng hơn.Mô phỏng Bàn phím với API SendInput trong các ứng dụng DirectInput

Tôi đã thực hiện khá nhiều tìm kiếm và thấy rằng bằng cách sử dụng API SendInput với Scancode thay vì các phím ảo sẽ hoạt động, nhưng có vẻ như hoạt động như khóa là "gắn bó". Tôi đã gửi cả hai sự kiện KEYDOWN và KEYUP nhưng khi tôi cố gửi tin nhắn trong môi trường DirectInput, trò chơi hoạt động như thể phím đang được giữ. Ví dụ, nếu tôi mô phỏng một phím "W" và có khóa được ánh xạ trong một Shooter người đầu tiên đến hành động "di chuyển về phía trước", khi tôi đang ở trong trò chơi, chức năng dưới đây sẽ khiến nhân vật di chuyển về phía trước . Tuy nhiên, chỉ bằng cách phát lệnh một lần, nó sẽ di chuyển nhân vật về phía trước vô thời hạn.

Đây là một đoạn mã (trong C#) cho hàm SendInput Tôi gọi:

[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()); 
    } 
} 

Tôi không chắc chắn nếu phương pháp này là một nguyên nhân bị mất, hoặc nếu có chỉ là một cái gì đó ngớ ngẩn tôi đang mất tích. Tôi ghét làm phức tạp hơn mã của tôi nếu tôi không phải bằng cách sử dụng móc, nhưng đây cũng là lãnh thổ mới cho tôi.

Bất kỳ trợ giúp nào mà bất kỳ ai có thể cung cấp đều được đánh giá cao.

Cảm ơn!

+4

'INPUT [] 'là gì? Đó có phải là từ ''user32.dll' '? –

Trả lời

21

Tôi đã tìm ra giải pháp cho vấn đề của riêng mình. Vì vậy, tôi nghĩ rằng tôi muốn đăng bài ở đây để giúp đỡ bất cứ ai có thể có vấn đề tương tự trong tương lai.

Lệnh khóa không hoạt động đúng vì khi chỉ gửi mã quét, khóa phải được OR'ed với cờ mã quét (cho phép cả hai cờ hiệu quả) để báo cho SendInput() API rằng đây là cả hai KEYUP và lệnh SCANCODE.

Ví dụ, đoạn mã sau sẽ đúng cách phát hành một mã quét key-up:

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))) 

Nhờ Hans cho các phản ứng. Tôi đã làm một số điều tra và gửi hai tin nhắn trở lại trở lại như ví dụ ban đầu thực sự mô phỏng một "bấm phím" nhưng nó rất nhanh. Nó sẽ không hoạt động tốt cho một lệnh chuyển động, nhưng sẽ là lý tưởng khi các phím thao tác được "khai thác" và không được giữ.

Ngoài ra, trường khóa ảo bị bỏ qua khi gửi mã quét. MSDN có những điều sau đây để nói về chủ đề:

"Đặt cờ KEYEVENTF_SCANCODE để xác định đầu vào bàn phím theo điều khoản của mã quét. Điều này rất hữu ích để mô phỏng một phím tắt vật lý bất kể bàn phím nào hiện đang được sử dụng. giá trị của một khóa có thể thay đổi tùy thuộc vào bố cục bàn phím hiện tại hoặc các phím khác được nhấn, nhưng mã quét sẽ luôn giống nhau. "

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

+3

Trong giải pháp của bạn tìm thấy bạn đề cập đến một DirectInputKeyScanCode, mà tôi không thể có được nó sử dụng, bạn có thể giúp tôi? – Fede

+0

Bạn có thể đăng giải pháp đầy đủ để nhấn phím và khóa không? Tôi không chắc chắn những gì tôi đang làm sai và những gì tôi cần phải thay thế trong đoạn mã đầu tiên bạn đã gửi. CÁM ƠN! –

3

Tôi đã cố gắng để mô phỏng bàn phím cho một bài thuyết trình trong Flash, và cũng đã có cùng một vấn đề. Nó đã làm việc cho các ứng dụng như Notepad, nhưng không phải cho flash. Sau nhiều giờ googling tôi cuối cùng đã làm cho nó hoạt động:

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])); 
    } 
Các vấn đề liên quan