[.net] Simulate Keypress and Directx

Started by
23 comments, last by novice4ever 17 years, 5 months ago
I'm trying to write a program that will send a keypress (and eventually i will do a mouse move / press also) to an appliction. i tried using the managed sendinput and while it works in normal applications it does NOT work in Directx applications. any suggestions? i am trying to figure out the pinvoke version of SenInput but having very little luck at the moment so if you happen to know what to do in order to get this to work please help.
- The collective intelligence of the human race is a constant; the population is growing at an exponential rate. The conclusion is left as an exercise for the student.
Advertisement
Quote:Original post by LostAgain
I'm trying to write a program that will send a keypress (and eventually i will do a mouse move / press also) to an appliction. i tried using the managed sendinput and while it works in normal applications it does NOT work in Directx applications. any suggestions? i am trying to figure out the pinvoke version of SenInput but having very little luck at the moment so if you happen to know what to do in order to get this to work please help.


If it's ANY application...this should do the trick. Just be sure to modify it for what you want...it's straight out of one of my toys.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace wiseKontrol.CommandClasses
{
class InsertText : BaseCommand
{
public InsertText()
{
this.SCommandName = "InsertText";
this.SMenuItemName = "Insert Te&xt";
this.SArgumentHelp = "Enter the text to be inserted:";
}

public const ushort KEYEVENTF_KEYUP = 0x0002;
public const ushort KEYEVENTF_KEYDOWN = 0x0000;
public const ushort KEYEVENTF_SCANCODE = 0x0008;
public const ushort KEYEVENTF_UNICODE = 0x0004;

public struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public long time;
public uint dwExtraInfo;
};

[StructLayout(LayoutKind.Explicit, Size = 28)]
public struct INPUT
{
[FieldOffset(0)]
public uint type;
[FieldOffset(4)]
public KEYBDINPUT ki;
};


[DllImport("user32.dll")]
public static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);

public override void executeCommand()
{
INPUT structInput;
structInput = new INPUT();
structInput.type = 1;
structInput.ki.wScan = 0;
structInput.ki.wVk = 0;
structInput.ki.time = 0;
structInput.ki.dwFlags = 0;
structInput.ki.dwExtraInfo = 0;

foreach (char c in SArgument.ToCharArray())
{
structInput.ki.dwFlags = KEYEVENTF_UNICODE;
structInput.ki.wScan = (ushort)c;
SendInput(1, ref structInput, Marshal.SizeOf(structInput));

structInput.ki.dwFlags = KEYEVENTF_UNICODE;
structInput.ki.dwFlags += KEYEVENTF_KEYUP;
structInput.ki.wScan = (ushort)c;
SendInput(1, ref structInput, Marshal.SizeOf(structInput));

}
}
}
}
Yup. go to a text window and it works go to my directx application and it doesn't.

Anyone else have some ideas?

I was thinking maybe throwing in a windowshookex and using the journalplay think like one of the msdn files i was reading said but reading that was like slamming my face into a wall. i got nothing out of it but a headache.
- The collective intelligence of the human race is a constant; the population is growing at an exponential rate. The conclusion is left as an exercise for the student.
Quote:Original post by LostAgain
Yup. go to a text window and it works go to my directx application and it doesn't.

Anyone else have some ideas?

I was thinking maybe throwing in a windowshookex and using the journalplay think like one of the msdn files i was reading said but reading that was like slamming my face into a wall. i got nothing out of it but a headache.


That's odd...I use it just fine in Warcraft III to hold down my alt key for life checking =0 Well good luck finding a solution, I just tossed it out there since I had it lying around.

trying to use it in everquest and so far no luck. no CLUE wth is wrong.
- The collective intelligence of the human race is a constant; the population is growing at an exponential rate. The conclusion is left as an exercise for the student.
For my program that simulates key presses in games I use the KEYEVENTF_SCANCODE in the dwFlags. I had a similar problem as you but I played around for a while and found that DirectInput will only react if you add KEYEVENTF_SCANCODE and you add the scan code in wScan.

Edit: Also I should mention that just casting the char to the scan code didn't work for me, the proper scan codes can be found at Microsoft.DirectX.DirectInput.Key (I'm not sure where they are in unmanaged, sorry).
i am relativly certai i tried this (Ox100 or Ox001 i forget which it was that it's defined as) but i will try again. i am nearlly certain what i need to do is either hook in and inject my own code (ala another post on this board from almost 2 years ago) OR provide an alternative wrapper directinput dll that emulates the current dll but with a direct pipeline to access the keystates (either of which is an inelegant time consumming and risky method of doing this)

oh well will play with it some more to try.

on the possitive side they no longer use directinput for mouse work and instead use the system mouse and htis is pretty simple to work with. so i can do that relativly easilly.
- The collective intelligence of the human race is a constant; the population is growing at an exponential rate. The conclusion is left as an exercise for the student.
Odd, my program works perfectly in every single game I've tried it in (about 10), and I know for sure that some of them used DI for input. I can post some sections of my app if that would help...
i would appriciate that greatly. in exchange i will package it into a nice little .net class library along with modified send cursor and send keyboard routines making everything in nice one package. figure other people have the same issue and would definatly like this also. if you have any form of repetitive stress syndrom not having to hit a button over and over just because a developer said to is so very nice. <clutches his wrist in agony> my wrist thanks you
- The collective intelligence of the human race is a constant; the population is growing at an exponential rate. The conclusion is left as an exercise for the student.
Ok, here is where I define the unmanaged stuff:
[StructLayout(LayoutKind.Sequential)]struct INPUT{public UInt32 type;//KEYBDINPUT:public ushort wVk;public ushort wScan;public UInt32 dwFlags;public UInt32 time;public UIntPtr dwExtraInfo;//HARDWAREINPUT:public UInt32 uMsg;public ushort wParamL;public ushort wParamH;}enum SendInputFlags{KEYEVENTF_EXTENDEDKEY = 0x0001,KEYEVENTF_KEYUP = 0x0002,KEYEVENTF_UNICODE = 0x0004,KEYEVENTF_SCANCODE = 0x0008,}[DllImport("user32.dll")]static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);


And here is where I get the scan code. It's messy, I know, but I simply couldn't find any other way to do it.

private Key GetScanCode(char Letter){	switch(Letter)	{		case '0':			return Key.D0;		case '1':			return Key.D1;		case '2':			return Key.D2;		case '3':			return Key.D3;		case '4':			return Key.D4;		case '5':			return Key.D5;		case '6':			return Key.D6;		case '7':			return Key.D7;		case '8':			return Key.D8;		case '9':			return Key.D9;		case 'a':		case 'A':			return Key.A;		case 'b':		case 'B':			return Key.B;		case 'c':		case 'C':			return Key.C;		case 'd':		case 'D':			return Key.D;		case 'e':		case 'E':			return Key.E;		case 'f':		case 'F':			return Key.F;		etc...


And this is how I make the call:

INPUT[] InputData = new INPUT[1];Key ScanCode = GetScanCode(ControllerScheme.KeyMappings[Count]);	InputData[0].type = 1; //INPUT_KEYBOARD	InputData[0].wScan = (ushort)ScanCode;	InputData[0].dwFlags = (uint)SendInputFlags.KEYEVENTF_SCANCODE;	if (SendInput(1, InputData, Marshal.SizeOf(InputData[0])) == 0)	{		System.Diagnostics.Debug.WriteLine("SendInput failed with code: " +		Marshal.GetLastWin32Error().ToString());	}


And that's all I do.

This topic is closed to new replies.

Advertisement