DoEasy. Steuerung (Teil 10): WinForms-Objekte - Animieren der Nutzeroberfläche
Inhalt
Konzept
Alle zuvor erstellten WinForms-Objekte sind in Wirklichkeit statische Bilder, die über den gesamten Bildschirm gezogen werden können. Nun ist es an der Zeit, die grafische Oberfläche zu animieren, indem die Funktionalität für die Interaktion von Objekten mit Nutzern und Objekten implementiert wird.
Die WinForms-Objekte, die wir bereits erstellt haben, sind sowohl unabhängige Einheiten für den Aufbau einer grafischen Oberfläche als auch Komponenten für komplexere Objekte. Die neue Funktionsweise wird auch notwendig sein, damit komplexere Objekte korrekt funktionieren. Ich werde damit beginnen, all diese Dinge im aktuellen Artikel umzusetzen. Außerdem werde ich eine visuelle Komponente für Objekte erstellen, die mit der Maus interagieren. In den folgenden Artikeln werde ich die Ereignisfunktionen dieser Objekte implementieren und die Erstellung der neuen WinForms-Objekte der Bibliothek fortsetzen.
Jedes aktive GUI-Objekt, das mit der Maus interagieren kann und das Verfügbarkeits-Flag hat, sollte die Nutzer darüber informieren, dass sie mit ihm interagieren können. Nehmen wir zum Beispiel eine einfache Schaltfläche. Wenn man mit der Maus darüberfährt, ändert die Schaltfläche leicht ihre Farbe, um dem Nutzer mitzuteilen, dass sie aktiv und zur Interaktion bereit ist. Wenn er gedrückt wird, ändert er seine Farbe erneut, wird aber noch nicht ausgelöst. Die Auslösung erfolgt, wenn die Maustaste innerhalb des Interaktionsobjekts losgelassen wird. Wenn man die Maustaste auf dem Objekt drückt und, ohne sie loszulassen, den Cursor vom Objekt wegbewegen und dann die Maustaste loslässt, sollte das Objekt nicht ausgelöst werden - es kehrt in den Zustand zurück, in dem es sich befand, bevor die Maustaste gedrückt wurde. So verhalten sich alle Objekte des Windows-Betriebssystems. Hier implementieren wir das gleiche Verhalten für WinForms-Objekte.
Nach dem Erstellen der visuellen Komponente werde ich mit dem Erstellen der Ereignisfunktionen von WinForms-Objekten beginnen, die es uns ermöglicht, komplexere Objekte aus einfachen Objekten zu erstellen. Ereignisse von einfachen Objekten, aus denen ein komplexes besteht, sind vom Objekt selbst zu analysieren und zu verarbeiten. Sein Erscheinungsbild ändert sich entsprechend, und als Ergebnis sendet das Objekt das in diesem Objekt aufgetretene Ereignis an die Kontrollprogramm auf dem Chart.
Da das Objekt nun mehrere Farben für denselben Zustand haben muss (Grundfarbe, Farbe, wenn der Mauszeiger darüber bewegt wird, Farbe, wenn die Schaltfläche auf einem Objekt gedrückt wird), fügen wir diese neuen Farben für verschiedene Objekteigenschaften hinzu, die sie haben können. Wenn neue Farben in den Objekteigenschaften vorhanden sind, wird es später einfacher sein, visuelle Editoren für diese Objekte zu erstellen - alle Eigenschaften können auf dem Bedienfeld angezeigt und bearbeitet werden. Wenn in den Objekteigenschaften keine neuen zusätzlichen Farben eingestellt sind, müssen wir sie manuell für jedes Objekt einstellen, um sie anzuzeigen. Dies ist nicht die eleganteste Lösung.
Verbesserung der Bibliotheksklassen
Fügen Sie in \MQL5\Include\DoEasy\Defines.mqh die neuen Makrosubstitutionen für Standardfarben verschiedener WinForms-Objektzustände hinzu:
//--- Canvas parameters #define PAUSE_FOR_CANV_UPDATE (16) // Canvas update frequency #define CLR_CANV_NULL (0x00FFFFFF) // Zero for the canvas with the alpha channel #define CLR_DEF_FORE_COLOR (C'0x2D,0x43,0x48') // Default color for texts of objects on canvas #define CLR_DEF_FORE_COLOR_MOUSE_DOWN (C'0x0E,0x11,0x98') // Default color for texts of objects on canvas when clicking the mouse on the control #define CLR_DEF_FORE_COLOR_MOUSE_OVER (C'0x14,0x67,0xF1') // Default color for texts of objects on canvas when hovering the mouse over the control #define CLR_DEF_FORE_COLOR_OPACITY (255) // Default color non-transparency for canvas object texts #define CLR_DEF_BORDER_COLOR (C'0x2D,0x43,0x48') // Default color for object frames on canvas #define CLR_DEF_BORDER_MOUSE_DOWN (C'0x61,0x88,0xC9') // Default color for object frames on canvas when clicking the mouse on the control #define CLR_DEF_BORDER_MOUSE_OVER (C'0x93,0xAD,0xC8') // Default color for object frames on canvas when hovering the mouse over the control #define CLR_DEF_BORDER_COLOR_OPACITY (255) // Default color non-transparency for canvas object frames #define CLR_DEF_BORDER_COLOR_DARKNESS (-2.0) // Default color opacity for canvas object frames (when using the background color) #define CLR_DEF_FRAME_GBOX_COLOR (C'0xDC,0xDC,0xDC') // Default color for GroupBox object frames on canvas #define CLR_DEF_OPACITY (200) // Default color non-transparency for canvas objects #define CLR_DEF_SHADOW_COLOR (C'0x6B,0x6B,0x6B') // Default color for canvas object shadows #define CLR_DEF_SHADOW_OPACITY (127) // Default color opacity for canvas objects #define DEF_SHADOW_BLUR (4) // Default blur for canvas object shadows #define CLR_DEF_CHECK_BACK_COLOR (C'0xFF,0xFF,0xFF') // Color of control checkbox background #define CLR_DEF_CHECK_BACK_OPACITY (255) // Opacity of the control checkbox background color #define CLR_DEF_CHECK_BACK_MOUSE_DOWN (C'0xC0,0xDC,0xF3') // Color of control checkbox background when clicking on the control #define CLR_DEF_CHECK_BACK_MOUSE_OVER (C'0xD8,0xE6,0xF2') // Color of control checkbox background when hovering the mouse over the control #define CLR_DEF_CHECK_BORDER_COLOR (C'0x2D,0x43,0x48') // Color of control checkbox frame #define CLR_DEF_CHECK_BORDER_OPACITY (255) // Opacity of the control checkbox frame color #define CLR_DEF_CHECK_BORDER_MOUSE_DOWN (C'0x00,0x54,0x99') // Color of control checkbox frame when clicking on the control #define CLR_DEF_CHECK_BORDER_MOUSE_OVER (C'0x00,0x78,0xD7') // Color of control checkbox frame when hovering the mouse over the control #define CLR_DEF_CHECK_FLAG_COLOR (C'0x04,0x7B,0x0D') // Color of control checkbox #define CLR_DEF_CHECK_FLAG_OPACITY (255) // Opacity of the control checkbox color #define CLR_DEF_CHECK_FLAG_MOUSE_DOWN (C'0x00,0x54,0x99') // Color of control checkbox when clicking on the control #define CLR_DEF_CHECK_FLAG_MOUSE_OVER (C'0x00,0x78,0xD7') // Color of control checkbox when hovering the mouse over the control #define CLR_DEF_CONTROL_STD_BACK_COLOR (C'0xF0,0xF0,0xF0') // Standard controls background color #define CLR_DEF_CONTROL_STD_MOUSE_DOWN (C'0xC0,0xDC,0xF3') // Color of standard control background when clicking on the control #define CLR_DEF_CONTROL_STD_MOUSE_OVER (C'0xD8,0xE6,0xF2') // Color of standard controls background when hovering the mouse over the control #define CLR_DEF_CONTROL_STD_OPACITY (255) // Opacity of standard controls background color #define CLR_DEF_CONTROL_STD_BACK_COLOR_ON (C'0xC9,0xDE,0xD0') // Background color of standard controls which are on #define CLR_DEF_CONTROL_STD_BACK_DOWN_ON (C'0xA6,0xC8,0xB0') // Color of standard control background when clicking on the control when it is on #define CLR_DEF_CONTROL_STD_BACK_OVER_ON (C'0xB8,0xD3,0xC0') // Color of standard control background when hovering the mouse over the control when it is on #define DEF_FONT ("Calibri") // Default font #define DEF_FONT_SIZE (8) // Default font size #define DEF_CHECK_SIZE (12) // Verification flag default size #define OUTER_AREA_SIZE (16) // Size of one side of the outer area around the form workspace #define DEF_FRAME_WIDTH_SIZE (3) // Default form/panel/window frame width //--- Graphical object parameters
ForeColor wird für das Ankreuzfeld nicht benötigt. Ersetzen wir es also durch BorderColor — die Rahmenfarbe des Kontrollkästchens. Sie ändert sich zusammen mit der Hintergrundfarbe, wenn mit der Maus interagiert wird. Die Farbe des Kontrollkästchens wird hier als ForeColor verwendet.
Ein weiterer Mauszustand in Bezug auf das Formular soll in der Bibliothek verfolgt werden — wenn sich der Cursor im aktiven Bereich befindet und die Maustaste nach dem Klicken losgelassen wurde. Wir fügen den neuen Zustand zur Liste der möglichen Mauszustände in Bezug auf das Formular hinzu:
//+------------------------------------------------------------------+ //| The list of possible mouse states relative to the form | //+------------------------------------------------------------------+ enum ENUM_MOUSE_FORM_STATE { MOUSE_FORM_STATE_NONE = 0, // Undefined state //--- Outside the form MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED, // The cursor is outside the form, the mouse buttons are not clicked MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED, // The cursor is outside the form, the mouse button (any) is clicked MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL, // The cursor is outside the form, the mouse wheel is being scrolled //--- Within the form MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED, // The cursor is inside the form, no mouse buttons are clicked MOUSE_FORM_STATE_INSIDE_FORM_PRESSED, // The cursor is inside the form, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_FORM_WHEEL, // The cursor is inside the form, the mouse wheel is being scrolled //--- Within the window header area MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED, // The cursor is inside the active area, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED, // The cursor is inside the active area, any mouse button is clicked MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL, // The cursor is inside the active area, the mouse wheel is being scrolled MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED, // The cursor is inside the active area, left mouse button is released //--- Within the window scrolling area MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_NOT_PRESSED, // The cursor is within the window scrolling area, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_PRESSED, // The cursor is within the window scrolling area, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_WHEEL, // The cursor is within the window scrolling area, the mouse wheel is being scrolled }; //+------------------------------------------------------------------+
Indem wir diesen Zustand verfolgen, können wir den Zeitpunkt des Loslassens der Maustaste bestimmen. Dieser Moment ist der Schlüssel zur Änderung des Zustands des grafischen Objekts.
Um auf die Interaktion mit der Maus reagieren zu können, müssen wir wissen, welches Mausereignis eingetreten ist. Anschließend senden wir dieses Ereignis an das Programm, so dass die Bibliotheksnutzer dieses Ereignis in ihrem Programm behandeln können.
Wir erstellen eine neue Enumeration mit der Liste der Mausereignisse:
//+------------------------------------------------------------------+ //| List of possible mouse events | //+------------------------------------------------------------------+ enum ENUM_MOUSE_EVENT { MOUSE_EVENT_NO_EVENT = CHART_OBJ_EVENTS_NEXT_CODE, // No event //--- MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED, // The cursor is outside the form, the mouse buttons are not clicked MOUSE_EVENT_OUTSIDE_FORM_PRESSED, // The cursor is outside the form, the mouse button (any) is clicked MOUSE_EVENT_OUTSIDE_FORM_WHEEL, // The cursor is outside the form, the mouse wheel is being scrolled //--- Within the form MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED, // The cursor is inside the form, no mouse buttons are clicked MOUSE_EVENT_INSIDE_FORM_PRESSED, // The cursor is inside the form, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_FORM_WHEEL, // The cursor is inside the form, the mouse wheel is being scrolled //--- Within the window header area MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED, // The cursor is inside the active area, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_ACTIVE_AREA_PRESSED, // The cursor is inside the active area, any mouse button is clicked MOUSE_EVENT_INSIDE_ACTIVE_AREA_WHEEL, // The cursor is inside the active area, the mouse wheel is being scrolled MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED, // The cursor is inside the active area, left mouse button is released //--- Within the window scrolling area MOUSE_EVENT_INSIDE_SCROLL_AREA_NOT_PRESSED, // The cursor is within the window scrolling area, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_SCROLL_AREA_PRESSED, // The cursor is within the window scrolling area, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_SCROLL_AREA_WHEEL, // The cursor is within the window scrolling area, the mouse wheel is being scrolled }; #define ENUM_MOUSE_EVENT_NEXT_CODE (MOUSE_EVENT_INSIDE_SCROLL_AREA_WHEEL+1) // The code of the next event after the last chart event code //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Data for handling graphical elements | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| List of possible graphical object events | //+------------------------------------------------------------------+ enum ENUM_GRAPH_OBJ_EVENT { GRAPH_OBJ_EVENT_NO_EVENT = ENUM_MOUSE_EVENT_NEXT_CODE,// No event GRAPH_OBJ_EVENT_CREATE, // "Creating a new graphical object" event GRAPH_OBJ_EVENT_CHANGE, // "Changing graphical object properties" event GRAPH_OBJ_EVENT_RENAME, // "Renaming graphical object" event GRAPH_OBJ_EVENT_DELETE, // "Removing graphical object" event GRAPH_OBJ_EVENT_DEL_CHART, // "Removing a graphical object together with the chart window" event }; #define GRAPH_OBJ_EVENTS_NEXT_CODE (GRAPH_OBJ_EVENT_DEL_CHART+1) // The code of the next event after the last graphical object event code //+------------------------------------------------------------------+
Da ich eine neue Enumeration für Ereignisse hinzugefügt habe, die zwischen der Liste der Chartereignisse und der Liste der Chartobjekt-Ereignisse eingefügt wurde, wird der Anfangswert des ersten Ereignisses von grafischen Objekten nun als das letzte Mausereignis+1 berechnet.
Wir fügen die neuen Eigenschaften zur Liste der ganzzahligen Eigenschaften des grafischen Elements hinzu:
//+------------------------------------------------------------------+ //| Integer properties of the graphical element on the canvas | //+------------------------------------------------------------------+ enum ENUM_CANV_ELEMENT_PROP_INTEGER { CANV_ELEMENT_PROP_ID = 0, // Element ID CANV_ELEMENT_PROP_TYPE, // Graphical element type //---... //---... CANV_ELEMENT_PROP_FORE_COLOR, // Default text color for all control objects CANV_ELEMENT_PROP_FORE_COLOR_OPACITY, // Default text color opacity for all control objects CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN, // Default control text color when clicking on the control CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER, // Default control text color when hovering the mouse over the control CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE, // Text color of the control which is on CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_DOWN, // Default control text color when clicking on the control which is on CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_OVER, // Default control text color when hovering the mouse over the control which is on CANV_ELEMENT_PROP_BACKGROUND_COLOR, // Control background color CANV_ELEMENT_PROP_BACKGROUND_COLOR_OPACITY, // Opacity of control background color CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_DOWN, // Control background color when clicking on the control CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER, // Control background color when hovering the mouse over the control CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE, // Background color of the control which is on CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN,// Control background color when clicking on the control which is on CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER,// Control background color hovering the mouse over control which is on CANV_ELEMENT_PROP_BOLD_TYPE, // Font width type CANV_ELEMENT_PROP_BORDER_STYLE, // Control frame style //---... //---... CANV_ELEMENT_PROP_CHECK_STATE, // Status of a control having a checkbox CANV_ELEMENT_PROP_AUTOCHECK, // Auto change flag status when it is selected CANV_ELEMENT_PROP_BUTTON_TOGGLE, // Toggle flag of the control featuring a button CANV_ELEMENT_PROP_BUTTON_STATE, // Status of the Toggle control featuring a button CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR, // Color of control checkbox background CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_OPACITY, // Opacity of the control checkbox background color //---... //---... CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN, // Color of control checkbox when clicking on the control CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER, // Color of control checkbox when hovering the mouse over the control }; #define CANV_ELEMENT_PROP_INTEGER_TOTAL (81) // Total number of integer properties #define CANV_ELEMENT_PROP_INTEGER_SKIP (0) // Number of integer properties not used in sorting //+------------------------------------------------------------------+
Erhöhen wir die Gesamtzahl der ganzzahligen Eigenschaften von 71 auf 81.
Wir sortieren nach neuer Eigenschaft zur Enumeration möglicher Kriterien zum Sortieren von grafischen Elementen auf der Leinwand hinzufügen:
//+------------------------------------------------------------------+ //| Possible sorting criteria of graphical elements on the canvas | //+------------------------------------------------------------------+ #define FIRST_CANV_ELEMENT_DBL_PROP (CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP) #define FIRST_CANV_ELEMENT_STR_PROP (CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP+CANV_ELEMENT_PROP_DOUBLE_TOTAL-CANV_ELEMENT_PROP_DOUBLE_SKIP) enum ENUM_SORT_CANV_ELEMENT_MODE { //--- Sort by integer properties SORT_BY_CANV_ELEMENT_ID = 0, // Sort by element ID SORT_BY_CANV_ELEMENT_TYPE, // Sort by graphical element type //---... //---... SORT_BY_CANV_ELEMENT_FORE_COLOR, // Sort by default text color for all control objects SORT_BY_CANV_ELEMENT_FORE_COLOR_OPACITY, // Sort by default text color opacity for all control objects SORT_BY_CANV_ELEMENT_FORE_COLOR_MOUSE_DOWN, // Sort by control text color when clicking on the control SORT_BY_CANV_ELEMENT_FORE_COLOR_MOUSE_OVER, // Sort by control text color when hovering the mouse over the control SORT_BY_CANV_ELEMENT_FORE_COLOR_TOGGLE, // Sort by control text color when the control is on SORT_BY_CANV_ELEMENT_FORE_COLOR_TOGGLE_MOUSE_DOWN, // Sort by the default control text color when clicking on the control while it is on SORT_BY_CANV_ELEMENT_FORE_COLOR_TOGGLE_MOUSE_OVER, // Sort by the default control text color when hovering the mouse over the control while it is on SORT_BY_CANV_ELEMENT_BACKGROUND_COLOR, // Sort by control background text color SORT_BY_CANV_ELEMENT_BACKGROUND_COLOR_OPACITY, // Sort by control background color opacity SORT_BY_CANV_ELEMENT_BACKGROUND_COLOR_MOUSE_DOWN, // Sort by control background text color when clicking on the control SORT_BY_CANV_ELEMENT_BACKGROUND_COLOR_MOUSE_OVER, // Sort by control background text color when hovering the mouse over the control SORT_BY_CANV_ELEMENT_BACKGROUND_COLOR_TOGGLE, // Sort by control background color when the control is on SORT_BY_CANV_ELEMENT_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN,// Sort by control background color when clicking on the control while it is on SORT_BY_CANV_ELEMENT_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER,// Sort by control background color when hovering the mouse over the control while it is on SORT_BY_CANV_ELEMENT_BOLD_TYPE, // Sort by font width type SORT_BY_CANV_ELEMENT_BORDER_STYLE, // Sort by control frame style //---... //---... SORT_BY_CANV_ELEMENT_CHECK_STATE, // Sort by status of a control having a checkbox SORT_BY_CANV_ELEMENT_AUTOCHECK, // Sort by auto change flag status when it is selected SORT_BY_CANV_ELEMENT_BUTTON_TOGGLE, // Sort by the Toggle flag of the control featuring a button SORT_BY_CANV_ELEMENT_BUTTON_STATE, // Sort by the status of the Toggle control featuring a button SORT_BY_CANV_ELEMENT_CHECK_BACKGROUND_COLOR, // Sort by color of control checkbox background SORT_BY_CANV_ELEMENT_CHECK_BACKGROUND_COLOR_OPACITY, // Sort by opacity of control checkbox background color //---... //---... SORT_BY_CANV_ELEMENT_CHECK_FLAG_COLOR_MOUSE_DOWN, // Sort by color of control checkbox when clicking on the control SORT_BY_CANV_ELEMENT_CHECK_FLAG_COLOR_MOUSE_OVER, // Sort by color of control checkbox when hovering the mouse over the control //--- Sort by real properties //--- Sort by string properties SORT_BY_CANV_ELEMENT_NAME_OBJ = FIRST_CANV_ELEMENT_STR_PROP,// Sort by an element object name SORT_BY_CANV_ELEMENT_NAME_RES, // Sort by the graphical resource name SORT_BY_CANV_ELEMENT_TEXT, // Sort by graphical element text }; //+------------------------------------------------------------------+
Jetzt können wir Objekte nach neuen Eigenschaften sortieren und auswählen.
In \MQL5\Include\DoEasy\Data.mqh wurden neuen Nachrichtenindizes hinzugefügt:
MSG_CANV_ELEMENT_PROP_FORE_COLOR, // Default text color for all control objects MSG_CANV_ELEMENT_PROP_FORE_COLOR_OPACITY, // Default text color opacity for all control objects MSG_CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN, // Default control text color when clicking on the control MSG_CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER, // Default control text color when hovering the mouse over the control MSG_CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE, // Text color of the control which is on MSG_CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_DOWN,// Default control text color when clicking on the control which is on MSG_CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_OVER,// Default control text color when hovering the mouse over the control which is on MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR, // Control background color MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_OPACITY, // Opacity of control background color MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_DOWN, // Control background color when clicking on the control MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER, // Control background color when hovering the mouse over the control MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE, // Background color of the control which is on MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN,// Control background color when clicking on the control which is on MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER,// Control background color when hovering the mouse over control which is on MSG_CANV_ELEMENT_PROP_BOLD_TYPE, // Font width type MSG_CANV_ELEMENT_PROP_BORDER_STYLE, // Control frame style
...
MSG_CANV_ELEMENT_PROP_CHECK_STATE, // Status of a control having a checkbox MSG_CANV_ELEMENT_PROP_AUTOCHECK, // Auto change flag status when it is selected MSG_CANV_ELEMENT_PROP_BUTTON_TOGGLE, // Toggle flag of the control featuring a button MSG_CANV_ELEMENT_PROP_BUTTON_STATE, // Status of the Toggle control featuring a button MSG_CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR, // Color of control checkbox background MSG_CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_OPACITY,// Opacity of the control checkbox background color MSG_CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_DOWN,// Color of control checkbox background when clicking on the control MSG_CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_OVER,// Color of control checkbox background when hovering the mouse over the control MSG_CANV_ELEMENT_PROP_CHECK_FORE_COLOR, // Color of control checkbox frame MSG_CANV_ELEMENT_PROP_CHECK_FORE_COLOR_OPACITY, // Opacity of the control checkbox frame color MSG_CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_DOWN, // Color of control checkbox frame when clicking on the control MSG_CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_OVER, // Color of control checkbox frame when hovering the mouse over the control MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR, // Color of control checkbox MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_OPACITY, // Opacity of the control checkbox color MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN, // Color of control checkbox when clicking on the control MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER, // Color of control checkbox when hovering the mouse over the control //--- Real properties of graphical elements //--- String properties of graphical elements MSG_CANV_ELEMENT_PROP_NAME_OBJ, // Graphical element object name MSG_CANV_ELEMENT_PROP_NAME_RES, // Graphical resource name MSG_CANV_ELEMENT_PROP_TEXT, // Graphical element text
und die Textnachrichten, die den neu hinzugefügten Indizes entsprechen:
{"Цвет текста по умолчанию для всех объектов элемента управления","Default text color for all objects in the control"}, {"Непрозрачность цвета текста по умолчанию для всех объектов элемента управления","Default text color opacity for all objects in the control"}, {"Цвет текста элемента по умолчанию при нажатии мышки на элемент управления","The default text color of an element when the mouse is pressed on the control"}, {"Цвет текста элемента по умолчанию при наведении мышки на элемент управления","The default text color of an element when hovering over the control"}, {"Цвет текста элемента управления в состоянии \"включено\"","The text color of a control in the enabled state"}, {"Цвет текста элемента управления по умолчанию в состоянии \"включено\" при нажатии мышки на элемент управления","The default text color of the control in the \"On\" state when the mouse is pressed on the control"}, {"Цвет текста элемента управления по умолчанию в состоянии \"включено\" при наведении мышки на элемент управления","The default text color of a control in the \"On\" state when hovering the mouse over the control"}, {"Цвет фона элемента управления","Background color of the control"}, {"Непрозрачность цвета фона элемента управления","Opacity of the control's background color"}, {"Цвет фона элемента управления при нажатии мышки на элемент управления","Background color of the control when the mouse is clicked on the control"}, {"Цвет фона элемента управления при наведении мышки на элемент управления","Background color of the control when hovering the mouse over the control"}, {"Цвет фона элемента управления в состоянии \"включено\"","Background color of the control in the enabled state"}, {"Цвет фона элемента управления в состоянии \"включено\" при нажатии мышки на элемент управления","The background color of the control in the \"On\" state when the mouse is pressed on the control"}, {"Цвет фона элемента управления в состоянии \"включено\" при наведении мышки на элемент управления","The background color of a control in the \"On\" state when the mouse is over the control"}, {"Тип толщины шрифта","Font weight type"}, {"Стиль рамки элемента управления","Control's border style"},
...
{"Состояние элемента управления, имеющего флажок проверки","The state of a control that has a checkbox"}, {"Автоматическое изменение состояния флажка при его выборе","Automatically change the state of the checkbox when it is selected"}, {"Флаг \"Переключатель\" элемента управления, имеющего кнопку","\"Button-toggle\" flag of a control"}, {"Состояние элемента управления \"Переключатель\", имеющего кнопку","The \"Toggle-button\" control state"}, {"Цвет фона флажка проверки элемента управления","The background color of the control's validation checkbox"}, {"Непрозрачность цвета фона флажка проверки элемента управления","Opacity of the backgroung color of the checkbox control"}, {"Цвет фона флажка проверки элемента управления при нажатии мышки на элемент управления","The background color of the control's checkbox when the control is pressed with the mouse"}, {"Цвет фона флажка проверки элемента управления при наведении мышки на элемент управления","The background color of the control's validation checkbox when hovering the mouse over the control"}, {"Цвет рамки флажка проверки элемента управления","Border color of the checkbox control"}, {"Непрозрачность цвета рамки флажка проверки элемента управления","Border color opacity of the checkbox control"}, {"Цвет рамки флажка проверки элемента управления при нажатии мышки на элемент управления","Border color of the checkbox control when the mouse is pressed on the control"}, {"Цвет рамки флажка проверки элемента управления при наведении мышки на элемент управления","Border color of the checkbox control when hovering the mouse over the control"}, {"Цвет флажка проверки элемента управления","Control Checkbox Color"}, {"Непрозрачность цвета флажка проверки элемента управления","Opacity of control's checkbox color"}, {"Цвет флажка проверки элемента управления при нажатии мышки на элемент управления","Control Checkbox Colorl when the mouse is pressed on the control"}, {"Цвет флажка проверки элемента управления при наведении мышки на элемент управления","Control Checkbox Colorl when hovering the mouse over the control"}, //--- String properties of graphical elements {"Имя объекта-графического элемента","The name of the graphic element object"}, {"Имя графического ресурса","Image resource name"}, {"Текст графического элемента","Text of the graphic element"},
Wenn man mit dem Mauszeiger über ein Objekt fährt oder darauf klickt, muss sich seine Hintergrundfarbe ändern. Aber um die ursprüngliche Farbe wiederherzustellen, müssen wir uns bei der ersten Objektkonstruktion daran erinnern und die benötigte Farbe aus der zuvor gespeicherten nehmen.
Da die Hintergrundfarbe eines grafischen Objekts ein Farbverlauf sein kann, d.h. ein Array von Farben verwenden kann, benötigen wir ein ganzes Array und nicht nur eine Variable zum Speichern der Ausgangsfarbe. Es wird genauso gefüllt wie das Array der Farbverläufe, wenn das Objekt erstellt wird. Wenn wir die Farbe wiederherstellen, nehmen wir die Farbe aus dem gespeicherten Array.
In \MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqh, und zwar in seinem geschützten (protected) Abschnitt, deklarieren wir das Array der anfänglichen Hintergrundfarben und verschieben die Methode zum Ausfüllen der Farbarrays aus dem privaten Abschnitt hierher. Wir werden sie in den geerbten Klassen benötigen:
//+------------------------------------------------------------------+ //| Class of the graphical element object | //+------------------------------------------------------------------+ class CGCnvElement : public CGBaseObj { protected: CGCnvElement *m_element_main; // Pointer to the initial parent element within all the groups of bound objects CGCnvElement *m_element_base; // Pointer to the parent element within related objects of the current group CCanvas m_canvas; // CCanvas class object CPause m_pause; // Pause class object bool m_shadow; // Shadow presence color m_chart_color_bg; // Chart background color uint m_duplicate_res[]; // Array for storing resource data copy color m_array_colors_bg[]; // Array of element background colors color m_array_colors_bg_dwn[]; // Array of control background colors when clicking on the control color m_array_colors_bg_ovr[]; // Array of control background colors when hovering the mouse over the control bool m_gradient_v; // Vertical gradient filling flag bool m_gradient_c; // Cyclic gradient filling flag int m_init_relative_x; // Initial relative X coordinate int m_init_relative_y; // Initial relative Y coordinate color m_array_colors_bg_init[]; // Array of element background colors (initial color) //--- Create (1) the object structure and (2) the object from the structure virtual bool ObjectToStruct(void); virtual void StructToObject(void); //--- Copy the color array to the specified background color array void CopyArraysColors(color &array_dst[],const color &array_src[],const string source); private:
Im privaten Bereich der Klasse, d. h. in der Objektdatenstruktur, fügen wir neue Objekt-Ganzzahl-Eigenschaften hinzu:
private: int m_shift_coord_x; // Offset of the X coordinate relative to the base object int m_shift_coord_y; // Offset of the Y coordinate relative to the base object struct SData { //--- Object integer properties int id; // Element ID int type; // Graphical element type //---... //---... color check_flag_color_mouse_down; // Color of control checkbox when clicking on the control color check_flag_color_mouse_over; // Color of control checkbox when clicking on the control color fore_color_mouse_down; // Default control text color when clicking on the control color fore_color_mouse_over; // Default control text color when hovering the mouse over the control color fore_color_toggle; // Text color of the control which is on color fore_color_toggle_mouse_down; // Default control text color when clicking on the control which is on color fore_color_toggle_mouse_over; // Default control text color when hovering the mouse over the control which is on color background_color_toggle; // Background color of the control which is on color background_color_toggle_mouse_down; // Control background color when clicking on the control which is on color background_color_toggle_mouse_over; // Control background color when hovering the mouse over the control which is on bool button_toggle; // Toggle flag of the control featuring a button bool button_state; // Status of the Toggle control featuring a button //--- Object real properties //--- Object string properties uchar name_obj[64]; // Graphical element object name uchar name_res[64]; // Graphical resource name uchar text[256]; // Graphical element text }; SData m_struct_obj; // Object structure uchar m_uchar_array[]; // uchar array of the object structure
Dies ist notwendig, damit das Objekt in Zukunft korrekt auf dem Medium gespeichert und von ihm gelesen werden kann.
Fügen wir eine weitere Methode zum Speichern eines Arrays von Farbverläufen hinzu, um die ursprüngliche Hintergrundfarbe zu speichern:
//--- Save the colors to the background color array void SaveColorsBG(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg,colors,DFUN); } void SaveColorsBGMouseDown(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg_dwn,colors,DFUN); } void SaveColorsBGMouseOver(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg_ovr,colors,DFUN); } void SaveColorsBGInit(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg_init,colors,DFUN); } public:
Die Methode wird in der Methode zur Einstellung der Hintergrundfarbe aufgerufen. Um dies zu erreichen, werde ich das Flag einführen, das angibt, dass die anfängliche Hintergrundfarbe nach dem Einstellen der Hintergrundfarbe des Objekts in den formalen Variablen gespeichert werden muss. Wir haben also die Wahl: Entweder wir legen eine Objekt-Hintergrundfarbe fest und merken uns ihre Ausgangsfarben im Array, oder wir legen einfach eine neue Hintergrundfarbe fest, die dann aus dem gesamten Satz von Hintergrund-Farbverläufen wiederhergestellt werden kann, die zuvor im Array festgelegt wurden. Ich werde dies für alle Objekte tun, deren Farbe sich bei Interaktion mit der Maus ändern soll:
//--- Set the main background color void SetBackgroundColor(const color colour,const bool set_init_color) { this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR,colour); color arr[1]; arr[0]=colour; this.SaveColorsBG(arr); if(set_init_color) this.SetBackgroundColorInit(this.BackgroundColor()); } void SetBackgroundColors(color &colors[],const bool set_init_colors) { this.SaveColorsBG(colors); this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR,this.m_array_colors_bg[0]); if(set_init_colors) this.SetBackgroundColorsInit(colors); }
Fügen wir ähnlich hinzu Methoden zur Einstellung der anfänglichen Hintergrundfarbe:
void SetBackgroundColorsMouseOver(color &colors[]) { this.SaveColorsBGMouseOver(colors); this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER,this.m_array_colors_bg_ovr[0]); } //--- Set the initial main background color void SetBackgroundColorInit(const color colour) { color arr[1]; arr[0]=colour; this.SaveColorsBGInit(arr); } void SetBackgroundColorsInit(color &colors[]) { this.SaveColorsBGInit(colors); } //--- Set (1) object movability, (2) activity, (3) interaction,
Hier ist alles gleich wie bei den Methoden zum Einstellen der Haupthintergrundfarbe, mit Ausnahme des Flags, das die Notwendigkeit des Speicherns der Ausgangsfarbe anzeigt, die durch den Aufruf dieser Methoden gespeichert wird.
Schreiben wir die Methoden, die die ursprüngliche Hintergrundfarbe zurückgeben:
//--- Return the background color when hovering the mouse over the control color BackgroundColorMouseOver(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER); } color BackgroundColorMouseOver(const uint index) const { uint total=this.m_array_colors_bg_ovr.Size(); if(total==0) return this.BackgroundColorMouseOver(); return(index>total-1 ? this.m_array_colors_bg_ovr[total-1] : this.m_array_colors_bg_ovr[index]); } //--- Return the initial color of the main background color BackgroundColorInit(void) const { return (color)this.m_array_colors_bg_init[0]; } color BackgroundColorInit(const uint index)const { uint total=this.m_array_colors_bg_init.Size(); if(total==0) return this.BackgroundColor(); return(index>total-1 ? this.m_array_colors_bg_init[total-1] : this.m_array_colors_bg_init[index]); } //--- Return (1) the opacity, coordinate (2) of the right and (3) bottom element edge
Die Methoden geben entweder die einzige Hintergrundfarbe oder eine Farbe aus der Menge der Farbverläufe zurück, die dem an die Methode übergebenen Index entspricht.
Wir legen in beiden Klassenkonstruktoren die Initialisierung neuer Eigenschaften fest und übergeben das Flag zum Speichern der anfänglichen Hintergrundfarbe:
//+------------------------------------------------------------------+ //| Parametric constructor | //+------------------------------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id, const int element_num, const long chart_id, const int wnd_num, const string name, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable=true, const bool activity=true, const bool redraw=false) : m_shadow(false) { this.m_type=OBJECT_DE_TYPE_GELEMENT; this.m_element_main=NULL; this.m_element_base=NULL; this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND); this.m_name=(::StringFind(name,this.m_name_prefix)<0 ? this.m_name_prefix : "")+name; this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id); this.m_subwindow=wnd_num; this.m_type_element=element_type; this.SetFont(DEF_FONT,DEF_FONT_SIZE); this.m_text_anchor=0; this.m_text_x=0; this.m_text_y=0; this.SetBackgroundColor(colour,true); this.SetOpacity(opacity); this.m_shift_coord_x=0; this.m_shift_coord_y=0; if(::ArrayResize(this.m_array_colors_bg,1)==1) this.m_array_colors_bg[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_dwn,1)==1) this.m_array_colors_bg_dwn[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_ovr,1)==1) this.m_array_colors_bg_ovr[0]=this.BackgroundColor(); if(this.Create(chart_id,wnd_num,this.m_name,x,y,w,h,redraw)) { this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,this.m_canvas.ResourceName()); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_CHART_ID,CGBaseObj::ChartID()); // Chart ID this.SetProperty(CANV_ELEMENT_PROP_WND_NUM,CGBaseObj::SubWindow()); // Chart subwindow index this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,CGBaseObj::Name()); // Element object name this.SetProperty(CANV_ELEMENT_PROP_TYPE,element_type); // Graphical element type this.SetProperty(CANV_ELEMENT_PROP_ID,element_id); // Element ID this.SetProperty(CANV_ELEMENT_PROP_NUM,element_num); // Element index in the list this.SetProperty(CANV_ELEMENT_PROP_COORD_X,x); // Element's X coordinate on the chart this.SetProperty(CANV_ELEMENT_PROP_COORD_Y,y); // Element's Y coordinate on the chart this.SetProperty(CANV_ELEMENT_PROP_WIDTH,w); // Element width this.SetProperty(CANV_ELEMENT_PROP_HEIGHT,h); // Element height this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT,0); // Active area offset from the left edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP,0); // Active area offset from the upper edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT,0); // Active area offset from the right edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM,0); // Active area offset from the bottom edge of the element this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,movable); // Element moveability flag this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,activity); // Element activity flag this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,false); // Flag of interaction with the outside environment this.SetProperty(CANV_ELEMENT_PROP_ENABLED,true); // Element availability flag this.SetProperty(CANV_ELEMENT_PROP_RIGHT,this.RightEdge()); // Element right border this.SetProperty(CANV_ELEMENT_PROP_BOTTOM,this.BottomEdge()); // Element bottom border this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_X,this.ActiveAreaLeft()); // X coordinate of the element active area this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_Y,this.ActiveAreaTop()); // Y coordinate of the element active area this.SetProperty(CANV_ELEMENT_PROP_ACT_RIGHT,this.ActiveAreaRight()); // Right border of the element active area this.SetProperty(CANV_ELEMENT_PROP_ACT_BOTTOM,this.ActiveAreaBottom()); // Bottom border of the element active area //--- this.SetProperty(CANV_ELEMENT_PROP_BELONG,ENUM_GRAPH_OBJ_BELONG::GRAPH_OBJ_BELONG_PROGRAM); // Graphical element affiliation this.SetProperty(CANV_ELEMENT_PROP_ZORDER,0); // Priority of a graphical object for receiving the event of clicking on a chart this.SetProperty(CANV_ELEMENT_PROP_BOLD_TYPE,FW_NORMAL); // Font width type this.SetProperty(CANV_ELEMENT_PROP_BORDER_STYLE,FRAME_STYLE_NONE); // Control frame style this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_TOP,0); // Control frame top size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_BOTTOM,0); // Control frame bottom size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_LEFT,0); // Control frame left size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_RIGHT,0); // Control frame right size this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR,this.BackgroundColor()); // Control frame color this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE,false); // Flag of the element auto resizing depending on the content this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE_MODE,CANV_ELEMENT_AUTO_SIZE_MODE_GROW); // Mode of the element auto resizing depending on the content this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL,false); // Auto scrollbar flag this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL_MARGIN_W,0); // Width of the field inside the element during auto scrolling this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL_MARGIN_H,0); // Height of the field inside the element during auto scrolling this.SetProperty(CANV_ELEMENT_PROP_DOCK_MODE,CANV_ELEMENT_DOCK_MODE_NONE); // Mode of binding control borders to the container this.SetProperty(CANV_ELEMENT_PROP_MARGIN_TOP,0); // Top margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_BOTTOM,0); // Bottom margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_LEFT,0); // Left margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_RIGHT,0); // Right margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_PADDING_TOP,0); // Top margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_BOTTOM,0); // Bottom margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_LEFT,0); // Left margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_RIGHT,0); // Right margin inside the control this.SetProperty(CANV_ELEMENT_PROP_TEXT_ALIGN,ANCHOR_LEFT_UPPER); // Text position within text label boundaries this.SetProperty(CANV_ELEMENT_PROP_CHECK_ALIGN,ANCHOR_LEFT_UPPER); // Position of the checkbox within control borders this.SetProperty(CANV_ELEMENT_PROP_CHECKED,false); // Control checkbox status this.SetProperty(CANV_ELEMENT_PROP_CHECK_STATE,CANV_ELEMENT_CHEK_STATE_UNCHECKED); // Status of a control having a checkbox this.SetProperty(CANV_ELEMENT_PROP_AUTOCHECK,true); // Auto change flag status when it is selected //--- this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR,CLR_DEF_CHECK_BACK_COLOR); // Color of control checkbox background this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_OPACITY,CLR_DEF_CHECK_BACK_OPACITY); // Opacity of the control checkbox background color this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_DOWN,CLR_DEF_CHECK_BACK_MOUSE_DOWN);// Color of control checkbox background when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_OVER,CLR_DEF_CHECK_BACK_MOUSE_OVER);// Color of control checkbox background when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR,CLR_DEF_CHECK_BORDER_COLOR); // Color of control checkbox frame this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_OPACITY,CLR_DEF_CHECK_BORDER_OPACITY); // Opacity of the control checkbox frame color this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_DOWN,CLR_DEF_CHECK_BORDER_MOUSE_DOWN);// Color of control checkbox frame when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_OVER,CLR_DEF_CHECK_BORDER_MOUSE_OVER);// Color of control checkbox frame when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR,CLR_DEF_CHECK_FLAG_COLOR); // Control checkbox color this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_OPACITY,CLR_DEF_CHECK_FLAG_OPACITY); // Control checkbox color opacity this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN,CLR_DEF_CHECK_FLAG_MOUSE_DOWN); // Control checkbox color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER,CLR_DEF_CHECK_FLAG_MOUSE_OVER); // Control checkbox color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR,CLR_DEF_FORE_COLOR); // Default text color for all control objects this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_OPACITY,CLR_DEF_FORE_COLOR_OPACITY); // Opacity of the default text color for all control objects this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN,CLR_DEF_FORE_COLOR_MOUSE_DOWN); // Default control text color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER,CLR_DEF_FORE_COLOR_MOUSE_OVER); // Default control text color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE,CLR_DEF_FORE_COLOR); // Text color of the control which is on this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_DOWN,CLR_DEF_FORE_COLOR_MOUSE_DOWN); // Default control text color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_OVER,CLR_DEF_FORE_COLOR_MOUSE_OVER); // Default control text color when hovering the mouse over the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_DOWN,this.BackgroundColor()); // Control background color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER,this.BackgroundColor()); // Control background color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE,CLR_DEF_CONTROL_STD_BACK_COLOR_ON); // Background color of the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN,CLR_DEF_CONTROL_STD_BACK_DOWN_ON); // Control background color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER,CLR_DEF_CONTROL_STD_BACK_OVER_ON); // Control background color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR_MOUSE_DOWN,CLR_DEF_BORDER_MOUSE_DOWN); // Control frame color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR_MOUSE_OVER,CLR_DEF_BORDER_MOUSE_OVER); // Control frame color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_BUTTON_TOGGLE,false); // Toggle flag of the control featuring a button this.SetProperty(CANV_ELEMENT_PROP_BUTTON_STATE,false); // Status of the Toggle control featuring a button } else { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),": ",this.m_name); } } //+------------------------------------------------------------------+
BorderColor-Werte werden jetzt auf die ForceColor-Eigenschaften des Kontrollkästchens gesetzt, da das Kontrollkästchen seine eigene Farbe hat.
Der zweite Konstruktor ist ähnlich. Es hat keinen Sinn, ihn hier zu besprechen.
In der Methode, die die Objektstruktur erstellt, fügen wir das Sichern der Objekteigenschaften zu den Strukturfeldern hinzu:
//+------------------------------------------------------------------+ //| Create the object structure | //+------------------------------------------------------------------+ bool CGCnvElement::ObjectToStruct(void) { //--- Save integer properties this.m_struct_obj.id=(int)this.GetProperty(CANV_ELEMENT_PROP_ID); // Element ID this.m_struct_obj.type=(int)this.GetProperty(CANV_ELEMENT_PROP_TYPE); // Graphical element type //---... //---... this.m_struct_obj.check_flag_color_mouse_down=(color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN);// Control checkbox color when clicking on the control this.m_struct_obj.check_flag_color_mouse_over=(color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER);// Control checkbox color when hovering the mouse over the control this.m_struct_obj.fore_color_mouse_down=(color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN); // Default control text color when clicking on the control this.m_struct_obj.fore_color_mouse_over=(color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER); // Default control text color when hovering the mouse over the control this.m_struct_obj.fore_color_toggle=(color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE); // Text color of the control which is on this.m_struct_obj.fore_color_toggle_mouse_down=(color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_DOWN);// Default control text color when clicking on the control which is on this.m_struct_obj.fore_color_toggle_mouse_over=(color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_OVER);// Default control text color when hovering the mouse over the control which is on this.m_struct_obj.background_color_toggle=(color)this.GetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE); // Background color of the control which is on this.m_struct_obj.background_color_toggle_mouse_down=(color)this.GetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN);// Control background color when clicking on the control which is on this.m_struct_obj.background_color_toggle_mouse_over=(color)this.GetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER);// Control background color when hovering the mouse over the control which is on this.m_struct_obj.button_toggle=(bool)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_TOGGLE); // Toggle flag of the control featuring a button this.m_struct_obj.button_state=(bool)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_STATE); // Status of the Toggle control featuring a button //--- Save real properties //--- Save string properties ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_NAME_OBJ),this.m_struct_obj.name_obj); // Graphical element object name ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_NAME_RES),this.m_struct_obj.name_res); // Graphical resource name ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TEXT),this.m_struct_obj.text); // Graphical element text //--- Save the structure to the uchar array ::ResetLastError(); if(!::StructToCharArray(this.m_struct_obj,this.m_uchar_array)) { CMessage::ToLog(DFUN,MSG_LIB_SYS_FAILED_SAVE_OBJ_STRUCT_TO_UARRAY,true); return false; } return true; } //+------------------------------------------------------------------+
Fügen wir in der Methode, die ihr Strukturobjekt erstellt, die Einstellung neuer Objekteigenschaften aus den Strukturfeldern hinzu:
//+------------------------------------------------------------------+ //| Create the object from the structure | //+------------------------------------------------------------------+ void CGCnvElement::StructToObject(void) { //--- Save integer properties this.SetProperty(CANV_ELEMENT_PROP_ID,this.m_struct_obj.id); // Element ID this.SetProperty(CANV_ELEMENT_PROP_TYPE,this.m_struct_obj.type); // Graphical element type //---... //---... this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER,this.m_struct_obj.check_flag_color_mouse_over); // Control checkbox color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN,this.m_struct_obj.fore_color_mouse_down); // Default control text color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER,this.m_struct_obj.fore_color_mouse_over); // Default control text color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE,this.m_struct_obj.fore_color_toggle); // Text color of the control which is on this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_DOWN,this.m_struct_obj.fore_color_toggle_mouse_down);// Default control text color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_OVER,this.m_struct_obj.fore_color_toggle_mouse_over);// Default control text color when hovering the mouse over the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE,this.m_struct_obj.background_color_toggle); // Background color of the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN,this.m_struct_obj.background_color_toggle_mouse_down);// Control background color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER,this.m_struct_obj.background_color_toggle_mouse_over);// Control background color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_BUTTON_TOGGLE,this.m_struct_obj.button_toggle); // Toggle flag of the control featuring a button this.SetProperty(CANV_ELEMENT_PROP_BUTTON_STATE,this.m_struct_obj.button_state); // Status of the Toggle control featuring a button //--- Save real properties //--- Save string properties this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,::CharArrayToString(this.m_struct_obj.name_obj)); // Graphical element object name this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,::CharArrayToString(this.m_struct_obj.name_res)); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_TEXT,::CharArrayToString(this.m_struct_obj.text)); // Graphical element text } //+------------------------------------------------------------------+
Im Konstruktor der Schattenobjektklasse in \MQL5\Include\DoEasy\Objects\Graph\ShadowObj.mqh übergeben wir das Flag, das angibt, dass die Ausgangsfarbe beim Einstellen der Hintergrundfarbe gespeichert werden muss:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CShadowObj::CShadowObj(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h) : CGCnvElement(GRAPH_ELEMENT_TYPE_SHADOW_OBJ,chart_id,subwindow,name,x,y,w,h) { this.m_type=OBJECT_DE_TYPE_GSHADOW; CGCnvElement::SetBackgroundColor(clrNONE,true); CGCnvElement::SetOpacity(0); CGCnvElement::SetActive(false); this.m_opacity=CLR_DEF_SHADOW_OPACITY; this.m_blur=DEF_SHADOW_BLUR; color gray=CGCnvElement::ChangeColorSaturation(this.ChartBackgroundColor(),-100); this.m_color=CGCnvElement::ChangeColorLightness(gray,-50); this.m_shadow=false; this.m_visible=true; CGCnvElement::Erase(); } //+------------------------------------------------------------------+
Es besteht keine Notwendigkeit, hier eine vollständig transparente Farbe zu speichern, aber wir sollten sie beibehalten, um nicht initialisierte Eigenschaftswerte zu vermeiden.
Das Formularobjekt ist ein Basisobjekt des grafischen Elements, das die Funktionalität der Interaktion mit der Maus enthält. Wir fügen im selben Formularobjekt den virtuellen Maus-Ereignishandler und virtuelle Handler für jedes durch den Ereignishandler definierte Ereignis hinzu.
Die Ereignisbehandlung wird virtuell sein, falls sie in den abgeleiteten Klassen überschrieben werden muss, während die Handler der einzelnen Mausereignisse virtuell sein sollten, da die Behandlung eines bestimmten Mausereignisses für jedes der Objekte, die Erben der Formularobjektklasse sind, individuell sein wird. Um den Zustand des Objekts und seiner Farbe wiederherzustellen, nachdem der Cursor den aktiven Bereich verlassen hat, benötigen wir eine Methode, die einen solchen Zustand (Bewegen des Cursors vom Objekt weg) behandelt. Da ein anderes Objekt (oder gar kein Objekt) aktiv wird, nachdem der Cursor von dem einen Objekt entfernt wurde, müssen wir alle WinForms-Objekte durchgehen, ihren letzten Zustand bestimmen und ihn behandeln, falls der letzte Zustand ein Überfahren mit der Maus war. Dann müssen wir den Zustand durch einen anderen ersetzen, der seinem aktuellen Zustand entspricht. Wir werden also nur einmal das Entfernen des Cursors vom Objekt behandeln und das Objekt in den richtigen Zustand versetzen — der Cursor befindet sich außerhalb des Formulars.
Im geschützten Klassenabschnitt der Formularobjektdatei \MQL5\Include\DoEasy\Objects\Graph\Form.mqh deklarieren wir zwei Variablen — zum Speichern des letzten Mausereignisses (erforderlich für den letzten Ereignishandler) und zum Speichern der anfänglichen Farbe des Formularrahmens (da sich die Farbe bei der Interaktion mit der Maus ändern kann, so dass es notwendig ist, die ursprüngliche Farbe wiederherzustellen). Deklarieren wir auch die virtuellen Handler für jedes Mausereignis:
protected: CArrayObj m_list_elements; // List of attached elements CArrayObj m_list_interact; // List of interaction elements CAnimations *m_animations; // Pointer to the animation object CShadowObj *m_shadow_obj; // Pointer to the shadow object CMouseState m_mouse; // "Mouse status" class object ENUM_MOUSE_FORM_STATE m_mouse_form_state; // Mouse status relative to the form ENUM_MOUSE_EVENT m_mouse_event_last; // Last mouse event ushort m_mouse_state_flags; // Mouse status flags int m_offset_x; // Offset of the X coordinate relative to the cursor int m_offset_y; // Offset of the Y coordinate relative to the cursor CArrayObj m_list_tmp; // List for storing the pointers int m_init_x; // Newly created form X coordinate int m_init_y; // Newly created form Y coordinate int m_init_w; // Newly created form width int m_init_h; // Newly created form height color m_border_color_init; // Initial color of the control frame //--- Initialize the variables virtual void Initialize(void); void Deinitialize(void); //--- Create a shadow object void CreateShadowObj(const color colour,const uchar opacity); //--- Return the name of the dependent object string CreateNameDependentObject(const string base_name) const { return ::StringSubstr(this.NameObj(),::StringLen(::MQLInfoString(MQL_PROGRAM_NAME))+1)+"_"+base_name; } //--- Update coordinates of bound objects virtual bool MoveDependentObj(const int x,const int y,const bool redraw=false); //--- Create a new bound element and add it to the list of bound objects virtual CGCnvElement *CreateAndAddNewElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool activity); //--- Create the list of all interaction objects void CreateListDepInteractObj(CArrayObj *list); //--- Return the flag indicating the presence of the pointer to an object in the list of interaction objects by name bool IsPresentInteractObj(const string name); //--- 'The cursor is outside the form, no mouse buttons are clicked' event handler virtual void MouseOutsideNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is outside the form, a mouse button is clicked (any)' event handler virtual void MouseOutsidePressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is outside the form, the mouse wheel is being scrolled' event handler virtual void MouseOutsideWhellHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the form, no mouse buttons are clicked' event handler virtual void MouseInsideNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the form, a mouse button is clicked (any)' event handler virtual void MouseInsidePressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the form, the mouse wheel is being scrolled' event handler virtual void MouseInsideWhellHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, the mouse buttons are not clicked' event handler virtual void MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, a mouse button is clicked (any)' event handler virtual void MouseActiveAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, the mouse wheel is being scrolled' event handler virtual void MouseActiveAreaWhellHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, the left mouse button is clicked' event handler virtual void MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the window scrolling area, no mouse buttons are clicked' event handler virtual void MouseScrollAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the window scrolling area, a mouse button is clicked (any)' event handler virtual void MouseScrollAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the window scrolling area, the mouse wheel is being scrolled' event handler virtual void MouseScrollAreaWhellHandler(const int id,const long& lparam,const double& dparam,const string& sparam); public:
Im öffentlichen (public) Abschnitt der Klasse deklarieren wir die virtuelle Methode zum Neuzeichnen eines Objekts, schreiben die Methode, die die Variable zum Speichern des Mausstatus zurückgibt, sowie
die Methode, die das letzte Mausereignis zurückgibt.
Die Methoden zur Einstellung der Rahmengröße auf jeder Seite sind virtuell. Deklarieren wir auch die Handler für die virtuellen Mausereignisse sowie den letzten Event-Handler:
public: //--- Redraw the object virtual void Redraw(bool redraw) { return; } //--- Create the list of all interaction objects int CreateListInteractObj(void); //--- Return the pointer to the form object in the list of interaction objects CForm *GetInteractForm(const int index) { return this.m_list_interact.At(index); } //--- Return the initial (1) X and (2) Y coordinate, (3) form width and (4) height int GetCoordXInit(void) const { return this.m_init_x; } int GetCoordYInit(void) const { return this.m_init_y; } int GetWidthInit(void) const { return this.m_init_w; } int GetHeightInit(void) const { return this.m_init_h; } //--- Set the initial (1) X and (2) Y coordinate, (3) form width and (4) height void SetCoordXInit(const int value) { this.m_init_x=value; } void SetCoordYInit(const int value) { this.m_init_y=value; } void SetWidthInit(const int value) { this.m_init_w=value; } void SetHeightInit(const int value) { this.m_init_h=value; } //--- (1) Get and (2) return the mouse status relative to the form, as well as cursor (3) X, (4) Y coordinates and (4) the last mouse event ENUM_MOUSE_FORM_STATE MouseFormState(const int id,const long lparam,const double dparam,const string sparam); ENUM_MOUSE_FORM_STATE GetMouseState(void) const { return this.m_mouse_form_state; } int MouseCursorX(void) const { return this.m_mouse.CoordX(); } int MouseCursorY(void) const { return this.m_mouse.CoordY(); } ENUM_MOUSE_EVENT MouseEventLast(void) const { return this.m_mouse_event_last; } //--- Set the flags of mouse scrolling, context menu and the crosshairs tool for the chart void SetChartTools(const bool flag); //--- (1) Set and (2) return the shift of X and Y coordinates relative to the cursor void SetOffsetX(const int value) { this.m_offset_x=value; } void SetOffsetY(const int value) { this.m_offset_y=value; } int OffsetX(void) const { return this.m_offset_x; } int OffsetY(void) const { return this.m_offset_y; } //--- Return the frame size (1) to the left, (2) at the top, (3) to the right, (4) at the bottom and (5) on all sides int BorderSizeLeft(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_LEFT); } int BorderSizeTop(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_TOP); } int BorderSizeRight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_RIGHT); } int BorderSizeBottom(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_BOTTOM);} //--- Set the frame size (1) to the left, (2) at the top, (3) to the right, (4) at the bottom and (5) on all sides virtual void SetBorderSizeLeft(const uint value) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_LEFT,value); } virtual void SetBorderSizeTop(const uint value) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_TOP,value); } virtual void SetBorderSizeRight(const uint value) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_RIGHT,value); } virtual void SetBorderSizeBottom(const uint value) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_BOTTOM,value); } //--- Update the coordinates (shift the canvas) virtual bool Move(const int x,const int y,const bool redraw=false); //--- Set the priority of a graphical object for receiving the event of clicking on a chart virtual bool SetZorder(const long value,const bool only_prop); //--- Set the object above all virtual void BringToTop(void); //--- Event handler virtual void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam); //--- Mouse event handler virtual void OnMouseEvent(const int id,const long& lparam,const double& dparam,const string& sparam); //--- Last mouse event handler virtual void OnMouseEventPostProcessing(void); //--- Constructors
Ändern wir die Methode zum Setzen der Objektrahmenfarbe so, dass der Flag-Status die Notwendigkeit anzeigt, die ursprüngliche Rahmenfarbe zu speichern und schreiben die Methoden zum Setzen und Zurückgeben der ursprünglichen Objektrahmenfarbe:
//+------------------------------------------------------------------+ //| Methods of simplified access to object properties | //+------------------------------------------------------------------+ //--- (1) Set and (2) return the control frame color void SetBorderColor(const color colour,const bool set_init_color) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR,colour); if(set_init_color) this.SetBorderColorInit(colour); } color BorderColor(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_BORDER_COLOR); } //--- (1) Set and (2) return the control frame color when clicking the control void SetBorderColorMouseDown(const color colour) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR_MOUSE_DOWN,colour); } color BorderColorMouseDown(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_BORDER_COLOR_MOUSE_DOWN); } //--- (1) Set and (2) return the control frame color when hovering the mouse over the control void SetBorderColorMouseOver(const color colour) { this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR_MOUSE_OVER,colour); } color BorderColorMouseOver(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_BORDER_COLOR_MOUSE_OVER); } //--- (1) Set and (2) get the initial color of the control frame void SetBorderColorInit(const color colour) { this.m_border_color_init=colour; } color BorderColorInit(void) const { return (color)this.m_border_color_init; } //--- (1) Set and (2) return the form shadow color
Die anfängliche Rahmenfarbe in der Objektinitialisierungsmethode speichern wir, indem wir das erforderliche Flag in der Methode zum Einstellen der Farbe angeben, und wir legen die Standardfarben für die Rahmenfarbe fest, wenn der Mauszeiger über dem Objekt schwebt und wenn man darauf klickt. Initialisieren des letzten Mausereignisses:
//+------------------------------------------------------------------+ //| Initialize the variables | //+------------------------------------------------------------------+ void CForm::Initialize(void) { this.m_list_elements.Clear(); this.m_list_elements.Sort(); this.m_list_interact.Clear(); this.m_list_interact.Sort(); this.m_list_tmp.Clear(); this.m_list_tmp.Sort(); this.m_shadow_obj=NULL; this.m_shadow=false; this.SetBorderSizeTop(DEF_FRAME_WIDTH_SIZE); this.SetBorderSizeBottom(DEF_FRAME_WIDTH_SIZE); this.SetBorderSizeLeft(DEF_FRAME_WIDTH_SIZE); this.SetBorderSizeRight(DEF_FRAME_WIDTH_SIZE); this.SetBorderColor(CLR_DEF_BORDER_COLOR,true); this.SetBorderColorMouseDown(CLR_DEF_BORDER_MOUSE_DOWN); this.SetBorderColorMouseOver(CLR_DEF_BORDER_MOUSE_OVER); this.m_gradient_v=true; this.m_gradient_c=false; this.m_mouse_state_flags=0; this.m_mouse_event_last=MOUSE_EVENT_NO_EVENT; this.m_offset_x=0; this.m_offset_y=0; this.m_init_x=0; this.m_init_y=0; this.m_init_w=0; this.m_init_h=0; CGCnvElement::SetInteraction(false); this.m_animations=new CAnimations(CGCnvElement::GetObject()); this.m_list_tmp.Add(this.m_animations); } //+------------------------------------------------------------------+
Wir setzen das Flag in allen Objekterstellungsmethoden, die die Hintergrundfarbe erfordern. In der Methode CreateAndAddNewElement():
obj.SetBackgroundColor(colour,true);
In der Methode Einstellung des Farbschemas:
//+------------------------------------------------------------------+ //| Set the color scheme | //+------------------------------------------------------------------+ void CForm::SetColorTheme(const ENUM_COLOR_THEMES theme,const uchar opacity) { if(this.m_shadow && this.m_shadow_obj!=NULL) this.SetColorShadow(array_color_themes[theme][COLOR_THEME_COLOR_FORM_SHADOW]); this.SetOpacity(opacity); this.SetBackgroundColor(array_color_themes[theme][COLOR_THEME_COLOR_FORM_BG],true); this.SetBorderColor(array_color_themes[theme][COLOR_THEME_COLOR_FORM_FRAME],true); } //+------------------------------------------------------------------+
Die ursprüngliche Hintergrundfarbe des Steuerelements wird nun in jedem Fall beibehalten.
In der Methode, die den Zustand der Maus relativ zum Formular festlegt und zurückgibt, haben wir zuvor eine lokale Variable deklariert, in die wir den Zustand der Maus geschrieben und den Variablenwert zurückgegeben haben. Jetzt haben wir eine solche Variable in der Klasse, um diesen Wert zu speichern.
Schreiben wir die Werte hinein und kehren aus der Methode zurück:
//+------------------------------------------------------------------+ //| Set and get the mouse status relative to the form | //+------------------------------------------------------------------+ ENUM_MOUSE_FORM_STATE CForm::MouseFormState(const int id,const long lparam,const double dparam,const string sparam) { //--- Get the mouse status relative to the form, as well as the states of mouse buttons and Shift/Ctrl keys this.m_mouse_form_state=MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED; ENUM_MOUSE_BUTT_KEY_STATE state=this.m_mouse.ButtonKeyState(id,lparam,dparam,sparam); //--- Get the mouse status flags from the CMouseState class object and save them in the variable this.m_mouse_state_flags=this.m_mouse.GetMouseFlags(); //--- If the cursor is inside the form if(CGCnvElement::CursorInsideElement(m_mouse.CoordX(),m_mouse.CoordY())) { //--- Set bit 8 responsible for the "cursor inside the form" flag this.m_mouse_state_flags |= (0x0001<<8); //--- If the cursor is inside the active area, set bit 9 "cursor inside the active area" if(CGCnvElement::CursorInsideActiveArea(m_mouse.CoordX(),m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<9); //--- otherwise, release the bit "cursor inside the active area" else this.m_mouse_state_flags &=0xFDFF; //--- If one of the mouse buttons is clicked, check the cursor location in the active area and //--- return the appropriate value of the pressed key (in the active area or the form area) if((this.m_mouse_state_flags & 0x0001)!=0 || (this.m_mouse_state_flags & 0x0002)!=0 || (this.m_mouse_state_flags & 0x0010)!=0) this.m_mouse_form_state=((this.m_mouse_state_flags & 0x0200)!=0 ? MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED : MOUSE_FORM_STATE_INSIDE_FORM_PRESSED); //--- otherwise, if not a single mouse button is pressed else { //--- if the mouse wheel is scrolled, return the appropriate wheel scrolling value (in the active area or the form area) if((this.m_mouse_state_flags & 0x0080)!=0) this.m_mouse_form_state=((this.m_mouse_state_flags & 0x0200)!=0 ? MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL : MOUSE_FORM_STATE_INSIDE_FORM_WHEEL); //--- otherwise, return the appropriate value of the unpressed key (in the active area or the form area) else this.m_mouse_form_state=((this.m_mouse_state_flags & 0x0200)!=0 ? MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED : MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED); } } //--- If the cursor is outside the form else { //--- return the appropriate button value in an inactive area this.m_mouse_form_state= ( ((this.m_mouse_state_flags & 0x0001)!=0 || (this.m_mouse_state_flags & 0x0002)!=0 || (this.m_mouse_state_flags & 0x0010)!=0) ? MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED ); } return this.m_mouse_form_state; } //+------------------------------------------------------------------+
Maus-Ereignisbehandlung:
//+------------------------------------------------------------------+ //| Mouse event handler | //+------------------------------------------------------------------+ void CForm::OnMouseEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { switch(id) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_EVENT_OUTSIDE_FORM_PRESSED : case MOUSE_EVENT_OUTSIDE_FORM_WHEEL : break; //--- The cursor is inside the form, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED : this.MouseInsideNotPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the form, any mouse button is clicked case MOUSE_EVENT_INSIDE_FORM_PRESSED : this.MouseInsidePressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the form, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_FORM_WHEEL : this.MouseInsideWhellHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED : this.MouseActiveAreaNotPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, any mouse button is clicked case MOUSE_EVENT_INSIDE_ACTIVE_AREA_PRESSED : this.MouseActiveAreaPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_ACTIVE_AREA_WHEEL : this.MouseActiveAreaWhellHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, left mouse button is released case MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED : this.MouseActiveAreaReleasedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_SCROLL_AREA_NOT_PRESSED : this.MouseScrollAreaNotPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area, any mouse button is clicked case MOUSE_EVENT_INSIDE_SCROLL_AREA_PRESSED : this.MouseScrollAreaPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_SCROLL_AREA_WHEEL : this.MouseScrollAreaWhellHandler(id,lparam,dparam,sparam); break; //--- MOUSE_EVENT_NO_EVENT default: break; } this.m_mouse_event_last=(ENUM_MOUSE_EVENT)id; } //+------------------------------------------------------------------+
Hier rufen wir für jedes Ereignis entsprechend der Mausereigniskennung die entsprechende Behandlungsmethode auf. Schließlich speichern wir das an die Methode übergebene Ereignis in der Variablen, die das letzte Mausereignis speichert. Wir behandeln also zunächst das Ereignis und setzen es dann als das zuletzt behandelte Ereignis. Alle hier aufgerufenen Methoden sind virtuell und sollten in den geerbten Klassen neu definiert werden.
Die virtuellen Handler der einzelnen Mausereignisse:
//+------------------------------------------------------------------+ //| 'The cursor is outside the form, | //| no mouse buttons are clicked' event handler | //+------------------------------------------------------------------+ void CForm::MouseOutsideNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is outside the form, | //| a mouse button is clicked (any) | //+------------------------------------------------------------------+ void CForm::MouseOutsidePressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is outside the form, | //| the mouse wheel is being scrolled | //+------------------------------------------------------------------+ void CForm::MouseOutsideWhellHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the form, | //| no mouse buttons are clicked' event handler | //+------------------------------------------------------------------+ void CForm::MouseInsideNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the form, | //| a mouse button is clicked (any) | //+------------------------------------------------------------------+ void CForm::MouseInsidePressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the form, | //| the mouse wheel is being scrolled | //+------------------------------------------------------------------+ void CForm::MouseInsideWhellHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| no mouse buttons are clicked' event handler | //+------------------------------------------------------------------+ void CForm::MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| a mouse button is clicked (any) | //+------------------------------------------------------------------+ void CForm::MouseActiveAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| the mouse wheel is being scrolled | //+------------------------------------------------------------------+ void CForm::MouseActiveAreaWhellHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| left mouse button released | //+------------------------------------------------------------------+ void CForm::MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the window scrolling area, | //| no mouse buttons are clicked' event handler | //+------------------------------------------------------------------+ void CForm::MouseScrollAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the window scrolling area, | //| a mouse button is clicked (any) | //+------------------------------------------------------------------+ void CForm::MouseScrollAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+ //| 'The cursor is inside the window scrolling area, | //| the mouse wheel is being scrolled | //+------------------------------------------------------------------+ void CForm::MouseScrollAreaWhellHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { return; } //+------------------------------------------------------------------+
Die Methoden bewirken nichts, da die gesamte Behandlung jedes Ereignisses für jedes abgeleiteten Objekt des Formularobjekts individuell ist. Falls erforderlich, sollte der Prozess in jedem geerbten Objekt neu definiert werden.
Der virtuelle Handler des letzten Mausereignisses:
//+------------------------------------------------------------------+ //| Last mouse event handler | //+------------------------------------------------------------------+ void CForm::OnMouseEventPostProcessing(void) { ENUM_MOUSE_FORM_STATE state=GetMouseState(); switch(state) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL : if(MouseEventLast()==MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED) { this.SetBackgroundColor(this.BackgroundColorInit(),false); this.SetBorderColor(this.BorderColorInit(),false); this.Redraw(true); this.m_mouse_event_last=ENUM_MOUSE_EVENT(state+MOUSE_EVENT_NO_EVENT); } break; //--- The cursor is inside the form, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED : break; //--- The cursor is inside the form, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_FORM_PRESSED : break; //--- The cursor is inside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_FORM_WHEEL : break; //--- The cursor is inside the active area, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED : break; //--- The cursor is inside the active area, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED : break; //--- The cursor is inside the active area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL : break; //--- The cursor is inside the active area, left mouse button is released case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED : break; //--- The cursor is within the window scrolling area, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_NOT_PRESSED : break; //--- The cursor is within the window scrolling area, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_PRESSED : break; //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_WHEEL : break; //--- MOUSE_EVENT_NO_EVENT default: break; } } //+------------------------------------------------------------------+
Die Methode ist ebenfalls virtuell. Falls erforderlich, sollte sie in den abgeleiteten Klassen neu definiert werden.
Wenn der Mausstatus für das Objekt als „der Cursor befindet sich außerhalb des Formulars“ definiert ist (der Status der Tasten und des Rads ist nicht wichtig), prüfen wir das letzte Mausereignis für das Objekt. Im Falle von „der Cursor befindet sich innerhalb des aktiven Bereichs und es werden keine Maustasten angeklickt“, wird der Cursor als vom Objekt entfernt betrachtet. Also, wir behandeln das entsprechende Ereignis - setzen die anfängliche Hintergrundfarbe, die anfängliche Objektrahmenfarbe, zeichnen das Objekt neu und schreiben das aktuelle Mausereignis in die Variable, die das letzte Mausereignis speichert.
In Anbetracht der Tatsache, dass sich alle konstanten Werte in der Enumeration ENUM_MOUSE_EVENT von den konstanten Werten in der Enumeration ENUM_MOUSE_FORM_STATE (sofern sie die gleiche Zusammensetzung und Reihenfolge haben) durch den konstanten Wert MOUSE_EVENT_NO_EVENT der Enumeration ENUM_MOUSE_EVENT unterscheiden, müssen wir den konstanten Wert MOUSE_EVENT_NO_EVENT zum Mausereigniswert addieren, der in der Zustandsvariablen ENUM_MOUSE_FORM_STATE empfangen wird, um den richtigen Wert zu erhalten.
Der Text auf dem Formular, z. B. der Schaltflächentext, kann ebenfalls seine Farbe ändern, wenn der Mauszeiger über dem Objekt schwebt oder es angeklickt wird, allerdings nicht in allen Fällen und nicht bei allen Objekten (nur wenn nötig). Die Methoden zur Behandlung des Textes von WinForms-Objekten befinden sich in der Klasse des Basis-WinForms-Objekts in \MQL5\Include\DoEasy\Objects\Graph\WForms\WinFormBase.mqh.
Im geschützten Abschnitt der Klasse deklarieren wir die Variable zum Speichern der anfänglichen Objekttextfarbe. Im öffentlichen Abschnitt deklarieren wir die Methoden, die die Liste der gebundenen Objekte nach Typ, die Anzahl der gebundenen Steuerelemente nach Typ und die Methode, die den Zeiger auf das gebundene Objekt zurückgibt, nach Typ.
Wir schreiben die Methoden zum Setzen und Abrufen zusätzlicher Objekttextfarben:
//+------------------------------------------------------------------+ //| Form object class | //+------------------------------------------------------------------+ class CWinFormBase : public CForm { protected: color m_fore_color_init; // Initial color of the control text private: //--- Return the font flags uint GetFontFlags(void); public: //--- Return by type the (1) list, (2) the number of bound controls, (3) the bound control by index in the list CArrayObj *GetListElementsByType(const ENUM_GRAPH_ELEMENT_TYPE type); int ElementsTotalByType(const ENUM_GRAPH_ELEMENT_TYPE type); CGCnvElement *GetElementByType(const ENUM_GRAPH_ELEMENT_TYPE type,const int index); //--- Clear the element filling it with color and opacity virtual void Erase(const color colour,const uchar opacity,const bool redraw=false); //--- Clear the element with a gradient fill virtual void Erase(color &colors[],const uchar opacity,const bool vgradient,const bool cycle,const bool redraw=false); //--- Clear the element completely virtual void Erase(const bool redraw=false); //--- Redraw the object virtual void Redraw(bool redraw); //--- Set the new size for the (1) current object and (2) the object specified by index virtual bool Resize(const int w,const int h,const bool redraw); virtual bool Resize(const int index,const int w,const int h,const bool redraw); //--- Constructors CWinFormBase(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h); CWinFormBase(const string name) : CForm(::ChartID(),0,name,0,0,0,0) { this.m_type=OBJECT_DE_TYPE_GWF_BASE; } //--- (1) Set and (2) return the default text color of all panel objects void SetForeColor(const color clr,const bool set_init_color) { this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR,clr); if(set_init_color) this.SetForeColorInit(clr); } color ForeColor(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR); } //--- (1) Set and (2) return the initial default text color of all panel objects void SetForeColorInit(const color clr) { this.m_fore_color_init=clr; } color ForeColorInit(void) const { return (color)this.m_fore_color_init; } //--- (1) Set and (2) return the default text color opacity of all panel objects void SetForeColorOpacity(const uchar value) { this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_OPACITY,value); } uchar ForeColorOpacity(void) const { return (uchar)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_OPACITY); } //--- (1) Set and (2) return the control text color when clicking the control void SetForeColorMouseDown(const color clr) { this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN,clr); } color ForeColorMouseDown(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN); } //--- (1) Set and (2) return the control text color when hovering the mouse over the control void SetForeColorMouseOver(const color clr) { this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER,clr); } color ForeColorMouseOver(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER); } //--- (1) Set and (2) return the element text virtual void SetText(const string text) { this.SetProperty(CANV_ELEMENT_PROP_TEXT,text); } string Text(void) const { return this.GetProperty(CANV_ELEMENT_PROP_TEXT); }
Im Klassenkonstruktor geben wir bei der Einstellung der Textfarbe an , dass die ursprüngliche Textfarbe gespeichert werden muss:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CWinFormBase::CWinFormBase(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h) : CForm(chart_id,subwindow,name,x,y,w,h) { //--- Set the graphical element and library object types as a base WinForms object CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_BASE); CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_BASE); this.m_type=OBJECT_DE_TYPE_GWF_BASE; //--- Initialize all variables this.SetText(""); this.SetForeColor(CLR_DEF_FORE_COLOR,true); this.SetForeColorOpacity(CLR_DEF_FORE_COLOR_OPACITY); this.SetFontBoldType(FW_TYPE_NORMAL); this.SetMarginAll(0); this.SetPaddingAll(0); this.SetBorderSizeAll(0); this.SetDockMode(CANV_ELEMENT_DOCK_MODE_NONE,false); this.SetBorderStyle(FRAME_STYLE_NONE); this.SetAutoSize(false,false); CForm::SetCoordXInit(x); CForm::SetCoordYInit(y); CForm::SetWidthInit(w); CForm::SetHeightInit(h); this.m_shadow=false; this.m_gradient_v=true; this.m_gradient_c=false; } //+------------------------------------------------------------------+
In der Rückgabe der Beschreibung des Elements Integer-Eigenschaft, fügen wir die Code-Blöcke für die Rückgabe Beschreibungen der neuen WinForms Objekt Eigenschaften:
property==CANV_ELEMENT_PROP_FORE_COLOR_OPACITY ? CMessage::Text(MSG_CANV_ELEMENT_PROP_FORE_COLOR_OPACITY)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN ? CMessage::Text(MSG_CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER ? CMessage::Text(MSG_CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_DOWN ? CMessage::Text(MSG_CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_DOWN)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_OVER ? CMessage::Text(MSG_CANV_ELEMENT_PROP_FORE_COLOR_TOGGLE_MOUSE_OVER)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_BACKGROUND_COLOR ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) :
...
property==CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_BOLD_TYPE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BOLD_TYPE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+FontBoldTypeDescription() ) :
...
property==CANV_ELEMENT_PROP_AUTOCHECK ? CMessage::Text(MSG_CANV_ELEMENT_PROP_AUTOCHECK)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)(bool)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_BUTTON_TOGGLE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BUTTON_TOGGLE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)(bool)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_BUTTON_STATE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BUTTON_STATE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)(bool)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_OPACITY ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_OPACITY)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_DOWN ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_DOWN)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_OVER ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_OVER)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_CHECK_FORE_COLOR ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_FORE_COLOR)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_CHECK_FORE_COLOR_OPACITY ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_FORE_COLOR_OPACITY)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_DOWN ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_DOWN)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_OVER ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_OVER)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_CHECK_FLAG_COLOR ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_OPACITY ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_OPACITY)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : "" ); } //+------------------------------------------------------------------+ //| Return the description of the control real property | //+------------------------------------------------------------------+
Die Methode gibt die Liste der gebundenen Steuerelemente nach Typ zurück:
//+------------------------------------------------------------------+ // Return the list of bound controls by type | //+------------------------------------------------------------------+ CArrayObj *CWinFormBase::GetListElementsByType(const ENUM_GRAPH_ELEMENT_TYPE type) { return CSelect::ByGraphCanvElementProperty(this.GetListElements(),CANV_ELEMENT_PROP_TYPE,type,EQUAL); } //+------------------------------------------------------------------+
Hier geben wir einfach die Liste der grafischen Elemente zurück, die aus der Liste der gebundenen Objekte nach dem angegebenen Typ ausgewählt wurden.
Die Methode, die (nach Typ) das gebundene Element nach Index in der Liste zurückgibt:
//+------------------------------------------------------------------+ //| Get (by type) the bound element by index in the list | //+------------------------------------------------------------------+ CGCnvElement *CWinFormBase::GetElementByType(const ENUM_GRAPH_ELEMENT_TYPE type,const int index) { CArrayObj *list=this.GetListElementsByType(type); return list.At(index); } //+------------------------------------------------------------------+
Hier erhalten wir die Liste von Objekten nach dem oben angegebenen Typ und geben den Zeiger auf das Objekt in der erhaltenen Liste nach dem angegebenen Index zurück. Wenn die Liste nicht erhalten wird oder die Größe der Liste nicht ausreicht, gibt die Methode NULL zurück.
Die Methode, die die Liste der gebundenen Elemente nach Typ zurückgibt:
//+------------------------------------------------------------------+ //| Get the list of bound elements by type | //+------------------------------------------------------------------+ int CWinFormBase::ElementsTotalByType(const ENUM_GRAPH_ELEMENT_TYPE type) { CArrayObj *list=this.GetListElementsByType(type); return(list!=NULL ? list.Total() : 0); } //+------------------------------------------------------------------+
Wir ermitteln die Liste der gebundenen Objekte nach dem angegebenen Typ und geben die Anzahl der Zeiger auf die Objekte in der Liste zurück. Gelingt es nicht, die Liste zu erhalten, gibt die Methode Null zurück.
In der Objektklasse des WinForms-Basiscontainers in \MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Container.mqh benennen wir die Methoden zur Einstellung der Rahmenbreite um. Früher habe ich „Frame“ (Rahmen) im Namen verwendet. Jetzt werde ich „Border“ (Rand) verwenden:
//--- Set the width of the form frame (1) to the left, (2) at the top, (3) to the right, (4) at the bottom and (5) on all sides of the control virtual void SetBorderSizeLeft(const uint value) { CForm::SetBorderSizeLeft(value); if(this.PaddingLeft()<this.BorderSizeLeft()) this.SetPaddingLeft(this.BorderSizeLeft()); } virtual void SetBorderSizeTop(const uint value) { CForm::SetBorderSizeTop(value); if(this.PaddingTop()<this.BorderSizeTop()) this.SetPaddingTop(this.BorderSizeTop()); } virtual void SetBorderSizeRight(const uint value) { CForm::SetBorderSizeRight(value); if(this.PaddingRight()<this.BorderSizeRight()) this.SetPaddingRight(this.BorderSizeRight()); } virtual void SetBorderSizeBottom(const uint value) { CForm::SetBorderSizeBottom(value); if(this.PaddingBottom()<this.BorderSizeBottom()) this.SetPaddingBottom(this.BorderSizeBottom()); }
Beachten Sie, dass sich die Methode nun selbst rekursiv aufruft, während diese Methoden zuvor unterschiedliche Namen hatten und der Aufruf der Methode der übergeordneten Klasse zum Einstellen der Rahmenbreite keine Probleme verursachte. Deshalb geben wir hier explizit den Kontext an, aus dem die notwendige gleichnamige Methode der Elternklasse aufgerufen wird.
In den Klassenkonstruktoren geben wir beim Speichern der Textfarbe die Notwendigkeit an, die ursprüngliche Farbe der Elementbeschriftungen zu speichern:
//--- Constructors CContainer(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h); CContainer(const string name) : CWinFormBase(::ChartID(),0,name,0,0,0,0) { CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_CONTAINER); CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_CONTAINER); this.m_type=OBJECT_DE_TYPE_GWF_CONTAINER; this.SetForeColor(CLR_DEF_FORE_COLOR,true); this.SetFontBoldType(FW_TYPE_NORMAL); this.SetMarginAll(3); this.SetPaddingAll(0); this.SetDockMode(CANV_ELEMENT_DOCK_MODE_NONE,false); this.SetBorderStyle(FRAME_STYLE_NONE); this.SetAutoScroll(false,false); this.SetAutoScrollMarginAll(0); this.SetAutoSize(false,false); this.SetAutoSizeMode(CANV_ELEMENT_AUTO_SIZE_MODE_GROW,false); this.Initialize(); } //--- Destructor ~CContainer(); }; //+------------------------------------------------------------------+ //| Constructor indicating the chart and subwindow ID | //+------------------------------------------------------------------+ CContainer::CContainer(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h) : CWinFormBase(chart_id,subwindow,name,x,y,w,h) { CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_CONTAINER); CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_CONTAINER); this.m_type=OBJECT_DE_TYPE_GWF_CONTAINER; this.SetForeColor(CLR_DEF_FORE_COLOR,true); this.SetFontBoldType(FW_TYPE_NORMAL); this.SetMarginAll(3); this.SetPaddingAll(0); this.SetDockMode(CANV_ELEMENT_DOCK_MODE_NONE,false); this.SetBorderStyle(FRAME_STYLE_NONE); this.SetAutoScroll(false,false); this.SetAutoScrollMarginAll(0); this.SetAutoSize(false,false); this.SetAutoSizeMode(CANV_ELEMENT_AUTO_SIZE_MODE_GROW,false); this.Initialize(); this.SetCoordXInit(x); this.SetCoordYInit(y); this.SetWidthInit(w); this.SetHeightInit(h); } //+------------------------------------------------------------------+
In der Methode zum Erstellen eines neuen gebundenen Elements geben wir die Notwendigkeit an, dass die Originalfarbe überall gespeichert werden muss:
//+------------------------------------------------------------------+ //| Create a new attached element | //+------------------------------------------------------------------+ bool CContainer::CreateNewElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool activity, const bool redraw) { //--- If the object type is less than the base WinForms object if(element_type<GRAPH_ELEMENT_TYPE_WF_BASE) { //--- report the error and return 'false' CMessage::ToLog(DFUN,MSG_PANEL_OBJECT_ERR_OBJ_MUST_BE_WFBASE); return false; } //--- If failed to create a new graphical element, return 'false' CWinFormBase *obj=CForm::CreateAndAddNewElement(element_type,x,y,w,h,colour,opacity,activity); if(obj==NULL) return false; //--- Set the text color of the created object as that of the base panel obj.SetForeColor(this.ForeColor(),true); //--- Depending on the created object type, switch(obj.TypeGraphElement()) { //--- For the Container, Panel and GroupBox WinForms objects case GRAPH_ELEMENT_TYPE_WF_CONTAINER : case GRAPH_ELEMENT_TYPE_WF_PANEL : case GRAPH_ELEMENT_TYPE_WF_GROUPBOX : //--- set the frame color equal to the background color obj.SetBorderColor(obj.BackgroundColor(),true); break; //--- For the Text Label, CheckBox and RadioButton WinForms objects case GRAPH_ELEMENT_TYPE_WF_LABEL : case GRAPH_ELEMENT_TYPE_WF_CHECKBOX : case GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON : //--- set the object text color depending on the one passed to the method: //--- either the container text color, or the one passed to the method. //--- The frame color is set equal to the text color obj.SetForeColor(colour==clrNONE ? this.ForeColor() : colour,true); obj.SetBorderColor(obj.ForeColor(),true); break; //--- For the Button WinForms object case GRAPH_ELEMENT_TYPE_WF_BUTTON : //--- set the object text color as a container text color depending on the one passed to the method: //--- set the background color depending on the one passed to the method: //--- either the default standard control background color, or the one passed to the method. //--- The frame color is set equal to the text color obj.SetForeColor(this.ForeColor(),true); obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_STD_BACK_COLOR : colour,true); obj.SetBorderColor(obj.ForeColor(),true); obj.SetBorderStyle(FRAME_STYLE_SIMPLE); break; default: break; } //--- If the panel has auto resize enabled and features bound objects, call the resize method if(this.AutoSize() && this.ElementsTotal()>0) this.AutoSizeProcess(redraw); //--- Redraw the panel and all added objects, and return 'true' this.Redraw(redraw); return true; } //+------------------------------------------------------------------+
In der Datei \MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\GroupBox.mqh der WinForms-Objektklasse GroupBox, und zwar in ihrer Initialisierungsmethode Initialize(), legen wir die Notwendigkeit fest, die Ausgangsfarben zu speichern , wenn wir die Standardfarben einstellen:
//--- Create an animation object and add it to the list for storing such objects this.m_animations=new CAnimations(CGCnvElement::GetObject()); this.m_list_tmp.Add(this.m_animations); //--- Set a transparent background for the object background and the default color for the frame this.SetBackgroundColor(CLR_CANV_NULL,true); this.SetOpacity(0); this.SetBorderColor(CLR_DEF_FRAME_GBOX_COLOR,true); //--- Set the default color and text opacity, as well as the absence of the object frame this.SetForeColor(CLR_DEF_FORE_COLOR,true); this.SetForeColorOpacity(CLR_DEF_FORE_COLOR_OPACITY); this.SetBorderStyle(FRAME_STYLE_SIMPLE); //--- Set the default text parameters
In der Datei \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\CommonBase.mqh des Standard-WinForms-Basisobjekts, und zwar in seiner Initialisierungsmethode Initialize(), legen wir die Notwendigkeit fest, die Ausgangsfarben zu speichern , wenn wir die Standardfarben einstellen:
//--- Create an animation object and add it to the list for storing such objects this.m_animations=new CAnimations(CGCnvElement::GetObject()); this.m_list_tmp.Add(this.m_animations); //--- Set the transparent color for the object background this.SetBackgroundColor(CLR_CANV_NULL,true); this.SetOpacity(0); //--- Set the default color and text opacity, as well as the absence of the object frame this.SetForeColor(CLR_DEF_FORE_COLOR,true); this.SetForeColorOpacity(CLR_DEF_FORE_COLOR_OPACITY); this.SetBorderStyle(FRAME_STYLE_NONE); //--- Set the default text parameters
Das WinForms-Objekt CheckBox besteht aus einem Feld mit einem Ankreuzfeld und einem Text. Wenn man den Mauszeiger bewegt und auf die Schaltfläche klickt, ändert sich die Farbe des Feldes, seines Rahmens und des Kontrollkästchens. Daher müssen wir die Variablen für alle Komponenten erstellen, um ihre Ausgangsfarben zu speichern, sowie die Methoden, um die Farben entsprechend einem Mausereignis zu setzen.
Im geschützten Abschnitt der Klasse in \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\CheckBox.mqh deklarieren wir die Variablen für die Speicherung der Ausgangsfarben und die virtuellen Methoden zur Behandlung von Mausereignissen:
//+------------------------------------------------------------------+ //| CheckBox object class of the WForms controls | //+------------------------------------------------------------------+ class CCheckBox : public CLabel { private: //--- Set X and Y checkbox coordinates void SetCheckFlagCoords(int &x,int &y); //--- Set the corrected text coordinates depending on the text alignment and checkbox void SetCorrectTextCoords(void); protected: int m_text_x; // Text X coordinate int m_text_y; // Text Y coordinate int m_check_x; // Checkbox X coordinate int m_check_y; // Checkbox Y coordinate int m_check_w; // Checkbox width int m_check_h; // Checkbox height color m_check_back_color_init; // Initial color of the checkbox background color m_check_border_color_init; // Initial color of the checkbox background frame color m_check_flag_color_init; // Initial color of the checkbox //--- Set the element width and height automatically virtual bool AutoSetWH(void); //--- Displays the checkbox for the specified state virtual void ShowControlFlag(const ENUM_CANV_ELEMENT_CHEK_STATE state); //--- (1) Set and (2) return the checkbox size on the element void SetCheckWidth(const int width) { this.m_check_w=(width<5 ? 5 : width); } void SetCheckHeight(const int height) { this.m_check_h=(height<5 ? 5 : height); } int CheckWidth(void) const { return this.m_check_w; } int CheckHeight(void) const { return this.m_check_h; } //--- 'The cursor is inside the active area, the mouse buttons are not clicked' event handler virtual void MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, a mouse button is clicked (any)' event handler virtual void MouseActiveAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, the left mouse button is clicked' event handler virtual void MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); public:
Wir ändern die Methoden zur Einstellung der Hintergrundfarbe des Ankreuzfeldes, des Feldrahmens und des Ankreuzfeldes selbst, sodass es möglich ist, die ursprüngliche Feldfarbe durch den Flag-Wert beizubehalten. Fügen wir die Methoden zum Setzen und Abrufen der Ausgangsfarben hinzu und deklarieren die Handhabung des letzten Mausereignisses:
//--- (1) Set and (2) return the flag of the checkbox auto change when it is selected void SetAutoCheck(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_AUTOCHECK,flag); } bool AutoCheck(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_AUTOCHECK); } //--- (1) Set and (2) return the control verification checkbox background color void SetCheckBackgroundColor(const color clr,const bool set_init_color) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR,clr); if(set_init_color) this.SetCheckBackgroundColorInit(clr); } color CheckBackgroundColor(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR); } //--- (1) Set and (2) return the control verification checkbox background color opacity void SetCheckBackgroundColorOpacity(const uchar value) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_OPACITY,value); } uchar CheckBackgroundColorOpacity(void) const { return (uchar)this.GetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_OPACITY); } //--- (1) Set and (2) return the color of control checkbox background when clicking the control void SetCheckBackgroundColorMouseDown(const color clr) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_DOWN,clr); } color CheckBackgroundColorMouseDown(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_DOWN);} //--- (1) Set and (2) return the color of control checkbox background when hovering the mouse over the control void SetCheckBackgroundColorMouseOver(const color clr) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_OVER,clr); } color CheckBackgroundColorMouseOver(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_OVER);} //--- (1) Set and (2) return the initial color of the control verification checkbox background void SetCheckBackgroundColorInit(const color clr) { this.m_check_back_color_init=clr; } color CheckBackgroundColorInit(void) const { return (color)this.m_check_back_color_init; } //--- (1) Set and (2) return the control checkbox frame color void SetCheckBorderColor(const color clr,const bool set_init_color) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR,clr); if(set_init_color) this.SetCheckBorderColorInit(clr); } color CheckBorderColor(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR); } //--- (1) Set and (2) return the control checkbox frame color opacity void SetCheckBorderColorOpacity(const uchar value) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_OPACITY,value); } uchar CheckBorderColorOpacity(void) const { return (uchar)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_OPACITY); } //--- (1) Set and (2) return the color of control checkbox frame color when clicking on the control void SetCheckBorderColorMouseDown(const color clr) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_DOWN,clr); } color CheckBorderColorMouseDown(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_DOWN); } //--- (1) Set and (2) return the color of the control checkbox frame color when hovering the mouse over the control void SetCheckBorderColorMouseOver(const color clr) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_OVER,clr); } color CheckBorderColorMouseOver(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_OVER); } //--- (1) Set and (2) return the initial color of the control verification checkbox frame void SetCheckBorderColorInit(const color clr) { this.m_check_border_color_init=clr; } color CheckBorderColorInit(void) const { return (color)this.m_check_border_color_init; } //--- (1) Set and (2) return the control verification checkbox color void SetCheckFlagColor(const color clr,const bool set_init_color) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR,clr); if(set_init_color) this.SetCheckFlagColorInit(clr); } color CheckFlagColor(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR); } //--- (1) Set and (2) return the control verification checkbox color opacity void SetCheckFlagColorOpacity(const uchar value) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_OPACITY,value); } uchar CheckFlagColorOpacity(void) const { return (uchar)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_OPACITY); } //--- (1) Set and (2) return the color of control checkbox when clicking on the control void SetCheckFlagColorMouseDown(const color clr) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN,clr); } color CheckFlagColorMouseDown(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN); } //--- (1) Set and (2) return the color of the control checkbox when hovering the mouse over the control void SetCheckFlagColorMouseOver(const color clr) { this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER,clr); } color CheckFlagColorMouseOver(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER); } //--- (1) Set and (2) return the initial color of the control verification checkbox void SetCheckFlagColorInit(const color clr) { this.m_check_flag_color_init=clr; } color CheckFlagColorInit(void) const { return (color)this.m_check_flag_color_init; } //--- Last mouse event handler virtual void OnMouseEventPostProcessing(void); //--- Redraw the object virtual void Redraw(bool redraw); //--- Constructor
Im Klassenkonstruktor legen wir die Standardfarben für verschiedene Ereignisse und Mauszustände fest:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CCheckBox::CCheckBox(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h) : CLabel(chart_id,subwindow,name,x,y,w,h) { CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_CHECKBOX); CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_CHECKBOX); this.m_type=OBJECT_DE_TYPE_GWF_COMMON; this.SetCoordX(x); this.SetCoordY(y); this.SetCheckWidth(DEF_CHECK_SIZE); this.SetCheckHeight(DEF_CHECK_SIZE); this.SetWidth(w); this.SetHeight(h); this.Initialize(); this.SetForeColorMouseDown(CLR_DEF_FORE_COLOR_MOUSE_DOWN); this.SetForeColorMouseOver(CLR_DEF_FORE_COLOR_MOUSE_OVER); this.SetCheckBackgroundColor(CLR_DEF_CHECK_BACK_COLOR,true); this.SetCheckBackgroundColorMouseDown(CLR_DEF_CHECK_BACK_MOUSE_DOWN); this.SetCheckBackgroundColorMouseOver(CLR_DEF_CHECK_BACK_MOUSE_OVER); this.SetCheckBorderColor(CLR_DEF_CHECK_BORDER_COLOR,true); this.SetCheckBorderColorMouseDown(CLR_DEF_CHECK_BORDER_MOUSE_DOWN); this.SetCheckBorderColorMouseOver(CLR_DEF_CHECK_BORDER_MOUSE_OVER); this.SetCheckFlagColor(CLR_DEF_CHECK_FLAG_COLOR,true); this.SetCheckFlagColorMouseDown(CLR_DEF_CHECK_FLAG_MOUSE_DOWN); this.SetCheckFlagColorMouseOver(CLR_DEF_CHECK_FLAG_MOUSE_OVER); this.SetWidthInit(this.Width()); this.SetHeightInit(this.Height()); this.SetCoordXInit(x); this.SetCoordYInit(y); this.SetTextAlign(ANCHOR_LEFT); this.m_text_x=0; this.m_text_y=0; this.m_check_x=0; this.m_check_y=0; this.Redraw(false); } //+------------------------------------------------------------------+
Nicht alle Maus-Ereignishandler müssen hier neu definiert werden. Betrachten wir nun die umdefinierten Methoden der übergeordneten Klasse.
Der Cursor befindet sich innerhalb des aktiven Bereichs, die Maustasten sind nicht angeklickt:
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| no mouse buttons are clicked' event handler | //+------------------------------------------------------------------+ void CCheckBox::MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { this.SetCheckBackgroundColor(this.CheckBackgroundColorMouseOver(),false); this.SetCheckBorderColor(this.CheckBorderColorMouseOver(),false); this.SetCheckFlagColor(this.CheckFlagColorMouseOver(),false); this.Redraw(true); } //+------------------------------------------------------------------+
Wenn sich der Mauszeiger über einem aktiven Bereich des Objekts befindet, werden die neuen Hintergrundfarben (für den aktuellen Maus- und Objektstatus) für das Kontrollkästchen, seinen Rahmen und das Flag selbst festgelegt und das Objekt neu gezeichnet.
Der Cursor befindet sich innerhalb des aktiven Bereichs, eine beliebige Maustaste wurde angeklickt:
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| a mouse button is clicked (any) | //+------------------------------------------------------------------+ void CCheckBox::MouseActiveAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { this.SetCheckBackgroundColor(this.CheckBackgroundColorMouseDown(),false); this.SetCheckBorderColor(this.CheckBorderColorMouseDown(),false); this.SetCheckFlagColor(this.CheckFlagColorMouseDown(),false); this.Redraw(false); } //+------------------------------------------------------------------+
Wenn sich der Mauszeiger über einem aktiven Bereich des Objekts befindet, werden die neuen Hintergrundfarben (für den aktuellen Maus- und Objektstatus) für das Kontrollkästchen, seinen Rahmen und das Flag selbst festgelegt und das Objekt neu gezeichnet.
Der Cursor befindet sich im aktiven Bereich, die linke Maustaste wurde geklickt:
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| left mouse button released | //+------------------------------------------------------------------+ void CCheckBox::MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { //--- The mouse button released outside the element means refusal to interact with the element if(lparam<this.CoordX() || lparam>this.RightEdge() || dparam<this.CoordY() || dparam>this.BottomEdge()) { this.SetCheckBackgroundColor(this.BackgroundColorInit(),false); this.SetCheckBorderColor(this.CheckBorderColorInit(),false); this.SetCheckFlagColor(this.CheckFlagColorInit(),false); //--- Send a test entry to the journal Print(DFUN_ERR_LINE,TextByLanguage("Отмена","Cancel")); } //--- The mouse button released within the element means a click on the control else { this.SetCheckBackgroundColor(this.CheckBackgroundColorMouseOver(),false); this.SetCheckBorderColor(this.CheckBorderColorMouseOver(),false); this.SetCheckFlagColor(this.CheckFlagColorInit(),false); this.SetChecked(!this.Checked()); //--- Send a test entry to the journal Print(DFUN_ERR_LINE,TextByLanguage("Щелчок","Click")); } this.Redraw(false); } //+------------------------------------------------------------------+
Hier werden zwei Zustände behandelt:
wenn die Maustaste losgelassen wird und sich der Cursor außerhalb des aktiven Bereichs des Objekts befindet, und
wenn die Maustaste losgelassen wird und sich der Cursor innerhalb des aktiven Bereich des Objekts befindet.
Befindet sich der Cursor außerhalb des Objekts, bedeutet dies, dass ein Nutzer die Schaltfläche angeklickt, den Cursor wegbewegt und die Schaltfläche losgelassen hat. In diesem Fall sollte das Kontrollkästchen seinen Status nicht ändern, da dies eine Verweigerung der Interaktion mit dem Objekt bedeutet. Legen wir also die anfänglichen Flags und Feldfarben für das Objekt fest.
Befindet sich der Cursor innerhalb des Objekts, hat ein Nutzer die Schaltfläche angeklickt und losgelassen. Dadurch sollte sich der Status des Kontrollkästchens ändern. Ändern wir also die Farbe des Feldes, des Rahmens und des Kontrollkästchens auf die Farbe, die für das Objekt eingestellt ist, wenn der Mauszeiger über dem aktiven Bereich schwebt (auch wenn die Maustaste losgelassen wurde, blieb der Mauszeiger über dem Objekt, so dass die Farbe dieselbe sein sollte wie beim Schweben über dem Objekt), und setzen wir den entgegengesetzten Status des Kontrollkästchens.
Schließlich zeichnen wir das Objekt neu. Wir senden einen Testeintrag zum Status des Ankreuzfeldes für jede der behandelten Situationen. Später, wenn das Kontrollkästchen ausgelöst wird, ersetzen wir das Senden des Eintrags an das Journal durch das Senden des Ereignisses für die weitere Bearbeitung.
Der virtuelle Behandlung des letzten Mausereignisses:
//+------------------------------------------------------------------+ //| Last mouse event handler | //+------------------------------------------------------------------+ void CCheckBox::OnMouseEventPostProcessing(void) { ENUM_MOUSE_FORM_STATE state=GetMouseState(); switch(state) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL : if(MouseEventLast()==MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED) { this.SetBackgroundColor(this.BackgroundColorInit(),false); this.SetBorderColor(this.BorderColorInit(),false); this.SetCheckBackgroundColor(this.CheckBackgroundColorInit(),false); this.SetCheckBorderColor(this.CheckBorderColorInit(),false); this.SetCheckFlagColor(this.CheckFlagColorInit(),false); this.m_mouse_event_last=ENUM_MOUSE_EVENT(state+MOUSE_EVENT_NO_EVENT); this.Redraw(false); } break; //--- The cursor is inside the form, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED : break; //--- The cursor is inside the form, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_FORM_PRESSED : break; //--- The cursor is inside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_FORM_WHEEL : break; //--- The cursor is inside the active area, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED : break; //--- The cursor is inside the active area, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED : break; //--- The cursor is inside the active area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL : break; //--- The cursor is inside the active area, left mouse button is released case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED : break; //--- The cursor is within the window scrolling area, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_NOT_PRESSED : break; //--- The cursor is within the window scrolling area, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_PRESSED : break; //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_WHEEL : break; //--- MOUSE_EVENT_NO_EVENT default: break; } } //+------------------------------------------------------------------+
Hier wird nur die Situation behandelt, wenn sich der Mauszeiger außerhalb des Objekts befindet, während der vorherige Status lautete: „Der Mauszeiger befindet sich innerhalb des aktiven Bereichs, die Maustasten sind nicht angeklickt“. In diesem Fall setzen wir die Anfangswerte für alle veränderbaren Objekteigenschaften und ordnen den aktuellen Status dem letzten Mausereignis zu.
Die RadioButton-Klasse des WinForms-Objekts in \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\RadioButton.mqh wird von der neu modifizierten CheckBox-Objektklasse geerbt, sodass weniger Änderungen erforderlich sind.
Bei diesem Objekt ist das Flag immer aktiv. Seine Deaktivierung hängt von einem anderen ähnlichen Objekt ab, mit dem es zusammenarbeitet. Wenn das Kontrollkästchen in einem Objekt gesetzt ist, ist es in einem anderen Objekt nicht markiert und umgekehrt. Hier müssen wir nur eine einzige virtuelle Methode der übergeordneten Klasse umdefinieren:
//+------------------------------------------------------------------+ //| CheckBox object class of the WForms controls | //+------------------------------------------------------------------+ class CRadioButton : public CCheckBox { private: protected: //--- Displays the checkbox for the specified state virtual void ShowControlFlag(const ENUM_CANV_ELEMENT_CHEK_STATE state); //--- 'The cursor is inside the active area, the left mouse button is clicked' event handler virtual void MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); public:
Der Cursor befindet sich im aktiven Bereich, die linke Maustaste wurde geklickt:
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| left mouse button released | //+------------------------------------------------------------------+ void CRadioButton::MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { //--- The mouse button released outside the element means refusal to interact with the element if(lparam<this.CoordX() || lparam>this.RightEdge() || dparam<this.CoordY() || dparam>this.BottomEdge()) { this.SetCheckBackgroundColor(this.BackgroundColorInit(),false); this.SetCheckBorderColor(this.CheckBorderColorInit(),false); this.SetCheckFlagColor(this.CheckFlagColorInit(),false); Print(DFUN_ERR_LINE,TextByLanguage("Отмена","Cancel")); } //--- The mouse button released within the element means a click on the control else { this.SetCheckBackgroundColor(this.CheckBackgroundColorMouseOver(),false); this.SetCheckBorderColor(this.CheckBorderColorMouseOver(),false); this.SetCheckFlagColor(this.CheckFlagColorInit(),false); Print(DFUN_ERR_LINE,TextByLanguage("Щелчок","Click")); } this.Redraw(false); } //+------------------------------------------------------------------+
Die Methode ähnelt der für die Objektklasse CheckBox, nur dass wir hier das Flag nicht auf den entgegengesetzten Wert in dem Block setzen müssen , der das Loslassen der Schaltfläche im aktiven Bereich des Objekts behandelt.
Die Schaltfläche WinForms-Objekt Die Schaltfläche kann auf zwei Arten verwendet werden:
- Wenn man darauf klickt, wird die Schaltfläche ausgelöst und kehrt in ihren Ausgangszustand zurück,
- Beim Anklicken wird die Schaltfläche ausgelöst und bleibt gedrückt, beim zweiten Anklicken wechselt ihr Status in den entgegengesetzten (der Auslöser ist Toggle-Button).
Wir brauchen also das Flag, die definiert, um welche Schaltfläche es sich handelt, und das Flag, die die Auslöseschaltfläche definiert (gedrückt/freigegeben), und natürlich einen weiteren Satz, um die Farben der Schaltfläche zu bestimmen, wenn sie angeklickt wird (Hintergrundfarbe, Farbe, wenn der Mauszeiger in der Schwebe ist und wenn die Schaltfläche angeklickt wird).
In \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\Button.mqh, und zwar im privaten Abschnitt der Klasse, deklarieren wir die Arrays zum Speichern der Farben der neuen Schaltflächenzustände:
//+------------------------------------------------------------------+ //| Label object class of WForms controls | //+------------------------------------------------------------------+ class CButton : public CLabel { private: int m_text_x; // Text X coordinate int m_text_y; // Text Y coordinate color m_array_colors_bg_tgl[]; // Array of element background colors for the 'enabled' state color m_array_colors_bg_tgl_dwn[]; // Array of control background colors for the 'enabled' state when clicking on the control color m_array_colors_bg_tgl_ovr[]; // Array of control background colors for the 'enabled' state when hovering the mouse over the control color m_array_colors_bg_tgl_init[]; // Array of initial element background colors for the 'enabled' state protected:
Im Abschnitt für die geschützte Klasse deklarieren wir die Behandlung für die Mausereignisse der übergeordneten Klasse, die hier neu definiert werden sollen:
protected: //--- Set the element width and height automatically virtual bool AutoSetWH(void); //--- 'The cursor is inside the active area, the mouse buttons are not clicked' event handler virtual void MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, a mouse button is clicked (any)' event handler virtual void MouseActiveAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, the left mouse button is clicked' event handler virtual void MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); public:
In den öffentlichen Abschnitt der Klasse schreiben wir die Methoden zum Setzen und Zurückgeben des Flag der Auslöseschaltfläche, die Methoden zum Setzen und Zurückgeben des Status der Auslöseschaltfläche, die Methoden zur Behandlung neuer Statusfarben der Schaltfläche und deklarieren die Methode zur Behandlung des letzten Mausereignisses:
public: //--- Redraw the object virtual void Redraw(bool redraw); //--- (1) Set and (2) return the mode of the element auto resizing depending on the content void SetAutoSizeMode(const ENUM_CANV_ELEMENT_AUTO_SIZE_MODE mode,const bool redraw) { ENUM_CANV_ELEMENT_AUTO_SIZE_MODE prev=this.AutoSizeMode(); if(prev==mode) return; this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE_MODE,mode); } ENUM_CANV_ELEMENT_AUTO_SIZE_MODE AutoSizeMode(void) const { return (ENUM_CANV_ELEMENT_AUTO_SIZE_MODE)this.GetProperty(CANV_ELEMENT_PROP_AUTOSIZE_MODE); } //--- (1) Set and (2) return the control Toggle flag void SetToggleFlag(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_BUTTON_TOGGLE,flag); if(this.Toggle()) this.SetColorsToggleON(CLR_DEF_CONTROL_STD_BACK_COLOR_ON,CLR_DEF_CONTROL_STD_BACK_DOWN_ON,CLR_DEF_CONTROL_STD_BACK_OVER_ON,true); } bool Toggle(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_TOGGLE); } //--- (1) Set and (2) return the Toggle control status void SetState(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_BUTTON_STATE,flag); } bool State(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_STATE); } //--- (1,2) Set and (3) return the main background color for the 'enabled' status void SetBackgroundColorToggleON(const color colour,const bool set_init_color) { this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE,colour); color arr[1]; arr[0]=colour; this.CopyArraysColors(this.m_array_colors_bg_tgl,arr,DFUN); if(set_init_color) this.CopyArraysColors(this.m_array_colors_bg_tgl_init,arr,DFUN); } void SetBackgroundColorsToggleON(color &colors[],const bool set_init_colors) { this.CopyArraysColors(this.m_array_colors_bg_tgl,colors,DFUN); this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE,this.m_array_colors_bg_tgl[0]); if(set_init_colors) this.CopyArraysColors(this.m_array_colors_bg_tgl_init,colors,DFUN); } color BackgroundColorToggleON(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE); } //--- (1,2) Set and (3) return the background color when clicking on the control for the 'enabled' status void SetBackgroundColorToggleONMouseDown(const color colour) { this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN,colour); color arr[1]; arr[0]=colour; this.CopyArraysColors(this.m_array_colors_bg_tgl_dwn,arr,DFUN); } void SetBackgroundColorsToggleONMouseDown(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg_tgl_dwn,colors,DFUN); this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN,this.m_array_colors_bg_dwn[0]); } color BackgroundColorToggleONMouseDown(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_DOWN); } //--- (1,2) Set and (3) return the background color when hovering the mouse over the control for the 'enabled' status void SetBackgroundColorToggleONMouseOver(const color colour) { this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER,colour); color arr[1]; arr[0]=colour; this.CopyArraysColors(this.m_array_colors_bg_tgl_ovr,arr,DFUN); } void SetBackgroundColorsToggleONMouseOver(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg_tgl_ovr,colors,DFUN); this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER,this.m_array_colors_bg_ovr[0]); } color BackgroundColorToggleONMouseOver(void) const { return (color)this.GetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_TOGGLE_MOUSE_OVER); } //--- Return the initial main background color for the 'enabled' status color BackgroundColorToggleONInit(void) const { return this.m_array_colors_bg_tgl_init[0]; } //--- Set the colors for the 'enabled' status void SetColorsToggleON(const color back,const color back_down,const color back_over,const bool set_init_color); //--- Last mouse event handler virtual void OnMouseEventPostProcessing(void); //--- Constructor CButton(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h); }; //+------------------------------------------------------------------+
Die Methoden sind identisch mit den Methoden zum Setzen und Zurückgeben der Objektfarben anderer Klassen, die ich oben besprochen habe.
Im Klassenkonstruktor legen wir die Standardfarben für den Objekthintergrund, den Opazitätswert des Objekts und die Hintergrundfarben beim Hoovern und Klicken auf die Schaltfläche fest. Wir setzen das Flag für die reguläre Schaltfläche (nicht die Umschalttaste) und den Status der Umschalttaste auf false:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CButton::CButton(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h) : CLabel(chart_id,subwindow,name,x,y,w,h) { CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_BUTTON); CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_BUTTON); this.m_type=OBJECT_DE_TYPE_GWF_COMMON; this.SetCoordX(x); this.SetCoordY(y); this.SetWidth(w); this.SetHeight(h); this.Initialize(); this.SetBackgroundColor(CLR_DEF_CONTROL_STD_BACK_COLOR,true); this.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_STD_MOUSE_DOWN); this.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_STD_MOUSE_OVER); this.SetOpacity(CLR_DEF_CONTROL_STD_OPACITY); this.SetTextAlign(ANCHOR_CENTER); this.SetMarginAll(3); this.SetWidthInit(this.Width()); this.SetHeightInit(this.Height()); this.SetCoordXInit(x); this.SetCoordYInit(y); this.SetToggleFlag(false); this.SetState(false); this.Redraw(false); } //+------------------------------------------------------------------+
Neudefinition der Maus-Ereignisbehandlung.
Der Cursor befindet sich innerhalb des aktiven Bereichs, die Maustasten sind nicht angeklickt:
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| no mouse buttons are clicked' event handler | //+------------------------------------------------------------------+ void CButton::MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { //--- If this is a simple button, set the color for the "The cursor is over the active area, the mouse button is not clicked" status if(!this.Toggle()) this.SetBackgroundColor(this.BackgroundColorMouseOver(),false); //--- If this is the toggle button, set the color for the status depending on whether the button is pressed or not else this.SetBackgroundColor(this.State() ? this.BackgroundColorToggleONMouseOver() : this.BackgroundColorMouseOver(),false); //--- Set the frame color for the status this.SetBorderColor(this.BorderColorMouseOver(),false); //--- Redraw the object this.Redraw(false); } //+------------------------------------------------------------------+
Der Cursor befindet sich innerhalb des aktiven Bereichs, eine beliebige Maustaste wurde angeklickt:
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| a mouse button is clicked (any) | //+------------------------------------------------------------------+ void CButton::MouseActiveAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { //--- If this is a simple button, set the color for the "The cursor is over the active area, the mouse button is clicked" status if(!this.Toggle()) this.SetBackgroundColor(this.BackgroundColorMouseDown(),false); //--- If this is the toggle button, set the color for the status depending on whether the button is pressed or not else this.SetBackgroundColor(this.State() ? this.BackgroundColorToggleONMouseDown() : this.BackgroundColorMouseDown(),false); //--- Set the frame color for the status this.SetBorderColor(this.BorderColorMouseDown(),false); //--- Redraw the object this.Redraw(false); } //+------------------------------------------------------------------+
Der Cursor befindet sich im aktiven Bereich, die linke Maustaste wurde geklickt:
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| left mouse button released | //+------------------------------------------------------------------+ void CButton::MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { //--- The mouse button released outside the element means refusal to interact with the element if(lparam<this.CoordX() || lparam>this.RightEdge() || dparam<this.CoordY() || dparam>this.BottomEdge()) { //--- If this is a simple button, set the initial background color if(!this.Toggle()) this.SetBackgroundColor(this.BackgroundColorInit(),false); //--- If this is the toggle button, set the initial color depending on whether the button is pressed or not else this.SetBackgroundColor(!this.State() ? this.BackgroundColorInit() : this.BackgroundColorToggleONInit(),false); //--- Set the initial frame color this.SetBorderColor(this.BorderColorInit(),false); //--- Send the test message to the journal Print(DFUN_ERR_LINE,TextByLanguage("Отмена","Cancel")); } //--- The mouse button released within the element means a click on the control else { //--- If this is a simple button, set the color for "The cursor is over the active area" status if(!this.Toggle()) this.SetBackgroundColor(this.BackgroundColorMouseOver(),false); //--- If this is the toggle button, else { //--- set the button status to the opposite one this.SetState(!this.State()); //--- set the background color for "The cursor is over the active area" status depending on whether the button is clicked or not this.SetBackgroundColor(this.State() ? this.BackgroundColorToggleONMouseOver() : this.BackgroundColorMouseOver(),false); } //--- Send the test message to the journal Print(DFUN_ERR_LINE,TextByLanguage("Щелчок","Click")); //--- Set the frame color for "The cursor is over the active area" status this.SetBorderColor(this.BorderColorMouseOver(),false); } //--- Redraw the object this.Redraw(false); } //+------------------------------------------------------------------+
Die Logik der Methode ist in den Code-Kommentaren ausführlich beschrieben und bedarf keiner Erläuterung.
Behandlung des letzten Mausereignisses:
//+------------------------------------------------------------------+ //| Last mouse event handler | //+------------------------------------------------------------------+ void CButton::OnMouseEventPostProcessing(void) { ENUM_MOUSE_FORM_STATE state=GetMouseState(); switch(state) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL : if(MouseEventLast()==MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED) { this.SetBackgroundColor(this.State() ? this.BackgroundColorToggleON() : this.BackgroundColorInit(),false); this.SetBorderColor(this.BorderColorInit(),false); this.m_mouse_event_last=ENUM_MOUSE_EVENT(state+MOUSE_EVENT_NO_EVENT); this.Redraw(false); } break; //--- The cursor is inside the form, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED : break; //--- The cursor is inside the form, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_FORM_PRESSED : break; //--- The cursor is inside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_FORM_WHEEL : break; //--- The cursor is inside the active area, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED : break; //--- The cursor is inside the active area, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED : break; //--- The cursor is inside the active area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL : break; //--- The cursor is inside the active area, left mouse button is released case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED : break; //--- The cursor is within the window scrolling area, the mouse buttons are not clicked case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_NOT_PRESSED : break; //--- The cursor is within the window scrolling area, any mouse button is clicked case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_PRESSED : break; //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_WHEEL : break; //--- MOUSE_EVENT_NO_EVENT default: break; } } //+------------------------------------------------------------------+
In dieser Methode wird nur die Situation behandelt, in der sich der Mauszeiger außerhalb des Formulars befindet, während das letzte Mausereignis ein Mauszeiger über dem Formular ist und die Maustasten nicht angeklickt werden. Die Ausgangsfarbe der Schaltfläche wird auf die Hintergrundfarbe der Schaltfläche gesetzt, je nachdem, ob die Schaltfläche gedrückt ist oder nicht (der von der Methode State() zurückgegebene, einfache Schaltflächenwert ist immer false).
Die Methode, die die Farben für den Status „aktiviert“ der Umschalttaste festlegt:
//+------------------------------------------------------------------+ //| Set the colors for the toggle element 'enabled' status | //+------------------------------------------------------------------+ void CButton::SetColorsToggleON(const color back,const color back_down,const color back_over,const bool set_init_color) { this.SetBackgroundColorToggleON(back,set_init_color); this.SetBackgroundColorToggleONMouseDown(back_down); this.SetBackgroundColorToggleONMouseOver(back_over); } //+------------------------------------------------------------------+
Die Methode empfängt die Farben für drei Schaltflächenzustände. Sie werden auf die entsprechenden Variablen gesetzt. Mit dem Flag set_init_color kann festgelegt werden, ob die ursprüngliche Hintergrundfarbe der Schaltfläche gespeichert werden soll.
Jetzt müssen wir die Kollektionsklasse der grafischen Elemente \MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqh verbessern.
In der Methode GetFormUnderCursor() gibt es zwei identische Codeblöcke, in denen die an das Formular gebundenen Objekte, die sich unter dem Cursor befinden, gesucht werden. Wir verschieben diesen Codeblock in eine separate Methode, um den Methodencode zu verkürzen und die Logik besser sichtbar zu machen.
Im privaten Abschnitt der Klasse deklarieren wir die Methode und die Methode zur Behandlung von Ereignissen des Formulars, aus dem der Cursor wegbewegt wurde:
//--- Add (1) the standard graphical object and (2) the graphical element on canvas to the collection bool AddGraphObjToCollection(const string source,CChartObjectsControl *obj_control); //--- Search for interaction objects CForm *SearchInteractObj(CForm *form,const int id,const long &lparam,const double &dparam,const string &sparam); //--- Return the pointer to the form located under the cursor CForm *GetFormUnderCursor(const int id, const long &lparam, const double &dparam, const string &sparam, ENUM_MOUSE_FORM_STATE &mouse_state, long &obj_ext_id, int &form_index); //--- Reset all interaction flags for all forms except the specified one void ResetAllInteractionExeptOne(CGCnvElement *form); //--- Post-processing of the former active form under the cursor void FormPostProcessing(void); //--- Add the element to the collection list bool AddCanvElmToCollection(CGCnvElement *element);
In allen Methoden zum Erstellen verschiedener grafischer Elemente sind die Flags bereits in den Methoden gesetzt, die die Farben setzen und die Flags zum Speichern der Ausgangsfarbe enthalten sollen (Übergabe von true, da wir die Ausgangsfarbe beim Erstellen eines Objekts speichern müssen). Alle diese Änderungen wurden bereits an der Klasse vorgenommen, so dass wir hier nicht weiter darauf eingehen werden.
Zum Beispiel die Methode, die das grafische Formularobjekt im Canvas auf dem angegebenen Chart und Unterfenster erstellt:
//--- Create a graphical form object on canvas on a specified chart and subwindow int CreateForm(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h, const color clr, const uchar opacity, const bool movable, const bool activity, const bool shadow=false, const bool redraw=false) { int id=this.m_list_all_canv_elm_obj.Total(); CForm *obj=new CForm(chart_id,subwindow,name,x,y,w,h); ENUM_ADD_OBJ_RET_CODE res=this.AddOrGetCanvElmToCollection(obj,id); if(res==ADD_OBJ_RET_CODE_ERROR) return WRONG_VALUE; obj.SetID(id); obj.SetActive(activity); obj.SetMovable(movable); obj.SetBackgroundColor(clr,true); obj.SetBorderColor(clr,true); obj.SetOpacity(opacity,false); obj.SetShadow(shadow); obj.DrawRectangle(0,0,obj.Width()-1,obj.Height()-1,obj.BorderColor(),obj.Opacity()); obj.Done(); obj.Erase(clr,opacity,redraw); return obj.ID(); }
Ähnliche Änderungen wurden an allen Methoden vorgenommen, bei denen die Farbe festgelegt wird.
Die Methode für die Suche nach Interaktionsobjekten:
//+------------------------------------------------------------------+ //| Search for interaction objects | //+------------------------------------------------------------------+ CForm *CGraphElementsCollection::SearchInteractObj(CForm *form,const int id,const long &lparam,const double &dparam,const string &sparam) { //--- If a non-empty pointer is passed if(form!=NULL) { //--- Create the list of interaction objects int total=form.CreateListInteractObj(); //--- In the loop by the created list for(int i=total-1;i>WRONG_VALUE;i--) { //--- get the next form object CForm *obj=form.GetInteractForm(i); //--- If the object is received and the mouse cursor is located above the object, return the pointer to the found object if(obj!=NULL && obj.MouseFormState(id,lparam,dparam,sparam)>MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL) return obj; } } //--- Return the same pointer return form; } //+------------------------------------------------------------------+
Im vorigen Artikel haben wir die Methodenlogik betrachtet, aber der Code befand sich innerhalb der Methode GetFormUnderCursor().
Jetzt fügen wir einfach den Aufruf der Methode anstelle des Codeblocks hinzu:
//+------------------------------------------------------------------+ //| Return the pointer to the form located under the cursor | //+------------------------------------------------------------------+ CForm *CGraphElementsCollection::GetFormUnderCursor(const int id, const long &lparam, const double &dparam, const string &sparam, ENUM_MOUSE_FORM_STATE &mouse_state, long &obj_ext_id, int &form_index) { //--- Set the ID of the extended standard graphical object to -1 //--- and the index of the anchor point managed by the form to -1 obj_ext_id=WRONG_VALUE; form_index=WRONG_VALUE; //--- Initialize the mouse status relative to the form mouse_state=MOUSE_FORM_STATE_NONE; //--- Declare the pointers to graphical element collection class objects CGCnvElement *elm=NULL; CForm *form=NULL; //--- Get the list of objects the interaction flag is set for (there should be only one object) CArrayObj *list=CSelect::ByGraphCanvElementProperty(GetListCanvElm(),CANV_ELEMENT_PROP_INTERACTION,true,EQUAL); //--- If managed to obtain the list and it is not empty, if(list!=NULL && list.Total()>0) { //--- Get the only graphical element there elm=list.At(0); //--- If the element is a form object or its descendants if(elm.TypeGraphElement()>=GRAPH_ELEMENT_TYPE_WF_BASE) { //--- Assign the pointer to the element for the form object pointer form=elm; //--- Get the mouse status relative to the form mouse_state=form.MouseFormState(id,lparam,dparam,sparam); //--- If the cursor is inside the form, if(mouse_state>MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL) { //--- Find the interaction object. //--- This will be either the found object or the same form form=this.SearchInteractObj(form,id,lparam,dparam,sparam); //--- Return the form object return form; } } } //--- If there is no a single form object with a specified interaction flag, //--- in the loop by all graphical element collection class objects int total=this.m_list_all_canv_elm_obj.Total(); for(int i=0;i<total;i++) { //--- get the next element elm=this.m_list_all_canv_elm_obj.At(i); if(elm==NULL) continue; //--- if the obtained element is a form object or its descendants if(elm.TypeGraphElement()>=GRAPH_ELEMENT_TYPE_WF_BASE) { //--- Assign the pointer to the element for the form object pointer form=elm; //--- Get the mouse status relative to the form mouse_state=form.MouseFormState(id,lparam,dparam,sparam); //--- If the cursor is within the form, return the pointer to the form if(mouse_state>MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL) { //--- Find the interaction object. //--- This will be either the found object or the same form form=this.SearchInteractObj(form,id,lparam,dparam,sparam); //--- Return the form object return form; } } } //--- If there is no a single form object from the collection list //--- Get the list of extended standard graphical objects list=this.GetListStdGraphObjectExt(); if(list!=NULL) { //--- in the loop by all extended standard graphical objects for(int i=0;i<list.Total();i++) { //--- get the next graphical object, CGStdGraphObj *obj_ext=list.At(i); if(obj_ext==NULL) continue; //--- get the object of its toolkit, CGStdGraphObjExtToolkit *toolkit=obj_ext.GetExtToolkit(); if(toolkit==NULL) continue; //--- handle the event of changing the chart for the current graphical object obj_ext.OnChartEvent(CHARTEVENT_CHART_CHANGE,lparam,dparam,sparam); //--- Get the total number of form objects created for the current graphical object total=toolkit.GetNumControlPointForms(); //--- In the loop by all form objects for(int j=0;j<total;j++) { //--- get the next form object, form=toolkit.GetControlPointForm(j); if(form==NULL) continue; //--- get the mouse status relative to the form mouse_state=form.MouseFormState(id,lparam,dparam,sparam); //--- If the cursor is inside the form, if(mouse_state>MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL) { //--- set the object ID and form index //--- and return the pointer to the form obj_ext_id=obj_ext.ObjectID(); form_index=j; return form; } } } } //--- Nothing is found - return NULL return NULL; } //+------------------------------------------------------------------+
Dank einer solchen kleinen Verfeinerung ist der Methodencode lesbarer geworden.
Die Methode, die Mausereignisse des ehemals aktiven Formulars unter dem Cursor behandelt:
//+------------------------------------------------------------------+ //| Post-processing of the former active form under the cursor | //+------------------------------------------------------------------+ void CGraphElementsCollection::FormPostProcessing(void) { //--- Get all the elements of the CForm type and above CArrayObj *list=GetList(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_FORM,EQUAL_OR_MORE); if(list==NULL) return; //--- In the loop by the list of received elements int total=list.Total(); for(int i=0;i<total;i++) { //--- get the pointer to the object CForm *obj=list.At(i); //--- if failed to get the pointer, move on to the next one in the list if(obj==NULL) continue; //--- Create the list of interaction objects and get their number int count=obj.CreateListInteractObj(); //--- In the loop by the obtained list for(int j=0;j<count;j++) { //--- get the next object CForm *elm=obj.GetInteractForm(j); if(elm==NULL) continue; //--- and call its method of handling mouse events elm.OnMouseEventPostProcessing(); } } } //+------------------------------------------------------------------+
Wenn wir den Cursor vom Formularobjekt im Chart wegbewegen, verliert dieses Objekt den Fokus und ein anderes Objekt, das sich unter dem Cursor befindet, wird automatisch ausgewählt. Wenn sich keine anderen Objekte unter dem Cursor befinden, werden alle zuvor deaktivierten Chartfunktionen aktiviert - Scrollen, Kontextmenü und andere. Manchmal ist es jedoch erforderlich, den Cursor vom Objekt zu entfernen, z. B. wenn es notwendig ist, die Farbe des Objekts zu ändern oder, in unserem Fall, die ursprüngliche Farbe wiederherzustellen. Das ist genau das, was die Methode tut. Sie durchläuft alle grafischen Elemente vom Typ „form“ und höher, erstellt eine Liste von Objekten, die an jedes Element gebunden sind, und ruft die oben erwähnte Methode zur Behandlung von Mausereignissen in einer Schleife durch diese Objekte auf. Auf diese Weise wird jedes Objekt, das sich auf jedem Formular im Chart befindet, behandelt, aber nur, wenn sein letztes Mausereignis benötigt wird (der Cursor befindet sich über dem Objekt und die Maustasten werden nicht angeklickt). Nach der Behandlung des Ereignisses wird der aktuelle Status (der Cursor befindet sich außerhalb des Formulars) dem Objekt Letztes Mausereignis zugewiesen. Es wird also nur ein Objekt (das letzte, von dem aus der Cursor bewegt wurde) einmal behandelt.
//--- If this is a mouse movement event and the movement flag is active, move the form, above which the cursor is located (if the pointer to it is valid) if(id==CHARTEVENT_MOUSE_MOVE && move) { if(form!=NULL) { //---... //---...
Wir müssen ihre Überprüfung trennen, damit wir feststellen können, wann das Bewegungs-Flag entfernt wird, die Maus sich aber bewegt (während das Halte-Flag gesetzt ist). Wenn die Maustaste losgelassen wird, wird das Ereignis MOUSE_FORM_STATE_NONE registriert. Dieses Ereignis erscheint nur in diesem Fall, weil ich noch nicht die Behandlung einer solchen Situation hinzugefügt habe, da dies das Ereignis Loslassen der Maustaste ist.
Daher müssen wir das Ereignis der Überprüfung des Cursorbewegungsereignisses und das aktivierte Bewegungs-Flag trennen. Im Falle des deaktivierten Bewegungs-Flags müssen wir das Ereignis MOUSE_FORM_STATE_NONE definieren und es durch das neue Ereignis MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED ersetzen.
Nachfolgend ist ein wie oben beschrieben überarbeitetes Codesegment zu sehen. Hier habe ich die beiden Ereignisse getrennt, damit sie getrennt überprüft werden können:
if(id==CHARTEVENT_MOUSE_MOVE) { //--- If the cursor is above the form if(form!=NULL) { //--- If the move flag is set, shift the form following the cursor if(move) { //--- calculate the cursor movement relative to the form coordinate origin int x=this.m_mouse.CoordX()-form.OffsetX(); int y=this.m_mouse.CoordY()-form.OffsetY(); //--- get the width and height of the chart the form is located at int chart_width=(int)::ChartGetInteger(form.ChartID(),CHART_WIDTH_IN_PIXELS,form.SubWindow()); int chart_height=(int)::ChartGetInteger(form.ChartID(),CHART_HEIGHT_IN_PIXELS,form.SubWindow()); //--- If the form is not within an extended standard graphical object if(form_index==WRONG_VALUE) { //--- Adjust the calculated form coordinates if the form is out of the chart range if(x<0) x=0; if(x>chart_width-form.Width()) x=chart_width-form.Width(); if(y<0) y=0; if(y>chart_height-form.Height()) y=chart_height-form.Height(); //--- If the one-click trading panel is not present on the chart, if(!::ChartGetInteger(form.ChartID(),CHART_SHOW_ONE_CLICK)) { //--- calculate the form coordinates so that the form does not overlap with the one-click trading panel button if(y<17 && x<41) y=17; } //--- If the one-click trading panel is on the chart, else { //--- calculate the form coordinates so that the form does not overlap with the one-click trading panel if(y<80 && x<192) y=80; } } //--- If the form is included into the extended standard graphical object else { if(graph_obj_id>WRONG_VALUE) { //--- Get the list of objects by object ID (there should be one object) CArrayObj *list_ext=CSelect::ByGraphicStdObjectProperty(GetListStdGraphObjectExt(),GRAPH_OBJ_PROP_ID,0,graph_obj_id,EQUAL); //--- If managed to obtain the list and it is not empty, if(list_ext!=NULL && list_ext.Total()>0) { //--- get the graphical object from the list CGStdGraphObj *ext=list_ext.At(0); //--- If the pointer to the object has been received, if(ext!=NULL) { //--- get the object type ENUM_OBJECT type=ext.GraphObjectType(); //--- If the object is built using screen coordinates, set the coordinates to the object if(type==OBJ_LABEL || type==OBJ_BUTTON || type==OBJ_BITMAP_LABEL || type==OBJ_EDIT || type==OBJ_RECTANGLE_LABEL) { ext.SetXDistance(x); ext.SetYDistance(y); } //--- otherwise, if the object is built based on time/price coordinates, else { //--- calculate the shift from the form coordinate origin to its center int shift=(int)::ceil(form.Width()/2)+1; //--- If the form is located on one of the graphical object pivot points, if(form_index<ext.Pivots()) { //--- limit the form coordinates so that they do not move beyond the chart borders if(x+shift<0) x=-shift; if(x+shift>chart_width) x=chart_width-shift; if(y+shift<0) y=-shift; if(y+shift>chart_height) y=chart_height-shift; //--- set the calculated coordinates to the object ext.ChangeCoordsExtendedObj(x+shift,y+shift,form_index); } //--- If the form is central for managing all pivot points of a graphical object else { //--- Get screen coordinates of all object pivot points and write them to the m_data_pivot_point structure if(this.GetPivotPointCoordsAll(ext,m_data_pivot_point)) { //--- In the loop by the number of object pivot points, for(int i=0;i<(int)this.m_data_pivot_point.Size();i++) { //--- limit the screen coordinates of the current pivot point so that they do not move beyond the chart borders //--- By X coordinate if(x+shift-::fabs(this.m_data_pivot_point[i].ShiftX)<0) x=-shift+::fabs(m_data_pivot_point[i].ShiftX); if(x+shift+::fabs(this.m_data_pivot_point[i].ShiftX)>chart_width) x=chart_width-shift-::fabs(this.m_data_pivot_point[i].ShiftX); //--- By Y coordinate if(y+shift-::fabs(this.m_data_pivot_point[i].ShiftY)<0) y=-shift+::fabs(this.m_data_pivot_point[i].ShiftY); if(y+shift+::fabs(this.m_data_pivot_point[i].ShiftY)>chart_height) y=chart_height-shift-::fabs(this.m_data_pivot_point[i].ShiftY); //--- set the calculated coordinates to the current object pivot point ext.ChangeCoordsExtendedObj(x+shift+this.m_data_pivot_point[i].ShiftX,y+shift+this.m_data_pivot_point[i].ShiftY,i); } } } } } } } } //--- Move the form by the obtained coordinates if(form.IsMain()) form.Move(x,y,true); } //--- If the move flag is disabled else { //--- The undefined mouse status in mouse_state means releasing the left button //--- Assign the new mouse status to the variable if(mouse_state==MOUSE_FORM_STATE_NONE) mouse_state=MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED; //--- Handle moving the cursor mouse away from the graphical element this.FormPostProcessing(); } } }
Jetzt sind wir in der Lage, ein neues Mausereignis „abzufangen“ , vorausgesetzt, das Verschub-Flag wird freigegeben, und das Ereignis der Bewegung des Cursors weg vom Objekt für das aktive Formularobjekt sofort zu behandeln.
In derselben Ereignisbehandlung, d. h. in den Maus-Ereignishandlungsblöcken, rufen wir OnChartEvent() die Maus-Ereignishandlung für das Objekt auf, wobei wir das zuvor gefundene Ereignis angeben:
//--- If the cursor is above the form else { //--- If the button is still pressed and held on the chart, exit if(pressed_chart) { return; } //--- If the flag of holding the button on the form is not set yet if(!pressed_form) { pressed_chart=false; // The button is not pressed on the chart this.SetChartTools(form.ChartID(),false); //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the form, no mouse buttons are clicked' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED,lparam,dparam,sparam); //--- If the cursor is above the form for managing the pivot point of an extended graphical object, if(graph_obj_id>WRONG_VALUE) { //--- get the object by its ID and by the chart ID CGStdGraphObj *graph_obj=this.GetStdGraphObjectExt(graph_obj_id,form.ChartID()); if(graph_obj!=NULL) { //--- Get the toolkit of an extended standard graphical object CGStdGraphObjExtToolkit *toolkit=graph_obj.GetExtToolkit(); if(toolkit!=NULL) { //--- Draw a point with a circle on the form and delete it on all other forms toolkit.DrawOneControlPoint(form); } } } } //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the form, a mouse button is clicked (any)' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_FORM_PRESSED) { this.SetChartTools(::ChartID(),false); //--- If the flag of holding the form is not set yet if(!pressed_form) { pressed_form=true; // set the flag of pressing on the form pressed_chart=false; // disable the flag of pressing on the form } form.OnMouseEvent(MOUSE_EVENT_INSIDE_FORM_PRESSED,lparam,dparam,sparam); } //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the form, the mouse wheel is being scrolled' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_FORM_WHEEL) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_FORM_WHEEL,lparam,dparam,sparam); } //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the active area, the mouse buttons are not clicked' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED) { //--- Set the cursor shift relative to the form initial coordinates form.SetOffsetX(this.m_mouse.CoordX()-form.CoordX()); form.SetOffsetY(this.m_mouse.CoordY()-form.CoordY()); form.OnMouseEvent(MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED,lparam,dparam,sparam); //--- If the cursor is above the active area of the form for managing the pivot point of an extended graphical object, if(graph_obj_id>WRONG_VALUE) { //--- get the object by its ID and by the chart ID CGStdGraphObj *graph_obj=this.GetStdGraphObjectExt(graph_obj_id,form.ChartID()); if(graph_obj!=NULL) { //--- Get the toolkit of an extended standard graphical object CGStdGraphObjExtToolkit *toolkit=graph_obj.GetExtToolkit(); if(toolkit!=NULL) { //--- Draw a point with a circle on the form and delete it on all other forms toolkit.DrawOneControlPoint(form); } } } } //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the active area, any mouse button is clicked' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED && !move) { pressed_form=true; // the flag of holding the mouse button on the form //--- If the left mouse button is pressed if(this.m_mouse.IsPressedButtonLeft()) { //--- Set flags and form parameters move=true; // movement flag form.SetInteraction(true); // flag of the form interaction with the environment form.BringToTop(); // form on the background - above all others form.SetOffsetX(this.m_mouse.CoordX()-form.CoordX()); // Cursor shift relative to the X coordinate form.SetOffsetY(this.m_mouse.CoordY()-form.CoordY()); // Cursor shift relative to the Y coordinate this.ResetAllInteractionExeptOne(form); // Reset interaction flags for all forms except the current one //--- Get the maximum ZOrder long zmax=this.GetZOrderMax(); //--- If the maximum ZOrder has been received and the form's ZOrder is less than the maximum one or the maximum ZOrder of all forms is equal to zero if(zmax>WRONG_VALUE && (form.Zorder()<zmax || zmax==0)) { //--- If the form is not a control point for managing an extended standard graphical object, //--- set the form's ZOrder above all others if(form.Type()!=OBJECT_DE_TYPE_GFORM_CONTROL) this.SetZOrderMAX(form); } } form.OnMouseEvent(MOUSE_EVENT_INSIDE_ACTIVE_AREA_PRESSED,lparam,dparam,sparam); } //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the active area, the mouse wheel is being scrolled' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_ACTIVE_AREA_WHEEL,lparam,dparam,sparam); } //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the active area, the left mouse button is clicked' event handler | //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED,lparam,dparam,sparam); } //+---------------------------------------------------------------------------------------------+ //| 'The cursor is inside the window scrolling area, no mouse buttons are clicked' event handler| //+---------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_NOT_PRESSED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_NOT_PRESSED,lparam,dparam,sparam); } //+------------------------------------------------------------------------------------------------+ //| 'The cursor is inside the window scrolling area, a mouse button is clicked (any)' event handler| //+------------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_PRESSED) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_PRESSED,lparam,dparam,sparam); } //+--------------------------------------------------------------------------------------------------+ //| 'The cursor is inside the window scrolling area, the mouse wheel is being scrolled' event handler| //+--------------------------------------------------------------------------------------------------+ if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_WHEEL) { form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_WHEEL,lparam,dparam,sparam); } } } } }
Hier fügen wir auch einen neuen Handler für die Behandlung des Ereignisses des Loslassens der Maustaste hinzu.
In der Methode zum Setzen der Maus-Scroll-, Kontextmenü- und Fadenkreuz-Flags für ein bestimmtes Chart fügen wir die Prüfung des bereits gesetzten Flags hinzu, um zu vermeiden, dass ständig derselbe Status gesetzt wird, der bereits zuvor für das Chart gesetzt wurde:
//+------------------------------------------------------------------+ //| Set the flags of scrolling a chart | //| context menu and crosshairs for the chart | //+------------------------------------------------------------------+ void CGraphElementsCollection::SetChartTools(const long chart_id,const bool flag) { if(::ChartGetInteger(chart_id,CHART_MOUSE_SCROLL)==flag) return; ::ChartSetInteger(chart_id,CHART_MOUSE_SCROLL,flag); ::ChartSetInteger(chart_id,CHART_CONTEXT_MENU,flag); ::ChartSetInteger(chart_id,CHART_CROSSHAIR_TOOL,flag); } //+------------------------------------------------------------------+
Derzeit sind dies alle Verbesserungen der Bibliotheksklassen.
Test
Um den Test durchzuführen, verwende ich den EA aus dem vorherigen Artikel und speichere ihn in \MQL5\Experts\TestDoEasy\Part110\ als TstDE110.mq5.
Ich werde alle Objekte aus dem vorherigen EA so belassen, wie sie sind. Stattdessen werde ich die Größe und Position der Schaltflächen leicht ändern und die Zeiger auf Objekte nach ihrem Typ abrufen, um die Funktionsweise der Methode zu testen.
Fügen wir den EA-Eingängen das Flag für die Umschalttaste hinzu und ändern die Standardparameter:
//--- input parameters sinput bool InpMovable = true; // Panel Movable flag sinput ENUM_INPUT_YES_NO InpAutoSize = INPUT_YES; // Panel Autosize sinput ENUM_AUTO_SIZE_MODE InpAutoSizeMode = AUTO_SIZE_MODE_GROW; // Panel Autosize mode sinput ENUM_BORDER_STYLE InpFrameStyle = BORDER_STYLE_SIMPLE; // Label border style sinput ENUM_ANCHOR_POINT InpTextAlign = ANCHOR_CENTER; // Label text align sinput ENUM_INPUT_YES_NO InpTextAutoSize = INPUT_NO; // Label autosize sinput ENUM_ANCHOR_POINT InpCheckAlign = ANCHOR_LEFT; // Check flag align sinput ENUM_ANCHOR_POINT InpCheckTextAlign = ANCHOR_LEFT; // Check label text align sinput ENUM_CHEK_STATE InpCheckState = CHEK_STATE_UNCHECKED; // Check flag state sinput ENUM_INPUT_YES_NO InpCheckAutoSize = INPUT_YES; // CheckBox autosize sinput ENUM_BORDER_STYLE InpCheckFrameStyle = BORDER_STYLE_NONE; // CheckBox border style sinput ENUM_ANCHOR_POINT InpButtonTextAlign = ANCHOR_CENTER; // Button text align sinput ENUM_INPUT_YES_NO InpButtonAutoSize = INPUT_YES; // Button autosize sinput ENUM_AUTO_SIZE_MODE InpButtonAutoSizeMode= AUTO_SIZE_MODE_GROW; // Button Autosize mode sinput ENUM_BORDER_STYLE InpButtonFrameStyle = BORDER_STYLE_NONE; // Button border style sinput bool InpButtonToggle = false; // Button toggle flag //--- global variables
OnInit() enthält nun den folgenden Code:
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Set EA global variables ArrayResize(array_clr,2); // Array of gradient filling colors array_clr[0]=C'26,100,128'; // Original ≈Dark-azure color array_clr[1]=C'35,133,169'; // Lightened original color //--- Create the array with the current symbol and set it to be used in the library string array[1]={Symbol()}; engine.SetUsedSymbols(array); //--- Create the timeseries object for the current symbol and period, and show its description in the journal engine.SeriesCreate(Symbol(),Period()); engine.GetTimeSeriesCollection().PrintShort(false); // Short descriptions //--- Create WinForms Panel object CPanel *pnl=NULL; pnl=engine.CreateWFPanel("WFPanel",50,50,230,150,array_clr,200,true,true,false,-1,FRAME_STYLE_BEVEL,true,false); if(pnl!=NULL) { //--- Set Padding to 4 pnl.SetPaddingAll(4); //--- Set the flags of relocation, auto resizing and auto changing mode from the inputs pnl.SetMovable(InpMovable); pnl.SetAutoSize(InpAutoSize,false); pnl.SetAutoSizeMode((ENUM_CANV_ELEMENT_AUTO_SIZE_MODE)InpAutoSizeMode,false); //--- In the loop, create 2 bound panel objects CPanel *obj=NULL; for(int i=0;i<2;i++) { //--- create the panel object with calculated coordinates, width of 90 and height of 40 CPanel *prev=pnl.GetElement(i-1); int xb=0, yb=0; int x=(prev==NULL ? xb : xb+prev.Width()+20); int y=0; if(pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_PANEL,x,y,90,40,C'0xCD,0xDA,0xD7',200,true,false)) { obj=pnl.GetElement(i); if(obj==NULL) continue; obj.SetBorderSizeAll(3); obj.SetBorderStyle(FRAME_STYLE_BEVEL); obj.SetBackgroundColor(obj.ChangeColorLightness(obj.BackgroundColor(),4*i),true); obj.SetForeColor(clrRed,true); //--- Calculate the width and height of the future text label object int w=obj.Width()-obj.BorderSizeLeft()-obj.BorderSizeRight(); int h=obj.Height()-obj.BorderSizeTop()-obj.BorderSizeBottom(); //--- Create a text label object obj.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_LABEL,0,0,w,h,clrNONE,255,false,false); //--- Get the pointer to a newly created object CLabel *lbl=obj.GetElement(0); if(lbl!=NULL) { //--- If the object has an even or zero index in the list, set the default text color for it if(i % 2==0) lbl.SetForeColor(CLR_DEF_FORE_COLOR,true); //--- If the object index in the list is odd, set the object opacity to 127 else lbl.SetForeColorOpacity(127); //--- Set the font Black width type and //--- specify the text alignment from the EA settings lbl.SetFontBoldType(FW_TYPE_BLACK); lbl.SetTextAlign(InpTextAlign); lbl.SetAutoSize((bool)InpTextAutoSize,false); //--- For an object with an even or zero index, specify the Bid price for the text, otherwise - the Ask price of the symbol lbl.SetText(GetPrice(i % 2==0 ? SYMBOL_BID : SYMBOL_ASK)); //--- Set the frame width, type and color for a text label and update the modified object lbl.SetBorderSizeAll(1); lbl.SetBorderStyle((ENUM_FRAME_STYLE)InpFrameStyle); lbl.SetBorderColor(CLR_DEF_BORDER_COLOR,true); lbl.Update(true); } } } //--- Create the 'GroupBox' WinForms object CGroupBox *gbox=NULL; //--- Indent from attached panels by 6 pixels is a Y coordinate for GroupBox int w=pnl.GetUnderlay().Width(); int y=obj.BottomEdgeRelative()+6; //--- If the attached GroupBox object is created if(pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_GROUPBOX,0,y,210,110,C'0x91,0xAA,0xAE',0,true,false)) { //--- get the pointer to the GroupBox object by its index in the list of bound GroupBox type objects gbox=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_GROUPBOX,0); if(gbox!=NULL) { //--- set the "indented frame" type, the frame color matches the main panel background color, //--- while the text color is the background color of the last attached panel darkened by 1 gbox.SetBorderStyle(FRAME_STYLE_STAMP); gbox.SetBorderColor(pnl.BackgroundColor(),true); gbox.SetForeColor(gbox.ChangeColorLightness(obj.BackgroundColor(),-1),true); //--- Create the CheckBox object gbox.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_CHECKBOX,2,10,50,20,clrNONE,255,true,false); //--- get the pointer to the CheckBox object by its index in the list of bound CheckBox type objects CCheckBox *cbox=gbox.GetElementByType(GRAPH_ELEMENT_TYPE_WF_CHECKBOX,0); //--- If CheckBox is created and the pointer to it is received if(cbox!=NULL) { //--- Set the CheckBox parameters from the EA inputs cbox.SetAutoSize((bool)InpCheckAutoSize,false); cbox.SetCheckAlign(InpCheckAlign); cbox.SetTextAlign(InpCheckTextAlign); //--- Set the displayed text, frame style and color, as well as checkbox status cbox.SetText("CheckBox"); cbox.SetBorderStyle((ENUM_FRAME_STYLE)InpCheckFrameStyle); cbox.SetBorderColor(CLR_DEF_BORDER_COLOR,true); cbox.SetChecked(true); cbox.SetCheckState((ENUM_CANV_ELEMENT_CHEK_STATE)InpCheckState); } //--- Create the RadioButton object gbox.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON,2,cbox.BottomEdgeRelative()+4,50,20,clrNONE,255,true,false); //--- get the pointer to the RadioButton object by its index in the list of bound RadioButton type objects CRadioButton *rbtn=gbox.GetElementByType(GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON,0); //--- If RadioButton is created and the pointer to it is received if(rbtn!=NULL) { //--- Set the RadioButton parameters from the EA inputs rbtn.SetAutoSize((bool)InpCheckAutoSize,false); rbtn.SetCheckAlign(InpCheckAlign); rbtn.SetTextAlign(InpCheckTextAlign); //--- Set the displayed text, frame style and color, as well as checkbox status rbtn.SetText("RadioButton"); rbtn.SetBorderStyle((ENUM_FRAME_STYLE)InpCheckFrameStyle); rbtn.SetBorderColor(CLR_DEF_BORDER_COLOR,true); rbtn.SetChecked(true); } //--- Create the Button object gbox.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_BUTTON,(int)fmax(rbtn.RightEdgeRelative(),cbox.RightEdgeRelative())+10,14,60,36,clrNONE,255,true,false); //--- get the pointer to the Button object by its index in the list of bound Button type objects CButton *butt=gbox.GetElementByType(GRAPH_ELEMENT_TYPE_WF_BUTTON,0); //--- If Button is created and the pointer to it is received if(butt!=NULL) { //--- Set the Button parameters from the EA inputs butt.SetAutoSize((bool)InpButtonAutoSize,false); butt.SetAutoSizeMode((ENUM_CANV_ELEMENT_AUTO_SIZE_MODE)InpButtonAutoSizeMode,false); butt.SetTextAlign(InpButtonTextAlign); //--- Set the text color, as well as frame style and color butt.SetForeColor(butt.ChangeColorLightness(CLR_DEF_FORE_COLOR,2),true); butt.SetBorderStyle((ENUM_FRAME_STYLE)InpButtonFrameStyle); butt.SetBorderColor(butt.ChangeColorLightness(butt.BackgroundColor(),-10),true); //--- Set the 'toggle' mode depending on the settings butt.SetToggleFlag(InpButtonToggle); //--- Set the displayed text on the button depending on the 'toggle' flag if(butt.Toggle()) butt.SetText("Toggle-Button"); else butt.SetText("Button"); } } } //--- Redraw all objects according to their hierarchy pnl.Redraw(true); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
In der Tat bleibt hier alles beim Alten. Ich habe die Namen der in der Bibliothek umbenannten Methoden geändert. Die Flags (true) zur Beibehaltung der Ausgangsfarbe werden nun in den Methoden zum Setzen von Farben übergeben, während ein ausgewählter Schaltflächenmodus nun auf der entsprechenden Schaltfläche als Text angezeigt wird.
Sie können alle Änderungen in den unten angehängten Dateien einsehen.
Kompilieren Sie den EA und starten Sie ihn auf dem Chart eines Symbols:
Wie wir sehen können, funktioniert die gesamte visuelle Komponente der Objekte bei der Interaktion mit der Maus korrekt.
Was kommt als Nächstes?
Im nächsten Artikel werde ich meine Arbeit an der Interaktivität der Bibliothek WinForms-Objekte fortsetzen.
*Vorherige Artikel in dieser Reihe:
DoEasy. Steuerung (Teil 1): Erste Schritte
DoEasy. Steuerung (Teil 2): Arbeiten an der Klasse CPanel
DoEasy. Steuerung (Teil 3): Erstellen gebundener Steuerelemente
DoEasy. Steuerung (Teil 4): Paneel-Steuerung, Parameter für Padding und Dock
DoEasy. Steuerung (Teil 5): Basisobjekt von WinForms, Paneel-Steuerelement, Parameter AutoSize
DoEasy. Steuerung (Teil 6): Paneel-Steuerung, automatische Größenanpassung des Containers an den inneren Inhalt
DoEasy. Steuerung (Teil 7): Steuerung der Text Label
DoEasy. Steuerung (Teil 8): Objektkategorien von Basis-WinForms zur Steuerung von GroupBox- und CheckBox
DoEasy. Steuerung (Teil 9): Neuanordnung von WinForms-Objektmethoden, Steuerung von RadioButton und Steuerungen
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/11173
- 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.