![Grafische Interfaces X: Updates für die Easy And Fast Bibliothek (Build 2)](https://c.mql5.com/i/articles/overlay.png)
Grafische Interfaces X: Updates für die Easy And Fast Bibliothek (Build 2)
Inhalt
Einleitung
Der erste Artikel Grafisches Interface I: Vorbereiten der Bibliotheksstruktur (Kapitel 1) Beschreibt im Detail wofür diese Bibliothek gedacht ist. Am Ende von jedem Kapitel, finden Sie eine vollständige Liste mit Links zu diesem Artikel. Zudem finden Sie dort eine Möglichkeit das Projekt, entsprechend dem aktuellen Entwicklungszustand, herunterzuladen. Die Dateien müssen in den gleichen Verzeichnissen untergebracht werden, so, wie Sie auch in dem Archiv abgelegt sind.
Seit der Veröffentlichung des vorangegangenen Artikels dieser Serie, hat die Easy And Fast Bibliothek einige neue Features bekommen. Die Bibliotheksstruktur und der Programmcode wurden teilweise optimiert, was die CPU-Auslastung leicht reduziert hat. Einige wiederkehrende Methoden in vielen Control-Klassen wurden in die CElement Basisklasse bewegt. Zudem wurden einige kleinere visuelle Verbesserungen und Fehlerbehebungen durchgeführt. Lassen Sie uns diese im Detail anschauen.
Updates
1. Veränderung des standardmäßigen Farbschemas. Dieses Farbschema besteht nun meistens aus hellen Farbtönen das dem Charthintergrund entspricht. Die Verwendung des standardmäßigen Farbschemas erlaubt es nun, dass nur eine minimale Menge von Eigenschaften angegeben werden muss, wenn man Methoden für die Erzeugung der Controls in einer benutzerdefinierten Klasse entwickelt.
Die folgenden Screenshots zeigen Beispiele einer MQL Anwendung mit dem grafischen Interface auf einem hellen und einem dunklen Hintergrund.
Abbildung 1. Einige grafische Interfaces mit dem Standard-Farbschema auf hellem Hintergrund
Abbildung 2. Einige grafische Interfaces mit dem Standard-Farbschema auf dunklem Hintergrund
2. Implementierung der ersten Version der CMouse Klasse für das Abspeichern der Maus- und der Mauszeiger-Parameter. Lassen Sie uns dieses genauer ansehen.
Die CMouse Klasse finden Sie in der Mouse.mqh Datei die sich in dem Ordner für alle Bibliotheksdateien befindet: “<terminal directlory>\MQLX\Include\EasyAndFastGUI\Controls ”. Hier benötigen wir die CChart Klassen-Instanz der Standard-Bibliothek. Aus dieser Klasse wird die CChart::SubwindowY() Methode dazu verwendet, die Y Koordinate relativ zu dem Unterfenster, in welchem sich der Mauszeiger zurzeit befindet, zu berechnen. Die Verbindung zu den Chart Wird in den Konstruktor der Klasse durchgeführt, während Das abkoppeln in dem Destruktor stattfindet.
Die CChart Klasse ist von hier aus für alle grundlegenden Bibliotheks-Klassen erreichbar. Hierfür wurden die notwendigen Änderungen implementiert.
//+---------------------------------------------------------------- //| Mouse.mqh | //| Copyright 2016, MetaQuotes Software Corp. | //| http://www.mql5.com | //+---------------------------------------------------------------- #include <Charts\Chart.mqh> //+---------------------------------------------------------------- //| Klasse für die Abfrage der Maus-Parameter | //+---------------------------------------------------------------- class CMouse { private: //--- Klassen-Instanz für die Verwaltung des Charts CChart m_chart; //--- public: CMouse(void); ~CMouse(void); }; //+---------------------------------------------------------------- //| Konstruktor | //+---------------------------------------------------------------- CMouse::CMouse(void) { //--- Abfrage der aktuellen Chart ID m_chart.Attach(); } //+---------------------------------------------------------------- //| Destruktor | //+---------------------------------------------------------------- CMouse::~CMouse(void) { //--- Abkoppeln vom Chart m_chart.Detach(); }
Die Liste der Maus- und Mauszeiger-Parameter, die in fast allen Klassen verwendet werden kann, wird nachfolgend gezeigt.
- Die aktuellen Koordinaten des Mauszeigers
- Die Nummer des Unterfensters, die zur Zeit dem Mauszeiger zugeordnet ist
- Die Zeit entsprechend der X Koordinate auf dem Chart.
- Den Wert entsprechend der Y Koordinate auf dem Chart.
- Status der linken Maustaste (gedrückt/nicht gedrückt)
Die relevanten Variablen auch Methoden für das Abspeichern und Abfragen der Parameter sind in der CMouse Klasse implementiert:
class CMouse { private: //--- Koordinaten int m_x; int m_y; //--- Nummer des Fensters, in welchem sich der Mauszeiger befindet int m_subwin; //--- Die Zeit entsprechend der x-Koordinate datetime m_time; //--- Der Wert entsprechend der y-Koordinate double m_level; //--- Status der linken Maustaste (gedrückt/nicht gedrückt) bool m_left_button_state; //--- public: //--- Rückgabe der Koordinaten int X(void) const { return(m_x); } int Y(void) const { return(m_y); } //--- Gibt die (1) Nummer des Fensters mit dem Mauszeiger zurück, (2) die Zeit entsprechend der x-Koordinate zurück, // (3) Den Wert entsprechend der y-Koordinate zurück int SubWindowNumber(void) const { return(m_subwin); } datetime Time(void) const { return(m_time); } double Level(void) const { return(m_level); } //--- Status der linken Maustaste (gedrückt/nicht gedrückt) bool LeftButtonState(void) const { return(m_left_button_state); } };
Natürlich benötigen wir den Eventhandler für das Nachverfolgen des Auftretens des CHARTEVENT_MOUSE_MOVE Events. Die CMouse Klassenvariablen, werden in dem Abschnitt der Event-Bearbeitung gefüllt. Wir haben diesen Programmcode in allen Control Event-Handlern bereits gesehen. Nun ist dieser Code nur in der CMouse Klasse vorhanden, was den Programmcode der Control Klassen intuitiver gestalten lässt. Außerdem werden jetzt die Maus- und Mauszeiger-Parameter nur noch einmal innerhalb der ganzen Elemente abgefragt, was natürlich die CPU Auslastung verringert.
class CMouse { //--- Eventhandler void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); }; //+---------------------------------------------------------------- //| Eventhandler für die Bewegung des Mauszeigers | //+---------------------------------------------------------------- void CMouse::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Eventhandler für die Bewegung des Mauszeigers if(id==CHARTEVENT_MOUSE_MOVE) { //--- Linke Maustaste, Koordinaten und Status m_x =(int)lparam; m_y =(int)dparam; m_left_button_state =(bool)int(sparam); //--- Abfrage der Position des Mauszeigers if(!::ChartXYToTimePrice(0,m_x,m_y,m_subwin,m_time,m_level)) return; //--- Abfrage der relativen y-Koordinate if(m_subwin>0) m_y=m_y-m_chart.SubwindowY(m_subwin); } }
Die CMouse Klassen-Instanz wird in der Basisklasse der Bibliotheks-Engine deklariert (CWndContainer):
//+---------------------------------------------------------------- //| Klasse für das Abspeichern der Interface-Objekte | //+---------------------------------------------------------------- class CWndContainer { protected: //--- Klassen-Instanz für die Abfrage der Maus-Parameter CMouse m_mouse; };
Die CMouse Klassen-Instanz wird auch in der CElement Basis-Control-Klasse für das Abspeichern des Pointers zu dem Objekt von diesen Typ deklariert, was wiederum in der CWndContainer Klasse deklariert wird. Außerdem befinden sich hier die Methoden für das Abspeichern und Abfragen der Pointer.
//+---------------------------------------------------------------- //| Base control class | //+---------------------------------------------------------------- class CElement# { protected: //--- Klassen-Instanz für die Abfrage der Maus-Parameter CMouse *m_mouse; //--- public: //--- (1) abspeichern und (2) Rückgabe des Maus-Pointers void MousePointer(CMouse &object) { m_mouse=::GetPointer(object); } CMouse *MousePointer(void) const { return(::GetPointer(m_mouse)); } };
Der Pointer zu dem CMouse Objekt Wird automatisch allen Controls übergeben, wenn das grafische Interface erzeugt wird. Dafür muss das CMouse Objekt der CWndContainer::AddToObjectsArray() Methode übergeben werden, wo alle Pointer von allen grafischen Objekten der Controls zu dem gemeinsamen Array gesendet werden. Dieses wird in dem nachfolgenden Listing gezeigt.
//+---------------------------------------------------------------- //| Hinzufügen des Pointers zu den Control-Objekten in das gemeinsame Array | //+---------------------------------------------------------------- template<typename T> void CWndContainer::AddToObjectsArray(const int window_index,T &object) { int total=object.ObjectsElementTotal(); for(int i=0; i<total; i++) AddToArray(window_index,object.Object(i)); //--- Abspeichern des Mauszeigers in der Basis-Control-Klasse object.MousePointer(m_mouse); }
Nun hat jede Control-Klasse Zugriff auf die Maus- und Mauszeiger-Parameter, die in einem einzigen Objekt innerhalb der gesamten Bibliothek abgespeichert sind. Damit neue Werte in dem ChartEvent() Eventhandler der CWndEvents Klasse empfangen werden können, muss der CMouse Objekthandler aufgerufen werden und ihm alle aktuellen Parameter des Events übergeben werden. Da der Aufruf vor der Verarbeitung der Events innerhalb aller Controls durchgeführt wird, sind die relevanten Werte der Maus und des Mauszeigers in allen Controls verfügbar ohne die Typen wiederholt konvertieren, Werte zuweisen und die relative Y-Koordinate berechnen zu müssen.
//+---------------------------------------------------------------- //| Verarbeiten der Programm-Events | //+---------------------------------------------------------------- void CWndEvents::ChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Verlassen falls das Array leer ist //--- Initialisierung der Felder der Eventparameter //--- Abfrage der Maus-Parameter m_mouse.OnEvent(id,lparam,dparam,sparam); //--- Benutzerdefinierte Events //--- Überprüfung der Interface Control Events //--- Event für die Bewegung des Mauszeigers //--- Event bei Chartveränderungen }
Lassen Sie uns einen Auszug des CSimpleButton Control Code Handler als ein Beispiel verwenden. Das nachfolgende Listing zeigt eine Kurzfassung der CSimpleButton::OnEvent() Methode. Die in Gelb hervorgehobenen Zeilen enthalten den Aufruf der CMouse Objektmethoden für das Abfragen der (1) Nummer des Unterfensters, in welchem sich der Mauszeiger befindet, (2) die Koordinaten des Mauszeigers (3) und der Status der linken Maustaste.
//+---------------------------------------------------------------- //| Event handler | //+---------------------------------------------------------------- void CSimpleButton::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Verarbeiten des Events für die Bewegung des Mauszeigers if(id==CHARTEVENT_MOUSE_MOVE) { //--- Verlassen, falls das Control versteckt ist if(!CElement::IsVisible()) return; //--- Verlassen, falls das Formular gesperrt ist if(m_wnd.IsLocked()) return; //--- Essen, falls die Nummer des Unterfensters nicht stimmt if(CElement::m_subwin!=CElement::m_mouse.SubWindowNumber()) return; //--- Verlassen, falls der Button gesperrt ist if(!m_button_state) return; //--- Den Fokus definieren CElement::MouseFocus(CElement::m_mouse.X()>X() && CElement::m_mouse.X()<X2() && CElement::m_mouse.Y()>Y() && CElement::m_mouse.Y()<Y2()); //--- Verlassen, falls der Maus-Button nicht gedrückt ist if(!CElement::m_mouse.LeftButtonState()) return; //--- ... return; } //... }
Die entsprechenden Veränderungen wurden in allen Klassen der Bibliothek implementiert.
3. Früher wurden die Methoden für das Abfragen der Control ID und des Index der graphischen Objekte der Controls wiederholt in vielen Klassen der Bibliothek durchgeführt. Nun wurden diese Methoden in der CElement Basisklasse untergebracht, um Wiederholungen zu vermeiden.
//+---------------------------------------------------------------- //| Basis Control-Klasse | //+---------------------------------------------------------------- class CElement# { protected: //--- Abfrage der ID aus dem Namen des Buttons int IdFromObjectName(const string object_name); //--- Abfrage des Index aus dem Namen des Menüs int IndexFromObjectName(const string object_name); };
4. Hinzufügen von Methoden in der CWindow Klasse um den Button für das Maximieren und Minimieren des Fensters und der Positionierung des Text-Labels in der Kopfzeile zu aktivieren.
//+---------------------------------------------------------------- //| Klasse für die Erzeugung eines Formulars mit Controls | //+---------------------------------------------------------------- class CWindow : public CElement { private: //--- Einrückungen des Text tables der Kopfzeile int m_label_x_gap; int m_label_y_gap; //--- Darstellung des Buttons für das minimieren und maximieren des Fensters bool m_roll_button; //--- public: //--- Einrückungen des Text Labels void LabelXGap(const int x_gap) { m_label_x_gap=x_gap; } void LabelYGap(const int y_gap) { m_label_y_gap=y_gap; } //--- Verwendung des Tooltip-Buttons void UseRollButton(void) { m_roll_button=true; } };
5. Es wurde der CElement Klasse die Methode CheckWindowPointer() hinzugefügt, um die Anwesenheit eines Fenster pointers überprüfen zu können(CWindow). Senden Sie den Typ des Pointers dieser Methode unter Verwendung der CheckPointer() System-Methode zu, um die Korrektheit festzustellen. Zuvor wurde der selbe Code innerhalb der Erzeugung des Haupt-Controls in allen Control Klassen wiederholt. Die CElement::CheckWindowPointer() Methode vereinfacht nun diesen Prozess, reduziert die Menge an Programmcode und macht das System vielseitiger.
//+---------------------------------------------------------------- //| Base control class | //+---------------------------------------------------------------- class CElement# { protected: //--- Überprüfung ob der Pointer zu einem Formular existiert bool CheckWindowPointer(ENUM_POINTER_TYPE pointer_type); }; //+---------------------------------------------------------------- //| Überprüfung, ob der Pointer zu dem Formular existiert | //+---------------------------------------------------------------- bool CElement::CheckWindowPointer(ENUM_POINTER_TYPE pointer_type) { //--- Falls es keinen Pointer zu diesem Formular gibt if(pointer_type==POINTER_INVALID) { //--- Erzeuge eine Nachricht string message=__FUNCTION__+" > Before creating the control, the pointer to the form: "+ClassName()+"::WindowPointer(CWindow &object)" should be sent; //--- Sende diese Nachricht zu dem Terminal-Journal ::Print(message); //--- Unterbreche die Erzeugung des grafischen Interfaces return(false); } //--- Sende die Attribute für die Existenz des Pointers return(true); }
Nun können Sie ganz einfach die CElement::CheckWindowPointer() Methode für die Überprüfung der Existenz eines Pointers zu dem Formular, zu welchem das Control hinzugefügt werden soll durchführen, so wie es das nachfolgende Listing zeigt(Erzeugung eines einfachen Buttons in der CSimpleButton Klasse). Die entsprechenden Veränderungen wurden in allen Klassen der Bibliothek implementiert.
//+---------------------------------------------------------------- //| Erzeugung eines "einfacher Button" Controls | //+---------------------------------------------------------------- bool CSimpleButton::CreateSimpleButton(const long chart_id,const int subwin,const string button_text,const int x,const int y) { //--- Abbrechen, falls der Pointer zu dem Formular nicht existiert if(!CElement::CheckWindowPointer(::CheckPointer(m_wnd))) return(false); //--- Initialisiere die Variablen m_id =m_wnd.LastId()+1; m_chart_id =chart_id; m_subwin =subwin; m_x =x; m_y =y; m_button_text =button_text; //--- Abstände vom Eckpunkt CElement::XGap(m_x-m_wnd.X()); CElement::YGap(m_y-m_wnd.Y()); //--- Erzeugung des Buttons if(!CreateButton()) return(false); //--- Verstecke das Control, falls es sich bei dem Fenster um ein Dialogfenster handelt oder falls es minimiert ist if(m_wnd.WindowType()==W_DIALOG || m_wnd.IsMinimized()) Hide(); //--- return(true); }
6. Es wurde ein Modus für die automatische Veränderung der Breite eines Controls bei der Veränderung der Breite des Formulars, zu welchem das Control hinzugefügt wurde, der CElement Klasse hinzugefügt. Die CElement::AutoXResizeMode() Methode wird für die Festlegung des Modus verwendet. Bei der Verwendung des Modus, ist die rechte Ecke des Controls an die rechte Ecke des Formulars gebunden. Zudem wurde die CElement::AutoXResizeRightOffset() Methode für das Setzen und Abfragen der Einrückungen (in Pixeln) von der rechten Ecke des Formulars hinzugefügt.
//+---------------------------------------------------------------- //| Base control class | //+---------------------------------------------------------------- class CElement# { protected: //--- Modus für die automatisch Veränderung der Breite eines Controls bool m_auto_xresize_mode; //--- Einrückungen von der rechten Seite des Formulars bei dem automatischen Modus für die Veränderung der Breite eines Controls int m_auto_xresize_right_offset; //--- public: //--- (1) Modus für die automatische Veränderungen Controls, (2) Setzen/Abfragen der Einrückungen von der rechten Seite des Formulars bool AutoXResizeMode(void) const { return(m_auto_xresize_mode); } void AutoXResizeMode(const bool flag) { m_auto_xresize_mode=flag; } int AutoXResizeRightOffset(void) const { return(m_auto_xresize_right_offset); } void AutoXResizeRightOffset(const int offset) { m_auto_xresize_right_offset=offset; } };
Standardmäßig ist diese Funktion deaktiviert (false) und der Wert für die Einrückungen entspricht 0. Die Initialisierung wird in dem CElement Klassenkonstruktor durchgeführt (Sehen Sie sich dazu das nachfolgende Codebeispiel an):
//+---------------------------------------------------------------- //| Konstruktor | //+---------------------------------------------------------------- CElement::CElement(void) : m_auto_xresize_mode(false), m_auto_xresize_right_offset(0) { }
Zuvor wurde die CWindow::ChangeWindowWidth() Methode bereits in der CWindow Klasse für die Änderung der Breite des Formulars erzeugt. Jetzt, wenn der Modus aktiviert ist, wird die Breite des Formulars nur dann verändert, falls sich das grafische Interface in einem Indikator-Unterfenster befindet. Mit anderen Worten, wenn sich die Breite des Chartfensters verändert und es einen CHARTEVENT_CHART_CHANGE Event gibt, dann wird die Breite des Formulars verändert.
//--- Event bei der Veränderung des Charts if(id==CHARTEVENT_CHART_CHANGE) { //--- Wenn der die Taste losgelassen wird / nicht gedrückt ist if(m_clamping_area_mouse==NOT_PRESSED) { //--- Abfrage der Größe des Chart-Fensters SetWindowProperties(); //--- Korrektur der Koordinaten UpdateWindowXY(m_x,m_y); } //--- Verändere die Größe, falls der Modus aktiviert ist if(CElement::AutoXResizeMode()) ChangeWindowWidth(m_chart.WidthInPixels()-2); //--- return; }
Die folgende neue ID wurde der Bibliotheks-Event-ID-Liste hinzugefügt: ON_WINDOW_CHANGE_SIZE. Diese ID wird dazu verwendet, um das Event für die Veränderung der Größe des Formulars zu generieren
//+---------------------------------------------------------------- //| Defines.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+---------------------------------------------------------------- ... //--- Event IDs #define ON_WINDOW_CHANGE_SIZE (3) // Change the window size ...
Die Erzeugung einer solchen Nachricht wurde der CWindow::ChangeWindowWidth() Methode hinzugefügt. Die Kurzfassung des Verfahrens ist unten dargestellt:
//+---------------------------------------------------------------- //| Ändere die Breite des Fensters | //+---------------------------------------------------------------- void CWindow::ChangeWindowWidth(const int width) { //--- Abbrechen, falls sich die Breite nicht verändert hat //--- Aktualisiere die Breite der Kopfzeile und des Hintergrundes //--- Aktualisiere die Koordinaten und die Einrückungen für alle Buttons: // Close button //--- Maximieren button //--- Minimieren button //--- Der Tooltip Button (falls aktiviert) //--- Nachricht über die Veränderung der Größe des Fensters ::EventChartCustom(m_chart_id,ON_WINDOW_CHANGE_SIZE,(long)CElement::Id(),0,””); }
Diese Nachricht wird in der Bibliotheks-Engine (in der CWndEvents Klasse) verarbeitet. Es wurde die virtuelle ChangeWidthByRightWindowSide() Methode der CElement Basis Control Klasse hinzugefügt. Zudem wurden einige Implementationen von Methoden in vielen Ableitungen (wo die Breite des Controls verändert wird) geändert.
//+---------------------------------------------------------------- //| Basis Control-Klasse | //+---------------------------------------------------------------- class CElement# { public: //--- Verändere die Breite über die rechte Kante des Fensters virtual void ChangeWidthByRightWindowSide(void) {} };
Nachdem das ON_WINDOW_CHANGE_SIZE Event empfangen worden ist, Kann die Breite der controls, die den entsprechenden Modus aktiviert haben in der CWndEvents Klasse geändert werden. Die CWndEvents::OnWindowChangeSize() Methode wurde hierfür implementiert.
//+---------------------------------------------------------------- //| Klasse für das Verarbeiten von Events | //+---------------------------------------------------------------- class CWndEvents : public CWndContainer { private: //--- Verarbeitet das Event der Veränderung der Fenstergröße bool OnWindowChangeSize(void); }; //+---------------------------------------------------------------- //| ON_WINDOW_CHANGE_SIZE event | //+---------------------------------------------------------------- bool CWndEvents::OnWindowChangeSize(void) { //--- Im Falle eines "Change control size" Signals if(m_id!=CHARTEVENT_CUSTOM+ON_WINDOW_CHANGE_SIZE) return(false); //--- Index des aktiven Fensters int awi=m_active_window_index; //--- Falls die IDs übereinstimmen if(m_lparam!=m_windows[awi].Id()) return(true); //--- Verändere die Breite aller Controls, mit Ausnahme des Formulars int elements_total=CWndContainer::ElementsTotal(awi); for(int e=0; e<elements_total; e++) { if(m_wnd[awi].m_elements[e].ClassName()=="CWindow") continue; //--- if(m_wnd[awi].m_elements[e].AutoXResizeMode()) m_wnd[awi].m_elements[e].ChangeWidthByRightWindowSide(); } //--- return(true); }
Die Methode wird in der Hauptmethode der CWndEvents::ChartEventCustom() Bibliotheks-Events aufgerufen:
//+---------------------------------------------------------------- //| CHARTEVENT_CUSTOM event | //+---------------------------------------------------------------- void CWndEvents::ChartEventCustom(void) { //--- Signal zum minimieren des Formulars //--- Signal zum Maximieren des Formulars //--- Signal zur Veränderung der Größe if(OnWindowChangeSize()) return; //--- Signal für das Verstecken der Kontextmenüs vom Aufruferitem //--- Signal für das Verstecken aller Kontextmenüs //--- Signal zum Öffnen des Dialogfensters //--- Signal zum Schließen des Dialogfensters //--- Signal zum Zurücksetzen der Control-Farbe auf dem angegebenen Formular //--- Signal zum Zurücksetzen der Prioritäten der linken Maustaste //--- Signal zum Wiederherstellen der Prioritäten der linken Maustaste }
Aktuell ist die eindeutige ChangeWidthByRightWindowSide() Methode für die Veränderung der Breite eines Controls relativ zu der Breite des Formulars, zu welchem sie hinzugefügt worden sind, in den folgenden Klassen enthalten:
- CTabs – Einfache Tabs.
- CIconTabs – Tabs mit Bildern.
- CStatusBar – Statusbar.
- CMenuBar – Hauptmenü.
- CLabelsTable – Text-Label-Tabelle.
- CTable – Editbox-Tabelle
- CCanvasTable – Gerenderte Tabelle.
- CProgressBar – Fortschrittsanzeige.
- CTreeView – Baumansicht.
- CFileNavigator – Datai-Navigator.
- CLineGraph – Linienchart.
Der Programmcode für die Methode der CLabelsTable wird nachfolgend als Beispiel gezeigt.
//+---------------------------------------------------------------- //| Verändern der Breite über die rechte Ecke | //+---------------------------------------------------------------- void CLabelsTable::ChangeWidthByRightWindowSide(void) { //--- Koordinaten int x=0; //--- Größe int x_size=0; //--- Berechnung und Setzen der neuen Größe des Hintergrundes der Tabelle x_size=m_wnd.X2()-m_area.X()-m_auto_xresize_right_offset; CElement::XSize(x_size); m_area.XSize(x_size); m_area.X_Size(x_size); //--- Berechnen und Setzen der neuen Koordinate für die vertikale Scrollbar x=m_area.X2()-m_scrollv.ScrollWidth(); m_scrollv.XDistance(x); //--- Berechnen und Verändern der Breite der horizontalen Scrollbar x_size=CElement::XSize()-m_scrollh.ScrollWidth()+1; m_scrollh.ChangeXSize(x_size); //--- Aktualisierung der Positionen der Objekte Moving(m_wnd.X(),m_wnd.Y()); }
7. Es wurde die Möglichkeit hinzugefügt, die Tabs nach ihrer Erzeugung programmtechnisch auszuwählen Die SelectTab() Methode wurde hierfür in den CTabs und CIconTabs Klassen implementiert. Das nachfolgende Listing zeigt die Methode der CTabs Klasse als ein Beispiel:
//+---------------------------------------------------------------- //| Klasse für die Erzeugung von Tabs | //+---------------------------------------------------------------- class CTabs : public CElement { public: //--- Hervorheben des angegebenen Tabs void SelectTab(const int index); }; //+---------------------------------------------------------------- //| Hervorheben des angegebenen Tabs | //+---------------------------------------------------------------- void CTabs::SelectTab(const int index) { for(int i=0; i<m_tabs_total; i++) { //--- Falls das Tab selektiert ist if(index==i) { //--- Koordinaten int x=0; int y=0; //--- Größe int x_size=0; int y_size=0; //--- Abspeichern des hervorgehobenen Tab-Index SelectedTab(index); //--- Setzen der Farben m_tabs[i].Color(m_tab_text_color_selected); m_tabs[i].BackColor(m_tab_color_selected); //--- Berechnung relativ zu der Positionierung des Tab CalculatingPatch(x,y,x_size,y_size); //--- Aktualisierung des Wertes m_patch.X_Size(x_size); m_patch.Y_Size(y_size); m_patch.XGap(x-m_wnd.X()); m_patch.YGap(y-m_wnd.Y()); //--- Aktualisierung der Position der Objekte Moving(m_wnd.X(),m_wnd.Y()); } else { //--- Die Farben für nicht-aktive Tabs setzen m_tabs[i].Color(m_tab_text_color); m_tabs[i].BackColor(m_tab_color); } } //--- Zeige nur die Controls des hervorgehobenen Tabs ShowTabElements(); }
8. Es wurde die Möglichkeit hinzugefügt, die Auswahl einer Zeile in einer Entry-Box Tabelle wieder aufzuheben (CTable), indem man noch einmal auf sie Klickt.
9. Der String vom Format "column_row_text" wird in dem generierten Event als String Parameter (sparam) bei einem Klick auf eine Zelle der Tabelle (CTable), bei der der Edit-Modus deaktiviert ist, gesendet.
10. Es wurden Fehler bei der Enumeration und den Methoden für die Definition des Bereichs, in welchen mit der Maus geklickt wurde, behoben. Jetzt wird in allen Controls die ENUM_MOUSE_STATE Enumeration für das Nachverfolgen des Bereiches, in welchem mit der linken Maustaste geklickt wurde, verwendet.
11. Es wurden einige Dateinamen von Bildern, die innerhalb der Ressourcen in der Bibliothek verwendet wurden, geändert, da es Beschränkungen bei der Länge der Dateinamen bei Anwendungen vom Typ-"Indikator" gab.
12. Es wurden noch ein paar kleinere visuelle Verbesserungen und Fehlerbehebungen durchgeführt. Einige Fehler konnte nur in demMetaTrader 4 Terminal reproduziert werden.
Anwendung für den Test der Updates
Lassen Sie uns eine Anwendung entwickeln, um alle oben angegebenen Updates testen zu können. Wir erzeugen zwei Versionen dieser Anwendung — "Expert" und "Indicator". Die Indikator-Version wird in einem Unterfenster getestet, damit die automatische Anpassung der Fensterbreite getestet werden kann, sowie die automatische Anpassung der Elemente, die diesen Fenster hinzugefügt worden sind.
Alle verfügbaren Typen von Controls sollten hier implementiert werden, damit wir einen vollständigen Test durchführen können. Die Controls sollten sich auf unterschiedlichen Tabs befinden (CTabs) um das Interface so platzsparend wie möglich gestalten zu können. Da die Liste der Controls bereits sehr groß ist, macht es Sinn, die Implementation der Methoden für die Erzeugung dieser Controls in einer separaten Datei unterzubringen. Lassen Sie uns diese Datei MainWindow.mqh nennen. Sie wird in den gleichen Ordner abgelegt, in welchem sich auch die anderen Projektdateien befinden. Sie sollte direkt nach dem Körper der benutzerdefinierten Klasse verbunden werden, so wie es das nachfolgende Listing zeigt:
//+---------------------------------------------------------------- //| Program.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+---------------------------------------------------------------- #include <EasyAndFastGUI\Controls\WndEvents.mqh> //+---------------------------------------------------------------- //| Klasse für die Erzeugung der Anwendung | //+---------------------------------------------------------------- class CProgram : public CWndEvents { //... }; //+---------------------------------------------------------------- //| Erzeugung der Controls | //+---------------------------------------------------------------- #include "MainWindow.mqh"
Program.mqh should be connected to MainWindow.mqh.
//+---------------------------------------------------------------- //| MainWindow.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+---------------------------------------------------------------- #include "Program.mqh"
Es macht Sinn, in der Program.mqh Datei, nur die Hauptprogramm-Datei für die Erzeugung des grafischen Interface bestehen zu lassen, in welcher alle Methoden für die Erzeugung der Controls aufgerufen werden.
Unsere Testanwendung für das grafische Interface wird 8 Tabs beinhalten. Der nachfolgende Screenshot zeigt die Positionierung der Controls Das erste Tab beinhaltet alle Typen von Buttons (auch die Button Gruppen) und die Liste mit der vertikalen Scrollbar. "Simple Button 3" besitzt zwei Modi. Falls aktiviert, dann wird die Fortschrittsanzeige, die eine Ausführung eines Prozesses simuliert, sichtbar.
Abbildung 3. Die Gruppe von Controls für das Erste Tab des grafischen Interfaces
Wenn der "Simple Button 3" Aktiviert ist, dann wird die Fortschrittsanzeige in dem Bereich der Statusbar dargestellt. (Sehen Sie dazu den nachfolgenden Screenshot):
Abbildung 4. Fortschrittsanzeige
Das zweite, dritte und vierte Tab beinhaltet Tabellen vom unterschiedlichen Typ
Abbildung 5. Gruppe von Controls für das zweite Tab des grafischen Interfaces
Abbildung 6. Die Gruppe von Controls für das Dritte Tab des grafischen Interfaces
Abbildung 7. Die Gruppe von Controls für das Vierte Tab des grafischen Interfaces
Das fünfte Tab beinhaltet das Linienchart-Control Die Methoden um hiermit zu arbeiten, werden in der CProgram Klasse deklariert und implementiert. Der CProgram::OnTimerEvent() Timer generiert alle 300 Millisekunden zufällige Serien:
Fig. 8. Die Gruppe von Controls für das Fünfte Tab des grafischen Interfaces
Das sechste und siebente Tab beinhaltet die Baumansicht und den Datei Navigator, sowie verschiedene Typen der Combobox, Eingabefelder und Checkboxen:
Abbildung 9 Die Gruppe von Controls für das sechste Tab des grafischen Interfaces
Abbildung 10. Die Gruppe von Controls für das siebte Tab des grafischen Interfaces
Das siebte Tab beinhaltet die folgenden Controls Kalender, Dropdown-Kalender, Schieberegler, doppelter Schieberegler, Trennlinie und Farbpalette-Button:
Abbildung 11. Die Gruppe von Controls für das achte Tab des grafischen Interfaces
Wenn Sie die Farbpalette in dem Hauptfenster erzeugen wollen, dann setzen Sie den Index für das Formular und der Controls zurück damit sie hier hinzugefügt werden. Hier wird nur ein Control (Die Farbpalette) dem Formular hinzugefügt. Der nachfolgende Screenshot zeigt das endgültige Ergebnis:
Fig. 12. Die Farbpalette in dem Haupt-Chartfenster
Wie bereits erwähnt, wurde auch eine andere Anwendung (Expert) mit den gleichen grafischen Interface-Elementen für einen Test erzeugt:
Fig. 13. Test der Expert Advisor Anwendung
Beide Typen von Anwendungen (Expert und Indikator) wurden für die beiden Plattformen – MetaTrader 4 und MetaTrader 5 implementiert. Alle dafür notwendigen Dateien sind nachfolgend angefügt.
Schlussfolgerung
Die Bibliothek für das Erzeugen von grafischen Interfaces sieht zu dem aktuellen Stand der Entwicklung wie folgt aus: (Schematisch).
Abbildung 14. Die Struktur der Bibliothek zum aktuellen Stand der Entwicklung
Es wurden viele Fehlerbehebungen und Aktualisierungen auf Wunsch von den Anwendern implementiert. Wenn Ihnen etwas fehlt oder wenn Sie einen Fehler im Zusammenhang mit der Bibliothek erkannt haben oder wenn Sie eine Anwendung entwickeln, dann hinterlassen Sie einen Kommentar zu diesem Artikel oder senden Sie mir eine persönliche Nachricht. Ich werde Ihnen gerne dabei behilflich sein. Ich arbeite bereits an der nächsten Version dieser Bibliothek (Build 3) Sie wird einige zusätzliche Eigenschaften besitzen, die diese Bibliothek auf einen nächsten Level heben werden.
Zu den hier vorgestellten Testanwendungen, beinhalten die unten angefügten Archive auch die aktualisierten Versionen von allen vorangegangenen Artikeln dieser Serie.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/2634
![Rezepte MQL5 - Handelssignale der gleitenden Kanäle](https://c.mql5.com/2/24/ava2.png)
![Grafische Interfaces IX: Die Fortschrittsanzeige und das Linienchart-Control (Kapitel 2)](https://c.mql5.com/2/23/IX__1.png)
![Tiefes Neuronales Netzwerk mit geschichtetem RBM. Selbsttraining, Selbstkontrolle](https://c.mql5.com/2/22/images__1.png)
![Grafische Interfaces IX: Das Farbauswahl Control (Kapitel 1)](https://c.mql5.com/2/23/IX.png)
![MQL5 - Sprache von Handelsstrategien, eingebaut ins Kundenterminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- 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.