
Grafische Interfaces VII: Das Tab-Control (Kapitel 2)
Inhalt
- Einleitung
- Tabs-Control
- Entwicklung einer Klasse für die Erzeugung des Tabs-Controls
- Testen des Tabs Control
- Schlussfolgerung
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 Entwicklungsstand, herunterzuladen. Die Dateien müssen in den gleichen Verzeichnissen untergebracht werden, so, wie Sie auch in dem Archiv abgelegt sind.
Das erste Kapitel des siebten Teil befasste sich mit drei Klassen von Controls für die Erzeugung der folgenden Tabellen: Text-Label-Tabelle (CLabelsTable), Edit-box-Tabelle (CTable) und die gerenderte Tabelle (CCanvasTable). In diesem Artikel (Kapitel 2) Werden wir das Tabs-Control besprechen. Wir werden zwei Klassen für dieses Control präsentieren - eine Einfache und eine mit erweiterten Funktionalitäten.
Tabs-Control
Tabs werden dazu verwendet, vordefinierte Gruppen von grafischen Interface-Controls darzustellen. Sehr oft benötigen multifunktionale Anwendungen eine ganze Menge von Controls, die auf einer bestimmten Fläche des grafischen Interfaces untergebracht werden müssen. Tabs können dazu verwendet werden, diese Controls zu kategorisieren und dann in Gruppen darzustellen. Eine solche Vorgehensweise macht ein Interface für den Anwender bedienungsfreundlicher. Auf der Oberfläche sieht einen Tab aus, wie eine Gruppe von Buttons mit Labeln (Die Namen der gruppierten Controls). Es kann immer nur ein Tab selektiert sein (Aktiv).
Lassen Sie uns alle Komponenten dieses Controls auflisten.
- Der Hintergrund, beziehungsweise der Bereich, wo die Controls gruppiert werden.
- Tabs
Abbildung 1. Komponenten des Tabs-Controls.
Lassen Sie uns vier Modi für die Position definieren, wo die Tabs in Relation zu dem Bereich, wo die gruppierten Kontos platziert werden, erscheinen: Oben, unten, links und rechts.
Entwicklung einer Klasse für die Erzeugung des Tabs-Controls
Erzeugen Sie die Tabs.mqh Datei und beziehen Sie sie in der WndContainer.mqh Datei der Bibliothek mit ein:
//+------------------------------------------------------------------+ //| WndContainer.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "Tabs.mqh"
Die CTabs Klasse muss in der Tabs.mqh Datei erzeugt werden. In dieser Klasse, müssen, wie in allen anderen Klassen auch, die notwendigen Standardmethoden, sowie die Methoden für das Abspeichern des Pointers zu dem Formular, zu welchen das Control hinzugefügt wurde, hinzugefügt werden.
//+------------------------------------------------------------------+ //| Klasse für die Erzeugung von Tabs | //+------------------------------------------------------------------+ class CTabs : public CElement { private: //--- Ein Pointer zu der Form zu welchem das Element hinzugefügt worden ist CWindow *m_wnd; //--- public: CTabs(void); ~CTabs(void); //--- (1) Speichert den Pointer das Formulars, (2) Gibt den Pointer zu den Scrollbars zurück void WindowPointer(CWindow &object) { m_wnd=::GetPointer(object); } //--- public: //--- Chart Eventhandler virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); //--- Timer virtual void OnEventTimer(void); //--- Bewegen des Elementes virtual void Moving(const int x,const int y); //--- (1) Anzeigen, (2) verstecken, (3) zurücksetzen, (4) löschen virtual void Show(void); virtual void Hide(void); virtual void Reset(void); virtual void Delete(void); //--- (1) Setzen, (2) Zurücksetzen der Prioritäten der linken Maustaste virtual void SetZorders(void); virtual void ResetZorders(void); //--- Zurücksetzen der Farbe virtual void ResetColors(void) {} }; //+-----------------------------------------------------------------+ //| Konstruktor | //+-----------------------------------------------------------------+ CTabs::CTabs(void) { } //+-----------------------------------------------------------------+ //| Destruktor | //+-----------------------------------------------------------------+ CTabs::~CTabs(void) { }
Die Eigenschaften der Tabs können in besondere Eigenschaften und gemeinsame Eigenschaften aufgeteilt werden. Lassen Sie uns beide Listen aufzeigen:
Die besonderen Eigenschaften:
- Array mit Pointern zu den Controls, die dem Tab hinzugefügt werden
- Text
- Breite
Erzeugen Sie die TElements Struktur für die besonderen Eigenschaften und deklarieren Sie ein dynamisches Array mit diesem Typ:
class CTabs : public CElement { private: //--- Struktur der Eigenschaften und ein Array für die Controls, die dem Tab hinzugefügt wurden struct TElements { CElement *elements[]; string m_text; int m_width; }; TElements m_tab[]; };
Gemeinsame Eigenschaften
- Positionierungsmodus der Tabs
- Farbe des Hintergrundes
- Die Größe der Tabs entlang der Y Achse (Höhe)
- Die Farbe der Tabs in den unterschiedlichen Zuständen
- Die Farbe des Textes in den unterschiedlichen Zuständen
- Die Farbe der Ränder der Tabs
- Prioritäten für einen Klick mit der linken Maustaste
Für den Modus der Positionierung, benötigen wir die ENUM_TABS_POSITION Aufzählung, welche der Enums.mqh Datei hinzugefügt werden muss:
//+-----------------------------------------------------------------+ //| Enumeration für die Positionierung der Tabs | //+-----------------------------------------------------------------+ enum ENUM_TABS_POSITION { TABS_TOP =0, TABS_BOTTOM =1, TABS_LEFT =2, TABS_RIGHT =3 };
Die Deklaration der Variablen und Methoden für das Festlegen der Eigenschaften, werden in dem nachfolgenden Listing gezeigt:
class CTabs : public CElement { private: //--- Positionierung der Tabs ENUM_TABS_POSITION m_position_mode; //--- Farbe des Hintergrundes int m_area_color; //--- Die Größe der Tabs entlang der Y Achse int m_tab_y_size; //--- Die Farbe der Tabs in den unterschiedlichen Zuständen color m_tab_color; color m_tab_color_hover; color m_tab_color_selected; color m_tab_color_array[]; //--- Die Farbe des Textes in den unterschiedlichen Zuständen color m_tab_text_color; color m_tab_text_color_selected; //--- Die Farbe der Rahmen der Tabs color m_tab_border_color; //--- Priorität für die linke Maustaste int m_zorder; int m_tab_zorder; //--- public: //--- (1) Setzen der Positionierung (Oben, unten, links, rechts), (2) Setzen der Größe der Tabs entlang der Y Achse void PositionMode(const ENUM_TABS_POSITION mode) { m_position_mode=mode; } ENUM_TABS_POSITION PositionMode(void) const { return(m_position_mode); } void TabYSize(const int y_size) { m_tab_y_size=y_size; } //--- Farbe (1) des Hintergrundes, (2) Farbe der Tabs in den unterschiedlichen Zuständen, (3) Farbe der Rahmen der Tabs void AreaColor(const color clr) { m_area_color=clr; } void TabBackColor(const color clr) { m_tab_color=clr; } void TabBackColorHover(const color clr) { m_tab_color_hover=clr; } void TabBackColorSelected(const color clr) { m_tab_color_selected=clr; } void TabBorderColor(const color clr) { m_tab_border_color=clr; } //--- Die Farbe des Textes in den unterschiedlichen Zuständen void TabTextColor(const color clr) { m_tab_text_color=clr; } void TabTextColorSelected(const color clr) { m_tab_text_color_selected=clr; } };
Bevor wir das Control erzeugen, muss die benötigte Anzahl der Tabs mit dem zugehörigen Text und deren Breite angegeben werden. Lassen Sie uns dazu die CTabs::AddTab() Methode schreiben. Die Standardwerte für die Argumente dieser Methode sind«» (leerer string) und 50 (Breite).
class CTabs : public CElement { public: //--- Fügt einen Tab hinzu void AddTab(const string tab_text="",const int tab_width=50); }; //+-----------------------------------------------------------------+ //| Fügt einen Tab hinzu | //+-----------------------------------------------------------------+ void CTabs::AddTab(const string tab_text,const int tab_width) { //--- Legt die Größe des Arrays fest int array_size=::ArraySize(m_tabs); ::ArrayResize(m_tabs,array_size+1); ::ArrayResize(m_tab,array_size+1); //--- Speichert die übergebenen Eigenschaften m_tab[array_size].m_text =tab_text; m_tab[array_size].m_width =tab_width; //--- Speichert die Anzahl der Tabs m_tabs_total=array_size+1; }
Falls ein bestimmter Tab bei dem Start einer Anwendung vorselektiert sein soll, dann kann dieses über die Methode CTabs::SelectedTab() angegeben werden. Wir benötigen zudem die private CTabs::CheckTabIndex() Methode um die Korrektheit des angegebenen Index zu überprüfen.
class CTabs : public CElement { private: //--- Index des selektierten Tabs int m_selected_tab; //--- public: //--- (1) Speichern und (2) Rückgabe des Index des selektierten Tabs void SelectedTab(const int index) { m_selected_tab=index; } int SelectedTab(void) const { return(m_selected_tab); } //--- private: //--- Überprüfung des Index des selektierten Tabs void CheckTabIndex(void); }; //+-----------------------------------------------------------------+ //| Überprüfung des Index des selektierten Tabs | //+-----------------------------------------------------------------+ void CTabs::CheckTabIndex(void) { //--- Überprüfung der Überschreitung des ABCs int array_size=::ArraySize(m_tab); if(m_selected_tab<0) m_selected_tab=0; if(m_selected_tab>=array_size) m_selected_tab=array_size-1; }
Für die Erzeugung des Controls brauchen wir drei private Methoden und eine public (öffentliche) Methode:
class CTabs : public CElement { private: //--- Objekte für die Erzeugung des Elementes CRectLabel m_main_area; CRectLabel m_tabs_area; CEdit m_tabs[]; //--- public: //--- Methoden für die Erzeugung des Tabs bool CreateTabs(const long chart_id,const int subwin,const int x,const int y); //--- private: bool CreateMainArea(void); bool CreateTabsArea(void); bool CreateButtons(void); };
Falls dem Control keine Tabs hinzugefügt worden sind, dann führt der Aufruf der CTabs::CreateTabs() Methode zu einem Abbruch der Erzeugung des grafischen Interfaces und einer entsprechenden Nachricht:
//--- Falls es in der Gruppe keinen Tab gibt, dann benachrichtigen if(m_tabs_total<1) { ::Print(__FUNCTION__," > This method is to be called, " "if a group contains at least one tab! Use the CTabs::AddTab() method"); return(false); }
Die Ermittlung und Berechnung der Koordinaten für die Komponenten des Controls, geschieht in Abhängigkeit des gewählten Positionierungsmodus. Diese Berechnungen benötigen die CTabs::SumWidthTabs() Methode, die die gesamte Breite aller Tabs zurück gibt. In dem linken (TABS_LEFT) und rechten (TABS_RIGHT) Positionierungsmodus, wird die Breite des ersten Tabs zurückgegeben. Für die 'oben' (TABS_TOP) und 'unten' (TABS_BOTTOM) Modi, Wird die Breite aller Tabs aufsummiert.
class CTabs : public CElement { private: //--- Positionierung der Tabs ENUM_TABS_POSITION m_position_mode; //--- private: //--- Breite aller Tabs int SumWidthTabs(void); }; //+-----------------------------------------------------------------+ //| Gesamtbreite aller Tabs | //+-----------------------------------------------------------------+ int CTabs::SumWidthTabs(void) { int width=0; //--- Falls die Tabs links oder rechts positioniert wurden, dann wird die Breite des ersten Tabs zurückgegeben if(m_position_mode==TABS_LEFT || m_position_mode==TABS_RIGHT) return(m_tab[0].m_width); //--- Die Summe der Breiten aller Tabs for(int i=0; i<m_tabs_total; i++) width=width+m_tab[i].m_width; //--- Unter der Berücksichtigung mit einem Pixel Überlappung width=width-(m_tabs_total-1); return(width); }
Die CTabs::CreateMainArea() Methode dient dazu, den Bereich, in welchen die Controls platziert werden, zu erzeugen. Die Berechnung der Koordinaten und der Größe der Objekte sieht wie folgt aus (eine abgekürzte Version der Methode):
//+-----------------------------------------------------------------+ //| Erzeugt den Bereich für den Hintergrund | //+-----------------------------------------------------------------+ bool CTabs::CreateMainArea(void) { //--- Den Objektnamen bilden string name=CElement::ProgramName()+"_tabs_main_area_"+(string)CElement::Id(); //--- Koordinaten int x=0; int y=0; //--- Größe int x_size=0; int y_size=0; //--- Berechnung der Koordinaten und der Größen in Relation zu der Positionierung der Tabs switch(m_position_mode) { case TABS_TOP : x =CElement::X(); y =CElement::Y()+m_tab_y_size-1; x_size =CElement::XSize(); y_size =CElement::YSize()-m_tab_y_size; break; case TABS_BOTTOM : x =CElement::X(); y =CElement::Y(); x_size =CElement::XSize(); y_size =CElement::YSize()-m_tab_y_size; break; case TABS_RIGHT : x =CElement::X(); y =CElement::Y(); x_size =CElement::XSize()-SumWidthTabs()+1; y_size =CElement::YSize(); break; case TABS_LEFT : x =CElement::X()+SumWidthTabs()-1; y =CElement::Y(); x_size =CElement::XSize()-SumWidthTabs()+1; y_size =CElement::YSize(); break; } //--- Erzeugung des Objektes if(!m_main_area.Create(m_chart_id,name,m_subwin,x,y,x_size,y_size)) return(false); //--- Festlegen der Eigenschaften //--- Ränder von den Kanten //--- Abspeichern der Größe //--- Abspeichern der Koordinaten //--- Abspeichern des Objekt-Pointers //... return(true); }
Der folgende Abschnitt zeigt die Berechnung der Koordinaten und der Größe des Hintergrundes für die Tabs, in Abhängigkeit des positionierungs Modus, welche in der CTabs::CreateTabsArea() Methode angegeben werden:
//+-----------------------------------------------------------------+ //| Erzeugung des Tab Hintergrundes | //+-----------------------------------------------------------------+ bool CTabs::CreateTabsArea(void) { //--- Den Objektnamen bilden string name=CElement::ProgramName()+"_tabs_area_"+(string)CElement::Id(); //--- Koordinaten int x=CElement::X(); int y=CElement::Y(); //--- Größe int x_size=SumWidthTabs(); int y_size=0; //--- Berechnung der Größen in Relation zu der Positionierung der Tabs if(m_position_mode==TABS_TOP || m_position_mode==TABS_BOTTOM) { y_size=m_tab_y_size; } else { y_size=m_tab_y_size*m_tabs_total-(m_tabs_total-1); } //--- Einstellungen der Koordinaten für die Positionierung der Tabs auf der unteren und rechten Seite if(m_position_mode==TABS_BOTTOM) { y=CElement::Y2()-m_tab_y_size-1; } else if(m_position_mode==TABS_RIGHT) { x=CElement::X2()-x_size; } //--- Erzeugung des Objektes if(!m_tabs_area.Create(m_chart_id,name,m_subwin,x,y,x_size,y_size)) return(false); //--- Festlegen der Eigenschaften //--- Ränder von den Kanten //--- Abspeichern der Größe //--- Abspeichern der Koordinaten //--- Abspeichern des Objekt-Pointers //... return(true); }
Die CTabs::CreateButtons() Methode benötigt nur die Berechnung der Koordinaten um die Tabs zu erzeugen. Die Breite wird in einer benutzerdefinierten Klasse der Anwendung festgelegt, bevor das Control erzeugt wird. Andernfalls wird der Standardwert verwendet (Breite). Nachfolgend ist die abgekürzte Version der Methode:
//+-----------------------------------------------------------------+ //| Erzeugung der Tabs | //+-----------------------------------------------------------------+ bool CTabs::CreateButtons(void) { //--- Koordinaten int x =CElement::X(); int y =CElement::Y(); //--- Berechnung der Koordinaten in Relation zu der Positionierung der Tabs if(m_position_mode==TABS_BOTTOM) y=CElement::Y2()-m_tab_y_size-1; else if(m_position_mode==TABS_RIGHT) x=CElement::X2()-SumWidthTabs(); //--- Überprüfung des Index des selektierten Tabs CheckTabIndex(); //--- Erzeugung der Tabs for(int i=0; i<m_tabs_total; i++) { //--- Den Objektnamen bilden string name=CElement::ProgramName()+"_tabs_edit_"+(string)i+"__"+(string)CElement::Id(); //--- Berechnung der Koordinaten in Relation zu der Positionierung der Tabs für jeden individuellen Tab if(m_position_mode==TABS_TOP || m_position_mode==TABS_BOTTOM) x=(i>0) ? x+m_tab[i-1].m_width-1 : CElement::X(); else y=(i>0) ? y+m_tab_y_size-1 : CElement::Y(); //--- Erzeugung des Objektes if(!m_tabs[i].Create(m_chart_id,name,m_subwin,x,y,m_tab[i].m_width,m_tab_y_size)) return(false); //--- Festlegen der Eigenschaften //--- Ränder von den Kanten des Panels //--- Koordinaten //--- Größe //--- Initialisierung des Arrays //--- Abspeichern des Objekt-Pointers } //--- return(true); }
Um einen bestimmten Tab einen control hinzufügen zu können, schreiben wir die CTabs::AddToElementsArray() Methode. Sie besitzt zwei Argumente: (1) Tab Index, zu welchem das Control hinzugefügt werden soll und (2) Eine Referenz zu dem Control, Ein Pointer, welcher in dem Array der Tab-Ccontrols abgespeichert werden muss.
class CTabs : public CElement { public: //--- Minecontrol dem Tab-Array hinzufügen void AddToElementsArray(const int tab_index,CElement &object); }; //+-----------------------------------------------------------------+ //| Ein Control dem Array ausgewählten Tab hinzufügen | //+-----------------------------------------------------------------+ void CTabs::AddToElementsArray(const int tab_index,CElement &object) { //--- Überprüfung der Überschreitung des ABCs int array_size=::ArraySize(m_tab); if(array_size<1 || tab_index<0 || tab_index>=array_size) return; //--- Hinzufügen des Pointers des übergebenen Controls zu dem Array des angegebenen Tabs int size=::ArraySize(m_tab[tab_index].elements); ::ArrayResize(m_tab[tab_index].elements,size+1); m_tab[tab_index].elements[size]=::GetPointer(object); }
Bei einem Wechsel zwischen den Tabs, müssen die Controls des zuletzt selektierten Tabs versteckt werden und die Controls des jetzt selektierten Tabs angezeigt werden. Hierfür schreiben wir die CTabs::ShowTabElements() Methode. Zu Beginn wird eine Überprüfung der Sichtbarkeit der Controls durchgeführt. Falls das Control versteckt ist, dann bricht das Programm die Methode ab. Als nächstes wird der Index des aktiven Tabs überprüft und falls notwendig korrigiert. Dann werden in einer Schleife alle Tabs überprüft und die Hauptaufgabe der Methode wird ausgeführt.
class CTabs : public CElement { public: //--- Zeige nur die Controls des selektierten Tabs void ShowTabElements(void); }; //+-----------------------------------------------------------------+ //| Zeige nur die Controls des selektierten Tabs | //+-----------------------------------------------------------------+ void CTabs::ShowTabElements(void) { //--- Abbrechen, falls die Tabs versteckt sind if(!CElement::IsVisible()) return; //--- Überprüfung des Index des selektierten Tabs CheckTabIndex(); //--- for(int i=0; i<m_tabs_total; i++) { //--- Abfrage der Anzahl der controls, die zu diesem Tab gehören int tab_elements_total=::ArraySize(m_tab[i].elements); //--- Falls dieses Tab selektiert ist if(i==m_selected_tab) { //--- Anzeigen der Controls des Tabs for(int j=0; j<tab_elements_total; j++) m_tab[i].elements[j].Show(); } //--- Verstecke in die Controls von inaktiven Tabs else { for(int j=0; j<tab_elements_total; j++) m_tab[i].elements[j].Hide(); } } }
Die CTabs::OnClickTab() Methode wird für die Verarbeitung eines Klicks auf einen Tab benötigt. Zu nächsten müssen zwei Überprüfungen vorgenommen werden: (1) basierend auf den Namen des angeklickten Objektes und (2) basierend auf dem Bezeichner des Controls, der aus dem Objektnamen unter Verwendung der CTabs::IdFromObjectName() Methode gewonnen wird. Wenn die Überprüfung erfolgreich waren, dann (1) ermittelt das Programm das angeklickte Tab in einer Schleife, (2) speichert seinen Index ab und (3) setzt die entsprechenden Farben. Am Ende der CTabs::ShowTabElements() Methode, werden nur die Controls des aktiven Tabs sichtbar gemacht.
class CTabs : public CElement { private: //--- Verarbeitung eines Klicks auf einen Tab bool OnClickTab(const string pressed_object); //--- Den Bezeichner aus dem Objektnamen entnehmen int IdFromObjectName(const string object_name); }; //+-----------------------------------------------------------------+ //| Verarbeitung eines Klicks auf einen Tab | //+-----------------------------------------------------------------+ bool CTabs::OnClickTab(const string clicked_object) { //--- Abbrechen, falls es sich nicht um einen Klick auf eine Zelle dieser Tabelle handelt if(::StringFind(clicked_object,CElement::ProgramName()+"_tabs_edit_",0)<0) return(false); //--- Den Bezeichner aus dem Objektnamen entnehmen int id=IdFromObjectName(clicked_object); //--- Abbrechen, falls der Bezeichner nicht übereinstimmt if(id!=CElement::Id()) return(false); //--- for(int i=0; i<m_tabs_total; i++) { //--- Falls auf dieses Tab geklickt wurde if(m_tabs[i].Name()==clicked_object) { //--- Abspeichern des Index des selektierten Tabs SelectedTab(i); //--- Setzen der Farben m_tabs[i].Color(m_tab_text_color_selected); m_tabs[i].BackColor(m_tab_color_selected); } else { //--- Festlegen der Farbe für die inaktiven Tabs m_tabs[i].Color(m_tab_text_color); m_tabs[i].BackColor(m_tab_color); } } //--- Zeige nur die Controls des selektierten Tabs ShowTabElements(); return(true); }
Nachfolgend wird der Programmcode für den CTabs::OnEvent() Eventhandler gezeigt:
//+-----------------------------------------------------------------+ //| Chart Eventhandler | //+-----------------------------------------------------------------+ void CTabs::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Verarbeiten des Mauszeiger Bewegungs Events if(id==CHARTEVENT_MOUSE_MOVE) { //--- Abbrechen, falls das Element versteckt ist if(!CElement::IsVisible()) return; //--- Koordinaten int x=(int)lparam; int y=(int)dparam; for(int i=0; i<m_tabs_total; i++) m_tabs[i].MouseFocus(x>m_tabs[i].X() && x<m_tabs[i].X2() && y>m_tabs[i].Y() && y<m_tabs[i].Y2()); //--- return; } //--- Verarbeiten eines Klicks mit der linken Maustaste auf ein Objekt if(id==CHARTEVENT_OBJECT_CLICK) { //--- Anklicken eines Tabs if(OnClickTab(sparam)) return; } }
Es wurden nun alle Methoden der CTabs Klasse berücksichtigt. Lassen Sie uns nun einen Test durchführen.
Testen des Tabs Control
Lassen Sie uns nun den EA aus dem vorherigen Teil dieser Serie für den Test verwenden. Entfernen Sie alle Elemente, bis auf das Hauptmenü und die Statusbar. Lassen Sie uns einen Test für alle Positionierungsmodi (Oben unten rechts links) Testen, sowie deren Größe (Höhe). Lassen Sie uns dafür den EA weitere externe Parameter in der Program.mqh Datei hinzufügen:
//--- Externe Parameter des Expert Advisors input ENUM_TABS_POSITION TabsPosition =TABS_TOP; // Tabs Position input int TabsHeight =20; // Tabs Height
Anschließend deklarieren wir in der benutzerdefinierten Klasse der Anwendung(CProgram) eine Instanz der CTabs Klasse und Methoden für die Erzeugung des Tabs Controls mit Abständen von den Eckpunkten des Formulars:
class CProgram : public CWndEvents { private: //--- Tabs CTabs m_tabs; //--- private: //--- Tabs #define TABS1_GAP_X (4) #define TABS1_GAP_Y (45) bool CreateTabs(void); };
Es wird insgesamt 4 Tipps geben. Der angezeigte Text und die Breite der Tabs kann über die Initialisierungsarrays eingestellt werden. Die Werte der Elemente werden dann in einer Schleife unter Verwendung der CTabs::AddTab() Methode übergeben. Die Höhe und die Positionierung der Tabs wird über externe Parameter festgelegt. Das zweite Tab (index 1) wird standardmäßig vorselektiert sein, wenn das Programm auf dem Chart geladen wird. Der vollständige Programmcode der CProgram::CreateTabs() Methode wird nachfolgend dargestellt:
//+-----------------------------------------------------------------+ //| Erzeuge einen Bereich mit Tabs | //+-----------------------------------------------------------------+ bool CProgram::CreateTabs(void) { #define TABS1_TOTAL 4 //--- Übergabe des Panel Objektes m_tabs.WindowPointer(m_window1); //--- Koordinaten int x=m_window1.X()+TABS1_GAP_X; int y=m_window1.Y()+TABS1_GAP_Y; //--- Arrays mit dem Text und der Breite für die Tabs string tabs_text[]={"Tab 1","Tab 2","Tab 3","Tab 4"}; int tabs_width[]={90,90,90,90}; //--- Festlegen der Eigenschaften vor der Erzeugung m_tabs.XSize(596); m_tabs.YSize(243); m_tabs.TabYSize(TabsHeight); m_tabs.PositionMode(TabsPosition); m_tabs.SelectedTab((m_tabs.SelectedTab()==WRONG_VALUE) ? 1 : m_tabs.SelectedTab()); m_tabs.AreaColor(clrWhite); m_tabs.TabBackColor(C'225,225,225'); m_tabs.TabBackColorHover(C'240,240,240'); m_tabs.TabBackColorSelected(clrWhite); m_tabs.TabBorderColor(clrSilver); m_tabs.TabTextColor(clrGray); m_tabs.TabTextColorSelected(clrBlack); //--- Füge Tabs mit angegebenen Eigenschaften hinzu for(int i=0; i<TABS1_TOTAL; i++) m_tabs.AddTab(tabs_text[i],tabs_width[i]); //--- Erzeugung des Controls if(!m_tabs.CreateTabs(m_chart_id,m_subwin,x,y)) return(false); //--- Hinzufügen des Objektes zu dem gemeinsamen Array von Objektgruppen CWndContainer::AddToElementsArray(0,m_tabs); return(true); }
Die Methode muss in der Hauptmethode für die Erzeugung des grafischen Interfaces der Anwendung aufgerufen werden (Sehen Sie dazu nachfolgend die verkürzte Version der Methode):
//+-----------------------------------------------------------------+ //| Erzeugung eines Expert-Bedienfeldes | //+-----------------------------------------------------------------+ bool CProgram::CreateExpertPanel(void) { //--- Erzeugen des Formulars 1 für die Controls //---Erzeugung der Controls: // Hauptmenü //--- Kontextmenüs //--- Tabs if(!CreateTabs()) return(false); //--- Neuzeichnen des Charts m_chart.Redraw(); return(true); }
Kompilieren Sie dieses Programm und laden Sie es auf einen Chart. Die Positionierungsmodi werden sukzessive mit den externen Parametern geändert (Sehen Sie sich dazu die nachfolgenden Screenshots an):
Abbildung 2. Tabs Positionoierungsmodus — «Top».
Abbildung 3. Tabs Positionoierungsmodus — «Bottom».
Abbildung 4. Tabs Positionoierungsmodus — «Left».
Abbildung 5. Tabs Positionoierungsmodus — «Right».
Lassen Sie uns nun testen, wie das Ganze mit Gruppen von Controls funktioniert, die wir jetzt jedem Tab hinzufügen. Erzeugen Sie dafür eine separate Kopie des gleich EAs und entfernen Sie alle externen Parameter. Hier werden die Tabs oben auf der Arbeitsfläche positioniert (TABS_TOP).
- Dem ersten Tab wird eine Text-Label-Tabelle hinzugefügt.
- Dem zweiten Tab wird eine Editbox-Tabelle hinzugefügt
- Dem dritten Tab wird eine gerenderte Tabelle hinzugefügt.
- Dem vierten Tab wird eine Gruppe von Controls hinzugefügt, dazu gehören:
- Vier Checkboxen
- Vier Checkboxen mit Edit-Boxen
- Vier Comboboxen mit Checkboxen
- Eine Trennlinie
In der benutzerdefinierten Klasse der Testanwendung (CProgram), deklarieren Sie (1) Instanzen dieser Controls, (2) Methoden für deren Erzeugung und (3) Abstände von der Ecke des Formulars (Sehen Sie dazu den Programmcode in dem nachfolgenden Listing):
class CProgram : public CWndEvents { private: //--- Text-Label-Tabelle CLabelsTable m_labels_table; //--- Editbox-Tabelle CTable m_table; //--- Gerenderte Tabelle CCanvasTable m_canvas_table; //--- Checkboxen CCheckBox m_checkbox1; CCheckBox m_checkbox2; CCheckBox m_checkbox3; CCheckBox m_checkbox4; //--- Vier Checkboxen mit Edit-Boxen CCheckBoxEdit m_checkboxedit1; CCheckBoxEdit m_checkboxedit2; CCheckBoxEdit m_checkboxedit3; CCheckBoxEdit m_checkboxedit4; //--- Vier Comboboxen mit Checkboxen CCheckComboBox m_checkcombobox1; CCheckComboBox m_checkcombobox2; CCheckComboBox m_checkcombobox3; CCheckComboBox m_checkcombobox4; //--- Trennlinie CSeparateLine m_sep_line; //--- private: //--- Text-Label-Tabelle #define TABLE1_GAP_X (5) #define TABLE1_GAP_Y (65) bool CreateLabelsTable(void); //--- Editbox-Tabelle #define TABLE2_GAP_X (5) #define TABLE2_GAP_Y (65) bool CreateTable(void); //--- Gerenderte Tabelle #define TABLE3_GAP_X (5) #define TABLE3_GAP_Y (65) bool CreateCanvasTable(void); //--- Trennlinie #define SEP_LINE_GAP_X (300) #define SEP_LINE_GAP_Y (70) bool CreateSepLine(void); //--- Checkboxen #define CHECKBOX1_GAP_X (18) #define CHECKBOX1_GAP_Y (75) bool CreateCheckBox1(const string text); #define CHECKBOX2_GAP_X (18) #define CHECKBOX2_GAP_Y (175) bool CreateCheckBox2(const string text); #define CHECKBOX3_GAP_X (315) #define CHECKBOX3_GAP_Y (75) bool CreateCheckBox3(const string text); #define CHECKBOX4_GAP_X (315) #define CHECKBOX4_GAP_Y (175) bool CreateCheckBox4(const string text); //--- Vier Checkboxen mit Edit-Boxen #define CHECKBOXEDIT1_GAP_X (40) #define CHECKBOXEDIT1_GAP_Y (105) bool CreateCheckBoxEdit1(const string text); #define CHECKBOXEDIT2_GAP_X (40) #define CHECKBOXEDIT2_GAP_Y (135) bool CreateCheckBoxEdit2(const string text); #define CHECKBOXEDIT3_GAP_X (337) #define CHECKBOXEDIT3_GAP_Y (105) bool CreateCheckBoxEdit3(const string text); #define CHECKBOXEDIT4_GAP_X (337) #define CHECKBOXEDIT4_GAP_Y (135) bool CreateCheckBoxEdit4(const string text); //--- Vier Comboboxen mit Checkboxen #define CHECKCOMBOBOX1_GAP_X (40) #define CHECKCOMBOBOX1_GAP_Y (205) bool CreateCheckComboBox1(const string text); #define CHECKCOMBOBOX2_GAP_X (40) #define CHECKCOMBOBOX2_GAP_Y (235) bool CreateCheckComboBox2(const string text); #define CHECKCOMBOBOX3_GAP_X (337) #define CHECKCOMBOBOX3_GAP_Y (205) bool CreateCheckComboBox3(const string text); #define CHECKCOMBOBOX4_GAP_X (337) #define CHECKCOMBOBOX4_GAP_Y (235) bool CreateCheckComboBox4(const string text); };
In den vorherigen Artikel haben wir wiederholt gezeigt, wie Controls erzeugt und zu einem Formular hinzugefügt werden. Daher werden wir hier nur zeigen, wie ein Konto zu einem Tab hinzugefügt wird. Hier reicht das einfachste Beispiel - eine Trennlinie - aus. In dem nachfolgenden Programmcode, ist die Zeile mit dem Aufruf der CTabs::AddToElementsArray() Methode in Gelb hervorgehoben. Das erste Argument, ist der Index des Tabs, zu welchem ein Control hinzugefügt werden soll. In diesem Fall ist der Index 3, was dem vierten Tab entspricht. Das zweite Argument ist das Objekt, welches dem Tab hinzugefügt werden soll.
//+-----------------------------------------------------------------+ //| Erzeugt eine Trennlinie | //+-----------------------------------------------------------------+ bool CProgram::CreateSepLine(void) { //--- Abspeichern des Fenster-Pointers m_sep_line.WindowPointer(m_window1); //--- Hinzufügen zu dem vierten Tab der ersten Gruppe von Tabs m_tabs.AddToElementsArray(3,m_sep_line); //--- Koordinaten int x=m_window1.X()+SEP_LINE_GAP_X; int y=m_window1.Y()+SEP_LINE_GAP_Y; //--- Größe int x_size=2; int y_size=210; //--- Festlegen der Eigenschaften vor der Erzeugung m_sep_line.DarkColor(C'213,223,229'); m_sep_line.LightColor(clrWhite); m_sep_line.TypeSepLine(V_SEP_LINE); //--- Erzeugung des Elementes if(!m_sep_line.CreateSeparateLine(m_chart_id,m_subwin,0,x,y,x_size,y_size)) return(false); //--- Hinzufügen des Pointers des Elementes zu der Basis CWndContainer::AddToElementsArray(0,m_sep_line); return(true); }
Nachdem das grafische Interface der Anwendung erzeugt wurde, muss die CTabs::ShowTabElements() Methode aufgerufen werden, damit nur noch die Controls des aktiven Tabs dargestellt werden. (Nachfolgend sehen Sie eine verkürzte Version der Methode). Falls dieses nicht gemacht wird, dann sind alle Controls von allen Tabs sichtbar.
//+-----------------------------------------------------------------+ //| Erzeugung eines Expert-Bedienfeldes | //+-----------------------------------------------------------------+ bool CProgram::CreateExpertPanel(void) { //--- Erzeugen des Formulars 1 für die Controls //---Erzeugung der Controls: //--- Hauptmenü //--- Kontextmenüs //--- Status bar //--- Tabs //... //--- Text-Label-Tabelle if(!CreateLabelsTable()) return(false); //--- Editbox-Tabelle if(!CreateTable()) return(false); //--- Erzeugung der gerenderten Tabelle if(!CreateCanvasTable()) return(false); //--- Trennlinie if(!CreateSepLine()) return(false); //--- Checkboxen if(!CreateCheckBox1("Checkbox 1")) return(false); if(!CreateCheckBox2("Checkbox 2")) return(false); if(!CreateCheckBox3("Checkbox 3")) return(false); if(!CreateCheckBox4("Checkbox 4")) return(false); //--- Vier Checkboxen mit Edit-Boxen if(!CreateCheckBoxEdit1("Checkbox Edit 1:")) return(false); if(!CreateCheckBoxEdit2("Checkbox Edit 2:")) return(false); if(!CreateCheckBoxEdit3("Checkbox Edit 3:")) return(false); if(!CreateCheckBoxEdit4("Checkbox Edit 4:")) return(false); //--- Vier Comboboxen mit Checkboxen if(!CreateCheckComboBox1("CheckCombobox 1:")) return(false); if(!CreateCheckComboBox2("CheckCombobox 2:")) return(false); if(!CreateCheckComboBox3("CheckCombobox 3:")) return(false); if(!CreateCheckComboBox4("CheckCombobox 4:")) return(false); //--- Nur die Controls des aktiven Tabs anzeigen m_tabs.ShowTabElements(); //--- Neuzeichnen des Charts m_chart.Redraw(); return(true); }
Das Ergebnis sollte so wie in dem nachfolgend gezeigten Screenshot aussehen:
Abbildung 6. Die Controls des ersten Tabs.
Abbildung 7. Die Controls des zweiten Tabs
Fig. 8. Die Controls bis dritten Tabs
Fig. 9. Die Controls des vierten Tabs
Alles funktioniert wie vorgesehen. Der siebte Teil der Serie der Bibliothek, der den grafischen Schnittstellen gewidmet ist, kann nun abgeschlossen werden. Als Ergänzung können Sie eine weitere Klasse (CIconTabs) für die Erzeugung von Tabs mit einer erweiterten Funktionalität herunterladen, die diesem Artikel beigefügt sind. Anders als bei der CTabs Klasse, können die Controls vom Typ CIconTabs einstellbare Icons für jeden Tab besitzen. Dieses kann das grafische Interface noch benutzerfreundlicher machen.
Die Icons und der Text können mit der nachfolgenden Methode sehr genau auf jedem Tab platziert werden:
//+-----------------------------------------------------------------+ //| Klasse für die Erzeugung von Icon-Tabs | //+-----------------------------------------------------------------+ class CIconTabs : public CElement { private: //--- Label Abstände int m_icon_x_gap; int m_icon_y_gap; //--- Die Ränder des Text Labels int m_label_x_gap; int m_label_y_gap; //--- public: //--- Label Abstände void IconXGap(const int x_gap) { m_icon_x_gap=x_gap; } void IconYGap(const int y_gap) { m_icon_y_gap=y_gap; } //--- Die Ränder 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; } };
Ein Beispiel für das Aussehen der Icon-Tabs-Controls, wird in dem nachfolgenden Screenshot gezeigt:
Abbildung 10. Icon Tabs Control.
Der Programmcode dieses Expert Advisors kann ebenfalls mit den an diesen Artikel beigefügten Dateien heruntergeladen werden.
Schlussfolgerung
Zur Zeit sieht das schematische Diagramm unserer Bibliothek für das Erzeugen von grafischen Interfaces wie folgt aus:
Abbildung 11. Die Struktur unserer Bibliothek zum aktuellen Stand der Entwicklung
Der siebte Teil der Serie über grafische Interfaces innerhalb des MetaTrader Trading-Terminals, deckt die Erzeugung von Tabellen und Tab-Controls ab. Es werden damit dre Tabellenklassen (CLabelsTable, CTable und CCanvasTable) für die Erzeugung von Tabellen angeboten und zwei Klassen (CTabs and CIconTabs) für die Erzeugung von Tabs.
Der nächste (achte) wird sich mit den folgenden Controls beschäftigen.
- Ein statischer und ein Dropdown-Kalender
- Ein Baumverzeichnis
- Ein Dateien-Navigator
Sie können das Material des siebten Teils dieser Serie über die angehängten Dateien herunterladen und testen. Wenn Sie fragen zur Verwendung dieses Materials haben, dann können Sie zunächst auf die detaillierte Beschreibung in der Bibliothek zurückgreifen oder Sie stellen Ihre Frage(n) in den Kommentaren zu diesem Artikel.
Liste der Artikel (Kapitel) des siebten Teils:
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/2503





- 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.