English Русский 中文 Español Deutsch 日本語
Interfaces Gráficas X: Caixa de Edição de Texto, Slider de Imagens e Controles Simples (build 5)

Interfaces Gráficas X: Caixa de Edição de Texto, Slider de Imagens e Controles Simples (build 5)

MetaTrader 5Exemplos | 25 janeiro 2017, 09:55
1 522 0
Anatoli Kazharski
Anatoli Kazharski

Conteúdo

Introdução

A fim de obter uma melhor compreensão do propósito desta biblioteca, leia por favor o primeiro artigo: Interfaces Gráficas I: Preparação da Estrutura da Biblioteca (Capítulo 1). Você irã encontrar uma lista de artigos com os links no final de cada capítulo. Lá, você também pode encontrar e baixar a versão completa da biblioteca, no estágio de desenvolvimento atual. Os arquivos devem estar localizados nas mesmas pastas que o arquivo baixado.

Este artigo irá considerar novos controles: A Caixa de Edição de Texto, o Slider de Imagem, bem como os controles simples adicionais: Rótulo de Texto e Imagem, que poderá ser útil em vários casos. A biblioteca continua a crescer, e, além da introdução de novos controles, aqueles que foram criados anteriormente também estão sendo melhorados. Como, atualmente, a biblioteca é utilizada por um grande número de pessoas, várias observações e sugestões foram recebidas. Muitos dessas solicitações foram implementadas na nova versão da biblioteca. Além disso, alguns algoritmos foram otimizados. Isso reduziu ainda mais a carga da CPU. Mais detalhes sobre isto se encontrará mais adiante no artigo.

 

O Controle Caixa de Edição de Texto

Até agora, a biblioteca desenvolvida já contém um controle Caixa de edição (a classe CSpinEdit), mas ela foi projetada para entrar apenas com os valores numéricos. Agora, a biblioteca será complementada com um outro controle, na qual permitiria que qualquer texto seja inserido no campo. O controle Caixa de Edição de Texto pode ser necessário em diferentes situações. Por exemplo, é possível criar uma string de pesquisa nos arquivos do "ambiente protegido" do terminal. Outra opção consiste em proporcionar ao usuário final da aplicação MQL a capacidade de inserir um array de símbolos para a negociação. Em suma, este pode ser qualquer dado de texto necessário para o trabalho.

Vamos enumerar todos os componentes do controle Caixa de Edição de Texto:

  1. Fundo
  2. Ícone
  3. Descrição
  4. Caixa de edição

 

Fig. 1. Componentes do controle Caixa de Edição de texto.


Vamos dar uma olhada mais a fundo na classe deste controle.

 

Classe para a criação do controle Caixa de Edição de Texto

Cria o arquivo TextEdit.mqh com a classe CTextEdit que tem os métodos padrão para todos os controles e inclui ele no motor da biblioteca (o arquivo WndContainer.mqh). Abaixo estão as propriedades do controle que estão disponíveis ao usuário para personalização:

  • Cor de fundo do controle
  • Ícones do controle para os estados ativo e bloqueado
  • Margens do ícone ao longo dos dois eixos (x, y)
  • Descrição de texto do controle
  • Margens para o rótulo de texto ao longo dos dois eixos (x, y)
  • Cor do texto em diferentes estados do controle
  • Tamanho da Caixa de Edição
  • Margens para a Caixa de Edição ao longo dos dois eixos (x, y)
  • Cores da Caixa de Edição e do texto da Caixa de Edição em estados diferentes
  • Alinhamento do texto na Caixa de Edição (esquerda/direita/centro)
  • Modo de exibição do cursor de seleção de texto
  • Modo de resetar o valor na Caixa de Edição
//+------------------------------------------------------------------+
//| Classe para a criação de caixa de edição de texto           |
//+------------------------------------------------------------------+
class CTextEdit : public CElement
  {
private:
   //--- Cor de fundo do controle
   color             m_area_color;
   //--- Ícones da caixa de seleção nos estados ativo e bloqueado
   string            m_icon_file_on;
   string            m_icon_file_off;
   //--- Margens do ícone
   int               m_icon_x_gap;
   int               m_icon_y_gap;
   //--- Texto da descrição da Caixa de Edição
   string            m_label_text;
   //--- Margens do rótulo de texto
   int               m_label_x_gap;
   int               m_label_y_gap;
   //--- Cor do texto em diferentes estados
   color             m_label_color;
   color             m_label_color_hover;
   color             m_label_color_locked;
   color             m_label_color_array[];
   //--- Valor atual da Caixa de Edição
   string            m_edit_value;
   //--- Tamanho da Caixa de Edição
   int               m_edit_x_size;
   int               m_edit_y_size;
   //--- Margem para o Campo de Edição
   int               m_edit_x_gap;
   int               m_edit_y_gap;
   //--- Cores da Caixa de Edição e do texto da Caixa de Edição em diferentes estados
   color             m_edit_color;
   color             m_edit_color_locked;
   color             m_edit_text_color;
   color             m_edit_text_color_locked;
   color             m_edit_text_color_highlight;
   //--- Cores do quadro do campo de edição em diferentes estados
   color             m_edit_border_color;
   color             m_edit_border_color_hover;
   color             m_edit_border_color_locked;
   color             m_edit_border_color_array[];
   //--- Modo de resetar o valor (string vazia)
   bool              m_reset_mode;
   //--- Modo de exibição do ponteiro de seleção de texto
   bool              m_show_text_pointer_mode;
   //--- Modo de alinhamento do texto
   ENUM_ALIGN_MODE   m_align_mode;
   //---
public:
   //--- Margens do ícone
   void              IconXGap(const int x_gap)                      { m_icon_x_gap=x_gap;                 }
   void              IconYGap(const int y_gap)                      { m_icon_y_gap=y_gap;                 }
   //--- (1) Cor de fundo, (2) texto da descrição do caixa de edição, (3) margens do rótulo de texto
   void              AreaColor(const color clr)                     { m_area_color=clr;                   }
   string            LabelText(void)                          const { return(m_label.Description());      }
   void              LabelText(const string text)                   { m_label.Description(text);          }
   void              LabelXGap(const int x_gap)                     { m_label_x_gap=x_gap;                }
   void              LabelYGap(const int y_gap)                     { m_label_y_gap=y_gap;                }
   //--- Cores do rótulo de texto em diferentes estados
   void              LabelColor(const color clr)                    { m_label_color=clr;                  }
   void              LabelColorHover(const color clr)               { m_label_color_hover=clr;            }
   void              LabelColorLocked(const color clr)              { m_label_color_locked=clr;           }
   //--- (1) Tamanho do campo de edição, (2) margem do campo de edição do lado direito
   void              EditXSize(const int x_size)                    { m_edit_x_size=x_size;               }
   void              EditYSize(const int y_size)                    { m_edit_y_size=y_size;               }
   //--- Margins for the Edit box
   void              EditXGap(const int x_gap)                      { m_edit_x_gap=x_gap;                 }
   void              EditYGap(const int y_gap)                      { m_edit_y_gap=y_gap;                 }
   //--- Cores da caixa de edição em diferentes estados
   void              EditColor(const color clr)                     { m_edit_color=clr;                   }
   void              EditColorLocked(const color clr)               { m_edit_color_locked=clr;            }
   //--- Cores do texto do campo de edição em diferentes estados
   void              EditTextColor(const color clr)                 { m_edit_text_color=clr;              }
   void              EditTextColorLocked(const color clr)           { m_edit_text_color_locked=clr;       }
   void              EditTextColorHighlight(const color clr)        { m_edit_text_color_highlight=clr;    }
   //--- Cores do quadro do campo de edição em diferentes estados
   void              EditBorderColor(const color clr)               { m_edit_border_color=clr;            }
   void              EditBorderColorHover(const color clr)          { m_edit_border_color_hover=clr;      }
   void              EditBorderColorLocked(const color clr)         { m_edit_border_color_locked=clr;     }
   // --- (1) Modo de resete ao pressionar o rótulo de texto, (2) o modo do ponteiro de seleção do texto de exibição
   bool              ResetMode(void)                                { return(m_reset_mode);               }
   void              ResetMode(const bool mode)                     { m_reset_mode=mode;                  }
   void              ShowTextPointerMode(const bool mode)           { m_show_text_pointer_mode=mode;      }
   //--- Modo de alinhamento do texto
   void              AlignMode(ENUM_ALIGN_MODE mode)                { m_align_mode=mode;                  }
   //--- Definir os ícones para o botão nos estados ativo e bloqueado
   void              IconFileOn(const string file_path);
   void              IconFileOff(const string file_path);
  };

