English Русский 中文 Español Deutsch 日本語
preview
DoEasy. Controles (Parte 28): Estilos de barra no controle ProgressBar

DoEasy. Controles (Parte 28): Estilos de barra no controle ProgressBar

MetaTrader 5Exemplos | 4 abril 2023, 10:40
157 0
Artyom Trishkin
Artyom Trishkin

Conteúdo


Ideia

Atualmente, o controle ProgressBar criado para a biblioteca possui um único estilo de exibição, uma barra de progresso, que é uma linha contínua (Continuous). No entanto, esse controle tem mais dois estilos de exibição: blocos segmentados (Blocks) e rolagem contínua do bloco em um objeto (Marquee). O estilo Blocks é bastante claro (a linha contínua é substituída por blocos localizados separadamente). O estilo Marquee pode ser usado quando o número de iterações a serem visualmente exibidas usando o controle ProgressBar não é conhecido antecipadamente. Nesse caso, um único bloco com metade da largura da barra de progresso rolará constantemente. 

Além de criar esses dois novos estilos, vamos adicionar texto à barra de progresso que será exibido dentro dela. O próprio texto será representado por um objeto regular da classe CLabel da biblioteca, e não será vinculado ao objeto da barra de progresso, mas ao objeto de fundo, que é a base do controle ProgressBar. O texto será renderizado dentro de um objeto de rótulo de texto totalmente transparente dimensionado para a largura e altura da barra de progresso, e esse objeto estará sempre em primeiro plano, isto é, acima de todos os objetos no controle ProgressBar.

Por padrão, o texto não será exibido na barra de progresso, mas sempre poderá ser adicionado durante a execução de um programa criado com base na biblioteca. Basta especificar o texto de saída e seus atributos (fonte, tamanho, sinalizadores da fonte, cor, opacidade, etc.).


Modificando as classes da biblioteca

Antes de começarmos a desenvolver novos estilos para o controle ProgressBar, vamos simplificar os construtores do elemento gráfico básico. Após criar um objeto, configuramos os valores de suas propriedades nos construtores protegido e paramétrico. Nos dois construtores, há uma lista longa de mais de cem diferentes parâmetros de elementos gráficos de biblioteca, que são constantemente adicionados quando novos objetos são criados. Dessa forma, temos que definir as propriedades do objeto duas vezes - nos construtores protegido e paramétrico da classe CGCnvElement. Seria lógico mover a configuração de todas essas propriedades para um método de inicialização separado. Ao mesmo tempo, se algumas propriedades devem ser definidas de forma diferente em diferentes construtores, elas podem ser passadas nos parâmetros formais do novo método.

No arquivo \MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqh, adicione novas propriedades à estrutura do objeto:

   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

A estrutura de um objeto gráfico é necessária para a escrita correta das propriedades do objeto em um arquivo e para a leitura dessas propriedades do arquivo durante a restauração. As propriedades já adicionadas ao objeto agora devem ser adicionadas à estrutura. Mesmo que os campos da estrutura não correspondam às propriedades do objeto, não há nada com que se preocupar neste estágio de desenvolvimento, já que ainda não implementamos a gravação do objeto em um arquivo e a leitura de suas propriedades. Posteriormente, salvaremos as propriedades dos objetos gráficos em um arquivo e precisaremos de uma correspondência completa dos campos da estrutura com as propriedades do objeto.

Na seção privada da classe, declaramos um novo método para inicializar as propriedades do 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:

O método receberá as propriedades do objeto criado, que têm valores diferentes em diferentes construtores ou são especificadas diretamente nos parâmetros formais dos construtores, e passará todas essas propriedades para o método por meio de seus parâmetros.


Remova a longa lista de definição das propriedades do objeto em cada um dos construtores e substitua-a por uma chamada ao método de inicialização:

//+------------------------------------------------------------------+
//| 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, os valores próprios de cada construtor específico são passados para o método de inicialização em ambos os construtores.


No novo método de inicialização, mova a definição das propriedades do objeto que foi removida dos construtores da classe:

//+------------------------------------------------------------------+
//| 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
  }
//+------------------------------------------------------------------+

Aqui, simplesmente movemos as linhas que foram removidas dos construtores da classe. Os valores das propriedades que eram diferentes em diferentes construtores agora são passados e definidos para as propriedades do objeto por meio dos parâmetros formais do método.


No método que cria a estrutura do objeto, adicione a definição dos valores apropriados das propriedades do elemento gráfico nos novos campos da estrutura:

//+------------------------------------------------------------------+
//| 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;
  }
//+------------------------------------------------------------------+


No método que cria um objeto a partir de uma estrutura, implemente a definição das propriedades do objeto a partir dos campos correspondentes da estrutura que foram adicionados neste artigo:

//+------------------------------------------------------------------+
//| 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
  }
//+------------------------------------------------------------------+

Agora, o objeto do elemento gráfico será salvo corretamente em um arquivo e restaurado a partir de um arquivo.


Um efeito de brilho ao longo da barra de progresso pode ter a forma de um paralelepípedo. Trata-se de um quadrilátero distorcido, cujos vértices da face superior são deslocados em 6 pixels em relação aos vértices da face inferior. Para um objeto pequeno, esse deslocamento é suficiente para fazer com que ele pareça bastante inclinado. No entanto, à medida que sua altura aumenta, o ângulo de inclinação, fixo em seis pixels, torna-se indistinguível. Para corrigir essa situação, é necessário tornar o ângulo de inclinação um valor relativo, ou seja, quanto maior o objeto, maior será o ângulo de inclinação. Portanto, para definir o tamanho do deslocamento dos vértices, usaremos a altura do objeto. Dessa forma, o ângulo de inclinação será sempre de aproximadamente 45 graus.

No arquivo \MQL5\Include\DoEasy\Objects\Graph\WForms\GlareObj.mqh, no método que desenha a forma do objeto brilho na forma de um paralelogramo, corrigimos a inicialização dos parâmetros das coordenadas dos vértices. Em vez do número 6, atribuímos o valor da altura do 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();
  }
//+------------------------------------------------------------------+

Agora, os vértices serão deslocados de acordo com o valor da altura do objeto e o ângulo de inclinação será sempre de aproximadamente 45 graus, independentemente da altura do objeto.


Para criar um estilo de barra de progresso "Blocos Segmentados", é possível usar diferentes opções, desde a criação direta de cada bloco até o simples desenho deles. Para isso, faremos o seguinte: já temos uma barra de progresso totalmente preenchida e só precisamos apagar o fundo desse objeto nos locais onde não há blocos. Dessa forma, obtemos a aparência de uma barra de progresso composta por blocos segmentados. A desvantagem dessa abordagem é que a localização de cada bloco deve ser calculada. No entanto, a vantagem dessa abordagem é a simplicidade de sua implementação.

No arquivo \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\BarProgressBar.mqh, adicione variáveis à seção privada para armazenar os parâmetros do segmento e declare um método para a segmentação do fundo do 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:

As variáveis declaradas conterão os parâmetros iniciais a partir dos quais a localização dos segmentos poderá ser calculada. A largura do segmento sempre será de 3/4 da altura e a distância entre os segmentos será calculada a partir da largura do segmento resultante. Esses dados serão registrados quando o objeto for inicializado e, em seguida, poderão ser usados para calcular a localização de qualquer segmento por seu número. Como não estamos desenhando os segmentos em si, mas os espaços entre eles, o ponto de partida será a largura do primeiro segmento, contado a partir de zero ou de um. Se a altura da barra de progresso for superior a três pixels, um espaço vazio de um pixel deverá ser desenhado redor da borda do objeto em todos os lados. Isso separará os segmentos da borda externa da barra, tornando-os unidades visualmente independentes. Nesse caso, o preenchimento do primeiro segmento deverá começar em um, que é um espaço vazio de um pixel da borda do objeto até o primeiro segmento. Se a altura da barra de progresso for de três pixels ou menos, não será necessário desenhar um espaço vazio, já que ele ocupará toda a área utilizável do objeto no qual os segmentos são desenhados. Nesse caso, o recuo no início do primeiro segmento deverá ser zero.

