Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending keys to a DirectX Game

I got into a little trouble sending keys. It seems like when ever I want to send keys It doesn't work.

I'm thinking about sending alphabetic characters such as T to bring the chat up from example, but If I write It to the enum, nothing happens whenever I use them. Any ideas?

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// Virtual Keys
/// </summary>
public enum VirtualKeyStates : int
{
    VK_LBUTTON = 0x01,
    VK_RBUTTON = 0x02,
    VK_CANCEL = 0x03,
    VK_MBUTTON = 0x04,
    //
    VK_XBUTTON1 = 0x05,
    VK_XBUTTON2 = 0x06,
    //
    VK_BACK = 0x08,
    VK_TAB = 0x09,
    //
    VK_CLEAR = 0x0C,
    VK_RETURN = 0x0D,
    //
    VK_SHIFT = 0x10,
    VK_CONTROL = 0x11,
    VK_MENU = 0x12,
    VK_PAUSE = 0x13,
    VK_CAPITAL = 0x14,
    //
    VK_KANA = 0x15,
    VK_HANGEUL = 0x15, /* old name - should be here for compatibility */
    VK_HANGUL = 0x15,
    VK_JUNJA = 0x17,
    VK_FINAL = 0x18,
    VK_HANJA = 0x19,
    VK_KANJI = 0x19,
    //
    VK_ESCAPE = 0x1B,
    //
    VK_CONVERT = 0x1C,
    VK_NONCONVERT = 0x1D,
    VK_ACCEPT = 0x1E,
    VK_MODECHANGE = 0x1F,
    //
    VK_SPACE = 0x20,
    VK_PRIOR = 0x21,
    VK_NEXT = 0x22,
    VK_END = 0x23,
    VK_HOME = 0x24,
    VK_LEFT = 0x25,
    VK_UP = 0x26,
    VK_RIGHT = 0x27,
    VK_DOWN = 0x28,
    VK_SELECT = 0x29,
    VK_PRINT = 0x2A,
    VK_EXECUTE = 0x2B,
    VK_SNAPSHOT = 0x2C,
    VK_INSERT = 0x2D,
    VK_DELETE = 0x2E,
    VK_HELP = 0x2F,
    //
    VK_LWIN = 0x5B,
    VK_RWIN = 0x5C,
    VK_APPS = 0x5D,
    //
    VK_SLEEP = 0x5F,
    //
    VK_NUMPAD0 = 0x60,
    VK_NUMPAD1 = 0x61,
    VK_NUMPAD2 = 0x62,
    VK_NUMPAD3 = 0x63,
    VK_NUMPAD4 = 0x64,
    VK_NUMPAD5 = 0x65,
    VK_NUMPAD6 = 0x66,
    VK_NUMPAD7 = 0x67,
    VK_NUMPAD8 = 0x68,
    VK_NUMPAD9 = 0x69,
    VK_MULTIPLY = 0x6A,
    VK_ADD = 0x6B,
    VK_SEPARATOR = 0x6C,
    VK_SUBTRACT = 0x6D,
    VK_DECIMAL = 0x6E,
    VK_DIVIDE = 0x6F,
    VK_F1 = 0x70,
    VK_F2 = 0x71,
    VK_F3 = 0x72,
    VK_F4 = 0x73,
    VK_F5 = 0x74,
    VK_F6 = 0x75,
    VK_F7 = 0x76,
    VK_F8 = 0x77,
    VK_F9 = 0x78,
    VK_F10 = 0x79,
    VK_F11 = 0x7A,
    VK_F12 = 0x7B,
    VK_F13 = 0x7C,
    VK_F14 = 0x7D,
    VK_F15 = 0x7E,
    VK_F16 = 0x7F,
    VK_F17 = 0x80,
    VK_F18 = 0x81,
    VK_F19 = 0x82,
    VK_F20 = 0x83,
    VK_F21 = 0x84,
    VK_F22 = 0x85,
    VK_F23 = 0x86,
    VK_F24 = 0x87,
    //
    VK_NUMLOCK = 0x90,
    VK_SCROLL = 0x91,
    //
    VK_OEM_NEC_EQUAL = 0x92, // '=' key on numpad
    //
    VK_OEM_FJ_JISHO = 0x92, // 'Dictionary' key
    VK_OEM_FJ_MASSHOU = 0x93, // 'Unregister word' key
    VK_OEM_FJ_TOUROKU = 0x94, // 'Register word' key
    VK_OEM_FJ_LOYA = 0x95, // 'Left OYAYUBI' key
    VK_OEM_FJ_ROYA = 0x96, // 'Right OYAYUBI' key
    //
    VK_LSHIFT = 0xA0,
    VK_RSHIFT = 0xA1,
    VK_LCONTROL = 0xA2,
    VK_RCONTROL = 0xA3,
    VK_LMENU = 0xA4,
    VK_RMENU = 0xA5,
    //
    VK_BROWSER_BACK = 0xA6,
    VK_BROWSER_FORWARD = 0xA7,
    VK_BROWSER_REFRESH = 0xA8,
    VK_BROWSER_STOP = 0xA9,
    VK_BROWSER_SEARCH = 0xAA,
    VK_BROWSER_FAVORITES = 0xAB,
    VK_BROWSER_HOME = 0xAC,
    //
    VK_VOLUME_MUTE = 0xAD,
    VK_VOLUME_DOWN = 0xAE,
    VK_VOLUME_UP = 0xAF,
    VK_MEDIA_NEXT_TRACK = 0xB0,
    VK_MEDIA_PREV_TRACK = 0xB1,
    VK_MEDIA_STOP = 0xB2,
    VK_MEDIA_PLAY_PAUSE = 0xB3,
    VK_LAUNCH_MAIL = 0xB4,
    VK_LAUNCH_MEDIA_SELECT = 0xB5,
    VK_LAUNCH_APP1 = 0xB6,
    VK_LAUNCH_APP2 = 0xB7,
    //
    VK_OEM_1 = 0xBA, // ';:' for US
    VK_OEM_PLUS = 0xBB, // '+' any country
    VK_OEM_COMMA = 0xBC, // ',' any country
    VK_OEM_MINUS = 0xBD, // '-' any country
    VK_OEM_PERIOD = 0xBE, // '.' any country
    VK_OEM_2 = 0xBF, // '/?' for US
    VK_OEM_3 = 0xC0, // '`~' for US
    //
    VK_OEM_4 = 0xDB, // '[{' for US
    VK_OEM_5 = 0xDC, // '|' for US
    VK_OEM_6 = 0xDD, // ']}' for US
    VK_OEM_7 = 0xDE, // ''"' for US
    VK_OEM_8 = 0xDF,
    //
    VK_OEM_AX = 0xE1, // 'AX' key on Japanese AX kbd
    VK_OEM_102 = 0xE2, // "<>" or "|" on RT 102-key kbd.
    VK_ICO_HELP = 0xE3, // Help key on ICO
    VK_ICO_00 = 0xE4, // 00 key on ICO
    //
    VK_PROCESSKEY = 0xE5,
    //
    VK_ICO_CLEAR = 0xE6,
    //
    VK_PACKET = 0xE7,
    //
    VK_OEM_RESET = 0xE9,
    VK_OEM_JUMP = 0xEA,
    VK_OEM_PA1 = 0xEB,
    VK_OEM_PA2 = 0xEC,
    VK_OEM_PA3 = 0xED,
    VK_OEM_WSCTRL = 0xEE,
    VK_OEM_CUSEL = 0xEF,
    VK_OEM_ATTN = 0xF0,
    VK_OEM_FINISH = 0xF1,
    VK_OEM_COPY = 0xF2,
    VK_OEM_AUTO = 0xF3,
    VK_OEM_ENLW = 0xF4,
    VK_OEM_BACKTAB = 0xF5,
    //
    VK_ATTN = 0xF6,
    VK_CRSEL = 0xF7,
    VK_EXSEL = 0xF8,
    VK_EREOF = 0xF9,
    VK_PLAY = 0xFA,
    VK_ZOOM = 0xFB,
    VK_NONAME = 0xFC,
    VK_PA1 = 0xFD,
    VK_OEM_CLEAR = 0xFE,
    //
    VK_0 = 0x30,
    VK_1 = 0x31,
    VK_2 = 0x32,
    VK_3 = 0x33,
    VK_4 = 0x34,
    VK_5 = 0x35,
    VK_6 = 0x36,
    VK_7 = 0x37,
    VK_8 = 0x38,
    VK_9 = 0x39
}
///summary> 
/// Virtual Messages 
/// </summary> 
public enum WMessages : int
/// <summary>
/// Sends a message to the specified window
/// </summary>
/// <param name="winTitle">string Title of window</param>
/// <param name="Key">Virtual key code of the key to send</param>
public static void ControlSendMessage(string winTitle, VirtualKeyStates Key, bool shift)
{
    IntPtr hWnd = FindWindow(null, winTitle);
    if (shift == true)
    {
        //send shift down
        SendMessage(hWnd, 0x100, (int)VirtualKeyStates.VK_SHIFT, 0);
        //send key down
        SendMessage(hWnd, 0x100, (int)Key, 0);
        //sleep 50ms
        Thread.Sleep(50);
        //send key up
        SendMessage(hWnd, 0x101, (int)Key, 0);
        //send shift up
        SendMessage(hWnd, 0x101, (int)VirtualKeyStates.VK_SHIFT, 0);
    }
    else
    {
        //send key down
        SendMessage(hWnd, 0x100, (int)Key, 0);
        //sleep 50ms
        Thread.Sleep(50);
        //send key up
        SendMessage(hWnd, 0x101, (int)Key, 0);
    }
}
/// <summary>
/// Sends a Keydown message(0x100) to the specified window with a Virtual Key
/// </summary>
/// <param name="winTitle">Window Title</param>
/// <param name="Key">Virtual Key to Send</param>
public static void KeyDown(string winTitle, VirtualKeyStates Key)
{
    IntPtr hWnd = FindWindow(null, winTitle);
    SendMessage(hWnd, 0x100, (int)Key, 0);
}
/// <summary>
/// Sends a Keydup message(0x101) to the specified window with a Virtual Key
/// </summary>
/// <param name="winTitle">Window Title</param>
/// <param name="Key">Virtual Key to Send</param>
public static void KeyUp(string winTitle, VirtualKeyStates Key)
{
    IntPtr hWnd = FindWindow(null, winTitle);
    SendMessage(hWnd, 0x101, (int)Key, 0);
}
/// <summary> 
/// Sends a message to the specified handle 
/// </summary> 
public void _SendMessage(IntPtr handle, int Msg, int wParam, int lParam)
{
    SendMessage(handle, Msg, wParam, lParam);
}
like image 570
DreTaX Avatar asked Feb 07 '23 20:02

