SendInput C#

12/06/2006 20:01 sirru#1
Ich habe folgende Klasse geschrieben:
Code:
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
  class DirectInput
  {
    public enum VK : ushort
    {
      SHIFT = 0x10,
      CONTROL = 0x11,
      MENU = 0x12,
      ESCAPE = 0x1B,
      BACK = 0x08,
      TAB = 0x09,
      RETURN = 0x0D,
      PRIOR = 0x21,
      NEXT = 0x22,
      END = 0x23,
      HOME = 0x24,
      LEFT = 0x25,
      UP = 0x26,
      RIGHT = 0x27,
      DOWN = 0x28,
      SELECT = 0x29,
      PRINT = 0x2A,
      EXECUTE = 0x2B,
      SNAPSHOT = 0x2C,
      INSERT = 0x2D,
      DELETE = 0x2E,
      HELP = 0x2F,
      NUMPAD0 = 0x60,
      NUMPAD1 = 0x61,
      NUMPAD2 = 0x62,
      NUMPAD3 = 0x63,
      NUMPAD4 = 0x64,
      NUMPAD5 = 0x65,
      NUMPAD6 = 0x66,
      NUMPAD7 = 0x67,
      NUMPAD8 = 0x68,
      NUMPAD9 = 0x69,
      MULTIPLY = 0x6A,
      ADD = 0x6B,
      SEPARATOR = 0x6C,
      SUBTRACT = 0x6D,
      DECIMAL = 0x6E,
      DIVIDE = 0x6F,
      F1 = 0x70,
      F2 = 0x71,
      F3 = 0x72,
      F4 = 0x73,
      F5 = 0x74,
      F6 = 0x75,
      F7 = 0x76,
      F8 = 0x77,
      F9 = 0x78,
      F10 = 0x79,
      F11 = 0x7A,
      F12 = 0x7B,
      OEM_1 = 0xBA,  // ',:' for US
      OEM_PLUS = 0xBB,  // '+' any country
      OEM_COMMA = 0xBC,  // ',' any country
      OEM_MINUS = 0xBD,  // '-' any country
      OEM_PERIOD = 0xBE,  // '.' any country
      OEM_2 = 0xBF,  // '/?' for US
      OEM_3 = 0xC0,  // '`~' for US
      MEDIA_NEXT_TRACK = 0xB0,
      MEDIA_PREV_TRACK = 0xB1,
      MEDIA_STOP = 0xB2,
      MEDIA_PLAY_PAUSE = 0xB3,
      LWIN = 0x5B,
      RWIN = 0x5C
    }

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

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

    public static void Send(String message)
    {
      INPUT[] input = new INPUT[message.Length];
      for (int i = 0; i <= message.Length - 1; i++)
      {
        input[i].type = 1;
        input[i].ki.wVk = (short)message[i];
        input[i].ki.dwFlags = 0x01;        
      }
      uint sent = SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]));
    }
  }
Die rufe ich jetzt folgendermaßen auf
Code:
DirectInput.Send(textBox1.Text);
nachdem ich mit folgendem Codeblock zum Notepad gewechselt habe
Code:
private void SwitchToProcess(string m_processName)
    {
      int ret;
      IntPtr hwndMain;
      Process[] myProcesses = Process.GetProcessesByName(
        m_processName);
      foreach (Process p in myProcesses)
      {
        if (p.Id != Process.GetCurrentProcess().Id)
        {
          hwndMain = p.MainWindowHandle;
          if (IsIconic(hwndMain) != 0)
          { // Fenster minimiert?
            ret = OpenIcon(hwndMain);
            if (ret == 0)
            {
              throw new Exception(
          "Error restoring Window from icon");
            }
          }
          ret = SetForegroundWindow(hwndMain);
          if (ret == 0)
          {
            throw new Exception(
         "Error bringing Window to front");
          }
          return;
        }
      }
    }
Das komische ist nur, dass die KeyCodes anscheinend nicht stimmen. Wenn ich ABCDEFG eintippe gibt er abcdefg aus, bei abcdefg schreibt er 1234567. Zahlen hingegen werden einwandfrei ausgegeben. Darüber hinaus macht er aus einem M ein - und s werden total ignoriert. Hilfe erwünscht :ops:
12/06/2006 21:32 NoName#2
Code:
 input[i].type = 1;
 input[i].ki.wVk = (short)message[i];
 input[i].ki.dwFlags = 0x01;
das mit folgenden ersetzen

Code:
input[i].type = 1;
input[i].ki.dwFlags = 0x0004;
input[i].ki.wScan = *(short)message[i];
dann nutzt er unicode fürs übermitteln, ansonsten müsstest du ne shift simulieren

weil mit dwflags auf 1 simulierst du tastendrücke, als wenn du mit der tastatur schreiben würdest und ne tastatur hat keine klein und grossbuchstaben und vordefiniert sind die werte als grossbuchstaben deshalb fügt er bei kleinen buchstaben mit deiner methode anderes zeugs ein, weil das die definition davon sind.
12/07/2006 16:12 sirru#3
Danke, hat toll funktioniert.
Mein einziges Problem ist jetzt noch, dass er mehrere identische Zeichen hintereinander nicht mag, bei aaa schreibt er nur a, gibts da ne möglichkeit das im Befehl zu unterbinden oder muss ich dafür ne Abfrage einbauen?
12/07/2006 17:46 sirru#4
Folgender Code funktioniert im Debugger, leider nicht im Spiel
Code:
    public static void Send(string message)
    {
      INPUT[] input = new INPUT[message.Length];
      uint sent = 0;
      char m_prevChar = (char)0;
      for (int i = 0; i <= message.Length - 1; i++)
      {
        if (message[i] == m_prevChar)
        {
          string m_substring = message.Substring(i, message.Length - i);
          sent = SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]));
          SendKeyup(input);
          Send(m_substring);
          return;
        }
        input[i].type = 1;
        input[i].ki.dwFlags = 0x04;//0x0004;
        input[i].ki.wScan = (short)message[i];
        m_prevChar = message[i];
      }
      sent = SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]));
      SendKeyup(input);
    }

    public static void SendKeyup(INPUT[] input)
    {
      uint sent = 0;
      for (int i = 0; i <= input.Length-1; i++)
      {
        input[i].ki.dwFlags = 0x02;
      }
      sent = SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]));
    }
Im Notepad geht es übrigens manchmal, seltsam seltsam :/
12/07/2006 19:43 sirru#5
Ok, anscheinend funktionierts schon wenn ich vor
Code:
 sent = SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]));
ein Thread.Sleep(200); einfüge, den m_prevChar Kram kann ich mir sparen. Blöd nur dass ich davon nix sehe.
Bei Cy und jemand anderem dem ich mein Programm gezeigt habe klappt alles wunderbar, nur leider bei mir nicht.
Jemand ne Ahnung was falsch sein könnte?
[Only registered and activated users can see links. Click Here To Register...] Da gibts den Sourcecode, bei dem lediglich das Thread.Sleep(200); noch fehlt.