Tastendruck für eine andere Anwendung simulieren
-
Hallo,
ich möchte aus meinem Programm heraus einen Tastendruck "F1" für eine zweite bereits laufende Anwendung simulieren. Mein Programm funktioniert auch schon, siehe unten. Zum Ausprobieren verwende ich "Notepad" als zweites Programm, wo durch "F1" die Hilfe-Seite geöffnet wird. Später soll auf diese Weise ein anderes Programm zu einer bestimmten Aktion veranlasst werden.
1. Frage: Dies ist eines meiner ersten C# Programme. Ich bitte um Hinweise was man daran verbessern könnte.
2. Frage: Eigentlich möchte ich das zweite Programm gar nicht in den Vordergrund bringen. Es würde völlig genügen, wenn es im Hintergrund läuft und den simulierten Tastendruck bekommt. Geht das irgendwie?Gruß
Michaelusing System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Runtime.InteropServices; public class WinAPI { [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr i); } namespace fernbedienung_test1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) // Wenn ich auf diesen Button drücke { Process[] allNotepads = Process.GetProcessesByName("notepad"); // dann werden alle Notepad Anwendungen gesucht if (allNotepads.Count() == 0) // Fehlermeldung falls kein Notepad gefunden wurde... { MessageBox.Show("Kein Notepad gefunden!"); return; } IntPtr notepadHandle = allNotepads.First().MainWindowHandle; // der erste Notepad aus der Liste wird genommen... WinAPI.SetForegroundWindow(notepadHandle); // in den Vordergrund gebracht... System.Threading.Thread.Sleep(200); // etwas Verzögerungszeit scheint notwendig zu sein SendKeys.Send("{F1}"); // dann wird {F1} an das Notepad gesendet SendKeys.Flush(); // wichtig, sonst geht's nicht WinAPI.SetForegroundWindow(Process.GetCurrentProcess().MainWindowHandle); // und dann wird der Fokus wieder auf dieses Programm gelegt } } }
-
Stichworte: SendMessage sowie WM_KEYDOWN bzw. WM_KEYUP
-
-
Hallo,
danke für eure Antworten. Ich habe inzwischen viele Diskussionsbeiträge zu SendMessage und SendInput gelesen, aber meistens sind das nur Fragen weil es nicht so funktioniert wie es soll, und nur wenige Lösungen die angeblich funktionieren sollen -- und durch die steige ich nicht durch. Ich werde es besser so lassen wie es ist. Ist zwar nicht schön wenn dauernd der Fokus hin- und hergeschaltet werden muss, aber es funktioniert wenigstens.
Gruß
Michael
-
Hallo,
also mal angenommen ich würde den Tastendruck über SendMessage oder über SendInput an die andere Anwendung senden. Wie legt man dann fest wo die Nachricht hin gesendet werden soll, wenn man die andere Anwendung nicht mit SetForegroundWindow in den Vordergrund bringen will?
Gruß
Michael
-
In dem du beim SendMessage / eher PostMessage (damit deine Anwendungs nicht wartet bis dein Tastendruck wirklich gesendet wird) beim HWND das Fensterhandle des Empfangsfensters mitgibst.
Du gehst also hin und suchst dir erst Mal das Empfangsfenster, merkst dir das Fensterhandle und übergibst den Parameter Send- / Postmessage.
Aber Achtung, mit Notepad zu testen ist eher schlecht. Das Mainwindow reagiert nicht auf A-Z Tasten. Dazu müsstest du dir das Childcontrol ermitteln. Genau hier wird kniffeliger. Es kommt drauf an was du machen willst. Möchtest du in einer Externen Form / externen Dialog einfach eine Taste senden oder sogar eine TextBox etc. füllen?
-
Hallo,
Hellsgore schrieb:
In dem du beim SendMessage / eher PostMessage (damit deine Anwendungs nicht wartet bis dein Tastendruck wirklich gesendet wird) beim HWND das Fensterhandle des Empfangsfensters mitgibst.
Stimmt. Meine Frage bezog sich nur auf SendInput, da wird nämlich kein HWND übergeben. Hat sich aber inzwischen erledigt, siehe unten.
Hellsgore schrieb:
Aber Achtung, mit Notepad zu testen ist eher schlecht. Das Mainwindow reagiert nicht auf A-Z Tasten.
Danke, das war jetzt der entscheidende Hinweis. Ich hatte nämlich versucht, einen einzelnen Buchstaben zu senden, und da ist beim Notepad nichts angekommen.
Eigentlich muss ich aber einen "F1" Tastendruck simulieren. Und das funktioniert jetzt mit PostMessage, auch dann wenn sich die Ziel-Anwendung im Hintergrund befindet. Ich bitte um Kommentare ob das so ok ist:using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Runtime.InteropServices; public class WinAPI { [DllImport("user32.dll")] public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); } namespace fernbedienung_test2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) // Wenn ich auf diesen Button drücke { Process[] allNotepads = Process.GetProcessesByName("notepad"); // dann werden alle Notepad Anwendungen gesucht if (allNotepads.Count() == 0) // Fehlermeldung falls kein Notepad gefunden wurde... { MessageBox.Show("Kein Notepad gefunden!"); return; } IntPtr notepadHandle = allNotepads.First().MainWindowHandle; // das erste Notepad aus der Liste wird genommen... const uint WM_KEYDOWN = 0x100; const uint WM_KEYUP = 0x101; WinAPI.PostMessage(notepadHandle, WM_KEYDOWN, (IntPtr)Keys.F1, IntPtr.Zero); WinAPI.PostMessage(notepadHandle, WM_KEYUP, (IntPtr)Keys.F1, IntPtr.Zero); } } }
-
micha7 schrieb:
Hallo,
Hellsgore schrieb:
In dem du beim SendMessage / eher PostMessage (damit deine Anwendungs nicht wartet bis dein Tastendruck wirklich gesendet wird) beim HWND das Fensterhandle des Empfangsfensters mitgibst.
Stimmt. Meine Frage bezog sich nur auf SendInput, da wird nämlich kein HWND übergeben. Hat sich aber inzwischen erledigt, siehe unten.
Ne, das geht bei SendInput und keyb_event nicht. Dort musst du tatsächlich das Fenster in den Vordergrund setzen.
Der Rest sieht doch gut aus. Sollte so funktionieren.
Gruß
Hellsgore