Grafische Interfaces X: Text Edit Box, Bild Slider und einfache Controls (build 5)

Anatoli Kazharski | 16 Januar, 2017


Inhalt

Einleitung

Damit sie diese Bibliothek besser verstehen können, lesen Sie bitte den ersten Artikel: Grafische Interfaces I: Vorbereiten der Bibliotheksstruktur (Kapitel 1). 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.

Dieser Artikel beschreibt neue Controls: Text Edit Box, Bild Slider, Sowie zusätzliche einfache Controls: Text Label und Bild, welche in vielen Fällen hilfreich sein können. Die Bibliothek wächst weiter, und neben der Einführung der neuen Steuerelemente, werden auch die zuvor erstellten verbessert. Da diese Bibliothek bereits von einer größeren Anzahl von Anwendern verwendet wird, haben wir auch schon verschiedene Kommentare und Vorschläge erhalten. Viele dieser Vorschläge wurden in der neuen Version der Bibliothek implementiert. Zusätzlich wurden verschiedene Algorithmen optimiert. Dieses hat die CPU-Auslastung weiter verringert. Weitere Informationen dazu finden Sie in diesem Artikel.

 

Das Text Edit Box Control

Die hier entwickelte Bibliothek enthält bereits ein Edit Box Control (die CSpinEdit Klasse), aber diese wurde nur für numerische Eingaben entwickelt. Jetzt wird die Bibliothek um ein weiteres Control erweitert, welches es auch erlaubt, jede Art von Text einzugeben. Das Text Edit Box Control wird in verschiedensten Situationen benötigt. Zum Beispiel könnte man hier einen Suchstring für Dateien im Terminal eingeben "sandbox". Eine weitere Möglichkeit wäre, es dem Anwender zu ermöglichen eine Reihe von Symbolen zum Handeln einzugeben. Kurz gesagt, hier kann jeder benötigte Text eingegeben werden.

Lassen Sie uns nun alle Elemente des Text Edit box control auflisten:

  1. Hintergrund
  2. Icon
  3. Beschreibung:
  4. Edit box

 

Abbildung 1. Komponenten des Text Edit box Controls.

Lassen Sie uns die Klasse dieses Controls näher anschauen.

 

Klasse für die Erzeugung des Text Edit Box Controls

Erzeugen Sie die TextEdit.mqh Datei mit der CTextEdit Klasse mit allen Standardmethoden, die wir auch für alle anderen Kontos benötigen und beziehen Sie diese in der ( WndContainer.mqh Datei mit ein). Nachfolgend sehen Sie die Eigenschaften des Controls für die benutzerdefinierten Einstellungen:

  • Die Farbe des Control-Hintergrundes
  • Control Icons für den aktiven und den gesperrten Status
  • Abstände für das Icon entlang der beiden Achsen (x, y)
  • Beschreibender Text für das Control
  • Abstände für das textlabel entlang der zwei Achsen (x, y)
  • Farben des Textes für die unterschiedlichen Zustände des controls
  • Die Größe der Editbox
  • Abstände für die Editbox entlang der zwei Achsen (x, y)
  • Farben für die Editbox und den Text der Editbox in unterschiedlichen Zuständen
  • Ausrichtung des Textes in der Editbox (left/right/center)
  • Anzeigemodus des Text-Auswahl-Cursors
  • Modus für das Zurücksetzen des Wertes in der Editbox
//+------------------------------------------------------------------+
//| Klasse für das Erzeugen der Text-Edit-Box                      |
//+------------------------------------------------------------------+
class CTextEdit : public CElement
  {
private:
   //--- Farbe des Hintergrundes
   color             m_area_color;
   //--- Die control icons in dem aktiven und dem gesperrten Status
   string            m_icon_file_on;
   string            m_icon_file_off;
   //--- Icon Abstände
   int               m_icon_x_gap;
   int               m_icon_y_gap;
   //--- Text der Beschreibung der Editbox
   string            m_label_text;
   //--- Abstände des Text-Labels
   int               m_label_x_gap;
   int               m_label_y_gap;
   //--- Die Farbe des Textes in den unterschiedlichen Zuständen
   color             m_label_color;
   color             m_label_color_hover;
   color             m_label_color_locked;
   color             m_label_color_array[];
   //--- Aktueller Wert der Editbox
   string            m_edit_value;
   //--- Die Größe der Edit box
   int               m_edit_x_size;
   int               m_edit_y_size;
   //--- Abstände für die Edit box
   int               m_edit_x_gap;
   int               m_edit_y_gap;
   //--- Farben für die Editbox und den Text der Editbox in den unterschiedlichen Zuständen
   color             m_edit_color;
   color             m_edit_color_locked;
   color             m_edit_text_color;
   color             m_edit_text_color_locked;
   color             m_edit_text_color_highlight;
   //--- Die Farben des Editbox-Rahmens in den unterschiedlichen Zuständen
   color             m_edit_border_color;
   color             m_edit_border_color_hover;
   color             m_edit_border_color_locked;
   color             m_edit_border_color_array[];
   //--- Modus für das Zurücksetzen des Wertes (leerer string)
   bool              m_reset_mode;
   //--- Display Modus für den Textauswahl Pointer
   bool              m_show_text_pointer_mode;
   //--- Modus für die Textausrichtung
   ENUM_ALIGN_MODE   m_align_mode;
   //---
public:
   //--- Icon Abstände
   void              IconXGap(const int x_gap)                      { m_icon_x_gap=x_gap;                 }
   void              IconYGap(const int y_gap)                      { m_icon_y_gap=y_gap;                 }
   //--- (1) Hintergrundfarbe, (2) Text der Beschreibung der Editbox, (3) Abstände des Text-Labels
   void              AreaColor(const color clr)                     { m_area_color=clr;                   }
   string            LabelText(void)                          const { return(m_label.Description());      }
   void              LabelText(const string text)                   { m_label.Description(text);          }
   void              LabelXGap(const int x_gap)                     { m_label_x_gap=x_gap;                }
   void              LabelYGap(const int y_gap)                     { m_label_y_gap=y_gap;                }
   //--- Die Farbe des Text Labels in den unterschiedlichen Zuständen
   void              LabelColor(const color clr)                    { m_label_color=clr;                  }
   void              LabelColorHover(const color clr)               { m_label_color_hover=clr;            }
   void              LabelColorLocked(const color clr)              { m_label_color_locked=clr;           }
   //--- (1) Die Größe der Editbox, (2) Abstand der Editbox von der rechten Seite
   void              EditXSize(const int x_size)                    { m_edit_x_size=x_size;               }
   void              EditYSize(const int y_size)                    { m_edit_y_size=y_size;               }
   //--- Abstände für die Editbox
   void              EditXGap(const int x_gap)                      { m_edit_x_gap=x_gap;                 }
   void              EditYGap(const int y_gap)                      { m_edit_y_gap=y_gap;                 }
   //--- Farben für die editbox in den unterschiedlichen Zuständen
   void              EditColor(const color clr)                     { m_edit_color=clr;                   }
   void              EditColorLocked(const color clr)               { m_edit_color_locked=clr;            }
   //--- Farben für den editbox-Text in den unterschiedlichen Zuständen
   void              EditTextColor(const color clr)                 { m_edit_text_color=clr;              }
   void              EditTextColorLocked(const color clr)           { m_edit_text_color_locked=clr;       }
   void              EditTextColorHighlight(const color clr)        { m_edit_text_color_highlight=clr;    }
   //--- Farben für den Rahmen der editbox in den unterschiedlichen Zuständen
   void              EditBorderColor(const color clr)               { m_edit_border_color=clr;            }
   void              EditBorderColorHover(const color clr)          { m_edit_border_color_hover=clr;      }
   void              EditBorderColorLocked(const color clr)         { m_edit_border_color_locked=clr;     }
   //--- (1) Reset Modus, wenn auf das textlabel geklickt wird, (2) Anzeigemodus für den Textauswahl Pointer
   bool              ResetMode(void)                                { return(m_reset_mode);               }
   void              ResetMode(const bool mode)                     { m_reset_mode=mode;                  }
   void              ShowTextPointerMode(const bool mode)           { m_show_text_pointer_mode=mode;      }
   //--- Modus für die Ausrichtung des Textes
   void              AlignMode(ENUM_ALIGN_MODE mode)                { m_align_mode=mode;                  }
   //--- Festlegen der Icons für den Button in dem aktiven und dem gesperrten Status
   void              IconFileOn(const string file_path);
   void              IconFileOff(const string file_path);
  };