DreTaX


1 Answers

Seems like this question is raising a lot of views, so here is my solution that I did before (I collected the inputs from a site, and made It to an enum for easier usage.):

/// <summary>
/// My own question as reference: https://stackoverflow.com/questions/35138778/sending-keys-to-a-directx-game
/// http://www.gamespp.com/directx/directInputKeyboardScanCodes.html
/// </summary>
public class Keyboard
{
    [Flags]
    public enum InputType
    {
        Mouse = 0,
        Keyboard = 1,
        Hardware = 2
    }

    [Flags]
    public enum KeyEventF
    {
        KeyDown = 0x0000,
        ExtendedKey = 0x0001,
        KeyUp = 0x0002,
        Unicode = 0x0004,
        Scancode = 0x0008,
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern uint SendInput(uint nInputs, Input[] pInputs, int cbSize);

    [DllImport("user32.dll")]
    private static extern IntPtr GetMessageExtraInfo();

    /// <summary>
    /// DirectX key list collected out from the gamespp.com list by me.
    /// </summary>
    public enum DirectXKeyStrokes
    {
        DIK_ESCAPE = 0x01,
        DIK_1 = 0x02,
        DIK_2 = 0x03,
        DIK_3 = 0x04,
        DIK_4 = 0x05,
        DIK_5 = 0x06,
        DIK_6 = 0x07,
        DIK_7 = 0x08,
        DIK_8 = 0x09,
        DIK_9 = 0x0A,
        DIK_0 = 0x0B,
        DIK_MINUS = 0x0C,
        DIK_EQUALS = 0x0D,
        DIK_BACK = 0x0E,
        DIK_TAB = 0x0F,
        DIK_Q = 0x10,
        DIK_W = 0x11,
        DIK_E = 0x12,
        DIK_R = 0x13,
        DIK_T = 0x14,
        DIK_Y = 0x15,
        DIK_U = 0x16,
        DIK_I = 0x17,
        DIK_O = 0x18,
        DIK_P = 0x19,
        DIK_LBRACKET = 0x1A,
        DIK_RBRACKET = 0x1B,
        DIK_RETURN = 0x1C,
        DIK_LCONTROL = 0x1D,
        DIK_A = 0x1E,
        DIK_S = 0x1F,
        DIK_D = 0x20,
        DIK_F = 0x21,
        DIK_G = 0x22,
        DIK_H = 0x23,
        DIK_J = 0x24,
        DIK_K = 0x25,
        DIK_L = 0x26,
        DIK_SEMICOLON = 0x27,
        DIK_APOSTROPHE = 0x28,
        DIK_GRAVE = 0x29,
        DIK_LSHIFT = 0x2A,
        DIK_BACKSLASH = 0x2B,
        DIK_Z = 0x2C,
        DIK_X = 0x2D,
        DIK_C = 0x2E,
        DIK_V = 0x2F,
        DIK_B = 0x30,
        DIK_N = 0x31,
        DIK_M = 0x32,
        DIK_COMMA = 0x33,
        DIK_PERIOD = 0x34,
        DIK_SLASH = 0x35,
        DIK_RSHIFT = 0x36,
        DIK_MULTIPLY = 0x37,
        DIK_LMENU = 0x38,
        DIK_SPACE = 0x39,
        DIK_CAPITAL = 0x3A,
        DIK_F1 = 0x3B,
        DIK_F2 = 0x3C,
        DIK_F3 = 0x3D,
        DIK_F4 = 0x3E,
        DIK_F5 = 0x3F,
        DIK_F6 = 0x40,
        DIK_F7 = 0x41,
        DIK_F8 = 0x42,
        DIK_F9 = 0x43,
        DIK_F10 = 0x44,
        DIK_NUMLOCK = 0x45,
        DIK_SCROLL = 0x46,
        DIK_NUMPAD7 = 0x47,
        DIK_NUMPAD8 = 0x48,
        DIK_NUMPAD9 = 0x49,
        DIK_SUBTRACT = 0x4A,
        DIK_NUMPAD4 = 0x4B,
        DIK_NUMPAD5 = 0x4C,
        DIK_NUMPAD6 = 0x4D,
        DIK_ADD = 0x4E,
        DIK_NUMPAD1 = 0x4F,
        DIK_NUMPAD2 = 0x50,
        DIK_NUMPAD3 = 0x51,
        DIK_NUMPAD0 = 0x52,
        DIK_DECIMAL = 0x53,
        DIK_F11 = 0x57,
        DIK_F12 = 0x58,
        DIK_F13 = 0x64,
        DIK_F14 = 0x65,
        DIK_F15 = 0x66,
        DIK_KANA = 0x70,
        DIK_CONVERT = 0x79,
        DIK_NOCONVERT = 0x7B,
        DIK_YEN = 0x7D,
        DIK_NUMPADEQUALS = 0x8D,
        DIK_CIRCUMFLEX = 0x90,
        DIK_AT = 0x91,
        DIK_COLON = 0x92,
        DIK_UNDERLINE = 0x93,
        DIK_KANJI = 0x94,
        DIK_STOP = 0x95,
        DIK_AX = 0x96,
        DIK_UNLABELED = 0x97,
        DIK_NUMPADENTER = 0x9C,
        DIK_RCONTROL = 0x9D,
        DIK_NUMPADCOMMA = 0xB3,
        DIK_DIVIDE = 0xB5,
        DIK_SYSRQ = 0xB7,
        DIK_RMENU = 0xB8,
        DIK_HOME = 0xC7,
        DIK_UP = 0xC8,
        DIK_PRIOR = 0xC9,
        DIK_LEFT = 0xCB,
        DIK_RIGHT = 0xCD,
        DIK_END = 0xCF,
        DIK_DOWN = 0xD0,
        DIK_NEXT = 0xD1,
        DIK_INSERT = 0xD2,
        DIK_DELETE = 0xD3,
        DIK_LWIN = 0xDB,
        DIK_RWIN = 0xDC,
        DIK_APPS = 0xDD,
        DIK_BACKSPACE = DIK_BACK,
        DIK_NUMPADSTAR = DIK_MULTIPLY,
        DIK_LALT = DIK_LMENU,
        DIK_CAPSLOCK = DIK_CAPITAL,
        DIK_NUMPADMINUS = DIK_SUBTRACT,
        DIK_NUMPADPLUS = DIK_ADD,
        DIK_NUMPADPERIOD = DIK_DECIMAL,
        DIK_NUMPADSLASH = DIK_DIVIDE,
        DIK_RALT = DIK_RMENU,
        DIK_UPARROW = DIK_UP,
        DIK_PGUP = DIK_PRIOR,
        DIK_LEFTARROW = DIK_LEFT,
        DIK_RIGHTARROW = DIK_RIGHT,
        DIK_DOWNARROW = DIK_DOWN,
        DIK_PGDN = DIK_NEXT,

        // Mined these out of nowhere.
        DIK_LEFTMOUSEBUTTON = 0x100,
        DIK_RIGHTMOUSEBUTTON  = 0x101,
        DIK_MIDDLEWHEELBUTTON = 0x102,
        DIK_MOUSEBUTTON3 = 0x103,
        DIK_MOUSEBUTTON4 = 0x104,
        DIK_MOUSEBUTTON5 = 0x105,
        DIK_MOUSEBUTTON6 = 0x106,
        DIK_MOUSEBUTTON7 = 0x107,
        DIK_MOUSEWHEELUP = 0x108,
        DIK_MOUSEWHEELDOWN = 0x109,
    }

    /// <summary>
    /// Sends a directx key.
    /// http://www.gamespp.com/directx/directInputKeyboardScanCodes.html
    /// </summary>
    /// <param name="key"></param>
    /// <param name="KeyUp"></param>
    /// <param name="inputType"></param>
    public static void SendKey(DirectXKeyStrokes key, bool KeyUp, InputType inputType)
    {
        uint flagtosend;
        if (KeyUp)
        {
            flagtosend = (uint) (KeyEventF.KeyUp | KeyEventF.Scancode);
        }
        else
        {
            flagtosend = (uint) (KeyEventF.KeyDown | KeyEventF.Scancode);
        }

        Input[] inputs =
        {
            new Input
            {
                type = (int) inputType,
                u = new InputUnion
                {
                    ki = new KeyboardInput
                    {
                        wVk = 0,
                        wScan = (ushort) key,
                        dwFlags = flagtosend,
                        dwExtraInfo = GetMessageExtraInfo()
                    }
                }
            }
        };

        SendInput((uint) inputs.Length, inputs, Marshal.SizeOf(typeof(Input)));
    }

    /// <summary>
    /// Sends a directx key.
    /// http://www.gamespp.com/directx/directInputKeyboardScanCodes.html
    /// </summary>
    /// <param name="key"></param>
    /// <param name="KeyUp"></param>
    /// <param name="inputType"></param>
    public static void SendKey(ushort key, bool KeyUp, InputType inputType)
    {
        uint flagtosend;
        if (KeyUp)
        {
            flagtosend = (uint) (KeyEventF.KeyUp | KeyEventF.Scancode);
        }
        else
        {
            flagtosend = (uint) (KeyEventF.KeyDown | KeyEventF.Scancode);
        }

        Input[] inputs =
        {
            new Input
            {
                type = (int) inputType,
                u = new InputUnion
                {
                    ki = new KeyboardInput
                    {
                        wVk = 0,
                        wScan = key,
                        dwFlags = flagtosend,
                        dwExtraInfo = GetMessageExtraInfo()
                    }
                }
            }
        };

        SendInput((uint) inputs.Length, inputs, Marshal.SizeOf(typeof(Input)));
    }

    public struct Input
    {
        public int type;
        public InputUnion u;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct InputUnion
    {
        [FieldOffset(0)] public readonly MouseInput mi;
        [FieldOffset(0)] public KeyboardInput ki;
        [FieldOffset(0)] public readonly HardwareInput hi;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MouseInput
    {
        public readonly int dx;
        public readonly int dy;
        public readonly uint mouseData;
        public readonly uint dwFlags;
        public readonly uint time;
        public readonly IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct KeyboardInput
    {
        public ushort wVk;
        public ushort wScan;
        public uint dwFlags;
        public readonly uint time;
        public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct HardwareInput
    {
        public readonly uint uMsg;
        public readonly ushort wParamL;
        public readonly ushort wParamH;
    }
}
like image 177
DreTaX Avatar answered Feb 10 '23 12:02

DreTaX