Graphische Interfaces VI: Das Checkbox Control, Das Edit Control und deren gemischte Typen (Kapitel 1)
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.
Der sechste Teil dieser Serie wird aus zwei Kapiteln bestehen. In dem ersten Kapitel, werden wir vier Controls (Steuerelemente) erzeugen:
- Checkbox
- Edit
- Edit mit Checkbox
- Check Combobox
Wir werden hier nur die Checkbox und das Edit-Control besprechen, da ein Edit mit Checkbox und eine Checkcombobox nichts beinhaltet, was zuvor nicht schon betrachtet wurde.
Der zweite Artikel wird den folgenden Elementen gewidmet:
- Slider
- Doppel Slider
Das Checkbox-Control
Die Checkbox wird für die Verwaltung und Steuerung von Parameter entworfen, die nur zwei Zustände annehmen können. Hierfür wird ein Button mit zwei Icons verwendet, damit der aktuelle Status des Parameters, mit welchem dieses Control verbunden wurde, angezeigt werde kann. Das Icon mit dem Check-Symbol bedeutet, dass der Parameter aktiviert ist (an). Das Icon ohne dem Check-Symbol bedeutet, dass der Parameter deaktiviert ist (aus) Neben dem Button befindet sich eine kurze Beschriftung.
Dieses Element wird aus drei grafischen Objekten zusammengesetzt. :Diese sind:
- Hintergrund
- Icon (Button)
- Text Label
Abbildung 1. Die zusammengesetzten Teile des Checkbox-Controls
Lassen Sie uns die Klasse dieses Controls näher anschauen.
Entwicklung einer Klasse für die Erzeugung des Checkbox-Controls
In den dritten Teil dieser Serie haben wir über ein ähnliches Control gesprochen - einen Icon-Button und seine Klasse CIconButton (Sehen Sie hierzu den Artikel Graphische Interfaces III: Einfache und multifunktionale Buttons (Kapitel 1)). Das Checkbox-Control ist dem Icon-Button mit seinen zwei Zuständen sehr ähnlich. Der einzige Unterschied ist hier, dass ein Button in seinen unterschiedlichen Zuständen unterschiedliche Hintergrundfarben und Textfarben besitzt (Falls diese angegeben wurden), und im Falle einer Checkbox kann sich nur das Icon und die Textfarbe ändern (Falls diese angegeben wurden). Die Hintergrundfarbe der Checkbox wird die gleiche sein, wie die Hintergrundfarbe des Fensters, zu welchem sie hinzugefügt wurde. Der Hintergrund wird hier dafür verwendet, um den Bereich für den Maus-Cursor zu identifizieren und um den den Status der linken Maustaste zu erfassen. Das Checkbox Control ist einfacher als ein Icon-Button, da er weniger Eigenschaften besitzt, die ein User festlegen kann.
Erzeugen Sie die CheckBox.mqh Datei und beziehen Sie diese Datei mit in der WndContainer.mqh Datei unserer Bibliothek mit ein:
//+------------------------------------------------------------------+ //| WndContainer.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "CheckBox.mqh"
Erzeugen Sie die CCheckBox Klasse mit den Standardmethoden für alle Elemente der Bibliothek in der CheckBox.mqh Datei:
//+------------------------------------------------------------------+ //| CheckBox.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "Element.mqh" #include "Window.mqh" //+------------------------------------------------------------------+ //| Klasse für das Erzeugen einer Checkbox | //+------------------------------------------------------------------+ class CCheckBox : public CElement { private: //--- Ein Pointer zu der Form zu welchem das Element hinzugefügt worden ist CWindow *m_wnd; //--- public: CCheckBox(void); ~CCheckBox(void); //--- 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) Setzen, (2) Zurücksetzen der Priorität der linken Maustaste virtual void SetZorders(void); virtual void ResetZorders(void); //--- Zurücksetzen der Farbe virtual void ResetColors(void); };
Bevor dieses Control erzeugt wird, kann der User noch über verschiedene Methoden die nachfolgenden Eigenschaften festlegen:
- Den Hintergrund
- Die Icons für die Checkbox in dem aktiven und in dem gesperrten Status
- Die Abstände für das Textlabel
- Die Farben für das Textlabel für die zwei unterschiedlichen Zustände
Es wird vier Icons für die Checkbox geben, zwei Icons für den aktiven Status und zwei für den gesperrten Status. Alle hier verwendeten Icons können wir am Ende dieses Artikels herunterladen und verwenden.
class CCheckBox : public CElement { private: //--- Hintergrundfarbe der Checkbox color m_area_color; //--- Die Icons für den aktiven und gesperrten Status string m_check_bmp_file_on; string m_check_bmp_file_off; string m_check_bmp_file_on_locked; string m_check_bmp_file_off_locked; //--- Text der Checkbox string m_label_text; //--- Die Ränder des Text Labels int m_label_x_gap; int m_label_y_gap; //--- Die Farben für das Textlabel für die unterschiedlichen Zustände color m_label_color; color m_label_color_off; color m_label_color_hover; color m_label_color_locked; color m_label_color_array[]; //--- Priorität für die linke Maustaste int m_zorder; int m_area_zorder; //--- public: //--- Festlegen der Labels für den Button in dem aktiven und in dem gesperrten Status void CheckFileOn(const string file_path) { m_check_bmp_file_on=file_path; } void CheckFileOff(const string file_path) { m_check_bmp_file_off=file_path; } void CheckFileOnLocked(const string file_path) { m_check_bmp_file_on_locked=file_path; } void CheckFileOffLocked(const string file_path) { m_check_bmp_file_off_locked=file_path; } //--- (1) Hintergrundfarbe, (2) Abstände für das Text-Label void AreaColor(const color clr) { m_area_color=clr; } 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 für den Text in den unterschiedlichen Zuständen void LabelColor(const color clr) { m_label_color=clr; } void LabelColorOff(const color clr) { m_label_color_off=clr; } void LabelColorHover(const color clr) { m_label_color_hover=clr; } void LabelColorLocked(const color clr) { m_label_color_locked=clr; } //--- Beschreibung der Checkbox string LabelText(void) const { return(m_label.Description()); } };
Für die Erzeugung der Checkbox, benötigen wir drei private Methoden und eine public Methode:
class CCheckBox : public CElement { private: //--- Objekte für das Erzeugen einer Checkbox CRectLabel m_area; CBmpLabel m_check; CLabel m_label; //--- public: //--- Methoden für das Erzeugen einer Checkbox bool CreateCheckBox(const long chart_id,const int subwin,const string text,const int x,const int y); //--- private: bool CreateArea(void); bool CreateCheck(void); bool CreateLabel(void); };
Lassen Sie uns die CCheckBox::CheckButtonState() und die CCheckBox::CheckBoxState() Methoden für das Verwalten des Status der Checkbox erzeugen:
class CCheckBox : public CElement { private: //--- Status des Checkbox button bool m_check_button_state; //--- Checkbox Status (Verfügbar/gesperrt) bool m_checkbox_state; //--- public: //--- Setzen und Abfragen des Status der Checkbox bool CheckBoxState(void) const { return(m_checkbox_state); } void CheckBoxState(const bool state); //--- Setzen und Abfragen des Status des Checkbox-Buttons bool CheckButtonState(void) const { return(m_check.State()); } void CheckButtonState(const bool state); };
Um das Control zu blockieren und zu entsperren, verwenden Sie die CCheckBox::CheckBoxState() Methode:
//+-----------------------------------------------------------------+ //| Festlegen des Status des Controls | //+-----------------------------------------------------------------+ void CCheckBox::CheckBoxState(const bool state) { //--- Status des Controls m_checkbox_state=state; //--- Icon m_check.BmpFileOn((state)? "::"+m_check_bmp_file_on : "::"+m_check_bmp_file_on_locked); m_check.BmpFileOff((state)? "::"+m_check_bmp_file_off : "::"+m_check_bmp_file_off_locked); //--- Farbe des Text Labels m_label.Color((state)? m_label_color : m_label_color_locked); }
Um den Status des Checkbox-Buttons zu setzen, verwenden Sie die CCheckBox::CheckButtonState() Methode:
//+-----------------------------------------------------------------+ //| Setzen des Status des Checkbox-Buttons | //+-----------------------------------------------------------------+ void CCheckBox::CheckButtonState(const bool state) { //--- Verlassen, falls das Control gesperrt ist if(!m_checkbox_state) return; //--- Setzen des Status des Buttons m_check.State(state); m_check_button_state=state; //--- Wechseln der Farbe, entsprechend dem aktuellen Status m_label.Color((state)? m_label_color : m_label_color_off); CElement::InitColorArray((state)? m_label_color : m_label_color_off,m_label_color_hover,m_label_color_array); }
Wir müssen lediglich noch eine Methode für das Verwalten eines Klicks auf das Control erzeugen. Diese Methode wird indem Haupt-Eventhandler des Controls CCheckBox::OnEvent() Über das Event mit dem CHARTEVENT_OBJECT_CLICK Bezeichner aufgerufen. Lassen Sie sie uns CCheckBox::OnClickLabel() nennen. Zunächst wird eine Überprüfung vorgenommen, ob der Klick über dem Bereich des Controls lag (dem Hintergrund). Um eindeutig unterscheiden zu können, über welchen Control ein Klick stattgefunden hat, bekommt der Hintergrund die Priorität (der linken Maustatse) eins und die anderen Objekte den Wert 0. Daher wird auch ein Klick auf den Checkbox-Button oder auf das Text-Label wie ein Klick auf das Control behandelt, da der Hintergrund die höchste Priorität hat. Anschließend verwenden wir die CCheckBox::CheckButtonState() Methode um den Status entgegengesetzt des Checkbox-Buttons zu setzen. Am Ende der Methode senden wir ein a custom event mit (1) dem Bezeichner ON_CLICK_LABEL, (2) dem Bezeichner des Elementes (3) Und der Beschreibung des Elementes.
class CCheckBox : public CElement { private: //--- Verarbeitung eines Klicks auf das Element bool OnClickLabel(const string clicked_object); }; //+-----------------------------------------------------------------+ //| Event handling | //+-----------------------------------------------------------------+ void CCheckBox::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Verarbeiten eines Klicks mit der linken Maustaste auf ein Objekt if(id==CHARTEVENT_OBJECT_CLICK) { //--- Klick auf eine Checkbox if(OnClickLabel(sparam)) return; } } //+-----------------------------------------------------------------+ //| Klick auf ein Element Label | //+-----------------------------------------------------------------+ bool CCheckBox::OnClickLabel(const string clicked_object) { //--- Abbrechen, falls die Namen unterschiedlich sind if(m_area.Name()!=clicked_object) return(false); //--- Verlassen, falls das Control gesperrt ist if(!m_checkbox_state) return(false); //--- In den entgegengesetzten Zustand wechseln CheckButtonState(!m_check.State()); //--- Der Mauszeiger befindet sich aktuell über dem Element m_label.Color(m_label_color_hover); //--- Eine Nachricht darüber senden ::EventChartCustom(m_chart_id,ON_CLICK_LABEL,CElement::Id(),0,m_label.Description()); return(true); }
Test des Checkbox-Controls
Alle Methoden für die CCheckBox Klasse sind nun fertig und somit können wir jetzt testen, ob dieses Control funktioniert. Die Datei mit der Klasse dieses Kontos muss bereits in der Bibliothek mit einbezogen sein. Für den Test kann der EA aus dem vorherigen Artikel kopiert werden. Entfernen Sie hier alle Controls, mit Ausnahme des Hauptmenüs und der Statusbar. Erzeugen sie für den Test zwei Checkboxen Stellen Sie sicher, dass die zweite Checkbox blockiert ist, während das Programm startet. Die erste Checkbox ist für die Interaktion mit dem User verfügbar, aber sie befindet sich in einem deaktivierten Status. Das Aktivieren der ersten Checkbox ist ein Signal für das Entsperren der zweiten Checkbox. Das gleiche soll auch entgegengesetzt funktionieren - Das Deaktivieren der ersten Checkbox führt zu einem Signal, welches die zweite Checkbox blockiert.
Erzeugen sie in der benutzerdefinierten CProgram Klasse zwei Instanzen der CCheckBox und deklarieren Sie zwei Methoden für das Erzeugen der Checkboxen und spezifizieren Sie die Abstände von der Ecke des Formulars, zu welchem diese hinzugefügt werden:
//+-----------------------------------------------------------------+ //| Kasse für das erzeugende Anwendung | //+-----------------------------------------------------------------+ class CProgram : public CWndEvents { private: //--- Checkboxen CCheckBox m_checkbox1; CCheckBox m_checkbox2; //--- private: //--- Checkboxen #define CHECKBOX1_GAP_X (7) #define CHECKBOX1_GAP_Y (50) bool CreateCheckBox1(const string text); #define CHECKBOX2_GAP_X (30) #define CHECKBOX2_GAP_Y (75) bool CreateCheckBox2(const string text); };
Der einzige Unterschied bei der Implementation der Methoden ist, dass Die Verfügbarkeit der zweiten Checkbox von dem Status der ersten Checkbox abhängt:
//+-----------------------------------------------------------------+ //| Erzeugt Checkbox 2 | //+-----------------------------------------------------------------+ bool CProgram::CreateCheckBox2(string text) { //--- Übergabe des Panel Objektes m_checkbox2.WindowPointer(m_window1); //--- Koordinaten int x=m_window1.X()+CHECKBOX2_GAP_X; int y=m_window1.Y()+CHECKBOX2_GAP_Y; //--- Festlegen der Eigenschaften vor der Erzeugung m_checkbox2.XSize(90); m_checkbox2.YSize(18); m_checkbox2.AreaColor(clrWhiteSmoke); m_checkbox2.LabelColor(clrBlack); m_checkbox2.LabelColorOff(clrBlack); m_checkbox2.LabelColorLocked(clrSilver); //--- Erzeugung des Controls if(!m_checkbox2.CreateCheckBox(m_chart_id,m_subwin,text,x,y)) return(false); //--- Die Verfügbarkeit hängt von dem aktuellen Status der ersten Checkbox ab m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState()); //--- Fügen Sie das Objekt zu dem gemeinsamen Array von Objektgruppen hinzu CWndContainer::AddToElementsArray(0,m_checkbox2); return(true); }
Fügen Sie den Aufruf der Methoden für das Erzeugen der Checkboxen in der Hauptmethode für das Erzeugen des grafischen Interfaces hinzu. Nachfolgend wird eine abgekürzte Version das Programmcodes gezeigt:
//+-----------------------------------------------------------------+ //| Erzeugt das Trading-Panel | //+-----------------------------------------------------------------+ bool CProgram::CreateTradePanel(void) { //--- Erzeugen des Formulars 1 für die Controls //---Erzeugung der Controls: // Hauptmenü //--- Kontextmenüs //--- Erzeugen der Statusbar //--- Checkboxen if(!CreateCheckBox1("Checkbox 1")) return(false); if(!CreateCheckBox2("Checkbox 2")) return(false); //--- Neuzeichnen des Charts m_chart.Redraw(); return(true); }
Wir empfangen und verarbeiten die Nachricht mit dem ON_CLICK_LABEL Bezeichner in dem Eventhandler von der CProgram Klasse. Die Verfügbarkeit der zweiten Checkbox wird über den Status der ersten Checkbox definiert, wie ist auch in dem nachfolgenden Code gezeigt wird:
//+-----------------------------------------------------------------+ //| Eventhandler | //+-----------------------------------------------------------------+ void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Der Event für einen Klick auf die Checkbox if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL) { ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); //--- Falls es sich um einen Klick auf die erste Checkbox handelt if(lparam==m_checkbox1.Id()) { //--- Setzen des Status der zweiten Checkbox m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState()); } } }
Kompilieren Sie die Dateien und laden Sie den EA auf einen Chart. Das Ergebnis sollte so aussehen, wie es in dem nachfolgenden Screenshot gezeigt wird.
Abbildung 2. Test this Checkbox-Controls.
Der Screenshot zeigt, dass die zweite Checkbox gesperrt ist. Den Hinweis darauf sehen wir in der Textfarbe und dem entsprechenden Icon des Buttons (verblasste Fraben). Alles arbeitet einwandfrei und wir fahren daher mit der Entwicklung der Klasse für die Erzeugung eines Edit-Controls fort.
Das Edit-Control
Ein Edit-Control wird dafür verwendet, um einen numerischen Wert in einem Textfeld einzugeben. Der Wert kann manuell eingegeben werden oder mit der Hilfe von Buttons. Der User kann Minimum- und Maximumwerte festlegen, sowie auch die Schrittweite für die Eingabe mit den Buttons. Falls die Buttons mit den Pfeilen einmal gedrückt werden, dann ändert sich der Wert mit der angegebenen Schrittweite. Wenn die Pfeile gedrückt und gehalten werden, dann ändert sich der Wert in dem Edit-Control schnell. Das Verändern des Wertes stoppt, sobald das Minimum oder Maximum erreicht ist.
Dieses Control wird aus fünf grafischen Objekten zusammengesetzt. :Diese sind:
- Hintergrund
- Text Label
- Edit
- Zwei Buttons für das Scrollen der Werte in dem Edit-Control
Abbildung 3. Die Komponenten Edit-Controls
In den nächsten Teil des Artikels, werden wir die Klasse für die Erzeugung dieses Interface Elementes schreiben.
Entwickeln einer Klasse für die Erzeugung des Edit-Controls
Ähnlich wie bei dem Checkbox-Control, ist die Entwicklung des Edit-Controls einfach. Mit anderen Worten, dieses Control wird aus einfachen Objekten zusammengesetzt und beinhaltet keine weiteren Controls. Dieses ist auch der Grund dafür, warum keine weiteren Ergänzungen in der WndContainer.mqh Datei notwendig sind. Wir müssen lediglich die Datei mit der Klasse für das Edit-Control mit einbeziehen.
Erzeugen Sie jetzt die Datei SpinEdit.mqh und binden Sie diese mit in der WndContainer.mqh Datei mit ein:
//+------------------------------------------------------------------+ //| WndContainer.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "SpinEdit.mqh"
Erzeugen sie in der SpinEdit.mqh Datei die CSpinEdit Klasse mit den Standard-Methoden für alle Elemente dieser Bibliothek, so wie in der oben gezeigten Beschreibung der CCheckBox Klasse. Das ist der Grund, warum dir direkt mit der Beschreibung der Eigenschaften des Edit-Controls fortfahren.
Nachfolgend ist eine Liste aller Eigenschaften des Edit-Controls, welche für den Anwender zugänglich sind.
- Die Hintergrundfarbe
- Ein Text mit der Beschreibung des Edit
- Abstände des Textlabel
- Die Farbe des Textes in den unterschiedlichen Zuständen
- Die Größe des Edit
- Die Abstände des Edit-Controls von der rechten Seite des Elementes
- Farben des Edit-Controls in den unterschiedlichen Zuständen
- Farben des Textes in den unterschiedlichen Zuständen
- Farbe des Rahmens in den unterschiedlichen Zuständen
- Die Labels der Schalter in dem aktiven und gesperrten Zustand
- Abstände der Buttons (Von der rechten Seite)
- Der Modus für das Zurücksetzen des Wertes zum Minimum
- Minimum- und Maximumwert
- Schrittweite für das Verändern des Wertes unter Verwendung der Buttons
- Der Modus für die Text-Ausrichtung
- Die Anzahl der Nachkommastellen
Der Nachfolgende Programmcode präsentiert die Variablen und Methoden der Klasse für das Setzen der Eigenschaften des Controls:
//+-----------------------------------------------------------------+ //| Klasse für die Erzeugung des Edit-Controls | //+-----------------------------------------------------------------+ class CSpinEdit : public CElement { private: //--- Farbe des Control-Hintergrundes color m_area_color; //--- Text der Beschreibung des Edit-Controls string m_label_text; //--- Die Ränder des Text Labels int m_label_x_gap; int m_label_y_gap; //--- Die Farbe für den Text in den unterschiedlichen Zuständen color m_label_color; color m_label_color_hover; color m_label_color_locked; color m_label_color_array[]; //--- Die Größe int m_edit_x_size; int m_edit_y_size; //--- Die Abstände des Controls von der rechten Seite int m_edit_x_gap; //--- Die Farbe und der Text des Controls 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 Farbe des Rahmens des controles 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 Labels der Schalter in dem aktiven und dem gesperrten Status string m_inc_bmp_file_on; string m_inc_bmp_file_off; string m_inc_bmp_file_locked; string m_dec_bmp_file_on; string m_dec_bmp_file_off; string m_dec_bmp_file_locked; //--- Abstände der Buttons (Von der rechten Seite) int m_inc_x_gap; int m_inc_y_gap; int m_dec_x_gap; int m_dec_y_gap; //--- Der Modus für das Zurücksetzen des Wertes zum Minimum bool m_reset_mode; //--- Minimum/maximum Wert double m_min_value; double m_max_value; //--- Schrittweise für die Veränderung des Wertes double m_step_value; //--- Modus der Textausrichtung ENUM_ALIGN_MODE m_align_mode; //--- Anzahl der Nachkommastellen int m_digits; //--- public: //--- (1) Hintergrundfarbe, (2) Text der Beschreibung, (3) Abstände des Text-Labels void AreaColor(const color clr) { m_area_color=clr; } string LabelText(void) const { return(m_label.Description()); } 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 Farben für das Textlabel für die unterschiedlichen Zustände 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 des Controls, (2) Abstände für das Control 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; } void EditXGap(const int x_gap) { m_edit_x_gap=x_gap; } //--- Farbe des Controls in den unterschiedlichen Zuständen void EditColor(const color clr) { m_edit_color=clr; } void EditColorLocked(const color clr) { m_edit_color_locked=clr; } //--- Farbe des Control-Textes 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; } //--- Die Farbe des Rahmens des controles 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; } //--- Festlegen der Labels für den Button in dem aktiven und in dem gesperrten Status void IncFileOn(const string file_path) { m_inc_bmp_file_on=file_path; } void IncFileOff(const string file_path) { m_inc_bmp_file_off=file_path; } void IncFileLocked(const string file_path) { m_inc_bmp_file_locked=file_path; } void DecFileOn(const string file_path) { m_dec_bmp_file_on=file_path; } void DecFileOff(const string file_path) { m_dec_bmp_file_off=file_path; } void DecFileLocked(const string file_path) { m_dec_bmp_file_locked=file_path; } //--- Abstände für die Buttons void IncXGap(const int x_gap) { m_inc_x_gap=x_gap; } void IncYGap(const int y_gap) { m_inc_y_gap=y_gap; } void DecXGap(const int x_gap) { m_dec_x_gap=x_gap; } void DecYGap(const int y_gap) { m_dec_y_gap=y_gap; } //--- Der Reset Modus, wenn ein Klick auf das Textlabel stattfindet bool ResetMode(void) { return(m_reset_mode); } void ResetMode(const bool mode) { m_reset_mode=mode; } //--- 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; } //--- Die Schrittweite 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; } };
Für die Erzeugung des Kontos, benötigen wir fünf private Methoden für die Erzeugung des einfachen grafischen Objektes und eine public Methode, die in der benutzerdefinierten Klasse aufgerufen wird, wenn das grafische Interface erzeugt wird. Die Icons für die scrolling Buttons können am Ende des Artikels heruntergeladen werden. Diese werden standardmäßig verwendet. Sie können natürlich auch ihre Eigenen verwenden.
class CSpinEdit : public CElement { private: //--- Objekte für die Erzeugung des Controls CRectLabel m_area; CLabel m_label; CEdit m_edit; CBmpLabel m_spin_inc; CBmpLabel m_spin_dec; //--- public: //--- Methoden für die Erzeugung des Controls bool CreateSpinEdit(const long chart_id,const int subwin,const string label_text,const int x,const int y); //--- private: bool CreateArea(void); bool CreateLabel(void); bool CreateEdit(void); bool CreateSpinInc(void); bool CreateSpinDec(void); };
Nun werden wir die Modi und die Methoden für das Verwalten des Status und die Eigenschaften des Controls besprechen. Lassen Sie uns mit der CSpinEdit::SetValue() Methode für das Einstellen und Speichern des Wertes des Controls und der externen CSpinEdit::HighlightLimit() Methode für das Hervorheben (Aufblitzen) des Textes in dem Control, sobald das Minimum oder das Maximum erreicht ist, beginnen.
Am Anfang der CSpinEdit::SetValue() Methode, können wir die Schrittweite für das Verändern des Wertes einstellen. Anschließend werden Überprüfungen für das Überschreiten der Limits (Maximum/Minimum) vorgenommen. Falls die Limits überschritten werden, dann wird ein Wert entsprechen dieser Überprüfung gesetzt und die CSpinEdit::HighlightLimit() Methode für das Hervorheben des Textes wird aufgerufen. Falls sich nach diesen Überprüfungen der Wert im Vergleich zu dem Wert, welcher zuvor gespeichert wurde, verändert hat, dann wird der alte Wert mit dem neuen überschrieben.
Die CSpinEdit::HighlightLimit() Methode ist recht einfach. Zunächst wird die Farbe für das Hervorheben gesetzt. Standardmäßig wird hier Rot verwendet, aber der User kann natürlich eine eigene Farbe wählen. Anschließend gibt es eine Pause von 100 Millisekunden. Dieses ist ausreichend, damit ein Farbwechsel auch bemerkt wird. Danach wird wieder die ursprüngliche Textfarbe gesetzt.
Nachfolgend nun der Programmcode der beschriebenen Methoden:
class CSpinEdit : public CElement { private: //--- Aktueller Wert des Controls double m_edit_value; //--- public: //--- Rückgabe und setzen des Wertes double GetValue(void) const { return(m_edit_value); } bool SetValue(const double value); //--- Blinken, wenn das Limit erreicht wird void HighlightLimit(void); }; //+-----------------------------------------------------------------+ //| Überprüfung des aktuellen Wertes | //+-----------------------------------------------------------------+ bool CSpinEdit::SetValue(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) { //--- Setzen des minimalen Wertes corrected_value=m_min_value; //--- Setzen des Status auf "An" m_spin_dec.State(true); //--- Blinken, für den Hinweis auf ein erreichtes Limit HighlightLimit(); } if(corrected_value>m_max_value) { //--- Setzen des maximalen Wertes corrected_value=m_max_value; //--- Setzen des Status auf "An" m_spin_inc.State(true); //--- Blinken, für den Hinweis auf ein erreichtes Limit HighlightLimit(); } //--- Falls sich der Wert geändert hat if(m_edit_value!=corrected_value) { m_edit_value=corrected_value; m_edit.Color(m_edit_text_color); return(true); } //--- Wert ist unverändert return(false); } //+-----------------------------------------------------------------+ //| Hervorheben des Limits | //+-----------------------------------------------------------------+ void CSpinEdit::HighlightLimit(void) { //--- Temporäre Veränderung der Textfarbe m_edit.Color(m_edit_text_color_highlight); //--- Aktualisierung ::ChartRedraw(); //--- Pause bis zur Rückkehr zur alten Farbe ::Sleep(100); //--- Zur vorherigen Textfarbe zurückkehren m_edit.Color(m_edit_text_color); }
Die CSpinEdit::SetValue() Methode ist nur dafür gedacht, den Wert neu einzustellen, falls ein Limit erreicht wurde. Die CSpinEdit:: ChangeValue() Methode wird für die Veränderung des Wertes in dem Control benötigt:
class CSpinEdit : public CElement { private: //--- Verändern des Wertes in dem Control void ChangeValue(const double value); }; //+-----------------------------------------------------------------+ //| Verändern des Wertes in dem Edit | //+-----------------------------------------------------------------+ void CSpinEdit::ChangeValue(const double value) { //--- Überprüfen, Einstellen und Abspeichern des neuen Wertes SetValue(value); //--- In dem Edit den neuen Wert setzen m_edit.Description(::DoubleToString(GetValue(),m_digits)); }
Ähnlich wie bei den anderen Elementen, benötigen wir eine Methode für das Verwalten der Verfügbarkeit des Edit-Controls, so wie es in dem nachfolgenden Code gezeigt wird:
class CSpinEdit : public CElement { private: //--- Checkbox Status (Verfügbar/gesperrt) bool m_spin_edit_state; //--- public: //--- Rückgabe/ setzen Des Status der Verfügbarkeit des Edit bool SpinEditState(void) const { return(m_spin_edit_state); } void SpinEditState(const bool state); }; //+-----------------------------------------------------------------+ //| Festlegen des Status des Controls | //+-----------------------------------------------------------------+ void CSpinEdit::SpinEditState(const bool state) { m_spin_edit_state=state; //--- Farbe des Text Labels m_label.Color((state)? m_label_color : m_label_color_locked); //--- Farbe des Edit m_edit.Color((state)? m_edit_text_color : m_edit_text_color_locked); m_edit.BackColor((state)? m_edit_color : m_edit_color_locked); m_edit.BorderColor((state)? m_edit_border_color : m_edit_border_color_locked); //--- Icons der Schalter m_spin_inc.BmpFileOn((state)? "::"+m_inc_bmp_file_on : "::"+m_inc_bmp_file_locked); m_spin_dec.BmpFileOn((state)? "::"+m_dec_bmp_file_on : "::"+m_dec_bmp_file_locked); //--- Setzen des aktuellen Status if(!m_spin_edit_state) { //--- Prioritäten m_edit.Z_Order(-1); m_spin_inc.Z_Order(-1); m_spin_dec.Z_Order(-1); //--- Edit In "nur lesen"-Modus m_edit.ReadOnly(true); } else { //--- Prioritäten m_edit.Z_Order(m_edit_zorder); m_spin_inc.Z_Order(m_spin_zorder); m_spin_dec.Z_Order(m_spin_zorder); //--- Das Edit-Control im "Edit"-Modus m_edit.ReadOnly(false); } }
Jetzt werden wir Methoden für die Verwaltung der Control-Events betrachten: Ein Klick auf das Textlabel wird ein Benutzerdefiniertes Event generieren mit (1) dem ON_CLICK_LABEL Bezeichner, (2) dem Control-Bezeichner, (3) dem Index des Controlsand (4) der Beschreibung des Text-Labels. Der Modus für das Zurücksetzen des Wertes auf den Minimum-Wert, wurde zuvor schon besprochen. Dieser Modus ist standardmäßig deaktiviert (false). Er kann über die CSpinEdit::ResetMode() Methode aktiviert werden. Dafür muss ihr lediglich das true Argument übergeben werden. Falls dieser Modus aktiviert ist, dann führt ein Klick auf das Text-Label zum Aufruf der Methode für das Setzen des minimalen Wertes.
Der Programmcode der CSpinEdit::OnClickLabel() Methode für das Verarbeiten eines Klicks auf das Textlabel, wird nachfolgend nun gezeigt:
class CSpinEdit : public CElement { private: //--- Verarbeiten eines Klicks auf das Text Label bool OnClickLabel(const string clicked_object); }; //+-----------------------------------------------------------------+ //| Klick auf ein Element Label | //+-----------------------------------------------------------------+ bool CSpinEdit::OnClickLabel(const string clicked_object) { //--- Abbrechen, falls die Namen unterschiedlich sind if(m_area.Name()!=clicked_object) return(false); //--- Falls der Modus für das Zurücksetzen des Wertes aktiviert ist if(m_reset_mode) { //--- Setzen des minimalen Wertes ChangeValue(MinValue()); } //--- Eine Nachricht darüber senden ::EventChartCustom(m_chart_id,ON_CLICK_LABEL,CElement::Id(),CElement::Index(),m_label.Description()); return(true); }
Der Benutzer kann den Wert in dem Control manuell eingeben oder die Tasten für das Erhöhen und Verringern verwenden. Wir brauchen jetzt neue Bezeichner für benutzerdefinierte Events. Fügen Sie diese der Defines.mqh Datei hinzu:
//+------------------------------------------------------------------+ //| Defines.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #define ON_END_EDIT (18) // Final editing of the value in the edit #define ON_CLICK_INC (19) // Change the counter up #define ON_CLICK_DEC (20) // Change the counter down
Um die manuelle Eingabe eines neuen Wertes bearbeiten zu können, schreiben wir die CSpinEdit::OnEndEdit() Methode. Sie wird in dem CSpinEdit::OnEvent() gemeinsamen Eventhandler für das Empfangen eines Events mit dem CHARTEVENT_OBJECT_ENDEDIT Bezeichner aufgerufen. Wenn sich die Notwendigkeit ergibt, kann der neue Wert eingestellt werden. Am Ende der Methode wird ein benutzerdefinierter Event generiert mit (1) dem ON_END_EDIT Event-Bezeichner, (2) dem Element-Bezeichner, (3) dem Element-Index und (4) der Beschreibung des Text-Labels.
class CSpinEdit : public CElement { private: //--- Verarbeiten der manuellen Eingabe eines Wertes bool OnEndEdit(const string edited_object); }; //+-----------------------------------------------------------------+ //| Verarbeiten der manuellen Eingabe eines Wertes | //+-----------------------------------------------------------------+ bool CSpinEdit::OnEndEdit(const string edited_object) { //--- Abbrechen, falls die Namen unterschiedlich sind if(m_edit.Name()!=edited_object) return(false); //--- Abfrage des eingegebenen Wertes double entered_value=::StringToDouble(m_edit.Description()); //--- Überprüfen, Einstellen und Abspeichern des neuen Wertes ChangeValue(entered_value); //--- Eine Nachricht darüber senden ::EventChartCustom(m_chart_id,ON_END_EDIT,CElement::Id(),CElement::Index(),m_label.Description()); return(true); }
Für die Verarbeitung eines Klicks auf die Inkrement- und Dekrement-Buttons müssen wir zwei separate Methoden entwerfen: CSpinEdit::OnClickSpinInc() und CSpinEdit::OnClickSpinDec(). Diese sind recht simpel. Nachdem auf ein grafisches Objekt geklickt wurde, gibt es eine Überprüfung, ob es sich bei dem Namen um einen unserer Buttons handelt. Anschließend fragen wir den aktuellen Wert ab und erhöhen oder verringern ihn um die gewünschte Schrittweite. Am Ende der Methode wird ein benutzerdefiniertes Event mit (1) dem ON_CLICK_INC/ON_CLICK_DEC Event-Bezeichner, (2) dem Element-Bezeichner, (3) dem Element-Index und (4) der Beschreibung des Text-Labels generiert.
class CSpinEdit : public CElement { private: //--- Arbeiten eines Button-Klick Events bool OnClickSpinInc(const string clicked_object); bool OnClickSpinDec(const string clicked_object); }; //+-----------------------------------------------------------------+ //| Klick auf Inkrement | //+-----------------------------------------------------------------+ bool CSpinEdit::OnClickSpinInc(const string clicked_object) { //--- Abbrechen, falls die Namen unterschiedlich sind if(m_spin_inc.Name()!=clicked_object) return(false); //--- Abfrage des aktuellen Wertes double value=GetValue(); //--- Erhöhung um einen Schritt und anschließende Überprüfung auf Überschreitung des Limits ChangeValue(value+m_step_value); //--- Setzen des Status auf "An" m_spin_inc.State(true); //--- Eine Nachricht darüber senden ::EventChartCustom(m_chart_id,ON_CLICK_INC,CElement::Id(),CElement::Index(),m_label.Description()); return(true); } //+-----------------------------------------------------------------+ //| Klick auf den Decrement-Button | //+-----------------------------------------------------------------+ bool CSpinEdit::OnClickSpinDec(const string clicked_object) { //--- Abbrechen, falls die Namen unterschiedlich sind if(m_spin_dec.Name()!=clicked_object) return(false); //--- Abfrage des aktuellen Wertes double value=GetValue(); //--- Verringern um einen Schritt und anschließende Überprüfung auf Überschreitung des Limits ChangeValue(value-m_step_value); //--- Setzen des Status auf "An" m_spin_dec.State(true); //--- Eine Nachricht darüber senden ::EventChartCustom(m_chart_id,ON_CLICK_DEC,CElement::Id(),CElement::Index(),m_label.Description()); return(true); }
Wie nachfolgend gezeigt, müssen alle diese Methoden in der Hauptmethode für das Verarbeiten von Events aufgerufen werden. Der Zugriff auf den Körper der Events-Verarbeitungsmethoden, wird über die aktuelle Verfügbarkeit des Controls gesteuert.
//+------------------------------------------------------------------+ //| Event handling | //+------------------------------------------------------------------+ void CSpinEdit::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Verarbeiten eines Klicks mit der linken Maustaste auf ein Objekt if(id==CHARTEVENT_OBJECT_CLICK) { //--- Verlassen, falls das Control gesperrt ist if(!m_spin_edit_state) return; //--- Verarbeiten eines Klicks auf das Text Label if(OnClickLabel(sparam)) return; //--- Arbeiten eines Button-Klick Events if(OnClickSpinInc(sparam)) return; if(OnClickSpinDec(sparam)) return; //--- return; } //--- Verarbeiten des "Value change" Events (Wert hat sich geändert) if(id==CHARTEVENT_OBJECT_ENDEDIT) { //--- Verlassen, falls das Control gesperrt ist if(!m_spin_edit_state) return; //--- Verarbeiten der Eingabe des Wertes if(OnEndEdit(sparam)) return; } }
Für die schnelle Veränderung des Wertes, wenn die linke Maustaste über einen der Buttons gedrückt und gehalten wird, erzeugen wir die CSpinEdit::FastSwitching() Methode, die über den Timer des Controls aufgerufen wird. Wir haben diese Methode schon besprochen, als wir die CListView Klasse für die Erzeugung einer ListView mit Scrollbar entwickelt haben. So wie dort die Methode für das Scrollen durch eine Liste verwendet wurde, wird sie hier für das Erhöhen und Verringern der Werte in dem Edit-Control verwendet. Der detaillierte Programmcode der CSpinEdit::FastSwitching() Methode wird nachfolgend gezeigt:
class CSpinEdit : public CElement { private: //--- Schnelles Scrollen in der Werte in dem Edit void FastSwitching(void); }; //+------------------------------------------------------------------+ //| Timer | //+------------------------------------------------------------------+ void CSpinEdit::OnEventTimer(void) { //--- Falls es sich um ein drop-down-element handelt if(CElement::IsDropdown()) { ChangeObjectsColor(); FastSwitching(); } else { //--- Protokolliere die Veränderung der Farbe und der schnell scrollenden Werte // if the form is not blocked if(!m_wnd.IsLocked()) { ChangeObjectsColor(); FastSwitching(); } } } //+------------------------------------------------------------------+ //| Schnelle Veränderung der Werte in dem Edit | //+------------------------------------------------------------------+ void CSpinEdit::FastSwitching(void) { //--- Abbrechen, falls sich der Fokus nicht auf diesem Control befindet if(!CElement::MouseFocus()) return; //--- Den Zähler auf den anfänglichen Wert zurücksetzen, falls der Mousebutton losgelassen wird if(!m_mouse_state) m_timer_counter=SPIN_DELAY_MSC; //--- Falls die Maustaste gedrückt wird else { //--- Erhöhen des Zählers um den angegebenen Schritt m_timer_counter+=TIMER_STEP_MSC; //--- Verlassen, falls der kleiner als Null ist if(m_timer_counter<0) return; //--- Abfrage des aktuellen Wertes in dem Control double current_value=::StringToDouble(m_edit.Description()); //--- Falls erhöhen if(m_spin_inc.State()) SetValue(current_value+m_step_value); //--- Falls verringert else if(m_spin_dec.State()) SetValue(current_value-m_step_value); //--- Verändere den Wert, falls der Button weiterhin gedrückt ist if(m_spin_inc.State() || m_spin_dec.State()) m_edit.Description(::DoubleToString(GetValue(),m_digits)); } }
Test des Edit-Control
Alle Methoden für das Edit-Control wurden nun implementiert. Lassen Sie es uns nun in dem Programm, welches wir zuvor schon verwendet haben, testen. In der CProgram Benutzerdefinierten Klasse der Anwendung erzeugen wie eine Instanz der CSpinEdit Klasse und deklarieren Sie eine Methode für die Erzeugung des Edit-Controls.
//+------------------------------------------------------------------+ //| Kasse für das erzeugende Anwendung | //+------------------------------------------------------------------+ class CProgram : public CWndEvents { private: //--- Edits CSpinEdit m_spin_edit1; //--- private: //--- Edits #define SPINEDIT1_GAP_X (150) #define SPINEDIT1_GAP_Y (75) bool CreateSpinEdit1(const string text); };
Hier ist ebenfalls die erste Checkbox für die Verwaltung der Verfügbarkeit unseres Controls verantwortlich, genauso wie es auch mit der zweiten Checkbox geschieht. Somit hängt die Verfügbarkeit von dem Status der ersten Checkbox ab, wie es auch in den nachfolgenden Programmcode gezeigt ist.
//+------------------------------------------------------------------+ //| Erzeugt Edit 1 | //+------------------------------------------------------------------+ bool CProgram::CreateSpinEdit1(string text) { //--- Abspeichern des Fenster-Pointers m_spin_edit1.WindowPointer(m_window1); //--- Koordinaten int x=m_window1.X()+SPINEDIT1_GAP_X; int y=m_window1.Y()+SPINEDIT1_GAP_Y; //--- Wert double v=(m_spin_edit1.GetValue()==WRONG_VALUE) ? 4 : m_spin_edit1.GetValue(); //--- Festlegen der Eigenschaften vor der Erzeugung m_spin_edit1.XSize(150); m_spin_edit1.YSize(18); m_spin_edit1.EditXSize(76); m_spin_edit1.MaxValue(1000); m_spin_edit1.MinValue(-1000); m_spin_edit1.StepValue(1); m_spin_edit1.SetDigits(0); m_spin_edit1.SetValue(v); m_spin_edit1.ResetMode(true); m_spin_edit1.AreaColor(clrWhiteSmoke); m_spin_edit1.LabelColor(clrBlack); m_spin_edit1.LabelColorLocked(clrSilver); m_spin_edit1.EditColorLocked(clrWhiteSmoke); m_spin_edit1.EditTextColor(clrBlack); m_spin_edit1.EditTextColorLocked(clrSilver); m_spin_edit1.EditBorderColor(clrSilver); m_spin_edit1.EditBorderColorLocked(clrSilver); //--- Erzeugung des Controls if(!m_spin_edit1.CreateSpinEdit(m_chart_id,m_subwin,text,x,y)) return(false); //--- Die Verfügbarkeit hängt von dem aktuellen Status der ersten Checkbox ab m_spin_edit1.SpinEditState(m_checkbox1.CheckButtonState()); //--- Fügen Sie das Objekt zu dem gemeinsamen Array von Objektgruppen hinzu CWndContainer::AddToElementsArray(0,m_spin_edit1); return(true); }
Wie auch bei den anderen Controls, muss die CProgram::CreateSpinEdit1() Methode für die Erzeugung des Controls in der Hauptmethode für die Erzeugung des grafischen Interfaces aufgerufen werden. Nachfolgend ist die abgekürzte Version der Methode:
//+------------------------------------------------------------------+ //| Erzeugt das Trading-Panel | //+------------------------------------------------------------------+ bool CProgram::CreateTradePanel(void) { //--- Erzeugen des Formulars 1 für die Controls //---Erzeugung der Controls: // Hauptmenü //--- Kontextmenüs //--- Erzeugen der Statusbar //--- Checkboxen //--- Edits if(!CreateSpinEdit1("Spin Edit 1:")) return(false); //--- Neuzeichnen des Charts m_chart.Redraw(); return(true); }
In dem CProgram::OnEvent() Eventhandler fügen wir den Programmcode für den Test der Events des Edit-Controls ein und geben zudem an, dass das erste Edit von dem Status der ersten Checkbox abhängt.:
//+-----------------------------------------------------------------+ //| Eventhandler | //+-----------------------------------------------------------------+ 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 es sich um einen Klick auf die erste Checkbox handelt if(lparam==m_checkbox1.Id()) { //--- Festlegen des Status der zweiten Checkbox und des Edit-Controls m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState()); m_spin_edit1.SpinEditState(m_checkbox1.CheckButtonState()); } } //--- Das Event für das Abschließen einer Eingabe if(id==CHARTEVENT_CUSTOM+ON_END_EDIT) { ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); } //--- Die Events der Buttons if(id==CHARTEVENT_CUSTOM+ON_CLICK_INC || id==CHARTEVENT_CUSTOM+ON_CLICK_DEC) { ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); } }
Kompilieren Sie dieses Programm und laden Sie es auf einen Chart. Die Anwendung sollte nun so aussehen, wie sie es in dem nachfolgenden Screenshot sehen können:
Abbildung 4. Test des Edit-Controls
Andere Controls mit Checkboxen
Am Anfang des Artikels haben wir darüber gesprochen, dass wir neben der Checkbox und den Edit-Control, auch ein Edit-Control mit Checkbox und die Checkcombobox besprechen wollen. Ein Edit mit Checkbox ist eine erweiterte Version der CSpinEdit Klasse, die mit loyal und Methoden der CCheckBox Klasse erweitert wird, die wir schon in diesem Artikel betrachtet haben.
Abbildung 5. Komponenten des Edit-Controls mit Checkbox-Control.
Die Checkcombobox ist eine Kombination aus den CComboBox und CCheckBox Klassen:
Abbildung 6. Komponenten des Check-Combobox-Controls.
Sie finden die Implementationen der CCheckBoxEdit (Edit mit Checkbox) und CCheckComboBox (Check-Combobox) in den Dateien, die diesem Artikel beigefügt sind. Da das Control vom Typ CCheckComboBox Ein Dropdown List View beinhaltet, müssen in der WndContainer.mqh noch Ergänzungen vorgenommen werden, wie es auch bei anderen Elementen mit einer Drop-Down-Liste geschehen ist. In diesem Fall, muss der Pointer der DropDown-List-View in das m_drop_lists[] Pointer-Array. Eine genau Beschreibung, wie dieses gelöst werden kann, finden Sie in dem Artikel Graphical Interfaces V: Das Combobox Control (Kapitel 3).
Lassen Sie uns beispielhaft dieser Test-Anwendung diese Controls hinzufügen, damit Sie sehen können, wie sie funktionieren. Lassen Sie uns zwei Checkboxen vom Typ CCheckBox und eine vom Typ CCheckBoxEdit und CCheckComboBox hinzufügen. Die Verfügbarkeit des controles vom Typ CCheckBoxEdit hängt von dem Status der dritten Checkbox ab und die Verfügbarkeit des Controls vom Typ CCheckComboBox wird über den Status der vierten Combobox definiert.
Fig. 7. Test der Controls mit gemischten Typen.
Schlussfolgerung
In diesem Artikel haben wir die weitverbreiteten Controls: checkbox, edit, edit with checkbox and check combobox entwickelt. In dem zweiten Kapitel werden wir den Slider und den Doppel-Slider entwickeln.
- Graphische Interfaces VI: Das Checkbox Control, Das Edit Control und deren gemischte Typen (Kapitel 1)
- Graphische Interfaces VI: Die Slider und Doppel-Slider Controls (Kapitel 2)
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/2466
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.