Anzeigemodus für den Textauswahl Pointer bedeutet, dass der Mauszeiger durch ein zusätzliches Symbol ergänzt werden soll, wenn er sich über dem Bearbeitungsfeld befindet und somit darauf hinweist, dass ein Text eingegeben werden kann. Damit dieses funktioniert, benötigen wir einen weiteren Bezeichner (MP_TEXT_SELECT) , der der ENUM_MOUSE_POINTER Enumeration hinzugefügt werden muss.

//+------------------------------------------------------------------+
//| Enumeration der Pointer Typen |
//+------------------------------------------------------------------+
enum ENUM_MOUSE_POINTER
  {
   MP_CUSTOM      =0,
   MP_X_RESIZE    =1,
   MP_Y_RESIZE    =2,
   MP_XY1_RESIZE  =3,
   MP_XY2_RESIZE  =4,
   MP_X_SCROLL    =5,
   MP_Y_SCROLL    =6,
   MP_TEXT_SELECT =7
  };

Die entsprechenden Ergänzungen wurden ebenfalls in der Klasse CPointer durchgeführt. (Sehen Sie sich dazu den nachfolgenden Programmcode an). Das entsprechende Bild für den Cursor bei einer Textauswahl, finden Sie am Ende dieses Artikels. 

//+------------------------------------------------------------------+
//|                                                      Pointer.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
//--- Resources
...
#resource "\\Images\\EasyAndFastGUI\\Controls\\pointer_text_select.bmp"

//+------------------------------------------------------------------+
//| Festlegen der Icons für den Cursor entsprechend seinem Typ                |
//+------------------------------------------------------------------+
void CPointer::SetPointerBmp(void)
  {
   switch(m_type)
     {
      case MP_X_RESIZE :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_x_rs_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_x_rs.bmp";
         break;
      case MP_Y_RESIZE :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_y_rs_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_y_rs.bmp";
         break;
      case MP_XY1_RESIZE :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_xy1_rs_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_xy1_rs.bmp";
         break;
      case MP_XY2_RESIZE :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_xy2_rs_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_xy2_rs.bmp";
         break;
      case MP_X_SCROLL :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_x_scroll_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_x_scroll.bmp";
         break;
      case MP_Y_SCROLL :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_y_scroll_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_y_scroll.bmp";
         break;
      case MP_TEXT_SELECT :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_text_select.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_text_select.bmp";
         break;

     }
//--- Falls ein benutzerdefinierter Typ (MP_CUSTOM) angegeben wurde
   if(m_file_on=="" || m_file_off=="")
      ::Print(__FUNCTION__," > Both icons must be set for the cursor!");
  }

Für die Erzeugung des Text Edit box Controls, Benötigen wir fünf private und eine public Methoden: 

class CTextEdit : public CElement
  {
private:
   //--- Objekte für die Erzeugung der EditBox
   CRectLabel        m_area;
   CBmpLabel         m_icon;
   CLabel            m_label;
   CEdit             m_edit;
   CPointer          m_text_select;
   //---
public:
   //--- Methoden für die Erzeugung der Text Edit Box
   bool              CreateTextEdit(const long chart_id,const int subwin,const string label_text,const int x,const int y);
   //---
private:
   bool              CreateArea(void);
   bool              CreateIcon(void);
   bool              CreateLabel(void);
   bool              CreateEdit(void);
   bool              CreateTextSelectPointer(void);
  };


Der Rest der CTextEdit beinhalten nichts, was dir nicht schon in den vorherigen Artikel dieser Serie besprochen haben. Daher können Sie diese Fähigkeiten selbst untersuchen.. Die aktuelle Version der Text Edit box hat eine Begrenzung auf 63 Zeichen

 

Das Bild Slider Control

Der Bild-Slider gehört zu den informierenden Controls des grafischen Interfaces. Es ist sinnvoll, eine Kurzanleitung zu schaffen, wo Illustrationen für bestimmte Situationen bei Kurs-Charts oder kurze Erklärungen über den Zweck des Steuerelementes der grafischen Oberfläche in der benutzten MQL Applikation zeigen. 

Lassen Sie uns alle Komponenten des Bild-Slider-Controls aufzählen:

  1. Hintergrund
  2. Slider Pfeil-Buttons
  3. Gruppe von Radio buttons
  4. Gruppe von Bildern in Verbindung mit der Gruppe von Radio buttons

 

Abbildung 2. Komponenten des Bild-Slider-Controls.

 

Klasse für die Erzeugung des Bild Slider Controls

Erzeugen Sie die PicturesSlider.mqh Datei mit den Standardmethoden, wie sie auch in den anderen Klassen vorhanden sind, und beziehen Sie sie in der WndContainer.mqh Datei mit ein. Nachfolgend sehen Sie die Eigenschaften des Controls, die von dem Benutzer verändert werden können.

  • Die Farbe des Control-Hintergrundes
  • Rahmenfarbe des Hintergrundes
  • Abstand für das Bild entlang der y-Achse
  • Abstand für die Slider-Pfeil-Buttons entlang der zwei Achsen
  • Abstände für die Radiobuttons entlang der zwei Achsen (x, y)
  • Abstände zwischen den Radiobuttons
//+------------------------------------------------------------------+
//| Klasse für die Erzeugung des Bild-Sliders                            |
//+------------------------------------------------------------------+
class CPicturesSlider : public CElement
  {
private:
   //--- Rahmenfarbe des Hintergrundes
   color             m_area_color;
   color             m_area_border_color;
   //--- Abstände der Bilder entlang der y-Achse
   int               m_pictures_y_gap;
   //--- Abstände für die Buttons
   int               m_arrows_x_gap;
   int               m_arrows_y_gap;
   //--- Abstände für die Radiobuttons
   int               m_radio_buttons_x_gap;
   int               m_radio_buttons_y_gap;
   int               m_radio_buttons_x_offset;
   //---
public:
   //--- (1) Farbe des Hintergrundes und(2) des Rahmens des Hintergrundes
   void              AreaColor(const color clr)              { m_area_color=clr;                      }
   void              AreaBorderColor(const color clr)        { m_area_border_color=clr;               }
   //--- Abstände für die Pfeil Buttons
   void              ArrowsXGap(const int x_gap)             { m_arrows_x_gap=x_gap;                  }
   void              ArrowsYGap(const int y_gap)             { m_arrows_y_gap=y_gap;                  }
   //--- Abstand für die Bilder entlang der y-Achse
   void              PictureYGap(const int y_gap)            { m_pictures_y_gap=y_gap;                }
   //--- (1) Abstände der Radiobuttons, (2) Abstand zwischen den Radiobuttons
   void              RadioButtonsXGap(const int x_gap)       { m_radio_buttons_x_gap=x_gap;           }
   void              RadioButtonsYGap(const int y_gap)       { m_radio_buttons_y_gap=y_gap;           }
   void              RadioButtonsXOffset(const int x_offset) { m_radio_buttons_x_offset=x_offset;     }
  };

 To create the Picture Slider control, five private and one public methods will be needed:

class CPicturesSlider : public CElement
  {
private:
   //--- Objekte für die Erzeugung des Controls
   CRectLabel        m_area;
   CBmpLabel         m_pictures[];
   CRadioButtons     m_radio_buttons;
   CIconButton       m_left_arrow;
   CIconButton       m_right_arrow;
   //---
public:
   //--- Methoden für die Erzeugung des Bild-Sliders
   bool              CreatePicturesSlider(const long chart_id,const int subwin,const int x,const int y);
   //---
private:
   bool              CreateArea(void);
   bool              CreatePictures(void);
   bool              CreateRadioButtons(void);
   bool              CreateLeftArrow(void);
   bool              CreateRightArrow(void);
  };

Die Breite des Controls wird automatisch berechnet, basierend auf den benutzerdefinierten Angaben. Zu den Parametern gehören die Abstände der Gruppe der Radiobuttons von der linken Ecke des Controls, unter Berücksichtigung der Koordinate für den rechten Pfeilbutton des Bild Sliders. Die Höhe des Controls hängt von der Größe des Bildes ab Es wird angenommen, dass alle Bilder die gleiche Größe haben, daher werden die Berechnung über die Größe des ersten Bildes durchgeführt.

Bevor die Hauptmethode für die Erzeugung des controls aufgerufen werden kann, müssen die Bilder den Array unter Verwendung der CPicturesSlider::AddPicture() Methode hinzugefügt werden. Wenn kein Pfad angegeben worden ist, dann wird derdefault Pfad verwendet.  