O modo de exibição do ponteiro de seleção de texto significa que o cursor do mouse será complementado por um ícone adicional quando se passa sobre a Caixa de Edição, indicando que o texto pode ser digitado lá. Para que isto funcione, foi adicionado mais um identificador (MP_TEXT_SELECT) à enumeração ENUM_MOUSE_POINTER.

//+------------------------------------------------------------------+
//| Enumeração dos tipos de ponteiros                                 |
//+------------------------------------------------------------------+
enum ENUM_MOUSE_POINTER
  {
   MP_CUSTOM      =0,
   MP_X_RESIZE    =1,
   MP_Y_RESIZE    =2,
   MP_XY1_RESIZE  =3,
   MP_XY2_RESIZE  =4,
   MP_X_SCROLL    =5,
   MP_Y_SCROLL    =6,
   MP_TEXT_SELECT =7
  };

A adição correspondente foi feita na classe CPointer (veja o código abaixo). A imagem para o ícone do cursor de seleção do texto está disponível no arquivo do final do artigo. 

//+------------------------------------------------------------------+
//|                                                                     Pointer.mqh |
//|                Copyright 2015, MetaQuotes Software Corp. |
//|                                                      http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
//--- Recursos
...
#resource "\\Images\\EasyAndFastGUI\\Controls\\pointer_text_select.bmp"

//+------------------------------------------------------------------+
//| Define as imagens do cursor com base no tipo do cursor|
//+------------------------------------------------------------------+
void CPointer::SetPointerBmp(void)
  {
   switch(m_type)
     {
      case MP_X_RESIZE :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_x_rs_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_x_rs.bmp";
         break;
      case MP_Y_RESIZE :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_y_rs_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_y_rs.bmp";
         break;
      case MP_XY1_RESIZE :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_xy1_rs_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_xy1_rs.bmp";
         break;
      case MP_XY2_RESIZE :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_xy2_rs_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_xy2_rs.bmp";
         break;
      case MP_X_SCROLL :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_x_scroll_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_x_scroll.bmp";
         break;
      case MP_Y_SCROLL :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_y_scroll_blue.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_y_scroll.bmp";
         break;
      case MP_TEXT_SELECT :
         m_file_on  ="Images\\EasyAndFastGUI\\Controls\\pointer_text_select.bmp";
         m_file_off ="Images\\EasyAndFastGUI\\Controls\\pointer_text_select.bmp";
         break;

     }
//--- Se o tipo personalizado (MP_CUSTOM) é especificado
   if(m_file_on=="" || m_file_off=="")
      ::Print(__FUNCTION__," > Both icons must be set for the cursor!");
  }

Para criar o controle Caixa de Edição de Texto, vamos precisar de cinco métodos privados e um público

class CTextEdit : public CElement
  {
private:
   //--- Objetos para a criação da Caixa de Edição
   CRectLabel        m_area;
   CBmpLabel         m_icon;
   CLabel            m_label;
   CEdit             m_edit;
   CPointer          m_text_select;
   //---
public:
   // --- Métodos para criar a Caixa de Edição de Texto
   bool              CreateTextEdit(const long chart_id,const int subwin,const string label_text,const int x,const int y);
   //---
private:
   bool              CreateArea(void);
   bool              CreateIcon(void);
   bool              CreateLabel(void);
   bool              CreateEdit(void);
   bool              CreateTextSelectPointer(void);
  };


O resto da classe CTextEdit não possui nada que nós já não estudamos nos artigos anteriores desta série. Portanto, você pode examinar suas capacidades por si próprio. A versão atual da Caixa de Edição de Texto tem um limite de 63 caracteres

 

O Controle Slider de Imagem

O Slider de Imagem pertence aos controles de informação da interface gráfica. Ele é útil para criar um guia de referência rápida, onde as ilustrações mostram certas situações no gráfico de preços ou uma breve explicação sobre o propósito de um controle específico da interface gráfica na aplicação MQL utilizada. 

Vamos enumerar todos os componentes do controle Slider de Imagem:

  1. Fundo
  2. Botões de seta do Slider
  3. Grupo de botões de radio
  4. Grupo de imagens associadas ao grupo de botões de radio


 

Fig. 2. Componentes do controle Slider de Imagem.

 

Classe para a criação do controle Slider de Imagem

Cria o arquivo PicturesSlider.mqh com os métodos convencionais presentes em outras classes e inclui ele no arquivo WndContainer.mqh. A seguir estão as propriedades do controle que podem ser personalizadas pelos usuários da biblioteca.

  • Cor de fundo do controle
  • Cor do controle quadro de fundo
  • Margem para as imagens ao longo do eixo Y
  • Margens para os botões do slider ao longo dos dois eixos (x, y)
  • Margens para os botões de radio ao longo dos dois eixos (x, y)
  • Margem entre os botões de radio
//+------------------------------------------------------------------+
//| Classe para criar o Slider de Imagem                              |
//+------------------------------------------------------------------+
class CPicturesSlider : public CElement
  {
private:
   //--- Cor de fundo do controle e do quadro
   color             m_area_color;
   color             m_area_border_color;
   //--- Margem para as imagens ao longo do eixo Y
   int               m_pictures_y_gap;
   //--- Margens para os botões
   int               m_arrows_x_gap;
   int               m_arrows_y_gap;
   //--- Margens para os botões de radio
   int               m_radio_buttons_x_gap;
   int               m_radio_buttons_y_gap;
   int               m_radio_buttons_x_offset;
   //---
public:
   //--- (1) Cor do fundo e (2) do fundo do quadro
   void              AreaColor(const color clr)              { m_area_color=clr;                      }
   void              AreaBorderColor(const color clr)        { m_area_border_color=clr;               }
   //--- Margens para os botões de seta
   void              ArrowsXGap(const int x_gap)             { m_arrows_x_gap=x_gap;                  }
   void              ArrowsYGap(const int y_gap)             { m_arrows_y_gap=y_gap;                  }
   //--- Margem para as imagens ao longo do eixo Y
   void              PictureYGap(const int y_gap)            { m_pictures_y_gap=y_gap;                }
   //--- (1) Margens dos botões de radio, (2) distância entre os botões de radio
   void              RadioButtonsXGap(const int x_gap)       { m_radio_buttons_x_gap=x_gap;           }
   void              RadioButtonsYGap(const int y_gap)       { m_radio_buttons_y_gap=y_gap;           }
   void              RadioButtonsXOffset(const int x_offset) { m_radio_buttons_x_offset=x_offset;     }
  };

 Para criar o controle de Slider de Imagem, vamos precisar de cinco métodos privados e um público:

class CPicturesSlider : public CElement
  {
private:
   //--- Objetos para criar o controle
   CRectLabel        m_area;
   CBmpLabel         m_pictures[];
   CRadioButtons     m_radio_buttons;
   CIconButton       m_left_arrow;
   CIconButton       m_right_arrow;
   //---
public:
   //--- Métodos para criar o Slider de Imagem
   bool              CreatePicturesSlider(const long chart_id,const int subwin,const int x,const int y);
   //---
private:
   bool              CreateArea(void);
   bool              CreatePictures(void);
   bool              CreateRadioButtons(void);
   bool              CreateLeftArrow(void);
   bool              CreateRightArrow(void);
  };

A largura do controle será calculada automaticamente, com base nos parâmetros definidos pelo usuário. Esses parâmetros incluem as margens do grupo de botões de radio a partir da borda esquerda do controle, que também se calcula a coordenada para o botão de seta para a direita do Slider de Imagem. A altura do controle depende também do tamanho das imagens. Supõe-se que os tamanhos da imagem serão o mesmo, de modo que os cálculos usam o tamanho da primeira imagem do grupo.

Antes de chamar o método principal para criar o controle, é necessário adicionar as imagens para um array usando o método CPicturesSlider::AddPicture(). Se o caminho para a imagem não está definida como um único argumento deste método, o caminho padrão será aplicado.  

//+------------------------------------------------------------------+
//|                                                           PicturesSlider.mqh |
//|                 Copyright 2016, MetaQuotes Software Corp. |
//|                                                      http://www.mql5.com |
//+------------------------------------------------------------------+
...
//--- Imagem padrão
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp"
//+------------------------------------------------------------------+
//| Classe para criar a imagem Slider                                   |
//+------------------------------------------------------------------+
class CPicturesSlider : public CElement
  {
private:
   //--- Array de imagens (caminho para fotos)
   string            m_file_path[];
   <//--- Caminho padrão para a imagem
   string            m_default_path;
   //---
public:
   <//--- Adicionar imagem
   void              AddPicture(const string file_path="");
  };
//+------------------------------------------------------------------+
//| Construtor                                                                        |
//+------------------------------------------------------------------+
CPicturesSlider::CPicturesSlider(void) : m_default_path("Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp"),
                                         m_area_color(clrNONE),
                                         m_area_border_color(clrNONE),
                                         m_arrows_x_gap(2),
                                         m_arrows_y_gap(2),
                                         m_radio_button_width(12),
                                         m_radio_buttons_x_gap(25),
                                         m_radio_buttons_y_gap(1),
                                         m_radio_buttons_x_offset(20),
                                         m_pictures_y_gap(25)
  {
//--- Guarda o nome da classe do controle na classe base
   CElement::ClassName(CLASS_NAME);
//--- Define as prioridades do botão esquerdo do mouse
   m_zorder=0;
  }
//+------------------------------------------------------------------+
//| Adiciona uma imagem                                                     |
//+------------------------------------------------------------------+
void CPicturesSlider::AddPicture(const string file_path="")
  {
//--- Aumenta o tamanho do array por um elemento
   int array_size=::ArraySize(m_pictures);
   int new_size=array_size+1;
   ::ArrayResize(m_pictures,new_size);
   ::ArrayResize(m_file_path,new_size);
//--- Armazena os valores dos parâmetros passados
   m_file_path[array_size]=(file_path=="")? m_default_path : file_path;
  }

Para exibir uma imagem do grupo, utilize o método CPicturesSlider::SelectPicture(). Este método será chamado ao pressionar as teclas de setas e botões de radio no manipulador da classe CPicturesSlider.  

class CPicturesSlider : public CElement
  {
public:
//--- Muda a imagem no índice especificado
   void              SelectPicture(const uint index);
  };
//+------------------------------------------------------------------+
//| Especifica a imagem a ser exibida                                   |
//+------------------------------------------------------------------+
void CPicturesSlider::SelectPicture(const uint index)
  {
//--- Obtém o número de imagens
   uint pictures_total=PicturesTotal();
//--- Se não houver nenhuma imagem no grupo, reporta
   if(pictures_total<1)
     {
      ::Print(__FUNCTION__," > This method is to be called, "
              "if a group contains at least one picture! Use the CPicturesSlider::AddPicture() method");
      return;
     }
//--- Ajusta o valor do índice, se o tamanho do array for excedido
   uint correct_index=(index>=pictures_total)? pictures_total-1 : index;
//--- Seleciona o botão de radio neste índice
   m_radio_buttons.SelectRadioButton(correct_index);
//--- Muda para a imagem
   for(uint i=0; i<pictures_total; i++)
     {
      if(i==correct_index)
         m_pictures[i].Timeframes(OBJ_ALL_PERIODS);
      else
         m_pictures[i].Timeframes(OBJ_NO_PERIODS);
     }
  }

