Taste an Fenster senden
-
Ich habe weiter rumprobiert und was festgestellt.
Statt dem KEYDOWN habe ich einfach mal das gleiche nur mit der Maus gemacht.SendMessage(this.Handle, 513, 1, IntPtr.Zero);
513 steht hierbei für
#define WM_LBUTTONDOWN 513
die 1 eigentlich für
#define VK_LBUTTON 1
Aufjedenfall, nach Ausführung der Methode, habe ich nichts besonderes festgestellt. Aber als ich dann auf den x-Button zum schließen des Fensters klicken wollte, ging es beim ersten Mal nicht. Ich musste ein 2. mal klicken, damit etwas passiert. D.h., dass SendMessage wohl funktioniert, denn es hatte wohl noch ein LButtonDown drin. Als ich darunter die gleiche Ausführung, nur mit 514, für LBUTTONUP benutzt habe, ging es auch wieder beim 1. Klick. Allerdings hat die Maus nicht geklickt, als ich sie z.B. über einen Button gehalten habe. Irgendwas mache ich wohl also falsch mit wParam oder lParam.
-
Wenn du eine Taste an ein Fenster senden willst, musst du sie mit einem Schraubenzieher rausbrechen, in einen Briefumschlag stecken und die Adresse eines Fensters draufschreiben.
Oder du simulierts einen Tastendruck.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx
-
"Danke" für die "Hilfe".
Aber wie schon erwähnt, funktioniert SendInput nicht.Edit:
P.S., falls das Schlüsselwort keybd_event() fallen sollte, dass habe ich auch schon probiert und es funktioniert auch nicht in dem Fenster.
-
In welchem Fenster wird die TAB-Taste (ASCII 9) gedrückt und welchem anderen Fenster soll das Ereignis mitgeteilt werden? Zufälligerweise ein Edit-Fenster? Wenn ja, eignet sich subclassing zum Abfangen von WM_CHAR gut. Die Mitteilung kann dann bequem mit SendMessage systemweit überall hin geschickt werden. Diesen Weg kenne und benutze ich, anderes dafür nicht.
-
Nein, die Taste soll in einem Spiel gedrückt werden. Wenn ich in meinem Programm auf einen Button klicke, soll 5 Sekunden später die Taste im Spiel gedrückt werden.
-
FreakY<3Cpp schrieb:
Nein, die Taste soll in einem Spiel gedrückt werden. Wenn ich in meinem Programm auf einen Button klicke, soll 5 Sekunden später die Taste im Spiel gedrückt werden.
Oh Mann, kann man sich nicht für alle klar verständlich ausdrücken?
Also: Ein Spiel --> Button wird gedrückt --> 5 Sekunden später wird eine Tastatureingabe simuliert so als hätte der Benutzer das gemacht --> Spiel geht weiter ==> unsere Raterei auch!
-
FreakY<3Cpp schrieb:
Das Programm, eher ein Spiel, soll die Taste TAB entgegen nehmen.
Ich hab eine WinForms Anwendung, die einen Button enthält. Wenn ich diesen Button drücke, soll in den nächsten 5 Sekunden die TAB-Taste in diesem Spiel gedrückt werden. Ob ich dafür das Spiel offen haben muss oder nicht, ist egal. Beides wäre okay. Dieses Spiel nimmt aber bei keinen der oben genannten Varianten die simulierte Taste entgegen, es reagiert nicht. Wenn ich allerdings es z.B. in meinem WinForms Fenster ausprobiere, klappt es z.B. mit keybd_event() und SendKeys.SendWait. SendInput hat erst garnicht geklappt und ich vermute das es mit SendMessage funktionieren sollte, ich es aber scheinbar falsch verwende. Deutlich genug?
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum Rund um die Programmierung in das Forum C# und .NET verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
@FreakY<3Cpp
Mach mal folgendes: Sende erst den Down und dann den Up an den Button.
-
inflames2k schrieb:
@FreakY<3Cpp
Mach mal folgendes: Sende erst den Down und dann den Up an den Button.
Das ist des Rätsels Lösung
Dein Spielchen wird wohl auf ein "Key Pressed" oder "Key Up" warten. Mit "Key Down" passiert da erstmal nicht viel...
Ich habe selbst damit mal sehr viel rumgetestet und kam zu folgenden Entschluss:
[DllImport("User32.dll", EntryPoint = "MapVirtualKey")] internal static extern uint MapVirtualKey(uint uCode, uint uMapType); [DllImport("User32.dll", EntryPoint = "keybd_event")] internal static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); internal static void SendKey(int key, int modifier) { bool ctrlKey = ( ( modifier & (int)Keys.Control ) == (int)Keys.Control ); bool altKey = ( ( modifier & (int)Keys.Alt ) == (int)Keys.Alt ); bool shiftKey = ( ( modifier & (int)Keys.Shift ) == (int)Keys.Shift ); if ( ctrlKey ) keybd_event((byte)Keys.ControlKey, 0x1D, 0, UIntPtr.Zero); if ( altKey ) keybd_event((byte)Keys.Menu, 0x38, 0, UIntPtr.Zero); if ( shiftKey ) keybd_event((byte)Keys.ShiftKey, 0x2A, 0, UIntPtr.Zero); uint scanCode = MapVirtualKey((uint)key, 0); keybd_event((byte)key, (byte)scanCode, 0, UIntPtr.Zero); keybd_event((byte)key, (byte)scanCode, KEYEVENTF_KEYUP, UIntPtr.Zero); if ( ctrlKey ) keybd_event((byte)Keys.ControlKey, 0x1D, KEYEVENTF_KEYUP, UIntPtr.Zero); if ( altKey ) keybd_event((byte)Keys.Menu, 0x38, KEYEVENTF_KEYUP, UIntPtr.Zero); if ( shiftKey ) keybd_event((byte)Keys.ShiftKey, 0x2A, KEYEVENTF_KEYUP, UIntPtr.Zero); }
Bevor die Methode augerufen wird, sorge ich nur noch dafür das das zu empfangende Fenster den Focus erhält. Bzw. das Empfangsfenster verliert nicht den Focus, wenn in meiner Anwendung etwas gemacht wird.
Hiermit kannst du auch direkt Tastenkombinationen schicken.
gruß
Hellsgore
-
Erstmal vielen Dank für die Hilfe. Leider funktioniert es immer noch nicht.
Ich habe deinen Code verwendet, der auch außerhalb des Spiels funktioniert. Auch wie du sagtest, habe ich vorher das hier verwendet[System.Runtime.InteropServices.DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd);
um sicher zu stellen, dass es im Fokus ist.
Ich habe es jetzt mal bei einem anderen Spiel getestet, es funktioniert. Kann man etwa ein Spiel dagegen sichern, dass es keine virtuellen Tastendrücke entgegen nimmt? Wenn ja, könnte man sowas umgehen, bzw., könnte man einen Tastendruck noch "besser" simulieren?
-
Vermutlich verwendet dein Spielchen DirectX.
-
Und nur wegen DirectX werden meine virtuellen Tastendrücke nicht erkannt? Kann man dagegen was machen?
-
FreakY<3Cpp schrieb:
Und nur wegen DirectX werden meine virtuellen Tastendrücke nicht erkannt? Kann man dagegen was machen?
Das hättes du noch erwähnen sollen
Bei DirectX wird DirectInput verwende. Der greift direkt die Tastendrücke ab und interessiert sich einen feuchten ... für die WindowsMessageLoop.
Bei verschiedenen Spielchen hats funktioniert, bei Anderen wiederum nicht. Ich denke mal die Leute die sich mit der DirectX SDK beschäftigt haben, können das bestimmt erklären. Hier hören meine Kenntnisse aber wieder auf.
Du kannst noch ein "KEYEVENTF_SCANCODE" als Flag mit übergeben. Vielleicht schaut er noch zusätzlich explizit auf den Scancode.
KEYEVENTF_SCANCODE = 0x08; keybd_event((byte)key, (byte)scanCode, KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE, UIntPtr.Zero);
Ansonsten Google mit "directx directinput simulation". Gibts schon massig Themen...
gruß
Hellsgore
-
Vielen Dank für die Hilfe, es funktioniert endlich.
Für die Nachwelt:
Ich habe den Code, den man unter diesem Link finden kann http://www.gamedev.net/topic/419710-simulate-keypress-and-directx/ , benutzt.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); private void button2_Click(object sender, EventArgs e) { //... INPUT[] InputData = new INPUT[1]; InputData[0].type = 1; //INPUT_KEYBOARD InputData[0].wScan = (ushort)0x0F; 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()); } //... }
Bei der Zeile
InputData[0].wScan = (ushort)0x0F;
muss man dann den Keycode eingeben. Da ich die TAB-Taste wollte, wäre das eig. ASCII 0x09, aber DirectX hat da eine andere Tabelle: http://tescosi.com/wiki/General:DirectX_KeyMap
Deswegen ist die TAB Taste 0x0F.Vielen Dank nochmal für die Hilfe.