Von den Grundlagen zur Mittelstufe: Umgang von Mausereignissen
Einführung
Im vorigen Artikel „ Von der Grundstufe zur Mittelstufe: Funktionszeiger“ haben wir besprochen, wie man Ereignisse in einem Skript implementiert. Aber zuallererst haben wir erklärt, wie ein spezieller Datentyp verwendet werden kann: der Zeiger, den wir bereits kennen. Da der vorangegangene Artikel wichtiges Grundlagenmaterial enthält – insbesondere für jeden, der plant, sich eingehender mit grafischer Programmierung zu befassen –, empfehle ich dringend, ihn sorgfältig durchzugehen. In diesem Artikel werden wir uns jedoch auf ein anderes und einfacheres Thema konzentrieren.
Das Hauptthema hier ist die Mausinteraktion und mausbezogene Ereignisse. Um alles logisch getrennt zu halten, beginnen wir mit dem ersten Thema dieses Artikels.
Mausereignisse
Beginnen wir also damit, folgenden Punkt zu verstehen: Die Maus ist ein albernes, nerviges, schreckliches Ding, das scheinbar aus den tiefsten Abgründen der Hölle gekrochen ist. Sie verhält sich auf scheinbar zufällige Weise, ohne die Funktionsweise des Codes oder die eigenen Einschränkungen des Programmierers zu berücksichtigen. Obwohl MetaTrader 5 sehr nützlich ist und eine beachtliche Flexibilität bietet, generiert er standardmäßig keine Mausereignisse für Anwendungen, die in einem Chartfenster ausgeführt werden. Aber warum? Der Grund dafür ist, dass MetaTrader 5 darauf ausgerichtet ist, exzellente Leistung und Effizienz zu bieten. Die Mausbehandlung wiederum kann sich negativ auf Leistung und Effizienz auswirken. Darüber hinaus sind Anwendungen auf Charts im Hinblick auf die Verarbeitung mausbezogener Ereignisse meist schlecht optimiert.
Sie haben vielleicht keine klare Vorstellung davon, wie ernst Probleme der Mausereignisse werden können, wenn eine Anwendung schlecht für deren Handhabung optimiert ist. Wir werden dieses Thema jedoch in den folgenden Artikeln genauer untersuchen. Doch zunächst müssen wir einige andere Dinge verstehen.
Vielleicht haben Sie bereits begonnen, über das erste davon nachzudenken: „Nun, lieber Autor, Sie irren sich bezüglich der Verwendung der Maus auf dieser Plattform. Wenn wir mit der rechten Maustaste auf den Chart klicken, erhalten wir Zugriff auf eine Reihe von Elementen, die dort direkt genutzt werden können. Darüber hinaus können wir Aufträge mithilfe der One-Click-Trading-Funktion in MetaTrader 5 senden und verarbeiten. Daher ist Ihre Behauptung, dass die Maus ein Problem darstellt, einfach ein Zeichen für einen Mangel an Wissen Ihrerseits.“
In Ordnung, ich stimme Ihnen zu. Sie haben mit dieser Aussage absolut recht, liebe Leser. Ich habe jedoch nicht gesagt, dass die Maus ein Problem für diese Plattform ist. Ich sagte, dass die Maus Probleme für auf dem Chart laufende Anwendungen bereiten kann. Besonders dann, wenn der Ereignishandler dieser Anwendung schlecht optimiert ist. Oder zumindest extrem unorganisiert. Und je länger der Code, desto größer das Chaos. Aus diesem Grund achte ich immer darauf, relativ kurzen Code zu erstellen, und suche vor allem nach Einfachheit. Und genau deshalb: Ich möchte vermeiden, aufgrund meiner eigenen Nachlässigkeit schlecht optimierten Code zu erstellen.
Der nächste Punkt: Da MetaTrader 5 standardmäßig keine Mausereignisse für Anwendungen generiert, die an einen Chart angehängt sind, müssen wir Code schreiben, der MetaTrader 5 mitteilt, dass der Chart Mausereignisse empfangen soll. Wenn wir MetaTrader 5 per Code anweisen, Mausereignisse an den Chart zu senden, müssen wir beim Schließen der Anwendung auch dafür sorgen, dass diese Ereignisse wieder deaktiviert werden, wenn die Anwendung geschlossen wird.
Leider geschieht dies in den meisten Fällen nicht, was dazu führt, dass MetaTrader 5 weiterhin Mausereignisse für den Chart generiert, da die Anwendung das, was sie zuvor aktiviert hatte, nicht deaktiviert hat. Seien Sie also vorsichtig und organisiert. Wenn Sie etwas eingeschaltet haben, dann schalten Sie es wieder aus. Sie sollten nicht erwarten, dass die Plattform selbst einen Weg findet, das Problem zu lösen.
Der nächste Punkt: Versuchen Sie nicht, mehr Ressourcen als nötig zu aktivieren oder zu verwenden. Es gibt kleine Unterschiede zwischen den Ereignissen, die von MetaTrader 5 generiert werden, wenn Mausereignisse ausgelöst werden. Wenn die Anwendung bestimmte Ereignisfunktionen nicht benötigt, sollten diese nicht aktiviert werden. Alles sollte einfach und unkompliziert sein. Aktivieren Sie nur das, was wirklich notwendig ist.
Diese kurze Einführung mag zwar etwas hart erscheinen, erfordert jedoch tatsächlich eine klare Erklärung, damit ein Entwickler, der mit dem Programmieren beginnt, die Anfangsphase seiner Arbeit richtig aufbauen kann. Ich habe viele Leute gesehen, die mehr als nötig tun und sich dann beschweren, dass das Programm nicht wie erwartet funktioniert.
Wenn wir innehalten und betrachten, was geschieht, werden wir feststellen, dass das Problem darin liegt, dass zu viele Steuerelemente unnötigerweise aktiviert sind. Wenn die überflüssigen Komponenten entfernt werden, stellt die Anwendung das erwartete Leistungsniveau wieder her. Und dies gilt nicht unbedingt nur für Programme für MetaTrader 5; es geht um diese Praxis im Allgemeinen.
Beginnen wir also mit der Tatsache, dass Mausereignisse nur im OnChartEvent-Handler empfangen und verarbeitet werden können. Daher können nur zwei Arten von Anwendungen Mausereignisse empfangen und verarbeiten. Eine davon ist ein Expert Advisor, über den wir später sprechen werden. Die zweite ist ein Indikator. Aber alles, was hier gesagt wurde, gilt auch für einen Expert Advisor, da alle Daten an OnChartEvent gesendet werden. Es ist wichtig, dies zu verstehen, liebe Leser, damit Sie keine Fragen haben wie: „Wow, Sie haben erklärt, wie man mit der Maus in einem Indikator arbeitet. Allerdings haben Sie nie erklärt, wie man dies in einem Expert Advisor macht.“
Alles beginnt mit dem unten gezeigten Code.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #define def_Prefix "Demo" 05. //+------------------------------------------------------------------+ 06. int OnInit() 07. { 08. IndicatorSetString(INDICATOR_SHORTNAME, def_Prefix); 09. 10. return INIT_SUCCEEDED; 11. }; 12. //+------------------------------------------------------------------+ 13. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 14. { 15. return rates_total; 16. }; 17. //+------------------------------------------------------------------+ 18. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) 19. { 20. switch (id) 21. { 22. case CHARTEVENT_MOUSE_MOVE: 23. break; 24. case CHARTEVENT_MOUSE_WHEEL: 25. break; 26. } 27. }; 28. //+------------------------------------------------------------------+ 29. void OnDeinit(const int reason) 30. { 31. }; 32. //+------------------------------------------------------------------+
Code 01
Hier haben wir das, was man als Grundgerüst eines Indikators bezeichnen kann, der in seiner Funktionsweise die Maus verwendet. Bitte beachten Sie Folgendes: In OnChartEvent können zwei Arten von Mausereignissen erfasst werden. Das erste Beispiel befindet sich in Zeile 22 und das zweite in Zeile 24. Die Verwendung des einen oder anderen Ereignisses hat keinen Einfluss auf die Ausführung oder Kompilierung des Codes. In seiner jetzigen Form generiert MetaTrader 5 jedoch keines dieser beiden Ereignisse. Dies liegt daran, dass beide Ereignistypen standardmäßig deaktiviert sind. Damit OnChartEvent eines dieser beiden Ereignisse empfangen kann, müssen wir genau den Ereignistyp aktivieren, den wir empfangen möchten.
Das Aktivieren und Deaktivieren dieser Ereignisse ist ein äußerst einfaches und leicht zu implementierendes Verfahren. Der Ansatz zur Lösung solcher Situationen ist jedoch etwas anders. Aus irgendeinem Grund funktioniert das Ereignis CHARTEVENT_MOUSE_WHEEL etwas anders als das Ereignis CHARTEVENT_MOUSE_MOVE. Aber machen Sie sich darüber jetzt keine Sorgen; Sie werden bald alles verstehen und in der Lage sein, die Maus in immer mehr Anwendungen und auf unterschiedliche Weise zu nutzen. Der Punkt ist, dass dieses Werkzeug bei korrekter Programmierung äußerst nützlich und vielseitig ist, insbesondere auf einer grafischen Plattform.
Um die Maus in Aktion beobachten zu können und somit verschiedene andere Aspekte zu verstehen, die bei einer Visualisierung der Prozesse leichter wahrnehmbar werden, aktivieren wir eines der Mausereignisse und geben gleichzeitig bestimmte Informationen direkt im Chart aus. Auf diese Weise werden wir in der Praxis lernen, wie es tatsächlich funktioniert. Dazu ändern wir Code 01 und machen ihn zu Code 02, der unten dargestellt ist.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #define def_Prefix "Demo" 05. //+------------------------------------------------------------------+ 06. int OnInit() 07. { 08. IndicatorSetString(INDICATOR_SHORTNAME, def_Prefix); 09. ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true); 10. 11. return INIT_SUCCEEDED; 12. }; 13. //+------------------------------------------------------------------+ 14. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 15. { 16. return rates_total; 17. }; 18. //+------------------------------------------------------------------+ 19. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) 20. { 21. string sz = ""; 22. 23. switch (id) 24. { 25. case CHARTEVENT_MOUSE_MOVE: 26. Comment(sz); 27. sz += "Mouse position X: " + (string)(short)lparam; 28. sz += "\nMouse position Y: " + (string)(short)dparam; 29. Comment(sz); 30. break; 31. case CHARTEVENT_MOUSE_WHEEL: 32. break; 33. } 34. }; 35. //+------------------------------------------------------------------+ 36. void OnDeinit(const int reason) 37. { 38. Comment(""); 39. ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, false); 40. }; 41. //+------------------------------------------------------------------+
Code 02
Wenn Code 02 auf dem Chart ausgeführt wird, sehen wir ein Ergebnis, das dem in der folgenden Animation gezeigten ähnelt.

