Entwickler-Ecke
Sonstiges (.NET) - Frage zu MouseHooks MouseMove, MouseUp und MouseDown
markusmayer123 - Fr 23.02.18 00:15
Titel: Frage zu MouseHooks MouseMove, MouseUp und MouseDown
Hallo,
ich bin neu in dem Forum und entschuldige mich vorab, wenn ich in einer falschen Sektion poste:D
Ich beschäftige mich aktuell mit folgender Bibliothek:
https://archive.codeplex.com/?p=keyboardmousehooks
Hierbei stehe ich vor folgendem Problem:
Ich würde gerne eine Schleife programmieren, welche solange ich die linke Maustaste gedrückt halte,
eine einfache Konsolenausgabe ausgibt.
Die folgende While-Schleife funktioniert natürlich nicht:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| private void MouseHook_LeftButtonUp(RamGecTools.MouseHook.MSLLHOOKSTRUCT mouseStruct) { gedrückt = false; }
private void MouseHook_LeftButtonDown(RamGecTools.MouseHook.MSLLHOOKSTRUCT mouseStruct) { gedrückt = true; }
public void MouseMoved(object sender, MouseEventArgs e) { while(gedrückt == true) { Console.Writeline("abc"); } } |
Moderiert von Th69: C#-Tags hinzugefügtModeriert von Th69: Topic aus C# - Die Sprache verschoben am Fr 23.02.2018 um 09:10
Delete - Fr 23.02.18 00:56
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Fr 23.02.18 01:07
Hi, vielen Dank für deine Antwort.
Ja, du meinst vermutlich das hier:
C#-Quelltext
1: 2: 3:
| mouseHook.LeftButtonDown += new RamGecTools.MouseHook.MouseHookCallback(MouseHook_LeftButtonDown); mouseHook.LeftButtonUp += new RamGecTools.MouseHook.MouseHookCallback(MouseHook_LeftButtonUp); mouseHook.Install(); |
Das habe ich in
Form1_Load geschrieben.
Ich könnte also mit
GetAsyncKeyState() einfach direkt abfragen, ob die Taste aktuell gedrückt wird und sobald sie losgelassen wird, aus der Schleife springen?
LG
Moderiert von Th69: C#-Tags hinzugefügt
Moderiert von Th69: Vollzitat entfernt
Delete - Fr 23.02.18 01:25
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Fr 23.02.18 12:37
Also die Ausgabe an sich funktioniert ja wunderbar.
Ich würde nur gerne ausgeben, während die linke Maustaste gedrückt ist. Sobald die nicht mehr gedrückt wird, wird ein Wert auf False gesetzt und die Ausgabe wird gestoppt.
Leider hat das mit While-Schleife nicht wirklich funktioniert.
Moderiert von Th69: Vollzitat entfernt.
Delete - Fr 23.02.18 13:25
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Fr 23.02.18 13:40
Verzeihung, ich habe mich nicht klar ausgedrückt.
Das hier zum Beispiel funktioniert mit der Konsolenausgabe wunderbar. Allerdings nur einmalig bei einem Linksklick.
Jetzt will ich es irgendwie schaffen im MouseMoved Block eine Schleife zu schreiben, die solange eine Konsolenausgabe wie z.B.
Console.WriteLine("taste wird gedrückt"); ausgibt, solange die linke Maustaste gedrückt gehalten wird.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| private void MouseHook_LeftButtonUp(RamGecTools.MouseHook.MSLLHOOKSTRUCT mouseStruct) { gedrückt = false; }
private void MouseHook_LeftButtonDown(RamGecTools.MouseHook.MSLLHOOKSTRUCT mouseStruct) { gedrückt = true; } public void MouseMoved(object sender, MouseEventArgs e) { if (gedrückt == true) { Console.WriteLine("taste wird gedrückt"); } } |
Moderiert von Th69: Vollzitat entfernt.
Moderiert von Th69: C#-Tags hinzugefügt
Delete - Fr 23.02.18 13:58
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Fr 23.02.18 14:22
-Ich habe mir überlegt im MouseMoved Block eine While-Schleife einzubauen, um zu überprüfen, ob die Linke Maustaste noch immer gedrückt ist und wenn ja, dass eine Konsolenausgabe erfolgt, solange der Wert true ist. Dafür habe ich den Wert "gedrückt" als boolean deklariert und setzte sie mit mouseup/mousedown auf false/true.
-Das Ereignis MouseMoved soll später dafür verwendet werden, um den Cursor zu einem bestimmten Punkt zu bewegen, während die Linke Maustaste gedrückt wird.
Zum Beispiel soll das Ereignis das hier ausführen:
Allerdings nicht die ganze Zeit, sondern wirklich nur während die Maustaste gedrückt wird.
C#-Quelltext
1: 2: 3: 4: 5:
| while(gedrückt == true) { Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 15); System.Threading.Thread.Sleep(25); } |
-Ich benötige die MouseHook-Klasse, damit ich außerhalb der Form prüfen kann, ob eine Maustaste gedrückt wird.
-Das Konsolenfenster habe ich nur als Testmittel genutzt. Ich wollte dadurch schauen, ob ich solange ich die linke Maustaste gedrückt halte eine Konsolenausgabe machen kann.
Ich hoffe ich konnte deine Fragen einigermaßen beantworten.
Vielen Dank für deine Hilfe!
LG
Moderiert von Th69: Vollzitat entfernt.
Ralf Jansen - Fr 23.02.18 14:33
Zitat: |
Ich benötige die MouseHook-Klasse, damit ich außerhalb der Form prüfen kann, ob eine Maustaste gedrückt wird. |
Dir ist aber bewußt das der MouseMove Event den du scheinbar benutzt nur dann feuert wenn das Control an dem du den Event verdrahtet hast auch das Control ist über dem sich der Mouse Cursor gerade befindet?
markusmayer123 - Fr 23.02.18 14:54
Hi, erstmal Danke für deine Antwort.
Sorry hätte vielleicht noch hinzufügen sollen, dass MouseMoved ebenfalls von einer MouseHook-Klasse verwendet wird.
Hier wird die Methode MouseMoved registriert in der Main()
C#-Quelltext
1:
| actHook.OnMouseActivity += new MouseEventHandler(MouseMoved); |
Moderiert von Th69: Vollzitat entfernt.
Th69 - Fr 23.02.18 14:56
Für wiederholende Aufgaben benutze einen Timer (ansonsten blockierst du mit der Schleife alle weiteren UI- bzw. MouseHook-Aktivitäten).
PS: Bitte keine ganzen Beiträge zitieren.
Ralf Jansen - Fr 23.02.18 16:41
Zitat: |
Sorry hätte vielleicht noch hinzufügen sollen, dass MouseMoved ebenfalls von einer MouseHook-Klasse verwendet wird. |
Meine Nase sagt mir das da was stinkt ;)
Ich bezweifle das der Move Event eine winformstypische Sender,EventArgs-Signatur hat die anderen Events der Klasse aber mit einem eigenen struct arbeiten.
Das klingt total sinnfrei da die interna bei den Hooks die gleichen sind. Da macht mann die Eventsignaturen nicht einfach so unterschiedlich.
markusmayer123 - Fr 23.02.18 16:55
Th69 hat folgendes geschrieben : |
Für wiederholende Aufgaben benutze einen Timer (ansonsten blockierst du mit der Schleife alle weiteren UI- bzw. MouseHook-Aktivitäten). |
Hi, vielen Dank für deine Antwort.
Ich werde es mal versuchen.
Ralf Jansen hat folgendes geschrieben : |
Ich bezweifle das der Move Event eine winformstypische Sender,EventArgs-Signatur hat die anderen Events der Klasse aber mit einem eigenen struct arbeiten.
Das klingt total sinnfrei da die interna bei den Hooks die gleichen sind. Da macht mann die Eventsignaturen nicht einfach so unterschiedlich. |
Ich hatte 2 verschiedene Klassen, da ich zuerst einmal eine andere benutzt habe und dann dort festgestellt habe, dass die kein MouseUp/MouseDown implementiert hatten. Daraufhin benutzte ich für MouseDown/MouseUp eine neue Klasse und behielt die alte Klasse für MouseMove.
Hab das jetzt mal geändert, damit es nicht für Verwirrung sorgt.
C#-Quelltext
1:
| mouseHook.MouseMove += new RamGecTools.MouseHook.MouseHookCallback(mouseHook_MouseMove); |
C#-Quelltext
1: 2: 3: 4: 5: 6: 7:
| void mouseHook_MouseMove(RamGecTools.MouseHook.MSLLHOOKSTRUCT mouseStruct) { if (gedrückt == true) { Console.WriteLine("taste wird gedrückt"); } } |
Delete - Fr 23.02.18 21:21
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Fr 23.02.18 22:40
Frühlingsrolle hat folgendes geschrieben : |
Es funktioniert schon, wie es soll:
|
Vielen Dank!
Hast du eine Idee, wie ich das hier umsetzen könnte?
Wenn _pressed = true und ich eben keine Mausbewegung mache? Also die MouseMoved Funktion ganz weglasse?
C#-Quelltext
1: 2:
| Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 15); System.Threading.Thread.Sleep(25); |
Das soll immer wieder aufgerufen werden, solange die linke Maustaste gedrückt gehalten wird.
LG
Delete - Fr 23.02.18 23:35
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Sa 24.02.18 13:23
Cool, vielen Dank! Es funktioniert wunderbar mit dem Timer :)
Eine kleine Frage noch:
Wenn ich jetzt beispielsweise im Timer Block den Befehl
C#-Quelltext
1:
| Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 15); |
mit verschiedenen Y Koordinaten also zum Beispiel
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| private void timer1_Tick(object sender, EventArgs e) { Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 15); Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 21); Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 22); Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 22); Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 24); } |
Das hier ausführen will, aber nicht direkt nacheinander, sondern mit einer Art
Thread.Sleep dazwischen, wie kann ich das elegant lösen in dem Fall?
Es sollen später ca. 30 solcher Befehle nacheinander folgen.
LG
Moderiert von Th69: C#-Tags hinzugefügt
Moderiert von Th69: Zitat entfernt.
Delete - Sa 24.02.18 15:00
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Sa 24.02.18 16:38
Hi, danke.
Aber ist es möglich, dass die Anweisungen nicht direkt nacheinander aufgerufen werden? Also ein Sleep dazwischen einzubauen?
Gibt es da möglicherweiße eine Funktion die man über den Timer aufrufen kann?
Sorry bin noch ganz neu in C# :D
LG
Moderiert von Narses: Komplettzitat des letzten Beitrags entfernt.
Delete - Sa 24.02.18 18:32
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Sa 24.02.18 18:51
Frühlingsrolle hat folgendes geschrieben : |
Weiss nicht, was du meinst. :gruebel: Aufrufe erfolgen nunmal nacheinander.
Wenn du Thread.Sleep() ständig aufrufst, dann blockst du in dieser Zeit den Haupt-Thread, also deine Anwendung per se. D.h. du kannst in dieser Zeit das Fenster der Anwendung nicht bedienen.
Mit dem Timer kannst du nebenbei, während er arbeitet, die Hauptanwendung bedienen. Wie regelmäßig der Timer etwas ausführt, hängt von seiner gesetzten .Intervall-Eigenschaft (in Millisekundnen) ab.
|
Ja genau, die erfolgen genau nacheinander und dazwischen suche ich was, um einen kurzen delay zwischen den Aufrufen zu haben:D
Schau mal, ich versuche mit C# ein AutoHotKey Ablauf nachzubilden, dieser sieht wie folgt aus:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| if GetKeyState(key_pressed) {
if s { loop { DllCall("mouse_event", uint, 2, int, 0, int, 0, uint, 0, int, 0) sleep 92 if !GetKeyState(key_pressed) { DllCall("mouse_event", uint, 4, int, 0, int, 0, uint, 0, int, 0) break } DllCall("mouse_event", "UInt", 0x01, "UInt", 0*modifier, "UInt", 25*modifier) sleep 92 if !GetKeyState(key_pressed) { DllCall("mouse_event", uint, 4, int, 0, int, 0, uint, 0, int, 0) break } DllCall("mouse_event", "UInt", 0x01, "UInt", 0*modifier, "UInt", 25*modifier) sleep 92 if !GetKeyState(key_pressed) { DllCall("mouse_event", uint, 4, int, 0, int, 0, uint, 0, int, 0) break } DllCall("mouse_event", "UInt", 0x01, "UInt", 0*modifier, "UInt", 25*modifier) sleep 92 if !GetKeyState(key_pressed) { DllCall("mouse_event", uint, 4, int, 0, int, 0, uint, 0, int, 0) break } DllCall("mouse_event", "UInt", 0x01, "UInt", 0*modifier, "UInt", 22*modifier) sleep 92 |
Hier ist im AutoHotKey Script auch eine Art Sleep drinne.
Das versuche ich auch in C# umzusetzen.
Ist das überhaupt möglich?
Moderiert von Th69: Code-Tags hinzugefügt
Delete - Sa 24.02.18 19:07
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - Sa 24.02.18 19:26
Frühlingsrolle hat folgendes geschrieben : |
Ja, das ist möglich, und hier muss auch sleep() aufgerufen werden, damit die Befehle die nötige Zeit haben, ausgeführt werden zu können. Wo ist nun das Problem? |
Okay, ja mit
Thread.Sleep(92); hängt ja das ganze Programm:D
markusmayer123 - Sa 24.02.18 19:54
Dankeschön, ich schau es mir an:)
Th69 hat folgendes geschrieben : |
Warum bleibst du nicht bei AutoHotKey? |
Da ich sehr eingeschränkte Möglichekeiten mit AHK habe. Leider.
LG
markusmayer123 - So 25.02.18 01:11
Guten Abend zusammen!
Ich habe mal folgendes ausprobiert mit einem Async Timer:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
| private async void timer2_TickAsync(object sender, EventArgs e) {
if (_pressed == true) {
Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 21); await Task.Delay(92); } if (_pressed == true) { Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 21); await Task.Delay(92); }
if (_pressed == true) { Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 21); await Task.Delay(92); } if (_pressed == true) { Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 21); await Task.Delay(92);
}
if (_pressed == true) {
Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + 18); await Task.Delay(92);
} if (_pressed == true) { Cursor.Position = new Point(Cursor.Position.X -11, Cursor.Position.Y + 16); await Task.Delay(92);
} if (_pressed == true) {
Cursor.Position = new Point(Cursor.Position.X - 11, Cursor.Position.Y + 19); await Task.Delay(92); } } |
Das funktioniert soweit auch, allerdings geht der Cursor nur Y nach unten und ignoriert die X Werte:D
Hat jemand eine Idee, woran das liegen könnte? Habe jetzt sämtliches erfolglos ausprobiert.
LG
Delete - So 25.02.18 20:01
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - So 25.02.18 20:50
Guten Abend!
Erstmal vielen herzlichen Dank für deine Hilfe! :)
Ich bin deinen geposteten Code durchgegangen und habe mir die Links die du gepostet hast, angeschaut.
Mir ist leider nicht ganz klar, wie der Code jetzt ausführbar ist:D
Wenn ich jetzt annehmen würde, der Modifier hätte den Wert 1 und ich würde die Linke Maustaste drücken wollen, müsste ich doch dann in Form1_Load das hier schreiben, um den Code ausführen zu können:
C#-Quelltext
1:
| DoAutoHotKey(0x01, 1); |
PS: Tut mir leid für die dummen Fragen:P
Edit2:
C#-Quelltext
1:
| DoAutoHotKey(0x01, 1); |
Das hier kommt glaub ich in einen Timer und
Timer1.Enabled = true;
in form1_load
LG
Delete - So 25.02.18 22:33
- Nachträglich durch die Entwickler-Ecke gelöscht -
markusmayer123 - So 25.02.18 23:04
Frühlingsrolle hat folgendes geschrieben : |
Gute Frage. Wo wird es denn im AutoHotKey ausgeführt? Ich hätte es wohl in einem MouseDown oder KeyDown Ereignis ausgeführt.
Solltest du es im Timer ausführen, dann muss aber die while-Schleife verschwinden, ansonsten hängt sich die Anwendung noch auf. |
Das wird auch innerhalb einer Loop ausgeführt.
Okay, ich teste ein wenig herum.
Vielen Dank nochmal!
Edit: Also ohne Timer schaffe ich es garnicht,
DoAutoHotkey(); auszuführen.
LG
Markus
Delete - So 25.02.18 23:23
- Nachträglich durch die Entwickler-Ecke gelöscht -
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!