English Русский 中文 Deutsch 日本語 Português
Interfaces gráficas IX: Control "Paleta para seleccionar el color" (Capítulo 1)

Interfaces gráficas IX: Control "Paleta para seleccionar el color" (Capítulo 1)

MetaTrader 5Ejemplos | 19 agosto 2016, 10:36
1 395 0
Anatoli Kazharski
Anatoli Kazharski

Índice

 

 

Introducción

El primer artículo de la serie nos cuenta con más detalles para qué sirve esta librería: Interfaces gráficas I: Preparación de la estructura de la librería (Capítulo 1). Al final de los artículos de cada parte se puede encontrar la lista de los capítulos con los enlaces, así como descargar la versión completa de la librería en la fase actual del desarrollo del proyecto. Es necesario colocar los ficheros en los mismos directorios, tal como están ubicados en el archivo.

En la novena parte hablaremos de los siguientes controles y elementos de la interfaz:

1. Primer capítulo:

  • Control «Paleta para seleccionar el color» (clase CColorPicker).
  • Control «Botón para abrir la paleta de colores» (clase CColorButton).

2. Segundo capítulo:

  • Elemento «Indicador de progreso» (clase CProgressBar).
  • Elemento «Gráfico lineal» (clase CLineGraph).

Para cada uno de estos elementos vamos a mostrar detallados ejemplos de cómo puede usarlos en sus aplicaciones.

 

Control «Paleta para seleccionar el color»

La paleta de colores está presente en una gran variedad de aplicaciones que ofrecen la posibilidad de especificar el color para algún objeto. Usted puede necesitar la paleta de colores en los terminales MetaTrader para cambiar rápidamente el color de los elementos en su aplicación MQL. Supongamos que al diseñar el estudio visual para la creación de las interfaces gráficas, cuando es necesario configurar la solución de colores para cada elemento, sería muy inconveniente hacerlo sin la paleta de colores.

La paleta de colores es un complejo control compuesto que aparte de la misma paleta que muestra el modelo de colores seleccionado, contiene otros objetos y grupos de controles. Vamos a nombrar todas las partes integrantes de este control.

  1. Fondo
  2. Paleta de colores que muestra el modelo de colores especificado.
  3. Marcador del color establecido
  4. Marcador del color seleccionado
  5. Marcador del color al situar el cursor encima
  6. Grupo de botones de opción (radio buttons) con los campos de edición para el ajuste manual de los componentes del modelo de colores
  7. Botón para cancelar el color seleccionado
  8. Botón para establecer (fijar) el color especificado en el segundo marcador

 

Fig. 1. Partes integrantes del control «Paleta para seleccionar el color».

En la captura de pantalla de arriba se ve que el grupo de botones de opción (radio buttons) está dividido en tres subgrupos con tres botones en cada uno. Cada uno de estos subgrupos determina un modelo de colores, y cada botón de opción determina el componente de este modelo (coordenada del espacio de colores). La lista de abajo contiene el descifre de las abreviaturas de todos los modelos de colores que van a utilizarse durante la creación de la paleta de colores para nuestra librería.

1. Modelo de colores HSL:

  • H (Hue) – tono del color. El rango de valores es de 0 a 360
  • S (Saturation) – saturación. El rango de valores es de 0 a 100.
  • L (Lightness) – luminosidad. El rango de valores es de 0 a 100.

2. Modelo de colores RGB:

  • R (Red) – rojo. El rango de valores es de 0 a 255.
  • G (Green) – verde. El rango de valores es de 0 a 255.
  • B (Blue) – azul. El rango de valores es de 0 a 255.

3. Modelo de colores Lab:

  • L (Luminance) – luminancia. El rango de valores es de 0 a 100.
  • a – la primera coordenada cromática que define la matiz del color del verde al coccíneo. El rango de valores es de -128 a 127.
  • b – la segunda coordenada cromática que define la matiz del color del azul al amarillo. El rango de valores es de -128 a 127.

A continuación, vamos a ver cómo está organizada la clase de CColorPicker para la creación de l apaleta de colores.

 

Desarrollo de la clase CColorPicker

Creamos el archivo ColorPicker.mqh en el mismo directorio que ahora contiene los archivos de los demás controles (<carpeta de datos>\MQLX\Include\EasyAndFastGUI\Controls). En este archivo se debe crear la clase CColorPicker con los miembros estándar, tal como se muestra a continuación:

//+------------------------------------------------------------------+
//|                                                  ColorPicker.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
#include "Window.mqh"
//+------------------------------------------------------------------+
//| Clase para crear la paleta para seleccionar el color             |
//+------------------------------------------------------------------+
class CColorPicker : public CElement
  {
private:
   //--- Puntero al formulario al que está adjuntado el control
   CWindow          *m_wnd;
   //---
public:
                     CColorPicker(void);
                    ~CColorPicker(void);
   //---
public:
   //--- Guarda el puntero del formulario
   void              WindowPointer(CWindow &object)           { m_wnd=::GetPointer(object);            }
   //---
public:
   //--- Manejador de eventos del gráfico
   virtual void      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   //--- Temporizador
   virtual void      OnEventTimer(void);
   //--- Desplazamiento del control
   virtual void      Moving(const int x,const int y);
   //--- (1) Mostrar, (2) ocultar, (3) resetear, (4) eliminar
   virtual void      Show(void);
   virtual void      Hide(void);
   virtual void      Reset(void);
   virtual void      Delete(void);
   //--- (1) Establecer, (2) resetear las prioridades para el clic izquierdo del ratón
   virtual void      SetZorders(void);
   virtual void      ResetZorders(void);
   //--- Restablecer el color
   virtual void      ResetColors(void) {}
  };

Para la configuración de los objetos gráficos estarán disponibles las siguientes propiedades:

  • Color del fondo del control
  • Color del borde del fondo del control
  • Color del borde de la paleta y los marcadores del color

Usted puede cambiar las propiedades de los objetos gráficos de otros controles al obtener su puntero. 

class CColorPicker : public CElement
  {
private:
   //--- Color del (1) fondo y (2) borde del fondo
   color             m_area_color;
   color             m_area_border_color;
   //--- Color del borde de la paleta
   color             m_palette_border_color;
   //---
public:
   //--- Establecer el color del (1) fondo y (2) del borde del fondo, (3) borde de la paleta
   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;            }
  };

Puesto que vamos a utilizar otros controles como partes integrantes de la paleta de colores, hay que incluir los archivos con las clases de estos controles en el archivo ColorPicker.mqh. Para crear la paleta de colores, vamos a necesitar diecisiete métodos privados (private) y un método público (public).

//+------------------------------------------------------------------+
//|                                                  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"
//+------------------------------------------------------------------+
//| Clase para crear la paleta de colores            |
//+------------------------------------------------------------------+
class CColorPicker : public CElement
  {
private:
   //--- Objetos para crear el control
   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 crear el control
   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);
  };

Al conmutar el botón de opción, al lado de la paleta van a mostrarse los cortes bidimensionales de los espacios de colores de acuerdo con el valor especificado del componente seleccionado. En otras palabras, para el dibujo de cada corte, primero es necesario realizar el cálculo respecto al valor actual de su componente. Por eso para cada modelo de colores escribiremos tres métodos separados. Todos estos métodos van a recibir el índice del botón de opción (índice del componente seleccionado).

Para la conversión del color vamos a usar los métodos de la instancia de la clase CColors que está declarada en la clase base del control (CElement). Para la conversión desde el formato RGB al formato Lab, en la clase CColors no hay ningún método conveniente. Por eso cuando necesitamos la conversión RGB->Lab, va a aplicarse la conversión doble a través del modelo XYZ, es decir: RGB->XYZ->Lab. Para los cálculos y almacenamiento de los valores de los componentes de todos los modelos de colores, hay que declarar los campos correspondientes en la clase CColorPicker.

class CColorPicker : public CElement
  {
private:
   //--- Valores de los componentes en diferentes modelos de colores:
   //    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:
   //--- Dibuja la paleta según el modelo de colores HSL (0: H, 1: S, 2: L)
   void              DrawHSL(const int index);
   //--- Dibuja la paleta según el modelo de colores RGB (3: R, 4: G, 5: B)
   void              DrawRGB(const int index);
   //--- Dibuja la paleta según el modelo de colores LAB (6: L, 7: a, 8: b)
   void              DrawLab(const int index);
  };

Como ejemplo, vamos a mostrar aquí el código sólo de uno de estos métodos, CColorPicker::DrawHSL(). Porque la única diferencia que existe entre ellos es el cálculo previo de los valores de los componentes antes de la conversión. Puede estudiar el código de los demás métodos en los archivos adjuntos al artículo. 

El cálculo y el dibujo se realiza para cada píxel de la imagen. Preste atención en que los cálculos se realizan respecto a los tamaños de la paleta gráfica. Es decir, al usar este código, se puede crear un control semejante dentro del cual la paleta de colores va a tener otros tamaños, y no necesariamente tener la forma del cuadrado.

 Fig. 2. Ejemplo de la paleta de colores con el tamaño 500x255 píxeles.

Fig. 2. Ejemplo de la paleta de colores con el tamaño 500x255 píxeles. 


//+------------------------------------------------------------------+
//| Dibuja la paleta de colores HSL                                               |
//+------------------------------------------------------------------+
void CColorPicker::DrawHSL(const int index)
  {
   switch(index)
     {
      //--- Hue (H) - tono de colores en el rango de valores de 0 a 360
      case 0 :
        {
         //--- Calculamos el componente H
         m_hsl_h=m_hsl_h_edit.GetValue()/360.0;
         //---
         for(int ly=0; ly<m_canvas.YSize(); ly++)
           {
             //--- Calculamos el componente L
            m_hsl_l=ly/(double)m_canvas.YSize();
            //---
            for(int lx=0; lx<m_canvas.XSize(); lx++)
              {
               //--- Calculamos el componente S
               m_hsl_s=lx/(double)m_canvas.XSize();
               //--- Conversión de los componentes HSL en los componentes RGB
               m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
               //--- Unimos los canales
               uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
               m_canvas.PixelSet(lx,m_canvas.YSize()-ly,rgb_color);
              }
           }
         break;
        }
      //--- Saturation (S) - saturación en el rango de valores de 0 a 100
      case 1 :
        {
         //--- Calculamos el componente S
         m_hsl_s=m_hsl_s_edit.GetValue()/100.0;
         //---
         for(int ly=0; ly<m_canvas.YSize(); ly++)
           {
             //--- Calculamos el componente L
            m_hsl_l=ly/(double)m_canvas.YSize();
            //---
            for(int lx=0; lx<m_canvas.XSize(); lx++)
              {
                //--- Calculamos el componente H
               m_hsl_h=lx/(double)m_canvas.XSize();
               //--- Conversión de los componentes HSL en los componentes RGB
               m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
               //--- Unimos los canales
               uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
               m_canvas.PixelSet(lx,m_canvas.YSize()-ly,rgb_color);
              }
           }
         break;
        }
      //--- Lightness (L) - luminancia en el rango de valores de 0 a 100
      case 2 :
        {
         //--- Calculamos el componente L
         m_hsl_l=m_hsl_l_edit.GetValue()/100.0;
         //---
         for(int ly=0; ly<m_canvas.YSize(); ly++)
           {
             //--- Calculamos el componente S
            m_hsl_s=ly/(double)m_canvas.YSize();
            //---
            for(int lx=0; lx<m_canvas.XSize(); lx++)
              {
                //--- Calculamos el componente H
               m_hsl_h=lx/(double)m_canvas.XSize();
               //--- Conversión de los componentes HSL en los componentes RGB
               m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
               //--- Unimos los canales
               uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
               m_canvas.PixelSet(lx,m_canvas.YSize()-ly,rgb_color);
              }
           }
         break;
        }
     }
  }

Para dibujar el borde sobre el lienzo de la paleta de colores, escribiremos el método CColorPicker::DrawPaletteBorder(): 

class CColorPicker : public CElement
  {
private:
   //--- Dibuja borde de la paleta
   void              DrawPaletteBorder(void);
  };
//+------------------------------------------------------------------+
//| Dibuja el borde de la paleta                                             |
//+------------------------------------------------------------------+
void CColorPicker::DrawPaletteBorder(void)
  {
//--- Tamaño de la paleta
   int x_size=m_canvas.XSize()-1;
   int y_size=m_canvas.YSize()-1;
//--- Dibujar el borde
   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 los métodos de dibujo mencionados van a llamarse en el método para el dibujo de la paleta de colores CColorPicker::DrawPalette():

class CColorPicker : public CElement
  {
private:
   //--- Dibuja la paleta
   void              DrawPalette(const int index);
  };
//+------------------------------------------------------------------+
//| Dibuja la 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;
        }
     }
//--- Dibujamos el borde de la paleta
   DrawPaletteBorder();
 //--- Actualizamos la paleta
   m_canvas.Update();
  }

Cuando se selecciona un color en la paleta o durante la configuración de uno u otro componente de cualquier modelo de colores presente en el control, los valores en todos los campos de edición van a recalcularse automáticamente. Hacen falta los métodos mediante los cueles van a calcularse los componentes de todos los modelos de colores del control respecto al modelo cuyo corte (el botón de opción seleccionado) se muestre en la paleta en este momento. 

En primer lugar, vamos a necesitar los métodos de corrección de componentes de los modelos RGB y HSL, los que van a llamarse en muchos otros métodos de la clase:

class CColorPicker : public CElement
  {
private:
   //--- Corrección de los componentes RGB
   void              AdjustmentComponentRGB(void);
   //--- Corrección de los componentes HSL
   void              AdjustmentComponentHSL(void);
  };
//+------------------------------------------------------------------+
//| Corrección de los 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);
  }
//+------------------------------------------------------------------+
//| Corrección de los componentes HSL                                      |
//+------------------------------------------------------------------+
void CColorPicker::AdjustmentComponentHSL(void)
  {
   m_hsl_h*=360;
   m_hsl_s*=100;
   m_hsl_l*=100;
  }

Después de calcular todos los componentes, es necesario establecer nuevos valores en los campos de edición del control. En algunos casos habrá que (1) establecer los valores de todos los componentes, y a veces (2), para todos, a excepción del componente seleccionado en el momento actual. Para estas situaciones, escribiremos el método CColorPicker::SetControls(), que puede trabajar en dos modos.

class CColorPicker : public CElement
  {
private:
   //--- Establecer los parámetros actuales en los campos de edición
   void              SetControls(const int index,const bool fix_selected);
  };
//+------------------------------------------------------------------+
//| Establecer los parámetros actuales en los campos de edición                        |
//+------------------------------------------------------------------+
void CColorPicker::SetControls(const int index,const bool fix_selected)
  {
//--- Si es necesario fijar el valor en el campo de edición del botón de opción seleccionado
   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;
     }
//--- Si es necesario corregir los valores en los campos de edición de todos los modelos de colores
   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 los componentes de todos los modelos del control respecto al modelo cuyo corte (el botón de opción seleccionado) se muestre en la paleta en este momento, escribiremos tres métodos separados: CColorPicker::SetHSL(), CColorPicker::SetRGB() и CColorPicker::SetLab(). El contenido de estos métodos es muy parecido. Aquí mostraremos sólo uno de ellos: CColorPicker::SetRGB(). Al principio del método, obtenemos los valores de los campos de edición del modelo RGB en los campos de la clase. Convertimos loa valores obtenidos en el formato HSL y Lab. Luego, al final del todo, llamamos al método CColorPicker::SetControls() en el modo de establecimiento de valores para todos los modelos de colores del control (false). 

class CColorPicker : public CElement
  {
private:
   //--- Establecer los parámetros de los modelos de colores respecto a (1) HSL, (2) RGB, (3) Lab
   void              SetHSL(void);
   void              SetRGB(void);
   void              SetLab(void);
  };
//+------------------------------------------------------------------+
//| Establecer los parámetros de los modelos de colores respecto a RGB           |
//+------------------------------------------------------------------+
void CColorPicker::SetRGB(void)
  {
//--- Obtenemos el valor actual del componente 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();
//--- Conversión de los componentes RGB en los componentes HSL
   m_clr.RGBtoHSL(m_rgb_r,m_rgb_g,m_rgb_b,m_hsl_h,m_hsl_s,m_hsl_l);
//--- Corrección del componente HSL
   AdjustmentComponentHSL();
//--- Conversión de los componentes RGB en los componentes 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);
//--- Establecer los parámetros actuales en los campos de edición
   SetControls(0,false);
  }

Y por último, necesitamos el método principal en el que van a llamarse todos los métodos mencionado para los cálculos, el dibujo y establecimiento de los valores de los componentes en los campos de edición del control. Aquí este método es CColorPicker::SetComponents(). También trabaja en dos modos. Si el argumento fix_selected es true, los componentes van a calcularse respecto al color seleccionado, y el establecimiento de valores en los campos de edición será respecto al componente seleccionado con el botón de opción. Si el argumento fix_selected es false, el cálculo se realiza respecto al modelo de colores especificado. Una vez realizados todos los cálculos, la paleta de colores se redibuja

class CColorPicker : public CElement
  {
private:
   //--- Calcular y establecer los componentes del color
   void              SetComponents(const int index,const bool fix_selected);
  };
//+------------------------------------------------------------------+
//| Calcular y establecer los componentes del color                             |
//+------------------------------------------------------------------+
void CColorPicker::SetComponents(const int index=0,const bool fix_selected=true)
  {
//--- Si hace falta corregir los colores respecto al componente seleccionado con el botón de opción
   if(fix_selected)
     {
      //--- Descomponemos el color seleccionado en los componentes 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);
      //--- Convertimos los componentes RGB en los componentes HSL
      m_clr.RGBtoHSL(m_rgb_r,m_rgb_g,m_rgb_b,m_hsl_h,m_hsl_s,m_hsl_l);
      //--- Corrección del componente HSL
      AdjustmentComponentHSL();
      //--- Convertimos los componentes RGB en los componentes 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);
       //--- Establecemos los colores en los campos de edición
      SetControls(m_radio_buttons.SelectedButtonIndex(),true);
      return;
     }
//--- Establecer los parámetros de los modelos de colores
   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;
     }
//--- Dibujar la paleta del botón de opción seleccionado
   DrawPalette(m_radio_buttons.SelectedButtonIndex());
  }

Escribiremos el método CColorPicker::CurrentColor() para establecer el color actual de la paleta que va a asignarse a todos los objetos marcadores. Luego mostraremos dónde va a utilizarse.

class CColorPicker : public CElement
  {
public:
   //--- Establecer el color seleccionado por el usuario en la paleta
   void              CurrentColor(const color clr);
  };
//+------------------------------------------------------------------+
//| Establecer el color actual                                         |
//+------------------------------------------------------------------+
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));
  }

Tenemos preparados todos los métodos para los cálculos. Vamos a los métodos para procesar los eventos del control.

 

Métodos para procesar los eventos del control

Vamos a necesitar los siguientes métodos para procesar los eventos y controlar la paleta de colores:

  • El método CColorPicker::OnHoverColor() se utiliza para obtener el color (sobre la paleta) debajo del cursor del ratón. El programa sale del método si el cursor se encuentra fuera del área de la paleta de colores. Si el cursor se encuentra dentro de esta área, determinamos sus coordenadas sobre ella y obtenemos el color debajo del cursor. Inmediatamente después de eso, el nuevo color se establece para el marcador correspondiente, y a través del método ColorToString() se establece la descripción emergente en forma de la línea del color en el formato RGB para los objetos gráficos del marcador y la paleta de colores. 
//+------------------------------------------------------------------+
//| Obtener el color debajo del cursor del ratón                                |
//+------------------------------------------------------------------+
bool CColorPicker::OnHoverColor(const int x,const int y)
  {
//--- Salir si el foco no está sobre la paleta
   if(!m_canvas.MouseFocus())
      return(false);
//--- Determinamos el color sobre la paleta debajo del cursor
   int lx =x-m_canvas.X();
   int ly =y-m_canvas.Y();
   m_hover_color=(color)::ColorToARGB(m_canvas.PixelGet(lx,ly),0);
//--- Establecemos el color y la descripción emergente en el marcador correspondiente
   m_hover.Color(m_hover_color);
   m_hover.BackColor(m_hover_color);
   m_hover.Tooltip(::ColorToString(m_hover_color));
//--- Establecemos la descripción emergente para la paleta de colores
   m_canvas.Tooltip(::ColorToString(m_hover_color));
   return(true);
  }
  • El método CColorPicker::OnClickPalette() sirve para el procesamiento del clic en la paleta de colores. Al principio del método se comprueba el nombre del objeto. Si el clic ha sido hecho en la paleta, se guarda y se establece el color que encuentra debajo del cursor del ratón, así como la descripción emergente para el marcador correspondiente. Al final se invoca el método CColorPicker::SetComponents() para calcular y establecer los componentes del modelo de colores respecto al componente seleccionado con el botón de opción.
//+------------------------------------------------------------------+
//| Procesamiento del clic en la paleta de colores                            |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickPalette(const string clicked_object)
  {
//--- Salir si el nombre del objeto no coincide
   if(clicked_object!=m_canvas.Name())
      return(false);
//--- Establecemos el color y la descripción emergente en el marcador correspondiente
   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));
//--- Calculamos y establecemos los componentes del color respecto al botón de opción seleccionado
   SetComponents();
   return(true);
  }
  • El método CColorPicker::OnClickRadioButton() sirve para el procesamiento del clic en el botón de opción. Aquí primero hay que realizar dos pruebas: (1) del identificador del control y (2) del texto que muestra el botón de opción. Si las pruebas han sido superadas, la la paleta de colores se redibuja respecto al componente del modelo seleccionado al que pertenece.