Animation 01
Bitte beachten Sie, dass sich die Positionsanzeige in der oberen linken Ecke ändert, während sich die Maus bewegt. Es gibt jedoch Bereiche, in denen sich die Anzeige nicht ändert. Warum? Der Grund dafür ist, dass die Bereiche, in denen sich die Positionsanzeige nicht ändert, außerhalb des Clientbereichs liegen.
Und ja, das Chartfenster ist in Bereiche unterteilt. Solche Aspekte werden beim Studium der Programmierung für grafische Umgebungen berücksichtigt, zum Beispiel bei der Entwicklung von Windows-Anwendungen. Dies ist ein Prozess, der viele Details umfasst. Ich werde jedoch versuchen, die Erklärung so weit wie möglich zu vereinfachen. Auf diese Weise können Sie verstehen, was bei der MQL5-Programmierung wirklich wichtig ist.
In einer grafischen Benutzeroberfläche, zum Beispiel im Betriebssystem Windows, gibt es einen riesigen Bereich, der Desktop genannt wird, oder, für Nicht-Fachleute, Bildschirmbereich. Jedes Pixel in diesem Bereich entspricht einer Position im sogenannten Desktop-Bereich. Dieser Bereich kann zunächst in zwei weitere Bereiche unterteilt werden. Ein Bereich ist der Ort, an dem sich die Taskleiste befindet, und der andere ist der Bereich, in dem Anwendungsfenster platziert werden. Es spielt keine Rolle, ob die aktuellen Einstellungen den Bereich ausblenden, der der Taskleiste entspricht. Alles, was nicht von der Taskleiste belegt ist, gilt als Bereich für Anwendungsfenster.
Betrachten Sie zur Verdeutlichung das folgende Beispiel: Angenommen, es wird ein Bildschirm mit einer Auflösung von 1920 x 1080 Pixeln verwendet, also ein Full-HD-Bildschirm. Wenn der Taskleistenbereich 48 Pixel belegt, beträgt der nutzbare Bereich Ihres Bildschirms 1920 x 1032 Pixel. Daher kann jede Anwendung, die sich in einem maximierten Fenster befindet, während die Taskleiste angezeigt wird, die zuvor genannten Abmessungen einnehmen, also weniger als die Full-HD-Bildschirmauflösung. Der Effekt ist kaum wahrnehmbar. Als Hinweis sei jedoch angemerkt, dass bei der Anzeige eines Bildes von 1920 x 1080 Pixeln auf einem etwas kleineren Bildschirm die Darstellung leicht abweicht, da die fehlenden 48 Pixel kompensiert werden müssen.
Innerhalb dieses Clientbereichs, der normalerweise als vierter Quadrant konfiguriert ist (dieses Thema wird später im Detail untersucht), können also Programmfenster platziert werden. Dieses Fenster ist ebenfalls in Abschnitte unterteilt. In der Praxis gibt es drei Hauptbereiche, die zu berücksichtigen sind. Der erste Bereich ist die Titelleiste, der zweite ist der Fensterrahmen und der dritte ist der Clientbereich.
Wie auf dem Desktop wird der nutzbare Platz kleiner, da jeder Bereich außerhalb des Clientbereichs den für die Anwendung verfügbaren Platz reduziert. Mauskoordinaten werden nur innerhalb dieses Clientbereichs gemeldet und reichen von 0 x 0 in der oberen linken Ecke bis zu den Maximalwerten in der unteren rechten Ecke. Dies gilt bei der Standarddarstellung des Charts, die sich im vierten Quadranten befindet.
Sobald Sie den Mauszeiger außerhalb des Clientbereichs des MetaTrader 5-Chartfensters bewegen, werden daher keine Mausereignisse mehr für dieses Fenster generiert. Es gibt eine Möglichkeit, dies zu vermeiden und Mausereignisse weiterhin zu empfangen, selbst wenn sich der Cursor außerhalb des Clientbereichs des Chartfensters bewegt, in dem der Ereignishandler läuft. Aber das ist ein Thema für eine andere Diskussion. Wer weiß, vielleicht sehen wir uns in Zukunft an, wie das geht.
Daher ist dieser Teil am einfachsten und am leichtesten zu verstehen. Ein Detail: Die Position des Clientbereichs auf dem Bildschirm spielt keine Rolle. MetaTrader 5 ordnet Bildschirmpositionen kontinuierlich neu zu, sodass die Anwendung sie innerhalb ihres eigenen Koordinatenraums wahrnimmt – als würde sie den gesamten Bereich des Hauptbildschirms oder, mit anderen Worten, den Desktop verwenden.
Durch die automatische Durchführung dieser Koordinatenneuzuordnung reduziert MetaTrader 5 den erforderlichen Arbeitsaufwand erheblich. Dies ist Arbeit, die in einer anderen Programmierumgebung als MQL5 möglicherweise manuell erledigt werden müsste. Dies eliminiert eine Situation, in der die Anwendung fälschlicherweise interpretiert, Ereignisse zu empfangen, obwohl sie eigentlich nicht darauf reagieren sollte.
Ich denke, das ist jetzt klar. Was ist mit den Maustasten? Wie bestimmen wir, wann eine bestimmte Maustaste gedrückt wurde? Die Zustände der Maustasten werden über eine Bitmaske ausgewertet. Am einfachsten verwendet man dafür ein Makro im Code. Dies vereinfacht die Planung und Filterung verschiedener Ereignisse, da wir ein Element anklicken und gleichzeitig ziehen können.
Bevor wir zu diesem Thema übergehen, beachten Sie, dass wir in Zeile 09 des Codes 02 das Mausereignis aktiviert haben. In Zeile 39 haben wir es jedoch wieder deaktiviert. Und da die Informationen in verschiedenen Datenformaten vorliegen, müssen wir diese Daten konvertieren, damit sie Werte anzeigen, die unseren Erwartungen entsprechen. Deshalb verwenden wir explizite Typumwandlung, wie in den Zeilen 27 und 28 zu sehen ist. Das ist ganz einfach.
Maustasten
Das Thema Maustasten ist ein ziemlich kontroverses Thema, ebenso wie der Grund für diese Kontroverse. Einige Benutzer denken vielleicht, dass die Implementierung von mausbezogenen Funktionen recht einfach ist. In der Praxis ist jedoch alles etwas komplizierter, als es scheint. Auf den ersten Blick erscheint der Grund dafür etwas seltsam. In den meisten Anwendungen werden Maustasten verwendet, um bestimmte Funktionen auszuführen. Oder sogar vom Betriebssystem selbst. Im Fall von MetaTrader 5 ist die mittlere Maustaste für den Aufruf des standardmäßigen Fadenkreuz-Werkzeugs zuständig, das für Analysen verwendet wird. Die rechte Taste hingegen öffnet ein Menü für verschiedene Chart-Manipulationen und Einstellungen.
Unsere Anwendung muss diese Tasten jedoch möglicherweise für andere, ebenfalls spezifische Zwecke verwenden. Dies erzeugt einen Konflikt zwischen den Erwartungen des Benutzers und dem Standardverhalten von MetaTrader 5. Und in einigen Fällen kann auch das Betriebssystem in diesen Streit hineingezogen werden. Nun, was MetaTrader 5 betrifft, so hat er nichts dagegen, wenn wir als Programmierer diese Tasten vorübergehend für beliebige Zwecke und für einen bestimmten Zeitraum übernehmen. Es ist jedoch höchst unethisch, ihr Standardverhalten nicht wiederherzustellen, wenn die Anwendung aus dem Chart entfernt wurde. Es sei denn, sie stürzt ab. In diesem Fall ist es unmöglich.
Unsere Anwendung nimmt diese ausgeliehenen Maustasten gewissermaßen mit. Dies verhindert, dass der Benutzer während des angegebenen Zeitraums der Nutzung von MetaTrader 5 auf diesem speziellen Chart darauf zugreifen kann. Um den Betrieb der Maustasten wiederherzustellen, die unsere Anwendung verwendet, aber aufgrund einer Fehlfunktion nicht zurückgegeben hat, muss der Benutzer das Symbol-Chart schließen und erneut öffnen. Nur so kann MetaTrader 5 die Kontrolle über diese Maustasten zurückgewinnen. Daher sollten wir bei der Planung solcher Punkte vorsichtig sein. Andernfalls schaffen wir eine äußerst unangenehme Erfahrung für den Benutzer unserer Anwendung.
„In Ordnung, ich denke, wir haben das Problem behandelt. Aber wie wird das eigentlich gemacht? Wenn ich aus irgendeinem Grund die Kontrolle über die rechte und mittlere Taste übernehmen muss, was sollte ich tun? Und wie gibt man die Kontrolle über genau diese Maustasten am besten an MetaTrader 5 zurück?" Nun, das sind sehr gute Fragen, liebe Leser. Und da dies relevant ist, werden wir noch etwas anderes erklären, das ziemlich interessant ist. In den Artikeln, in denen wir über Tastaturereignisse gesprochen haben, haben wir die Tatsache nicht erwähnt, dass wir auch eine noch größere Kontrolle über die Tastatur erlangen können. Aber da wir die Kontrolle über die Maustasten sowie andere Elemente übernehmen werden, denke ich, dass dies eine gute Gelegenheit ist, zu zeigen, wie man Elemente der Benutzerinteraktion vollständig verwaltet. Dies geschieht mithilfe des folgenden Codes:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #define def_Prefix "Demo" 05. //+------------------------------------------------------------------+ 06. int OnInit() 07. { 08. IndicatorSetString(INDICATOR_SHORTNAME, def_Prefix); 09. ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true); 10. //+----------------+ 11. ChartSetInteger(0, CHART_MOUSE_SCROLL, false); 12. ChartSetInteger(0, CHART_CONTEXT_MENU, false); 13. ChartSetInteger(0, CHART_CROSSHAIR_TOOL, false); 14. //+----------------+ 15. ChartSetInteger(0, CHART_KEYBOARD_CONTROL, false); 16. ChartSetInteger(0, CHART_QUICK_NAVIGATION, false); 17. //+----------------+ 18. 19. return INIT_SUCCEEDED; 20. }; 21. //+------------------------------------------------------------------+ 22. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 23. { 24. return rates_total; 25. }; 26. //+------------------------------------------------------------------+ 27. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) 28. { 29. string sz = ""; 30. 31. switch (id) 32. { 33. case CHARTEVENT_MOUSE_MOVE: 34. Comment(sz); 35. sz += "Mouse position X: " + (string)(short)lparam; 36. sz += "\nMouse position Y: " + (string)(short)dparam; 37. Comment(sz); 38. break; 39. case CHARTEVENT_MOUSE_WHEEL: 40. break; 41. } 42. }; 43. //+------------------------------------------------------------------+ 44. void OnDeinit(const int reason) 45. { 46. Comment(""); 47. ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, false); 48. //+----------------+ 49. ChartSetInteger(0, CHART_MOUSE_SCROLL, true); 50. ChartSetInteger(0, CHART_CONTEXT_MENU, true); 51. ChartSetInteger(0, CHART_CROSSHAIR_TOOL, true); 52. //+----------------+ 53. ChartSetInteger(0, CHART_KEYBOARD_CONTROL, true); 54. ChartSetInteger(0, CHART_QUICK_NAVIGATION, true); 55. //+----------------+ 56. }; 57. //+------------------------------------------------------------------+
Code 03
Während seiner Ausführung blockiert dieser Code 03 die Verwendung von Standard-MetaTrader 5-Elementen und -Steuerelementen, wie zum Beispiel das Standard-Fadenkreuz-Werkzeug oder sogar die Möglichkeit, die EINGABETASTE zu drücken, um das aktuelle Chart-Symbol zu ändern. Sehen wir uns also an, wie wir das erreicht haben: Zuerst teilen wir MetaTrader 5 in Zeile 11 mit, dass der Benutzer das Chart nicht mehr ziehen kann, um Bars anzuzeigen, die nicht sichtbar sind. Um dieses Standardverhalten von MetaTrader 5 wieder zu aktivieren, verwenden wir Zeile 49.
In Zeile 12 deaktivieren wir das Kontextmenü des Charts, auf dem der Code ausgeführt wird. Dieses Menü wird durch Drücken der rechten Maustaste geöffnet. Um diese Standardfunktion von MetaTrader 5 wieder zu aktivieren, verwenden wir Zeile 50. In Zeile 13 deaktivieren wir das Standard-Fadenkreuz-Werkzeug, das durch Drücken der mittleren Maustaste aufgerufen wird. Um diese Funktion wieder zu aktivieren, verwenden wir Zeile 51.
Nun, in Zeile 15, deaktivieren wir die Steuerelemente für das Scrollen und Zoomen mit der Tastatur. Um sie wieder zu aktivieren, verwenden wir Zeile 53. Und schließlich deaktivieren wir in Zeile 16 die Funktion, die es dem Benutzer ermöglicht, die EINGABETASTE zu drücken und den Namen eines Symbols oder Zeitrahmens einzugeben. Um dieselbe Funktion wieder zu aktivieren, verwenden wir Zeile 54.
Diese Art von Code ist leichter zu verstehen, wenn Sie ihn direkt verwenden und den Chart vor und während der Ausführung dieses Codes 03 testen. In der beigefügten Datei finden Sie den gezeigten Code, und ich sehe keinen einfacheren Weg, den Lernprozess für den Umgang mit solchen Ereignissen zu erleichtern. Nur durch Experimentieren und Beobachten des Ergebnisses können Sie verstehen, wie man solche kleinen Probleme löst. Ich sage das, weil Sie diese Optionen jederzeit aktivieren und deaktivieren können. Es kann interessant sein, sie zu bestimmten Zeiten zu aktivieren und zu anderen Zeiten zu deaktivieren. Auf jeden Fall demonstrieren wir sie hier lediglich, um alles so lehrreich wie möglich zu gestalten.
Nun können wir uns auf ein umfassenderes Thema konzentrieren, nämlich die Maustasten. Aber wir werden auch die Tastatur hinzufügen. Dies wird es uns ermöglichen, das gesamte System wesentlich umfassender zu testen. Dies geschieht mithilfe des folgenden Codes:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #define def_Prefix "Demo" 05. //+------------------------------------------------------------------+ 06. int OnInit() 07. { 08. IndicatorSetString(INDICATOR_SHORTNAME, def_Prefix); 09. ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true); 10. //+----------------+ 11. ChartSetInteger(0, CHART_MOUSE_SCROLL, false); 12. ChartSetInteger(0, CHART_CONTEXT_MENU, false); 13. ChartSetInteger(0, CHART_CROSSHAIR_TOOL, false); 14. //+----------------+ 15. ChartSetInteger(0, CHART_KEYBOARD_CONTROL, false); 16. ChartSetInteger(0, CHART_QUICK_NAVIGATION, false); 17. //+----------------+ 18. 19. return INIT_SUCCEEDED; 20. }; 21. //+------------------------------------------------------------------+ 22. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 23. { 24. return rates_total; 25. }; 26. //+------------------------------------------------------------------+ 27. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) 28. { 29. string sz = ""; 30. 31. switch (id) 32. { 33. case CHARTEVENT_KEYDOWN: 34. Comment(sz); 35. sz += "Key press: " + (string)lparam; 36. Comment(sz); 37. break; 38. case CHARTEVENT_MOUSE_MOVE: 39. Comment(sz); 40. sz += "Mouse position X: " + (string)(short)lparam; 41. sz += "\nMouse position Y: " + (string)(short)dparam; 42. sz += StringFormat("\nHexadecimal mask of mouse buttons is: 0x%02X", (uchar)sparam); 43. Comment(sz); 44. break; 45. case CHARTEVENT_MOUSE_WHEEL: 46. break; 47. } 48. }; 49. //+------------------------------------------------------------------+ 50. void OnDeinit(const int reason) 51. { 52. Comment(""); 53. ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, false); 54. //+----------------+ 55. ChartSetInteger(0, CHART_MOUSE_SCROLL, true); 56. ChartSetInteger(0, CHART_CONTEXT_MENU, true); 57. ChartSetInteger(0, CHART_CROSSHAIR_TOOL, true); 58. //+----------------+ 59. ChartSetInteger(0, CHART_KEYBOARD_CONTROL, true); 60. ChartSetInteger(0, CHART_QUICK_NAVIGATION, true); 61. //+----------------+ 62. }; 63. //+------------------------------------------------------------------+
Code 04
Da Code 04, wie auch Code 03, für viele Anfänger belastend oder verwirrend sein kann, werden wir uns zuerst ansehen, wie man ihn beendet oder vom Chart entfernt. Sie werden dies nicht auf die gleiche Weise machen können, wie Sie es wahrscheinlich von anderen Indikatoren gewohnt sind. Um den obigen Code zu stoppen, der diese Standard-MetaTrader 5-Ressourcen vollständig blockiert, müssen wir auf das zugreifen, was in der folgenden Abbildung gezeigt wird.

