English Русский 中文 Español 日本語 Português
Grafische Interfaces VI: Die Slider und Dual-Slider Controls (Kapitel 2)

Grafische Interfaces VI: Die Slider und Dual-Slider Controls (Kapitel 2)

MetaTrader 5Beispiele | 19 Juli 2016, 08:47
705 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 Artikel haben wir unsere Bibliothek um die vier sehr häufig verwendeten Controls: Checkbox, Edit, Edit mit Checkbox und Check-Combobox erweitert. Das zweite Kapitel des sechsten Teils widmet sich den Slider (Schieberegler) und Dual-Slider Controls.

Das Slider Control

Ein Slider ist eine Art Edit-Control, welches eine Bandbreite, die durch ein Minimum und ein Maximum festgelegt wird, besitzt. Anders als bei den Edit Control, welches wir in dem vorherigen Artikel genau besprochen haben, besitzt ein Slider keine Buttons, um Werte zu verändern. Dafür gibt es hier eine Linie, die zu diesem Zwecke verschoben werden kann. Ein solches Interface-Element ist dann sinnvoll, wenn man nur ungefähre Werte innerhalb einer bestimmten Spanne eingeben will und ein exakter wird nicht unbedingt notwendig ist. Aber es gibt immer noch die Möglichkeit einen genauen Wert manuell einzugeben.

Dieses Element wird aus sechs grafischen Objekten zusammengebaut. Diese sind:

  1. Hintergrund
  2. Caption (text label)
  3. Eingabefeld
  4. Slider-Linie
  5. Slider-Läufer
  6. Slider Indikator

 

Abbildung 1. Komponenten des Slider-Controls

Lassen Sie uns diese Klasse im Detail studieren.

 


Entwickeln einer Klasse für die Erzeugung eines Slider Controls

Erzeugen Sie die Slider.mqh Dateien beziehen Sie diese in der WndContainer.mqh Datei mit ein:

//+------------------------------------------------------------------+
//|                                                 WndContainer.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Slider.mqh"

Erzeugen sie in der Slider.mqh Datei die CSlider Klasse mit den Standards Methoden, die in allen Controls dieser Bibliothek enthalten sein müssen. Zudem beziehen sie noch die Dateien Element.mqh und Window.mqh, und die SeparateLine.mqh Datei mit der CSeparateLine Klasse für das Erzeugen einer Trennlinie mit ein. Die CSeparateLine Klasse haben wir bereits in dem Artikel Graphische Interfaces II: Die Trennlinie und Kontextmenü Elemente (Kapitel 2) besprochen Weshalb wir hier nicht weiter darauf eingehen. Das einzige, worauf ich noch eben hinweisen möchte, ist, dass wenn eine Höhe von größer als 2 Pixeln angegeben wird, es einen Leerraum zwischen den beiden gezeichneten Linien gibt. Optisch sieht es aus wie ein Schatten, was für eine Slider-Linie auch geeignet ist (slit or slot) in welchem sich der Slider-Runner bewegt..

//+------------------------------------------------------------------+
//|                                                       Slider.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
#include "Window.mqh"
#include "SeparateLine.mqh"
//+------------------------------------------------------------------+
//| Klasse für das Erzeugen eines Sliders                            |
//+------------------------------------------------------------------+
class CSlider : public CElement
  {
private:
   //--- Ein Pointer zu der Form zu welchem das Element hinzugefügt worden ist
   CWindow          *m_wnd;
public:
                     CSlider(void);
                    ~CSlider(void);
   //---
public:
   //--- Speichert den 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) Set, (2) reset priorities of the left mouse button press
   virtual void      SetZorders(void);
   virtual void      ResetZorders(void);
   //--- Zurücksetzen der Farbe
   virtual void      ResetColors(void);
  };

Der Anwender der Bibliothek sollte die Möglichkeit haben, sämtliche Eigenschaften aller Objekte, die in diesem Control verwendet werden, einstellen zu können. Diese Eigenschaften werden nachfolgend aufgelistet.

  • Farbe des Hintergrundes des Elementes
  • Text für die Beschreibung des Sliders
  • Die Farben für das Textlabel für die unterschiedlichen Zustände
  • Der aktuelle Wert in dem Eingabefeld
  • Die Größe des Eingabefeldes
  • Die Farben des Eingabefeldes in den unterschiedlichen Zuständen
  • Die Farbe des Textes in dem Eingabefeld in den unterschiedlichen Zuständen
  • Die Farbe des Rahmens von dem Eingabefeld in den unterschiedlichen Zuständen
  • Größe des Schlitzes längs der y-Achse (Höhe)
  • Farbe der Linien für den Schlitz
  • Farbe des Slider Indikators in den unterschiedlichen Zuständen
  • Die Größe des Slider Läufers
  • Die Farbe des Läufers des Sliders
  • Prioritäten für einen Klick mit der linken Maustaste

Nachfolgend finden Sie den Programmcode der Klasse mit den Variablen und Methoden für die Elementeigenschaften, die wir oben aufgezählt haben: 

class CSlider : public CElement
  {
private:
   //--- Farbe des Element-Hintergrundes
   color             m_area_color;
   //--- Text für eine Beschreibung des Sliders
   string            m_label_text;
   //--- Die Farben für das Textlabel für die unterschiedlichen Zustände
   color             m_label_color;
   color             m_label_color_hover;
   color             m_label_color_locked;
   color             m_label_color_array[];
   //--- Die Größe des Eingabefeldes
   int               m_edit_x_size;
   int               m_edit_y_size;
   //--- Die Farbe des Eingabefeldes in den unterschiedlichen Zuständen
   color             m_edit_color;
   color             m_edit_color_locked;
   //--- Die Farbe des Textes des Eingabefeldes in den unterschiedlichen Zuständen
   color             m_edit_text_color;
   color             m_edit_text_color_locked;
   //--- Die Farbe des Rahmens des Eingabefeldes 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[];
   //--- Die Größe des Schlitzes
   int               m_slot_y_size;
   //--- Die Farbe des Schlitzes
   color             m_slot_line_dark_color;
   color             m_slot_line_light_color;
   //--- Die Farbe des Indikators in unterschiedlichen Zuständen
   color             m_slot_indicator_color;
   color             m_slot_indicator_color_locked;
   //--- Die Größe des Läufers
   int               m_thumb_x_size;
   int               m_thumb_y_size;
   //--- Die Farbe des Läufers des Sliders
   color             m_thumb_color;
   color             m_thumb_color_hover;
   color             m_thumb_color_locked;
   color             m_thumb_color_pressed;
   //--- Priorität für die linke Maustaste
   int               m_zorder;
   int               m_area_zorder;
   int               m_edit_zorder;
   //---
public:
   //--- (1) Hintergrundfarbe, (2) Die Farbe des Text-Labels
   void              AreaColor(const color clr)                     { m_area_color=clr;                   }
   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;           }
   //--- Größe des (1) Eingabefeldes und (2) des Schlitzes
   void              EditXSize(const int x_size)                    { m_edit_x_size=x_size;               }
   void              EditYSize(const int y_size)                    { m_edit_y_size=y_size;               }
   void              SlotYSize(const int y_size)                    { m_slot_y_size=y_size;               }
   //--- Die Farbe des Eingabefeldes in den unterschiedlichen Zuständen
   void              EditColor(const color clr)                     { m_edit_color=clr;                   }
   void              EditColorLocked(const color clr)               { m_edit_color_locked=clr;            }
   //--- Die Farbe des Textes des Eingabefeldes 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;       }
   //--- Die Farbe des Rahmens des Eingabefeldes 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) Dunkle und (2) Helle Farbe der Trennlinie (Schlitz)
   void              SlotLineDarkColor(const color clr)             { m_slot_line_dark_color=clr;         }
   void              SlotLineLightColor(const color clr)            { m_slot_line_light_color=clr;        }
   //--- Die Farbe des leider Indikators in den unterschiedlichen Zuständen
   void              SlotIndicatorColor(const color clr)            { m_slot_indicator_color=clr;         }
   void              SlotIndicatorColorLocked(const color clr)      { m_slot_indicator_color_locked=clr;  }
   //--- Die Größe des Läufers
   void              ThumbXSize(const int x_size)                   { m_thumb_x_size=x_size;              }
   void              ThumbYSize(const int y_size)                   { m_thumb_y_size=y_size;              }
   //--- Die Farbe des Läufers des Sliders
   void              ThumbColor(const color clr)                    { m_thumb_color=clr;                  }
   void              ThumbColorHover(const color clr)               { m_thumb_color_hover=clr;            }
   void              ThumbColorLocked(const color clr)              { m_thumb_color_locked=clr;           }
   void              ThumbColorPressed(const color clr)             { m_thumb_color_pressed=clr;          }
  };

Die Eigenschaften auf der vorherigen Liste beziehen sich hauptsächlich auf die Farbe und die Größe der Elemente. Die Eigenschaften, die sich auf die Spanne und das Eingabefeld beziehen, bilden eine separate Gruppe. Diese Eigenschaften sind: 

  • Minimaler Wert
  • Maximaler wert
  • Schritt für die Veränderungen des Wertes in dem Eingabefeld
  • Der Modus für die Text-Ausrichtung
  • Die Anzahl der Nachkommastellen
class CSlider : public CElement
  {
private:
   //--- (1) Minimum und (2) Maximum Wert, (3) Schrittweite für die Veränderung des Wertes
   double            m_min_value;
   double            m_max_value;
   double            m_step_value;
   //--- Anzahl der Nachkommastellen
   int               m_digits;
   //--- Modus der Textausrichtung
   ENUM_ALIGN_MODE   m_align_mode;
   //---
public:
   //--- Minimum-Wert
   double            MinValue(void)                           const { return(m_min_value);                }
   void              MinValue(const double value)                   { m_min_value=value;                  }
   //--- Maximum-Wert
   double            MaxValue(void)                           const { return(m_max_value);                }
   void              MaxValue(const double value)                   { m_max_value=value;                  }
   //--- Schrittweite für die Veränderung des Wertes
   double            StepValue(void)                          const { return(m_step_value);               }
   void              StepValue(const double value)                  { m_step_value=(value<=0)? 1 : value; }
   //--- (1) Anzahl der Nachkommastellen, (2) Modus der Textausrichtung
   void              SetDigits(const int digits)                    { m_digits=::fabs(digits);            }
   void              AlignMode(ENUM_ALIGN_MODE mode)                { m_align_mode=mode;                  }
  };

Um den aktuellen Wert abzufragen, sowie ihn einzustellen und einen neuen Wert in das Eingabefeld einzugeben, verwenden wir die Methoden CSlider::GetValue(), CSlider::SetValue() und CSlider::ChangeValue():

class CSlider : public CElement
  {
private:
   //--- Aktueller Wert in dem Eingabefeld
   double            m_edit_value;
   //---
public:
   //--- Abfragen und Setzen des Wertes in dem Eingabefeld
   double            GetValue(void)                           const { return(m_edit_value);               }
   bool              SetValue(const double value);
   //--- Verändern des Wertes in dem Eingabefeld
   void              ChangeValue(const double value);
  };
//+------------------------------------------------------------------+
//| Setzen des aktuellen Wertes                                      |
//+------------------------------------------------------------------+
bool CSlider::SetValue(const double value)
  {
//--- Für die Einstellungen
   double corrected_value=0.0;
//--- Einstellung unter Berücksichtigung der Schrittweite
   corrected_value=::MathRound(value/m_step_value)*m_step_value;
//--- Überprüfung auf Minimum/Maximum
   if(corrected_value<=m_min_value)
      corrected_value=m_min_value;
   if(corrected_value>=m_max_value)
      corrected_value=m_max_value;
//--- Falls sich der Wert geändert hat
   if(m_edit_value!=corrected_value)
     {
      m_edit_value=corrected_value;
      return(true);
     }
//--- Wert ist unverändert
   return(false);
  }
//+------------------------------------------------------------------+
//| Verändern des Wertes in dem Eingabefeld                          |
//+------------------------------------------------------------------+
void CSlider::ChangeValue(const double value)
  {
//--- Überprüfen, Einstellen und Abspeichern des neuen Wertes
   SetValue(value);
//--- Setzen des neuen Wertes in dem Eingabefeld
   m_edit.Description(::DoubleToString(GetValue(),m_digits));
  }

Wenn sich der Kleider bewegt, dann muss der Wert in dem Eingabefeld in Abhängigkeit zu der X Koordinate berechnet werden. Wenn der Wert manuell eingegeben wird, dann muss die X Koordinate des Slider Läufers in Relation zu dem neuen Wert berechnet werden. Mit anderen Worten, bei der Entwicklung muss die Möglichkeit einer inversen Transformation berücksichtigt werden. 

Für die korrekte Berechnung, benötigen wir noch weitere Variablen in der Klasse, die für die Berechnung verwendet wird. Diese Variablen müssen nur einmalig berechnet werden, wenn das Element erzeugt wird. Nachfolgend nun die Beschreibung dieser Variablen:

  • Die Anzahl der Pixel in dem Arbeitsbereich (m_pixels_total).
  • Die anzahl der Schritte (Spanne) in dem Arbeitsbereich (m_value_steps_total).
  • Schrittweite in Relation zu der Breite des Arbeitsbereichs (m_position_step).

Lassen Sie uns eine Methode für die Berechnung dieser Werte entwickeln. Wir nennen sie CSlider::CalculateCoefficients() nennen:

class CSlider : public CElement
  {
private:
   //--- Anzahl der Pixel im Arbeitsbereich
   int               m_pixels_total;
   //--- Anzahl der Schritte im Arbeitsbereich
   int               m_value_steps_total;
   //--- Schrittweite der transformierten Breite des Arbeitsbereichs
   double            m_position_step;
   //---
private:
   //--- Berechnung der Werte (Schritte und Koeffizienten)
   bool              CalculateCoefficients(void);
  };
//+------------------------------------------------------------------+
//| Berechnung der Werte (Schritte und Koeffizienten)                |
//+------------------------------------------------------------------+
bool CSlider::CalculateCoefficients(void)
  {
//--- Abbrechen, falls die Breite des Elementes kleiner als die Breite des Slider-Läufers ist
   if(CElement::XSize()<m_thumb_x_size)
      return(false);
//--- Anzahl der Pixel im Arbeitsbereich
   m_pixels_total=CElement::XSize()-m_thumb_x_size;
//--- Die Anzahl der schritte in der Werte-Spanne des Arbeitsbereichs
   m_value_steps_total=int((m_max_value-m_min_value)/m_step_value);
//--- Schritt in Relation zu der Breite des Arbeitsbereichs
   m_position_step=m_step_value*(double(m_value_steps_total)/double(m_pixels_total));
   return(true);
  }

Jetzt können die oben aufgelisteten Werte der Variablen für die Berechnung der X Koordinate des Slider Läufers in Relation zu dem Wert in dem Eingabefeld und auch umgekehrt berechnet werden. Lassen Sie uns dafür zwei separate Methoden schreiben CSlider::CalculateThumbX() und CSlider::CalculateThumbPos().

Zu Beginn der CSlider::CalculateThumbX() Methode, berechnen wir die Werte der externe lokalen variable (neg_range) für Einstellungen, falls der Wert des Minimums negativ ist. Anschließen berechnen wir die X Koordinate für den Slider-Läufer. Anschließen, falls die Linie des Sliders überschritten wird, wird der Wert angepasst. Am Ende der Methode wird ein neuer Wert für die X Koordinate für den Slider Läufer und die Abstände von der Ecke des Formulars, zu welchen dieses Element hinzugefügt wurde, berechnet.

Ganz am Anfang der CSlider::CalculateThumbPos() Methode, erhalten wir die Position des Slider Läufers aus der Werte-Spanne. Anschließend wird eine Einstellung vorgenommen, falls der Wert des Minimums negativ ist und der Wert der m_current_pos_x Variable korrekt ist. Danach, wird eine Korrektur des Wertes vorgenommen, falls der Arbeitsbereich überschritten wurde.

class CSlider : public CElement
  {
private:
   //--- Die aktuelle Position des Slider-Läufers: (1) Wert, (2) Die x-Koordinate
   double            m_current_pos;
   double            m_current_pos_x;
   //---
private:
   //--- Die Berechnung der x-Koordinate des Slider-Läufers
   void              CalculateThumbX(void);
   //--- Verändert die aktuelle Position des Slider-Läufers in Relation zu dem aktuellen Wert
   void              CalculateThumbPos(void);
  };
//+------------------------------------------------------------------+
//| Berechnung der x-Koordinate des Slider-Läufers                   |
//+------------------------------------------------------------------+
void CSlider::CalculateThumbX(void)
  {
//--- Anpassung unter der Berücksichtigung, dass der Minimum-Wert auch negativ sein kann
   double neg_range=(m_min_value<0)? ::fabs(m_min_value/m_position_step) : 0;
//--- Berechnung der X Koordinate für den Slider-Läufer
   m_current_pos_x=m_area.X()+(m_edit_value/m_position_step)+neg_range;
//--- Falls der Arbeitsbereich nach links überschritten wurde
   if(m_current_pos_x<m_area.X())
      m_current_pos_x=m_area.X();
//--- Falls der Arbeitsbereich nach rechts überschritten wurde
   if(m_current_pos_x+m_thumb.XSize()>m_area.X2())
      m_current_pos_x=m_area.X2()-m_thumb.XSize();
//--- Abspeichern und Setzen der neuen X Koordinaten
   m_thumb.X(int(m_current_pos_x));
   m_thumb.X_Distance(int(m_current_pos_x));
   m_thumb.XGap(m_thumb.X()-m_wnd.X());
  }
//+------------------------------------------------------------------+
//| Berechnung der Position des Slider Läufers in der Werte-Spanne   |
//+------------------------------------------------------------------+
void CSlider::CalculateThumbPos(void)
  {
//--- Die Positionsnummer des Slider-Läufers abfragen
   m_current_pos=(m_thumb.X()-m_area.X())*m_position_step;
//--- Anpassung unter der Berücksichtigung, dass der Minimum-Wert auch negativ sein kann
   if(m_min_value<0 && m_current_pos_x!=WRONG_VALUE)
      m_current_pos+=int(m_min_value);
//--- Überprüfen auf Verlassen des Arbeitsbereichs nach links oder rechts
   if(m_thumb.X2()>=m_area.X2())
      m_current_pos=int(m_max_value);
   if(m_thumb.X()<=m_area.X())
      m_current_pos=int(m_min_value);
  }

Während der Slider Läufer bewegt wird, muss die Breite des Slider-Indikators berechnet und aktualisiert werden. Die rechte Seite des Slider-Indikators muss an die Slider-Läufer gebunden werden. Lassen Sie uns dafür die CSlider::UpdateIndicator() Methode schreiben:

class CSlider : public CElement
  {
private:
   //--- Aktualisierung des Slider-Indikators
   void              UpdateIndicator(void);
  };
//+------------------------------------------------------------------+
//| Aktualisierung des Slider-Indikators                             |
//+------------------------------------------------------------------+
void CSlider::UpdateIndicator(void)
  {
//--- Berechnung der Größe
   int x_size=m_thumb.X()-m_indicator.X();
//--- Anpassung im Falle eines ungültigen Wertes
   if(x_size<=0)
      x_size=1;
//--- Setzen der neuen Größe
   m_indicator.X_Size(x_size);
  }

Um das Slider-Control erzeugen zu können, benötigen wir sechs private und eine public Methode.

class CSlider : public CElement
  {
public:
   //--- Methoden für die Erzeugung des Controls
   bool              CreateSlider(const long chart_id,const int subwin,const string text,const int x,const int y);
   //---
private:
   bool              CreateArea(void);
   bool              CreateLabel(void);
   bool              CreateEdit(void);
   bool              CreateSlot(void);
   bool              CreateIndicator(void);
   bool              CreateThumb(void);
  };