//+------------------------------------------------------------------+
//|                                               PicturesSlider.mqh |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
...
//--- Standard-Bild
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp"
//+------------------------------------------------------------------+
//| Klasse für die Erzeugung des Bild Sliders                            |
//+------------------------------------------------------------------+
class CPicturesSlider : public CElement
  {
private:
   //--- Array mit Bildern (Pfad zu den Bildern)
   string            m_file_path[];
   //--- Standardpfad zu den Bildern
   string            m_default_path;
   //---
public:
   //--- Bild hinzufügen
   void              AddPicture(const string file_path="");
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPicturesSlider::CPicturesSlider(void) : m_default_path("Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp"),
                                         m_area_color(clrNONE),
                                         m_area_border_color(clrNONE),
                                         m_arrows_x_gap(2),
                                         m_arrows_y_gap(2),
                                         m_radio_button_width(12),
                                         m_radio_buttons_x_gap(25),
                                         m_radio_buttons_y_gap(1),
                                         m_radio_buttons_x_offset(20),
                                         m_pictures_y_gap(25)
  {
//--- Abspeichern des Namens der Control-Klasse in der Basisklasse
   CElement::ClassName(CLASS_NAME);
//--- Festlegen der Prioritäten eines Klicks mit der linken Maustaste
   m_zorder=0;
  }
//+------------------------------------------------------------------+
//| Bild hinzufügen                                                |
//+------------------------------------------------------------------+
void CPicturesSlider::AddPicture(const string file_path="")
  {
//--- Vergrößern der Größe des Arrays um ein Element
   int array_size=::ArraySize(m_pictures);
   int new_size=array_size+1;
   ::ArrayResize(m_pictures,new_size);
   ::ArrayResize(m_file_path,new_size);
//--- Abspeichern der Werte der übergebenen Parameter
   m_file_path[array_size]=(file_path=="")? m_default_path : file_path;
  }

Um ein Bild aus der Gruppe darstellen zu können, verwenden Sie die CPicturesSlider::SelectPicture() Methode. Diese Methode wird in dem Eventhandler der CPicturesSlider Klasse aufgerufen, wenn Sie einen Pfeil-button oder Radiobutton drücken.  

class CPicturesSlider : public CElement
  {
public:
   //--- Schaltet das Bild an dem angegebenen Index
   void              SelectPicture(const uint index);
  };
//+------------------------------------------------------------------+
//| Gibt an, dass das Bild dargestellt werden soll                    |
//+------------------------------------------------------------------+
void CPicturesSlider::SelectPicture(const uint index)
  {
//--- Abfrage der Anzahl der Bilder
   uint pictures_total=PicturesTotal();
//--- Falls es kein Bild gibt, dann benachrichtigen
   if(pictures_total<1)
     {
      ::Print(__FUNCTION__," > This method is to be called, "
              "if a group contains at least one picture! Use the CPicturesSlider::AddPicture() method");
      return;
     }
//--- Korrigiere den Wert des Indexes, falls die Größe des Arrays überschritten wird
   uint correct_index=(index>=pictures_total)? pictures_total-1 : index;
//--- Wähle den radio button an diesem Index aus
   m_radio_buttons.SelectRadioButton(correct_index);
//--- Wechsle zu dem Bild
   for(uint i=0; i<pictures_total; i++)
     {
      if(i==correct_index)
         m_pictures[i].Timeframes(OBJ_ALL_PERIODS);
      else
         m_pictures[i].Timeframes(OBJ_NO_PERIODS);
     }
  }

Wenn ein Pfeil-Button gedrückt wird, dann ruft der Eventhandler des Controls die CPicturesSlider::OnClickLeftArrow() und CPicturesSlider::OnClickRightArrow() Methoden auf. Der nachfolgende Programmcode zeigt die Methode für die linke Maustaste. Falls gewünscht, können die Events über Klicks auf den Slider button in der benutzerdefinierten Klasse der MQL Anwendung nachverfolgt werden. 

class CPicturesSlider : public CElement
  {
public:
private:
   //--- Verarbeiten eines Klicks auf die linken Maustaste
   bool              OnClickLeftArrow(const string clicked_object);
   //--- Verarbeiten eines Klicks auf die rechte Maustaste
   bool              OnClickRightArrow(const string clicked_object);
  };
//+------------------------------------------------------------------+
//| Klick auf die linke Maustaste                                   |
//+------------------------------------------------------------------+
bool CPicturesSlider::OnClickLeftArrow(const string clicked_object)
  {
//--- Abbrechen, falls der Klick nicht auf den Button stattgefunden hat
   if(::StringFind(clicked_object,CElement::ProgramName()+"_icon_button_",0)<0)
      return(false);
//--- Abfrage des Bezeichners über den Namen des Objektes
   int id=CElement::IdFromObjectName(clicked_object);
//--- Abfrage des Index des Controls über den Namen des Objektes
   int index=CElement::IndexFromObjectName(clicked_object);
//--- Abbrechen, wenn die Bezeichner nicht übereinstimmen
   if(id!=CElement::Id())
      return(false);
//--- Abbrechen, wenn die Indizes nicht übereinstimmen
   if(index!=0)
      return(false);
//--- Abfrage des aktuellen Index des ausgewählten radio buttons
   int selected_radio_button=m_radio_buttons.SelectedButtonIndex();
//--- Wechsle das Bild
   SelectPicture(--selected_radio_button);
//--- Sende eine Nachricht darüber
   ::EventChartCustom(m_chart_id,ON_CLICK_BUTTON,CElement::Id(),CElement::Index(),"");
   return(true);
  }

Der nachfolgende Programmcode zeigt eine verkürzte Fassung von dem Eventhandler des Bild-Sliders Es ist offensichtlich, dass die Ereignisse eines Clicks auf die radio buttons des Sliders hier ebenfalls erfasst werden. Über die Bezeichner kann man ganz einfach verstehen, dass ein Radiobutton in einer lokalen Gruppe geklickt wurde, da dieser gleich dem Bezeichner des Bild-Sliders ist

//+------------------------------------------------------------------+
//| Event handler                                               |
//+------------------------------------------------------------------+
void CPicturesSlider::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Verarbeiten eines Events über die Bewegung des Mauszeigers
...
//--- Verarbeiten eines Events von einem Klick auf einen Radio button
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      //--- Wenn es sich um einen radio button des Sliders handelt, dann wechsle das Bild
      if(lparam==CElement::Id())
         SelectPicture(m_radio_buttons.SelectedButtonIndex());
      //---
      return;
     }
//--- Verarbeiten eines Klicks mit der linken Maustaste auf das Objekt
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Falls auf ein Pfeil-Button des Sliders geklickt wurde, wechsle das Bild
      if(OnClickLeftArrow(sparam))
         return;
      if(OnClickRightArrow(sparam))
         return;
      //---
      return;
     }
  }

 

Das Text Label und Bild Control

Als Zugabe besitzt die Bibliothek nun zwei neue CTextLabel und CPicture Klassen für die Erzeugung von einfachen Text-Labels und Bild-Controls. Sie können als einzelne separate Objekte verwendet werden, ohne Bindung zu irgendeinem anderen Control. Deren Inhalt ist sehr einfach. In der CPicture Klasse können die Anwender nur eine Eigenschaft ändern - Den Pfad zu dem Bild. Die CPicture::Path() Methode wurde für diesen Fall implementiert. Wenn kein Pfad angegeben wurde, wird das Standardbild verwendet. Das Bild kannst zu jeder Zeit programmtechnisch verändert werden, auch nach der Erzeugung des grafischen Interfaces der MQL Anwendung

