C# SendInput Methode für Tastenkombinationen

Fou-Lu

Lt. Junior Grade
Registriert
Aug. 2006
Beiträge
290
Hallo cbler,

ich bin wirklich kurz vorm verrückt werden wegen der SendInput Methode.

Ich will damit Tastaturkürzel wie z.B. "Strg + Alt + Entf" oder einfach nur "Shift + Buchstabe" senden, aber irgendwie klappt es ganz und gar nicht!!

Mausklicks hab ich wunderbar zum laufen gebracht. Funktioniert wunderbar. Auch normale Tastatureingaben (also einzelne Tasten z.B. a, b, entf, enter, up, down, ...) funktionieren hervorragend. Aber sobald ich z.B. Shift + A sende, dann bleibt bei mir die Shifttaste aktiviert und egal was ich mach ich kann sie nicht deaktivieren (es sei den ich drücke sie direkt auf der Tastatur noch einmal).

Hier mal meine Methode:

PHP:
//Shift Down
INPUT shiftDown = new INPUT();
shiftDown.type = InputType.INPUT_KEYBOARD;
shiftDown.ki.wVk = (VKeys)KeyCodes["ShiftKey"]; //VKeys ist eine enumeration. ShiftKey entspricht dem Wert: 0x10

//Shift Up
INPUT shiftUp = new INPUT();
shiftUp.type = InputType.INPUT_KEYBOARD;
shiftUp.ki.wVk = (VKeys)KeyCodes["ShiftKey"];
shiftUp.ki.dwFlags = KEYEVENTF.KEYUP;

//Key Down
INPUT keyDown = new INPUT();
keyDown.type = InputType.INPUT_KEYBOARD;
keyDown.ki.wVk = keyCode; // ist die zusätzlich gedrückte Taste z.B. der Code 0x48 für H

//Key Up
INPUT keyUp = new INPUT();
keyUp.type = InputType.INPUT_KEYBOARD;
keyUp.ki.wVk = keyCode;
keyUp.ki.dwFlags = KEYEVENTF.KEYUP;

//SendInput
INPUT[] input = { shiftDown, keyDown, keyUp, shiftUp };
uint failure = SendInput(4, input, Marshal.SizeOf(new INPUT()));

Also wenn ich die Funktion so aufrufe, dann schaltet es zwar auf Großschreibung, aber es bleibt so zu sagen "hängen". Die Shift-Taste wird nicht mehr released. Erst wenn ich auf der Tastatur dann nochmals die Shift-Taste betätige.

Hoffe ihr könnt mir helfen. Bin echt am verzweifeln.
 
Die SendKeys Methode hilft mir in meinem Fall leider nicht weiter, aber trotzdem danke für den Hinweis :) .

Außerdem interessiert es mich brennend wieso mein Code oben so rumspinnt :D .

Es kann ja echt nicht sein, dass ich z.B. wegen so ner Kleinigkeit mal ein ganzes Projekt einstampfen muss (oder eben umbauen auf SendKeys z.B. ) :(
 
naja, schau halt was mehr zeit kostet. das nachforschen, oder das nutzen einer alternativen technik :)
 
Ich glaub es kostet beides viel Zeit xDD

Ich sitze jetzt bereits seit 6 Stunden an diesem verdammten Problem und habs immernoch nicht gelöst. Aber allein schon deswegen, weil ich in Zukunft nicht (wenn das Problem mal wieder auftaucht) nicht alles umkrämpeln will (oder falls jemand anderes ähnliches Problem hat, dann kann ich ihm vielleicht auch weiterhelfen :) ), will ichs jetzt lösen. ^^
 
Auf den Beitrag bin ich bei meiner Suche auch gestoßen, aber selbst wenn ich es so schreibe:

PHP:
//Shift Down
INPUT shiftDown = new INPUT();
shiftDown.type = InputType.INPUT_KEYBOARD;
shiftDown.ki.wVk = (VKeys)KeyCodes["ShiftKey"];
shiftDown.ki.dwFlags = KEYEVENTF.EXTENDEDKEY;

//Shift Up
INPUT shiftUp = new INPUT();
shiftUp.type = InputType.INPUT_KEYBOARD;
shiftUp.ki.wVk = (VKeys)KeyCodes["ShiftKey"];
shiftUp.ki.dwFlags = KEYEVENTF.EXTENDEDKEY | KEYEVENTF.KEYUP;

dann hab ich immernoch das selbe Problem.
 
Also falls ichs richtig verstanden habe mit "delay" dass ich sowas wie ne kleine Pause dazwischen brauche, dann funktioniert das auch nicht.

Hab folgendes benutzt:

INPUT[] input = { shiftDown, keyDown, keyUp };
SendInput(...);

Thread.Sleep(200);
INPUT[] input2 = { shiftUp };
SendInput(...);
 
ist das projekt zu umfangreich, um es zu posten? evtl. kannst du den SendInput kram ja in ein separates projekt auslagern, damit man sich das mal live anschauen kann
 
Naja eigentlich gibts da nicht viel zu posten, aber hier mal der Code:

PHP:
[DllImport("user32.dll", EntryPoint = "SendInput", SetLastError = false)]
	static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

private enum InputType {
	INPUT_MOUSE = 0,
	INPUT_KEYBOARD = 1,
	INPUT_HARDWARE = 2,
}

[StructLayout(LayoutKind.Explicit, Size = 8)]
private struct INPUT {
	[FieldOffset(0)]
	public InputType type;
	[FieldOffset(4)]
	public MOUSEINPUT mi;
	[FieldOffset(4)]
	public KEYBDINPUT ki;
}

[StructLayout(LayoutKind.Sequential)]
private struct KEYBDINPUT : IDisposable {
	public short wVk;
	public short Scan;
	public KEYEVENTF dwFlags;
	public int time;
	public IntPtr dwExtraInfo;

	public void Dispose() {
	}
}

[Flags()]
private enum KEYEVENTF {
	EXTENDEDKEY = 0x0001,
	KEYUP = 0x0002,
	SCANCODE = 0x0008,
	UNICODE = 0x0004,
}

Das war jetzt der Standardcode den man eh überall im Inet findet. Der ist einfach nötig um die SendInput-Methode überhaupt verwenden zu können.

Hier noch meine Methode für die ShiftTaste:

PHP:
public void ShiftEnter(short taste) {
	try {
		//Shift Down
		INPUT shiftDown = new INPUT();
		shiftDown.type = InputType.INPUT_KEYBOARD;
		shiftDown.ki.wVk = 0x10; //steht für Shift-Taste
		shiftDown.ki.dwFlags = KEYEVENTF.EXTENDEDKEY;

		//Shift Up
		INPUT shiftUp = new INPUT();
		shiftUp.type = InputType.INPUT_KEYBOARD;
		shiftUp.ki.wVk = 0x10; //steht für Shift-Taste
		shiftUp.ki.dwFlags = KEYEVENTF.EXTENDEDKEY | KEYEVENTF.KEYUP; 

		//Key Down
		INPUT keyDown = new INPUT();
		keyDown.type = InputType.INPUT_KEYBOARD;
		keyDown.ki.wVk = taste; //jeweiliger Code für die übergebene Taste

		//Key Up
		INPUT keyUp = new INPUT();
		keyUp.type = InputType.INPUT_KEYBOARD;
		keyUp.ki.wVk = taste; //jeweiliger Code für die übergebene Taste
		keyUp.ki.dwFlags = KEYEVENTF.KEYUP;

		//SendInput
		INPUT[] input = { shiftDown, keyDown, keyUp, shiftUp };
		uint failure = SendInput(4, input, Marshal.SizeOf(new INPUT()));
	} catch (ArgumentException) {
	} catch (NullReferenceException) {
	}
}


Den Code kann man ja überall einsetzen ob in eigene Klasse oder direkt die WinForms-Klasse und dann z.b. per Button-Klick die ShiftEnter(short taste) Funktion aufrufen :)
 
weißt den keiner Rat? Langsam bin ich echt am verzweifeln!!
 
Fou-Lu schrieb:
weißt den keiner Rat? Langsam bin ich echt am verzweifeln!!

