本文介绍了使用SendInput包装器将击键发送到DirectX应用程序时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试将按键发送到DirectX应用程序一会儿,并且一直保持高调.我是C#的新手,所以有些更复杂的功能不胜枚举,但是我一直在尽力将其拼凑在一起.

I've been trying to send key presses to a DirectX application for a little while now, and keep striking out. I'm new to C#, so some of the more complicated functions go right over my head, but I've been trying to piece it together best I can.

SendInput是我似乎无法掌握的事情之一.

SendInput is one of those things that I just can't seem to grasp.

我尝试使用一些不同的SendInput包装器为我简化事情,包括:

I've tried using a few different SendInput wrappers to simplify things for me, including:

http://inputsimulator.codeplex.com/

http://www.codeproject. com/Articles/117657/InputManager-library-Track-user-input-and-simulate

和另一个叫拦截器

所有这些按钮都可以将按键发送给大多数应用程序,但是我仍然无法使它们发送到活动的游戏窗口.

All of them will send key presses fine to most applications, but I'm still unable to get them to send to an active game window.

我也尝试过SendKeys.

I've also tried SendKeys.

我曾尝试自己放置一个键盘挂钩,但对我自己来说,这太先进了,我的代码最终充满了错误.

I've attempted to place a keyboard hook myself, but it's just too advanced for me to figure out on my own, and my code ends up riddled with errors.

我希望是否将代码发布在这里(简单的服务器应用程序),以便有人可以向我解释在何处以及如何放置键盘挂钩.

I was hoping if I post my code here (simple server app) someone might be able to explain to me where and how to place the keyboard hook.

namespace ServerApp
{
public partial class Form1 : Form
{
    private TcpListener tcpListener;
    private Thread listenThread;
    private int connectedClients = 0;
    private delegate void WriteMessageDelegate(string msg);

    public Form1()
    {
        InitializeComponent();
        Server();
    }

    private void Server()
    {
        this.tcpListener = new TcpListener(IPAddress.Any, 8888);
        this.listenThread = new Thread(new ThreadStart(ListenForClients));
        this.listenThread.Start();
    }

    private void ListenForClients()
    {
        this.tcpListener.Start();

        while (true)
        {
            TcpClient client = this.tcpListener.AcceptTcpClient();

            connectedClients++;
            lblNumberOfConnections.Text = connectedClients.ToString();

            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
            clientThread.Start(client);

        }
    }

    private void HandleClientComm(object client)
    {
        TcpClient tcpClient = (TcpClient)client;
        NetworkStream clientStream = tcpClient.GetStream();

        byte[] message = new byte[4096];
        int bytesRead;

        while (true)
        {
            bytesRead = 0;

            try
            {
                bytesRead = clientStream.Read(message, 0, 4096);
            }
            catch
            {
                break;
            }

            if (bytesRead == 0)
            {
                connectedClients--;
                lblNumberOfConnections.Text = connectedClients.ToString();
                break;
            }

            ASCIIEncoding encoder = new ASCIIEncoding();


            //Write message in RichTextBox

            string msg = encoder.GetString(message, 0, bytesRead);
            WriteMessage(msg);

        }

        tcpClient.Close();
    }

    private void WriteMessage(string msg)
    {
        if (this.rtbServer.InvokeRequired)
        {
            WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
            this.rtbServer.Invoke(d, new object[] { msg });

        }
        else
        {
            this.rtbServer.AppendText(msg + Environment.NewLine);

            // SEND KEYSTROKES TO ACTIVE WINDOW
            if (msg.Equals("CTRL-T"))
            {
               // Keyboard.KeyDown(Keys.LControlKey);
               // Keyboard.KeyPress(Keys.T);             // I was using this for the InputManager Wrapper
               // Keyboard.KeyUp(Keys.LControlKey);
            }

在所有位置搜索之后,以下代码段似乎是让模拟按键在DirectX应用程序中工作的最佳机会,但是我无法在无大量错误且无法使用的情况下将其实现到我的代码中代码.

After searching all over the place, the following snippet seems to be my best chance at getting simulated key strokes to work in a DirectX application, but I haven't been able to implement it into my code with out numerous errors and unusable code.

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

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

    [StructLayout(LayoutKind.Sequential)]
    struct KEYBDINPUT
    {
        public short wVk;
        public short wScan;
        public int dwFlags;
        public int time;
        public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct HARDWAREINPUT
    {
        public int uMsg;
        public short wParamL;
        public short wParamH;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct INPUT
    {
        [FieldOffset(0)]
        public int type;
        [FieldOffset(4)]
        public MOUSEINPUT mi;
        [FieldOffset(4)]
        public KEYBDINPUT ki;
        [FieldOffset(4)]
        public HARDWAREINPUT hi;
    }

    const int KEYEVENTF_EXTENDEDKEY = 0x0001;
    const int KEYEVENTF_KEYUP = 0x0002;
    const int KEYEVENTF_UNICODE = 0x0004;
    const int KEYEVENTF_SCANCODE = 0x0008;

我相信以下部分对我来说可以发送CTRL+T命令,但我不确定100%

I believe the following section would work for me to send the CTRL+T command, but I'm not 100% sure

    // SEND KEYSTROKES TO ACTIVE WINDOW

            if (msg.Equals("CTRL-T"))
{
        INPUT[] InputData = new INPUT[1];

        InputData[0].type = 1;
        InputData[0].ki.wScan = 0x1D;
        InputData[0].ki.time = 0;
        InputData[0].ki.dwExtraInfo = IntPtr.Zero;

        InputData[0].type = 1;
        InputData[0].ki.wScan = 0x14;
        InputData[0].ki.time = 0;
        InputData[0].ki.dwExtraInfo = IntPtr.Zero;

        InputData[0].type = 1;
        InputData[0].ki.wScan = 0x1D;
        InputData[0].ki.dwFlags = 0x0002;
        InputData[0].ki.time = 0;
        InputData[0].ki.dwExtraInfo = IntPtr.Zero;

        SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));
}

我在这里真正遇到的主要问题是如何将键盘挂钩放入现有代码中,并使服务器的其余部分正常运行.使这些击键正常工作是我项目的最后一部分,并且开始令人沮丧,因此感谢您的帮助!

The main thing I'm really struggling with here is how to place the keyboard hook into my existing code, and still have the rest of my server function properly. Getting these keystrokes working is the last part of my project, and it's starting to get quite frustrating, so any help is appreciated!

更新我再次尝试使用keybd_event(),但是由于某种原因,我遇到了同样的问题.它可以在游戏之外的任何地方使用.

UPDATEI've made another attempt, this time using keybd_event(), but for some reason, I've got the same issue; it's working everywhere but in-game.

我使用的是VK代码,而不是DirectInput代码,我不确定这可能是这里的问题,但是我担心如果我使用DI代码而不是我需要的另一部分代码改变我不知道的东西.

I'm using VK codes, not DirectInput codes, I'm not sure if that may be the issue here, but I'm worried if I use the DI codes instead that there's another part of the code I'd need to change that I don't know about.

这是我这次尝试的片段:

Here's a snippet of what I tried this time:

[DllImport("user32.dll", SetLastError = true)]
    static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

    public const int KEYEVENTF_KEYUP = 0x0002;
    public const int VK_LCONTROL = 0xA2;
    public const int SEMICOLON = 0xBA;
    public const int QUOTE = 0xDE;
    public const int T = 0x54;
    public const int H = 0x48;
    public const int R = 0x52;
    public const int Z = 0x5A;
    public const int X = 0x58;
    public const int NUM8 = 0x68;
    public const int NUM2 = 0x62;
    public const int NUM4 = 0x64;
    public const int NUM6 = 0x66;
    public const int NUM5 = 0x65;
    public const int UP = 0x26;
    public const int DOWN = 0x28;
    public const int LEFT = 0x25;
    public const int RIGHT = 0x27;
    public const int RETURN = 0x0D;

// .....

if (msg.Equals("CTRL-T"))
     {
         keybd_event(VK_LCONTROL, 0, 0, 0);
         keybd_event(T, 0, 0, 0);
         keybd_event(T, 0, KEYEVENTF_KEYUP, 0);
         keybd_event(VK_LCONTROL, 0, KEYEVENTF_KEYUP, 0);
      }

我不知道自己的代码是否有问题,或者我仍然使用错误的方法.

I can't figure out if it's something wrong with my code, or if I'm still using the wrong method.

更新2 我再次尝试过,这次使用SendMessage,但是由于hWnd出现错误,所以我无法构建. 名称hWnd在当前上下文中不存在"

UPDATE 2I've tried again, this time using SendMessage, but I've been unable to build, because I'm getting errors with hWnd. "The name hWnd does not exist in the current context"

[DllImport("user32.dll")]
    public static extern IntPtr SetActiveWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, uint wParam, int lParam);

    public const ushort WM_KEYDOWN = 0x0100;
    public const ushort WM_KEYUP = 0x0101;

    private void WriteMessage(string msg)
    {
        if (this.rtbServer.InvokeRequired)
        {
            WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
            this.rtbServer.Invoke(d, new object[] { msg });

        }
        else
        {
            this.rtbServer.AppendText(msg + Environment.NewLine);

            // SEND KEYSTROKES TO ACTIVE WINDOW
            if (msg.Equals("CTRL-T"))
            {

                SetActiveWindow(hWnd);
                SendMessage(hWnd, WM_KEYDOWN, 0x1D, 0);
                SendMessage(hWnd, WM_KEYDOWN, 0x14, 0);
                SendMessage(hWnd, WM_KEYUP, 0x1D, 0);
                SendMessage(hWnd, WM_KEYUP, 0x14, 0);

            }

推荐答案

我最终使用"InputManager" SendInput包装器使一切正常运行.

I ended up getting everything to work perfect using the "InputManager" SendInput wrapper.

using InputManager

//......

Keyboard.KeyPress(Keys.YourSelectedKeyHere);

结果是,我要做的所有不同工作都是以管理员身份运行代码...

Turns out, all I had to do differently was run my code as an Administrator...

这篇关于使用SendInput包装器将击键发送到DirectX应用程序时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-04 23:11