Ao pressionar os botões de seta, o manipulador de eventos do controle chama os métodos CPicturesSlider::OnClickLeftArrow() e CPicturesSlider::OnClickRightArrow(). A lista abaixo mostra o código se o método for para o botão esquerdo do mouse. Os eventos de clique nos botões do Slider de Imagem podem ser rastreados na classe personalizada da aplicação em MQL, se necessário. 

class CPicturesSlider : public CElement
  {
public:
private:
   //--- Manipulação do clique do botão esquerdo
   bool              OnClickLeftArrow(const string clicked_object);
   //--- Manipulação do clique do botão direito
   bool              OnClickRightArrow(const string clicked_object);
  };
//+------------------------------------------------------------------+
//| Clique no botão esquerdo do mouse                               |
//+------------------------------------------------------------------+
bool CPicturesSlider::OnClickLeftArrow(const string clicked_object)
  {
//--- Sai, se o clique não estiver no botão
   if(::StringFind(clicked_object,CElement::ProgramName()+"_icon_button_",0)<0)
      return(false);
//--- Obtém o identificador do controle a partir do nome do objeto
   int id=CElement::IdFromObjectName(clicked_object);
//--- Obtém o índice do controle do nome do objeto
   int index=CElement::IndexFromObjectName(clicked_object);
//--- Sai, se os identificadores de controle não corresponderem
   if(id!=CElement::Id())
      return(false);
//--- Sai, se os índices do controle não corresponderem
   if(index!=0)
      return(false);
//--- Obtém o índice atual do botão de radio selecionado
   int selected_radio_button=m_radio_buttons.SelectedButtonIndex();
//--- Muda a imagem
   SelectPicture(--selected_radio_button);
//--- Envia uma mensagem sobre isso
   ::EventChartCustom(m_chart_id,ON_CLICK_BUTTON,CElement::Id(),CElement::Index(),"");
   return(true);
  }

Abaixo é exibido o código menor do manipulador de eventos para o Slider de Imagem. É evidente que os eventos de clique nos botões de radio do controle Slider são rastreados aqui também. É possível entender que um botão de radio em um grupo local foi clicado usando o identificador de controle, que é igual ao identificador do Slider de Imagem

//+------------------------------------------------------------------+
//| Manipulador de eventos                                                   |
//+------------------------------------------------------------------+
void CPicturesSlider::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Manipulação do evento de movimento do cursor
...
//--- Manipulação do evento de clique no botão de radio
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      //--- Se este é um botão de radio do controle Slider, muda a imagem
      if(lparam==CElement::Id())
         SelectPicture(m_radio_buttons.SelectedButtonIndex());
      //---
      return;
     }
//--- Manipulação do botão esquerdo do mouse sobre o objeto
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Se um botão de seta do controle Slider for clicado, muda a imagem
      if(OnClickLeftArrow(sparam))
         return;
      if(OnClickRightArrow(sparam))
         return;
      //---
      return;
     }
  }

 

Os Controles Rótulo de Texto e Imagem

Como um suplemento, a biblioteca inclui agora duas novas classes CTextLabel e cPicture para a criação do rótulo de texto simples e controles de imagem. Eles podem ser utilizados como objetos separados, sem liga-los a qualquer outro controle. Seu conteúdo é muito simples. Na classe cPicture, os usuários podem alterar apenas uma propriedade - o caminho para a imagem. O método CPicture::Path() é utilizado para este objetivo. A menos que um caminho personalizado não seja especificado, então, será usado uma imagem padrão. A imagem pode ser alterada de forma programática a qualquer momento, mesmo depois de criar a interface gráfica da aplicação MQL.

//+------------------------------------------------------------------+
//|                                                      Picture.mqh |
//|                 Copyright 2016, MetaQuotes Software Corp. |
//|                                                      http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
#include "Window.mqh"
//--- Recursos
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp"
//+------------------------------------------------------------------+
//| Classe para a criação da imagem                                       |
//+------------------------------------------------------------------+
class CPicture : public CElement
  {
private:
   //--- Caminho para a imagem
   string            m_path;
   //---
public:
   //--- Obtém/define o caminho para a imagem
   string            Path(void)               const { return(m_path);             }
   void              Path(const string path);
  };
//+------------------------------------------------------------------+
//| Construtor                                                      |
//+------------------------------------------------------------------+
CPicture::CPicture(void) : m_path("Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp")

  {
//--- Armazena o nome da classe de controle na classe base
   CElement::ClassName(CLASS_NAME);
//--- Define as prioridades do botão esquerdo do mouse
   m_zorder=0;
  }
//+------------------------------------------------------------------+
//| Define a imagem                                                |
//+------------------------------------------------------------------+
void CPicture::Path(const string path)
  {
   m_path=path;
   m_picture.BmpFileOn("::"+path);
   m_picture.BmpFileOff("::"+path);
  }

Quanto ao controle do rótulo de texto, tudo é bastante simples e apenas quatro propriedades podem ser definidas pelo usuário:

  • Texto do rótulo
  • Cor do texto
  • Fonte
  • Tamanho da fonte
//+------------------------------------------------------------------+
//| Classe para a criação de um rótulo de texto                                |
//+------------------------------------------------------------------+
class CTextLabel : public CElement
  {
public:
   //--- Obtém/define o texto do rótulo
   string            LabelText(void)             const { return(m_label.Description()); }
   void              LabelText(const string text)      { m_label.Description(text);     }
   //--- Define a (1) cor, (2) a fonte e (3) o tamanho da fonte do rótulo de texto
   void              LabelColor(const color clr)       { m_label.Color(clr);            }
   void              LabelFont(const string font)      { m_label.Font(font);            }
   void              LabelFontSize(const int size)     { m_label.FontSize(size);        }
  };

 

Classe CFonts para trabalhar com as fontes de texto

Para facilitar a seleção da fonte, foi implementado uma classe adicional - CFonts. Ela contém 187 fontes. Essas são as fontes do sistema do terminal, que você provavelmente já viu listados nas configurações de certos objetos gráficos.

 Fig. 3. Fontes do sistema do terminal.

Fig. 3. Fontes do sistema do terminal.


O arquivo com as fontes (Fonts.mqh) está localizado na pasta "MetaTrader 5\MQL5\Include\EasyAndFastGUI\Fonts.mqh". Ele foi incluído no arquivo Objects.mqh para permitir o acesso total ao longo de todo o esquema da biblioteca:

//+------------------------------------------------------------------+
//|                                                      Objects.mqh |
//|                Copyright 2015, MetaQuotes Software Corp. |
//|                                                      http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Enums.mqh"
#include "Defines.mqh"
#include "..\Fonts.mqh"
#include "..\Canvas\Charts\LineChart.mqh"
#include <ChartObjects\ChartObjectSubChart.mqh>
#include <ChartObjects\ChartObjectsBmpControls.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>

A classe CFonts contém apenas dois métodos públicos para obter o tamanho do array de fontes e obter o nome da fonte pelo índice. O array de fontes é inicializado no construtor da classe

//+------------------------------------------------------------------+
//|                                                        Fonts.mqh |
//|                 Copyright 2016, MetaQuotes Software Corp. |
//|                                                      http://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Classe para trabalhar com a fonte                                      |
//+------------------------------------------------------------------+
class CFonts
  {
private:
   //--- Array de fontes
   string            m_fonts[];
   //---
public:
                     CFonts(void);
                    ~CFonts(void);
   //--- Retorna o número de tipos de fontes
   int               FontsTotal(void) const { return(::ArraySize(m_fonts)); }
   //--- Retorna a fonte pelo índice
   string            FontsByIndex(const uint index);
   //---
private:
   //--- Inicializa o array de fontes
   void              InitializeFontsArray(void);
  };
//+------------------------------------------------------------------+
//| Construtor                                                      |
//+------------------------------------------------------------------+
CFonts::CFonts(void)
  {
//--- Inicializa o array de fontes
   InitializeFontsArray();
  }
//+------------------------------------------------------------------+
//| Destrutor                                                       |
//+------------------------------------------------------------------+
CFonts::~CFonts(void)
  {
   ::ArrayFree(m_fonts);
  }

A Chamada do método CFonts::FontsByIndex() recorre ao ajuste que impede que o tamanho do array exceda:

//+------------------------------------------------------------------+
//| Retorna a fonte pelo índice                                       |
//+------------------------------------------------------------------+
string CFonts::FontsByIndex(const uint index)
  {
//--- Tamanho do array
   uint array_size=FontsTotal();
//--- Ajuste no caso do tamanho ter excedido
   uint i=(index>=array_size)? array_size-1 : index;
//--- Retorna a fonte
   return(m_fonts[i]);
  }

 

Lista de atualizações adicionais da biblioteca

1. Corrigido a exibição incorreta das dicas de ferramentas nas caixas de diálogo. Agora, o estado pressionado do botão dicas de ferramentas na janela principal se aplica a todas as janelas da interface gráfica. Ao pressionar o botão, ele gera uma mensagem com o novo identificador de evento ON_WINDOW_TOOLTIPS (consulte o arquivo Defines.mqh).

//+------------------------------------------------------------------+
//|                                                      Defines.mqh |
//|                Copyright 2015, MetaQuotes Software Corp. |
//|                                                      http://www.mql5.com |
//+------------------------------------------------------------------+
...
#define ON_WINDOW_TOOLTIPS         (29) // Clique no botão dicas de ferramentas

Por conseguinte, o método OnClickTooltipsButton() foi adicionado a classe CWindow para lidar com o botão de dicas de ferramentas: 

//+------------------------------------------------------------------+
//| Classe para criar um formulário para os controles                     |
//+------------------------------------------------------------------+
class CWindow : public CElement
  {
private:
//--- Manipulação do evento de clique no botão dicas de ferramentas
   bool              OnClickTooltipsButton(const string clicked_object);
  };
//+------------------------------------------------------------------+
//| Manipulador de eventos do gráfico                                        |
//+------------------------------------------------------------------+
void CWindow::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Manipulação de eventos do clique em um objeto
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Se o botão de dicas de ferramentas foi clicado
      if(OnClickTooltipsButton(sparam))
         return;
     }
  }
//+------------------------------------------------------------------+
//| Manipulação do evento de clique no botão dicas de ferramentas           |
//+------------------------------------------------------------------+
bool CWindow::OnClickTooltipsButton(const string clicked_object)
  {
//--- Este botão não é necessário, se a janela for uma caixa de diálogo
   if(m_window_type==W_DIALOG)
      return(false);
//--- Sai, se o clique não estiver no botão de radio
   if(::StringFind(clicked_object,CElement::ProgramName()+"_window_tooltip_",0)<0)
      return(false);
//--- Obtém o identificador do controle a partir do nome do objeto
   int id=CElement::IdFromObjectName(clicked_object);
//--- Sai, se os identificadores do controle não corresponderem
   if(id!=CElement::Id())
      return(false);
//--- Armazena o estado no campo da classe
   m_tooltips_button_state=m_button_tooltip.State();
//--- Envia uma mensagem sobre ele
   ::EventChartCustom(m_chart_id,ON_WINDOW_TOOLTIPS,CElement::Id(),CElement::Index(),"");
   return(true);
  }

Por que tudo isto funcione no motor da biblioteca (classe CWndEvents), o método OnWindowTooltips() para tratamento de eventos com o identificador ON_WINDOW_TOOLTIPS foi adicionado: 

class CWndEvents : public CWndContainer
  {
private:
   //--- Ativar/desativar as dicas de ferramentas
   bool              OnWindowTooltips(void);
  };
//+------------------------------------------------------------------+
//| Evento CHARTEVENT_CUSTOM                                         |
//+------------------------------------------------------------------+
void CWndEvents::ChartEventCustom(void)
  {
//--- Se o sinal for para minimizar o formulário
//--- Se o sinal for para maximizar o formulário
//--- Se o sinal for para redimensionar os controles ao longo do eixo X
//--- Se o sinal for para redimensionar os controles ao longo do eixo Y
//--- Se o sinal for para ativar/desativar as dicas de ferramentas
   if(OnWindowTooltips())
      return;

//--- Se o sinal é para ocultar os menus de contexto abaixo do elemento inicial
//--- Se o sinal for para esconder todos os menus de contexto
//--- Se o sinal é para abrir uma janela de diálogo
//--- Se o sinal é para fechar uma janela de diálogo
//--- Se o sinal estiver é para resetar as cores de todos os elementos na formulário especificado
//--- Se o sinal for para resetar as prioridades do clique do botão esquerdo do mouse
//--- Se o sinal for para restaurar as prioridades do clique do botão esquerdo do mouse
  }
//+------------------------------------------------------------------+
//| Evento ON_WINDOW_TOOLTIPS                                        |
//+------------------------------------------------------------------+
bool CWndEvents::OnWindowTooltips(void)
  {
//--- Se o sinal for para "Ativar/desativar as dicas de ferramentas"
   if(m_id!=CHARTEVENT_CUSTOM+ON_WINDOW_TOOLTIPS)
      return(false);
//--- Se a janela de identificadores correspondem entre si
   if(m_lparam!=m_windows[0].Id())
      return(true);
//--- Sincroniza o modo de dicas de ferramentas em todas as janelas
   int windows_total=WindowsTotal();
   for(int w=0; w<windows_total; w++)
     {
      if(w>0)
         m_windows[w].TooltipButtonState(m_windows[0].TooltipButtonState());
     }
//---
   return(true);
  }

2. Adicionado a capacidade de mudar o texto na descrição dos seguintes controles adicionados depois de terem sido criados: 

 

Fig. 4. Lista de controles com a capacidade de alterar o texto depois de terem sido criados.


3. Agora o ícone pode ser definido em todos os controles, onde ele pode ser necessário (veja a tabela abaixo). Além disso, foi adicionado a capacidade de alterar os ícones do controle após eles terem sido criados:


 

Fig. 5. Lista de controles com a capacidade de alterar o ícone, após eles terem sido criados.

 

Para substituir o ícone em todos os controlos listados na tabela acima, há os métodos IconFileOn() e IconFileOff().


4. Adicionado a capacidade de gerenciar de forma programática o estado de todos os tipos de botões e guias (pressionado/solto) depois de terem sido criados. A tabela abaixo mostra os controles que incluem esta adição:

 

Fig. 6. Lista de controles com a capacidade de alterar o estado (pressionado/solto) depois de terem sido criados.


5. Otimizado o algoritmo para destacar os itens quando o cursor está pairando sobre eles nos seguintes controles:

 

Fig. 7. Controles com o algoritmo otimizado para destacar os itens de controle.

 

Anteriormente, o programa iterava todos os itens nas listas dos controles acima, verificando a localização do cursor do mouse por cima deles. Assim, o item sob o cursor foi destacado em uma cor diferente, enquanto a cor padrão foi definida para o restante dos itens. Mas este método exige um recurso muito intensivo, de modo que havia uma necessidade para otimiza-lo. Agora, em vez dele ficar iterando em todo o conjunto de itens, apenas dois itens participam da mudança de cor. A pesquisa no ciclo só ocorre quando houver uma transição para outro item, ou seja, o foco foi alterado. 

Além disso, como um exemplo, considere como este foi implementado na classe CListView. A Implementação acima requer a adição do campo da classe (1) m_prev_item_index_focus para armazenar o índice do último item focado, (2) o método CListView::CheckItemFocus() para verificar o foco sobre o item e (3) para alterar o algoritmo no método CListView::ChangeItemsColor().  

//+------------------------------------------------------------------+
//| Classe para criar uma lista                                   |
//+------------------------------------------------------------------+
class CListView : public CElement
  {
private:
   //--- Para determinar o momento de transição do cursor do mouse de um item para o outro
   int               m_prev_item_index_focus;
   //---
private:
   //--- Mudando a cor dos itens da lista quando o cursor está pairando sobre eles
   void              ChangeItemsColor(void);
   //--- Verificando o foco da lista dos itens da lista quando o cursor está pairado
   void              CheckItemFocus(void);
  };

O método CListView::CheckItemFocus() é chamado somente quando o cursor do mouse entra na área de controle (neste caso - CListView), e também quando o cursor do mouse se move de um item para o outro (veja o código abaixo). Uma vez que o item com o mouse pairando nele for encontrado, o seu índice é armazenado

//+------------------------------------------------------------------+
//| Verifica o foco da lista de itens da lista quando o cursor está pairado   |
//+------------------------------------------------------------------+
void CListView::CheckItemFocus(void)
  {
//--- Obtém a posição atual do controle deslizante da barra de rolagem
   int v=m_scrollv.CurrentPos();
//--- Identifica sobre qual item o cursor está e destaca-o
   for(int i=0; i<m_visible_items_total; i++)
     {
      //--- Aumenta o contador se o tamanho da lista não for excedido
      if(v>=0 && v<m_items_total)
         v++;
      //--- Pula o elemento selecionado
      if(m_selected_item_index==v-1)
        {
         m_items[i].BackColor(m_item_color_selected);
         m_items[i].Color(m_item_text_color_selected);
         continue;
        }
      //--- Se o cursor está sobre este elemento, destaca-o
      if(m_mouse.X()>m_items[i].X() && m_mouse.X()<m_items[i].X2() &&
         m_mouse.Y()>m_items[i].Y() && m_mouse.Y()<m_items[i].Y2())
        {
         m_items[i].BackColor(m_item_color_hover);
         m_items[i].Color(m_item_text_color_hover);
         //--- Lembrando do elemento
         m_prev_item_index_focus=i;
         break;
        }
     }
  }

O método CListView::CheckItemFocus() é chamado de dentro do método CListView::ChangeItemsColor() nos casos descritos no parágrafo anterior (veja o código abaixo):

//+------------------------------------------------------------------+
//| Mudando a cor da lista de itens da lista quando o cursor está pairado |
//+------------------------------------------------------------------+
void CListView::ChangeItemsColor(void)
  {
//--- Sai, se o realce do item quando o cursor está pairando sobre ele está desativado ou a barra de rolagem está ativa
   if(!m_lights_hover || m_scrollv.ScrollState())
      return;
//--- Sai, se não for um elemento suspenso e o formulário está bloqueado
   if(!CElement::IsDropdown() && m_wnd.IsLocked())
      return;
//--- Se entrou na lista novamente
   if(m_prev_item_index_focus==WRONG_VALUE)
     {
      //--- Verifica o foco no item atual
      CheckItemFocus();
     }
   else
     {
      //--- Verifica o foco na linha atual
      int i=m_prev_item_index_focus;
      bool condition=m_mouse.X()>m_items[i].X() && m_mouse.X()<m_items[i].X2() &&
                     m_mouse.Y()>m_items[i].Y() && m_mouse.Y()<m_items[i].Y2();
      //--- Se mudou para outro item
      if(!condition)
        {
       //--- Reseta a cor do elemento de menu
         m_items[i].BackColor(m_item_color);
         m_items[i].Color(m_item_text_color);
         m_prev_item_index_focus=WRONG_VALUE;
         //--- Verifica o foco no item atual
         CheckItemFocus();
        }
     }
  }