Ja doch .. :p SendInput macht Probleme bei längeren Arrays. :D
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Keyboarddown {
  static class Program {
    [DllImport("user32.dll", SetLastError = true)]
    static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr GetMessageExtraInfo();

    private enum InputType {
      INPUT_MOUSE = 0,
      INPUT_KEYBOARD = 1,
      INPUT_HARDWARE = 2,
    }

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

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

    [Flags()]
    private enum MOUSEEVENTF {
      ABSOLUTE = 0x8000,
      MOVE = 0x0001,
      LEFTDOWN = 0x0002,
      LEFTUP = 0x0004,
      RIGHTDOWN = 0x0008,
      RIGHTUP = 0x0010,
      MIDDLEDOWN = 0x0020,
      MIDDLEUP = 0x0040,
      VIRTUALDESK = 0x4000,
      WHEEL = 0x0800,
      XDOWN = 0x0080,
      XUP = 0x0100,
    }

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

    [Flags()]
    private enum KEYEVENTF {
      EXTENDEDKEY = 0x0001,
      KEYUP = 0x0002,
      UNICODE = 0x0004,
      SCANCODE = 0x0008
    }

    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,
      OEM_PLUS = 0xBB,
      OEM_COMMA = 0xBC,
      OEM_MINUS = 0xBD,
      OEM_PERIOD = 0xBE,
      OEM_2 = 0xBF,
      OEM_3 = 0xC0,
      MEDIA_NEXT_TRACK = 0xB0,
      MEDIA_PREV_TRACK = 0xB1,
      MEDIA_STOP = 0xB2,
      MEDIA_PLAY_PAUSE = 0xB3,
      LWIN = 0x5B,
      RWIN = 0x5C
    }

    [STAThread]
    public static void Main() {
      KeyPressedWithModifier();
    }

    // Der Tastencode, hier z.B a
    public static short vk = 0x41;
    public static bool Shift = true; // Shift gedrückt ..
    public static bool Ctrl = false;
    public static bool Alt = false;
    public static bool Win = false;

    public static void KeyPressedWithModifier() {
      INPUT structInput = new INPUT();
      structInput.type = InputType.INPUT_KEYBOARD;
      structInput.ki.wScan = 0;
      structInput.ki.time = 0;
      structInput.ki.dwFlags = 0;
      structInput.ki.dwExtraInfo = GetMessageExtraInfo();
      // Key down shift, ctrl, alt, and/or Win
      SendModifiers(structInput);
      // Key down der aktuelle Tastencode
      structInput.ki.wVk = vk;
      SendKey(structInput);
      // Key up des Tastencodes
      structInput.ki.dwFlags = KEYEVENTF.KEYUP;
      SendKey(structInput);
      // Key up shift, ctrl, alt, and/or Win
      SendModifiers(structInput);
    }

    private static void SendModifiers(INPUT structInput) {
      if (Shift)
        SendModifier(structInput, (short)VK.SHIFT);

      if (Ctrl)
        SendModifier(structInput, (short)VK.CONTROL);

      if (Alt)
        SendModifier(structInput, (short)VK.MENU);

      if (Win)
        SendModifier(structInput, (short)VK.LWIN);
    }

    private static void SendModifier(INPUT structInput, short wVk) {
      structInput.ki.wVk = wVk;
      SendKey(structInput);
    }

    private static void SendKey(INPUT structInput) {
      SendInput(1, new INPUT[] { structInput }, Marshal.SizeOf(structInput));
    }
  }
}

Edit: Evtl. liegt es daran das bei Deinem Code bei allen time = 0 ist und die Ausführungsreihenfolge dann zufällig ist?
 
Zuletzt bearbeitet:
Also ich hab zwar deinen Code noch nicht ausprobiert, aber was soll ich den sonst hinschreiben statt "time=0"? ^^

meld mich wieder sobald ich deinen code ausprobiert hab ;-)
Ergänzung ()

Ok es funktioniert tatsächlich. allem anschein nach lag es wirklich lediglich daran, dass ich alle aktionen in die sendinput methode gepackt habe.

wenn ich die sendinput methode mehrmals aufrufe wie in deinem code oben, dann funktioniert alles wunderbar.

vielen vielen dank =)
Ergänzung ()

Also langsam nervt es aber echt tierisch. Jetzt z.B. bleibt die Alt Taste hängen -_-"

Obwohl ichs genauso mache wie oben auch. Genau wie bei der Shifttaste.

PHP:
INPUT variable = new INPUT();
variable.type = InputType.INPUT_KEYBOARD;
variable.ki.wScan = 0;
variable.ki.time = 0;
variable.ki.dwFlags = KEYEVENTF.EXTENDEDKEY; //Strg, Alt und Entf sind ja EXTENDED Keys, deswegen als Flag "EXTENDEDKEY" 

SendModifier(variable, (short)(VKeys)KeyCodes["ControlKey"]); //entspricht 0x11 für Control
SendModifier(variable, (short)(VKeys)KeyCodes["Menu"]); //entspricht 0x12 für Alt
SendModifier(variable, (short)(VKeys)KeyCodes["Delete"]); //entspricht 0x2E für Entf

variable.ki.dwFlags |= KEYEVENTF.KEYUP;

SendModifier(variable, (short)(VKeys)KeyCodes["Delete"]);
SendModifier(variable, (short)(VKeys)KeyCodes["Menu"]);
SendModifier(variable, (short)(VKeys)KeyCodes["ControlKey"]);

Hab auch schon als Flag "0 | KEYEVENTF.EXTENDEDKEY" probiert, aber leider auch nichts. Alt hängt nach wie vor und der Taskmanager öffnet sich auch nicht!
 
Zuletzt bearbeitet:
evtl. ist es nun doch an der zeit, die geschichte mal mit der SendKeys klasse zu probieren :)
evtl. hast du da ja mehr erfolg.
 
Werd mir die Links gleich mal anschauen, aber ich danke schon mal vielmals für den Hinweis. Hätte echt nicht gedacht, dass Microsoft den schmarn nicht zulässt über SendInput. Ist aber wohl sogar besser so, wenn mans recht bedenkt. (ist nur blöd, wenn man es nicht weiß und ewig versucht das anzustellen :D ) ;-)
 
Zurück
Oben