DoEasy. Steuerung (Teil 28): Balkenstile im ProgressBar-Steuerelement
Inhalt
Konzept
Derzeit verfügt das für die Bibliothek erstellte Steuerelement der ProgressBar über einen einzigen Anzeigestil für Fortschrittsbalken — eine durchgehende Linie (Continuous Line). Dieses Steuerelement verfügt jedoch über zwei weitere Anzeigestile - segmentierte Blöcke (Blocks) und kontinuierlich scrollende Blöcke im Objekt (Marquee). Der Block-Stil ist ziemlich eindeutig (eine durchgehende Linie wird durch separat angeordnete Blöcke ersetzt). Der Marquee-Stil kann verwendet werden, wenn die Anzahl der Iterationen, die mit dem ProgressBar-Steuerelement visuell angezeigt werden müssen, nicht im Voraus bekannt ist. In diesem Fall wird ein einzelner Block, der der halben Breite des Fortschrittsbalkens entspricht, ständig weiterlaufen.
Zusätzlich zur Erstellung dieser beiden neuen Stile werde ich dem Fortschrittsbalken einen Text hinzufügen, der darin angezeigt werden soll. Der Text selbst wird durch ein reguläres Objekt der Klasse CLabel der Bibliothek dargestellt und ist nicht an das ProgressBar-Objekt, sondern an das Underlay-Objekt gebunden, das die Basis des ProgressBar-Steuerelements ist. Der Text wird in einem vollständig transparenten Textlabel-Objekt gerendert, das auf die Breite und Höhe des Fortschrittsbalkens zugeschnitten ist. Dieses Objekt wird immer im Vordergrund sein - über allen Objekten im ProgressBar-Steuerelement.
Standardmäßig wird der Text nicht auf dem Fortschrittsbalken angezeigt, er kann aber jederzeit direkt während der Ausführung eines bibliotheksbasierten Programms hinzugefügt werden. Wir müssen lediglich den Ausgabetext und seine Attribute (Schriftart, -größe, -Flags, Farbe, Deckkraft usw.) angeben.
Verbesserung der Bibliotheksklassen
Bevor ich mit der Entwicklung neuer Stile für das ProgressBar-Steuerelement beginne, sollten wir die Konstruktoren des grundlegenden grafischen Elements vereinfachen. Nachdem ich ein Objekt erstellt habe, lege ich die Werte seiner Eigenschaften in den geschützten und parametrischen Konstruktoren fest. In beiden Konstruktoren handelt es sich um eine lange Liste von mehr als hundert verschiedenen Parametern für grafische Bibliothekselemente, die beim Erstellen neuer Objekte ständig hinzugefügt werden. So müssen wir die Einstellung der Objekteigenschaften immer zweimal schreiben - in den geschützten und in den parametrischen Konstruktoren der Klasse CGCnvElement. Es wäre logisch, die Einstellung all dieser Eigenschaften in eine separate Initialisierungsmethode zu verschieben. Wenn einige Eigenschaften in verschiedenen Konstruktoren unterschiedlich eingestellt werden sollen, werden sie einfach in den formalen Parametern der neuen Methode übergeben und dort angegeben.
In \MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqh fügen wir die neue Eigenschaften zu der Objektstruktur hinzu:
struct SData { //--- Object integer properties int id; // Element ID int type; // Graphical element type //---... //---... //--- int group; // Group the graphical element belongs to int tab_size_mode; // Tab size setting mode int tab_page_number; // Tab index number int tab_page_row; // Tab row index int tab_page_column; // Tab column index int progress_bar_minimum; // The lower bound of the range ProgressBar operates in int progress_bar_maximum; // The upper bound of the range ProgressBar operates in int progress_bar_step; // ProgressBar increment needed to redraw it int progress_bar_style; // ProgressBar style int progress_bar_value; // Current ProgressBar value from Min to Max int progress_bar_marquee_speed; // Progress bar animation speed in case of Marquee style //--- ulong tooltip_initial_delay; // Tooltip display delay ulong tooltip_auto_pop_delay; // Tooltip display duration ulong tooltip_reshow_delay; // One element new tooltip display delay bool tooltip_show_always; // Display a tooltip in inactive window int tooltip_icon; // Icon displayed in a tooltip bool tooltip_is_balloon; // Tooltip in the form of a "cloud" bool tooltip_use_fading; // Fade when showing/hiding a tooltip //--- 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 uchar descript[256]; // Graphical element description uchar tooltip_title[256]; // Element tooltip title uchar tooltip_text[256]; // Element tooltip text }; SData m_struct_obj; // Object structure
Die Struktur eines grafischen Objekts wird benötigt, um die Eigenschaften des Objekts korrekt in eine Datei zu schreiben und sie bei der Wiederherstellung aus der Datei zu lesen. Die Eigenschaften, die jetzt in diese Struktur geschrieben werden, wurden dem Objekt bereits hinzugefügt, aber noch nicht in die Struktur eingefügt. Selbst wenn die Felder der Struktur nicht mit den Eigenschaften des Objekts übereinstimmen, gibt es in diesem Stadium der Entwicklung keinen Grund zur Sorge. Bisher habe ich noch nicht implementiert, das Objekt in einer Datei zu speichern und seine Eigenschaften aus der Datei zu lesen. Anschließend werde ich natürlich die Eigenschaften der grafischen Objekte in einer Datei speichern und von dort auslesen. Zu diesem Zeitpunkt wird eine vollständige Übereinstimmung zwischen den Strukturfeldern und den Objekteigenschaften benötigt.
Im privaten Abschnitt der Klasse deklarieren wir eine neue Methode zur Initialisierung der Eigenschaften des grafischen Elements:
//--- 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); } //--- Initialize property values void Initialize(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id,const int element_num, const int x,const int y,const int w,const int h, const string descript,const bool movable,const bool activity); public:
Die Eigenschaften des erstellten Objekts werden an die Methode übergeben. Die Eigenschaften haben in verschiedenen Konstruktoren unterschiedliche Werte oder werden direkt in den formalen Parametern der Konstruktoren angegeben, d.h. von außen übergeben. Ich werde alle diese Eigenschaften über die Parameter an die Methode übergeben.
Entfernen wir eine lange Liste von Objekteigenschaften in jedem der Konstruktoren und ersetzen sie durch einen Aufruf der Initialisierungsmethode:
//+---------------------------------------------+ //| Parametric constructor | //+---------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, CGCnvElement *main_obj,CGCnvElement *base_obj, const int element_id, const int element_num, const long chart_id, const int wnd_num, const string descript, 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.SetTypeElement(element_type); this.m_type=OBJECT_DE_TYPE_GELEMENT; this.m_element_main=main_obj; this.m_element_base=base_obj; this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND); this.m_name=this.CreateNameGraphElement(element_type); this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id); this.m_subwindow=wnd_num; 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,x,y,w,h,redraw)) { this.Initialize(element_type,element_id,element_num,x,y,w,h,descript,movable,activity); this.SetVisibleFlag(false,false); } else { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj()); } } //+---------------------------------------------+ //| Protected constructor | //+---------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int wnd_num, const string descript, const int x, const int y, const int w, const int h) : m_shadow(false) { this.m_type=OBJECT_DE_TYPE_GELEMENT; this.m_element_main=main_obj; this.m_element_base=base_obj; this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND); this.m_name=this.CreateNameGraphElement(element_type); 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(CLR_CANV_NULL,true); this.SetOpacity(0); 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,x,y,w,h,false)) { this.Initialize(element_type,0,0,x,y,w,h,descript,false,false); this.SetVisibleFlag(false,false); } else { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj()); } } //+------------------------------------------------------------------+
Wie wir sehen können, werden die Werte, die in jedem spezifischen Konstruktor enthalten sind, an die Initialisierungsmethode in beiden Konstruktoren übergeben.
In der neuen Initialisierungsmethode wird die Einstellung der Eigenschaft move aus den Klassenkonstruktoren entfernt:
//+---------------------------------------------+ //| Initialize the properties | //+---------------------------------------------+ void CGCnvElement::Initialize(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id,const int element_num, const int x,const int y,const int w,const int h, const string descript,const bool movable,const bool activity) { 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_VISIBLE_AREA_X,0); // Visibility scope X coordinate this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_Y,0); // Visibility scope Y coordinate this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_WIDTH,w); // Visibility scope width this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_HEIGHT,h); // Visibility scope height this.SetProperty(CANV_ELEMENT_PROP_DISPLAYED,true); // Non-hidden control display flag this.SetProperty(CANV_ELEMENT_PROP_DISPLAY_STATE,CANV_ELEMENT_DISPLAY_STATE_NORMAL);// Control display state this.SetProperty(CANV_ELEMENT_PROP_DISPLAY_DURATION,DEF_CONTROL_PROCESS_DURATION); // Control display duration this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,0); // Control area X coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,0); // Control area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,0); // Control area width this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,0); // Control area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT,0); // Right scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT,0); // Right scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT,0); // Right scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT,0); // Right scroll area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM,0); // Bottom scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM,0); // Bottom scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM,0); // Bottom scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM,0); // Bottom scroll area height this.SetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH,0); // Left edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH,0); // Bottom edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,0); // Right edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,0); // Top edge area width //--- 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_STATE_ON,CLR_DEF_FORE_COLOR); // Text color of the control which is on this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_STATE_ON_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_STATE_ON_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_STATE_ON,CLR_DEF_CONTROL_STD_BACK_COLOR_ON);// Background color of the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_STATE_ON_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_STATE_ON_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 this.SetProperty(CANV_ELEMENT_PROP_BUTTON_GROUP,false); // Button group flag this.SetProperty(CANV_ELEMENT_PROP_LIST_BOX_MULTI_COLUMN,false); // Horizontal display of columns in the ListBox control this.SetProperty(CANV_ELEMENT_PROP_LIST_BOX_COLUMN_WIDTH,0); // Width of each ListBox control column this.SetProperty(CANV_ELEMENT_PROP_TAB_MULTILINE,false); // Several lines of tabs in TabControl this.SetProperty(CANV_ELEMENT_PROP_TAB_ALIGNMENT,CANV_ELEMENT_ALIGNMENT_TOP); // Location of tabs inside the control this.SetProperty(CANV_ELEMENT_PROP_ALIGNMENT,CANV_ELEMENT_ALIGNMENT_TOP); // Location of an object inside the control this.SetProperty(CANV_ELEMENT_PROP_TEXT,""); // Graphical element text this.SetProperty(CANV_ELEMENT_PROP_DESCRIPTION,descript); // Graphical element description this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_FIXED_PANEL,0); // Panel that retains its size when the container is resized this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_FIXED,true); // Separator moveability flag this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE,50); // Distance from edge to separator this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH,4); // Separator width this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,0); // Separator location this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,false); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE,25); // Panel 1 minimum size this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,false); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE,25); // Panel 2 minimum size this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY,500); // Tooltip display delay this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY,5000); // Tooltip display duration this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY,100); // One element new tooltip display delay this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS,false); // Display a tooltip in inactive window this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_ICON,CANV_ELEMENT_TOOLTIP_ICON_NONE); // Icon displayed in a tooltip this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON,false); // Tooltip in the form of a "cloud" this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_USE_FADING,true); // Fade when showing/hiding a tooltip this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE,""); // Tooltip title for the element this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT,""); // Tooltip text for the element this.SetProperty(CANV_ELEMENT_PROP_GROUP,0); // Group the graphical element belongs to this.SetProperty(CANV_ELEMENT_PROP_TAB_SIZE_MODE,CANV_ELEMENT_TAB_SIZE_MODE_NORMAL);// Tab size setting mode this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_NUMBER,0); // Tab index number this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_ROW,0); // Tab row index this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_COLUMN,0); // Tab column index this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MAXIMUM,100); // The upper bound of the range ProgressBar operates in this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM,0); // The lower bound of the range ProgressBar operates in this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STEP,10); // ProgressBar increment needed to redraw it this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE,CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS); // ProgressBar style this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,50); // Current ProgressBar value from Min to Max this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,10); // Progress bar animation speed in case of Marquee style } //+------------------------------------------------------------------+
Hier haben wir einfach die Zeichenketten aus den Klassenkonstruktoren entfernt. Eigenschaftswerte, die in verschiedenen Konstruktoren unterschiedlich waren, werden nun über formale Methodenparameter an Objekteigenschaften übergeben und gesetzt.
In der Methode zum Anlegen einer Objektstruktur fügen wir den neuen Strukturfeldern Einstellwerte für die entsprechenden Grafikelementeigenschaften 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.belong=(int)this.GetProperty(CANV_ELEMENT_PROP_BELONG); // Graphical element affiliation this.m_struct_obj.number=(int)this.GetProperty(CANV_ELEMENT_PROP_NUM); // Element ID in the list //---... //---... this.m_struct_obj.border_right_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH); // Right edge area width this.m_struct_obj.border_top_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH); // Top edge area width //--- this.m_struct_obj.tooltip_initial_delay=this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY); // Tooltip display delay this.m_struct_obj.tooltip_auto_pop_delay=this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY); // Tooltip display duration this.m_struct_obj.tooltip_reshow_delay=this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY); // One element new tooltip display delay this.m_struct_obj.tooltip_show_always=this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS); // Display a tooltip in inactive window this.m_struct_obj.tooltip_icon=(int)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_ICON); // Icon displayed in the tooltip this.m_struct_obj.tooltip_is_balloon=(bool)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON); // Balloon tooltip this.m_struct_obj.tooltip_use_fading=(bool)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_USE_FADING); // Fade when showing and hiding the tooltip //--- this.m_struct_obj.group=(int)this.GetProperty(CANV_ELEMENT_PROP_GROUP); // Group the graphical element belongs to this.m_struct_obj.tab_size_mode=(int)this.GetProperty(CANV_ELEMENT_PROP_TAB_SIZE_MODE); // Tab size setting mode this.m_struct_obj.tab_page_number=(int)this.GetProperty(CANV_ELEMENT_PROP_TAB_PAGE_NUMBER); // Tab index number this.m_struct_obj.tab_page_row=(int)this.GetProperty(CANV_ELEMENT_PROP_TAB_PAGE_ROW); // Tab row index this.m_struct_obj.tab_page_column=(int)this.GetProperty(CANV_ELEMENT_PROP_TAB_PAGE_COLUMN); // Tab column index this.m_struct_obj.progress_bar_maximum=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MAXIMUM); // The upper bound of the range ProgressBar operates in this.m_struct_obj.progress_bar_minimum=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM); // The lower bound of the range ProgressBar operates in this.m_struct_obj.progress_bar_step=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STEP); // ProgressBar increment needed to redraw it this.m_struct_obj.progress_bar_style=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE); // ProgressBar style this.m_struct_obj.progress_bar_value=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE); // Current ProgressBar value from Min to Max this.m_struct_obj.progress_bar_marquee_speed=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED);// Progress bar animation speed in case of Marquee style //--- 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 ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_DESCRIPTION),this.m_struct_obj.descript);// Graphical element description ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE),this.m_struct_obj.tooltip_title);// Tooltip title for the element ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT),this.m_struct_obj.tooltip_text); // Tooltip text for the element //--- 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; } //+------------------------------------------------------------------+
In der Methode, die ein Objekt aus einer Struktur erzeugt, implementieren wir das Setzen von Objekteigenschaften aus den entsprechenden Strukturfeldern, die im aktuellen Artikel hinzugefügt wurden:
//+---------------------------------------------+ //| 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_BELONG,this.m_struct_obj.belong); // Graphical element affiliation this.SetProperty(CANV_ELEMENT_PROP_NUM,this.m_struct_obj.number); // Element index in the list //---... //---... this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,this.m_struct_obj.border_right_area_width); // Right edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,this.m_struct_obj.border_top_area_width); // Top edge area width this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY,this.m_struct_obj.tooltip_initial_delay); // Tooltip display delay this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY,this.m_struct_obj.tooltip_auto_pop_delay);// Tooltip display duration this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY,this.m_struct_obj.tooltip_reshow_delay);// One element new tooltip display delay this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS,this.m_struct_obj.tooltip_show_always);// Display a tooltip in inactive window this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_ICON,this.m_struct_obj.tooltip_icon); // Icon displayed in a tooltip this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON,this.m_struct_obj.tooltip_is_balloon); // Balloon tooltip this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_USE_FADING,this.m_struct_obj.tooltip_use_fading); // Fade when showing/hiding a tooltip this.SetProperty(CANV_ELEMENT_PROP_GROUP,this.m_struct_obj.group); // Group the graphical element belongs to this.SetProperty(CANV_ELEMENT_PROP_TAB_SIZE_MODE,this.m_struct_obj.tab_size_mode); // Tab size setting mode this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_NUMBER,this.m_struct_obj.tab_page_number); // Tab index number this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_ROW,this.m_struct_obj.tab_page_row); // Tab row index this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_COLUMN,this.m_struct_obj.tab_page_column); // Tab column index this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MAXIMUM,this.m_struct_obj.progress_bar_maximum);// The upper bound of the range ProgressBar operates in this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM,this.m_struct_obj.progress_bar_minimum);// The lower bound of the range ProgressBar operates in this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STEP,this.m_struct_obj.progress_bar_step); // ProgressBar increment needed to redraw it this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE,this.m_struct_obj.progress_bar_style); // ProgressBar style this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,this.m_struct_obj.progress_bar_value); // Current ProgressBar value from Min to Max this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,this.m_struct_obj.progress_bar_marquee_speed); // Progress bar animation speed in case of Marquee style //--- 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 this.SetProperty(CANV_ELEMENT_PROP_DESCRIPTION,::CharArrayToString(this.m_struct_obj.descript));// Graphical element description this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE,::CharArrayToString(this.m_struct_obj.tooltip_title));// Tooltip title for the element this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT,::CharArrayToString(this.m_struct_obj.tooltip_text)); // Tooltip text for the element } //+------------------------------------------------------------------+
Jetzt wird das grafische Elementobjekt korrekt in einer Datei gespeichert und aus dieser wiederhergestellt.
Eine Blende, die entlang des Fortschrittsbalkens verläuft, kann die Form eines Parallelepipeds haben. Es handelt sich um ein schräges Quadrat, bei dem die oberen Eckpunkte der Fläche um 6 Pixel von den unteren Eckpunkten der Fläche versetzt sind. Bei einem kleinen Objekt reicht dieser Versatz aus, um das Objekt ziemlich schräg aussehen zu lassen. Doch mit zunehmender Höhe wird die Neigung, die starr auf sechs Pixel festgelegt ist, ununterscheidbar. Um diese Situation zu korrigieren, müssen wir die Neigung zu einem relativen Wert machen - je höher das Objekt, desto stärker die Neigung. Um also die Größe des Versatzes der Scheitelpunkte festzulegen, verwenden wir die Höhe des Objekts - dann wird die Neigung visuell 45 Grad betragen.
In \MQL5\Include\DoEasy\Objects\Graph\WForms\GlareObj.mqh, in der Methode, die die Form des Objekts Glare in Form eines Parallelogramms zeichnet, fixieren wir die Initialisierung der Parameter der Scheitelpunktkoordinaten. Anstelle der Zahl 6 weisen wir den Wert der Höhe des grafischen Objekts zu:
//+------------------------------------------------------------------+ //| Draw the shape of the object glare as a parallelogram | //+------------------------------------------------------------------+ void CGlareObj::DrawFigureParallelogram(void) { int array_x[]={this.Height(),this.Width()-1,this.Width()-1-this.Height(),0}; int array_y[]={0,0,this.Height()-1,this.Height()-1}; CGCnvElement::DrawPolygonFill(array_x,array_y,this.m_color,this.OpacityDraw()); CGCnvElement::Update(); } //+------------------------------------------------------------------+
Jetzt werden die Scheitelpunkte um den Wert der Höhe des Objekts versetzt und die Neigung beträgt immer etwa 45 Grad, unabhängig von der Objekthöhe.
Ich kann verschiedene Optionen verwenden, um einen Fortschrittsbalken im Stil von „Segmentierten Blöcken“ zu erstellen — von der direkten Erstellung jedes Blocks bis hin zum einfachen Zeichnen der Blöcke. Ich werde dies wie folgt tun. Ich habe bereits einen vollständig gefüllten Fortschrittsbalken, und ich muss den Hintergrund dieses Objekts nur an den Stellen löschen, an denen keine Blöcke vorhanden sind. In diesem Fall erhalte ich das Aussehen eines Fortschrittsbalkens, der aus segmentierten Blöcken besteht. Der Nachteil dieses Ansatzes ist, dass die Lage jedes Blocks berechnet werden muss. Der Vorteil dieses Ansatzes liegt in der Einfachheit seiner Umsetzung.
Im privaten Abschnitt in \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\BarProgressBar.mqh fügen wir die Variablen für die Speicherung von Segmentparametern hinzu und deklarieren die Methode für die Hintergrundsegmentierung des Objekts:
//+------------------------------------------------------------------+ //| BarProgressBar object class of the ProgressBar control | //+------------------------------------------------------------------+ class CBarProgressBar : public CWinFormBase { private: int m_segment_s; // Segment countdown start int m_segment_x; // Last segment X coordinate int m_segment_w; // Segment width int m_segment_d; // Distance between segments //--- Segment the background void Segmentation(void); //--- (1) Set and (2) return a pause before displaying the effect void SetShowDelay(const long delay) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY,delay); } ulong ShowDelay(void) { return this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY); } //--- Initialize the properties void Initialize(void); protected: //--- Protected constructor with object type, chart ID and subwindow CBarProgressBar(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); public:
Die deklarierten Variablen enthalten die Anfangsparameter, aus denen die Lage der Segmente berechnet werden kann. Die Segmentbreite beträgt immer 3/4 der Höhe, und der Abstand zwischen den Segmenten wird aus der resultierenden Segmentbreite berechnet. Diese Daten werden bei der Initialisierung des Objekts aufgezeichnet und können dann verwendet werden, um die Position eines beliebigen Segments anhand seiner Nummer zu berechnen. Da wir nicht die Segmente selbst zeichnen, sondern die Abstände zwischen ihnen, ist der Ausgangspunkt die Breite des ersten Segments, entweder von Null oder von Eins an gerechnet. Wenn die Höhe des Fortschrittsbalkens mehr als drei Pixel beträgt, sollte auf allen Seiten ein Leerraum von einem Pixel um den Rand des Objekts herum gezeichnet werden. Dadurch werden die Segmente vom äußeren Rand des Balkens getrennt, sodass sie zu optisch unabhängigen Einheiten werden. In diesem Fall sollte der Einzug des ersten Segments bei 1 beginnen, d. h. bei einem Leerraum von einem Pixel zwischen dem Rand des Objekts und dem ersten Segment. Wenn die Höhe des Fortschrittsbalkens drei Pixel oder weniger beträgt, brauchen wir keinen leeren Raum zu zeichnen - er nimmt den gesamten nutzbaren Bereich des Objekts ein, auf dem die Segmente gezeichnet werden. In diesem Fall sollte der Einzug zum Beginn des ersten Segments Null sein.
Im öffentlichen Teil der Klasse implementieren wir die Methode, die den Stil des Fortschrittsbalkens zurückgibt, und die Methoden, die die Werte der variablen Parameter der Segmente zurückgeben. Deklarieren wir die Methoden zur Berechnung der Breite des Segments und des Abstands zwischen ihnen. Ich werde auch die virtuellen Methoden zum Löschen des Objekthintergrunds neu definieren müssen:
public: //--- Set the (1) animation speed in case of Marquee style, (2) display style, (3) increment value and (4) the current value of the ProgressBar control void SetMarqueeAnimationSpeed(const int value) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,value); } void SetStyle(const ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE style) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE,style); } void SetStep(const int value) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STEP,value); } void SetValue(const int value) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,value); } //--- Return the display style ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE Style(void) const { return (ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE); } //--- Return (1) the X coordinate of the last segment, (2) segment width, (3) distance between segments and (4) segment countdown start int SegmentX(void) const { return this.m_segment_x; } int SegmentWidth(void) const { return this.m_segment_w; } int SegmentDistance(void) const { return this.m_segment_d; } int SegmentStart(void) const { return this.m_segment_s; } //--- Calculate (1) the segment width and (2) the distance between segments int CalculateSegmentWidth(void); int CalculateSegmentDistance(const int width); //--- Supported object properties (1) integer, (2) real and (3) string ones virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_STRING property) { return true; } //--- 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); //--- Constructor CBarProgressBar(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); //--- Timer virtual void OnTimer(void); }; //+------------------------------------------------------------------+
Bei den Clearing-Methoden wird der Hintergrund des Elements mit seiner Hintergrundfarbe gefüllt. Dementsprechend muss nach dem Auffüllen der Hintergrund aus den Lücken zwischen den Segmenten entfernt werden. In diesen Methoden wird die im privaten Abschnitt deklarierte Methode zur Segmentierung des gezeichneten Objekthintergrunds aufgerufen. Da sie virtuell sind, werden diese Methoden immer aufgerufen, wenn die Reinigungsmethode aufgerufen wird, sofern es sich bei dem Objekt um einen Fortschrittsbalken oder dessen Nachfolger handelt.
Geben wir in der Initialisierungsmethode der Objekteigenschaften die Standardwerte für die Variablen ein, die die Segmentierungsparameter speichern. Die X-Koordinate des letzten Segments und der Start des Countdowns werden auf Null gesetzt, während die Segmentbreite und der Abstand zwischen den Segmenten sofort berechnet werden:
//+---------------------------------------------+ //| Initialize the properties | //+---------------------------------------------+ void CBarProgressBar::Initialize(void) { this.SetPaddingAll(0); this.SetMarginAll(0); this.SetBorderSizeAll(0); this.SetBackgroundColor(CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR,true); this.SetBorderColor(CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR,true); this.SetForeColor(CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR,true); this.SetShowDelay(2000); this.m_segment_x=0; this.m_segment_s=0; this.m_segment_w=this.CalculateSegmentWidth(); this.m_segment_d=this.CalculateSegmentDistance(this.m_segment_w); } //+------------------------------------------------------------------+
Betrachten wir die deklarierten Methoden im Detail.
Die Methode, die ein Element mit Farbe und Deckkraft versieht:
//+------------------------------------------------------------------+ //| Clear the element filling it with color and opacity | //+------------------------------------------------------------------+ void CBarProgressBar::Erase(const color colour,const uchar opacity,const bool redraw=false) { //--- Fill the element having the specified color and the redrawing flag CGCnvElement::EraseNoCrop(colour,opacity,false); //--- Segment the background this.Segmentation(); //--- If the object has a frame, draw it if(this.BorderStyle()!=FRAME_STYLE_NONE) this.DrawFormFrame(this.BorderSizeTop(),this.BorderSizeBottom(),this.BorderSizeLeft(),this.BorderSizeRight(),this.BorderColor(),this.Opacity(),this.BorderStyle()); //--- Crop the excess and update the element with the specified redraw flag this.Crop(); this.Update(redraw); } //+------------------------------------------------------------------+
Hier wird zunächst der gesamte Hintergrund des Elements gefüllt. Die Segmentierungsmethode heißt dann, den Hintergrund an den Stellen des Objekts zu löschen, an denen es keine Segmente geben soll. Wenn das Objekt einen Rahmen hat, wird es gezeichnet. Die Teile des Objekts, die über den übergeordneten Container hinausragen, werden abgeschnitten, und der Hintergrund des Objekts wird mit dem an die Methode übergebenen Flag für das Neuzeichnen der Karte aktualisiert.
Die Methode, die ein Element mit einem Farbverlaufsfüllung versieht:
//+---------------------------------------------+ //| Clear the element with a gradient fill | //+---------------------------------------------+ void CBarProgressBar::Erase(color &colors[],const uchar opacity,const bool vgradient,const bool cycle,const bool redraw=false) { //--- Fill the element having the specified color array and the redrawing flag CGCnvElement::EraseNoCrop(colors,opacity,vgradient,cycle,false); //--- Segment the background this.Segmentation(); //--- If the object has a frame, draw it if(this.BorderStyle()!=FRAME_STYLE_NONE) this.DrawFormFrame(this.BorderSizeTop(),this.BorderSizeBottom(),this.BorderSizeLeft(),this.BorderSizeRight(),this.BorderColor(),this.Opacity(),this.BorderStyle()); //--- Crop the excess and update the element with the specified redraw flag this.Crop(); this.Update(redraw); } //+------------------------------------------------------------------+
Die Logik der Methode ist identisch mit der Logik der obigen Methode, außer dass nicht eine einzelne Farbe an die Methode übergeben wird, sondern das Farbfeld der Farbverlaufsfüllung und dessen Richtungsflag — vertikal/horizontal und zyklisch.
Die Methode zur Berechnung der Segmentbreite:
//+---------------------------------------------+ //| Calculate the segment width | //+---------------------------------------------+ int CBarProgressBar::CalculateSegmentWidth(void) { int w=(int)::ceil((this.Height()-2)/1.75); return(w>3 ? w : 3); } //+------------------------------------------------------------------+
Die Breite eines jeden Segments sollte 2/3 seiner Höhe betragen. Diese Methode berechnet die Breite des Segments auf der Grundlage der Höhe des Fortschrittsbalkenobjekts. Nehmen wir die Höhe des Objekts minus zwei Pixel. In den meisten Fällen wird die Höhe des Fortschrittsbalkens mehr als drei Pixel betragen, was bedeutet, dass auf jeder Seite des Fortschrittsbalkens entlang seines Umfangs ein freies Feld von einem Pixel gezeichnet wird, was die sichtbare Höhe des Segments um zwei Pixel reduziert (eines oben und eines unten). Die resultierende Höhe wird durch 1,75 geteilt, was ein Seitenverhältnis von 3/4 ergibt. Wenn die resultierende Breite weniger als drei Pixel beträgt, ist die Breite gleich drei Pixel, da zu kleine Segmente mit einer Breite von 1-2 Pixeln schlecht aussehen.
Die Methode, mit der der Abstand zwischen den Segmenten berechnet wird:
//+---------------------------------------------+ //| Calculate the distance between segments | //+---------------------------------------------+ int CBarProgressBar::CalculateSegmentDistance(const int width) { int d=(int)::ceil(width/6); return(d<1 ? 1 : d); } //+------------------------------------------------------------------+
Hier ist alles ganz einfach. Die Methode erhält die Breite, aus der der Einzug berechnet werden soll. Der Abstand zwischen den Segmenten sollte sechsmal kleiner sein als die Breite des Blocks, aber nicht weniger als ein Pixel betragen.
Methode der Hintergrundsegmentierung:
//+---------------------------------------------+ //| Segment the background | //+---------------------------------------------+ void CBarProgressBar::Segmentation(void) { //--- If the drawing style is not "Segmented blocks", leave if(this.Style()!=CANV_ELEMENT_PROGRESS_BAR_STYLE_BLOCKS) return; //--- Reset the X coordinate of the segment this.m_segment_x=0; //--- Get the block width as 3/4 of its height int w=this.SegmentWidth(); //--- Get the distance between the segments (six times less than the block width) int d=this.SegmentDistance(); //--- Get the countdown start this.m_segment_s=w+(this.Height()>3 ? 1 : 0); //--- In the loop from the beginning of the countdown to the width of the progress bar with a step in the block width + indent between segments for(int i=this.SegmentStart();i<this.Width();i+=w+d) { //--- draw an empty fully transparent rectangle (erasing the element background) this.DrawRectangleFill(i,0,i+d-1,this.Height()-1,CLR_CANV_NULL,0); //--- Store the X coordinate of the segment this.m_segment_x=i; } //--- If the height of the progress line is more than three pixels, draw a completely transparent frame around the perimeter if(this.Height()>3) this.DrawRectangle(0,0,this.Width()-1,this.Height()-1,CLR_CANV_NULL,0); } //+------------------------------------------------------------------+
Die Methodenlogik wird in den Codekommentaren beschrieben. Wenn der Stil des Fortschrittsbalkens „Segmentierte Blöcke“ ist, gehen wir in einer Schleife den gesamten Hintergrund des Objekts durch und löschen den Hintergrund dort, wo es keine Segmente geben sollte. Wenn die Höhe des Objekts mehr als drei Pixel beträgt, löschen wir zusätzlich den Hintergrund entlang des Umfangs mit einem ein Pixel breiten Rand, sodass die Segmente von den Rändern des Fortschrittsbalkens getrennt werden.
Fügen wir im Objekt ProgressBar die Möglichkeit hinzu, eine Beschreibung auf dem Fortschrittsbalken anzuzeigen. Standardmäßig wird die Beschreibung nicht angezeigt, aber es reicht aus, ihren Text zu definieren, um sie zu aktivieren. Die Beschreibung wird durch ein CLabel-Objekt erstellt, das dauerhaft mit dem Objekt verbunden ist. Natürlich kann man beliebig viele solcher Objekte erstellen und sie an den richtigen Stellen platzieren. Das Objekt zur Beschreibung des Fortschrittsbalkens wird jedoch standardmäßig erstellt, wenn der Fortschrittsbalken erstellt wird, und der Zugriff darauf wird durch spezielle Methoden erleichtert.
In der Klassendatei \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\ProgressBar.mqh von CProgressBar entfernen wir die Variable zum Speichern der Anzahl der übersprungenen Schritte aus dem privaten Abschnitt, da sie nicht benötigt wurde:
//+------------------------------------------------------------------+ //| ArrowLeftRightBox object class of WForms controls | //+------------------------------------------------------------------+ class CProgressBar : public CContainer { private: int m_progress_bar_max; // Maximum progress bar width int m_value_by_max; // Value relative to Maximum int m_steps_skipped; // Number of skipped steps of increasing the width of the progress bar //--- Create a new graphical object
Außerdem deklarieren wir im privaten Abschnitt die Variablen zum Speichern von Textlabel-Eigenschaften mit der Beschreibung des Fortschrittsbalkens:
//+------------------------------------------------------------------+ //| ArrowLeftRightBox object class of WForms controls | //+------------------------------------------------------------------+ class CProgressBar : public CContainer { private: int m_progress_bar_max; // Maximum progress bar width int m_value_by_max; // Value relative to Maximum int m_progress_bar_text_x; // X coordinate of the text label with the description of the progress bar int m_progress_bar_text_y; // Y coordinate of the text label with the description of the progress bar color m_progress_bar_text_color; // Color of the text describing the progress bar uchar m_progress_bar_text_opacity; // Opacity of the text describing the progress bar string m_progress_bar_text; // Text describing the progress bar ENUM_FRAME_ANCHOR m_progress_bar_text_anchor; // Method for binding the text with a progress bar description //--- Create a new graphical object
Wir benötigen die Variablen, um die Eigenschaften des Textlabel-Objekts, das als Beschreibung des Fortschrittsbalkens dient, zu setzen und zurückzugeben.
Die in der Beschreibungszeile angezeigten Daten können entweder aktuell sein und jeden Schritt der Ausführung anzeigen oder als Prozentsatz der bereits abgeschlossenen Schritte angegeben werden.
Implementieren wir im öffentlichen Teil der Klasse die Methoden, die Value als Text und als Prozentsatz in numerischer und Textform zurückgeben:
//--- (1) Set and (2) return the current value of the progress bar in the range from Min to Max as a number and (3) as a text void SetValue(const int value); int Value(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE); } string ValueDescription(void) const { return (string)this.Value(); } //--- Return the current progress bar value in the range from Min to Max as a percentage in the form of (1) a number and (2) a text double ValuePercent(void) const; string ValuePercentDescription(void) const { return ::DoubleToString(this.ValuePercent(),2)+"%"; } //--- (1) Set and (2) return the upper bound of the ProgressBar operating range
Um einen vereinfachten Zugriff auf das Glare-Objekt zu erhalten, deklarieren wir die Methoden zum Festlegen seiner Eigenschaften sowie die Methoden zum Abrufen der Zeiger auf die erstellten angehängten Objekte im öffentlichen Abschnitt der Klasse und deklarieren die Methoden zur Handhabung des Objekts zur Beschreibung des Fortschrittsbalkens:
//--- (1) Set and (2) return the lower bound of the ProgressBar operating range void SetMinimum(const int value) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM,value); } int Minimum(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM); } //--- Set (1) style, (2) opacity and (3) color for the glare object void SetGlareStyle(const ENUM_CANV_ELEMENT_VISUAL_EFF_STYLE style); void SetGlareOpacity(const uchar opacity); void SetGlareColor(const color clr); //--- Return the pointer to the (1) progress bar object, (2) glare object and (3) the text label object with the progress bar description CBarProgressBar *GetProgressBar(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR,0); } CGlareObj *GetGlareObj(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ,0); } CLabel *GetProgressDescriptionObj(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_LABEL,0); } //--- Set the (1) text, (2) color //--- (3) opacity, (4) X, (5) Y coordinates, (6) font, (7) size and (8) font flags to the progress bar text label void SetBarDescriptionText(const string text,const bool redraw=false); void SetBarDescriptionColor(const color clr,const bool redraw=false,const bool set_init_color=false); void SetBarDescriptionOpacity(const uchar opacity,const bool redraw=false); void SetBarDescriptionX(const int x,const bool redraw=false); void SetBarDescriptionY(const int y,const bool redraw=false); void SetBarDescriptionFontName(const string font,const bool redraw=false); void SetBarDescriptionFontSize(const int size,const bool relative=false,const bool redraw=false); void SetBarDescriptionFontFlags(const uint flags,const bool redraw=false); //--- (1) hide and (2) display the progress bar text label void HideBarDescription(void); void ShowBarDescription(void); //--- Resets the progress bar values to the set minimum
Im Klassenkonstruktor initialisieren wir alle Variablen mit Standardwerten:
//+---------------------------------------------+ //| Initialize the element properties | //+---------------------------------------------+ void CProgressBar::Initialize(void) { this.SetBorderSizeAll(1); this.SetBorderStyle(FRAME_STYLE_SIMPLE); this.SetBackgroundColor(CLR_DEF_CONTROL_PROGRESS_BAR_BACK_COLOR,true); this.SetBorderColor(CLR_DEF_CONTROL_PROGRESS_BAR_BORDER_COLOR,true); this.SetForeColor(CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR,true); this.SetMarqueeAnimationSpeed(10); this.SetMaximum(100); this.SetMinimum(0); this.SetValue(50); this.SetStep(10); this.SetStyle(CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS); this.m_progress_bar_max=this.Width()-this.BorderSizeLeft()-this.BorderSizeRight(); this.m_value_by_max=this.Value()*100/this.Maximum(); this.m_progress_bar_text=""; this.m_progress_bar_text_x=1; this.m_progress_bar_text_y=0; this.m_progress_bar_text_color=CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR; this.m_progress_bar_text_opacity=255; this.m_progress_bar_text_anchor=FRAME_ANCHOR_LEFT_TOP; } //+------------------------------------------------------------------+
In der Methode, die das Fortschrittsbalkenobjekt erstellt, wird auch ein Blendenobjekt erstellt. Dort fügen wir auch das Objekt zur Beschreibung des Fortschrittsbalkens hinzu und erstellen es:
//+---------------------------------------------+ //| Create the progress bar object | //+---------------------------------------------+ void CProgressBar::CreateProgressBar(void) { //--- Set the length of the progress bar equal to the object Value() //--- The height of the progress bar is set equal to the height of the object minus the top and bottom border sizes int w=this.CalculateProgressBarWidth(); int h=this.Height()-this.BorderSizeTop()-this.BorderSizeBottom(); if(h<1) h=1; //--- Create the progress bar object this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR,0,0,w,h,clrNONE,255,false,false); //--- Create a description of the progress bar, get the text label object and set the default parameters this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_LABEL,1,0,this.Width()-2,this.Height()-2,clrNONE,0,false,false); CLabel *obj=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_LABEL,0); if(obj!=NULL) { obj.SetText(this.m_progress_bar_text); obj.SetFontName(DEF_FONT); obj.SetFontSize(DEF_FONT_SIZE); obj.SetTextAnchor(FRAME_ANCHOR_LEFT_TOP); obj.SetTextAlign(ANCHOR_LEFT_UPPER); this.HideBarDescription(); } //--- Create the glare object this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ,0,0,w,h,CLR_CANV_NULL,0,true,false); //--- Add the current CProgressBar object to the list of active elements of the collection this.AddObjToListActiveElements(); } //+------------------------------------------------------------------+
Unmittelbar nach der Erstellung der Textbeschriftung holen wir uns den Zeiger auf dieses Objekt und legen einige Eigenschaften dafür fest: Text, Schriftart, Schriftgröße, Verankerungsmethode und Textausrichtung, und blenden dann das erstellte Objekt aus. Die übrigen Parameter des Objekts können später ermittelt werden, indem der Zeiger auf dieses Objekt mit der Methode GetProgressDescriptionObj() abgerufen wird und dann die erforderlichen Eigenschaften auf das bereits erhaltene Objekt gesetzt werden.
Wenn wir versuchen, das Fortschrittsbalkenobjekt mit einer Höhe von weniger als einem Pixel zu erstellen, wird dies nicht funktionieren, da das Objekt nicht mit einer Größe von Null erstellt werden kann. Wir führen also eine Prüfung der Größe auf Null ein und passen sie an, falls die Prüfung positiv ausfällt.
In der Methode zur Erstellung eines neuen grafischen Objekts fügen wir den Codeblock zur Erstellung eines Text Label-Objekts hinzu:
//+---------------------------------------------+ //| Create a new graphical object | //+---------------------------------------------+ CGCnvElement *CProgressBar::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int obj_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity) { CGCnvElement *element=NULL; switch(type) { case GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR : element=new CBarProgressBar(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ : element=new CGlareObj(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_LABEL : element=new CLabel(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; default: break; } if(element==NULL) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),this.TypeElementDescription(type)); return element; } //+------------------------------------------------------------------+
Jetzt kann das ProgressBar-Objekt gebundene Objekte der Typen Progress Bar, Blande (Glare) und Text Label erstellen.
Das Objekt Fortschrittsbalken ist das aktive Steuerelement, das im Timer behandelt wird. Im Moment ist der Timer mit einer Blende versehen, die sich entlang des Fortschrittsbalkens erstreckt. Der Fortschrittsbalken, der im Marquee-Stil angezeigt wird, muss auch im Timer behandelt werden. In diesem Modus hat der Fortschrittsbalken eine feste Breite, die der halben Breite des gesamten Objekts entspricht, und scrollt ständig innerhalb des ProgressBar-Objekts, wodurch der Fortschritt des Prozesses angezeigt wird, dessen Anzahl der Iterationen nicht im Voraus bekannt ist.
Fügen wir die folgende Behandlung des Fortschrittsbalkens zum Objekt Timer Handler hinzu:
//+---------------------------------------------+ //| Timer | //+---------------------------------------------+ void CProgressBar::OnTimer(void) { CBarProgressBar *bar=this.GetProgressBar(); if(bar!=NULL) { if(bar.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE) { int x=bar.CoordX()+8; if(x>this.RightEdge()) x=this.CoordX()-bar.Width(); bar.Move(x,bar.CoordY()); bar.Redraw(true); } else bar.OnTimer(); } } //+------------------------------------------------------------------+
Wenn der Anzeigestil des Fortschrittsbalkens „Kontinuierlicher Bildlauf“ ist, erhalten wir hier die X-Koordinate, zu der das Objekt verschoben werden muss. Im Moment fügen wir der aktuellen X-Koordinate einen Versatz von 8 Pixeln hinzu und verschieben den Fortschrittsbalken horizontal an die neue Koordinate. Zunächst prüfen wir, ob sich das Objekt des Fortschrittsbalkens vollständig außerhalb seines Containers auf der rechten Seite befindet - in diesem Fall stellen wir seine X-Koordinate so ein, dass sich das Objekt mit dem Wert seiner Breite auf der linken Seite über den linken Rand seines Containers hinaus befindet. Die Methode Redraw() zeichnet das Objekt nicht nur neu, sondern hat noch eine weitere Funktion: Sie schneidet die Teile des Objekts ab, die über die Kanten des Containers hinausragen. Wir haben einen vollständigen Zyklus geschaffen, bei dem der Fortschrittsbalken innerhalb seines Containers verschoben wird, und gleichzeitig werden die Teile, die über die Ränder hinausragen, abgeschnitten.
Wenn das Objekt einen anderen Rendering-Stil hat, rufen wir den Timer des Fortschrittsbalken-Objekts auf, um das Blenden-Objekt anzuzeigen.
Da wir jetzt einen Fortschrittsbalken mit dem Zeichenstil „Segmentierte Blöcke“ haben, müssen wir die Methode, die den Wert des Fortschrittsbalkens festlegt, verfeinern. Gegenwärtig ändert diese Methode nach dem Setzen des Wertes sofort die Größe des Objekts entsprechend dem neuen Wert. Da segmentierte Blöcke jedoch nicht Pixel für Pixel, sondern Block für Block gezeichnet werden sollen, müssen wir wissen, wie viele Blöcke auf die festgelegte Breite des Fortschrittsbalkens passen. Wenn die Breite ausreicht, um ein neues Segment zu zeichnen, dann ändert das Objekt seine bereits in seiner Eigenschaft eingestellte Breite. Wenn die Breite nicht ausreicht (das aktuelle Zeichnungssegment wird unvollständig und abgeschnitten), müssen wir die Breite eines Segments von der eingestellten Breite des Objekts abziehen und genau diese Breite für den Fortschrittsbalken festlegen. In diesem Fall wird nur das vorletzte Segment mit allen vorherigen Segmenten gezogen. Die Objektbreite ändert sich also immer nur dann, wenn alle Segmente vollständig gezeichnet werden können, ohne sie zu beschneiden, wodurch sich die sichtbare Breite des Fortschrittsbalkens Block für Block ändert. In diesem Fall wird der Wert immer derjenige sein, der an das Objekt übergeben wurde. Mit anderen Worten, wir ändern die Breite des Objekts nur diskret, und der darin enthaltene Wert ist immer der, der dafür eingestellt ist.
Ich werde die oben beschriebenen Verbesserungen an der Methode implementieren, die den aktuellen Wert des Fortschrittsbalkens festlegt:
//+---------------------------------------------+ //| Set the current value of the progress bar | //+---------------------------------------------+ void CProgressBar::SetValue(const int value) { //--- Correct the value passed to the method and set it to the object property int v=(value<this.Minimum() ? this.Minimum() : value>this.Maximum() ? this.Maximum() : value); this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,v); //--- Get the progress bar object CBarProgressBar *bar=this.GetProgressBar(); if(bar!=NULL) { //--- Set 'value' for the progress bar bar.SetValue(v); //--- Calculate the width of the progress bar object int w=this.CalculateProgressBarWidth(); //--- If the calculated width is greater than the maximum possible value, set the maximum width if(w>this.m_progress_bar_max) w=this.m_progress_bar_max; //--- If the width is less than 1, then if(w<1) { //--- hide the progress bar and redraw the chart to display changes immediately bar.Hide(); ::ChartRedraw(bar.ChartID()); } //--- If the width value is not less than 1 else { //--- If the progress bar is hidden, display it and if(!bar.IsVisible()) bar.Show(); //--- If the style of the progress bar is "Continuous line", change the width of the object to the calculated value if(this.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS) bar.Resize(w,bar.Height(),true); //--- Otherwise, if the progress bar style is "Segmented blocks" else if(this.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_BLOCKS) { //--- Segment width including indent int wd=bar.SegmentWidth()+bar.SegmentDistance(); //--- The number of segments that fit the width of the progress bar int num=w/(wd>0 ? wd : 1); //--- The X coordinate of the last segment calculated from the beginning of the segment count int wx=bar.SegmentStart()+num*wd; //--- If the calculated width of the progress bar is less than the coordinate of the last segment, and this is not the last segment, //--- set the width of the progress bar equal to the penultimate segment coordinate if(w<wx-bar.SegmentDistance() && w<this.m_progress_bar_max) w=wx-wd+bar.SegmentDistance(); //--- If the calculated width of the progress bar is less than the coordinate of the last segment, or it is not the last segment, if(w<wx-bar.SegmentDistance() || w==this.m_progress_bar_max) //--- change the size of the progress bar in accordance with the received and adjusted width bar.Resize(w,bar.Height(),true); } } //--- If the progress bar description text is set, if(this.m_progress_bar_text!="") { //--- get the object description of the progress bar and bring it to the foreground CLabel *obj=this.GetProgressDescriptionObj(); if(obj!=NULL) obj.BringToTop(); } } } //+------------------------------------------------------------------+
Die Logik der Methode wird in den Codekommentaren beschrieben. Auch der Beschreibungstext muss behandelt werden: Jedes Mal, wenn sich der Wert des Fortschrittsbalkens ändert, muss sich möglicherweise auch die Beschreibung ändern. Daher wird dieses Objekt immer in den Vordergrund geholt, wenn es mit Text versehen ist.
Die Methode zur Berechnung der Breite des Fortschrittsbalkens muss verbessert werden, damit sie die Hälfte der Größe des ProgressBar-Steuerelements zurückgibt, wenn der Stil des Fortschrittsbalkens auf „Kontinuierliches Scrollen“ eingestellt ist:
//+---------------------------------------------+ //| Calculate the width of the progress bar | //+---------------------------------------------+ int CProgressBar::CalculateProgressBarWidth(void) { this.m_value_by_max=this.Value()*100/this.Maximum(); return(this.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE ? this.m_progress_bar_max/2 : this.m_progress_bar_max*this.m_value_by_max/100); } //+------------------------------------------------------------------+
Jetzt gibt die Methode die korrekte Größe der Bildlaufleiste für jeden ihrer Anzeigestile zurück.
In der Methode, die die neue Breite festlegt, müssen wir die im Objekt festgelegte Breite auch für das Textlabel-Objekt zuweisen, das zur Anzeige der Beschreibung des Fortschrittsbalkens verwendet wird:
//+---------------------------------------------+ //| Set a new width | //+---------------------------------------------+ bool CProgressBar::SetWidth(const int width) { if(!CGCnvElement::SetWidth(width)) return false; this.m_progress_bar_max=this.Width()-this.BorderSizeLeft()-this.BorderSizeRight(); CBarProgressBar *bar=this.GetProgressBar(); if(bar==NULL) return false; int w=this.CalculateProgressBarWidth(); bar.SetWidth(w); CLabel *lbl=this.GetProgressDescriptionObj(); if(lbl!=NULL) lbl.SetWidth(w); return true; } //+------------------------------------------------------------------+
Wenn die Größe des Textbeschriftungsobjekts nicht an die Größe des Fortschrittsbalkens angepasst ist, passt der in der scheinbaren Größe des Fortschrittsbalkens geschriebene Text möglicherweise nicht in ein Objekt, dessen Breite kleiner ist, als es visuell erscheint. Dies führt dazu, dass der Text einfach abgeschnitten wird. Daher müssen die Textbeschriftung und der Fortschrittsbalken die gleichen Abmessungen haben.
Schauen wir uns die Hilfsmethoden an, die dazu dienen, den Zugriff auf die Eigenschaften der an das ProgressBar-Steuerelement gebundenen Objekte zu erleichtern.
Die Methode, die den Stil für das Blendenobjekt festlegt:
//+---------------------------------------------+ //| Set the glare object style | //+---------------------------------------------+ void CProgressBar::SetGlareStyle(const ENUM_CANV_ELEMENT_VISUAL_EFF_STYLE style) { CGlareObj *obj=this.GetGlareObj(); if(obj==NULL) return; obj.SetVisualEffectStyle(style); } //+------------------------------------------------------------------+
Hier erhalten wir den Zeiger auf das Blendenobjekt und setzen den Stil auf das resultierende Objekt.
Die Methode, die die Deckkraft für ein Blendenobjekt festlegt:
//+---------------------------------------------+ //| Set the opacity of the highlight object | //+---------------------------------------------+ void CProgressBar::SetGlareOpacity(const uchar opacity) { CGlareObj *obj=this.GetGlareObj(); if(obj==NULL) return; obj.SetOpacity(opacity); } //+------------------------------------------------------------------+
Wir holen uns den Zeiger auf das Blendenobjekt und setzen den Deckkraftwert für das resultierende Objekt.
Die Methode, die die Farbe für das Blendenobjekt festlegt:
//+---------------------------------------------+ //| Set the color for the glare object | //+---------------------------------------------+ void CProgressBar::SetGlareColor(const color clr) { CGlareObj *obj=this.GetGlareObj(); if(obj==NULL) return; obj.SetColor(clr); } //+------------------------------------------------------------------+
Holt den Zeiger auf das Blendenobjekt und setzt den an die Methode übergebenen Farbwert auf das resultierende Objekt.
Die Methode, die einen Text für die Textbeschriftung des Fortschrittsbalkens festlegt:
//+------------------------------------------------------------------+ //| Set a text to the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionText(const string text,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text=text; obj.SetText(text); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
Hier erhalten wir den Zeiger auf das Textlabel-Objekt. Wir weisen den Text, der an die Methode übergeben wurde, der Variablen m_progress_bar_text zu. Dann weisen wir diesen Text dem Objekt zu. Da der Text sofort auf dem Objekt angezeigt wird, sollten der Hintergrund und alles, was darauf gezeichnet wurde, gelöscht werden, um zu vermeiden, dass sich ein Text mit einem anderen überschneidet. Anschließend zeigen wir den Text an und aktualisieren das Element.
Die Methode, die die Textfarbe des Fortschrittsbalkens auf die Textbeschriftung setzt:
//+------------------------------------------------------------------+ //| Set the text color of the progress bar to the text label | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionColor(const color clr,const bool redraw=false,const bool set_init_color=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text_color=clr; obj.SetForeColor(clr,false); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
Ermitteln des Zeigers auf das Textlabel-Objekt. Wir setzen die an die Methode übergebene Farbe in die Variable m_progress_bar_text_color. Dann legen wir die Farbe des Objekts als Textfarbe fest. Da der Text sofort angezeigt wird, wird der Hintergrund der Textbeschriftung gelöscht, um zu vermeiden, dass sich ein Text mit einem anderen überschneidet. Im weiteren Verlauf wird der Text angezeigt und das Element wird aktualisiert.
Die Methode, die die Deckkraft für die Textbeschriftung des Fortschrittsbalkens festlegt:
//+---------------------------------------------+ //| Set opacity to the progress bar text label | //+---------------------------------------------+ void CProgressBar::SetBarDescriptionOpacity(const uchar opacity,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text_opacity=opacity; obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
Die Logik der Methode ist identisch mit der obigen, aber wir setzen den Opazitätswert auf die entsprechende Variable und das Objekt.
Die Methode, die die X-Koordinate für die Textbeschriftung des Fortschrittsbalkens festlegt:
//+------------------------------------------------------------------+ //| Set the X coordinate to the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionX(const int x,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text_x=x; obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
Die Methode, die die Y-Koordinate für die Textbeschriftung des Fortschrittsbalkens festlegt:
//+------------------------------------------------------------------+ //| Set the Y coordinate to the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionY(const int y,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text_y=y; obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
Die Methode, die die Schriftart in der Textbeschriftung des Fortschrittsbalkens festlegt:
//+------------------------------------------------------------------+ //| Set the font in the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionFontName(const string font,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetFontName(font); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
Die Methode, die die Schriftgröße für die Textbeschriftung des Fortschrittsbalkens festlegt:
//+------------------------------------------------------------------+ //| Set the font size to the progress bar text label | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionFontSize(const int size,const bool relative=false,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetFontSize(size,relative); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
Die Methode, die die Schriftart-Flags in der Textbeschriftung des Fortschrittsbalkens setzt:
//+------------------------------------------------------------------+ //| Set the font flags in the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionFontFlags(const uint flags,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetFontFlags(flags); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
Alle oben gezeigten Methoden haben die gleiche Logik und ermöglichen es uns, die gewünschten Text- und Schriftparameter für die Beschreibung des Fortschrittsbalkens (für die Textbeschriftung) schnell festzulegen. Die Änderungen werden sofort auf dem Bildschirm angezeigt.
Wenn die Beschreibung des Fortschrittsbalkens ausgeblendet werden soll, muss das Objekt nicht nur ausgeblendet, sondern auch sein Nicht-Anzeigen-Flag gesetzt werden, da es ständig in den Vordergrund gebracht wird, was dazu führt, dass es angezeigt wird. Wenn wir nach dem Ausblenden des Objekts das Nicht-Anzeigen-Flag für das Objekt setzen, wird das Objekt nicht neu gezeichnet, bis es wieder das Anzeigen-Flag erhält.
Die Methode blendet die Textbeschriftung des Fortschrittsbalkens aus:
//+---------------------------------------------+ //| Hide the progress bar text label | //+---------------------------------------------+ void CProgressBar::HideBarDescription(void) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetDisplayed(false); obj.Hide(); } //+------------------------------------------------------------------+
Hier erhalten wir ein Text-Label-Objekt mit einer Beschreibung des Fortschrittsbalkens, setzen das Nicht-Anzeigen-Flag dafür und blenden das Objekt aus.
Die Methode, die die Textbeschriftung des Fortschrittsbalkens anzeigt:
//+---------------------------------------------+ //| Display a text label for the progress bar | //+---------------------------------------------+ void CProgressBar::ShowBarDescription(void) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetDisplayed(true); obj.Show(); } //+------------------------------------------------------------------+
Hier erhalten wir ein Text-Label-Objekt mit einer Beschreibung des Fortschrittsbalkens, setzen das Display-Flag dafür und zeigen das Objekt an.
Die Methode gibt den aktuellen Wert des Fortschrittsbalkens im Bereich von Min bis Max als Prozentwert zurück:
//+---------------------------------------------+ //| Return the current value of the progress bar| //| in the range from Min to Max as a percentage| //+---------------------------------------------+ double CProgressBar::ValuePercent(void) const { double range=this.Maximum()-this.Minimum(); return(this.Value()*100.0/(range>0 ? range : 1)); } //+------------------------------------------------------------------+
Wenn wir den Wert des Fortschrittsbalkens als Prozentsatz des Bereichs von Min bis Max benötigen, dann berechnet diese Methode den Wert, wie viele Prozent des angegebenen Bereichs bereits verarbeitet wurden, und gibt ihn zurück. 100% ist die Differenz zwischen dem Höchst- und dem Mindestwert, die im ProgressBar-Objekt eingestellt sind.
Überprüfen wir die Ergebnisse.
Test
Um den Test durchzuführen, verwende ich den EA aus dem vorherigen Artikel und speichere ihn in \MQL5\Experts\TestDoEasy\Part128\ als TestDoEasy128.mq5.
Wir erstellen eine Enumeration im Stil eines Fortschrittsbalkens für die Kompilierungsversionen in englischer und der Nutzersprache:
//--- enumerations by compilation language #ifdef COMPILE_EN enum ENUM_AUTO_SIZE_MODE { AUTO_SIZE_MODE_GROW=CANV_ELEMENT_AUTO_SIZE_MODE_GROW, // Grow AUTO_SIZE_MODE_GROW_SHRINK=CANV_ELEMENT_AUTO_SIZE_MODE_GROW_SHRINK // Grow and Shrink }; enum ENUM_BORDER_STYLE { BORDER_STYLE_NONE=FRAME_STYLE_NONE, // None BORDER_STYLE_SIMPLE=FRAME_STYLE_SIMPLE, // Simple BORDER_STYLE_FLAT=FRAME_STYLE_FLAT, // Flat BORDER_STYLE_BEVEL=FRAME_STYLE_BEVEL, // Embossed (bevel) BORDER_STYLE_STAMP=FRAME_STYLE_STAMP, // Embossed (stamp) }; enum ENUM_CHEK_STATE { CHEK_STATE_UNCHECKED=CANV_ELEMENT_CHEK_STATE_UNCHECKED, // Unchecked CHEK_STATE_CHECKED=CANV_ELEMENT_CHEK_STATE_CHECKED, // Checked CHEK_STATE_INDETERMINATE=CANV_ELEMENT_CHEK_STATE_INDETERMINATE, // Indeterminate }; enum ENUM_ELEMENT_ALIGNMENT { ELEMENT_ALIGNMENT_TOP=CANV_ELEMENT_ALIGNMENT_TOP, // Top ELEMENT_ALIGNMENT_BOTTOM=CANV_ELEMENT_ALIGNMENT_BOTTOM, // Bottom ELEMENT_ALIGNMENT_LEFT=CANV_ELEMENT_ALIGNMENT_LEFT, // Left ELEMENT_ALIGNMENT_RIGHT=CANV_ELEMENT_ALIGNMENT_RIGHT, // Right }; enum ENUM_ELEMENT_TAB_SIZE_MODE { ELEMENT_TAB_SIZE_MODE_NORMAL=CANV_ELEMENT_TAB_SIZE_MODE_NORMAL, // Fit to tab title text width ELEMENT_TAB_SIZE_MODE_FIXED=CANV_ELEMENT_TAB_SIZE_MODE_FIXED, // Fixed size ELEMENT_TAB_SIZE_MODE_FILL=CANV_ELEMENT_TAB_SIZE_MODE_FILL, // Fit TabControl Size }; enum ENUM_ELEMENT_PROGRESS_BAR_STYLE { ELEMENT_PROGRESS_BAR_STYLE_BLOCKS=CANV_ELEMENT_PROGRESS_BAR_STYLE_BLOCKS, // Blocks ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS=CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS, // Continuous ELEMENT_PROGRESS_BAR_STYLE_MARQUEE=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE, // Marquee }; #else enum ENUM_AUTO_SIZE_MODE { AUTO_SIZE_MODE_GROW=CANV_ELEMENT_AUTO_SIZE_MODE_GROW, // Increase only AUTO_SIZE_MODE_GROW_SHRINK=CANV_ELEMENT_AUTO_SIZE_MODE_GROW_SHRINK // Increase and decrease }; enum ENUM_BORDER_STYLE { BORDER_STYLE_NONE=FRAME_STYLE_NONE, // No frame BORDER_STYLE_SIMPLE=FRAME_STYLE_SIMPLE, // Simple frame BORDER_STYLE_FLAT=FRAME_STYLE_FLAT, // Flat frame BORDER_STYLE_BEVEL=FRAME_STYLE_BEVEL, // Embossed (convex) BORDER_STYLE_STAMP=FRAME_STYLE_STAMP, // Embossed (concave) }; enum ENUM_CHEK_STATE { CHEK_STATE_UNCHECKED=CANV_ELEMENT_CHEK_STATE_UNCHECKED, // Unchecked CHEK_STATE_CHECKED=CANV_ELEMENT_CHEK_STATE_CHECKED, // Checked CHEK_STATE_INDETERMINATE=CANV_ELEMENT_CHEK_STATE_INDETERMINATE, // Undefined }; enum ENUM_ELEMENT_ALIGNMENT { ELEMENT_ALIGNMENT_TOP=CANV_ELEMENT_ALIGNMENT_TOP, // Top ELEMENT_ALIGNMENT_BOTTOM=CANV_ELEMENT_ALIGNMENT_BOTTOM, // Bottom ELEMENT_ALIGNMENT_LEFT=CANV_ELEMENT_ALIGNMENT_LEFT, // Left ELEMENT_ALIGNMENT_RIGHT=CANV_ELEMENT_ALIGNMENT_RIGHT, // Right }; enum ENUM_ELEMENT_TAB_SIZE_MODE { ELEMENT_TAB_SIZE_MODE_NORMAL=CANV_ELEMENT_TAB_SIZE_MODE_NORMAL, // By tab title width ELEMENT_TAB_SIZE_MODE_FIXED=CANV_ELEMENT_TAB_SIZE_MODE_FIXED, // Fixed size ELEMENT_TAB_SIZE_MODE_FILL=CANV_ELEMENT_TAB_SIZE_MODE_FILL, // By TabControl size }; enum ENUM_ELEMENT_PROGRESS_BAR_STYLE { ELEMENT_PROGRESS_BAR_STYLE_BLOCKS=CANV_ELEMENT_PROGRESS_BAR_STYLE_BLOCKS, // Segmented blocks ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS=CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS, // Continuous bar ELEMENT_PROGRESS_BAR_STYLE_MARQUEE=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE, // Continuous scrolling }; #endif //--- input parameters
Wir fügen zwei neue Parameter zu den Eingaben hinzu — den Stil des Fortschrittsbalkens und das Flag für die Anzeige der Werte des Fortschrittsbalkens in Prozent:
//--- 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 = true ; // Button toggle flag sinput bool InpButtListMSelect = false; // ButtonListBox Button MultiSelect flag sinput bool InpListBoxMColumn = true; // ListBox MultiColumn flag sinput bool InpTabCtrlMultiline = false; // Tab Control Multiline flag sinput ENUM_ELEMENT_ALIGNMENT InpHeaderAlignment = ELEMENT_ALIGNMENT_TOP; // TabHeader Alignment sinput ENUM_ELEMENT_TAB_SIZE_MODE InpTabPageSizeMode = ELEMENT_TAB_SIZE_MODE_FILL; // TabHeader Size Mode sinput int InpTabControlX = 10; // TabControl X coord sinput int InpTabControlY = 20; // TabControl Y coord sinput ENUM_CANV_ELEMENT_TOOLTIP_ICON InpTooltipIcon = CANV_ELEMENT_TOOLTIP_ICON_NONE; // Tooltip Icon sinput string InpTooltipTitle = ""; // Tooltip Title sinput ENUM_ELEMENT_PROGRESS_BAR_STYLE InpProgressBarStyle= ELEMENT_PROGRESS_BAR_STYLE_BLOCKS; // Progress Bar Style sinput bool InpProgressBarPercent= false; // Show progress bar values as a percentage //--- global variables
In OnInit() des EA legen wir bei der Erstellung des ProgressBar-Steuerelements den Stil des Fortschrittsbalkens aus der Variable in den Einstellungen fest und setzen die Parameter zur Beschreibung des Fortschrittsbalkens:
//--- If this is the first tab and the second panel if(n==0 && j==1) { //--- Create the ProgressBar control on it if(split_container.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,4,4,100,12,clrNONE,255,false,false)) { CProgressBar *progress_bar=split_container.GetPanelElementByType(j,GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0); if(progress_bar!=NULL) { //--- Set the style of the progress bar specified in the EA settings progress_bar.SetStyle((ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE)InpProgressBarStyle); //--- Set the parameters for describing the progress bar progress_bar.SetBarDescriptionText("Progress Bar "); progress_bar.SetBarDescriptionColor(panel.BackgroundColor()); progress_bar.SetBarDescriptionOpacity(255); progress_bar.SetBarDescriptionY(-2); } } }
In der Schleife zum Anzeigen und Neuzeichnen aller Tafeln zeigen wir die Beschreibung an, wenn der Stil des Fortschrittsbalkens durchgehende Linie (Continuous) ist. Bei jeder Iteration der Schleife zur Erhöhung des Wertes des Fortschrittsbalkens zeigen wir die Werte in der Beschreibung an, je nach den Einstellungen - als Prozentsatz oder in abgeschlossenen Schritten. Nach Abschluss der Schleife schreiben wir in die Beschreibung des Fortschrittsbalkens eine Meldung über den Abschluss der Inkrementschleife, wobei die Schriftart auf fett geändert wird.
Um die Parameter des Glare-Objekts einzustellen, werde ich die Schnellzugriffsmethoden des Objekts verwenden:
//--- Display and redraw all created panels for(int i=0;i<FORMS_TOTAL;i++) { //--- Get the panel object pnl=engine.GetWFPanel("WinForms Panel"+(string)i); if(pnl!=NULL) { //--- display and redraw the panel pnl.Show(); pnl.Redraw(true); //--- Get the TabControl object from the panel CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0); //--- Get the SplitContainer object from the first tab of the TabControl object CSplitContainer *sc=tc.GetTabElementByType(0,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,0); //--- Get the second panel from the SplitContainer object CSplitContainerPanel *scp=sc.GetPanel(1); //--- Get the ProgressBar object from the received panel CProgressBar *pb=scp.GetElementByType(GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0); //--- Wait for 1/10 of a second Sleep(100); //--- Get the width of the ProgressBar object int w=pb.Width(); //--- In the loop, increase the width of the ProgressBar by 180 pixels with a delay of 1/50 for(int n=0;n<180;n++) { Sleep(20); pb.Resize(w+n,pb.Height(),true); } //--- Set the values for PerformStep of the ProgressBar object pb.SetValuesForProcessing(0,350,1,0); //--- Reset ProgressBar to minimum pb.ResetProgressBar(); //--- If the style of the progress bar is "Continuous line", display the progress bar description if(pb.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS) pb.ShowBarDescription(); //--- Wait for 1/5 second Sleep(200); //--- If the style of the progress bar is not "Continuous scrolling" if(pb.Style()!=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE) { //--- In the loop from the minimum to the maximum value of ProgressBar for(int n=0;n<=pb.Maximum();n++) { //--- call the method for increasing the progress bar by a given step with a wait of 1/5 second pb.PerformStep(); //--- Set the number of completed steps in the description of the progress bar pb.SetBarDescriptionText("Progress Bar, pass: "+(InpProgressBarPercent ? pb.ValuePercentDescription() : pb.ValueDescription())); Sleep(20); } } //--- Wait for 1/2 second, set the description font type to Bold and write a completion message on the progress bar Sleep(500); pb.SetBarDescriptionFontFlags(FW_BOLD); pb.SetBarDescriptionText("Progress Bar: Done"); //--- Set the glare object type - rectangle, opacity 40, color - white pb.SetGlareStyle(CANV_ELEMENT_VISUAL_EFF_STYLE_RECTANGLE); pb.SetGlareOpacity(40); pb.SetGlareColor(clrWhite); } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
Kompilieren Sie den EA und starten Sie ihn auf einem Chart:
Wie wir sehen können, funktionieren alle angegebenen Modi gut.
Was kommt als Nächstes?
Im nächsten Artikel werde ich mit der Entwicklung des Steuerelements der TrackBar beginnen.
*Vorherige Artikel in dieser Reihe:
DoEasy. Steuerung (Teil 26): Fertigstellung des ToolTip WinForms-Objekts und Weiterführung der ProgressBar-Entwicklung
DoEasy. Steuerung (Teil 27): Arbeiten am WinForms Objekt der ProgressBar
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/11823
- 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.