Wir werden hier nur den Programmcode der CSlider::CreateThumb() Methode besprechen, weil alle anderen Methoden für die Berechnung bereits besprochen wurden. Die anderen Methoden beinhalten nichts, was wir nicht schon in den vorherigen Artikeln besprochen haben.

//+------------------------------------------------------------------+
//| Erzeugt den Slider-Läufer                                        |
//+------------------------------------------------------------------+
bool CSlider::CreateThumb(void)
  {
//--- Den Objektnamen bilden
   string name=CElement::ProgramName()+"_slider_thumb_"+(string)CElement::Id();
//--- Koordinaten
   int x=CElement::X();
   int y=m_slot.Y()-((m_thumb_y_size-m_slot_y_size)/2);
//--- Setzen des Objektes
   if(!m_thumb.Create(m_chart_id,name,m_subwin,x,y,m_thumb_x_size,m_thumb_y_size))
      return(false);
//--- Setzen der Eigenschaften
   m_thumb.Color(m_thumb_color);
   m_thumb.BackColor(m_thumb_color);
   m_thumb.BorderType(BORDER_FLAT);
   m_thumb.Corner(m_corner);
   m_thumb.Selectable(false);
   m_thumb.Z_Order(m_zorder);
   m_thumb.Tooltip("\n");
//--- Abspeichern der Größe (In dem Objekt)
   m_thumb.XSize(m_thumb.X_Size());
   m_thumb.YSize(m_thumb.Y_Size());
//--- Abspeichern der Koordinaten
   m_thumb.X(x);
   m_thumb.Y(y);
//--- Ränder von den Kanten
   m_thumb.XGap(x-m_wnd.X());
   m_thumb.YGap(y-m_wnd.Y());
//--- Berechnung der Werte der Hilfs-Variablen
   CalculateCoefficients();
//--- Berechnung der x-Koordinate des Slider-Läufers in Relation zu dem aktuellen Wert in dem Eingabefeld
   CalculateThumbX();
//--- Berechnung der Slider-Läufer-Position in der Werte Spanne
   CalculateThumbPos();
//--- Aktualisierung des Slider-Indikators
   UpdateIndicator();
//--- Abspeichern des Objekt-Pointers
   CElement::AddToArray(m_thumb);
   return(true);
  }

Die Methoden für das Bewegen des Slider-Läufers, sind identisch mit den gleichnamigen Methoden in den CScroll und CScrollH Klassen, welche in dem Artikel Grafische Interfaces V: Die horizontale und vertikale Scrollbar (Kapitel 1) besprochen wurden. Aus diesem Grunde gehen wir hier auf den Code nicht weiter ein. Wir deklarieren ihn nur in dem Körper der CSlider Klasse. 

class CSlider : public CElement
  {
private:
   //--- Status der Maustaste (Gedrückt/nicht gedrückt)
   ENUM_THUMB_MOUSE_STATE m_clamping_area_mouse;
   //--- Für die Identifikation des Modus des leider Läufers
   bool              m_slider_thumb_state;
   //--- Variablen in Zusammenhang mit der Bewegung des Slider-Läufers
   int               m_slider_size_fixing;
   int               m_slider_point_fixing;
   //---
private:
   //--- Prozess der Bewegung des Slider-Läufers
   void              OnDragThumb(const int x);
   //--- Aktualisierung der Position des Slider-Läufers
   void              UpdateThumb(const int new_x_point);
   //--- Überprüfte den Status der Maustaste
   void              CheckMouseButtonState(void);
   //--- Zurücksetzen der Variablen, die mit der Bewegung des Slider-Läufers in Zusammenhang stehen
   void              ZeroThumbVariables(void);
  };

Um Eingaben in das Eingabefeld verarbeiten zu können, erzeugen wir die CSlider::OnEndEdit() Methode, die in der CSlider::OnEvent() Eventhandler Methode aufgerufen wird. 

Am Anfang der CSlider::OnEndEdit() wird eine Überprüfung des Namens vorgenommen, um festzustellen, ob es sich um eine Eingabe in das richtige Eingabefeld handelt. Anschließend fragen wir den aktuellen Wert des Eingabefeldes ab. Anschließend führen wir eine Überprüfung über ungültige Werte durch, nehmen Anpassungen vor, berechnen die X Koordinaten des 2. Läufers und eine Position in der Werte Spanne. Anschließend wird der Slider-Indikator aktualisiert. Am Ende dieser Methode muss eine Nachricht mit (1) dem benutzerdefinierten Event-Bezeichner ON_END_EDIT, (2) dem Bezeichner des Elementes, (3) dem Index des Elementes (4) und der Beschreibung des Text-Label gesendet werden. 

class CSlider : public CElement
  {
private:
   //--- Verarbeiten der manuellen Eingabe eines neuen Wertes
   bool              OnEndEdit(const string object_name);
  };
//+------------------------------------------------------------------+
//| HVerarbeiten der manuellen Eingabe eines neuen Wertes            |
//+------------------------------------------------------------------+
bool CSlider::OnEndEdit(const string object_name)
  {
//--- Abbrechen, falls die Objektnamen nicht übereinstimmen
   if(object_name!=m_edit.Name())
      return(false);
//--- Abfrage des eingegebenen Wertes
   double entered_value=::StringToDouble(m_edit.Description());
//--- Überprüfen, Einstellen und Abspeichern des neuen Wertes
   ChangeValue(entered_value);
//--- Berechnen der x-Koordinate des Slider-Läufers
   CalculateThumbX();
//--- Berechnen der Position in der Werte-Spanne
   CalculateThumbPos();
//--- Aktualisierung des Slider-Indikators
   UpdateIndicator();
//--- Eine Nachricht darüber senden
   ::EventChartCustom(m_chart_id,ON_END_EDIT,CElement::Id(),CElement::Index(),m_label.Description());
   return(true);
  }

Hier muss ebenfalls die Nachricht gesendet werden, falls die Bewegung des Slider Läufers stoppt. Die CSlider::ZeroThumbVariables() Methode bietet sich hier am besten an. Sie wird in der CSlider::CheckMouseButtonState() Methode aufgerufen, in dem Bereich für die Protokollierung der linken Maustaste. Der Aufruf der CSlider::ZeroThumbVariables() Methode, beinhaltet schon den Fall, dass die linke Maustaste losgelassen wurde. Falls die Maustaste über dem Bereich des Slider-Läufers gedrückt wurde, bedeutet das, dass die Veränderung der Position des Slider-Läufers abgeschlossen ist und eine Nachricht über die Veränderung des Wertes in dem Eingabefeld gesendet werden muss.