Na seção pública da classe, escreveremos um método que retorna o estilo da barra de progresso e métodos que retornam os valores dos parâmetros variáveis dos segmentos. Também declararemos métodos para calcular a largura do segmento e a distância entre eles. Além disso, precisaremos sobrescrever os métodos virtuais para limpar o fundo do 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);
  };
//+------------------------------------------------------------------+

Nos métodos de limpeza, o fundo do elemento é preenchido com sua cor de fundo. Em seguida, chamaremos o método declarado na seção privada para segmentar o fundo desenhado do objeto, removendo o fundo nos locais que são os espaços entre os segmentos. Como esses métodos são virtuais, serão sempre esses métodos que serão chamados quando o método de limpeza for chamado, caso o objeto seja uma barra de progresso ou seu sucessor.

No método de inicialização das propriedades do objeto, inseriremos os valores padrão para as variáveis que armazenam os parâmetros de segmentação. A coordenada X do último segmento e a origem serão iguais a zero, enquanto a largura do segmento e a distância entre eles serão calculadas imediatamente:

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+


Vejamos os métodos declarados com mais detalhes.

Método que limpa o elemento, preenchendo-o com cor e opacidade:

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+

Primeiro, o fundo do elemento é totalmente pintado e, em seguida, é executado o método de segmentação para apagar o fundo nos locais onde não deveria haver segmentos. Se o objeto possuir uma moldura, ela será desenhada e as partes que se projetam além do contêiner pai serão recortadas. Por fim, o plano de fundo do objeto será atualizado com o sinalizador de redesenho do gráfico, que é passado para o método.

Método que limpa o elemento com preenchimento 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);
  }
//+------------------------------------------------------------------+

A lógica desse método é semelhante à do método anterior, com a diferença de que ele recebe uma matriz de cores para preencher o gradiente e um sinalizador de direção (vertical/horizontal e cíclico), em vez de uma única cor.


Método que calcula a largura do segmento:

//+------------------------------------------------------------------+
//| Calculate the segment width                                      |
//+------------------------------------------------------------------+
int CBarProgressBar::CalculateSegmentWidth(void)
  {
   int w=(int)::ceil((this.Height()-2)/1.75);
   return(w>3 ? w : 3);
  }
//+------------------------------------------------------------------+

A largura de cada segmento deve ser 2/3 de sua altura. Esse método calcula a largura do segmento com base na altura do objeto da barra de progresso, que é reduzida em dois pixels (um acima e outro abaixo) para acomodar o espaço livre de um pixel desenhado em cada lado da barra ao longo de seu perímetro. A altura resultante é dividida por 1,75, o que resulta em uma proporção de 3/4. Se a largura calculada for inferior a três pixels, a largura será ajustada para três pixels, já que segmentos muito estreitos com 1-2 pixels ficam ruins visualmente.


Método que calcula a distância entre segmentos:

//+------------------------------------------------------------------+
//| Calculate the distance between segments                          |
//+------------------------------------------------------------------+
int CBarProgressBar::CalculateSegmentDistance(const int width)
  {
   int d=(int)::ceil(width/6);
   return(d<1 ? 1 : d);
  }
//+------------------------------------------------------------------+

Tudo é simples aqui, pois o método recebe a largura com a qual o recuo é calculado. A distância entre os segmentos deve ser seis vezes menor que a largura do bloco, mas não menor que um pixel.


Método que segmenta o plano de fundo:

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+

No código, a lógica desse método está descrita em seus comentários. Se o estilo da barra de progresso for "Blocos segmentados", percorremos em loop todo o plano de fundo do objeto e apagamos o fundo onde não deveria haver segmentos. Se a altura do objeto for superior a três pixels, apagamos também o fundo ao longo do perímetro com uma borda de um pixel de largura, o que separa os segmentos das bordas da barra de progresso.


