
DoEasy. Elementos de control (Parte 28): Estilos de barra en el control «ProgressBar»
Contenido
Concepto
El control ProgressBar que creamos para la biblioteca actualmente tiene un estilo para mostrar la barra de progreso: una línea continua (Continuous). No obstante, dicho control tiene dos estilos de visualización más: los bloques segmentados (Blocks) y el desplazamiento continuo de un bloque en un objeto (Marquee). Si con el estilo Blocks todo está claro (en lugar de una línea continua, se dibujan bloques ubicados por separado), el estilo Marquee, en cambio, se podrá usar si no conocemos de antemano la cantidad de iteraciones que deberán mostrarse visualmente usando el control ProgressBar. En este caso, durante la ejecución del objeto, un solo bloque igual a la mitad de la anchura de la barra de progreso se desplazará constantemente.
Además de crear estos dos nuevos estilos, añadiremos texto a la barra de progreso que se muestra dentro. El texto en sí se representará mediante un objeto normal de la clase CLabel de la biblioteca, y no estará vinculado al objeto de barra de progreso, sino al objeto de marca de agua, que será la base del control ProgressBar. El texto se representará dentro de un objeto de etiqueta de texto totalmente transparente con el tamaño de la anchura y la altura de la barra de progreso, y este objeto siempre estará en primer plano, siempre sobre todos los objetos en el control ProgressBar.
Por defecto, el texto no se mostrará en la barra de progreso, pero siempre se podrá añadir justo en el momento en que se ejecute un programa creado sobre la base de la biblioteca; solo deberemos especificar el texto a mostrar y sus atributos (fuente, tamaño, banderas de la fuente, color, opacidad, etc.)
Mejorando las clases de la biblioteca
Antes de comenzar a desarrollar nuevos estilos para el control ProgressBar, simplificaremos los constructores del elemento gráfico básico. En los constructores protegidos y paramétricos, tras crear un objeto, estableceremos los valores de sus propiedades. En ambos constructores, esta será una larga lista de más de cien parámetros diferentes para los elementos gráficos de biblioteca que se añadirán constantemente al crear nuevos objetos. Por consiguiente, deberemos escribir constantemente la configuración de las propiedades del objeto dos veces: en los constructores protegidos y en los constructores paramétricos de la clase CGCnvElement. Lo lógico sería sacar la configuración de todas estas propiedades a un método de inicialización aparte. Al mismo tiempo, si algunas propiedades deben configurarse de forma diferente en constructores distintos, simplemente las transmitiremos en los parámetros formales del nuevo método y las indicaremos en ellos.
En el archivo \MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqh, añadiremos a la estructura del objeto las nuevas propiedades:
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
La estructura del objeto gráfico será necesaria para escribir correctamente las propiedades del objeto en un archivo y leerlas desde este durante la restauración. Las propiedades ahora escritas en esta estructura ya las hemos añadido al objeto, pero aún no las hemos añadido a la estructura. Incluso si los campos de la estructura no coinciden con las propiedades del objeto, en esta etapa de desarrollo no habrá nada de qué preocuparse, ya que hasta ahora no hemos guardado el objeto en un archivo ni leído sus propiedades desde el mismo. Obviamente, más tarde guardaremos las propiedades de los objetos gráficos en un archivo y las leeremos desde allí, y luego realmente necesitaremos que los campos de la estructura coincidan totalmente con las propiedades del objeto.
En la sección privada de la clase, declararemos un nuevo método para inicializar las propiedades del elemento gráfico:
//--- 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:
Las propiedades del objeto creado se transmitirán al método, que tendrá diferentes valores en diferentes constructores, o se especificarán directamente en los constructores, en sus parámetros formales, es decir, se transmitirán desde el exterior. Después transmitiremos todas esas propiedades al método a través de sus parámetros.
En cada uno de los constructores, eliminaremos la larga lista de ajustes de las propiedades del objeto, reemplazándola con una llamada al método de inicialización:
//+------------------------------------------------------------------+ //| 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()); } } //+------------------------------------------------------------------+
Como podemos ver, en ambos constructores, los valores propios inherentes a cada constructor específico se transmiten al método de inicialización.
Luego trasladaremos al nuevo método de inicialización la configuración de propiedades eliminada de los constructores de clase:
//+------------------------------------------------------------------+ //| 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 } //+------------------------------------------------------------------+
Aquí simplemente hemos trasladado las líneas eliminadas de los constructores de clases. Los valores de propiedad que eran diferentes en distintos constructores ahora se transmitirán y establecerán en las propiedades del objeto usando los parámetros formales de los métodos.
En el método que crea la estructura del objeto, en los nuevos campos de la estructura, escribiremos un registro de los valores de las propiedades correspondientes del elemento gráfico:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
En el método que crea un objeto a partir de una estructura, escribiremos un registro de los valores de las propiedades del objeto a partir de los campos correspondientes de la estructura que hemos añadido hoy:
//+------------------------------------------------------------------+ //| 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 } //+------------------------------------------------------------------+
Ahora el objeto del elemento gráfico se guardará correctamente en un archivo y se restaurará desde el mismo.
El destello que recorre la barra de progreso puede tener la forma de un paralelepípedo. Este será rectángulo biselado con los vértices de la cara superior desplazados 6 píxeles desde los vértices de la cara inferior. Para un objeto pequeño, este desplazamiento será suficiente para que el objeto parezca bastante inclinado. Pero a medida que aumente su altura, el bisel, fijado rígidamente en seis píxeles, se volverá indistinguible. Para corregir esta situación, deberemos hacer que el bisel sea un valor relativo: cuanto más alto sea el objeto, más acusado será el bisel. Entonces, para establecer el tamaño del desplazamiento de los vértices, usaremos la altura del objeto; luego, visualmente, el bisel quedará a 45 grados.
En el archivo \MQL5\Include\DoEasy\Objects\Graph\WForms\GlareObj.mqh, en el método que dibuja la forma del destello de un objeto en forma de paralelogramo, corregiremos la inicialización de los parámetros de las coordenadas del vértice. En lugar del número 6, asignaremos el valor de la altura del objeto gráfico:
//+------------------------------------------------------------------+ //| 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(); } //+------------------------------------------------------------------+
Ahora los vértices estarán desplazados en el valor de la altura del objeto y el bisel siempre estará a unos 45 grados, independientemente de la altura del objeto.
Para crear un estilo de la barra de progreso "Bloques segmentados", podemos usar diferentes opciones, desde crear y dibujar directamente cada bloque hasta simplemente dibujarlos. Haremos esto: ya tenemos una barra de progreso completamente llena, y solo necesitaremos borrar el fondo de este objeto en aquellos lugares donde no haya bloques. Luego obtendremos la apariencia de una barra de progreso que constará de bloques segmentados. La desventaja de este enfoque es que se deberá calcular la ubicación de cada bloque. La ventaja de este enfoque es su simplicidad de implementación.
En el archivo \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\BarProgressBar.mqh, añadiremos las variables a la sección privada para almacenar los parámetros de los segmentos y declararemos un método para la segmentación del fondo del objeto:
//+------------------------------------------------------------------+ //| 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:
Las variables declaradas contendrán los parámetros iniciales a partir de los cuales se podrá calcular la ubicación de los segmentos. La anchura del segmento siempre será 3/4 de la altura, mientras que la distancia entre los segmentos se calculará a partir de la anchura del segmento resultante. Estos datos se registrarán al inicializarse el objeto, y luego se podrán usar para calcular la ubicación de cualquier segmento según su número. Como no estamos dibujando los segmentos en sí, sino los espacios entre ellos, el punto de partida será la anchura del primer segmento contado desde cero o desde uno. Si la altura de la barra de progreso es superior a tres píxeles, deberemos dibujar un espacio vacío de un píxel alrededor del borde del objeto en todos los lados. Esto separará los segmentos del borde exterior de la barra, convirtiéndolos en unidades visualmente independientes. En este caso, el rellenado del primer segmento deberá comenzar desde la unidad, es decir, habrá un espacio vacío de un píxel desde el borde del objeto hasta el primer segmento. Si la altura de la barra de progreso es de tres píxeles o menos, no necesitaremos dibujar un espacio vacío; este ocupará toda el área utilizable del objeto en el que se dibujan los segmentos. En este caso, la separación al comienzo del primer segmento deberá ser cero.
En la sección pública de la clase, escribiremos el método que retornará el estilo de la barra de progreso y los métodos que devolverán los valores de las variables de los parámetros de los segmentos, y también declararemos los métodos para calcular la anchura del segmento y la distancia entre ellos. También necesitaremos redefinir los métodos virtuales para eliminar el fondo del objeto:
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); }; //+------------------------------------------------------------------+
En los métodos de limpieza, colorearemos el fondo del elemento con su color de fondo. Como consecuencia, después de colorear, deberemos eliminar el fondo en aquellos lugares que supongan los espacios entre los segmentos. En estos métodos, llamaremos al método declarado en la sección privada para segmentar el fondo dibujado del objeto, y como son virtuales, siempre llamaremos a estos métodos al llamar al método de limpieza si el objeto es una barra de progreso o su sucesor.
En el método de inicialización de propiedades del objeto, introduciremos los valores predeterminados para las variables que almacenan los parámetros de segmentación. La coordenada X del último segmento y el inicio de la cuenta será igual a cero; a continuación, calcularemos directamente la anchura del segmento y la distancia entre ellos:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Vamos a echar un vistazo a los métodos declarados.
Método que limpia un elemento con rellenado de color y opacidad:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Aquí, en primer lugar, todo el fondo del elemento se pintará por completo, y luego llamaremos al método de segmentación, que borrará el fondo en aquellos lugares del objeto donde no debería haber segmentos. Además, si el objeto tiene un marco, este se dibujará; las partes del objeto que sobresalgan del contenedor principal se cortarán y el fondo del objeto se actualizará con el indicador de redibujado del gráfico transmitido al método.
Método que limpia el elemento con rellenado de gradiente:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
La lógica del método es idéntica a la lógica del método anterior, salvo que en lugar de transmitirse un solo color al método, se transmitirá un array de colores para el rellenado de gradiente y su indicador de dirección: vertical/horizontal y cíclico.
Método que calcula la anchura del segmento:
//+------------------------------------------------------------------+ //| Calculate the segment width | //+------------------------------------------------------------------+ int CBarProgressBar::CalculateSegmentWidth(void) { int w=(int)::ceil((this.Height()-2)/1.75); return(w>3 ? w : 3); } //+------------------------------------------------------------------+
La anchura de cualquier segmento deberá ser 2/3 de su altura. Este método calculará la anchura del segmento según la altura del objeto de la barra de progreso. Tomaremos la altura del objeto menos dos píxeles. Más a menudo, la altura de la barra de progreso será de más de tres píxeles, lo cual significará que se dibujará un espacio libre de un píxel a cada lado de la barra de progreso a lo largo de su perímetro, lo que reducirá la altura visible del segmento en dos píxeles (uno por encima y otro por debajo). La altura resultante se dividirá por 1,75, lo cual dará una relación de lados de 3/4. Si la anchura resultante es inferior a tres píxeles, la anchura será igual a tres píxeles, ya que los segmentos que tienen una altura demasiado pequeña se verán mal con una anchura de 1-2 píxeles.
Método que calcula la distancia entre segmentos:
//+------------------------------------------------------------------+ //| Calculate the distance between segments | //+------------------------------------------------------------------+ int CBarProgressBar::CalculateSegmentDistance(const int width) { int d=(int)::ceil(width/6); return(d<1 ? 1 : d); } //+------------------------------------------------------------------+
Aquí todo es simple: Primero transmitiremos al método la anchura a partir de la cual se deberá calcular la separación. La distancia entre los segmentos deberá ser seis veces inferior a la anchura del bloque, pero no inferior a un píxel.
Método de segmentación del fondo:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
La lógica del método se detalla en los comentarios al código. Si el estilo de la barra de progreso es "Bloques segmentados", entonces recorreremos en un ciclo todo el fondo del objeto y borraremos el fondo donde no tenga que haber segmentos. Si la altura del objeto es más de tres píxeles, también borraremos el fondo a lo largo del perímetro con un borde de un píxel de anchura, lo cual hará que los segmentos se separen de los bordes de la barra de progreso.
En el objeto ProgressBar, añadiremos la capacidad de incluir una descripción que se muestre en la barra de progreso. La descripción no se mostrará por defecto, pero para incluirla bastará con definir su texto. La descripción será construida por un objeto CLabel constantemente adjunto al objeto. Obviamente, podremos crear tantos objetos como deseemos y colocarlos en los lugares correctos. Pero el objeto de descripción de la barra de progreso se creará por defecto al crear ProgressBar, y será más fácil acceder a él mediante métodos especiales.
En el archivo de clase CProgressBar \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\ProgressBar.mqh, eliminaremos la variable de la sección privada para almacenar el número de pasos omitidos, ya que no era necesaria:
//+------------------------------------------------------------------+ //| 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
En el mismo lugar, en la sección privada, declararemos las variables para almacenar las propiedades de la etiqueta de texto con una descripción de la barra de progreso:
//+------------------------------------------------------------------+ //| 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
Asimismo, necesitaremos variables para establecer y retornar las propiedades del objeto de etiqueta de texto que actúa como una descripción de la barra de progreso.
Los datos que se muestran en la línea de descripción pueden ser los reales, mostrando cada paso de la ejecución, o bien como un porcentaje de los pasos ya completados.
En la sección pública de la clase, añadiremos los métodos que retornan el valor Value en una representación de texto y el valor Value como un porcentaje representado por valores numéricos y de texto:
//--- (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
Para acceder de forma simplificada al objeto de destello, en la sección pública de la clase, declararemos los métodos para establecer sus propiedades, añadiremos los métodos para obtener los punteros a los objetos adjuntos creadosy declararemos los métodos para trabajar con el objeto de descripción de la barra de progreso:
//--- (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
En el constructor de clases, inicializaremos las variables declaradas con los valores predeterminados:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
En el método que crea el objeto de barra de progreso, también crearemos un objeto resaltado. Entonces, añadiremos allí la creación de la descripción del objeto de barra de progreso:
//+------------------------------------------------------------------+ //| 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(); } //+------------------------------------------------------------------+
Inmediatamente después de crear la etiqueta de texto, obtendremos el puntero a este objeto y configuraremos algunas propiedades para él: el texto, el nombre de fuente, el tamaño de fuente, el método de anclaje y la alineación del texto, y luego ocultaremos el objeto creado. Los parámetros restantes del objeto se podrán obtener más tarde obteniendo el puntero a este objeto usando el método GetProgressDescriptionObj() y luego configurando las propiedades necesarias para el objeto ya recibido.
Si intentamos crear un objeto de barra de progreso con una altura inferior a un píxel, nada funcionará: el objeto no se podrá crear con un tamaño cero. Por lo tanto, introduciremos una verificación para el tamaño cero y lo corregiremos de ser así.
En el método que crea un nuevo objeto gráfico, añadiremos un bloque de código para crear el objeto de etiqueta de texto:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Ahora el objeto ProgressBar podrá crear objetos vinculados con los tipos «Barra de progreso», «Resaltado» y «Etiqueta de texto».
El objeto «Barra de progreso» será un control activo que se procesará en el temporizador. En este momento, el temporizador estará procesando un resaltado que se ejecutará a lo largo de la barra de progreso, pero también necesitaremos procesar en el temporizador la barra de progreso mostrada en el estilo "Marquee". En este modo, la barra de progreso tendrá una anchura fija igual a la mitad de la anchura del objeto completo, y se desplazará constantemente dentro del objeto ProgressBar, mostrando así el progreso de un proceso cuyo número de iteraciones no se conocerá de antemano.
Ahora añadiremos el siguiente procesamiento de la barra de progreso al manejador del temporizador del objeto:
//+------------------------------------------------------------------+ //| 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(); } } //+------------------------------------------------------------------+
Aquí, si el estilo de visualización de la barra de progreso es «Desplazamiento continuo», obtendremos la coordenada X en la que se debe desplazar el objeto. Por el momento, añadiremos un desplazamiento de 8 píxeles a la coordenada X actual y cambiaremos la barra de progreso a la nueva coordenada en horizontal. Primero verificaremos que el objeto de la barra de progreso esté completamente fuera de su contenedor a la derecha; en este caso, configuraremos su coordenada X para que el objeto tenga el valor de su anchura a la izquierda más allá del borde izquierdo de su contenedor. El método Redraw(), además de redibujar el objeto, realizará una función más: cortará las partes del objeto que sobresalgan de los bordes del contenedor. Por lo tanto, hemos creado un ciclo completo de desplazamiento de la barra de progreso dentro de su contenedor y, al mismo tiempo, se cortan las partes que sobresalen más allá de los bordes.
Si el objeto tiene un estilo de representación diferente, llamaremos al temporizador del objeto de la barra de progreso para mostrar el objeto resaltado.
Como ahora tenemos el estilo de dibujado de la barra de progreso "Bloques segmentados", necesitaremos mejorar el método que establece el valor de la barra de progreso. Actualmente, este método, tras establecer el valor, cambia inmediatamente el tamaño del objeto según el nuevo valor. No obstante, como los bloques segmentados no deben dibujarse píxel a píxel, sino bloque a bloque, deberemos comprender cuántos bloques pueden caber en la anchura establecida de la barra de progreso. Si la anchura es suficiente para dibujar un nuevo segmento, el objeto cambiará su anchura ya establecida en su propiedad. Si la anchura no es suficiente (el segmento dibujado actual estará incompleto, cortado), deberemos restar la anchura de un segmento a la anchura establecida del objeto y establecer exactamente dicha anchura para la barra de progreso, luego se dibujará solo el penúltimo segmento con todos los anteriores. Por lo tanto, la anchura del objeto cambiará solo cuando todos los segmentos se puedan dibujar completamente sin recortarlos, lo cual nos ofrecerá un cambio bloque a bloque en la anchura visible de la barra de progreso. En este caso, el valor Value siempre será el que se ha transmitido al objeto. Es decir, solo cambiaremos visualmente la anchura del objeto de forma discreta, y el valor Value en este será siempre el que está establecido para él.
Vamos a introducir las mejoras descritas anteriormente en el método que establece el valor actual de la barra de progreso:
//+------------------------------------------------------------------+ //| 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(); } } } //+------------------------------------------------------------------+
La lógica del método se explica con detalle en los comentarios al código. El texto de la descripción también deberá procesarse: cada vez que cambie el valor de la barra de progreso, es posible que también debamos cambiar la descripción. Por lo tanto, este objeto siempre se pondrá en primer plano si el texto está configurado para él.
El método que calcula la anchura de la barra de progreso deberá modificarse para que retorne la mitad del tamaño del control ProgressBar si el estilo de la barra de progreso se establece en "Desplazamiento continuo":
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Ahora el método retornará el tamaño correcto de la barra de desplazamiento para cualquiera de sus estilos de visualización.
En el método que establece la nueva anchura, deberemos asignar la anchura establecida en el objeto al objeto de etiqueta de texto utilizado para mostrar la descripción de la barra de progreso:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Si el tamaño del objeto de etiqueta de texto no se ajusta al tamaño de la barra de progreso, es posible que el texto escrito con el tamaño aparente de la barra de progreso no quepa en un objeto cuyo anchura sea inferior a lo que parece visualmente. Esto hará que el texto simplemente se corte. Por ello, es necesario que la etiqueta de texto y la barra de progreso tengan las mismas dimensiones.
Vamos a ver los métodos auxiliares utilizados para facilitar el acceso a las propiedades de los objetos vinculados al control ProgressBar.
Método que establece el estilo para el objeto de destello:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Aquí, obtendremos el puntero al objeto de destello y estableceremos el estilo para el objeto resultante.
Método que establece la opacidad para el objeto de destello:
//+------------------------------------------------------------------+ //| Set the opacity of the highlight object | //+------------------------------------------------------------------+ void CProgressBar::SetGlareOpacity(const uchar opacity) { CGlareObj *obj=this.GetGlareObj(); if(obj==NULL) return; obj.SetOpacity(opacity); } //+------------------------------------------------------------------+
Primero obtendremos el puntero al objeto de destello y luego estableceremos el valor de opacidad para el objeto resultante.
Método que establece un color para el objeto de destello:
//+------------------------------------------------------------------+ //| Set the color for the glare object | //+------------------------------------------------------------------+ void CProgressBar::SetGlareColor(const color clr) { CGlareObj *obj=this.GetGlareObj(); if(obj==NULL) return; obj.SetColor(clr); } //+------------------------------------------------------------------+
Ahora obtendremos el puntero al objeto de destello y estableceremos el valor de color transmitido al método para el objeto resultante.
Método que establece un texto para la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Aquí, obtendremos el puntero al objeto de etiqueta de texto. Luego estableceremos la variable m_progress_bar_text en el texto transmitido al método y estableceremos este texto en el objeto. Como el texto se mostrará directamente en el objeto, para evitar la superposición de un texto sobre otro, deberemos borrar el fondo y todo lo que se ha dibujado en él. A continuación, mostraremos el texto y actualizaremos el elemento.
Método que establece el color del texto de la barra de progreso en la etiqueta de texto:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Después obtendremos el puntero al objeto de etiqueta de texto, estableceremos la variable m_progress_bar_text_color en el color transmitido al método y luego estableceremos este color en el objeto como el color del texto. Como el texto se mostrará directamente, para evitar la superposición de un texto sobre otro, borraremos el fondo de la etiqueta de texto y, a continuación, mostraremos el texto y actualizaremos el elemento.
Método que establece la opacidad en la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
La lógica del método es idéntica a la anterior, pero estableciendo el valor de opacidad en la variable y el objeto correspondientes.
Método que establece la coordenada x de la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Método que establece la coordenada Y en la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Método que establece la fuente en la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Método que establece el tamaño de fuente en la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Método que establece las banderas de fuente en la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Todos los métodos mostrados arriba tienen la misma lógica y nos permiten establecer rápidamente los parámetros de fuente y texto deseados en la descripción de la barra de progreso (en la etiqueta de texto). Los cambios se muestran directamente en la pantalla.
Si necesitamos ocultar la descripción de la barra de progreso, además de ocultarla, el objeto deberá establecer su bandera de no visualización, ya que se pondrá constantemente en primer plano, lo cual hará que se visualice. Si, después de ocultar un objeto, configuramos la bandera de no visualización para él, dicho objeto no se redibujará hasta que obtenga la bandera de visualización nuevamente.
Método para ocultar la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| Hide the progress bar text label | //+------------------------------------------------------------------+ void CProgressBar::HideBarDescription(void) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetDisplayed(false); obj.Hide(); } //+------------------------------------------------------------------+
Aquí, obtendremos la etiqueta de texto del objeto con una descripción de la barra de progreso, configuraremos la bandera de no visualización y ocultaremos el objeto.
Método que muestra la etiqueta de texto de la barra de progreso:
//+------------------------------------------------------------------+ //| 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(); } //+------------------------------------------------------------------+
Aquí, obtendremos el puntero al objeto de etiqueta de texto con la descripción de la barra de progreso, configuraremos la bandera de visualización y mostraremos el objeto.
Método que retorna el valor actual de la barra de progreso en el rango de Min a Max como un porcentaje:
//+------------------------------------------------------------------+ //| 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)); } //+------------------------------------------------------------------+
Si necesitamos obtener el valor Value de la barra de progreso como un porcentaje del rango de Min a Max, este método calculará y retornará un valor que indicará qué porcentaje del rango especificado ha sido procesado ya. El 100% será la diferencia entre los valores máximo y mínimo establecidos en el objeto ProgressBar.
Veamos lo que tenemos ahora.
Simulación
Para la prueba, tomaremos el asesor experto del artículo anterior y lo guardaremos en la nueva carpeta \MQL5\Experts\TestDoEasy\Part128\ con el nuevo nombre TestDoEasy128.mq5.
Vamos a crear una enumeración de los estilos de la barra de progreso para la versión en inglés de la compilación y la versión de la compilación en el idioma del usuario:
//--- 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
Luego añadiremos dos nuevos parámetros a los parámetros de entrada: el estilo de la barra de progreso y la bandera para mostrar los valores de la barra de progreso como un porcentaje:
//--- 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
En el controlador OnInit() del asesor experto, al crear el control ProgressBar, configurará el estilo de la barra de progreso de la variable en los ajustes y establecerá los parámetros para describir la barra de progreso:
//--- 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); } } }
En el ciclo de visualización y redibujado de todos los paneles, mostraremos una descripción con el estilo de la barra de progreso "Línea continua", y en cada iteración del ciclo de incremento del valor Value de la barra de progreso, mostraremos los valores Value en la descripción dependiendo de la configuración: en porcentaje o en pasos completados. Al final del ciclo, escribiremos en la descripción de la barra de progreso un mensaje sobre la finalización del ciclo de incremento con la fuente cambiada al estilo Bold.
Para configurar los parámetros del objeto de destello, utilizaremos los métodos de acceso rápido a este objeto:
//--- 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); } //+------------------------------------------------------------------+
Vamos a compilar el asesor y a ejecutarlo en el gráfico:
Como podemos ver, todos los modos declarados funcionan bien.
¿Qué es lo próximo?
En el próximo artículo, comenzaremos a desarrollar el control TrackBar.
*Artículos de esta serie:
DoEasy. Elementos de control (Parte 26): Mejoramos el objeto WinForms "ToolTip" y comenzamos a desarrollar "ProgressBar"
DoEasy. Elementos de control (Parte 27): Seguimos trabajando en el objeto WinForms "ProgressBar"
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/11823





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso