Hallo zusammen, Ich möchte mit C# WPF eine Benutzeroberfläche programmieren, mit der auf ein Programm einer CNC-Steuerung zugegriffen werden kann. - Die Benutzeroberfläche hat das Ziel, die Bedienung der CNC-Maschine auf das Nötigste zu reduzieren. Die Oberfläche muss mit WPF erstellt werden, Windows Forms kommt aufgrund von Vorgaben nicht in Frage. - Das Programm, welches die CNC-Maschine steuert, läuft unter einem normalen Windows-Rechner. Die Befehle, die das Programm ausführen soll, können mit den Funktionstasten F2 bis F9 durchgeführt werden. - Beim Start der Oberfläche wird das CNC-Steuerprogramm unsichtbar mit geöffnet. Die Oberfläche besteht aus Buttons mit der Aufschrift "Referenzfahrt durchführen", "Parkposition anfahren", "Job starten", etc. - Bei einem Klick auf einen dieser Buttons soll der Druck auf eine Funktionstaste (F2 bis F9, je nach gedrückten Button) simuliert und an das CNC-Programm weitergeleitet werden. Das Problem dabei ist, das ich zum einen nicht weiß, wie ich den Druck auf eine Taste unter WPF simulieren kann (ich habe nur was gefunden, wie das unter Windows Forms geht) und zum anderen habe ich keine Idee, wie ich dann diesen Tastendruck an das CNC-Programm senden kann. Ich hoffe Ihr könnt mir helfen oder zumindest Tipps geben, in welche Richtung ich arbeiten sollte. Danke
:
Verschoben durch User
Daniel M. schrieb: > Das Problem dabei ist, das ich zum einen nicht weiß, wie ich den Druck > auf eine Taste unter WPF simulieren kann (ich habe nur was gefunden, wie > das unter Windows Forms geht) und zum anderen habe ich keine Idee, wie > ich dann diesen Tastendruck an das CNC-Programm senden kann. das hat auch nicht mit Windows Form oder WPF zu tun. Unter Windows werden Tastatureingaben per Event an ein Programm gesteuert. Du musst also nur die ProcessID von dem anderen Programm ermitteln und dann kannst du dort einen Event hin schicken.
Peter II schrieb: > Daniel M. schrieb: >> Das Problem dabei ist, das ich zum einen nicht weiß, wie ich den Druck >> auf eine Taste unter WPF simulieren kann (ich habe nur was gefunden, wie >> das unter Windows Forms geht) und zum anderen habe ich keine Idee, wie >> ich dann diesen Tastendruck an das CNC-Programm senden kann. > > das hat auch nicht mit Windows Form oder WPF zu tun. > > Unter Windows werden Tastatureingaben per Event an ein Programm > gesteuert. Du musst also nur die ProcessID von dem anderen Programm > ermitteln und dann kannst du dort einen Event hin schicken. Vielen Dank für die Antwort. Ist die Prozess ID dynamisch, d.h. bei jedem Start des Programms anders, oder ist sie immer gleich?
Daniel M. schrieb: > Ist die Prozess ID dynamisch, d.h. bei > jedem Start des Programms anders, oder ist sie immer gleich? Dynamisch. Die Frage hättest Du Dir mit Hilfe des Taskmanagers (oder Konsole & tasklist) aber auch leicht selbst beantworten können.
Daniel M. schrieb: > ich habe nur was gefunden, wie > das unter Windows Forms geht) Vermutlich SendKeys? Einfach die System.Windows.Forms Referenz zum Projekt hinzufügen und man kann sie trotz WPF nutzen? http://msdn.microsoft.com/de-de/library/system.windows.forms.sendkeys.aspx
Windows + Echtzeitmaschinensteuerung = bäh. Gruß Jonas
adamzwerg schrieb: > Daniel M. schrieb: >> Ist die Prozess ID dynamisch, d.h. bei >> jedem Start des Programms anders, oder ist sie immer gleich? > > Dynamisch. Die Frage hättest Du Dir mit Hilfe des Taskmanagers (oder > Konsole & tasklist) aber auch leicht selbst beantworten können. Ja, das ist mir im Nachhinein auch aufgefallen. Sorry für die unnötige Frage. Habe mittlerweile auch mit der Funktion: "System.Diagnostics.Process.GetProcessesByName(Prozessname)[0].Id" die PID in meinem Programm einholen können. jo schrieb: > Windows + Echtzeitmaschinensteuerung = bäh. > > Gruß Jonas Das mag eine Ansicht von dir sein, die ich auch respektiere. Allerdings sind das Parameter, die ich nicht ändern kann und mit denen ich ein vorgegebenes Ziel erreichen muss. Von daher wäre ich über eine konstruktivere Antwort dankbar.
Ich habe es jetzt geschafft mit folgenden Code einen Tastendruck zu simulieren:
1 | /// <summary>
|
2 | /// Interaktionslogik für MainWindow.xaml
|
3 | /// </summary>
|
4 | public partial class MainWindow : Window |
5 | {
|
6 | // Konstruktor für das Fenster
|
7 | public MainWindow() |
8 | {
|
9 | InitializeComponent(); |
10 | }
|
11 | // Eventhandler für das Event "Taste nach unten gedrückt"
|
12 | private void OnKeyDownHandler(object sender, KeyEventArgs e) |
13 | {
|
14 | // Wenn die gedrückte (simulierte) Taste die F5-Taste ist...
|
15 | if (e.Key == Key.F5) |
16 | {
|
17 | //... Infotext in der Textbox "textBox1" ausgeben
|
18 | textBox1.Text = "F5-Tastendruck wurde simuliert"; |
19 | }
|
20 | }
|
21 | // Eventhandler für das Event "button1 wurde geklickt"
|
22 | private void button1_Click(object sender, RoutedEventArgs e) |
23 | {
|
24 | KeyEventArgs args = new KeyEventArgs(Keyboard.PrimaryDevice, |
25 | |
26 | Keyboard.PrimaryDevice.ActiveSource, 0, Key.F5); |
27 | |
28 | args.RoutedEvent = Keyboard.KeyDownEvent; |
29 | |
30 | InputManager.Current.ProcessInput(args); |
31 | }
|
32 | }
|
Auch kann ich die Process-ID, an welches Programm der Tastendruck gesendet werden soll, mittels der im vorigen Beitrag genannten Funktion ermitteln. Jetzt stehe ich allerdings vor dem Problem, wie ich diesen Tastendruck an das Programm weiterleiten kann.
So wird das nicht gehen. Einfachste Möglichkeit die ich sehe, ist sowas wie https://www.autoitscript.com/site/autoit/ Gruß Jonas
Wenn müsstest du das handle von dem anderen Fenster(deines Programms) irgendwie bekommen um darauf mouseevents zu feiern... nur mal so noch Gruß Jonas
Dass das andere Programm versteckt im Hintergrund läuft, könnte ein Problem sein. Überhaupt ist das eine ziemlich unsaubere Methode, bei der die Details evtl. sogar von der Windows-Version abhängen. Es wäre sehr viel besser, wenn das CNC-Programm irgendeine Art von externer Steuerung zuließe (über Pipes, Sockets oder wie auch immer). Tipp: Probiere es erst einmal mit dem oben bereits genannten AutoIt (Send, ControlSend). Wenn du damit etwas erreichst, sollte es auch mit einem eigenen Programm klappen; wenn nicht, sieht es vermutlich eher schlecht aus.
Ich habe jetzt folgenden Code zum Testen geschrieben, der bis auf einen Kleinigkeit auch soweit funktioniert. Der Prozess "Notepad" wird in den Vordergrund geholt (dieser wurde zuvor gestartet) und auch wird ein F5-Tastendruck simuliert (der entsprechende Handler wird aufgerufen). Nur leider wird das Event nicht an den Prozess "Notepad" weitergeleitet. Wie kann das sein? Hier der Code:
1 | private void button1_Click(object sender, |
2 | RoutedEventArgs eventhandlerDelegate) |
3 | {
|
4 | // F5-Tastendruck simulieren
|
5 | KeyEventArgs args = new KeyEventArgs(Keyboard.PrimaryDevice, |
6 | Keyboard.PrimaryDevice.ActiveSource, |
7 | 0, |
8 | Key.F5); |
9 | // Event zuordnen
|
10 | args.RoutedEvent = Keyboard.KeyDownEvent; |
11 | //
|
12 | InputManager.Current.ProcessInput(args); |
13 | // Prozess in den Vordergrund holen (als Beispiel Notepad)
|
14 | SetForegroundWindow(Process.GetProcessesByName("notepad")[0].MainWindowHandle); |
15 | }
|
Daniel M. schrieb: > Ich habe jetzt folgenden Code zum Testen geschrieben, der bis auf > einen Kleinigkeit auch soweit funktioniert. Der funktioniert eigentlich überhaupt nicht ... Du rufst ProcessInput (BTW: das bedeutet nicht "Sende etwas an Prozess xyz") auf und bringst dann das Fenster in den Vordergrund. Aber selbst mit dem entsprechenden Fenster im Vordergrund klappt es so nicht. > Wie kann das sein? Das liegt daran, dass du einen Denkfehler machst: > Der Prozess "Notepad" wird in den Vordergrund geholt Nein, das Fenster wird in den Vordergrund geholt. > Nur leider wird das Event nicht an den Prozess "Notepad" weitergeleitet. An das Fenster. Lade mal das hier runter, wenn du willst: http://inputsimulator.codeplex.com/ bzw. installiere es direkt über die NuGet-Konsole in Visual Studio per Install-Package InputSimulator Dann sollte dein Notepad-Test ungefähr so funktionieren (Minimalbeispiel, alles in die Fenster-Klasse gepackt):
1 | public partial class MainWindow : Window |
2 | { |
3 | public MainWindow() |
4 | { |
5 | InitializeComponent(); |
6 | _keysim = new KeyboardSimulator(new InputSimulator()); |
7 | } |
8 | |
9 | [DllImport("user32.dll")] |
10 | static extern bool SetForegroundWindow(IntPtr hWnd); |
11 | |
12 | [DllImport("user32.dll")] |
13 | private static extern IntPtr GetForegroundWindow(); |
14 | |
15 | private void OnSend(object sender, RoutedEventArgs e) |
16 | { |
17 | if(ActivateTargetWindow("notepad")) |
18 | { |
19 | _keysim.KeyPress(VirtualKeyCode.F5); |
20 | } |
21 | } |
22 | |
23 | private static bool ActivateTargetWindow(string procName) |
24 | { |
25 | var proc = Process.GetProcessesByName(procName); |
26 | if(proc.Length == 0) return false; |
27 | |
28 | var windowHandle = proc[0].MainWindowHandle; |
29 | SetForegroundWindow(windowHandle); |
30 | |
31 | const int maxTries = 10; |
32 | const int delay = 20; |
33 | int curTry = 0; |
34 | bool targetIsForeground; |
35 | do |
36 | { |
37 | Thread.Sleep(delay); |
38 | targetIsForeground = GetForegroundWindow() == windowHandle; |
39 | curTry++; |
40 | } while(!targetIsForeground && curTry < maxTries); |
41 | |
42 | return targetIsForeground; |
43 | } |
44 | |
45 | private readonly KeyboardSimulator _keysim; |
46 | } |
Dir ist sicher klar, dass dir das - auch wenn es funktioniert - bei deinem versteckten Hintergrundfenster kaum weiter hilft. Darum mein Hinweis auf AutoIt und ControlSend (zum Testen, ob das Ganze überhaupt funktioniert, nicht als Ersatz für dein C#-Programm).
adamzwerg schrieb: > Lade mal das hier runter, wenn du willst: > http://inputsimulator.codeplex.com/ > bzw. installiere es direkt über die NuGet-Konsole in Visual Studio per > Install-Package InputSimulator Danke für die Antwort. Das Programm habe ich jetzt runter geladen. Aber ich verstehe nicht, wie ich das benutzen kann. Ich finde nirgends ein Menüpunkt mit Namen "Install-Package" im Visual Studio. Wie kann ich das Programm nutzen?
Na das gibst du in der Console ein: "Install-Package InputSimulator" dann wird es installiert. Eventuell musst du dann noch die passenden Usings in deinem Program einbauen. Gruß Jonas
jo schrieb: > Na das gibst du in der Console ein: > > "Install-Package InputSimulator" > > dann wird es installiert. Eventuell musst du dann noch die passenden > Usings in deinem Program einbauen. > > Gruß Jonas Ich habe aber keine Consolenanwendung...
Du kannst auch rechte Maustaste auf dein Projekt im "Solution Explorer"
und dann "Manage NuGet Packages" und dort nach InputSimulator suchen.
(Die nuget-Konsole kann ansonsten via "Tools" > "NuGet-Package Manager"
> "Package Manager Console" eingeblendet werden)
>Ich habe aber keine Consolenanwendung...
Eh, du hast eher kein Plan. Ich rede von einer Console (hier die nuget
console) die man über Visual-Studio aufrufen um anschließend damit
komfortabel neue Packete für die Integration in eigene Projekte
installieren kann.
Gruß Jonas
bluppdidupp schrieb: > Du kannst auch rechte Maustaste auf dein Projekt im "Solution Explorer" > und dann "Manage NuGet Packages" und dort nach InputSimulator suchen. > (Die nuget-Konsole kann ansonsten via "Tools" > "NuGet-Package Manager" >> "Package Manager Console" eingeblendet werden) "Tools" gibt es leider bei meiner Version nicht und auch im Solutionexplorer gibt es keinen Eintrag mit "Manage NuGet Packages". Wie heißt das denn bei der deutschen VS-Version?
:
Bearbeitet durch User
Daniel M. schrieb: > "Tools" gibt es leider bei meiner Version nicht und auch im > Solutionexplorer gibt es keinen Eintrag mit "Manage NuGet Packages". Ist auch erst in den neuern Visual Studio Versionen (2013?) enthalten.
Daniel M. schrieb: > Wie heißt das denn bei der deutschen VS-Version? Ganz ehrlich: laß es einfach. Gärtnern ist doch ein schönes Hobby. Töpfern. Vielleicht auch Minigolf?
Gustav schrieb: > Daniel M. schrieb: >> Wie heißt das denn bei der deutschen VS-Version? > > Ganz ehrlich: laß es einfach. > > Gärtnern ist doch ein schönes Hobby. Töpfern. Vielleicht auch Minigolf? Es geht hier ja nicht ums Hobby, sondern um eine Problemstellung innerhalb einer Abschlussarbeit. Von daher kein hilfreicher Ratschlag
Du hast recht. Es gibt doch auch andere schöne Abschlußarbeiten. Im Ausbildungsberuf Gärtner, Keramikmeister oder Spitzensportler. :-)
Gustav schrieb: > Du hast recht. > > Es gibt doch auch andere schöne Abschlußarbeiten. Im Ausbildungsberuf > Gärtner, Keramikmeister oder Spitzensportler. :-) Du scheinst das nicht ganz zu verstehen. Es geht hier um eine elektrotechnische/ informationstechnische Problemstellung. Und es geht auch nicht um eine Ausbildung sondern ein Studium. Und da ich fast fertig bin, kommt ein Wechsel der Fachrichtung auch nicht in Frage.
Leg dir lieber erstmal einen vernünftigen Ironiedetektor zu...
Boris P. schrieb: > Ist auch erst in den neuern Visual Studio Versionen (2013?) enthalten. Ich meine ab 2012 und auch in Express-Editions. Daniel M. schrieb: > "Tools" gibt es leider bei meiner Version nicht und auch im > Solutionexplorer gibt es keinen Eintrag mit "Manage NuGet Packages". Tools heisst dort meine ich "Extras", aber der Begriff "NuGet" sollte einem an zig Stellen über den Weg laufen, wenn man drauf achtet. Welches VS-Version ist denn installiert?
Ich habe das Problem jetzt erfolgreich gelöst: Mit der Funktion EnumWindos() zuerst sämtliche Prozesse einholen, diese dann nach Titel und Klassennamen filtern. Die Klasse "Process" ist dafür nicht geeigent, da diese nur die MainHandles zurückgibt und das in meinem Fall nicht ausreichend war. Anschließend das gesuchte Handle des Fensters ermitteln und an dieses mit der Funktion PostMessage() einen simulierten Tastendruck senden. Vielen Dank für die zahlreichen Antworten, auch wenn einer hier nicht ganz verstanden hat, worum es eigendlich ging :)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.