//+------------------------------------------------------------------+
//|                                                      Picture.mqh |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
#include "Window.mqh"
//--- Resources
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp"
//+------------------------------------------------------------------+
//| Klasse für die Erzeugung des Bildes                                       |
//+------------------------------------------------------------------+
class CPicture : public CElement
  {
private:
   //--- Pfad zu dem Bild
   string            m_path;
   //---
public:
   //--- Festlegen und Abfragen des Pfades zu dem Bild
   string            Path(void)               const { return(m_path);             }
   void              Path(const string path);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPicture::CPicture(void) : m_path("Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp")

  {
//--- Abspeichern des Namens der Control Klasse in der Basisklasse
   CElement::ClassName(CLASS_NAME);
//--- Festlegen der Prioritäten eines Klicks mit der linken Maustaste
   m_zorder=0;
  }
//+------------------------------------------------------------------+
//| Festlegen des Bildes                                                |
//+------------------------------------------------------------------+
void CPicture::Path(const string path)
  {
   m_path=path;
   m_picture.BmpFileOn("::"+path);
   m_picture.BmpFileOff("::"+path);
  }

Wie auch bei dem Text Label Control, ist hier alles sehr einfach und nur vier Eigenschaften können von dem User definiert werden:

  • Text des Labels
  • Die Textfarbe
  • Schrifttyp
  • Schriftgröße
//+------------------------------------------------------------------+
//| Klasse für die Erzeugung des Text Label                                |
//+------------------------------------------------------------------+
class CTextLabel : public CElement
  {
public:
   //--- Festlegen oder Abfragen des Textes des Labels
   string            LabelText(void)             const { return(m_label.Description()); }
   void              LabelText(const string text)      { m_label.Description(text);     }
   //--- Festlegen der (1) Farbe, (2) Schrift und (3) Schriftgröße des Textlabels
   void              LabelColor(const color clr)       { m_label.Color(clr);            }
   void              LabelFont(const string font)      { m_label.Font(font);            }
   void              LabelFontSize(const int size)     { m_label.FontSize(size);        }
  };

 

CFonts Klasse für das Arbeiten mit Schriften

Um die Schriftart-Auswahl zu erleichtern, wurde eine zusätzliche CFonts -Klasse implementiert. Sie enthält 187 Schriften. Dieses sind die Systemschriftarten des Terminals, die sie sicherlich schon bei den Einstellungen von verschiedenen grafischen Objekten gesehen haben.

 Abbildung 3. Systemschriftarten des Terminals.

Abbildung 3. Systemschriftarten des Terminals.

Die Datei mit den Schriftarten (Fonts.mqh) Finden Sie in dem folgenden Verzeichnis "MetaTrader 5\MQL5\Include\EasyAndFastGUI\Fonts.mqh". Diese wurde in der Objects.mqh Datei miteinbezogen, damit sie vollständigen Zugriff innerhalb der ganzen Bibliothek haben:

//+------------------------------------------------------------------+
//|                                                      Objects.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Enums.mqh"
#include "Defines.mqh"
#include "..\Fonts.mqh"
#include "..\Canvas\Charts\LineChart.mqh"
#include <ChartObjects\ChartObjectSubChart.mqh>
#include <ChartObjects\ChartObjectsBmpControls.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>

Die CFonts beinhaltet nur zwei öffentliche Methoden für Abfrage der Größe des Arrays für die Schriften und die Abfrage des Names der Schrift über den Index. Das Array mit den Schriftarten wird in dem Klassenkonstruktor initialisiert

//+------------------------------------------------------------------+
//|                                                        Fonts.mqh |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Klasse für das Arbeiten mit Schriften                                      |
//+------------------------------------------------------------------+
class CFonts
  {
private:
   //--- Array der Schriften
   string            m_fonts[];
   //---
public:
                     CFonts(void);
                    ~CFonts(void);
   //--- Gibt die Anzahl der Schriften zurück
   int               FontsTotal(void) const { return(::ArraySize(m_fonts)); }
   //--- Gibt die Schrift über den Index zurück
   string            FontsByIndex(const uint index);
   //---
private:
   //--- Initialisierung des Arrays für Schriften
   void              InitializeFontsArray(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CFonts::CFonts(void)
  {
//--- Initialisierung des Arrays für Schriften
   InitializeFontsArray();
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CFonts::~CFonts(void)
  {
   ::ArrayFree(m_fonts);
  }

Der Aufruf der CFonts::FontsByIndex()startet die Justage des Arrays um ein Überschreiten der Grenzen auszuschließen:

//+------------------------------------------------------------------+
//| Gibt die Schrift über den Index zurück                                       |
//+------------------------------------------------------------------+
string CFonts::FontsByIndex(const uint index)
  {
//--- Array-Größe
   uint array_size=FontsTotal();
//--- Korrektur, falls die Grenzen überschritten wurden
   uint i=(index>=array_size)? array_size-1 : index;
//--- Rückgabe der Schrift
   return(m_fonts[i]);
  }

 

Eine Liste über weitere Updates der Bibliothek

1. Fehlerbehebung der nicht korrekten Anzeige der Tooltips in den Dialog Boxen. Jetzt wird auch der gedrückte Status eines Tooltip-Buttons in dem Hauptfenster zu allen Fenstern des grafischen Interfaces weitergeleitet Ein Klick auf diesen Button erzeugt eine Nachricht mit dem neuen ON_WINDOW_TOOLTIPS Event-Bezeichner (Schauen Sie dazu auch in die Defines.mqh Datei).

//+------------------------------------------------------------------+
//|                                                      Defines.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
...
#define ON_WINDOW_TOOLTIPS         (29) // Klick auf einen Tooltip button

Entsprechend wurde die OnClickTooltipsButton() Methode zu der CWindow Klasse für die Verarbeitung von Tooltip Buttons hinzugefügt: 

//+------------------------------------------------------------------+
//| Klasse für die Erzeugung eines Formulars für controls                     |
//+------------------------------------------------------------------+
class CWindow : public CElement
  {
private:
   //--- Verarbeiten von Events bei einem Klick auf Tooltip buttons
   bool              OnClickTooltipsButton(const string clicked_object);
  };
//+------------------------------------------------------------------+
//| Chart Eventhandler                                        |
//+------------------------------------------------------------------+
void CWindow::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Verarbeiten eines Klicks auf ein Objekt
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Falls auf einen Tooltip Button geklickt wurde
      if(OnClickTooltipsButton(sparam))
         return;
     }
  }
//+------------------------------------------------------------------+
//| Verarbeiten eines Klicks auf einen Tooltip button           |
//+------------------------------------------------------------------+
bool CWindow::OnClickTooltipsButton(const string clicked_object)
  {
//--- Dieser Button wird nicht benötigt, falls es sich um ein Dialogfenster handelt
   if(m_window_type==W_DIALOG)
      return(false);
//--- Abbrechen, falls nicht auf dem Radio Button geklickt wurde
   if(::StringFind(clicked_object,CElement::ProgramName()+"_window_tooltip_",0)<0)
      return(false);
//--- Abfrage des Bezeichners des Controls über den Namen des Objektes
   int id=CElement::IdFromObjectName(clicked_object);
//--- Abbrechen, falls die Bezeichner nicht übereinstimmen
   if(id!=CElement::Id())
      return(false);
//--- Speichere den Status in der Klassen Variable
   m_tooltips_button_state=m_button_tooltip.State();
//--- Eine Nachricht darüber senden
   ::EventChartCustom(m_chart_id,ON_WINDOW_TOOLTIPS,CElement::Id(),CElement::Index(),"");
   return(true);
  }

Damit alles in dieser Bibliothek (CWndEvents class) funktioniert, muss die OnWindowTooltips() Methode für die Verarbeitung des Events mit dem ON_WINDOW_TOOLTIPS Bezeichner hinzugefügt werden: 

class CWndEvents : public CWndContainer
  {
private:
   //--- Aktivieren und deaktivieren von Tooltips
   bool              OnWindowTooltips(void);
  };
//+------------------------------------------------------------------+
//| CHARTEVENT_CUSTOM event                                         |
//+------------------------------------------------------------------+
void CWndEvents::ChartEventCustom(void)
  {
//--- Wenn es sich um ein Signal für das Minimieren des Formulars handelt
//--- Wenn das Formular maximiert werden soll
//--- Wenn die Controls entlang der x-Achse angepasst werden sollen
//--- Wenn die Controls entlang der y-Achse angepasst werden sollen
//--- Wenn die Tooltips aktiviert/deaktiviert werden sollen
   if(OnWindowTooltips())
      return;

//--- Wenn Kontextmenü Elemente unterhalb des auslösenden Elementes versteckt werden sollen
//--- Wenn alle Kontextmenüs versteckt werden sollen
//--- Wenn ein Dialogfenster geöffnet werden soll
//--- Wenn ein Dialogfenster geschlossen werden soll
//--- Wenn alle Farben aller Elemente der angegebenen Form zurückgesetzt werden sollen
//--- Zurücksetzen der Prioritäten der linken Maustaste
//--- Wiederherstellen der Prioritäten eines Klicks mit der linken Maustaste
  }
//+------------------------------------------------------------------+
//| ON_WINDOW_TOOLTIPS event                                        |
//+------------------------------------------------------------------+
bool CWndEvents::OnWindowTooltips(void)
  {
//--- Wenn die Tooltips aktiviert/deaktiviert werden sollen
   if(m_id!=CHARTEVENT_CUSTOM+ON_WINDOW_TOOLTIPS)
      return(false);
//--- Wenn die Fenster Bezeichner stimmen
   if(m_lparam!=m_windows[0].Id())
      return(true);
//--- Synchronisiere die Tooltips Modi entlang aller Fenster
   int windows_total=WindowsTotal();
   for(int w=0; w<windows_total; w++)
     {
      if(w>0)
         m_windows[w].TooltipButtonState(m_windows[0].TooltipButtonState());
     }
//---
   return(true);
  }

2. Es wurde die Möglichkeit hinzugefügt, den Text der Beschreibung der folgenden Controls auch nach deren Erzeugung ändern zu können: 

 

Abbildung 4. Liste der Controls, bei denen der Text auch nach deren Erzeugung verändert werden kann:

3. Ein Bild kann nun in allen Controls gesetzt werden, wo es notwendig sein könnte (Sehen Sie sich dazu die nachfolgende Tabelle an). Zusätzlich wurde noch die Möglichkeit geschaffen, das Icon auch nach der Erzeugung zu verändern:


 

Abbildung 5. Liste der Controls, bei dem die Möglichkeit besteht, das Icon auch nach der Erzeugung noch zu verändern:

 

Für das Ersetzen eines Icons in allen oben aufgeführten Controls, wurde die IconFileOn() und IconFileOff() Methode hinzugefügt.

4. Es wurde die Möglichkeit geschaffen, programmtechnisch den Status aller Typen von Buttons und Tabs nach deren Erzeugung verändern zu können (gedrückt/losgelassen). Die nachfolgende Tabelle zeigt die Controls, bei denen dieses hinzugefügt wurde:

 

Abbildung 6. Liste der controls, bei denen die Möglichkeit besteht, deren Status nach der Erzeugung noch zu verändern. (gedrückt/losgelassen)

5. Der Algorithmus für das Hervorheben von Elementen, wenn sich der Mauszeiger darüber befindet, wurde in den folgenden Controls optimiert:

 

Abbildung 7. Controls mit optimierten Algorithmus für das Hervorheben von Elementen.

 

Früher ging das Programm alle Elemente in der Liste der oben genannten Controls durch und hat geprüft, ob sich der Mauszeiger darüber befindet. Dann wurde das Element, welches sich unter dem Mauszeiger befand hervorgehoben und bei den anderen Elemente wurden die Standardfarbe gesetzt. Diese Methode Hat sehr viele Ressourcen beansprucht, daher gab es hier eine Notwendigkeit diese zu optimieren. Jetzt wird nicht mehr das gesamte Array der Elemente durchgegangen, sondern nur noch zwei Elemente erfahren eine Veränderung in der Farbe. Eine Suche über alle Elemente findet nur noch statt, wenn der Focus gewechselt hat. 

Sehen Sie sich beispielhaft an, wie dieses in der CListView Klasse umgesetzt wurde. Für die Implementierung der oben genannten Dinge, wird das hinzufügen (1) der m_prev_item_index_focus Klassen variablen notwendig um den Index des Elementes abzuspeichern, der zuletzt den Fokus besaß, (2) die CListView::CheckItemFocus() Methode um den Fokus über dem Element zu prüfen und (3) Die Änderung des Algorithmus in der CListView::ChangeItemsColor() Methode  

//+------------------------------------------------------------------+
//| Klasse für die Erzeugung einer ListView                                   |
//+------------------------------------------------------------------+
class CListView : public CElement
  {
private:
   //--- Für die Bestimmung des Momentes wo der Mauszeiger von einem Element zu dem nächsten wechselt
   int               m_prev_item_index_focus;
   //---
private:
   //--- Verändern der Farbe der ListView Elemente, wenn sich der Mauszeiger darüber befindet
   void              ChangeItemsColor(void);
   //--- Überprüfung des Fokus der ListView Element wenn der Mauszeiger sich darüber befindet
   void              CheckItemFocus(void);
  };

Die CListView::CheckItemFocus() Methode wird nur aufgerufen, wenn sich der Mauszeiger darüber befindet (in diesem Fall – CListView), und auch wenn sich der Mauszeiger von einem Element zu dem nächsten bewegt (Sehen Sie sich dazu den nachfolgenden Programmcode an). Sobald ein Element gefunden wird, über welchem sich der Mauszeiger befindet, wird sein Index gespeichert

//+------------------------------------------------------------------+
//| Überprüfung des Fokus der ListView Elemente wenn sich der Mauszeiger darüber befindet   |
//+------------------------------------------------------------------+
void CListView::CheckItemFocus(void)
  {
//--- Abfrage der aktuellen Position des Scrollbar Slider
   int v=m_scrollv.CurrentPos();
//--- Identifizierung, über welchem Element sich der Mauszeiger befindet und hervorheben des Elementes
   for(int i=0; i<m_visible_items_total; i++)
     {
      //--- Erhöhung des Zählers, falls die Grenzen der ListView nicht überschritten wurden
      if(v>=0 && v<m_items_total)
         v++;
      //--- Überspringe das ausgewählte Element
      if(m_selected_item_index==v-1)
        {
         m_items[i].BackColor(m_item_color_selected);
         m_items[i].Color(m_item_text_color_selected);
         continue;
        }
      //--- Falls sich der Mauszeiger über diesem Element befindet, hervorheben
      if(m_mouse.X()>m_items[i].X() && m_mouse.X()<m_items[i].X2() &&
         m_mouse.Y()>m_items[i].Y() && m_mouse.Y()<m_items[i].Y2())
        {
         m_items[i].BackColor(m_item_color_hover);
         m_items[i].Color(m_item_text_color_hover);
         //--- Element merken
         m_prev_item_index_focus=i;
         break;
        }
     }
  }

Die CListView::CheckItemFocus() Methode wird innerhalb der CListView::ChangeItemsColor() Methode in den oben genannten Fällen aufgerufen(Sehen Sie sich dazu das nachfolgende Listing an):

//+------------------------------------------------------------------+
//| Verändern der Farbe eines ListView Element ist, wenn sich der Mauszeiger darüber befindet |
//+------------------------------------------------------------------+
void CListView::ChangeItemsColor(void)
  {
//--- Abbrechen, falls das Element deaktiviert ist oder die Scrollbar aktiv ist
   if(!m_lights_hover || m_scrollv.ScrollState())
      return;
//--- Abbrechen, falls es sich nicht um ein Dropdown Element handelt und das Formular blockiert ist
   if(!CElement::IsDropdown() && m_wnd.IsLocked())
      return;
//--- Wenn die Listenansicht wieder aktiviert wurde
   if(m_prev_item_index_focus==WRONG_VALUE)
     {
      //--- Überprüfe den Fokus des aktuellen Elementes
      CheckItemFocus();
     }
   else
     {
      //--- Überprüfe den Fokus der aktuellen Zeile
      int i=m_prev_item_index_focus;
      bool condition=m_mouse.X()>m_items[i].X() && m_mouse.X()<m_items[i].X2() &&
                     m_mouse.Y()>m_items[i].Y() && m_mouse.Y()<m_items[i].Y2();
      //--- Falls zu einem anderen Element bewegt wurde
      if(!condition)
        {
         //--- Setze die Farbe des vorherigen Elementes zurück
         m_items[i].BackColor(m_item_color);
         m_items[i].Color(m_item_text_color);
         m_prev_item_index_focus=WRONG_VALUE;
         //--- Überprüfe den Fokus des aktuellen Elementes
         CheckItemFocus();
        }
     }
  }

In dem CListView::OnEvent() Eventhandler, wird die CListView::ChangeItemsColor() Methode nur aufgerufen, wenn sich der Mauszeiger innerhalb des Arbeitsbereiches des Controls befindet. Sobald der Mauszeiger den Control-bereich verlässt, werden die Standardfarben gesetzt und und der Index-Wert des Elementes wird zurückgesetzt. Eine abgekürzte Version des eventhandlers wird nachfolgend gezeigt. 

//+------------------------------------------------------------------+
//| Event handler                                               |
//+------------------------------------------------------------------+
void CListView::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Verarbeiten eines Events über die Bewegung des Mauszeigers
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      //--- Abbrechen, falls das Element versteckt ist
      //--- Abbrechen, falls die Anzahl der Unterfenster nicht stimmt
      //--- Überprüfe den Fokus über den Elementen
      //--- Falls es sich um eine Dropdown-Liste handelt und der Maus Button gedrückt ist
      //--- Bewege die Liste, falls die Verwaltung des Sliders aktiv ist

      //--- Bitte die Farbe des Elementes zurück, falls es nicht im Fokus ist
      if(!CElement::MouseFocus())
        {
         //--- Wenn das Element bereits den Fokus besitzt
         if(m_prev_item_index_focus!=WRONG_VALUE)
           {
            //--- Setze die Farbe der ListView zurück
            ResetColors();
            m_prev_item_index_focus=WRONG_VALUE;
           }
         return;
        }
      //--- Verändere die Farbe der ListView Elemente, falls sich der Cursor darüber befindet
      ChangeItemsColor();
      return;
     }
  }

