English Русский 中文 Español Deutsch 日本語
Interfaces Gráficas IX: O Controle Seletor de Cores (Capítulo 1)

Interfaces Gráficas IX: O Controle Seletor de Cores (Capítulo 1)

MetaTrader 5Exemplos | 7 novembro 2016, 09:19
1 104 0
Anatoli Kazharski
Anatoli Kazharski

Conteúdo

 

Introdução

Por favor, leia o primeiro artigo chamado Interfaces Gráficas I: Preparação da Estrutura da Biblioteca (Capítulo 1) para obter uma melhor compreensão da finalidade desta biblioteca. No final dos artigos de cada parte há uma lista de capítulos com os links, e você poderá baixar também uma versão completa da biblioteca no atual estágio de seu desenvolvimento. Os arquivos devem estar localizados nas mesmas pastas que o arquivo baixado.

A parte IX desta série irá descrever os seguintes elementos de controle e interface:

1. Primeiro capítulo:

  • Controle seletor de cores (classe CColorPicker).
  • Controle botão do seletor de cores (classe CColorButton).

2. Segundo capítulo:

  • Controle barra de progresso (classe CProgressBar).
  • Controle gráfico de linha (classe CLineGraph).

Haverá exemplos detalhados para todos os controlos mencionados acima, mostrando como eles poderão ser aplicados em uma aplicação personalizada.

 

Controle seletor de cores

Uma paleta de cores pode ser encontrada em várias aplicações que possuem uma opção para escolher a cor do objeto. Nos terminais de negociação MetaTrader, a paleta de cor pode ser usada para alterar rapidamente a cor dos controles em sua aplicação MQL. Por exemplo, ao criar um estúdio visual para as interfaces gráficas e as cores precisam ser definidas para cada controle, seria muito inconveniente fazê-la sem uma paleta de cores.

A paleta de cores é um elemento composto complexo do controle, que além da paleta atual exibir o modelo de cor selecionado, há também outros objetos e grupos de controles. As partes integrantes deste controle estão listadas abaixo.

  1. Fundo
  2. Paleta de cor que exibe um modelo de cor especificado
  3. Marcador da cor definida
  4. Marcador da cor selecionada
  5. Marcador da cor quando o mouse estiver sobre ela
  6. Grupo de botões de rádio com as caixas de edição para uma configuração manual dos componentes do modelo de cor
  7. Botão para cancelar a cor selecionada
  8. Botão para configurar (correção) a cor especificada no segundo marcador

 

Fig. 1. Partes componente do seletor de cor.

A imagem acima mostra que o grupo de botões de radio é dividido em três subgrupos, possuindo três botões de radio cada um. Cada subgrupo é um modelo de cor, e cada botão de radio é um componente deste modelo (coordenada da área de cores). A lista abaixo fornece a decifração das abreviações de todos os modelos de cores que serão utilizados durante a criação de uma paleta de cores para a biblioteca desenvolvida.

1. HSL modelo de cor:

  • H - matiz. Faixa de valores a partir do 0 até 360
  • S - saturação. Faixa de valores a partir do 0 até 100.
  • L - Luminosidade. Faixa de valores a partir do 0 até 100.

2. RGB modelo de cor:

  • R - cor vermelha. Faixa de valores do 0 até 255.
  • G - cor verde. Faixa de valores do 0 até 255.
  • B - cor azul. Faixa dos valores do 0 até 255.

3. Lab modelo de cor:

  • L - Luminância. Faixa de valores a partir do 0 até 100.
  • a - Primeira coordenada cromática que define o tom de cor de verde para roxo. Faixa de valores de 128 até 127.
  • b - Segunda coordenada cromática que define o tom de cor de azul para amarelo. Faixa de valores de 128 até 127.

Além disso, nós vamos analisar a classe CColorPicker para criar a paleta de cor.

 

Desenvolvimento da classe CColorPicker

Nós vamos criar o arquivo ColorPicker.mqh no mesmo diretório onde os arquivos dos controles restantes estão mantidos atualmente (<pasta de dados>\MQLX\Include\EasyAndFastGUI\Controls). Neste arquivo nós devemos criar a classe CColorPicker com os membros padrão como é mostrado no código abaixo:

//+------------------------------------------------------------------+
//|                                                  ColorPicker.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
#include "Window.mqh"
//+------------------------------------------------------------------+
//| Classe para a criação do seletor de cores                        |
//+------------------------------------------------------------------+
class CColorPicker : public CElement
  {
private:
   //--- Ponteiro para o formulário ao qual o controle será anexado
   CWindow          *m_wnd;
   //---
public:
                     CColorPicker(void);
                    ~CColorPicker(void);
   //---
public:
   //--- Armazena o ponteiro do formulário
   void              WindowPointer(CWindow &object)           { m_wnd=::GetPointer(object);            }
   //---
public:
   //--- Manipulador de eventos do gráfico
   virtual void      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   //--- Timer
   virtual void      OnEventTimer(void);
   //--- Mover o controle
   virtual void      Moving(const int x,const int y);
   //--- (1) Exibe, (2) oculta, (3) reseta, (4) remove
   virtual void      Show(void);
   virtual void      Hide(void);
   virtual void      Reset(void);
   virtual void      Delete(void);
   //--- (1) Define (2), reseta as prioridades para o clique esquerdo do mouse
   virtual void      SetZorders(void);
   virtual void      ResetZorders(void);
   //--- Resetar a cor
   virtual void      ResetColors(void) {}
  };

As seguintes propriedades estarão disponíveis para definir os objetos gráficos do controle:

  • Cor de fundo do controle
  • Cor da borda de fundo do controle
  • Cor da borda da paleta de cores e dos marcadores

As propriedades dos objetos gráficos de outros controles podem ser alteradas após o recebimento do ponteiro. 

class CColorPicker : public CElement
  {
private:
   //--- Cor da (1) área e (2) da borda da área
   color             m_area_color;
   color             m_area_border_color;
   //--- Cor da borda da paleta
   color             m_palette_border_color;
   //---
public:
   //--- Definição da cor (1) da área e (2) da borda da área (3), paleta da borda
   void              AreaBackColor(const color clr)           { m_area_color=clr;                      }
   void              AreaBorderColor(const color clr)         { m_area_border_color=clr;               }
   void              PaletteBorderColor(const color clr)      { m_palette_border_color=clr;            }
  };

Já que outros controles serão utilizadas como partes integrantes da paleta de cores, é necessário conectar os arquivos com as classes destes controles para o arquivo ColorPicker.mqh. Serão necessários de 17 métodos privados e um público para a criação da paleta de cores.