No manipulador de evento CListView::OnEvent(), o método CListView::ChangeItemsColor() é chamado somente quando o cursor do mouse está localizado dentro da área do controle. Assim que o cursor sair da área de controle, as cores padrão são definidas, e o valor do índice do item é resetado. A versão curta do manipulador de eventos é mostrada abaixo. 

//+------------------------------------------------------------------+
//| Manipulador de eventos                                                   |
//+------------------------------------------------------------------+
void CListView::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Manipulação do evento de movimento do cursor
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      //--- Sai se o elemento está oculto
      //--- Sai, se os números das sub-janelas não corresponderem
      //--- Verificando o foco sobre os elementos
      //--- Se esta é uma lista suspensa e o botão do mouse foi pressionado
      //--- Mova a lista se a gestão do controle slider for habilitado

      //--- Reseta a cor do elemento, se não estiver em foco
      if(!CElement::MouseFocus())
        {
         //--- Se o item já está em foco
         if(m_prev_item_index_focus!=WRONG_VALUE)
           {
            //--- Reseta a cor da lista
            ResetColors();
            m_prev_item_index_focus=WRONG_VALUE;
           }
         return;
        }
      //--- Muda a cor dos itens da lista quando o cursor está pairando sobre ele
      ChangeItemsColor();
      return;
     }
  }

O mesmo princípio foi aplicado nas classes CTable, CCalendar e CTreeView, mas com algumas diferenças que levam em conta as peculiaridades de cada controle.

6. Pressionando um botão do tipo CIconButton no modo de dois estados (quando o botão não é liberado após o clique), ele mostra um ícone diferente, se estiver definido. O ícone para o botão pressionado pode ser definido usando os métodos CIconButton::IconFilePressedOn() e CIconButton::IconFilePressedOff()

//+------------------------------------------------------------------+
//| Classe para criar um botão de Ícone |
//+------------------------------------------------------------------+
class CIconButton : public CElement
  {
private:
   //--- Ícones para o botão em estados ativos, bloqueados e pressionados
   string            m_icon_file_on;
   string            m_icon_file_off;
   string            m_icon_file_pressed_on;
   string            m_icon_file_pressed_off;

   //---
public:
   //--- Definindo os ícones para o botão nos estados pressionados, ativos e bloqueados
   void              IconFileOn(const string file_path);
   void              IconFileOff(const string file_path);
   void              IconFilePressedOn(const string file_path);
   void              IconFilePressedOff(const string file_path);

  };
//+------------------------------------------------------------------+
//| Define o ícone para o estado pressionado "ON"              |
//+------------------------------------------------------------------+
void CIconButton::IconFilePressedOn(const string file_path)
  {
//--- Sai, se o modo de dois estados estiver desativado para o botão
   if(!m_two_state)
      return;
//--- Armazena o caminho para a imagem
   m_icon_file_pressed_on=file_path;
//--- Determina imediatamente se o botão é pressionado
   if(m_button.State())
      m_icon.BmpFileOn("::"+file_path);
  }
//+------------------------------------------------------------------+
//| Define o ícone para o estado pressionado "OFF"              |
//+------------------------------------------------------------------+
void CIconButton::IconFilePressedOff(const string file_path)
  {
//--- Sai, se o modo de dois estados estiver desativado para o botão
   if(!m_two_state)
      return;
//--- Armazena o caminho para a imagem
   m_icon_file_pressed_off=file_path;
//--- Determina imediatamente se o botão é pressionado
   if(m_button.State())
      m_icon.BmpFileOff("::"+file_path);
  }

7. Adicionado a capacidade de selecionar programaticamente uma linha na tabela (CTable). Para fazer isso, use o método CTable::SelectRow(). Especificando o índice de uma linha já selecionada, ela é desmarcada. 

//+------------------------------------------------------------------+
//| Classe para a criação de uma tabela da caixa de edição |
//+------------------------------------------------------------------+
class CTable : public CElement
  {
public:
   //--- Escolha uma linha específica da tabela
   void              SelectRow(const uint row_index);
  };
//+------------------------------------------------------------------+
//| Seleciona a linha especificada da tabela                            |
//+------------------------------------------------------------------+
void CTable::SelectRow(const uint row_index)
  {
//--- Ajuste no caso do tamanho ser excedido
   uint index=(row_index>=(uint)m_rows_total)? m_rows_total-1 : row_index;
//--- Se esta linha estiver selecionada, desmarque-a
   bool is_selected=(index==m_selected_item);
//--- Armazena o índice de linha
   m_selected_item=(is_selected)? WRONG_VALUE : (int)index;
//--- Armazena a linha da célula
   m_selected_item_text=(is_selected)? "" : m_vcolumns[0].m_vrows[index];
//--- Gera uma string com os parâmetros da célula
   string cell_params=string(0)+"_"+string(index)+"_"+m_vcolumns[0].m_vrows[index];
//--- Reseta o foco
   m_prev_item_index_focus=WRONG_VALUE;
//--- Atualiza a tabela
   UpdateTable();
//--- Destaca uma linha selecionada
   HighlightSelectedItem();
  }

8. Corrigido um problema com a exibição dos elementos em uma guia selecionada do controle CIconTabs. O problema ocorria ao abrir e maximizando um formulário com este tipo de guias. 

 

Aplicação para testar os controles

Vamos escrever um aplicativo de teste, onde você pode testar todos os novos controles e praticar por si próprio, avaliando os seus diferentes modos. Na interface gráfica da aplicação, crie um controle Tabs (classe CTabs), que conterá quatro guias com o seguinte conteúdo:

1. A primeira guia:

  • Barra de progresso (CProgressBar).
  • Caixa de edição de texto(CTextEdit).
  • Combobox com uma lista suspensa (CComboBox).
  • Campo de edição para valores numéricos (CSpinEdit).
  • Botão para chamar o seletor de cores (CColorButton).
  • Rótulo de texto (CTextLabel).

Define um ícone para todos os controles, exceto o rótulo de texto. As descrições dos controles barra de progresso e da caixa de edição de texto serão alterados em intervalos de tempo regulares, a fim de demonstrar que tal recurso já está disponível. Coloque o nome de todas as fontes da classe CFonts para a lista da caixa de combinação. O modelo de evento da aplicação de teste MQL será construída de tal forma que a seleção de uma fonte na caixa de combinação é refletida no rótulo de texto. Da mesma forma, o rótulo de texto será ligado a caixa de edição numérica para mudar o tamanho da fonte e a seleção de cor no seletor. 

