English Русский 中文 Español 日本語 Português
Grafische Interfaces V: Das ListView-Element (Kapitel 2)

Grafische Interfaces V: Das ListView-Element (Kapitel 2)

MetaTrader 5Beispiele | 7 Juli 2016, 16:47
615 0
Anatoli Kazharski
Anatoli Kazharski

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

  1. Der Hintergrund der ListView
  2. Array mit Elementen der ListView.
  3. 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

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. 

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.

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 

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:

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/2380

Beigefügte Dateien |
Die Erstellung eines Helfers im manuellen Handeln Die Erstellung eines Helfers im manuellen Handeln
Die Anzahl der Handelsroboter für die Arbeit an Devisenmärkten nimmt in den letzten Jahren lawinenartig zu. In den Robotern werden verschiedene Konzepte und Strategien umgesetzt, keinem ist aber bis jetzt gelungen, eine gewinnsichere künstliche Intelligenz zu entwilckeln. Aus diesem Grund bleiben viele Trader manuellem Handel treu. Aber auch für sie werden Assistenten, die sogenannten Trading Panels erstellt. Dieser Artikel stellt ein Beispiel für die Erstellung eines solchen Panels von Grund auf dar.
Grafische Interfaces V: Die vertikale und horizontale Scrollbar (Kapitel 1) Grafische Interfaces V: Die vertikale und horizontale Scrollbar (Kapitel 1)
Wir besprechen weiterhin die Entwicklung der Bibliothek für die Erzeugung von grafischen Interfaces innerhalb der Metatrader-Umgebung. In dem ersten Artikel des fünften Teils dieser Serie, werden wir Klassen für die Erzeugung von vertikalen und horizontalen Scrollbars besprechen.
Lifehack für Händler: Indikatoren für Balance, Drawdown, Belastung und Ticks während des Testens Lifehack für Händler: Indikatoren für Balance, Drawdown, Belastung und Ticks während des Testens
Wie man einen Test mehr anschaulich machen kann? Die Antwort ist einfach: Sie müssen im Tester einen oder mehreren Indikatoren verwenden - der Tick-Indikator, der Indikator der Balance und Equity, der Indikator des Drawdowns und der Belastung des Deposites. Dies wird visuell ermöglichen, die Art der Ticks zu verfolgen, oder die Änderungen in der Balance und Equity oder im Drawdown und der Belastung des Deposites zu sehen.
Grafische Interfaces IV: Der Multi-Window-Modus und das System für Prioritäten (Kapitel 2) Grafische Interfaces IV: Der Multi-Window-Modus und das System für Prioritäten (Kapitel 2)
In diesem Kapitel werden wir die Bibliothek um die Möglichkeit der Erzeugung von Multi-Window-Modus-Interfaces für MQL Anwendungen erweitern. Wir werden zudem ein System für die Priorität eines Klicks mit der linken Maustaste auf grafische Objekte entwickeln. Dieses ist notwendig um Probleme zu vermeiden, falls der Anwender auf ein grafisches Element klickt und dieses nicht reagiert.