Para adicionar uma descrição à barra de progresso, basta definir o texto desejado. Por padrão, a descrição não é exibida, mas é possível criar quantos objetos CLabel forem necessários e posicioná-los corretamente. O objeto descrição da barra de progresso é criado automaticamente com o ProgressBar e pode ser facilmente acessado usando métodos específicos.

No arquivo da classe CProgressBar \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\ProgressBar.mqh, removemos a variável da seção privada para armazenar o número de passos ignorados, pois não era necessário:

//+------------------------------------------------------------------+
//| 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


No mesmo local, na seção privada, declararemos variáveis para armazenar as propriedades do rótulo de texto com uma descrição da barra de progresso:

//+------------------------------------------------------------------+
//| 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

Vamos precisar de variáveis para definir e retornar as propriedades do objeto rótulo de texto, que atua como uma descrição da barra de progresso.


Os dados exibidos na linha de descrição podem ser reais e exibir cada etapa da execução ou uma porcentagem das etapas já concluídas.

Na seção pública da classe, vamos adicionar métodos que retornam o valor Value como texto e o valor Value como porcentagem, representada por valores numéricos e textuais:

//--- (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 acesso simplificado ao objeto brilho, na seção pública da classe, declararemos métodos para definir suas propriedades, adicionaremos métodos para obter ponteiros para os objetos anexados que estão sendo criados e declararemos métodos para trabalhar com o objeto descrição da barra de progresso:

//--- (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


No construtor da classe, inicializamos as variáveis declaradas com valores padrão:

//+------------------------------------------------------------------+
//| 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;
  }
//+------------------------------------------------------------------+


Como no método que cria o objeto barra de progresso, também é criado um objeto brilho, vamos adicionar a criação do objeto descrição da barra de progresso lá:

//+------------------------------------------------------------------+
//| 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();
  }
//+------------------------------------------------------------------+

Logo após criar um rótulo de texto, obtemos um ponteiro para o objeto e definimos algumas propriedades, como texto, nome da fonte, tamanho da fonte, método de ancoragem e alinhamento do texto. Em seguida, ocultamos o objeto criado. Os demais parâmetros do objeto podem ser definidos posteriormente, obtendo um ponteiro para ele usando o método GetProgressDescriptionObj() e definindo as propriedades necessárias.
Se tentarmos criar um objeto barra de progresso com altura inferior a um pixel, nada será exibido, pois o objeto não pode ter tamanho zero. Portanto, vamos adicionar uma verificação de tamanho e corrigir o valor, se necessário.


No método que cria um novo objeto gráfico, adicionamos um bloco de código para criar um objeto rótulo 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;
  }
//+------------------------------------------------------------------+

Agora o objeto ProgressBar pode criar objetos anexados com os tipos "Barra de progresso", "Efeito de brilho" e "Rótulo de texto".


O objeto ProgressBar é o controle ativo que é processado pelo temporizador. No momento, o temporizador está processando um efeito de brilho que percorre a barra de progresso. Porém, também precisamos processar a barra de progresso no estilo "Marquee". Nesse modo, a barra de progresso tem uma largura fixa, igual à metade da largura do objeto completo, e rola constantemente dentro do ProgressBar, mostrando o andamento do processo cujo número de iterações não é conhecido antecipadamente.

Vamos adicionar o seguinte processamento da barra de progresso ao manipulador do temporizador do 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();
     }
  }
//+------------------------------------------------------------------+

Se o estilo de exibição da barra de progresso for "Rolagem contínua", obtemos a coordenada X com a qual o objeto precisa ser deslocado. Neste momento, adicionamos um deslocamento de 8 pixels à coordenada X atual e deslocamos a barra de progresso para a nova coordenada horizontalmente. Verificamos primeiro se o objeto da barra de progresso está completamente fora de seu contêiner à direita. Nesse caso, definimos sua coordenada X para que o objeto fique alinhado com a borda esquerda de seu contêiner, além de sua largura à esquerda. O método Redraw() também corta as partes do objeto que se projetam além das bordas do contêiner, criando um ciclo completo de movimentação da barra de progresso dentro de seu contêiner.
Se o objeto tiver um estilo de renderização diferente, chamamos o temporizador do objeto da barra de progresso para exibir o objeto brilho.


Agora que temos um estilo de desenho de barra de progresso "Blocos segmentados", precisamos refinar o método que define o valor da barra de progresso. Atualmente, após definir o valor, o método redimensiona imediatamente o objeto de acordo com o novo valor. Porém, como os blocos segmentados não devem ser desenhados pixel a pixel, mas bloco a bloco, precisamos calcular quantos blocos cabem na largura definida da barra de progresso. Se a largura for suficiente para desenhar um novo segmento, o objeto altera sua largura conforme configurado em sua propriedade. Se a largura não for suficiente (o segmento atual ficará incompleto, cortado), subtraímos a largura de um segmento da largura definida do objeto e definimos exatamente essa largura para a barra de progresso. Então, apenas o penúltimo segmento, junto com todos os anteriores, será desenhado. Assim, a largura do objeto mudará apenas quando todos os segmentos puderem ser desenhados completamente, sem recortá-los. Esse processo cria uma alteração bloco a bloco na largura visível da barra de progresso. O valor Value sempre será aquele que foi passado para o objeto. Ou seja, apenas alteramos visualmente a largura do objeto discretamente, enquanto o valor de Value permanece o mesmo.

Vamos fazer as melhorias descritas acima no método que define o valor atual da barra de progresso:

//+------------------------------------------------------------------+
//| 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();
        }
     }
  }
//+------------------------------------------------------------------+

A lógica do método é descrita nos comentários do código. O texto da descrição também precisa ser processado: cada vez que alteramos o valor da barra de progresso, pode ser necessário alterar também a descrição. Portanto, esse objeto sempre é trazido para o primeiro plano se tiver texto.


O método que calcula a largura da barra de progresso precisa ser modificado para que retorne metade do tamanho do controle ProgressBar se o estilo da barra de progresso estiver definido como "Rolagem contínua":

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+

Agora o método retornará o tamanho correto da barra de rolagem para qualquer um de seus estilos de exibição.


No método que define a nova largura, devemos atribuir a largura definida no objeto ao objeto rótulo de texto usado para exibir a descrição da barra de progresso:

//+------------------------------------------------------------------+
//| Set the 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;
  }
//+------------------------------------------------------------------+

Se o tamanho do objeto de rótulo de texto não for ajustado ao tamanho da barra de progresso, o texto escrito com base no tamanho aparente da barra de progresso pode não caber em um objeto cuja largura seja menor do que aparenta visualmente. Isso fará com que o texto seja cortado. Portanto, é necessário que o rótulo de texto e a barra de progresso tenham as mesmas dimensões para evitar esse problema.

Vejamos os métodos auxiliares usados para facilitar o acesso às propriedades dos objetos vinculados ao controle ProgressBar.

Método que define o estilo do objeto brilho:

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+

Aqui: obtemos um ponteiro para o objeto brilho e definimos o estilo para o objeto resultante.


Método que define a opacidade para o objeto brilho:

//+------------------------------------------------------------------+
//| Set the opacity of the highlight object                          |
//+------------------------------------------------------------------+
void CProgressBar::SetGlareOpacity(const uchar opacity)
  {
   CGlareObj *obj=this.GetGlareObj();
   if(obj==NULL)
      return;
   obj.SetOpacity(opacity);
  }
//+------------------------------------------------------------------+

Obtemos um ponteiro para o objeto brilho e definimos o valor de opacidade para o objeto resultante.


Método que define a cor do objeto brilho:

//+------------------------------------------------------------------+
//| Set the color for the glare object                               |
//+------------------------------------------------------------------+
void CProgressBar::SetGlareColor(const color clr)
  {
   CGlareObj *obj=this.GetGlareObj();
   if(obj==NULL)
      return;
   obj.SetColor(clr);
  }
//+------------------------------------------------------------------+

Obtemos um ponteiro para o objeto brilho e definimos o valor da cor, passado para o método, que o objeto resultante recebe.


Método que define o rótulo de texto da barra de progresso:

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+

Aqui: obtemos um ponteiro para o objeto de rótulo de texto. Definimos a variável m_progress_bar_text para o texto passado para o método e, em seguida, definimos esse texto para o objeto. Como o texto será exibido imediatamente no objeto, para evitar a sobreposição de texto, o fundo e tudo o que foi desenhado nele deve ser apagado. Em seguida, exibimos o texto e atualizamos o elemento.


Método que define no rótulo de texto a cor do texto da barra de progresso:

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+

Obtemos um ponteiro para o objeto de rótulo de texto. Definimos a variável m_progress_bar_text_color com a cor passada para o método e, em seguida, definimos essa cor para o objeto como a cor do texto. Como o texto será exibido imediatamente, para evitar a sobreposição de texto, o fundo do rótulo do texto é apagado e, em seguida, o texto é exibido e o elemento é atualizado.


Método que define no rótulo de texto da barra de progresso a opacidade:

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+

A lógica do método é idêntica à anterior, mas definimos o valor de opacidade na variável e o objeto correspondentes.


Método que define a coordenada x do rótulo de texto da barra de progresso:

//+------------------------------------------------------------------+
//| 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 define a coordenada Y do rótulo de texto da barra de progresso:

//+------------------------------------------------------------------+
//| 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 define a fonte no rótulo de texto da barra de progresso:

//+------------------------------------------------------------------+
//| 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 define o tamanho da fonte do rótulo de texto da barra de progresso:

//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+


O método que define os sinalizadores de fonte no rótulo de texto da barra de progresso:

//+------------------------------------------------------------------+
//| 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 os métodos mostrados acima têm a mesma lógica e permitem definir rapidamente os parâmetros de texto e fonte desejados na descrição da barra de progresso (no rótulo do texto). As alterações são imediatamente exibidas na tela.


Se precisarmos esconder a descrição da barra de progresso, então, além de ocultá-la, o objeto precisa ser ajustado para não exibi-la, pois sempre é trazido para o primeiro plano. Se, no entanto, depois de ocultar um objeto, o sinalizador que indica que ele não deve ser exibido tem de ser marcado antes, e o objeto não será redesenhado até receber novamente o sinalizador de exibição.

Método para ocultar o rótulo de texto da barra de progresso:

//+------------------------------------------------------------------+
//| Hide the progress bar text label                                 |
//+------------------------------------------------------------------+
void CProgressBar::HideBarDescription(void)
  {
   CLabel *obj=this.GetProgressDescriptionObj();
   if(obj==NULL)
      return;
   obj.SetDisplayed(false);
   obj.Hide();
  }
//+------------------------------------------------------------------+

Aqui: obtemos o objeto rotulo de texto com uma descrição da barra de progresso, marcamos o sinalizador de não exibição e escondemos o objeto.


Método que exibe o rótulo de texto da barra de progresso:

//+------------------------------------------------------------------+
//| 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();
  }
//+------------------------------------------------------------------+

Aqui: obtemos o ponteiro para o objeto rótulo de texto com uma descrição da barra de progresso, definimos o sinalizador de exibição e mostramos o objeto.


Método que retorna o valor atual da barra de progresso no intervalo de Min a Max em porcentagem:

//+------------------------------------------------------------------+
//| 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));
  }
//+------------------------------------------------------------------+

Se precisarmos obter o Value da barra de progresso como uma porcentagem do intervalo de Min a Max, esse método calculará e retornará o valor de quantos por cento do intervalo especificado já foram processados. 100% é a diferença entre os valores máximo e mínimo definidos no objeto ProgressBar.

Vamos verificar o que temos.


Teste

Para testar, vamos pegar o Expert Advisor do artigo anterior e salvá-lo na nova pasta \MQL5\Experts\TestDoEasy\Part128\ com o novo nome TestDoEasy128.mq5.

Vamos criar uma enumeração dos estilos da barra de progresso para a versão em inglês da compilação e a versão da compilação no idioma do usuário:

//--- 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


Vamos adicionar dois novos parâmetros aos parâmetros de entrada - o estilo da barra de progresso e o sinalizador para exibir os valores da barra de progresso como uma porcentagem:

//--- 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


No manipulador OnInit() do Expert Advisor, ao criar o controle ProgressBar, definimos o estilo da barra de progresso da variável nas configurações e definimos os parâmetros para descrever a barra de progresso:

                     //--- 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);
                             }
                          }
                       }


No ciclo de exibição e redesenho de todos os painéis, exibiremos a descrição com a barra de progresso estilo "Linha contínua" e a cada iteração do ciclo de incrementaremos o Value da barra de progresso, exibiremos os Value ​na descrição, dependendo das configurações - em porcentagens ou em passos concluídos. Ao final do ciclo, escreveremos na descrição da barra de progresso uma mensagem sobre a conclusão do ciclo de incremento com a fonte alterada para o estilo Bold.
Para definir os parâmetros do objeto brilho, usaremos os métodos de acesso 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 of a 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);
  }
//+------------------------------------------------------------------+


Compilamos o Expert Advisor e o iniciamos no gráfico:


Como você pode ver, todos os modos declarados funcionam bem.


O que virá a seguir?

No próximo artigo, começaremos a desenvolver o controle TrackBar.

Voltar ao conteúdo

*Artigos desta série:

 
DoEasy. Controles (Parte 26): Finalizamos o objeto WinForms "ToolTip" e começamos a desenvolver a barra de progresso "ProgressBar"
DoEasy. Controles (Parte 27): Continuamos a trabalhar no objeto WinForms "ProgressBar"

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/11823

Arquivos anexados |
MQL5.zip (4527.27 KB)
Redes neurais de maneira fácil (Parte 35): Módulo de curiosidade intrínseca Redes neurais de maneira fácil (Parte 35): Módulo de curiosidade intrínseca
Continuamos a explorar algoritmos de aprendizado por reforço. Todos os algoritmos que analisamos até agora exigiam a criação de uma política de recompensa de tal forma que o agente pudesse avaliar cada uma de suas ações em cada transição de um estado do sistema para outro. No entanto, essa abordagem é bastante artificial. Na prática, existe um intervalo de tempo entre a ação e a recompensa. Neste artigo, proponho que você se familiarize com um algoritmo de aprendizado de modelo capaz de lidar com diferentes atrasos temporais entre a ação e a recompensa.
Algoritmos de otimização populacionais: Busca por cardume de peixes (FSS - Fish School Search) Algoritmos de otimização populacionais: Busca por cardume de peixes (FSS - Fish School Search)
O FSS (Fish School Search) é um algoritmo avançado de otimização inspirado no comportamento dos peixes que nadam em cardumes. Aproximadamente 80% desses peixes nadam em comunidades organizadas de parentes, o que tem sido comprovado como uma estratégia importante para melhorar a eficiência de procura por alimento e proteção contra predadores.
DoEasy. Controles (Parte 29): Controle auxiliar "ScrollBar" DoEasy. Controles (Parte 29): Controle auxiliar "ScrollBar"
Neste artigo, iniciaremos o desenvolvimento do elemento de controle auxiliar ScrollBar e seus objetos derivados, incluindo as barras de rolagem vertical e horizontal. A ScrollBar (barra de rolagem) é utilizada para rolar o conteúdo da forma caso ele ultrapasse o contêiner. As barras de rolagem geralmente são posicionadas na parte inferior e à direita da forma. A barra de rolagem horizontal, localizada na parte inferior, permite rolar o conteúdo para a esquerda e direita, enquanto a barra de rolagem vertical possibilita rolar o conteúdo para cima e para baixo.
Desenvolvendo um sistema de Replay — Simulação de mercado (Parte 05): Adicionando Previas Desenvolvendo um sistema de Replay — Simulação de mercado (Parte 05): Adicionando Previas
Conseguimos desenvolver, uma forma de fazer com que o replay de mercado, fosse executado dentro de um tempo bastante realista e aceitável. Vamos continuar nosso projeto. Agora iremos adicionar dados de forma a ter um comportamento melhor do replay.