Das gleiche Prinzip wurde in den CTable, CCalendar und CTreeView Klassen implementiert, aber mit kleinen Unterschieden, die die Besonderheiten jedes Controls berücksichtigen.

6. Ein Klick auf einen Button vom Typ CIconButton im Zwei-Status-Modus (Wenn der Button nach dem Klicken nicht losgelassen wird) zeigt ein anderes Icon, falls dieses angegeben wurde. Sie können mit den Methoden CIconButton::IconFilePressedOn() und CIconButton::IconFilePressedOff() die Icons für den gedrückten Button festlegen. 

//+------------------------------------------------------------------+
//| Klasse für das Erzeugen eines Icon Button|
//+------------------------------------------------------------------+
class CIconButton : public CElement
  {
private:
   //--- Icons für den Button im aktiven, gesperrten und gedrückten Status
   string            m_icon_file_on;
   string            m_icon_file_off;
   string            m_icon_file_pressed_on;
   string            m_icon_file_pressed_off;

   //---
public:
   //--- Festlegen der Icons für den Button in dem gedrückten, aktiven und gesperrten Status
   void              IconFileOn(const string file_path);
   void              IconFileOff(const string file_path);
   void              IconFilePressedOn(const string file_path);
   void              IconFilePressedOff(const string file_path);

  };
//+------------------------------------------------------------------+
//| Festlegen des Icons für den gedrückten "ON" Status              |
//+------------------------------------------------------------------+
void CIconButton::IconFilePressedOn(const string file_path)
  {
//--- Abbrechen, falls der 2-Status -Modus für diesen Button deaktiviert ist
   if(!m_two_state)
      return;
//--- Abspeichern des Pfades zu dem Bild
   m_icon_file_pressed_on=file_path;
//--- Direktes bestimmen, ob der Button gedrückt ist
   if(m_button.State())
      m_icon.BmpFileOn("::"+file_path);
  }
//+------------------------------------------------------------------+
//| Festlegen des Icons für den gedrückten "OFF" Status             |
//+------------------------------------------------------------------+
void CIconButton::IconFilePressedOff(const string file_path)
  {
//--- Abbrechen, falls der 2-Status-Modus für diesen Button deaktiviert ist
   if(!m_two_state)
      return;
//--- Abspeichern des Pfades zu dem Bild
   m_icon_file_pressed_off=file_path;
//--- Direkte Bestimmung, ob der Button gedrückt ist
   if(m_button.State())
      m_icon.BmpFileOff("::"+file_path);
  }

7. Es wurde die Möglichkeit hinzugefügt, programmatisch eine Zeile in einer Tabelle auszuwählen (CTable). Sie können dieses mit der CTable::SelectRow() Methode durchführen. Wenn Sie einen Index einer Zeile angeben, die bereits ausgewählt ist, dann wird diese Selektierung aufgehoben. 

//+------------------------------------------------------------------+
//| Klasse für die Erzeugung einer Editbox-Tabelle|
//+------------------------------------------------------------------+
class CTable : public CElement
  {
public:
   //--- Selektieren der angegebene Zeile in der Tabelle
   void              SelectRow(const uint row_index);
  };
//+------------------------------------------------------------------+
//| Selektieren der angegebenen Zeile in der Tabelle                            |
//+------------------------------------------------------------------+
void CTable::SelectRow(const uint row_index)
  {
//--- Korrektur für den Fall, dass die Grenzen überschritten wurden
   uint index=(row_index>=(uint)m_rows_total)? m_rows_total-1 : row_index;
//--- Wenn diese Zeile bereit selektiert ist, dann die Auswahl aufheben
   bool is_selected=(index==m_selected_item);
//--- Speichere den Index der Zeile
   m_selected_item=(is_selected)? WRONG_VALUE : (int)index;
//--- Speichere die Zeile der Zelle
   m_selected_item_text=(is_selected)? "" : m_vcolumns[0].m_vrows[index];
//--- Erzeuge einen String mit den Parametern der Zelle
   string cell_params=string(0)+"_"+string(index)+"_"+m_vcolumns[0].m_vrows[index];
//--- Setze den Fokus zurück
   m_prev_item_index_focus=WRONG_VALUE;
//--- Aktualisiere die Tabelle
   UpdateTable();
//--- Hebe die selektierte Zeile hervor
   HighlightSelectedItem();
  }