//+---------------------------------------------------------------------------+
//| Zurücksetzen der Variablen in Zusammenhang mit der Bewegung der Scrollbar |
//+---------------------------------------------------------------------------+
void CSlider::ZeroThumbVariables(void)
  {
//--- Wenn wir uns hier befinden, bedeutet das, dass die linke Maustaste losgelassen wurde.
//    Falls die linke Maustaste über dem Slider-Läufer gedrückt wurde...
   if(m_clamping_area_mouse==THUMB_PRESSED_INSIDE)
     {
      //--- ... Senden einer Nachricht über die Veränderung des Wertes in dem Eingabefeld (nach abgeschlossener Bewegung des Slider-Läufers)
      ::EventChartCustom(m_chart_id,ON_END_EDIT,CElement::Id(),CElement::Index(),m_label.Description());
     }
//---
   m_slider_size_fixing  =0;
   m_clamping_area_mouse =THUMB_NOT_PRESSED;
//--- Falls der Element-Bezeichner dem aktivierenden Bezeichner entspricht,
//    Entsperren des Formulars und zurücksetzen des Bezeichners des aktivierenden Elementes
   if(CElement::Id()==m_wnd.IdActivatedElement())
     {
      m_wnd.IsLocked(false);
      m_wnd.IdActivatedElement(WRONG_VALUE);
     }
  }

Der vollständige Programmcode des CSlider::OnEvent() Eventhandlers sieht in unserem Falle wie folgt aus:

//+------------------------------------------------------------------+
//| Chart Eventhandler                                               |
//+------------------------------------------------------------------+
void CSlider::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Verarbeiten des Mauszeiger Bewegungs Events
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      //--- Abbrechen, falls das Element versteckt ist     
      if(!CElement::IsVisible())
         return;
      //---Koordinaten und der Status der linken Maustaste
      int x=(int)lparam;
      int y=(int)dparam;
      m_mouse_state=(bool)int(sparam);
      //--- Überprüfung des Fokus über dem Element
      CElement::MouseFocus(x>X() && x<X2() && y>Y() && y<Y2());
      m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && 
                         y>m_thumb.Y() && y<m_thumb.Y2());
      //--- Abbrechen, falls das Element gesperrt ist
      if(!m_slider_state)
         return;
      //--- Überprüfen und Abspeichern des Status der linken Maustaste
      CheckMouseButtonState();
      //--- Verändern der Farbe des Slider-Läufers
      ChangeThumbColor();
      //--- Falls das Management der Slider-Linie übergeben wurde, Identifizierung der Position
      if(m_clamping_area_mouse==THUMB_PRESSED_INSIDE)
        {
         //--- Bewegendes Slider-Läufers
         OnDragThumb(x);
         //--- Berechnung der Slider-Läufer-Position in der Werte Spanne
         CalculateThumbPos();
         //--- Setzen eines neuen Wertes in dem Eingabefeld
         ChangeValue(m_current_pos);
         //--- Aktualisierung des Slider-Indikators
         UpdateIndicator();
         return;
        }
     }
//--- Verarbeiten des Events über die Veränderung des Wertes in dem Eingabefeld
   if(id==CHARTEVENT_OBJECT_ENDEDIT)
     {
      //--- Verarbeiten der Eingabe des Wertes
      if(OnEndEdit(sparam))
         return;
     }
  }

Wir haben nun die Methoden für die Erzeugung und der Verwaltung des Slider-Elementes implementiert. Lassen Sie uns dieses nun in einer MQL Anwendung, die wir schon aus den vorherigen Artikeln kennen, testen. 

 


Test des Slider Control

In dem vorherigen Artikel haben wir innerhalb unserer Testanwendung vier Checkboxen erzeugt, die die Verfügbarkeit andere Elemente gesteuert haben. Wir fügen jetzt noch das Slider-Element und eine fünfte Checkbox für die Verwaltung der Verfügbarkeit dem grafischen Interface hinzu. Deklarieren Sie dafür in der CProgram Klasse die Instanzen der CCheckBox und CSlider Klassen, sowie Methoden für die Ränder von der Ecke des Formulars zu welchem dieses Control hinzugefügt wird.

//+------------------------------------------------------------------+
//| Kasse für das erzeugende Anwendung                               |
//+------------------------------------------------------------------+
class CProgram : public CWndEvents
  {
private:
   //--- Checkboxen
   CCheckBox         m_checkbox5;
   //--- Sliders
   CSlider           m_slider1;
   //---
private:
   //--- Checkboxen
#define CHECKBOX5_GAP_X       (7)
#define CHECKBOX5_GAP_Y       (200)
   bool              CreateCheckBox5(const string text);
   //--- Sliders
#define SLIDER1_GAP_X         (32)
#define SLIDER1_GAP_Y         (225)
   bool              CreateSlider1(const string text);
  };

Die Methoden für die Erzeugung der Checkboxen haben wir schon in den vorangegangenen Artikel besprochen. Aus diesem Grunde gehen wir nun direkt zu der Methode für die Erzeugung des CProgram::CreateSlider1()-Elementes über. Unter der Verwendung der CSlider::MinValue() und CSlider::MaxValue() Methoden, setzen wir eine Werte-Spanne von -1 bis 1. Die Schrittgrösse legen wir auf die 8. Nachkommastelle fest (0.00000001). Die Verfügbarkeit hängt von dem Status der fünften Checkbox ab..

//+------------------------------------------------------------------+
//| Erzeugt slider 1                                                 |
//+------------------------------------------------------------------+
bool CProgram::CreateSlider1(const string text)
  {
//--- Abspeichern des Fenster-Pointers
   m_slider1.WindowPointer(m_window1);
//--- Koordinaten
   int x=m_window1.X()+SLIDER1_GAP_X;
   int y=m_window1.Y()+SLIDER1_GAP_Y;
//--- Wert
   double v=(m_slider1.GetValue()==WRONG_VALUE) ? 0.84615385 : m_slider1.GetValue();
//--- Festlegen der Eigenschaften vor der Erzeugung
   m_slider1.XSize(264);
   m_slider1.YSize(40);
   m_slider1.EditXSize(87);
   m_slider1.MaxValue(1);
   m_slider1.StepValue(0.00000001);
   m_slider1.MinValue(-1);
   m_slider1.SetDigits(8);
   m_slider1.SetValue(v);
   m_slider1.AreaColor(clrWhiteSmoke);
   m_slider1.LabelColor(clrBlack);
   m_slider1.LabelColorLocked(clrSilver);
   m_slider1.EditColorLocked(clrWhiteSmoke);
   m_slider1.EditBorderColor(clrSilver);
   m_slider1.EditBorderColorLocked(clrSilver);
   m_slider1.EditTextColorLocked(clrSilver);
   m_slider1.SlotLineDarkColor(clrSilver);
   m_slider1.SlotLineLightColor(clrWhite);
   m_slider1.SlotYSize(4);
   m_slider1.ThumbColorLocked(clrLightGray);
   m_slider1.ThumbColorPressed(clrSilver);
   m_slider1.SlotIndicatorColor(C'85,170,255');
   m_slider1.SlotIndicatorColorLocked(clrLightGray);
//--- Erzeugung des Controls
   if(!m_slider1.CreateSlider(m_chart_id,m_subwin,text,x,y))
      return(false);
//--- Die Verfügbarkeit hängt von dem Status der fünften Checkbox ab
   m_slider1.SliderState(m_checkbox5.CheckButtonState());
//--- Hinzufügen des Objektes zu dem gemeinsamen Array von Objektgruppen
   CWndContainer::AddToElementsArray(0,m_slider1);
   return(true);
  }