//+------------------------------------------------------------------+
//| Procesamiento del clic en el botón de opción                                |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickRadioButton(const long id,const int button_index,const string button_text)
  {
//--- Salir si los identificadores no coinciden
   if(id!=CElement::Id())
      return(false);
//--- Salir si el texto del botón de opción no coincide
   if(button_text!=m_radio_buttons.SelectedButtonText())
      return(false);
//--- Actualizar la paleta de colores de acuerdo con últimos cambios
   DrawPalette(button_index);
   return(true);
  }
  • El método CColorPicker::OnEndEdit() sirve para procesar la introducción del valor nuevo en el campo de edición. Aquí bastará comprobar sólo el identificador del control. Después de superar la prueba, se realiza el cálculo de los componentes de todos los modelos de colores respecto al modelo cuyo botón de opción del componente está seleccionado en este momento. 
//+------------------------------------------------------------------+
//| Procesamiento de la introducción del valor nuevo en el campo de edición                    |
//+------------------------------------------------------------------+
bool CColorPicker::OnEndEdit(const long id,const int button_index)
  {
//--- Salir si los identificadores no coinciden
   if(id!=CElement::Id())
      return(false);
//--- Calculamos y establecemos los componentes del color para todos los modelos de colores
   SetComponents(button_index,false);
   return(true);
  }
  • El método CColorPicker::OnClickButtonOK() sirve para el procesamiento del clic en el botón OK. No es la versión definitiva del método. Luego en el artículo será completado un poco. Lo único que necesitamos saber ahora es que al hacer clic en este botón, el color seleccionado se guarda como el color actual. 
//+------------------------------------------------------------------+
//| Procesamiento del clic en el botón «OK»                                 |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickButtonOK(const string clicked_object)
  {
//--- Salir si el nombre del objeto no coincide
   if(clicked_object!=m_button_ok.Text())
      return(false);
//--- Guardar el color seleccionado
   m_current_color=m_picked_color;
   m_current.BackColor(m_current_color);
   m_current.Tooltip(::ColorToString(m_current_color));
   return(true);
  }
  • El método CColorPicker::OnClickButtonCancel() sirve para el procesamiento del clic en el botón «Cancel». En este método se comprueba sólo el nombre del objeto. Luego, si el formulario al que está adjuntado el control tiene el tipo «cuadro de diálogo», entonces se cierra
//+------------------------------------------------------------------+
//| Procesamiento del clic en el botón «Cancel»                             |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickButtonCancel(const string clicked_object)
  {
//--- Salir si el nombre del objeto no coincide
   if(clicked_object!=m_button_cancel.Text())
      return(false);
//--- Cerrar la ventana si es de diálogo
   if(m_wnd.WindowType()==W_DIALOG)
      m_wnd.CloseDialogBox();
//---
   return(true);
  }

El manejador de eventos de la paleta de colores CColorPicker::OnEvent() va a tener seis bloques en total. Cada método de la lista de arriba a ser llamado cuando llegue el identificador del evento correspondiente. Abajo se muestra el código completo del manejador de eventos del control:

//+------------------------------------------------------------------+
//| Manejador del evento del gráfico                                       |
//+------------------------------------------------------------------+
void CColorPicker::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Procesamiento del evento del desplazamiento del cursor
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      //--- Salir si el control está ocultado
      if(!CElement::IsVisible())
         return;
       //--- Coordenadas y el estado del botón izquierdo del ratón
      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);
      //--- Obtener el color debajo del cursor del ratón
      if(OnHoverColor(x,y))
         return;
      //---
      return;
     }
//--- Procesamiento del evento del clic izquierdo en el objeto
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Si el clic ha sido hecho en la paleta de colores
      if(OnClickPalette(sparam))
         return;
      //---
      return;
     }
//--- Procesamiento de la entrada del valor en el campo de edición
   if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
     {
      //--- Comprobación de la introducción del nuevo valor
      if(OnEndEdit(lparam,(int)dparam))
         return;
      //---
      return;
     }
//--- Procesamiento del clic en el control
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      //--- Si el clic ha sido hecho en el botón de opción
      if(OnClickRadioButton(lparam,(int)dparam,sparam))
         return;
      //---
      return;
     }
//--- Procesamiento del clic en los conmutadores de los campos de edición
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_INC || id==CHARTEVENT_CUSTOM+ON_CLICK_DEC)
     {
      //--- Comprobación de la introducción del nuevo valor
      if(OnEndEdit(lparam,(int)dparam))
         return;
      //---
      return;
     }
//--- Procesamiento del clic en el botón del control
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
     {
      //--- Salir si los identificadores no coinciden
      if(lparam!=CElement::Id())
         return;
      //--- Si el clic ha sido hecho en el botón «OK»
      if(OnClickButtonOK(sparam))
         return;
      //--- Si el clic ha sido hecho en el botón «Cancel»
      if(OnClickButtonCancel(sparam))
         return;
      //---
      return;
     }
  }

En muchos controles de nuestra librería hay método FastSwitching(). Suele utilizarse para el avance/retroceso rápido de los valores en los campos de edición, desplazamiento de las listas o tablas. No obstante, aquí es necesario para rediibujar la paleta de colores cuando está activado el avance/retroceso rápido de algún contador del campo de edición del componente. Puede estudiar el código del método CColorPicker::FastSwitching() en los archivos adjuntos al artículo.

 

 

Botón para abrir la paleta de colores

La clase para la creación de la paleta de colores ya está hecha, pero nos falta otro control más para poder usarla con productividad. Hace falta el botón que permita abrir la ventana con la paleta de colores. El botón debe estar organizado de tal manera que se vea el color que está establecido en este momento. Vamos a escribir la clase para la creación del botón de este tipo. Abajo se listan sus partes integrantes.

  1. Fondo del control
  2. Etiqueta de texto con la descripción
  3. Indicador del color seleccionado
  4. Fondo del botón
  5. Descripción del color seleccionado en el formato RGB

 

Fig. 3. Partes integrantes del botón «Botón para abrir la paleta de colores».


Ya hemos descrito los controles semejantes en los artículos anteriores, por eso no vamos a dar aquí la descripción de esta clase del código. En vez de eso, pasaremos directamente a la interacción entre el botón y la paleta de colores. En archivo adjunto al articulo se puede encontrar el fichero ColorButton.mqh con la clase CColorButton y estudiarlo más detalladamente. 

Necesitamos vincular la paleta de colores con el botón de su apertura. Hagámoslo usando el puntero del botón que va a guardarse en la clase CColorPicker. Para eso incluimos el archivo ColorButton.mqh en el archivo ColorPicker.mqh y declaramos la instancia de la clase CColorButton en la que va a almacenarse el puntero al botón de apertura de la paleta de colores.

//+------------------------------------------------------------------+
//|                                                  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"
//+------------------------------------------------------------------+
//| Clase para crear la paleta para seleccionar el color             |
//+------------------------------------------------------------------+
class CColorPicker : public CElement
  {
private:
   //--- Puntero al botón que llama al control para seleccionar el color
   CColorButton     *m_color_button;
  };

Además vamos a necesitar el método público para guardar el puntero al botón. Para facilitar al máximo la interacción entre el botón y la paleta, al pasar el objeto del botón para guardar su puntero, aquí mismo todos los marcadores de la paleta van a recibir el color actual del botón. Después de eso, se abrirá la ventana que contiene la paleta de colores (véase el código de abajo).  

class CColorPicker : public CElement
  {
public:
   //--- Guarda el puntero al botón que llama a la paleta de colores
   void              ColorButtonPointer(CColorButton &object);
  };
//+------------------------------------------------------------------+
//| Guarda el puntero al botón que llama a la paleta de colores y      |
//| abre la ventana que contiene la paleta                  |
//+------------------------------------------------------------------+
void CColorPicker::ColorButtonPointer(CColorButton &object)
  {
//--- Guardamos el puntero al botón
   m_color_button=::GetPointer(object);
//--- Establecemos el color del botón pasado para todos los marcadores de la paleta
   CurrentColor(object.CurrentColor());
//--- Abrimos la ventana a la que está adjuntada la paleta
   m_wnd.Show();
  }

Además, vamos a necesitar los métodos para determinar y obtener el color del botón. El color determinado va a mostrarse en el marcador (indicador) del botón. Como información adicional, en el contenido del texto del botón se mostrará la representación string del color en el formato RGB.

class CColorButton : public CElement
  {
public:
   //--- Devuelve/establece el color actual del parámetro
   color             CurrentColor(void)                 const { return(m_current_color);       }
   void              CurrentColor(const color clr);
  };
//+------------------------------------------------------------------+
//| Cambia el color actual del parámetro                                  |
//+------------------------------------------------------------------+
void CColorButton::CurrentColor(const color clr)
  {
   m_current_color=clr;
   m_button_icon.BackColor(clr);
   m_button_label.Description(::ColorToString(clr));
  }

Y otra pequeña adición se introduce en el método CColorPicker::OnClickButtonOK(). S el puntero al botón está establecido:

  • para el botón se establece el color seleccionado en la paleta de colores;
  • la ventana a la que está adjuntada la paleta se cierra;
  • se genera el mensaje indicando que en la paleta ha sido seleccionado nuevo color. Aquí se necesitará nuevo identificador del evento ON_CHANGE_COLOR que se encuentra en el archivo Defines.mqh. Además, este mensaje va a contener (1) el identificador del control, (1) identificador del elemento, (2) índice del control y (3) el texto del botón que ha abierto la paleta de colores. Así, en el manejador de la clase personalizada se podrá entender con qué botón está relacionado este mensaje, lo que permitirá procesar el evento correctamente;
  • el puntero al botón se anula. 

Si no hay puntero al botón, el desarrollador de la aplicación MQL recibirá un mensaje con la ayuda en el registro del terminal.

//+------------------------------------------------------------------+
//| Procesamiento del clic en el botón «OK»                                 |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickButtonOK(const string clicked_object)
  {
//--- Salir si el nombre del objeto no coincide
   if(clicked_object!=m_button_ok.Text())
      return(false);
//--- Guardar el color seleccionado
   m_current_color=m_picked_color;
   m_current.BackColor(m_current_color);
   m_current.Tooltip(::ColorToString(m_current_color));
//--- Si hay puntero del botón de apertura de la ventana para la selección del color
   if(::CheckPointer(m_color_button)!=POINTER_INVALID)
     {
      //--- Establecer el color seleccionado para el botón
      m_color_button.CurrentColor(m_current_color);
      //--- Cerramos la ventana
      m_wnd.CloseDialogBox();
      //--- Enviamos el mensaje sobre ello
      ::EventChartCustom(m_chart_id,ON_CHANGE_COLOR,CElement::Id(),CElement::Index(),m_color_button.LabelText());
      //--- Anulamos el puntero
      m_color_button=NULL;
     }
   else
     {
      //--- Si el puntero no existe y la ventana es de diálogo,
      //    mostrar el mensaje que no hay puntero al botón para la apertura del control
      if(m_wnd.WindowType()==W_DIALOG)
         ::Print(__FUNCTION__," > Puntero inválido del control de apertura (CColorButton).");
     }
//---
   return(true);
  }

Ahora tenemos todo preparado para probar la paleta de colores.

 

Prueba de controles

Se puede utilizar cualquier EA del artículo anterior para realizar el testeo. Haremos la copia y dejaremos dentro el menú principal y la barra de estado. En la ventana principal (W_MAIN) de la interfaz gráfica, crearemos cinco botones para abrir el cuadro de diálogo (W_DIALOG) con la paleta de colores. En otras palabras, será suficiente crear una paleta de colores para toda la aplicación MQL. Cada vez que se pinche en el botón de apertura del cuadro de diálogo con la paleta de colores, se abrirá la misma ventana. Pero en el momento de la llamada habrá que pasar el puntero del botón a la clase CColorPicker personalmente. A continuación, será mostrado cómo eso debe realizarse en la clase personalizada de la aplicación.

En la clase personalizada CProgram, hay que declarar las instancias de las clases para la creación de una ventana más (CWindow), cinco botones para llamar a la paleta de colores (CColorButton) y la paleta de colores (CColorPicker), así como los métodos para su creación con los márgenes desde el punto extremo del formulario.

class CProgram : public CWndEvents
  {
private:
   //--- Formulario 2 - ventana con la paleta de colores para seleccionar el color
   CWindow           m_window2;
   //--- Botones para abrir la ventana con la paleta de colores
   CColorButton      m_color_button1;
   CColorButton      m_color_button2;
   CColorButton      m_color_button3;
   CColorButton      m_color_button4;
   CColorButton      m_color_button5;
   //--- Paleta de colores
   CColorPicker      m_color_picker;
   //---
private:
   //--- Formulario 2
   bool              CreateWindow2(const string text);
   //--- Botones para abrir la paleta de colores
#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 colores
#define COLORPICKER_GAP_X     (1)
#define COLORPICKER_GAP_Y     (20)
   bool              CreateColorPicker(void);
  };

Los códigos de los métodos para la creación de los botones de apertura de la paleta de colores son prácticamente idénticos, por eso vamos a mostrar aquí sólo un ejemplo de ellos. La diferencia puede haber sólo en la determinación del color inicial que va a mostrarse en el indicador del botón inmediatamente después de la determinación, así como del texto en la descripción

//+------------------------------------------------------------------+
//| Crea el botón para abrir la paleta de colores 1                     |
//+------------------------------------------------------------------+
bool CProgram::CreateColorButton1(const string text)
  {
//--- Guardamos el puntero a la ventana
   m_color_button1.WindowPointer(m_window1);
//--- Coordenadas
   int x=m_window1.X()+COLORBUTTON1_GAP_X;
   int y=m_window1.Y()+COLORBUTTON1_GAP_Y;
//--- Establecemos las propiedades antes de la creación
   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);
//--- Crear el control
   if(!m_color_button1.CreateColorButton(m_chart_id,m_subwin,text,x,y))
      return(false);
//--- Añadimos el puntero al control a la base
   CWndContainer::AddToElementsArray(0,m_color_button1);
   return(true);
  }

La única diferencia del código del método para la creación del formulario del cuadro de diálogo y la ventana principal consiste solamente en el hecho de que es necesario especificar el tipo de la ventana (W_DIALOG). Aparte de eso, estableceremos una imagen única para esta ventana que indique en su propósito. Todas las imágenes van adjuntas al final del artículo. .

//+------------------------------------------------------------------+
//| Crea el formulario 2 para la paleta de colores                             |
//+------------------------------------------------------------------+
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp16\\color_picker.bmp"
//---
bool CProgram::CreateWindow2(const string caption_text)
  {
//--- Guardamos el puntero a la ventana
   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;
//--- Propiedades
   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");
//--- Creación del formulario
   if(!m_window2.CreateWindow(m_chart_id,m_subwin,caption_text,x,y))
      return(false);
//---
   return(true);
  }

Abajo se muestra el código del método CProgram::CreateColorPicker() para la creación de la paleta de colores. Es obligatorio guardar el puntero al cuadro de diálogo al que va adjuntarse el control. Al añadir el puntero del control a la base de controles, es necesario pasar el índice de la ventana al que está adjuntado el control. En este caso el índice de la ventana de diálogo es [1].

//+------------------------------------------------------------------+
//| Crea la paleta de colores para seleccionar el color                        |
//+------------------------------------------------------------------+
bool CProgram::CreateColorPicker(void)
  {
//--- Guardamos el puntero a la ventana
   m_color_picker.WindowPointer(m_window2);
//--- Coordenadas
   int x=m_window2.X()+COLORPICKER_GAP_X;
   int y=m_window2.Y()+COLORPICKER_GAP_Y;
//--- Creación del control
   if(!m_color_picker.CreateColorPicker(m_chart_id,m_subwin,x,y))
      return(false);
//--- Añadimos el puntero al control a la base
   CWndContainer::AddToElementsArray(1,m_color_picker);
   return(true);
  }

Al hacer clic en el botón, es necesario cuidar de que su puntero se pase a la paleta de colores. Se puede hacerlo en el manejador de eventos de la clase personalizada CProgram::OnEvent(). Al hacer clic en el botón, se genera el mensaje con el identificador del evento ON_CLICK_BUTTON. Además, el mensaje contiene el texto de la descripción del botón según el cual vamos a determinar qué objeto del botón tipo CColorButton hay que pasar a la paleta de colores. Una vez pasado el objeto del botón, se abrirá la ventana con la paleta de colorees, y en todos sus marcadores va a mostrarse el color del botón cuyo objeto acaba de ser traspasado. El código de abajo lo demuestra:

//+------------------------------------------------------------------+
//| Manejador de eventos                                               |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
 //--- Evento del clic en el botón
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
     {
      //--- Si ha sido pulsado el primer botón
      if(sparam==m_color_button1.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button1);
         return;
        }
      //--- Si ha sido pulsado el segundo botón
      if(sparam==m_color_button2.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button2);
         return;
        }
      //--- Si ha sido pulsado el tercer botón
      if(sparam==m_color_button3.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button3);
         return;
        }
      //--- Si ha sido pulsado el cuarto botón
      if(sparam==m_color_button4.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button4);
         return;
        }
      //--- Si ha sido pulsado el quinto botón
      if(sparam==m_color_button5.LabelText())
        {
         m_color_picker.ColorButtonPointer(m_color_button5);
         return;
        }
     }
  }

Una vez confirmada la selección del color con el clic en el botón «OK» en la paleta de colores, el mensaje con el identificador  ON_CHANGE_COLOR  será procesado tal como se muestra en el siguiente listado del código.

void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Evento del cambio del color a través de la paleta de colores
   if(id==CHARTEVENT_CUSTOM+ON_CHANGE_COLOR)
     {
      //--- Si los identificadores de los controles coinciden
      if(lparam==m_color_picker.Id())
        {
         //--- Si es la respuesta del primer botón
         if(sparam==m_color_button1.LabelText())
           {
            //--- Cambiar el color del objeto que se refiere al primer botón...
            return;
           }
         //--- Si es la respuesta del segundo botón
         if(sparam==m_color_button2.LabelText())
           {
            //--- Cambiar el color del objeto que se refiere al segundo botón...
            return;
           }
         //--- Si es la respuesta del tercer botón
         if(sparam==m_color_button3.LabelText())
           {
            //--- Cambiar el color del objeto que se refiere al tercer botón...
            return;
           }
         //--- Si es la respuesta del cuarto botón
         if(sparam==m_color_button4.LabelText())
           {
            //--- Cambiar el color del objeto que se refiere al cuarto botón...
            return;
           }
         //--- Si es la respuesta del quinto botón
         if(sparam==m_color_button5.LabelText())
           {
            //--- Cambiar el color del objeto que se refiere al quinto botón...
            return;
           }
        }
      return;
     }
  }

Compile el programa y cárguelo en el gráfico del terminal. El resultado se muestra en la captura de pantalla de abajo:

 Fig. 4. Prueba de los botones para abrir la paleta de colores.

Fig. 4. Prueba de los botones para abrir la paleta de colores.

Al pinchar en el botón de apertura de la paleta de colores (uno de cinco en la ventana principal), se abrirá la ventana para seleccionar el color (Color picker), tal como se muestra en la captura de pantalla de abajo:

 Fig. 5. Prueba del control «Paleta para seleccionar el color».

Fig. 5. Prueba del control «Paleta para seleccionar el color».

¡Ahora todo funciona tal como lo hemos planeado! 

 


Conclusión

En este artículo (el primer capítulo de la novena parte de la serie), hemos analizado un control bastante complejo de la interfaz gráfica, “Paleta para la selección del color”. Como control adicional, hemos creado el botón para abrir la paleta de colores. Ahora los usuarios de nuestra librería tienen posibilidad de controlar los colores de uno u otro objeto usando la interfaz gráfica de su aplicación MQL.

En el siguiente artículo será presentada la descripción de las clases del código de los siguientes elementos: «Indicador de progreso» y «Gráfico lineal».

Más abajo puede descargar el material de la novena parte de la serie para poder probar cómo funciona todo eso. Si le surgen algunas preguntas sobre el uso del material de estos archivos, puede dirigirse a la descripción detallada del proceso de desarrollo de la librería en uno de los artículos listados más abajo, o bien hacer su pregunta en los comentarios para el artículo.

Lista de artículos (capítulos) de la novena parte:


Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/2579

Archivos adjuntos |
Estudiamos la clase CCanvas. Suavizado y sombras Estudiamos la clase CCanvas. Suavizado y sombras
El algoritmo de suavizado de la clase CCanvas es la base de todas las construcciones en las que se usa el suavizado. En el artículo se cuenta cómo funciona este algoritmo y se muestran ejemplos visuales de su funcionamiento. Además, se analizará el dibujado de las sombras de los objetos gráficos y se desarrollará un algoritmo detallado del dibujado de la sombra en el elemento canvas. Para los cálculos se ha utilizado la biblioteca de análisis numérico ALGLIB.
Protección contra activaciones erróneas del robot comercial Protección contra activaciones erróneas del robot comercial
La rentabilidad de los sistemas comerciales se determina no solo por la lógica y la precisión del análisis de la dinámica de los instrumentos financieros, sino también por la calidad del algoritmo de ejecución de esta lógica. Una expresión característica de ejecución defectuosa de la lógica principal del robot comercial son las activaciones erróneas. En el artículo se analizan variantes para resolver este problema.
Asesor experto multiplataforma: Introducción Asesor experto multiplataforma: Introducción
En este artículo se describe con detalle un método para desarrollar de forma rápida y sencilla un asesor experto multiplataforma. El método propuesto aúna funciones comunes para ambas versiones en una clase y desarrolla la implementación para las funciones incompatibles en las clases heredadas.
Lógica difusa para crear estrategias de trading manual Lógica difusa para crear estrategias de trading manual
Este artículo sugiere las maneras de mejorar la estrategia de trading manual mediante la aplicación de teoría de conjuntos difusa. Como ejemplo hemos incluido una descripción paso a paso en la búsqueda de la estrategia y la selección de sus parámetros, seguido de la aplicación de lógica difusa para desenfocar criterios demasiado formales para entrar en el mercado. Así, después de la modificación de la estrategia obtenemos condiciones flexibles para la apertura de una posición que tiene una reacción razonable a una situación de mercado.