//+------------------------------------------------------------------+
//|                                                  ColorPicker.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
#include "Window.mqh"
#include "SpinEdit.mqh"
#include "SimpleButton.mqh"
#include "RadioButtons.mqh"
//+------------------------------------------------------------------+
//| Classe para a criação das paleta de cores       |
//+------------------------------------------------------------------+
class CColorPicker : public CElement
  {
private:
   //--- Objetos para criar o controle
   CRectLabel        m_area;
   CRectCanvas       m_canvas;
   CRectLabel        m_current;
   CRectLabel        m_picked;
   CRectLabel        m_hover;
   //---
   CRadioButtons     m_radio_buttons;
   CSpinEdit         m_hsl_h_edit;
   CSpinEdit         m_hsl_s_edit;
   CSpinEdit         m_hsl_l_edit;
   //---
   CSpinEdit         m_rgb_r_edit;
   CSpinEdit         m_rgb_g_edit;
   CSpinEdit         m_rgb_b_edit;
   //---
   CSpinEdit         m_lab_l_edit;
   CSpinEdit         m_lab_a_edit;
   CSpinEdit         m_lab_b_edit;
   //---
   CSimpleButton     m_button_ok;
   CSimpleButton     m_button_cancel;
   //---
public:
   //--- Métodos para criar o controle
   bool              CreateColorPicker(const long chart_id,const int subwin,const int x,const int y);
   //---
private:
   bool              CreateArea(void);
   bool              CreatePalette(void);
   bool              CreateCurrentSample(void);
   bool              CreatePickedSample(void);
   bool              CreateHoverSample(void);
   bool              CreateRadioButtons(void);
   bool              CreateHslHEdit(void);
   bool              CreateHslSEdit(void);
   bool              CreateHslLEdit(void);
   bool              CreateRgbREdit(void);
   bool              CreateRgbGEdit(void);
   bool              CreateRgbBEdit(void);
   bool              CreateLabLEdit(void);
   bool              CreateLabAEdit(void);
   bool              CreateLabBEdit(void);
   bool              CreateButtonOK(const string text);
   bool              CreateButtonCancel(const string text);
  };

Alterando o botão de radio ao lado da paleta de cores, será exibido dois cortes dimensionais nas áreas de cor de acordo com o valor indicado do componente selecionado. Em outras palavras, para desenhar cada corte, primeiro você precisa fazer o cálculo em relação ao valor atual de seu componente. Portanto, nós vamos escrever três métodos distintos para cada modelo de cor. O índice do botão de radio selecionado será enviado para todos estes métodos (índice selecionado).

Para alterar a cor, nós usamos os métodos da instância da classe CColors que é declarado na classe base do controle (CElement). Não há um método apropriado na classe CColors para a conversão do formato RGB para Lab. Portanto, onde a conversão RGB->Lab é necessária, será preciso aplicar uma correção dupla através do modelo mestre de cor XYZ: RGB->XYZ->Lab. Para calcular e armazenar os valores dos componentes de todos os modelos de cores na classe CColorPicker, será necessário definir campos relevantes.

class CColorPicker : public CElement
  {
private:
   //--- Valores dos componentes em modelos de cores diferentes:
   //    HSL
   double            m_hsl_h;
   double            m_hsl_s;
   double            m_hsl_l;
   //--- RGB
   double            m_rgb_r;
   double            m_rgb_g;
   double            m_rgb_b;
   //--- Lab
   double            m_lab_l;
   double            m_lab_a;
   double            m_lab_b;
   //--- XYZ
   double            m_xyz_x;
   double            m_xyz_y;
   double            m_xyz_z;
   //---
private:
   //--- Desenha a paleta com base no modelo de cor HSL (0: H, 1: S, 2: L)
   void              DrawHSL(const int index);
   //--- Desenha a paleta com base no modelo de cor RGB (3: R, 4: G, 5: B)
   void              DrawRGB(const int index);
   //--- Desenha a paleta com base no modelo de cor LAB (6: G, 7: A, 8: b)
   void              DrawLab(const int index);
  };

Como um exemplo, nós vamos fornecer aqui um código de apenas um destes métodos - CColorPicker::DrawHSL(), já que a única diferença entre eles é o cálculo preliminar do valor componente antes da alteração. O código de outros métodos está disponível a partir dos arquivos anexados neste artigo. 

Os cálculos e desenhos são realizados para cada pixel da exibição. Por favor note que os cálculos são realizados em relação ao tamanho da paleta de cores. Ou seja, usando esse código você poderá criar um controle semelhante onde a paleta de cores pode ter um tamanho ou forma diferente (não necessariamente um quadrado).

 Fig. 2. Exemplo da paleta de cores no tamanho de 500x255 pixels.

Fig. 2. Exemplo da paleta de cores no tamanho de 500x255 pixels. 


//+------------------------------------------------------------------+
//| Desenha a paleta HSL                                            |
//+------------------------------------------------------------------+
void CColorPicker::DrawHSL(const int index)
  {
   switch(index)
     {
      //--- Matiz (H) - tom de cor que varia de 0 a 360
      case 0 :
        {
         //--- Cálculo do componente H
         m_hsl_h=m_hsl_h_edit.GetValue()/360.0;
         //---
         for(int ly=0; ly<m_canvas.YSize(); ly++)
           {
            //--- Calculo do componente L
            m_hsl_l=ly/(double)m_canvas.YSize();
            //---
            for(int lx=0; lx<m_canvas.XSize(); lx++)
              {
               //--- Cálculo do componente S
               m_hsl_s=lx/(double)m_canvas.XSize();
               //--- Conversão do componente HSL para o RGB
               m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
               //--- Liga os canais
               uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
               m_canvas.PixelSet(lx,m_canvas.YSize()-ly,rgb_color);
              }
           }
         break;
        }
      //--- Saturação (S) - saturação na faixa de 0 a 100
      case 1 :
        {
         //--- Cálculo do componente S
         m_hsl_s=m_hsl_s_edit.GetValue()/100.0;
         //---
         for(int ly=0; ly<m_canvas.YSize(); ly++)
           {
            //--- Calculo do componente L
            m_hsl_l=ly/(double)m_canvas.YSize();
            //---
            for(int lx=0; lx<m_canvas.XSize(); lx++)
              {
               //--- Cálculo do componente H
               m_hsl_h=lx/(double)m_canvas.XSize();
               //--- Conversão do componente HSL para o RGB
               m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
               //--- Liga os canais
               uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
               m_canvas.PixelSet(lx,m_canvas.YSize()-ly,rgb_color);
              }
           }
         break;
        }
      //--- Luminosidade (L) - luminosidade no intervalo de 0 a 100
      case 2 :
        {
         //--- Calculo do componente L
         m_hsl_l=m_hsl_l_edit.GetValue()/100.0;
         //---
         for(int ly=0; ly<m_canvas.YSize(); ly++)
           {
            //--- Cálculo do componente S
            m_hsl_s=ly/(double)m_canvas.YSize();
            //---
            for(int lx=0; lx<m_canvas.XSize(); lx++)
              {
               //--- Cálculo do componente H
               m_hsl_h=lx/(double)m_canvas.XSize();
               //--- Conversão do componente HSL para o RGB
               m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
               //--- Liga os canais
               uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
               m_canvas.PixelSet(lx,m_canvas.YSize()-ly,rgb_color);
              }
           }
         break;
        }
     }
  }