Die neuen Methoden für das Erzeugen des Elementes müssen in der Hauptmethode für das Erzeugen des grafischen Interfaces aufgerufen werden. Nachfolgend ist der Code einer verkürzten Version dieser Methode:

//+------------------------------------------------------------------+
//| 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
//--- Checkboxen
   if(!CreateCheckBox5("Checkbox 5"))
      return(false);
//--- Sliders
   if(!CreateSlider1("Slider 1:"))
      return(false);
//--- Neuzeichnen des Charts
   m_chart.Redraw();
   return(true);
  }

Wir protokollieren die Veränderung des Status der fünften Checkbox für das Steuern der Verfügbarkeit des Sliders in dem CProgram::OnEvent() Eventhandler der Anwendung. Das Event mit dem Bezeichner ON_END_EDIT Gibt uns einen Hinweis darauf, dass sich der Wert in dem Eingabefeld geändert hat.

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Das Event für ein Klick auf das Textlabel
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
      //--- Falls auf die fünfte Checkbox geklickt wurde
      if(lparam==m_checkbox5.Id())
        {
         //--- Setzen des Status des ersten Sliders
         m_slider1.SliderState(m_checkbox5.CheckButtonState());
        }
     }
//--- Das Ende der Eingabe eines Wertes in dem Eingabefeld (Event)
   if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
     }
  }

Nun kann das Programm kompiliert und auf den Chart geladen werden. Versuchen Sie mit den Controls des grafischen Interfaces dieser Anwendung zu arbeiten. Wenn wir alles richtig gemacht haben, dann sollte das Ergebnis wie in dem nachfolgenden Screenshot gezeigt aussehen:

 Abbildung  2. Test des Slider-Controls.

Abbildung 2. Test des Slider-Controls. 

 


Das Dual-Slider-Control

Der Unterschied zwischen einem Dual-Slider und einem einfachen Slider ist, dass der Dual Slider die Auswahl einer Werte-Spanne ermöglicht. Aus diesem Grunde gibt es auf der Slider-Linie zwei Slider-Läufer. Der linke Slider-Läufer kann von der linken Seite bis zu dem rechten Slider-Läufer bewegt werden. Der rechte Slider-Läufer kann von der rechten Seite bis zu dem linken Slider-Läufer bewegt werden. Ein Dual-Slider hat auch zwei Eingabefelder, welche die Werte der Positionen der Slider-Läufer repräsentieren. In diesen Eingabefeldern können Werte manuell eingegeben werden. Dieses führt natürlich zu einer veränderten Position der Slider-Läufer.

Dieses Control wird aus acht einfachen grafischen Objekten zusammengestellt. :Diese sind:

  1. Hintergrund
  2. Beschriftung (text label).
  3. Linkes Eingabefeld.
  4. Rechtes Eingabefeld
  5. Slider Linie.
  6. Linker Slider-Läufer.
  7. Rechter Slider-Läufer
  8. Slider-Indikator.

Abbildung 3. Die Komponenten eines Dual-Slider-Controls

Lassen Sie uns die Klasse für einen Dual-Slider anschauen und die Unterschiede zu dem einfachen Slider aufzeigen.

 


Entwickeln einer Klasse für die Erzeugung des Dual-Slider-Control

Beziehen Sie die DualSlider.mqh Datei mit in der CDualSlider Klasse in der WndContainer.mqh Datei mit ein:

//+------------------------------------------------------------------+
//|                                                 WndContainer.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "DualSlider.mqh"

In Bezug auf die Eigenschaften des Controls, ist die CDualSlider Klasse mit der CSlider Klasse identisch. Der einzige Unterschied besteht darin, dass das linke und rechte Eingabefeld und die Slider-Läufer separate Variablen und Methoden benötigen. Die Unterschiede zwischen diesen Methoden sind aber unwesentlich und aus diesem Grunde werden wir hier nicht weiter darauf eingehen. Sie finden den Programmcode in den angehängten Dateien.

class CDualSlider : public CElement
  {
private:
   //--- Die aktuellen Werte in den Eingabefeldern (Links und rechts)
   double            m_left_edit_value;
   double            m_right_edit_value;
   //--- Die aktuellen Positionen der Slider-Läufer(Links und rechts)
   double            m_left_current_pos;
   double            m_left_current_pos_x;
   double            m_right_current_pos;
   double            m_right_current_pos_x;
   //--- Status der Maustaste (Gedrückt/nicht gedrückt) Für die Slider Läufer (Links und rechts)
   ENUM_THUMB_MOUSE_STATE m_clamping_mouse_left_thumb;
   ENUM_THUMB_MOUSE_STATE m_clamping_mouse_right_thumb;
   //---
public:
   //--- Rückgabe und setzen der Werte in den Eingabefeldern (Links und rechts)
   double            GetLeftValue(void)                       const { return(m_left_edit_value);          }
   double            GetRightValue(void)                      const { return(m_right_edit_value);         }
   bool              SetLeftValue(double value);
   bool              SetRightValue(double value);
   //--- Verändern der Werte in den Eingabefeldern (Links und rechts)
   void              ChangeLeftValue(const double value);
   void              ChangeRightValue(const double value);
   //---
private:
   //--- Vorgang für das Bewegen der Slider-Läufer (Links und rechts)
   void              OnDragLeftThumb(const int x);
   void              OnDragRightThumb(const int x);
   //---Aktualisieren der Position der Slider-Läufer  (Links und rechts)
   void              UpdateLeftThumb(const int new_x_point);
   void              UpdateRightThumb(const int new_x_point);
   //--- Überprüft den Status der linken Maustaste über einen Slider-Läufer
   void              CheckMouseOnLeftThumb(void);
   void              CheckMouseOnRightThumb(void);
   //--- Berechnung der X Koordinaten der Slider (Links und rechts)
   void              CalculateLeftThumbX(void);
   void              CalculateRightThumbX(void);
   //--- Verändert die Position des linken Slider-Läufers in Relation zu dem Wert (Links und rechts)
   void              CalculateLeftThumbPos(void);
   void              CalculateRightThumbPos(void);
  };

