
Grafische Interfaces V: Das ListView-Element (Kapitel 2)
Inhalt
- Einleitung
- Das ListView Element
- Entwickeln der Klasse für die Erzeugung des Elementes
- Testen des Setups der ListView
- Methoden für das Verwalten des Elementes
- Schneller Vorlauf der ListView
- 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.
In dem vorherigen Kapitel haben wir Klassen für die Erzeugung der vertikalen und horizontalen Scrollbar geschrieben. In diesem Kapitel werden wir diese implementieren. Wir werden eine Klasse für das Erzeugen eines ListView Elementes (Liste / Listenansicht) schreiben, bei der eine Komponente eine vertikale Scrollbar darstellt. Wir werden zudem die Implementation des Mechanismus demonstrieren, der dafür verantwortlich ist, dass bei gedrücktem Scrollbar-Button die ListView automatisch nach unten scrollt. Zum Schluss werden wir mit einem realen Beispiel einer MQL Anwendung dieses Element testen.
Das ListView Element
Dieses Element des grafischen Interfaces gibt dem Anwender eine Auswahlmöglichkeit an verschiedenen Optionen. Die gesamte Anzahl der Elemente in einer Liste und die Anzahl der sichtbaren Elemente einer Liste können unterschiedlich sein, wenn die maximale Anzahl für die den Arbeitsbereich der ListView zu groß ist. In diesen Fällen werden Scrollbars verwendet.
Wir werden eine ListView aus verschiedenen einfachen Objekten zusammenstellen und auch das Scrollbar Elements mit einbeziehen. :Diese sind:
- Der Hintergrund der ListView
- Array mit Elementen der ListView.
- Die vertikale Scrollbar
Abbildung 1. Die Komponenten des ListView Elementes
Nachfolgend betrachten wir uns nun die Entwicklung der Klasse für die Erzeugung des ListView Elementes.
Entwickeln der Klasse für die Erzeugung des Elementes
Um dieses Element erzeugen und es unserer Bibliothek hinzufügen zu können, benötigen wir eine Datei mit der CListView Klasse des Elementes. In unserem Fall ist das die ListView.mqh Datei. Zudem müssen wir die Datei mit in der WndContainer.mqh Datei mit einbeziehen:
//+---------------------------------------------------------------- //| WndContainer.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+---------------------------------------------------------------- #include "ListView.mqh"
Ähnlich wie bereits bei den anderen besprochenen Klassen, hat auch die CListView Klasse ein Standard-Set von Methoden. Für die Verwendung der Scrollbar muss auch noch die Scrolls.mqh Datei mit in der ListView.mqh Datei mit einbezogen werden.
//+---------------------------------------------------------------- //| ListView.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+---------------------------------------------------------------- #include "Element.mqh" #include "Window.mqh" #include "Scrolls.mqh" //+---------------------------------------------------------------- //| Klasse für die Erzeugung der ListView | //+---------------------------------------------------------------- class CListView : public CElement { private: //--- Ein Pointer zu der Form zu welchem das Element hinzugefügt worden ist CWindow *m_wnd; //--- public: CListView(void); ~CListView(void); //--- (1) Speicher den Formular-Pointer 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); }; //+---------------------------------------------------------------- //| Konstruktor | //+---------------------------------------------------------------- CListView::CListView(void) { //--- Abspeichern des namens der Elementklasse in der Basisklasse CElement::ClassName(CLASS_NAME); } //+---------------------------------------------------------------- //| Destruktor | //+---------------------------------------------------------------- CListView::~CListView(void) { }
Wir benötigen Methoden für das Setzen der Eigenschaften der primitiven Objekte (Komponenten der ListView) bevor diese selbst erzeugt wird.
- Die Höhe der ListView Elemente
- Die Farbe des Rahmens des ListView Hintergrundes
- Die Farbe der Hintergründe der Elemente in den unterschiedlichen Zuständen
- Die Farbe des Textes der Elemente in den unterschiedlichen Zuständen.
Die oben gezeigten Eigenschaften werden in den Konstruktor der Klasse gesetzt.
class CListView : public CElement { private: //--- Eigenschaften des ListView Hintergrundes int m_area_zorder; color m_area_border_color; //--- Eigenschaften der ListView Elemente int m_item_zorder; int m_item_y_size; color m_item_color; color m_item_color_hover; color m_item_color_selected; color m_item_text_color; color m_item_text_color_hover; color m_item_text_color_selected; //--- public: //--- Höhe der Elemente void ItemYSize(const int y_size) { m_item_y_size=y_size; } //--- Farbe des Rahmens des Hintergrundes void AreaBorderColor(const color clr) { m_area_border_color=clr; } //--- Farbe der ListView Elemente in unterschiedlichen Zuständen void ItemColor(const color clr) { m_item_color=clr; } void ItemColorHover(const color clr) { m_item_color_hover=clr; } void ItemColorSelected(const color clr) { m_item_color_selected=clr; } void ItemTextColor(const color clr) { m_item_text_color=clr; } void ItemTextColorHover(const color clr) { m_item_text_color_hover=clr; } void ItemTextColorSelected(const color clr) { m_item_text_color_selected=clr; } }; //+---------------------------------------------------------------- //| Konstruktor | //+---------------------------------------------------------------- CListView::CListView(void) : m_item_y_size(18), m_area_border_color(C'235,235,235'), m_item_color(clrWhite), m_item_color_hover(C'240,240,240'), m_item_color_selected(C'51,153,255'), m_item_text_color(clrBlack), m_item_text_color_hover(clrBlack), m_item_text_color_selected(clrWhite) { //--- Setzen der Priorität eines Klicks mit der linken Maustaste m_area_zorder =1; m_item_zorder =2; }
Es gibt drei private und eine öffentliche Methoden für die Erzeugung der Objekte der ListView. Zudem muss ein Array von Klassen-Instanzen des CEdit Typs für die Erzeugung der ListView Elemente deklariert werden. Dieses Array kann für die Erzeugung von grafischen Objekten des Typs OBJ_EDIT (Eingabefeld) verwendet werden..
class CListView : public CElement { private: //--- Objekte für die Erzeugung der ListView CRectLabel m_area; CEdit m_items[]; CScrollV m_scrollv; //--- public: //--- Methoden für die Erzeugung der ListView bool CreateListView(const long chart_id,const int window,const int x,const int y); //--- private: bool CreateArea(void); bool CreateList(void); bool CreateScrollV(void); };
Die Standardgröße der ListView und seines sichtbaren Bereiches entspricht zwei Elementen, da es keinen Grund für die Erzeugung einer ListView mit nur einem Element gibt. Um die Größe der Liste und seines sichtbaren Bereiches einstellen zu können, erzeugen wir die CListView::ListSize() und CListView::VisibleListSize() Methoden, die auch überprüfen, dass die Anzahl der Elemente nicht kleiner als Zwei ist.
class CListView : public CElement { private: //--- Array mit den ListView werten string m_value_items[]; //--- Die Größe der ListView und seines sichtbaren Bereiches int m_items_total; int m_visible_items_total; //--- public: //--- Gibt die Größe (1) der ListView und (2) die Größe des sichtbaren Bereiches zurück int ItemsTotal(void) const { return(m_items_total); } int VisibleItemsTotal(void) const { return(m_visible_items_total); } //--- Legt die Größe (1) der ListView und (2) den sichtbaren Bereich fest void ListSize(const int items_total); void VisibleListSize(const int visible_items_total); }; //+---------------------------------------------------------------- //| Konstruktor | //+---------------------------------------------------------------- CListView::CListView(void) : m_items_total(2), m_visible_items_total(2) { //--- Legt die Größe der ListView und die Größe des sichtbaren Bereiches fest ListSize(m_items_total); VisibleListSize(m_visible_items_total); } //+---------------------------------------------------------------- //| Legt die Größe der ListView fest | //+---------------------------------------------------------------- void CListView::ListSize(const int items_total) { //--- Es gibt keinen Grund eine ListView kleiner als zwei Elemente zu machen m_items_total=(items_total<2) ? 2 : items_total; ::ArrayResize(m_value_items,m_items_total); } //+---------------------------------------------------------------- //| Legt die Größe des sichtbaren Bereiches der ListView fest | //+---------------------------------------------------------------- void CListView::VisibleListSize(const int visible_items_total) { //--- Es gibt keinen Grund eine ListView kleiner als zwei Elemente zu machen m_visible_items_total=(visible_items_total<2) ? 2 : visible_items_total; ::ArrayResize(m_items,m_visible_items_total); }
Es sind nun Methoden für das Abspeichern und Abfragen des Index und des Textes des hervorgehobenen Elementes in der Liste notwendig. Das erste Element der ListView wird standardmäßig hervorgehoben. Falls nach der Erzeugung der ListView ein anderes Element hervorgehoben werden soll, verwenden wir die CListView::SelectedItemIndex() Methode. Sie müssen die Nummer des Indexes vor der Erzeugung der ListView und nach der Angabe der Anzahl der Elemente angeben.
class CListView : public CElement { private: //--- (1) Index und (2) der Text des hervorgehobenen Elementes int m_selected_item_index; string m_selected_item_text; //--- public: //--- Gibt/speichert (1) den Index und (2) den Text des hervorgehobenen Elementes in der ListView void SelectedItemIndex(const int index); int SelectedItemIndex(void) const { return(m_selected_item_index); } void SelectedItemText(const string text) { m_selected_item_text=text; } string SelectedItemText(void) const { return(m_selected_item_text); } }; //+---------------------------------------------------------------- //| Konstruktor | //+---------------------------------------------------------------- CListView::CListView(void) : m_selected_item_index(0), m_selected_item_text("") { //--- ... } //+---------------------------------------------------------------- //| Abspeichern des Index | //+---------------------------------------------------------------- void CListView::SelectedItemIndex(const int index) { //--- Korrekturen, falls die Größe überschritten wird m_selected_item_index=(index>=m_items_total)? m_items_total-1 : (index<0)? 0 : index; }
Sowohl nach dem die ListView erzeugt wurde und auch in dem Moment, wo ein Element ausgewählt wird, muss dieses Elements mit einer anderen Farbe hervorgehoben werden. Lassen Sie uns dazu die CListView::HighlightSelectedItem() Methode schreiben. Zu Beginn der Methode wird der aktuelle Zustand der Scrollbar geprüft. Falls diese aktiv ist und der Schieberegler bewegt wird, dann verlässt das Programm diese Methode. Wenn der Test bestanden wurde, dann Wird die aktuelle Position des Schiebereglers in der ListView abgefragt. Den Wert, den wir hier erhalten haben, wird unsere Startwert für den Fehler in der Schleife darstelle. Mit Hilfe dieser Schleife können wir das hervorzuhebende Element identifizieren.
class CListView : public CElement { public: //--- Hervorheben des ausgewählten Elementes void HighlightSelectedItem(void); }; //+---------------------------------------------------------------- //| Hebt das ausgewählte Element hervor | //+---------------------------------------------------------------- void CListView::HighlightSelectedItem(void) { //--- Abbrechen, falls die Scrollbar aktiv ist if(m_scrollv.ScrollState()) return; //--- Abfrage der aktuellen Position des Schiebereglers der Scrollbar int v=m_scrollv.CurrentPos(); //--- Durchlaufen der sichtbaren Teile der ListView for(int r=0; r<m_visible_items_total; r++) { //--- Falls Sie uns innerhalb der Bandbreite der ListView befinden if(v>=0 && v<m_items_total) { //--- Verändern der Hintergrundfarbe des Textes m_items[r].BackColor((m_selected_item_index==v) ? m_item_color_selected : m_item_color); m_items[r].Color((m_selected_item_index==v) ? m_item_text_color_selected : m_item_text_color); //--- Erhöhung des Zählers v++; } } }
Wenn die Listen-Elemente in der CListView::CreateList() Methode erzeugt werden, Werden auch die Koordinaten und die breiten berechnet, damit sie nicht den Rahmen des ListView-Hintergrundes überschreiten. Bei der Berechnung der Breite wird auch berücksichtigt, ob die ListView eine Scrollbar besitzt.. Alle Elemente unterhalb des ersten werden auf dem nächsten mit einer Überlappung von einem Pixel gesetzt. Das ist notwendig, damit keine Lücken zwischen den Pixeln entstehen, die dann sichtbar werden wenn die Elemente hervorgehoben werden wenn die Maus sich über diesen befindet. Dieses müssen wir auch bei der Berechnung der Höhe der ListView und der Scrollbars berücksichtigen. Nach der Erzeugung aller Elemente wird das ausgewählte Element hervorgehoben und der Text gespeichert.
//+---------------------------------------------------------------- //| Erzeugt die ListView Elemente | //+---------------------------------------------------------------- bool CListView::CreateList(void) { //--- Koordinaten int x =CElement::X()+1; int y =0; //--- Berechnung der Breite der ListView Elemente int w=(m_items_total>m_visible_items_total) ? CElement::XSize()-m_scrollv.ScrollWidth() : CElement::XSize()-2; //--- for(int i=0; i<m_visible_items_total; i++) { //--- Den Objektnamen bilden string name=CElement::ProgramName()+"_listview_edit_"+(string)i+"__"+(string)CElement::Id(); //--- Berechnung der y-Koordinate y=(i>0) ? y+m_item_y_size-1 : CElement::Y()+1; //--- Erzeugung des Objektes if(!m_items[i].Create(m_chart_id,name,m_subwin,x,y,w,m_item_y_size)) return(false); //--- Festlegen der Eigenschaften m_items[i].Description(m_value_items[i]); m_items[i].TextAlign(m_align_mode); m_items[i].Font(FONT); m_items[i].FontSize(FONT_SIZE); m_items[i].Color(m_item_text_color); m_items[i].BackColor(m_item_color); m_items[i].BorderColor(m_item_color); m_items[i].Corner(m_corner); m_items[i].Anchor(m_anchor); m_items[i].Selectable(false); m_items[i].Z_Order(m_item_zorder); m_items[i].ReadOnly(true); m_items[i].Tooltip("\n"); //--- Koordinaten m_items[i].X(x); m_items[i].Y(y); //--- Größe m_items[i].XSize(w); m_items[i].YSize(m_item_y_size); //--- Ränder von den Kanten des Panels m_items[i].XGap(x-m_wnd.X()); m_items[i].YGap(y-m_wnd.Y()); //--- Abspeichern des Objekt-Pointers CElement::AddToArray(m_items[i]); } //--- Hervorheben des ausgewählten Elementes HighlightSelectedItem(); //--- Abspeichern des Textes des ausgewählten Elementes m_selected_item_text=m_value_items[m_selected_item_index]; return(true); }
Während der Erzeugung der Scrollbar in der CListView::CreateScrollV() Methode, wird am Anfang das Verhältnis von der gesamten Anzahl der Elemente der Liste zu dem sichtbaren Bereich überprüft. Wenn die gesamte Anzahl von Elementen kleiner oder gleich der Anzahl der Elemente in dem sichtbaren Bereich ist, dann gibt es keinen Grund an dieser Stelle fortzufahren und das Programm verlässt die Methode. Anschließend (1) wird der Pointer des Formulars gespeichert, (2) die Koordinaten werden berechnet und (3) die Eigenschaften werden festgelegt. Der Bezeichner der Scrollbar muss der gleiche sein wie sein übergeordnetes Element. Der Modus des Dropdown Elementes muss ebenfalls der Gleiche sein.
//+---------------------------------------------------------------- //| Erzeugt die vertikale Scrollbar | //+---------------------------------------------------------------- bool CListView::CreateScrollV(void) { //--- Falls die Anzahl der Elemente größer ist als die Größe der Liste, dann // setze die vertikale Scrollbar if(m_items_total<=m_visible_items_total) return(true); //--- Abspeichern des Pointers der Form m_scrollv.WindowPointer(m_wnd); //--- Koordinaten int x=CElement::X()+m_area.X_Size()-m_scrollv.ScrollWidth(); int y=CElement::Y(); //--- Festlegen der Eigenschaften m_scrollv.Id(CElement::Id()); m_scrollv.XSize(m_scrollv.ScrollWidth()); m_scrollv.YSize(CElement::YSize()); m_scrollv.AreaBorderColor(m_area_border_color); m_scrollv.IsDropdown(CElement::IsDropdown()); //--- Erzeugen der Scrollbar if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_items_total,m_visible_items_total)) return(false); //--- return(true); }
Die Größe entlang der Y Achse wird in der CListView::CreateListView() Hauptmethode für die Erzeugung der ListView berechnet. Wie schon erwähnt, muss bei der Berechnung die Überlappung der ListView Elemente berücksichtigt werden. Behalten Sie auch im Hinterkopf, dass sich das Array von Elementen auf jeden Fall innerhalb des Hintergrundes befinden muss, damit es nicht den Rahmen überdeckt.
//+---------------------------------------------------------------- //| Erzeugt das ListView | //+---------------------------------------------------------------- bool CListView::CreateListView(const long chart_id,const int window,const int x,const int y) { //--- Abbrechen, falls es keinen Pointer zum Formular gibt if(::CheckPointer(m_wnd)==POINTER_INVALID) { ::Print(__FUNCTION__," > Before creating the list view, the class must be passed " "the form pointer: CListView::WindowPointer(CWindow &object)"); return(false); } //--- Initialisierung der Variablen m_id =m_wnd.LastId()+1; m_chart_id =chart_id; m_subwin =window; m_x =x; m_y =y; m_y_size =m_item_y_size*m_visible_items_total-(m_visible_items_total-1)+2; //--- Ränder von den Kanten CElement::XGap(m_x-m_wnd.X()); CElement::YGap(m_y-m_wnd.Y()); //--- Erzeugen eines Buttons if(!CreateArea()) return(false); if(!CreateList()) return(false); if(!CreateScrollV()) return(false); //--- Verstecken des Elementes, falls es sich um ein Dialogfenster handelt, oder falls es minimiert ist if(m_wnd.WindowType()==W_DIALOG || m_wnd.IsMinimized()) Hide(); //--- return(true); }
Der Anwender kann selbst entscheiden, ob das Element hervorgehoben wird, sobald sich der Mauszeiger darüber befindet. Diese Funktion ist standardmäßig deaktiviert. Als eine zusätzliche Eigenschaft, erzeugen wir noch eine Methode für das Setzen der Ausrichtung des Textes (1) links ausrichten, (2) rechts ausrichten (3) zentrieren. Standardmäßig wird der Text links ausgerichtet.
class CListView : public CElement { private: //--- Modus für das Hervorheben, falls sich der Mauszeiger darüber befindet bool m_lights_hover; //--- Modus für die Ausrichtung des Textes in der ListView ENUM_ALIGN_MODE m_align_mode; //--- public: //--- (1)Modus für das Hervorheben eines Elementes, wenn sich der Mauszeiger darüber befindet, (2) Ausrichtung des Textes void LightsHover(const bool state) { m_lights_hover=state; } void TextAlign(const ENUM_ALIGN_MODE align_mode) { m_align_mode=align_mode; } }; //+---------------------------------------------------------------- //| Konstruktor | //+---------------------------------------------------------------- CListView::CListView(void) : m_lights_hover(false), m_align_mode(ALIGN_LEFT) { //--- ... }
Bevor die ListView erfolgt wird, muss das Daten Array initialisiert werden. Dafür erzeugen wir die CListView::ValueToList() Methode, die eine Überprüfung der Größe des Arrays durchführt und auch den Index aktualisiert, falls die Größe des Arrays überschritten wird.
class CListView : public CElement { public: //--- Setzen des Wertes in der ListView über den spezifizierten Index der Zeile void ValueToList(const int item_index,const string value); }; //+---------------------------------------------------------------- //| Speichert den übergebenen Wert in der Liste über den angegebenen Index| //+---------------------------------------------------------------- void CListView::ValueToList(const int item_index,const string value) { int array_size=::ArraySize(m_value_items); //--- Falls es keine Elemente in dem Kontextmenü gibt, dann benachrichtigen if(array_size<1) { ::Print(__FUNCTION__," > This method is to be called, " "when the list view contains at least one item!"); } //--- Korrekturen, falls die Größe überschritten wird int i=(item_index>=array_size)? array_size-1 : (item_index <0)? 0 : item_index; //--- Abspeichern des Wertes in der ListView m_value_items[i]=value; }
Nun werden wir einen Test der Einstellungen der ListView mit einer vertikalen Scrollbar durchführen und dann werden wir direkt alle benötigten Methoden für die Verwaltung hinzufügen.
Testen des Setups der ListView
Da die ListView.mqh Datei bereits in der Bibliothek enthalten ist, ist auch die Klasse für das ListView-Element(CListView) bereits in der benutzerdefinierten Klasse zugreifbar. Bevor wir das Einbetten der ListView testen, müssen wir noch einige Ergänzungen in der CWndContainer Klasse vornehmen. Eine ListView ist ein Komponenten Element und daher müssen wir sicherstellen, dass der Scrollbar-Pointer der Elementen-Basis hinzugefügt wird.
Dafür schreiben wir die CWndContainer::AddListViewElements() Methode. Zu Beginn findet eine Überprüfung des Klassennamens statt. Falls sich herausstellt, dass es sich bei diesem Element nicht um eine ListView handelt, dann verläßt das Programm diese Methode. Anschließend, nachdem wir die Größe des gemeinsamen Arrays von Pointern erhöht haben und den Pointer des richtigen Typs erhalten haben, speichern wir ihn ab.
class CWndContainer { private: //--- Speichert den Pointer zu den ListView Objekten in der Basis ab bool AddListViewElements(const int window_index,CElement &object); }; //+---------------------------------------------------------------- //| Speichert den Pointer zu den ListView Objekten in der Basis a | //+---------------------------------------------------------------- bool CWndContainer::AddListViewElements(const int window_index,CElement &object) { //--- Abbrechen, falls es sich nicht um eine ListView handelt if(object.ClassName()!="CListView") return(false); //--- Abfrage des ListView pointers CListView *lv=::GetPointer(object); //--- Vergrößern des Elementen Arrays int size=::ArraySize(m_wnd[window_index].m_elements); ::ArrayResize(m_wnd[window_index].m_elements,size+1); //--- Abfrage des Scrollbar pointers CScrollV *sv=lv.GetScrollVPointer(); //--- Abspeichern des Elementes in der Basis m_wnd[window_index].m_elements[size]=sv; return(true); }
Die CWndContainer::AddListViewElements() Methode wird in der öffentlichen Hauptmethode für das Hinzufügen von Elementen zu der Basis aufgerufen:
//+---------------------------------------------------------------- //| Fügt einen Pointer zu dem Element Array hinzu | //+---------------------------------------------------------------- void CWndContainer::AddToElementsArray(const int window_index,CElement &object) { //--- Falls die Basis keine Formulare für Controls enthält //--- Falls es eine Anfrage für eine nicht existierende Form gibt //--- Hinzufügen zu dem gemeinsamen Array von Elementen //--- Hinzufügen von Element-Objekten zu dem gemeinsamen Array von Objekten //--- Abspeichern der ID von dem letzten Element in allen Forms //--- Erhöhen des Zählers für die Elemente //--- Abspeichern der Pointer zu den Kontextmenü Objekten in der Basis //--- Abspeichern der Pointer zu den Hauptmenü Objekten in der Basis //--- Abspeichern der Pointer der splitbutton Objekte in der Basis //--- Speichert den Pointer zu den Tooltip Objekten in der Basis //--- Speichert den Pointer zu den ListView Objekten in der Basis ab if(AddListViewElements(window_index,object)) return; }
Lassen Sie uns nun den EA aus dem vorherigen Teil dieser Serie für den Test verwenden. Wir lassen hier nur das Hauptmenü zusammen mit dem Kontextmenü und der Statusbar bestehen und die anderen Elemente werden entfernt. Wir erzeugen eine Klasseninstanz in der benutzerdefinierten Klasse, deklarieren die Methode für die Erzeugung eines Elementes und definieren die Ränder von der Ecke des Formulars:
class CProgram : public CWndEvents { private: //--- List view CListView m_listview1; //--- private: //--- List view #define LISTVIEW1_GAP_X (2) #define LISTVIEW1_GAP_Y (43) bool CreateListView1(void); };
Nachfolgend sehen Sie den Programmcode für die Erzeugung der ListView. Unsere Liste beinhaltet 20 Elemente. Aber nur zehn Elemente sind sichtbar. Wir werden die Funktion für das Hervorheben der Elemente, wenn sich der Mauszeigerüber ihnen befindet, aktivieren. Wir selektieren das sechste (5) Element der ListView. Da es sich hier nur um ein Beispiel handelt, füllen wir die Liste mit dem Text «SYMBOL» Mit der Element-Nummer.
//+---------------------------------------------------------------- //| Erzeugt ListView 1 | //+---------------------------------------------------------------- bool CProgram::CreateListView1(void) { //--- Die Größe der ListView #define ITEMS_TOTAL1 20 //--- Abspeichern des Fenster-Pointers m_listview1.WindowPointer(m_window1); //--- Koordinaten int x=m_window1.X()+LISTVIEW1_GAP_X; int y=m_window1.Y()+LISTVIEW1_GAP_Y; //--- Festlegen der Eigenschaften vor der Erzeugung m_listview1.XSize(100); m_listview1.LightsHover(true); m_listview1.ListSize(ITEMS_TOTAL1); m_listview1.VisibleListSize(10); m_listview1.AreaBorderColor(clrDarkGray); m_listview1.SelectedItemIndex(5); //--- Abfrage des Scrollbar pointers CScrollV *sv=m_listview1.GetScrollVPointer(); //--- Eigenschaften der Scrollbar sv.ThumbBorderColor(C'190,190,190'); sv.ThumbBorderColorHover(C'180,180,180'); sv.ThumbBorderColorPressed(C'160,160,160'); //--- Auffüllen der Liste mit Daten for(int r=0; r<ITEMS_TOTAL1; r++) m_listview1.ValueToList(r,"SYMBOL "+string(r)); //--- Erzeugen der ListView if(!m_listview1.CreateListView(m_chart_id,m_subwin,x,y)) return(false); //--- Hinzufügen des Pointers des Elementes zu der Basis CWndContainer::AddToElementsArray(0,m_listview1); return(true); }
Die Methode für das Erzeugen der ListView muss innerhalb der Hauptmethode für das Erzeugen der grafischen Interface-Objekte aufgerufen werden:
//+---------------------------------------------------------------- //| Erzeugung des Trading-Panels | //+---------------------------------------------------------------- bool CProgram::CreateTradePanel(void) { //--- Erzeugen des Formulars 1 für die Controls //---Erzeugung der Controls: // Hauptmenü //--- Kontextmenüs //--- Erzeugen der Statusbar //--- List view if(!CreateListView1()) return(false); //--- Neuzeichnen des Charts m_chart.Redraw(); return(true); }
Jetzt kann das Programm kompiliert und auf einen Chart geladen werden. Wenn wir alles richtig gemacht haben, dann sehen wir ein Ergebnis, wie es der nachfolgende Screenshot zeigt:
Abbildung 2. Test der Einrichtung eines ListView-Elementes
Sie sieht bereits ganz gut aus, aber sie kann zur Zeit noch nicht verwaltet werden und die Objekte reagieren nicht auf die Bewegungen des Mauszeigers. In dem nächsten Teil dieses Artikels werden wir Methoden schreiben, die uns die Verwaltung der ListView ermöglichen.
Methoden für das Verwalten des Elementes
Lassen Sie uns zunächst eine Methode schreiben, die es uns erlaubt die Farbe der Elemente zu verändern, sobald sich der Mauszeiger über ihnen befindet. Dann benötigen wir noch eine Methode die uns die Wiederherstellung der Standardfarben erleichtert.
class CListView : public CElement { public: //--- (1) Zurücksetzen der Farben der ListView-Elemente, (2) Ändern der Farben, sobald sich der Mauszeiger über den ListView-Element befindet void ResetItemsColor(void); void ChangeItemsColor(const int x,const int y); };
Das Zurücksetzen der Farben der Elemente, mit Ausnahme des selektierten Elementes, wird in der CListView::ResetItemsColor() Methode ausgeführt. Zu Beginn der Methode wird die Position des Schiebereglers identifiziert. Diesen Wert erhalten wir über die Variable die zuvor in der Schleife als ein Zähler für das Identifizieren des ausgewählten Elementes diente.
//+---------------------------------------------------------------- //| Zurücksetzen der Farben der ListView-Elemente | //+---------------------------------------------------------------- void CListView::ResetItemsColor(void) { //--- Abfrage der aktuellen Position des Schiebereglers der Scrollbar int v=m_scrollv.CurrentPos(); //--- Durchlaufen der sichtbaren Teile der ListView for(int i=0; i<m_visible_items_total; i++) { //--- Erhöhe den Zähler, solange die Anzahl der ListView Elemente nicht überschritten wurde if(v>=0 && v<m_items_total) v++; //--- Überspringe das ausgewählte Element if(m_selected_item_index==v-1) continue; //--- Festlegen der Farben (Hintergrund, Text) m_items[i].BackColor(m_item_color); m_items[i].Color(m_item_text_color); } }
Zu Beginn der CListView::ChangeItemsColor() Methode müssen noch einige Überprüfungen vorgenommen werden. Das Programm wird die Methode in den folgenden Fällen verlassen:
- Falls das Hervorheben durch den Mauszeiger nicht aktiviert wurde;
- Falls die Scrollbar gerade verwendet wird;
- Falls es sich nicht um einen Dropdown Element handelt und das Formular gesperrt ist.
Anschließen, ähnlich wie bei vielen anderen Methoden dieser Klasse, erhalten wir in der Variable die aktuelle Position der Scrollbar. Diese Variable wird für die Identifizierung des ausgewählten Elementes in der Schleife verwendet und sie wird übersprungen, wenn es keinen Grund für eine Änderung der Farbe gibt. Dieser Methode werden die Koordinaten des Mauszeigers übergeben. Diese Koordinaten Erlaubnis uns festzustellen, über welchem Element sich der Mauszeiger befindet. Nachfolgend wird der detaillierte Programmcode der CListView::ChangeItemsColor() Methode gezeigt.
//+---------------------------------------------------------------- //| Das Verändern der Farben eines ListView-Elementes, wenn sich der Mauszeiger darüber befindet | //+---------------------------------------------------------------- void CListView::ChangeItemsColor(const int x,const int y) { //--- Abbrechen, falls das Hervorheben der Elemente durch den Mauszeiger nicht gewünscht ist oder die Scrollbar gerade verwendet wird if(!m_lights_hover || m_scrollv.ScrollState()) return; //--- Abbrechen, falls es sich nicht um einen DropDown-Element handelt und das Formular gesperrt ist. if(!CElement::IsDropdown() && m_wnd.IsLocked()) return; //--- Abfrage der aktuellen Position des Schiebereglers der Scrollbar int v=m_scrollv.CurrentPos(); //--- Identifizierung und Hervorheben des Elementes, über welchen sich der Mauszeiger gerade befindet for(int i=0; i<m_visible_items_total; i++) { //--- Erhöhe den Zähler, solange die Anzahl der ListView Elemente nicht überschritten wurde if(v>=0 && v<m_items_total) v++; //--- Überspringe das ausgewählte Element if(m_selected_item_index==v-1) continue; //--- Falls sich der Mauszeiger über diesem Element befindet, dann hervorheben if(x>m_items[i].X() && x<m_items[i].X2() && y>m_items[i].Y() && y<m_items[i].Y2()) { m_items[i].BackColor(m_item_color_hover); m_items[i].Color(m_item_text_color_hover); } //--- Falls sich der Mauszeiger nicht über diesem Element befindet, dann weise dem Element die Farben entsprechend seinem Status zu else { m_items[i].BackColor(m_item_color); m_items[i].Color(m_item_text_color); } } }
Nun müssen wir die CListView::ChangeItemsColor() Methode in dem Eventhandler der CListView Klasse verwenden:
//+---------------------------------------------------------------- //| Event handler | //+---------------------------------------------------------------- void CListView::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { if(id==CHARTEVENT_MOUSE_MOVE) { //--- Liste versteckt if(!CElement::IsVisible()) return; //--- Koordinaten int x=(int)lparam; int y=(int)dparam; //--- Verändern der Farbe der ListView Elemente, sobald sich der Mauszeiger über ihnen befinde ChangeItemsColor(x,y); return; } }
Wenn wir das Programm nun testen, dann verändern sich die Farben der ListView Elemente, sobald sich der Mauszeiger über ihnen befindet, so wie es auch in dem nachfolgenden Screenshot gezeigt wird:
Abbildung 3. Test für das Wechseln der Farben der ListView-Elemente, sobald sich der Mauszeiger darüber befindet.
Damit sich die ListView zusammen mit dem Schieberegler der Scrollbar bewegt, schreiben wir die CListView::ShiftList() Methode. Diese Methode speichert ebenfalls zu Beginn die aktuelle Position des Schiebereglers in einer Variable. Ähnlich wie bei der vorherigen Methode, wird diese Variable als Zähler innerhalb der Schleife für das Speichern des ausgewählten Elementes in der ListView und für das Bewegen der Daten verwendet. Sehen Sie sich den nachfolgenden Programmcode an.
class CListView : public CElement { public: //--- Scrollen der ListView void ShiftList(void); }; //+---------------------------------------------------------------- //| Bewegt die ListView entsprechend der Scrollbar | //+---------------------------------------------------------------- void CListView::ShiftList(void) { //--- Abfrage der aktuellen Position des Schiebereglers der Scrollbar int v=m_scrollv.CurrentPos(); //--- Durchlaufen der sichtbaren Teile der ListView for(int i=0; i<m_visible_items_total; i++) { //--- Falls Sie uns innerhalb der Bandbreite der ListView befinden if(v>=0 && v<m_items_total) { //--- Bewegen des Textes, der Hintergrundfarbe und der Textfarbe m_items[i].Description(m_value_items[v]); m_items[i].BackColor((m_selected_item_index==v) ? m_item_color_selected : m_item_color); m_items[i].Color((m_selected_item_index==v) ? m_item_text_color_selected : m_item_text_color); //--- Erhöhung des Zählers v++; } } }
Die CListView::ShiftList() Methode muss in dem CListView::OnEvent() Eventhandler aufgerufen werden, sofern die CScrollV::ScrollBarControl() Methode der Scrollbar true zurück gibt. Dieses bedeutet, dass die Verwaltung des Schiebereglers aktiviert ist.
class CListView : public CElement { private: //--- Status der linken Maustaste (Gedrückt/losgelassen) bool m_mouse_state; }; //+---------------------------------------------------------------- //| Event handler | //+---------------------------------------------------------------- void CListView::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { if(id==CHARTEVENT_MOUSE_MOVE) { //--- Liste versteckt if(!CElement::IsVisible()) return; //--- Koordinaten und Status der linken Maustaste int x=(int)lparam; int y=(int)dparam; m_mouse_state=(bool)int(sparam); //--- Überprüfen des Fokus über der ListView CElement::MouseFocus(x>CElement::X() && x<CElement::X2() && y>CElement::Y() && y<CElement::Y2()); //--- Bewege die Liste, falls die Verwaltung des Schiebereglers aktiviert ist if(m_scrollv.ScrollBarControl(x,y,m_mouse_state)) ShiftList(); //--- Verändern der Farbe der ListView Elemente, sobald sich der Mauszeiger über ihnen befinde ChangeItemsColor(x,y); return; } }
Nach der Kompilierung des Programms, kann die ListView über den Schieberegler der Scrollbar verwaltet werden, so wie es der nachfolgende Screenshot auch zeigt. Alles wurde nun so implementiert, dass auch wenn der Mauszeiger die Grenzen des Schiebereglers nach dem Klick der linken Maustaste verlässt, die Verwaltung and die Scrollbar übergeben wird und der Schieberegler sich entsprechen bewegen lässt.
Abbildung 4. Verwaltung der Liste unter Verwendung des Schiebereglers der Scrollbar.
Nun brauchen wir eine Methode für die Identifizierung eines Klicks auf eines der Elemente der ListView. Lassen Sie uns dafür eine private Methode erzeugen und diese CListView::OnClickListItem() nennen. Zudem brauchen wir die CListView::IdFromObjectName() private Methode für das Extrahieren des Bezeichners des Elementes aus seinem Objektnamen, was wir auch schon in anderen Klassen von anderen Elementen unserer Bibliothek durchgeführt haben.
Zudem brauchen wir auch noch einen eindeutigen Identifizierung für einen Klick auf ein Element der ListView (ON_CLICK_LIST_ITEM). Fügen Sie diesen der Defines.mqh Datei hinzu:
//+---------------------------------------------------------------- //| Defines.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+---------------------------------------------------------------- #define ON_CLICK_LIST_ITEM (16) // Auswählen eines ListView Elementes
Zu Beginn der CListView::OnClickListItem() wird eine Überprüfung des Namens und des Bezeichners des Objektes, auf welchen geklickt wurde, vorgenommen. Anschließend wird der lokalen Variable die aktuelle Position des Schiebereglers zugewiesen. Diese Variable wird als Zähler innerhalb einer Schleife für die Identifizierung des Index und des Textes des Elementes verwendet. Am Ende der Methode wird eine Nachricht gesendet, die (1) den Bezeichner des ON_CLICK_LIST_ITEM Events, (2) den Bezeichner des Elementes und (3) den Text des aktuell selektierten Elementes enthält.
class CListView : public CElement { private: //--- Verarbeitung eines Klicks auf ein Element der ListView bool OnClickListItem(const string clicked_object); //--- Extrahieren des Bezeichners auf dem Namen des ListView Elementes int IdFromObjectName(const string object_name); }; //+---------------------------------------------------------------- //| Verarbeitung eines Klicks auf ein Element der ListView | //+---------------------------------------------------------------- bool CListView::OnClickListItem(const string clicked_object) { //--- Abbrechen, falls der Klick nicht auf diesem Menüpunkt stattgefunden hat if(::StringFind(clicked_object,CElement::ProgramName()+"_listview_edit_",0)<0) return(false); //--- Abfragen des Bezeichners und des Indexes über den Objektnamen int id=IdFromObjectName(clicked_object); //--- Abbrechen, falls der Bezeichner nicht übereinstimmt if(id!=CElement::Id()) return(false); //--- Abfrage der aktuellen Position des Schiebereglers der Scrollbar int v=m_scrollv.CurrentPos(); //--- Gehe über den sichtbaren Teil der ListView for(int i=0; i<m_visible_items_total; i++) { //--- Falls dieses ListView-Element selektiert wurde if(m_items[i].Name()==clicked_object) { m_selected_item_index =v; m_selected_item_text =m_value_items[v]; } //--- Falls Sie uns innerhalb der Bandbreite der ListView befinden if(v>=0 && v<m_items_total) //--- Erhöhung des Zählers v++; } //--- Eine Nachricht darüber senden ::EventChartCustom(m_chart_id,ON_CLICK_LIST_ITEM,CElement::Id(),0,m_selected_item_text); return(true); }
Nun haben wir alle notwendigen Methoden für das Verwalten der ListView. Wir müssen diese nur noch in dem CListView::OnEvent() ListView Eventhandler aufrufen. Ein Klick auf eines der ListView Elemente ruft die CListView::HighlightSelectedItem() Methode auf. In dieser Methode wird das Drücken der Buttons der Scrollbar nachverfolgt. Wenn es einen Klick auf einen dieser Button gab, dann wird die Liste entsprechend des Schiebereglers in die richtige Richtung bewegt.
//+---------------------------------------------------------------- //| Event handler | //+---------------------------------------------------------------- void CListView::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Verarbeitung von Klicks auf Objekte if(id==CHARTEVENT_OBJECT_CLICK) { //--- Falls ein Klick auf ein Element der ListView stattgefunden hat if(OnClickListItem(sparam)) { //--- Hervorheben des Elementes HighlightSelectedItem(); return; } //--- Falls es sich um einen Klick auf einer der Buttons der Scrollbar handelt if(m_scrollv.OnClickScrollInc(sparam) || m_scrollv.OnClickScrollDec(sparam)) { //--- Bewege die Liste entlang der Scrollbar ShiftList(); return; } } }
Schneller Vorlauf der ListView
Wir haben die Entwicklung des minimal benötigten Programmcode für die Verwaltung der ListView abgeschlossen. Wir können die Funktionalität aber noch erweitern. Lassen Sie uns noch eine weitere private Methode schreiben, damit ein Klick und das anschließende Halten des Buttons auf einer Scrollbar zu einem schnellen scrollen der ListView führt.
Wir müssen dafür noch sicherstellen, dass wenn die linke Maustaste gedrückt und gehalten wird, es eine kleine Pause gibt, bevor der schnelle Vorlauf beginnt. Falls wir dieses nicht machen, dann würde der schnelle Vorlauf auch schon bei einem einzigen kurzen Klick auf einer dieser Buttons stattfinden. Der SPIN_DELAY_MSC Bezeichner muss dafür in der Defines.mqh Datei mit dem Wert von -450 hinzugefügt werden. Das bedeutet, dass wir eine Verzögerung von 450 Millisekunden verwenden.
//+---------------------------------------------------------------- //| Defines.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+---------------------------------------------------------------- //--- Verzögerung, bevor der Schnelle Vorlauf stattfindet (Millisekunden) #define SPIN_DELAY_MSC (-450)
Nachfolgend finden Sie den Programmcode der CListView::FastSwitching() Methode. Wir müssen zu denen die m_timer_counter Variable, die als Zeitzähler dient, deklarieren. Zu Beginn der Methode CListView::FastSwitching() überprüfen wir den Fokus der ListView. Falls es keinen Fokus gibt, dann verläßt das Programm die Methode. Anschließend, sobald der die Maustaste losgelassen wurde, wird dem Zähler der Wert der Verzögerung zugewiesen (In unserem Fall ist es -450 ms). Falls die Maustaste gedrückt gehalten wird, dann wird der Wert des Zählers um den Schritt des Timers, den wir in der Bibliothek festgelegt haben (in unserem Fall ist das 16 ms) erhöht.. Dann gibt es eine Bedingung, die das Programm davor schützt weiterzuarbeiten, bis der Zähler größer oder nicht gleich 0 ist. Sobald dieser Zustand eintritt, wird der Status der Scrollbar-Buttons überprüft. Je nachdem, welcher Button gedrückt wurde, wird die Methode für die Initiierung eines wiederholten Klicks auf diesen Button aufgerufen. Anschließend wird die Liste entsprechend der Position des Schiebereglers bewegt.
class CListView : public CElement { private: //--- Zeitzähler für das schnelle scrollen der ListView int m_timer_counter; private: //--- Schneller Vorlauf der ListView void FastSwitching(void); }; //+---------------------------------------------------------------- //| Schneller Vorlauf der Scrollbar | //+---------------------------------------------------------------- void CListView::FastSwitching(void) { //--- Abbrechen, falls es keinen Fokus auf der ListView gibt if(!CElement::MouseFocus()) return; //--- Den Zähler auf den anfänglichen Wert zurücksetzen, falls der Mousebutton losgelassen wird if(!m_mouse_state) m_timer_counter=SPIN_DELAY_MSC; //--- Falls die Maustaste gedrückt wird else { //--- Erhöhen des Zählers um den angegebenen Schritt m_timer_counter+=TIMER_STEP_MSC; //--- Verlassen, falls der kleiner als Null ist if(m_timer_counter<0) return; //--- Falls aufwärts scrollen if(m_scrollv.ScrollIncState()) m_scrollv.OnClickScrollInc(m_scrollv.ScrollIncName()); //--- Falls abwärts scrollen else if(m_scrollv.ScrollDecState()) m_scrollv.OnClickScrollDec(m_scrollv.ScrollDecName()); //--- Bewege die Liste ShiftList(); } }
Die CListView::FastSwitching() Methode muss in der CListView::OnEventTimer() Methode aufgerufen werden. Falls es sich bei der ListView um ein Dropdown-Element handelt, sind keine weiteren Überprüfungen notwendig. Andernfalls müssen wir überprüfen, ob das Formular zur Zeit blockiert ist.
//+---------------------------------------------------------------- //| Timer | //+---------------------------------------------------------------- void CListView::OnEventTimer(void) { //--- Falls es sich um einen DropDown-Element handelt if(CElement::IsDropdown()) //--- Schneller Vorlauf der ListView FastSwitching(); //--- Falls es sich nicht um ein Dropdown-Element handelt, berücksichtige die aktuelle Verfügbarkeit des Formulars else { //--- Verfolge den schnellen Vorlauf der ListView nur, falls das Formular nicht gesperrt ist if(!m_wnd.IsLocked()) FastSwitching(); } }
Nun sind alle Methoden für das Verwalten der ListView fertig. Wir können dieses nun testen. Lassen Sie uns noch zwei weitere ListViews erstellen:
Abbildung 5. Test von drei ListViews in dem grafischen Interface
Wir empfangen die Nachrichten von der ListView in dem Eventhandler der benutzerdefinierten Klasse(CProgram):
//+---------------------------------------------------------------- //| Event handler | //+---------------------------------------------------------------- void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Events über einen Klick auf das ListView-Element if(id==CHARTEVENT_CUSTOM+ON_CLICK_LIST_ITEM) { if(lparam==m_listview1.Id()) ::Print(__FUNCTION__," > This message is from the first list view > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); else if(lparam==m_listview2.Id()) ::Print(__FUNCTION__," > This message is from the second list view > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); else if(lparam==m_listview3.Id()) ::Print(__FUNCTION__," > This message is from the third list view > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); } }
Wenn auf Elemente der ListView geklickt wurde, dann werden entsprechende Nachrichten in dem Journal gezeigt:
2016.01.16 13:02:00.085 TestLibrary (GBPUSD,D1) CProgram::OnEvent > This message is from the first list view > id: 1016; lparam: 7; dparam: 0.0; sparam: SYMBOL 11 2016.01.16 13:01:59.056 TestLibrary (GBPUSD,D1) CProgram::OnEvent > This message is from the third list view > id: 1016; lparam: 9; dparam: 0.0; sparam: SYMBOL 12 2016.01.16 13:01:58.479 TestLibrary (GBPUSD,D1) CProgram::OnEvent > This message is from the second list view > id: 1016; lparam: 8; dparam: 0.0; sparam: SYMBOL 9 2016.01.16 13:01:57.868 TestLibrary (GBPUSD,D1) CProgram::OnEvent > This message is from the third list view > id: 1016; lparam: 9; dparam: 0.0; sparam: SYMBOL 19 2016.01.16 13:01:56.854 TestLibrary (GBPUSD,D1) CProgram::OnEvent > This message is from the second list view > id: 1016; lparam: 8; dparam: 0.0; sparam: SYMBOL 4 2016.01.16 13:01:56.136 TestLibrary (GBPUSD,D1) CProgram::OnEvent > This message is from the first list view> id: 1016; lparam: 7; dparam: 0.0; sparam: SYMBOL 9 2016.01.16 13:01:55.433 TestLibrary (GBPUSD,D1) CProgram::OnEvent > This message is from the first list view > id: 1016; lparam: 7; dparam: 0.0; sparam: SYMBOL 14
Schlussfolgerung
In diesem Artikel haben wir das Komponenten-Control ListView besprochen. Zudem haben wir gezeigt, wie eine vertikale Scrollbar verwendet werden kann. In den nächsten Artikel werden wir uns mit einem weiteren Komponenten-Control beschäftigen, der Combobox.
Sie können das gesamte Material des fünften Teils herunterladen und testen. Wenn Sie fragen zur Verwendung dieses Materials haben, dann können Sie zunächst auf die detaillierte Beschreibung in dem Artikel zu dieser Bibliothek zurückgreifen oder Sie stellen Ihre Frage(n) in den Kommentaren zu diesem Artikel.
Liste der Artikel des fünften Teils:
- Grafische Interfaces V: Die vertikale und horizontale Scrollbar (Kapitel 1)
- Grafische Interfaces V: Das ListView-Element (Kapitel 2)
- Grafische Interfaces V: Das Combobox Control (Kapitel 3)
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/2380





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