Nós vamos escrever o método CColorPicker::DrawPaletteBorder() desenhar uma borda sobre a tela da paleta de cores: 

class CColorPicker : public CElement
  {
private:
   //--- Desenha a borda da paleta
   void              DrawPaletteBorder(void);
  };
//+------------------------------------------------------------------+
//| Desenha a borda da paleta                                        |
//+------------------------------------------------------------------+
void CColorPicker::DrawPaletteBorder(void)
  {
//--- Tamanho da paleta
   int x_size=m_canvas.XSize()-1;
   int y_size=m_canvas.YSize()-1;
//--- Desenha a borda
   m_canvas.Line(0,0,x_size,0,m_palette_border_color);
   m_canvas.Line(0,y_size,x_size,y_size,m_palette_border_color);
   m_canvas.Line(0,0,0,y_size,m_palette_border_color);
   m_canvas.Line(x_size,0,x_size,y_size,m_palette_border_color);
  }

Todos os métodos acima mencionados para o desenho serão chamados eventualmente no método principal para desenhar a paleta de cores CColorPicker::DrawPalette()

class CColorPicker : public CElement
  {
private:
   //--- Desenha a paleta
   void              DrawPalette(const int index);
  };
//+------------------------------------------------------------------+
//| Desenha a paleta                                                 |
//+------------------------------------------------------------------+
void CColorPicker::DrawPalette(const int index)
  {
   switch(index)
     {
      //--- HSL (0: H, 1: S, 2: L)
      case 0 : case 1 : case 2 :
        {
         DrawHSL(index);
         break;
        }
      //--- RGB (3: R, 4: G, 5: B)
      case 3 : case 4 : case 5 :
        {
         DrawRGB(index);
         break;
        }
      //--- LAB (6: L, 7: a, 8: b)
      case 6 : case 7 : case 8 :
        {
         DrawLab(index);
         break;
        }
     }
//--- Desenha a borda da paleta
   DrawPaletteBorder();
//--- Atualiza a paleta
   m_canvas.Update();
  }

Ao selecionar a cor da paleta ou configurar um componente de qualquer modelo de cor apresentado em um controle, os valores em todas as caixas de edição serão automaticamente recalculados. Nós exigimos os métodos que podem ser utilizados para calcular os componentes de todos os modelos de cores do controle em relação aquele cujo corte (botão de radio selecionado) é apresentado na paleta no momento atual. 

Primeiramente, serão exigidos os métodos para corrigir os componentes RGB e os modelos HSL, que serão chamados em muitos outros métodos da classe:

class CColorPicker : public CElement
  {
private:
   //--- Correção dos componentes RGB
   void              AdjustmentComponentRGB(void);
   //--- Correção dos componentes HSL
   void              AdjustmentComponentHSL(void);
  };
//+------------------------------------------------------------------+
//| Correção dos componentes RGB                                     |
//+------------------------------------------------------------------+
void CColorPicker::AdjustmentComponentRGB(void)
  {
   m_rgb_r=::fmin(::fmax(m_rgb_r,0),255);
   m_rgb_g=::fmin(::fmax(m_rgb_g,0),255);
   m_rgb_b=::fmin(::fmax(m_rgb_b,0),255);
  }
//+------------------------------------------------------------------+
//| Correção dos componentes HSL                                     |
//+------------------------------------------------------------------+
void CColorPicker::AdjustmentComponentHSL(void)
  {
   m_hsl_h*=360;
   m_hsl_s*=100;
   m_hsl_l*=100;
  }

Após o cálculo de todos os componentes, nós precisamos definir os novos valores na caixa de edição. Em alguns casos, pode ser necessário (1) definir os valores de todos os componentes, e ocasionalmente (2) para todos além daquele selecionado no momento. Para essas situações, nós vamos escrever o método CColorPicker::SetControls() que pode funcionar em dois modos.

class CColorPicker : public CElement
  {
private:
   //--- Definindo os parâmetros atuais nas caixas de edição
   void              SetControls(const int index,const bool fix_selected);
  };
//+------------------------------------------------------------------+
//| Define os parâmetros atuais nas caixas de edição                 |
//+------------------------------------------------------------------+
void CColorPicker::SetControls(const int index,const bool fix_selected)
  {
//--- Se o valor precisar ser corrigido na caixa de edição do botão de radio selecionado
   if(fix_selected)
     {
      //--- Componentes HSL
      if(index!=0)
         m_hsl_h_edit.ChangeValue(m_hsl_h);
      if(index!=1)
         m_hsl_s_edit.ChangeValue(m_hsl_s);
      if(index!=2)
         m_hsl_l_edit.ChangeValue(m_hsl_l);
      //--- Componentes RGB
      if(index!=3)
         m_rgb_r_edit.ChangeValue(m_rgb_r);
      if(index!=4)
         m_rgb_g_edit.ChangeValue(m_rgb_g);
      if(index!=5)
         m_rgb_b_edit.ChangeValue(m_rgb_b);
      //--- Componentes Lab
      if(index!=6)
         m_lab_l_edit.ChangeValue(m_lab_l);
      if(index!=7)
         m_lab_a_edit.ChangeValue(m_lab_a);
      if(index!=8)
         m_lab_b_edit.ChangeValue(m_lab_b);
      return;
     }
//--- Se for necessário corrigir os valores nas caixas de edição de todos os modelos de cores
   m_hsl_h_edit.ChangeValue(m_hsl_h);
   m_hsl_s_edit.ChangeValue(m_hsl_s);
   m_hsl_l_edit.ChangeValue(m_hsl_l);
//---
   m_rgb_r_edit.ChangeValue(m_rgb_r);
   m_rgb_g_edit.ChangeValue(m_rgb_g);
   m_rgb_b_edit.ChangeValue(m_rgb_b);
//---
   m_lab_l_edit.ChangeValue(m_lab_l);
   m_lab_a_edit.ChangeValue(m_lab_a);
   m_lab_b_edit.ChangeValue(m_lab_b);
  }

Para calcular os componentes de todos os modelos de cores do controle sobre aquele cujo corte (botão de radio selecionado) é exibido na paleta no momento atual, nós vamos escrever três métodos separados: CColorPicker::SetHSL(), CColorPicker::SetRGB() e CColorPicker::SetLab(). Já que estes métodos têm um conteúdo muito semelhante, apenas um código será fornecido aqui - CColorPicker::setRGB(). No início deste método nós obtemos os valores das caixas de edição do modelo RGB nos campos da classe. Os valores obtidos são convertidos para o formato HSL e Lab. No final nós chamamos o método CColorPicker::SetControls() no modo de definição dos valores para todos os modelos de cores do controle (false). 

class CColorPicker : public CElement
  {
private:
   //--- Definição dos parâmetros dos modelos de cores em relação ao (1) HSL, (2) RGB, (3) Lab
   void              SetHSL(void);
   void              SetRGB(void);
   void              SetLab(void);
  };
//+------------------------------------------------------------------+
//| Definição dos parâmetros dos modelos de cores em relação ao RGB  |
//+------------------------------------------------------------------+
void CColorPicker::SetRGB(void)
  {
//--- Obtém os valores atuais dos componentes RGB
   m_rgb_r=m_rgb_r_edit.GetValue();
   m_rgb_g=m_rgb_g_edit.GetValue();
   m_rgb_b=m_rgb_b_edit.GetValue();
//--- Conversão do componente RGB para os componentes HSL
   m_clr.RGBtoHSL(m_rgb_r,m_rgb_g,m_rgb_b,m_hsl_h,m_hsl_s,m_hsl_l);
//--- Correção dos componentes HSL
   AdjustmentComponentHSL();
//--- Conversão do componente RGB para o componente Lab
   m_clr.RGBtoXYZ(m_rgb_r,m_rgb_g,m_rgb_b,m_xyz_x,m_xyz_y,m_xyz_z);
   m_clr.XYZtoCIELab(m_xyz_x,m_xyz_y,m_xyz_z,m_lab_l,m_lab_a,m_lab_b);
//--- Definindo os parâmetros atuais nas caixas de edição
   SetControls(0,false);
  }

E, finalmente, o principal método é exigido quando todos os métodos mencionados acima para os cálculos, desenho e definição dos valores dos componentes são chamados na caixa de edição do controle. Aqui, ele é o método CColorPicker::SetComponents(). Ela também opera em dois modos. No caso do argumento fix_selected ser igual a true, então, os componentes serão calculados em relação à cor selecionada e a configuração dos valores na caixa de edição serão em relação ao botão de radio selecionado do componente. Se o argumento fix_selected ser igual a false, então o cálculo é feito em relação ao modelo da cor indicada. A paleta de cores é redesenhada após todos os cálculos. 

class CColorPicker : public CElement
  {
private:
   //--- Cálculo e definição dos componentes da cor
   void              SetComponents(const int index,const bool fix_selected);
  };
//+------------------------------------------------------------------+
//| Cálculo e definição dos componentes da cor                       |
//+------------------------------------------------------------------+
void CColorPicker::SetComponents(const int index=0,const bool fix_selected=true)
  {
//--- Se for necessário corrigir as cores em relação ao botão de radio selecionado do componente
   if(fix_selected)
     {
      //--- Decomposição da cor selecionada para os componentes em RGB
      m_rgb_r=m_clr.GetR(m_picked_color);
      m_rgb_g=m_clr.GetG(m_picked_color);
      m_rgb_b=m_clr.GetB(m_picked_color);
      //--- Converte os componentes em RGB para os componentes em HSL
      m_clr.RGBtoHSL(m_rgb_r,m_rgb_g,m_rgb_b,m_hsl_h,m_hsl_s,m_hsl_l);
      //--- Correção dos componentes HSL
      AdjustmentComponentHSL();
      //--- Converte os componentes em RGB para os componentes em LAB
      m_clr.RGBtoXYZ(m_rgb_r,m_rgb_g,m_rgb_b,m_xyz_x,m_xyz_y,m_xyz_z);
      m_clr.XYZtoCIELab(m_xyz_x,m_xyz_y,m_xyz_z,m_lab_l,m_lab_a,m_lab_b);
      //--- Define as cores nas caixas de edição
      SetControls(m_radio_buttons.SelectedButtonIndex(),true);
      return;
     }
//--- Definição dos parâmetros dos modelos de cores
   switch(index)
     {
      case 0 : case 1 : case 2 :
         SetHSL();
         break;
      case 3 : case 4 : case 5 :
         SetRGB();
         break;
      case 6 : case 7 : case 8 :
         SetLab();
         break;
     }
//--- Desenha a paleta em relação ao botão de radio selecionado
   DrawPalette(m_radio_buttons.SelectedButtonIndex());
  }

Para definir a cor atual da paleta que será atribuída a todos os objetos de marcador, nós escrevemos o método CColorPicker::CurrentColor(). O artigo revela ainda onde ele irá ser utilizado. 

class CColorPicker : public CElement
  {
public:
   //--- Definindo a cor selecionada pelo usuário a partir da paleta
   void              CurrentColor(const color clr);
  };
//+------------------------------------------------------------------+
//| Definindo a cor atual                                            |
//+------------------------------------------------------------------+
void CColorPicker::CurrentColor(const color clr)
  {
   m_hover_color=clr;
   m_hover.Color(clr);
   m_hover.BackColor(clr);
   m_hover.Tooltip(::ColorToString(clr));
//---
   m_picked_color=clr;
   m_picked.Color(clr);
   m_picked.BackColor(clr);
   m_picked.Tooltip(::ColorToString(clr));
//---
   m_current_color=clr;
   m_current.BackColor(clr);
   m_current.Tooltip(::ColorToString(clr));
  }

Todos os métodos de cálculos estão prontos. Procede com os métodos de manipulação de eventos do controle.

 

Métodos para a manipulação de eventos do controle

Serão necessários os seguintes métodos para a manipulação de eventos e gerenciamento das paletas de cores:

  • O método CColorPicker::OnHoverColor() — obtém a cor (sobre a paleta) do cursor do mouse. O programa sai do método se o cursor do mouse estiver além da área da paleta. Se o cursor estiver em sua área, então, nós vamos definir suas coordenadas sobre ele e obter a cor do cursor do mouse. Imediatamente após isto, uma nova cor é definida para o marcador correspondente, e através do método ColorToString(), é estabelecido a dica de ferramentas nos objetos gráficos do marcador e da paleta de cores - string colorida no formato RGB
//+------------------------------------------------------------------+
//| Obtém a cor do cursor do mouse                                   |
//+------------------------------------------------------------------+
bool CColorPicker::OnHoverColor(const int x,const int y)
  {
//--- Sai se o foco não está na paleta
   if(!m_canvas.MouseFocus())
      return(false);
//--- Define a cor na paleta do cursor do mouse
   int lx =x-m_canvas.X();
   int ly =y-m_canvas.Y();
   m_hover_color=(color)::ColorToARGB(m_canvas.PixelGet(lx,ly),0);
//--- Define a cor e a dica da ferramenta na amostra relevante (marcador)
   m_hover.Color(m_hover_color);
   m_hover.BackColor(m_hover_color);
   m_hover.Tooltip(::ColorToString(m_hover_color));
//--- Define a dica da ferramenta para a paleta
   m_canvas.Tooltip(::ColorToString(m_hover_color));
   return(true);
  }

  • O método CColorPicker::OnClickPalette() — lida com o clique na paleta de cores. No início do método o nome do objeto é verificado. Se o clique ocorre na paleta, então a cor do cursor do mouse e a dica para o marcador relevante são salvos e definido. Bem no final, o método CColorPicker::SetComponents() é chamado para calcular e configurar os componentes dos modelos de cores em relação ao botão de radio selecionado do componente.
//+------------------------------------------------------------------+
//| Manipula o clique na paleta de cores                             |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickPalette(const string clicked_object)
  {
//--- Sai se o nome do objeto não corresponder
   if(clicked_object!=m_canvas.Name())
      return(false);
//--- Define a cor e a dica da ferramenta na amostra relevante (marcador)
   m_picked_color=m_hover_color;
   m_picked.Color(m_picked_color);
   m_picked.BackColor(m_picked_color);
   m_picked.Tooltip(::ColorToString(m_picked_color));
//--- Calcula e define os componentes da cor em relação ao botão de radio selecionado
   SetComponents();
   return(true);
  }

  • O método CColorPicker::OnClickRadioButton() — lida com o clique no botão de radio. Primeiramente, duas verificações devem ser realizadas: (1) pelo identificador do elemento e (2) pelo texto exibido do botão de radio. Se as verificações são passados, então, a paleta de cor é redesenhada em relação ao componente selecionado do modelo de cor na qual ele pertence.
//+------------------------------------------------------------------+
//| Manipula o clique no botão de radio                              |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickRadioButton(const long id,const int button_index,const string button_text)
  {
//--- Sai se os identificadores não correspondem
   if(id!=CElement::Id())
      return(false);
//--- Sai se o texto do botão de radio não corresponde
   if(button_text!=m_radio_buttons.SelectedButtonText())
      return(false);
//--- Atualiza a paleta levando em consideração das últimas alterações
   DrawPalette(button_index);
   return(true);
  }

  • O método CColorPicker::OnEndEdit() — lida com a entrada de um novo valor na caixa de edição. É suficiente ter uma única verificação pelo elemento do identificador, e após sua conclusão, os componentes de todos os modelos de cor são calculados em relação àquele que tem um componente do botão de radio selecionado. 
//+------------------------------------------------------------------+
//| Lida com a entrada de um novo valor na caixa de edição           |
//+------------------------------------------------------------------+
bool CColorPicker::OnEndEdit(const long id,const int button_index)
  {
//--- Sai se os identificadores não correspondem
   if(id!=CElement::Id())
      return(false);
//--- Calcula e define os componentes de cor para todos os modelos de cores 
   SetComponents(button_index,false);
   return(true);
  }

  • O método CColorPicker::OnClickButtonOK() — lida com o clique no botão 'OK'. Esta não é uma versão final do método, e ele ainda será alterado no artigo. A única coisa que nós precisamos saber no momento, é que ao clicar no botão, a cor selecionada é salva como a atual.  
//+------------------------------------------------------------------+
//| Manipula o clique no botão "OK"                                  |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickButtonOK(const string clicked_object)
  {
//--- Sai se o nome do objeto não corresponder
   if(clicked_object!=m_button_ok.Text())
      return(false);
//--- Salva a cor selecionada
   m_current_color=m_picked_color;
   m_current.BackColor(m_current_color);
   m_current.Tooltip(::ColorToString(m_current_color));
   return(true);
  }

  • O método CColorPicker::OnClickButtonCancel() — lida com o clique no botão "Cancel". Há uma única verificação do nome do objeto neste método. Então, se a formulário que o controle é ligado possui um tipo de janela de diálogo, então ela é fechada
//+------------------------------------------------------------------+
//| Manipula o clique no botão "Cancel"                              |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickButtonCancel(const string clicked_object)
  {
//--- Sai se o nome do objeto não corresponder
   if(clicked_object!=m_button_cancel.Text())
      return(false);
//--- Fecha a janela se é uma janela de diálogo
   if(m_wnd.WindowType()==W_DIALOG)
      m_wnd.CloseDialogBox();
//---
   return(true);
  }

Há um total de seis blocos no manipulador de eventos da paleta de cores CColorPicker::OnEvent(). Cada método da lista acima será chamado até a chegada do identificador de evento ser destinado a ele. Todo o código do manipulador de eventos estará disponível no código a seguir:

//+------------------------------------------------------------------+
//| Manipulador de evento do gráfico                                 |
//+------------------------------------------------------------------+
void CColorPicker::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Manipula o evento de mover o mouse
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      //--- Sai se o controle está oculto
      if(!CElement::IsVisible())
         return;
      //--- Coordenadas e o estado do botão esquerdo do mouse
      int x=(int)lparam;
      int y=(int)dparam;
      m_mouse_state=(bool)int(sparam);
      CElement::MouseFocus(x>X() && x<X2() && y>Y() && y<Y2());
      m_canvas.MouseFocus(x>m_canvas.X() && x<m_canvas.X2()-1 && y>m_canvas.Y() && y<m_canvas.Y2()-1);
      //--- Obtém a cor do cursor do mouse
      if(OnHoverColor(x,y))
         return;
      //---
      return;
     }
//--- Manipula o evento de clicar no botão esquerdo do mouse sobre o objeto
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Se a paleta foi clicada
      if(OnClickPalette(sparam))
         return;
      //---
      return;
     }
//--- Manipula a entrada de valores na caixa de edição
   if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
     {
      //--- Verifica a entrada do novo valor
      if(OnEndEdit(lparam,(int)dparam))
         return;
      //---
      return;
     }
//--- Manipula o clique do controle
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      //--- Se botão foi clicado
      if(OnClickRadioButton(lparam,(int)dparam,sparam))
         return;
      //---
      return;
     }
//--- Manipula o clique de alteração das caixas de edição
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_INC || id==CHARTEVENT_CUSTOM+ON_CLICK_DEC)
     {
      //--- Verifica a entrada do novo valor
      if(OnEndEdit(lparam,(int)dparam))
         return;
      //---
      return;
     }