O manipulador de eventos para gerenciar os parâmetros do controle Rótulo de texto ficará da seguinte forma:

//+------------------------------------------------------------------+
//| Chart event handler                                        |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Evento de seleção da lista combobox
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_COMBOBOX_ITEM)
     {
      //--- Se os identificadores de controle correspondem entre si
      if(lparam==m_combobox1.Id())
        {
         //--- Altera a fonte
         m_text_label1.LabelFont(m_combobox1.ButtonText());
        }
      //---
      return;
     }
//--- Evento do clique nos botões caixa de edição
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_INC ||
      id==CHARTEVENT_CUSTOM+ON_CLICK_DEC)
     {
      //--- Se os identificadores de controle correspondem entre si
      if(lparam==m_spin_edit1.Id())
        {
         //--- Altera o tamanho da fonte
         m_text_label1.LabelFontSize(int(m_spin_edit1.GetValue()));
        }
      //---
      return;
     }
//--- Evento de mudar a cor usando o seletor de cores
   if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
     {
      //--- Se os identificadores do controle correspondem entre si
      if(lparam==m_spin_edit1.Id())
        {
         //--- Altera o tamanho da fonte
         m_text_label1.LabelFontSize(int(m_spin_edit1.GetValue()));
        }
      //---
      return;
     }
//--- Evento de mudar a cor usando o seletor de cores
   if(id==CHARTEVENT_CUSTOM+ON_CHANGE_COLOR)
     {
      //--- Se os identificadores de controle correspondem entre si
      if(lparam==m_color_picker.Id())
        {
         //--- Se a resposta é a partir do primeiro botão
         if(sparam==m_color_button1.LabelText())
           {
            //--- Muda a cor do objeto
            m_text_label1.LabelColor(m_color_button1.CurrentColor());
            return;
           }
        }
      return;
     }
//--- O evento de pressionamento do botão
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
     {
      //--- Se o primeiro botão para chamar o seletor de cores foi pressionado
      if(sparam==m_color_button1.LabelText())
        {
         //--- Passa o ponteiro do botão, que abre automaticamente a janela com o seletor de cores
         m_color_picker.ColorButtonPointer(m_color_button1);
         return;
        }
      //---
      return;
     }
  }

A imagem abaixo mostra como a visualização do texto pode ser configurada usando a interface gráfica.

Fig. 8. Grupo de controles na primeira guia. 

Fig. 8. Grupo de controles na primeira guia.


2. Apenas um controle - o Slider de Imagem (classe CPicturesSlider) será colocada na segunda aba. Apenas três imagens padrão serão adicionadas ao grupo, de modo que você pode testar rapidamente esse controle por si próprio. Para o controle funcionar corretamente, prepare as imagens com o mesmo tamanho.

Fig. 9. O controle Slider de Imagem na segunda guia. 

Fig. 9. O controle Slider de Imagem na segunda guia.


Para alternar programaticamente as imagens, use o método CPicturesSlider::SelectPicture().


3. A terceira guia irá conter uma tabela do tipo CTable. Para programaticamente selecionar uma linha, use o método CTable::SelectRow(). 

 Fig. 10. O controle Table na terceira guia.

Fig. 10. O controle Table na terceira guia.


4. Três controles serão localizados na quarta guia: (1) calendário, (2) calendário suspenso e (3) um botão com dois ícones diferentes para os estados pressionado/liberado.

Fig. 11. Grupo de controles sobre a quarta guia. 

Fig. 11. Grupo de controles sobre a quarta guia.

 

O aplicativo de teste apresentado no artigo pode ser baixado usando o link abaixo para estudá-lo ainda mais. 


Conclusão

A biblioteca para a criação de interfaces gráficas no atual estágio de desenvolvimento se parece com o esquema abaixo.

 Fig. 12. Estrutura da biblioteca no atual estágio de desenvolvimento.

Fig. 12. Estrutura da biblioteca no atual estágio de desenvolvimento.


Na próxima versão, a biblioteca será expandida com controles adicionais. Além disso, os controles existentes continuarão a serem desenvolvidos e ampliados com novas funcionalidades.

Se você tiver dúvidas sobre a utilização do material a partir desses arquivos, você poderá consultar a descrição detalhada do desenvolvimento da biblioteca em um dos artigos da lista abaixo ou fazer sua pergunta nos comentários deste artigo. 

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

Arquivos anexados |
Três Aspectos Sobre Automação da Negociação Manual. Parte 1: Negociação Três Aspectos Sobre Automação da Negociação Manual. Parte 1: Negociação
Este artigo é o primeiro de uma série de artigos sobre automação da negociação manual na plataforma МetaТrader 4. Cada artigo será dedicado a um dos seguintes aspectos: automação da negociação manual, atual estado da exibição da automação da negociação e automação dos relatórios sobre os resultados da negociação. Neste artigo, vou apresentar uma abordagem interessante para a criação de EAs controlados manualmente por um trader.
Como desenvolver e testar uma estratégia para Opções Binárias com o Testador de Estratégia do MetaTrader 4 Como desenvolver e testar uma estratégia para Opções Binárias com o Testador de Estratégia do MetaTrader 4
Tutorial para desenvolver uma estratégia para Opções Binárias e testa-la no Testador de Estratégia do MetaTrader 4 com o utilitário do Mercado Binary-Options-Strategy-Tester.
Padrões disponíveis ao negociar cestas de moedas Padrões disponíveis ao negociar cestas de moedas
Seguindo o nosso artigo anterior, sobre os princípios de negociação de cestas de moeda, vamos analisar os padrões que os traders podem detectar. Também consideraremos as vantagens e desvantagens de cada padrão e forneceremos algumas recomendações sobre seu uso. Os indicadores baseados no oscilador Williams, serão utilizados como ferramentas de análise.
Distribuições estatísticas em forma de histogramas sem buffers de indicador e matrizes Distribuições estatísticas em forma de histogramas sem buffers de indicador e matrizes
O artigo considera a possibilidade de criar histogramas, distribuições estatísticas das características do mercado usando memória gráfica, ou seja, sem o uso de buffers de indicador e matrizes. Aqui você tem à sua disposição não só exemplos detalhados de como construir esses histogramas, mas também pode conhecer a funcionalidade "oculta" dos objetos gráficos da linguagem MQL5.