Bild 01
Wenn wir die in Abbildung 01 in MetaTrader 5 gezeigte Option auswählen, wenn der Indikator mit vollständiger Blockierung aktiv ist, können wir auf diese Liste zugreifen. Wenn es sich um einen Expert Advisor handelt, müssen wir auf die Liste der Expert Advisors zugreifen. Danach greifen wir auf die Liste der Indikatoren oder Expert Advisors zu, die im Chart angezeigt oder auf der Plattform geöffnet sind. Auf diese Weise können wir sie aus dem Chart entfernen. Andernfalls wäre dies unmöglich. Der Punkt ist, dass wir den Zugriff des Benutzers auf alle Standardfunktionen von MetaTrader 5 vollständig blockieren.
Nachdem dies nun alles erklärt wurde, wollen wir sehen, was Code 04 bewirkt.

Animation 02
Es ist wichtig, dass Sie auf Folgendes achten: Animation 02 dient ausschließlich dazu, zu demonstrieren, wie MQL5 Maus- und Tastaturaktionen interpretiert. Es ist äußerst wichtig, den Indikator, den wir in Code 04 sehen, zu testen, um zu verstehen, was eine Kombination aus Maustasten und Tastatur bewirken kann. Das liegt daran, dass manche Dinge recht schwer zu erklären sind, egal wie einfach sie erscheinen mögen. Idealerweise sollten wir dies in der Praxis ausprobieren und verstehen, wie diese Elemente kombiniert werden können.
Wenn Sie sich jedoch die Kombination aus Maustasten und Tastatur ansehen, werden Sie feststellen, dass Zeile 42 des Codes 04 manchmal das eine und manchmal das andere Ergebnis anzeigt. Das erscheint seltsam. Dies geschieht jedoch, wenn die SHIFT- und/oder CTRL-Tasten gedrückt werden. Diese beiden Tasten haben eine interessante Eigenschaft. Wenn Sie diese drücken, ohne die Maus zu bewegen, werden Sie feststellen, dass das Ergebnis aus Zeile 35 erscheint.
Wenn Sie jedoch die Maus bewegen, ruft MetaTrader 5 ein Ereignis auf, das Zeile 42 aktiviert. Warum? Der Grund dafür ist, dass diese beiden Tasten, SHIFT und CTRL, mit der Maus verknüpft sind und Teil der Bitmaske sind. Wenn Sie dies verstehen, können Sie Dinge erstellen, die andernfalls viel schwieriger zu realisieren wären. Daher ist es sehr wichtig: Wenn Sie wirklich verstehen wollen, wie Maus und Tastatur in MQL5 funktionieren, müssen Sie die Ergebnisse aus Code 04 studieren.
Wir müssen jedoch noch über eine andere Art von Ereignis sprechen. Und zwar über den Ereignistyp, der in Zeile 45 des Codes 04 behandelt wird. Aber dieses Mausrad-Scroll-Ereignis ist, gelinde gesagt, ziemlich seltsam. Zumindest hier in MQL5. Es wird ausgelöst und gibt eine Datenstruktur zurück, die sich leicht von dem unterscheidet, was man erwarten könnte. Vielleicht wird es deshalb in Anwendungen, die in MQL5 geschrieben sind, nicht sehr oft verwendet.
Um dies zu verstehen, werden wir den notwendigen Code zum Ereignishandler hinzufügen, damit wir den Unterschied zwischen CHARTEVENT_MOUSE_MOVE und CHARTEVENT_MOUSE_WHEEL visualisieren können. Und glauben Sie mir, das ist in der Praxis wirklich sehr interessant zu beobachten. Daher ist der verwendete Code unten dargestellt.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #define def_Prefix "Demo" 05. //+------------------------------------------------------------------+ 06. int OnInit() 07. { 08. IndicatorSetString(INDICATOR_SHORTNAME, def_Prefix); 09. ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true); 10. ChartSetInteger(0, CHART_EVENT_MOUSE_WHEEL, true); 11. //+----------------+ 12. ChartSetInteger(0, CHART_MOUSE_SCROLL, false); 13. ChartSetInteger(0, CHART_CONTEXT_MENU, false); 14. ChartSetInteger(0, CHART_CROSSHAIR_TOOL, false); 15. //+----------------+ 16. ChartSetInteger(0, CHART_KEYBOARD_CONTROL, false); 17. ChartSetInteger(0, CHART_QUICK_NAVIGATION, false); 18. //+----------------+ 19. 20. return INIT_SUCCEEDED; 21. }; 22. //+------------------------------------------------------------------+ 23. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 24. { 25. return rates_total; 26. }; 27. //+------------------------------------------------------------------+ 28. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) 29. { 30. string sz = ""; 31. 32. switch (id) 33. { 34. case CHARTEVENT_KEYDOWN: 35. Comment(sz); 36. sz += "Key press: " + (string)lparam; 37. Comment(sz); 38. break; 39. case CHARTEVENT_MOUSE_MOVE: 40. Comment(sz); 41. sz += " **** Chart Event Mouse Move ****"; 42. sz += "\nMouse position X: " + (string)(short)lparam; 43. sz += "\nMouse position Y: " + (string)(short)dparam; 44. sz += StringFormat("\nHexadecimal mask of mouse buttons is: 0x%02X", (uchar)sparam); 45. Comment(sz); 46. break; 47. case CHARTEVENT_MOUSE_WHEEL: 48. Comment(sz); 49. sz += " **** Chart Event Mouse Wheel ****"; 50. sz += "\nMouse position X: " + (string)(short)lparam; 51. sz += "\nMouse position Y: " + (string)(short)(lparam >> 16); 52. sz += "\nMouse Delta: " + (string) dparam; 53. sz += StringFormat("\nHexadecimal mask of mouse buttons is: 0x%02X", (uchar)(lparam >> 32)); 54. Comment(sz); 55. break; 56. } 57. }; 58. //+------------------------------------------------------------------+ 59. void OnDeinit(const int reason) 60. { 61. Comment(""); 62. ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, false); 63. ChartSetInteger(0, CHART_EVENT_MOUSE_WHEEL, false); 64. //+----------------+ 65. ChartSetInteger(0, CHART_MOUSE_SCROLL, true); 66. ChartSetInteger(0, CHART_CONTEXT_MENU, true); 67. ChartSetInteger(0, CHART_CROSSHAIR_TOOL, true); 68. //+----------------+ 69. ChartSetInteger(0, CHART_KEYBOARD_CONTROL, true); 70. ChartSetInteger(0, CHART_QUICK_NAVIGATION, true); 71. //+----------------+ 72. }; 73. //+------------------------------------------------------------------+
Code 05
Und hier ist er, lieber Leser. Code 05 vervollständigt das, was ich in diesem Artikel zeigen wollte. Bitte beachten Sie, dass wir hier keinerlei Manipulationen zur Arbeit mit der Maus oder Tastatur verwenden. Wir verwenden einen klaren und einfachen Ansatz, damit Sie leicht verstehen können, was passiert. Mit Code 05 werden Sie in der Lage sein, etwas Ähnliches zu sehen, wie in der folgenden Animation dargestellt.