//--- Manipula o clique do botão do controle
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
     {
      //--- Sai se os identificadores não correspondem
      if(lparam!=CElement::Id())
         return;
      //--- Se clicou no botão "OK"
      if(OnClickButtonOK(sparam))
         return;
      //--- Se clicou no botão "Cancel"
      if(OnClickButtonCancel(sparam))
         return;
      //---
      return;
     }
  }

Muitos controles de biblioteca que foram desenvolvidos possuem o método FastSwitching(). Ele é normalmente utilizado para a troca rápida dos valores nas caixas de edição, barras de rolagem das listas ou tabelas. No entanto, aqui ele é necessário para redesenhar a paleta de cores quando a alteração rápida do contador do componente caixa de edição foi ativada. O código do método CColorPicker::FastSwitching() está disponível a partir dos arquivos ligados ao artigo.

 

 

Botão do seletor de cores

A classe para a criação da paleta de cores está pronto, mas ainda está faltando um elemento para a sua utilização plena. Nós precisamos de um botão que irá ser usado para chamar a janela com a paleta de cores. O botão deve ter uma opção para ver a cor definida no momento atual. Nós vamos escrever a classe para a criação de tal botão. A lista abaixo mostra as suas partes compostas.

  1. Área do controle
  2. Rótulo de texto com a descrição
  3. Indicador de cor selecionado
  4. Área do botão
  5. Descrição da cor selecionada no formato RGB


Fig. 3. Partes integrantes do botão para chamar uma paleta de cores.


Nos artigos anteriores nós já consideramos os controles semelhantes, por isso nós não iremos fornecer aqui uma descrição desta classe de código. Em vez disso, nós vamos avançar para a parte de interação entre o botão e a paleta de cores. Por favor, encontre o arquivo ColorButton.mqh com a classe CColorButton no arquivo anexado ao artigo para saber mais. 

Nós precisamos conectar a paleta de cores com o botão para chamá-lo. Nós vamos fazer isso através do ponteiro do botão que irá ser armazenado na classe CColorPicker. Para este propósito nós conectamos o arquivo ColorButton.mqh para o arquivo ColorPicker.mqh e declaramos a instância da classe CColorButton onde o ponteiro para o botão para chamar a paleta de cores é armazenado.

//+------------------------------------------------------------------+
//|                                                  ColorPicker.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
#include "Window.mqh"
#include "SpinEdit.mqh"
#include "SimpleButton.mqh"
#include "RadioButtons.mqh"
#include "ColorButton.mqh"
//+------------------------------------------------------------------+
//| Classe para a criação do seletor de cores                        |
//+------------------------------------------------------------------+
class CColorPicker : public CElement
  {
private:
   //--- Ponteiro ao botão que chama o controle para a seleção da cor
   CColorButton     *m_color_button;
  };

Será necessário também de um método público para armazenar o ponteiro para o botão. A fim de simplificar a interação entre o botão de chamada e a paleta, todos os marcadores da paleta serão atribuídos a uma cor atual do botão no envio do objeto do botão para armazenar seu ponteiro. Uma janela que tem uma paleta de cores conectada será aberta, então (veja o código abaixo).  

class CColorPicker : public CElement
  {
public:
   //--- Armazena o ponteiro para o botão que chama a paleta de cores
   void              ColorButtonPointer(CColorButton &object);
  };
//+------------------------------------------------------------------+
//| Armazena o ponteiro para o botão que chama a paleta de cores e    |
//| a janela aberta que a paleta está ligada                         |
//+------------------------------------------------------------------+
void CColorPicker::ColorButtonPointer(CColorButton &object)
  {
//--- Armazena o ponteiro para o botão
   m_color_button=::GetPointer(object);
//--- Define a cor do botão enviada a todos os marcadores da paleta
   CurrentColor(object.CurrentColor());
//--- Abre a janela que a paleta está ligada
   m_wnd.Show();
  }

Além disso, nós iremos exigir os métodos para definir e obter a cor do botão. A cor definida aparecerá no marcador (indicador) do botão, e para obter informações adicionais no texto do botão, é exibido uma apresentação da string colorida no formato RGB.

class CColorButton : public CElement
  {
public:
   //--- Retorna/define a cor atual do parâmetro
   color             CurrentColor(void)                 const { return(m_current_color);       }
   void              CurrentColor(const color clr);
  };
//+------------------------------------------------------------------+
//| Altera a cor atual do parâmetro                                  |
//+------------------------------------------------------------------+
void CColorButton::CurrentColor(const color clr)
  {
   m_current_color=clr;
   m_button_icon.BackColor(clr);
   m_button_label.Description(::ColorToString(clr));
  }

E uma pequena adição do método CColorPicker::OnClickButtonOK(). Se um ponteiro para o botão é definido em seguida:

  • uma cor selecionada na paleta é definida para o botão;
  • a janela que a paleta de cores está ligada pode ser fechada;
  • a mensagem de que uma nova cor, selecionada na paleta, foi gerada. Um novo identificador do evento ON_CHANGE_COLOR contido no arquivo Defines.mqh é necessário aqui. Esta mensagem também irá conter (1) o Identificador do controle, (2) o índice do elemento e (3) o texto do botão que chamou paleta de cores. Dessa forma, você será capaz de entender qual botão esta mensagem refere-se no manipulador de eventos, e irá nos ajudar a lidar com o evento corretamente;
  • o ponteiro para o botão é zerado. 

Se não houver um ponteiro para o botão, então, haverá uma mensagem com uma dica de ferramenta exibida pelo desenvolvedor do aplicativo em MQL no log do terminal.  

//+------------------------------------------------------------------+
//| Manipula o clique no botão "OK"                                  |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickButtonOK(const string clicked_object)
  {
//--- Sai se o nome do objeto não corresponder
   if(clicked_object!=m_button_ok.Text())
      return(false);
//--- Salva a cor selecionada
   m_current_color=m_picked_color;
   m_current.BackColor(m_current_color);
   m_current.Tooltip(::ColorToString(m_current_color));
//--- Se existe um ponteiro para o botão de chamada da janela para a seleção das cores
   if(::CheckPointer(m_color_button)!=POINTER_INVALID)
     {
      //--- Define uma cor selecionada para o botão
      m_color_button.CurrentColor(m_current_color);
      //--- Fecha a janela
      m_wnd.CloseDialogBox();
      //--- Envia uma mensagem sobre ele
      ::EventChartCustom(m_chart_id,ON_CHANGE_COLOR,CElement::Id(),CElement::Index(),m_color_button.LabelText());
      //--- Reseta o ponteiro
      m_color_button=NULL;
     }
   else
     {
      //--- Se não há nenhum ponteiro e é uma janela de diálogo,
      // exibe uma mensagem que não há nenhum ponteiro para o botão chamar o controle
      if(m_wnd.WindowType()==W_DIALOG)
         ::Print(__FUNCTION__," > Ponteiro inválido para a chamada do controle(CColorButton).");
     }
//---
   return(true);
  }