Hier zeigen wir nur den Programmcode der Methoden, wo zwei Eingabefelder und die Slider-Läufer behandelt werden. Nachfolgend ist die Struktur der CDualSlider::OnEndEdit() Methode dargestellt:

class CDualSlider : public CElement
  {
private:
   //--- Verarbeiten der manuellen Eingabe eines neuen Wertes
   bool              OnEndEdit(const string object_name);
  };
//+------------------------------------------------------------------+
//| Abschließen der Eingabe eines Wertes                             |
//+------------------------------------------------------------------+
bool CDualSlider::OnEndEdit(const string object_name)
  {
//--- Falls der Wert in dem linken Eingabefeld eingegeben wurde
   if(object_name==m_left_edit.Name())
     {
      //--- Abfrage des eingegebenen Wertes
      double entered_value=::StringToDouble(m_left_edit.Description());
      //--- Überprüfen, Einstellen und Abspeichern des neuen Wertes
      ChangeLeftValue(entered_value);
      //--- Berechnen der x-Koordinate des Slider-Läufers
      CalculateLeftThumbX();
      //--- Aktualisierung der Position des Slider-Läufers
      UpdateLeftThumb(m_left_thumb.X());
      //--- Berechnen der Position in der Werte-Spanne
      CalculateLeftThumbPos();
      //--- Überprüfen, Einstellen und Abspeichern des neuen Wertes
      ChangeLeftValue(m_left_current_pos);
      //--- Aktualisierung des Slider-Indikators
      UpdateIndicator();
      //--- Eine Nachricht darüber senden
      ::EventChartCustom(m_chart_id,ON_END_EDIT,CElement::Id(),CElement::Index(),m_label.Description());
      return(true);
     }
//--- Falls der Wert in dem rechten Eingabefeld eingegeben wurde
   if(object_name==m_right_edit.Name())
     {
      //--- Abfrage des eingegebenen Wertes
      double entered_value=::StringToDouble(m_right_edit.Description());
      //--- Überprüfen, Einstellen und Abspeichern des neuen Wertes
      ChangeRightValue(entered_value);
      //--- Berechnen der x-Koordinate des Slider-Läufers
      CalculateRightThumbX();
      //--- Aktualisierung der Position des Slider-Läufers
      UpdateRightThumb(m_right_thumb.X());
      //--- Berechnen der Position in der Werte-Spanne
      CalculateRightThumbPos();
      //--- Überprüfen, Einstellen und Abspeichern des neuen Wertes
      ChangeRightValue(m_right_current_pos);
      //--- Aktualisierung des Slider-Indikators
      UpdateIndicator();
      //--- Eine Nachricht darüber senden
      ::EventChartCustom(m_chart_id,ON_END_EDIT,CElement::Id(),CElement::Index(),m_label.Description());
      return(true);
     }
//---
   return(false);
  }

Das gleiche wird bei der Bewegung des linken und rechten Läufers angewendet. Der CDualSlider::OnEvent() Eventhandler besitzt für jeden von ihnen einen eigenen Codeblock: 

//+-----------------------------------------------------------------+
//| Chart Eventhandler                                              |
//+-----------------------------------------------------------------+
void CDualSlider::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Verarbeiten des Mauszeiger Bewegungs Events
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      //--- Abbrechen, falls das Element versteckt ist   
      if(!CElement::IsVisible())
         return;
      //---Koordinaten und der Status der linken Maustaste
      int x=(int)lparam;
      int y=(int)dparam;
      m_mouse_state=(bool)int(sparam);
      //--- Überprüfung des Fokus über dem Element
      CElement::MouseFocus(x>X() && x<X2() && y>Y() && y<Y2());
      m_left_thumb.MouseFocus(x>m_left_thumb.X() && x<m_left_thumb.X2() && 
                              y>m_left_thumb.Y() && y<m_left_thumb.Y2());
      m_right_thumb.MouseFocus(x>m_right_thumb.X() && x<m_right_thumb.X2() && 
                               y>m_right_thumb.Y() && y<m_right_thumb.Y2());
      //--- Abbrechen, falls das Element gesperrt ist
      if(!m_slider_state)
         return;
      //--- Überprüfen und Abspeichern des Status der linken Maustaste
      CheckMouseOnLeftThumb();
      CheckMouseOnRightThumb();
      //--- Verändern der Farbe des Slider-Läufers
      ChangeThumbColor();
      //--- Falls die Verwaltung an die Slider-Linie übergeben wurde (Linker Slider-Läufer)
      if(m_clamping_mouse_left_thumb==THUMB_PRESSED_INSIDE)
        {
         //--- Bewegendes Slider-Läufers
         OnDragLeftThumb(x);
         //--- Berechnung der Slider-Läufer-Position in der Werte Spanne
         CalculateLeftThumbPos();
         //--- Setzen eines neuen Wertes in dem Eingabefeld
         ChangeLeftValue(m_left_current_pos);
         //--- Aktualisierung des Slider-Indikators
         UpdateIndicator();
         return;
        }
      //--- Falls die Verwaltung dem rechten Slider-Läufer übergeben wurde
      if(m_clamping_mouse_right_thumb==THUMB_PRESSED_INSIDE)
        {
         //--- Bewegendes Slider-Läufers
         OnDragRightThumb(x);
         //--- Berechnung der Slider-Läufer-Position in der Werte Spanne
         CalculateRightThumbPos();
         //--- Setzen eines neuen Wertes in dem Eingabefeld
         ChangeRightValue(m_right_current_pos);
         //--- Aktualisierung des Slider-Indikators
         UpdateIndicator();
         return;
        }
     }
  }

Sie können die Dateien die diesem Artikel beigefügt sind herunterladen und den Programmcode derCDualSlider Klasse im Detail studieren. 

 


Test des Dual-Slider-Controls

Fügen Sie das Dual-Slider-Control dem grafischen Interface unserer Test-Anwendung hinzu. Deklarieren Sie eine Instanz der CDualSlider Und eine Methode mit den Rändern von der Ecke des Formulars in der CProgram benutzerdefinierten Klasse der Anwendung:

//+-----------------------------------------------------------------+
//| Kasse für das erzeugende Anwendung                              |
//+-----------------------------------------------------------------+
class CProgram : public CWndEvents
  {
private:
   //--- Sliders
   CDualSlider       m_dual_slider1;
   //---
private:
   //--- Sliders
#define DUALSLIDER1_GAP_X     (32)
#define DUALSLIDER1_GAP_Y     (275)
   bool              CreateDualSlider1(const string text);
  };