Animation 03
Beachten Sie, dass es praktisch keinen Unterschied zwischen Code 04 und Code 05 gibt. Aber dieser kleine Unterschied bedeutet, dass die beiden Codes völlig unterschiedliche Zwecke haben. In Zeile 10 von Code 05 aktivieren wir das Ereignis für den Empfang jeder Mausradbewegung, die vom Benutzer ausgeführt wird. Ebenso haben wir in Zeile 63 den Empfang genau dieser Ereignisse deaktiviert. Ich möchte Sie jedoch auf das aufmerksam machen, was in dem Ereignishandler angezeigt wird. Denn hier finden wir einen grundlegenden Unterschied.
Bitte beachten Sie, dass der Handler für CHARTEVENT_MOUSE_WHEEL dem Handler für CHARTEVENT_MOUSE_MOVE sehr ähnlich ist. Achten Sie darauf, woher diese Werte stammen. Die Platzierung der Positionswerte und die Werte der gedrückten Maustasten ist in den beiden Fällen unterschiedlich. Aber hier wird der Unterschied erst richtig gewaltig. WIR ERHALTEN DAS EREIGNIS CHARTEVENT_MOUSE_WHEEL NUR DANN, wenn ein Ereignis eintritt, während das Mausrad gedreht wird. Abgesehen davon werden alle anderen Mausereignisse an das Ereignis CHARTEVENT_MOUSE_MOVE weitergeleitet. Deshalb trifft man so selten auf Anwendungen oder Code, die das Ereignis CHARTEVENT_MOUSE_WHEEL verwenden. Dies liegt daran, dass wir keine Aktualisierungen über andere Mausstatus erhalten, wie z. B. Bewegungen oder Maustastendrücke, es sei denn, es tritt ein Ereignis am Mausrad auf.
Wie bereits erwähnt, ist die Maus also ein großartiger Verbündeter. Je nachdem, was wir implementieren wollen, kann sie jedoch auch direkt aus den Tiefen der Hölle stammen.
Abschließende Überlegungen
Vielleicht war dieser Artikel bis zu diesem Punkt einer von denen, bei denen das bloße Studium des Codes eindeutig nicht ausreicht, um zu verstehen, was passiert. Tatsächlich ist es notwendig, eine ausführbare Anwendung zu erstellen und diese auf einem beliebigen Chart auszuführen. Dies geschieht, damit Sie kleine Details verstehen können, die ansonsten überaus schwer zu erfassen wären, wie etwa die gleichzeitige Verwendung von Tastatur und Maus zur Erstellung bestimmter Elemente.
Wenn Sie verstehen, wie eine solche Kombination entstehen kann, werden Sie sicherlich verstehen, warum bei manchem Code der CHARTEVENT_KEYDOWN-Handler nicht aktiviert werden muss, um zu prüfen, ob die SHIFT- und CTRL-Tasten gedrückt sind. Sie können auch Kombinationen der Maustasten selbst erstellen, um weitaus komplexere und individuell angepasste Werkzeuge zu entwickeln.
In der beigefügten Datei finden Sie die Codes, die wir hier untersucht haben. Versuchen Sie daher, das Ergebnis zu untersuchen, das jeder der Codes auf dem Chart erzeugt. Experimentieren Sie mit Kombinationen aus Mausbewegungen, Maustasten- und Tastatureingaben, um Prinzipien zu erfassen, die in der Theorie völlig mühsam erscheinen, sich in der Praxis jedoch sehr interessant und gut nachvollziehbar sind.
| MQL5-Datei | Beschreibung |
|---|---|
| Code 01 | Maus-Demo |
Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/16000
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Marktsimulation (Teil 23): Positionsansicht (I)
Marktsimulation: Erste Schritte mit SQL in MQL5 (IV)
Neuronale Netze im Trading: Actor–Director–Critic (Letzter Teil)
Neuronale Netze im Trading: Akteur–Direktor–Kritiker
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.