Agora está tudo em ordem para prosseguirmos com o teste da paleta de cores. 

 

Teste dos controles

Qualquer Expert Advisor do artigo anterior pode ser usado para o teste. Vamos fazer uma cópia e manter lá somente o menu principal e uma string de estado. Na janela principal (W_MAIN) da interface gráfica, nós criamos cinco botões para chamar a janela de diálogo (W_DIALOG) com a paleta de cores. Em outras palavras, é suficiente criar uma paleta de cores para toda a aplicação MQL. Toda vez que ao clicar no botão para chamar a janela de diálogo com uma paleta de cores, a mesma janela será chamada. Mas o ponteiro do botão no ponto da chamada deve ser enviada para a classe CColorPicker de forma independente. Será ainda mostrado como este deve ser implementado na classe na aplicação personalizada.

Na classe personalizada chamada CProgram, nós precisamos declarar as instâncias de classes para a criação de uma janela adicional (CWindow), cinco botões para chamar as paletas de cores CColorButton e CColorPicker, e também os métodos para a sua criação com os deslocamentos do ponto extremo do formulário.

class CProgram : public CWndEvents
  {
private:
   //--- Formulário 2 - janela com a paleta de cores para seleção da cor
   CWindow           m_window2;
   //--- Botões para chamar a janela com a paleta de cores
   CColorButton      m_color_button1;
   CColorButton      m_color_button2;
   CColorButton      m_color_button3;
   CColorButton      m_color_button4;
   CColorButton      m_color_button5;
   //--- Paleta de cores
   CColorPicker      m_color_picker;
   //---
private:
   //--- Formulário 2
   bool              CreateWindow2(const string text);
   //--- Botões para chamar a paleta de cores
#define COLORBUTTON1_GAP_X    (7)
#define COLORBUTTON1_GAP_Y    (50)
   bool              CreateColorButton1(const string text);
#define COLORBUTTON2_GAP_X    (7)
#define COLORBUTTON2_GAP_Y    (75)
   bool              CreateColorButton2(const string text);
#define COLORBUTTON3_GAP_X    (7)
#define COLORBUTTON3_GAP_Y    (100)
   bool              CreateColorButton3(const string text);
#define COLORBUTTON4_GAP_X    (7)
#define COLORBUTTON4_GAP_Y    (125)
   bool              CreateColorButton4(const string text);
#define COLORBUTTON5_GAP_X    (7)
#define COLORBUTTON5_GAP_Y    (150)
   bool              CreateColorButton5(const string text);
   //--- Paleta de cores
#define COLORPICKER_GAP_X     (1)
#define COLORPICKER_GAP_Y     (20)
   bool              CreateColorPicker(void);
  };

Os códigos do métodos de criação dos botões para chamar a paleta de cores são praticamente idênticos, portanto, nós iremos fornecer aqui somente um exemplo. A diferença pode ser apenas na definição da cor inicial que será exibida no indicador do botão após a definição, e também o texto na descrição

//+------------------------------------------------------------------+
//| Cria o botão para chamar a paleta de cores 1                     |
//+------------------------------------------------------------------+
bool CProgram::CreateColorButton1(const string text)
  {
//--- Armazena o ponteiro para a janela
   m_color_button1.WindowPointer(m_window1);
//--- Coordenadas
   int x=m_window1.X()+COLORBUTTON1_GAP_X;
   int y=m_window1.Y()+COLORBUTTON1_GAP_Y;
//--- Define as propriedades antes da criação
   m_color_button1.XSize(195);
   m_color_button1.YSize(18);
   m_color_button1.ButtonXSize(100);
   m_color_button1.ButtonYSize(18);
   m_color_button1.AreaColor(clrWhiteSmoke);
   m_color_button1.LabelColor(clrBlack);
   m_color_button1.BackColor(C'220,220,220');
   m_color_button1.BorderColor(clrSilver);
   m_color_button1.CurrentColor(clrRed);
//--- Cria o elemento
   if(!m_color_button1.CreateColorButton(m_chart_id,m_subwin,text,x,y))
      return(false);
//--- Adiciona o ponteiro para controlar na base
   CWndContainer::AddToElementsArray(0,m_color_button1);
   return(true);
  }

O código do método usado para criar a formulário da janela de diálogo para uma paleta de cores difere da janela principal apenas por ter o tipo da janela (W_DIALOG) indicada. Em adição a isto, nós vamos definir uma imagem única para esta janela que indica o seu propósito. Todas as imagens são anexadas no arquivo no final do artigo. 

//+------------------------------------------------------------------+
//| Cria o formulário 2 para a paleta de cores                       |
//+------------------------------------------------------------------+
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp16\\color_picker.bmp"
//---
bool CProgram::CreateWindow2(const string caption_text)
  {
//--- Armazena o ponteiro para a janela
   CWndContainer::AddWindow(m_window2);
//--- Coordenadas
   int x=(m_window2.X()>0) ? m_window2.X() : 30;
   int y=(m_window2.Y()>0) ? m_window2.Y() : 30;
//--- Propriedades
   m_window2.Movable(true);
   m_window2.XSize(350);
   m_window2.YSize(286);
   m_window2.WindowType(W_DIALOG);
   m_window2.WindowBgColor(clrWhiteSmoke);
   m_window2.WindowBorderColor(clrLightSteelBlue);
   m_window2.CaptionBgColor(clrLightSteelBlue);
   m_window2.CaptionBgColorHover(clrLightSteelBlue);
   m_window2.IconFile("Images\\EasyAndFastGUI\\Icons\\bmp16\\color_picker.bmp");
//--- Criação de um formulário
   if(!m_window2.CreateWindow(m_chart_id,m_subwin,caption_text,x,y))
      return(false);
//---
   return(true);
  }

A lista abaixo tem o código do método CProgram::CreateColorPicker() para a criação de uma paleta de cores. É importante guardar um ponteiro para a janela de diálogo que um controlo será ligado. Ao adicionar um ponteiro do controle na base de controles, Índice da janela que o elemento está ligado precisa ser enviada. Neste caso, é um índice de janela de diálogo [1].

//+------------------------------------------------------------------+
//| Cri a paleta de cores para a seleção de cor                      |
//+------------------------------------------------------------------+
bool CProgram::CreateColorPicker(void)
  {
//--- Armazena o ponteiro para a janela
   m_color_picker.WindowPointer(m_window2);
//--- Coordenadas
   int x=m_window2.X()+COLORPICKER_GAP_X;
   int y=m_window2.Y()+COLORPICKER_GAP_Y;
//--- Cria o controle
   if(!m_color_picker.CreateColorPicker(m_chart_id,m_subwin,x,y))
      return(false);
//--- Adiciona o ponteiro para controlar na base
   CWndContainer::AddToElementsArray(1,m_color_picker);
   return(true);
  }