Der nachfolgende Programmcode zeigt den Code der CProgram::CreateDualSlider1() Methode. Legen Sie die Wertebereich von -2000 bis 1000 fest. Die Verfügbarkeit dieses Controls hängt ebenfalls von dem aktuellen Status der fünften Checkbox ab.

//+-----------------------------------------------------------------+
//| Erzeugt den Dual-Slider 1                                       |
//+-----------------------------------------------------------------+
bool CProgram::CreateDualSlider1(const string text)
  {
//--- Abspeichern des Fenster-Pointers
   m_dual_slider1.WindowPointer(m_window1);
//--- Koordinaten
   int x=m_window1.X()+DUALSLIDER1_GAP_X;
   int y=m_window1.Y()+DUALSLIDER1_GAP_Y;
//--- Werte
   double v1=(m_dual_slider1.GetLeftValue()==WRONG_VALUE) ? 0 : m_dual_slider1.GetLeftValue();
   double v2=(m_dual_slider1.GetRightValue()==WRONG_VALUE) ? 500 : m_dual_slider1.GetRightValue();
//--- Festlegen der Eigenschaften vor der Erzeugung
   m_dual_slider1.XSize(264);
   m_dual_slider1.YSize(40);
   m_dual_slider1.EditXSize(87);
   m_dual_slider1.MaxValue(1000);
   m_dual_slider1.StepValue(1);
   m_dual_slider1.MinValue(-2000);
   m_dual_slider1.SetDigits(0);
   m_dual_slider1.SetLeftValue(v1);
   m_dual_slider1.SetRightValue(v2);
   m_dual_slider1.AreaColor(clrWhiteSmoke);
   m_dual_slider1.LabelColor(clrBlack);
   m_dual_slider1.LabelColorLocked(clrSilver);
   m_dual_slider1.EditColorLocked(clrWhiteSmoke);
   m_dual_slider1.EditBorderColor(clrSilver);
   m_dual_slider1.EditBorderColorLocked(clrSilver);
   m_dual_slider1.EditTextColorLocked(clrSilver);
   m_dual_slider1.SlotLineDarkColor(clrSilver);
   m_dual_slider1.SlotLineLightColor(clrWhite);
   m_dual_slider1.SlotYSize(4);
   m_dual_slider1.ThumbColorLocked(clrLightGray);
   m_dual_slider1.ThumbColorPressed(clrSilver);
   m_dual_slider1.SlotIndicatorColor(C'85,170,255');
   m_dual_slider1.SlotIndicatorColorLocked(clrLightGray);
//--- Erzeugung des Controls
   if(!m_dual_slider1.CreateSlider(m_chart_id,m_subwin,text,x,y))
      return(false);
//--- Die Verfügbarkeit hängt von dem Status der fünften Checkbox ab
   m_dual_slider1.SliderState(m_checkbox5.CheckButtonState());
//--- Hinzufügen des Objektes zu dem gemeinsamen Array von Objektgruppen
   CWndContainer::AddToElementsArray(0,m_dual_slider1);
   return(true);
  }

Vergessen Sie nicht den Aufruf der Methode für das Erzeugen des neuen Controls in der Hauptmethode für das Erzeugen des grafischen Interfaces hinzuzufügen. 

//+------------------------------------------------------------------+
//| 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
//--- Checkboxen
//--- Sliders
   if(!CreateDualSlider1("Dual Slider 1:"))
      return(false);
//--- Neuzeichnen des Charts
   m_chart.Redraw();
   return(true);
  }

Jetzt steuert der Status der fünften Checkbox zwei Controls- Den einfachen Schieberegler und den doppelten Schieberegler.

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Das Event für ein Klick auf das Textlabel
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
      //--- Falls auf die fünfte Checkbox geklickt wurde
      if(lparam==m_checkbox5.Id())
        {
         //--- Setzen des Status für die Schieberegler
         m_slider1.SliderState(m_checkbox5.CheckButtonState());
         m_dual_slider1.SliderState(m_checkbox5.CheckButtonState());
        }
     }
//--- Das Ende der Eingabe eines Wertes in dem Eingabefeld (Event)
   if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
     }
  }

Kompilieren Sie dieses Programm und laden Sie es auf einen Chart. Der nachfolgende Screenshot zeigt das Resultat:

 Abbildung 4. Der doppelte Schieberegler.

Abbildung 4. Der doppelte Schieberegler.

 


Schlussfolgerung

In dem sechsten Teil dieser Serie haben wir sechs Controls betrachtet:

  • Checkbox.
  • Das Edit-Control
  • Edit mit Checkbox
  • Check Combobox
  • Schlieberegler (Slider).
  • Doppelter Schieberegler (Dual slider).

Zur Zeit sieht das schematische Diagramm unserer Bibliothek für das Erzeugen von grafischen Interfaces wie folgt aus:

 Abbildung 5. Die Struktur unserer Bibliothek zum aktuellen Stand der Entwicklung

Abbildung 5. Die Struktur unserer Bibliothek zum aktuellen Stand der Entwicklung

In den nächsten Teil unserer Serie werden wir unsere Bibliothek mit Tabellen und Tabs erweitern.

Sie können das gesamte Material des sechsten 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 (Kapitel) des sechten Teils:


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

Beigefügte Dateien |
Verwendung von Textdateien zum Speichern von Eingabeparametern von Expert Advisors, Indikatoren und Skripts Verwendung von Textdateien zum Speichern von Eingabeparametern von Expert Advisors, Indikatoren und Skripts
Der Artikel beschreibt die Anwendung von Textdateien zum Speichern von dynamischen Objekten, Arrays und anderen Variablen die als Eigenschaften für Expert Advisors, Indikatoren und Skripts verwendet werden. Die Dateien dienen als eine bequeme Erweiterung der Funktionalität der Standardtools, die von der MQL-Sprache angeboten werden.
Graphische Interfaces VI: Das Checkbox Control, Das Edit Control und deren gemischte Typen (Kapitel 1) Graphische Interfaces VI: Das Checkbox Control, Das Edit Control und deren gemischte Typen (Kapitel 1)
Dieser Artikel ist der Anfang des 6. Teils dieser Serie, welche der Entwicklung einer Bibliothek für die Erzeugung von grafischen Interfaces im Metatrader-Terminal gewidmet ist. In dem ersten Kapitel werden wir das Checkbox-Control, dass Edit-Control und deren gemischte Typen besprechen.
Arbeiten mit Sockets in MQL, oder Wie man ein Signalprovider wird Arbeiten mit Sockets in MQL, oder Wie man ein Signalprovider wird
Sockets… Was in unserer IT-Welt könnte ohne sie auskommen? Seit 1982 und bis heute kaum verändert arbeiten sie ununterbrochen jede Sekunde für uns. Dies ist die Grundlage des Netzwerks, die Nervenenden der Matrix, in der wir alle Leben.
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.