8. Fehlerbehebung bei der Anzeige von Elementen in einem ausgewählten Tab eines CIconTabs Controls. Das Problem trat auf, wenn man ein Formular geöffnet und maximiert hat und dieses diese Art von Tabs besaß. 

 

Anwendung für das Testen der Controls

Lassen Sie uns eine Testanwendung schreiben, mit der sie alle neuen Controls Testen und deren unterschiedlichen Modi kennenlernen können. Erzeugen sie in de, grafischen Interface der Anwendung ein Tab control (CTabs Klasse), welches vier Tabs mit den folgenden Inhalt besitzt:

1. Das erste Tab:

  • Progress bar (CProgressBar).
  • Text edit Box (CTextEdit).
  • Combobox mit einer drop-down-Liste(CCombobox).
  • Spin edit box Für numerische Werte (CSpinEdit).
  • Button für den Aufruf der Farbauswahl(CColorButton).
  • Text label (CTextLabel).

Legen Sie ein Icon für alle Controls, mit Ausnahme des Text Labels fest. Die Beschreibung der Fortschrittsanzeige und der Text-Edith-Box Controls wird in regelmäßigen Intervallen verändert, damit demonstriert werden kann, dass dieses Feature nun erhältlich ist. Platzieren Sie die Namen aller Schriftarten aus der CFonts Klasse in die Combobox-Liste. Die Event-Struktur der Testanwendung wird so konstruiert, dass eine Auswahl einer Schrift aus der Combobox in dem Text-Label wiedergegeben wird. Genauso wird das Text-Label an die numerische Edith-Box gebunden, um die Größe der Schrift und die Farbe in der Farbauswahl zu ändern. 

Der Eventhandler für die Verwaltung der Parameter des Text-Label-Controls sieht wie folgt aus:

//+------------------------------------------------------------------+
//| Chart event handler                                        |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Event bei einer Auswahl aus der Combobox Liste
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_COMBOBOX_ITEM)
     {
      //--- Falls die Control-Bezeichner übereinstimmen
      if(lparam==m_combobox1.Id())
        {
         //--- Ändere die Schriftart
         m_text_label1.LabelFont(m_combobox1.ButtonText());
        }
      //---
      return;
     }
//--- Event bei einem Klick auf die Spin-Editbox-Buttons
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_INC ||
      id==CHARTEVENT_CUSTOM+ON_CLICK_DEC)
     {
      //--- Falls die Bezeichner der Controls übereinstimmen
      if(lparam==m_spin_edit1.Id())
        {
         //--- Ändere die Größe der Schrift
         m_text_label1.LabelFontSize(int(m_spin_edit1.GetValue()));
        }
      //---
      return;
     }
//--- Event für das Ändern der Farbe unter Verwendung des Color-Pickers
   if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
     {
      //--- Falls die Bezeichner der Controls übereinstimmen
      if(lparam==m_spin_edit1.Id())
        {
         //--- Ändere die Größe der Schrift
         m_text_label1.LabelFontSize(int(m_spin_edit1.GetValue()));
        }
      //---
      return;
     }
//--- Event für das Verändern der Farbe unter Verwendung des Color-Pickers
   if(id==CHARTEVENT_CUSTOM+ON_CHANGE_COLOR)
     {
      //--- Falls die Bezeichner der Controls übereinstimmen
      if(lparam==m_color_picker.Id())
        {
         //--- Falls es eine Antwort von dem ersten Button gibt
         if(sparam==m_color_button1.LabelText())
           {
            //--- Ändere die Objektfarbe
            m_text_label1.LabelColor(m_color_button1.CurrentColor());
            return;
           }
        }
      return;
     }
//--- Event für einen Klick auf einen Button
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
     {
      //--- Falls der erste Button für den Aufruf des Colorpickers gedrückt wurde
      if(sparam==m_color_button1.LabelText())
        {
         //--- Übergebe den Pointer des Buttons, welcher automatisch das Fenster mit dem Colorpicker öffnet
         m_color_picker.ColorButtonPointer(m_color_button1);
         return;
        }
      //---
      return;
     }
  }

Der nachfolgende Screenshot zeigt, wie die Textanzeige unter Verwendung des grafischen Interfaces konfiguriert werden kann.

Fig. 8. Gruppe von Controls auf dem ersten Tab. 

Fig. 8. Gruppe von Controls auf dem ersten Tab.

2. Nur ein Control – der Bild-Slider (CPicturesSlider Klasse) wird auf dem zweiten Tab platziert. Es werde dieser Gruppe nur 3 Standard Bilder hinzugefügt, damit sie dieses Control schnell Testen können. Damit dieses control richtig arbeitet, verwenden Sie bitte Bilder mit der gleichen Größe.

Abbildung 9 Der Bild-Slider auf dem zweiten Tab 

Abbildung 9 Der Bild-Slider auf dem zweiten Tab

Um Programm gesteuert die Bilder ändern zu können, verwenden Sie die CPicturesSlider::SelectPicture() Methode.

3. Das dritte Tab enthält eine Tabelle vom Typ CTable. Um programmgesteuert eine Zeile auszuwählen, verwenden Sie die CTable::SelectRow() Methode. 

 Abbildung 10. Das Tabellen-Control auf dem dritten Tab.

Abbildung 10. Das Tabellen-Control auf dem dritten Tab.

4. Auf dem vierten Tag gibt es drei Controls: (1) Kalender, (2) Drop-down-Kalender und (3) Einen Button mit zwei unterschiedlichen Icons für den gedrückten und losgelassenen Status.

Abbildung 11. Gruppe von Controls auf dem vierten Tab. 

Abbildung 11. Gruppe von Controls auf dem vierten Tab.

 

Die Testanwendung, die in diesem Artikel vorgestellt wird, kann mit dem unten aufgeführten Link heruntergeladen werden. 


Schlussfolgerung

Die Bibliothek für das Erzeugen von grafischen Interfaces sieht zu dem aktuellen Stand der Entwicklung wie folgt aus: (Schematisch).

 Fig. 12. Die Struktur unserer Bibliothek zum aktuellen Stand der Entwicklung

Fig. 12. Die Struktur unserer Bibliothek zum aktuellen Stand der Entwicklung

In der nächsten Version wird die Bibliothek um zusätzliche Steuerelemente erweitert. Ebenso werden die bereits existierenden Controls weiterentwickelt und mit zusätzlichen neuen Features ausgestattet.

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.