Nós precisamos garantir que, ao clicar no botão, o ponteiro é enviado para a paleta de cores. Pode ser feito no processador de eventos da classe personalizada CProgram::OnEvent(). Ao clicar no botão, uma mensagem com o identificador ON_CLICK_BUTTON é gerado. A mensagem também contém o texto da descrição do botão usado para definir qual objeto do tipo CColorButton necessita ser enviado para a paleta de cores. Logo após o envio do objeto do botão, uma janela com a paleta de cores será aberta, e a cor do botão cujo objeto foi enviado será exibido em todos os seus marcadores. Isto é demonstrado no código a seguir:

//+------------------------------------------------------------------+
//| Manipulador de eventos                                           |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Evento clique do botão
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
     {
      //--- Se o botão 1 foi clicado
      if(sparam==m_color_button1.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button1);
         return;
        }
      //--- Se o botão 2 foi clicado
      if(sparam==m_color_button2.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button2);
         return;
        }
      //--- Se o botão 3 foi clicado
      if(sparam==m_color_button3.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button3);
         return;
        }
      //--- Se o botão 4 foi clicado
      if(sparam==m_color_button4.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button4);
         return;
        }
      //--- Se o botão 5 foi clicado
      if(sparam==m_color_button5.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button5);
         return;
        }
     }
  }

Após a seleção das cores serem confirmadas clicando no botão "ОК" na paleta de cores, uma mensagem com o identificador ON_CHANGE_COLOR será tratada como é exibido na listagem do código.

void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Evento para mudar a cor usando a paleta de cores
   if(id==CHARTEVENT_CUSTOM+ON_CHANGE_COLOR)
     {
      //--- Se os identificadores de controles corresponder
      if(lparam==m_color_picker.Id())
        {
         //--- Se a resposta é a partir do botão 1
         if(sparam==m_color_button1.LabelText())
           {
            //--- Altera a cor do objeto que se refere ao botão 1...
            return;
           }
         //--- Se a resposta é do botão 2
         if(sparam==m_color_button2.LabelText())
           {
            //--- Altera a cor do objeto que se refere ao botão 2...
            return;
           }
         //--- Se a resposta é do botão 3
         if(sparam==m_color_button3.LabelText())
           {
            //--- Altera a cor do objeto que se refere a tecla 3 ...
            return;
           }
         //--- Se a resposta é do botão 4
         if(sparam==m_color_button4.LabelText())
           {
            //--- Mude a cor do objeto que se refere a tecla 4...
            return;
           }
         / --- Se a resposta é do botão 5 
         if(sparam==m_color_button5.LabelText())
           {
            //--- Altera a cor do objeto que se refere a tecla 5...
            return;
           }
        }
      return;
     }
  }

Compile o programa e carregue-o na parada do terminal. O resultado aparece na imagem abaixo:

 Fig. 4. Teste dos botões para chamar uma paleta de cores.

Fig. 4. Teste dos botões para chamar uma paleta de cores.

Ao clicar no botão para chamar uma paleta de cores a partir dos cinco botões coloridos na apresentados na janela principal, a janela do seletor de cores será aberta como é mostrado na imagem a seguir:

 Fig. 5. Teste do elemento de cor selecionado.

Fig. 5. Teste do elemento de cor selecionado.

Agora tudo funciona como era de se esperar. 

 


Conclusão

Foi apresentado um controle composto e complexo da interface chamada seletor de cor foi apresentado neste artigo (primeiro capítulo da parte 9 da série de artigos). Um botão especial para chamar a paleta de cores foi criado como um controle adicional. Agora, os usuários da biblioteca desenvolvida possuem a oportunidade de gerenciar as cores de objetos usando uma interface gráfica de sua aplicação MQL.

O seguinte artigo irá conter uma descrição das classes de códigos dos controles, como a barra de progresso e o gráfico de linhas.

A seguir estão os materiais da parte nove da série de artigos que você pode baixar no seu PC, a fim de testar como tudo funciona. Para qualquer dúvida relacionadas com a utilização do material fornecido nestes arquivos, você pode referir-se a descrição detalhada do processo de desenvolvimento da biblioteca em um dos artigos da lista abaixo ou fazer perguntas nos comentários do artigo.

Lista de artigos (capítulos) da parte nove:


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

Arquivos anexados |
Distribuição Estatística no MQL5 - tirando o melhor de R e o fazendo mais rápido Distribuição Estatística no MQL5 - tirando o melhor de R e o fazendo mais rápido
As funções para trabalhar com as distribuições estatísticas básicas implementadas na linguagem R são consideradas. as distribuições de Cauchy, Weibull, normal, log-normal, logistic, exponential, uniform, gamma, beta central e não-central, qui-quadrado, F de Fisher-Snedecor, t de Student, assim como as distribuições binomiais discretas e binomiais negativas, distribuições geométricas, hipergeométricas e de Poisson. Existem funções para o cálculo de momentos teóricos de distribuições, que permitem avaliar o grau de conformidade da distribuição real com o modelado.
Interfaces Gráficas VIII: O Controle Navegador de Arquivos (Capítulo 3) Interfaces Gráficas VIII: O Controle Navegador de Arquivos (Capítulo 3)
Nos capítulos anteriores da oitava parte da série, nossa biblioteca foi reforçada por várias classes para o desenvolvimento de ponteiros para o cursor do mouse, calendários e as listas hierárquicas. O presente artigo lida com o controle navegador de arquivos que também pode ser utilizado como parte de uma interface gráfica na aplicação MQL.
Sistema de negociação 'Turtle Soup' e sua modificação 'Turtle Soup Plus One' Sistema de negociação 'Turtle Soup' e sua modificação 'Turtle Soup Plus One'
No artigo regras de estratégias de negociação formalizadas e programadas Turtle Soup e Turtle Soup Plus One a partir do livro de Linda Raschke e Laurence Connors Street Smarts: High Probability Short-Term Trading Strategies. As estratégias descritas no livro receberam uma ampla acolhida, no entanto é importante entender que os autores conceberam suas ideias com base no comportamento do mercado de há 15-20 anos.
Sistema de negociação '80-20' Sistema de negociação '80-20'
Este artigo trata de como criar instrumentos (indicador e Expert Advisor) para estudo sobre a Estratégia de Negociação '80-20' descrita no livro "Street Smarts: High Probability Short-Term Trading Strategies" de Linda Raschke e Laurence Connors. Na linguagem MQL5, estão estabelecidas as regras desta estratégia, e seu principal indicador e Expert Advisor estão testados com base no histórico atual de mercado.