English Русский 中文 Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Cree sus propios paneles gráficos en MQL5

Cree sus propios paneles gráficos en MQL5

MetaTrader 5Ejemplos | 26 diciembre 2013, 09:04
2 357 0
MetaQuotes
MetaQuotes

Introducción

Hay disponibles un nuevo conjunto de clases en la librería estándar. Estas clases están pensadas para el desarrollo por separado de cuadros de diálogo y paneles gráficos en los programas de MQL5.

El nuevo conjunto de clases permite a cualquier persona crear componentes de interfaz personalizados usando el modelo de eventos como modelo subyacente. Todo se basa en los objetos gráficos incrustados y en los eventos del terminal.

Las clases que se han desarrollado pueden usarse de las siguientes formas:
  1. Un panel gráfico en una subventana gráfica separada;
  2. Un panel de control para un asesor experto;
  3. Un panel de control gráfico personalizado;

Este artículo demostrará lo fácil que es crear sus propios paneles gráficos en una subventana gráfica separada usando las clases de la librería estándar.


¿Qué nos puede ofrecer la librería estándar?

La librería estándar proporciona al programador los siguientes controles prediseñados:

1. Controles simples:

Control Aplicación Implementación basada en el objeto incrustado Archivo de librería estándar

Botón con texto

Asegurar la interacción entre el ratón y el programa MQL

"Botón"  <Controls\Button.mqh>

Botón con imagen

Asegurar la interacción entre el ratón y el programa MQL

"Etiqueta gráfica"  <Controls\BmpButton.mqh>

Edit

Entrada o representación en pantalla de información de texto (en el modo "Solo lectura")

"Editar"  <Controls\Edit.mqh>

Encabezado

Muestra información auxiliar de texto

"Etiqueta texto"  <Controls\Label.mqh>

Panel

Control auxiliar (agrupación visual de los controles)

"Etiqueta rectángulo"  <Controls\Label.mqh>

Imagen

Control decorativo

 "Etiqueta gráfica"  <Controls\Picture.mqh>



2. Controles complejos:


Control Aplicación Implementación basada en el objeto incrustado Archivo de librería estándar

Lista

Visualizar una lista

"Rectángulo", "Botón con imagen" y "Editar"  <Controls\List.mqh>

Campo con una lista desplegable

Campo con una lista desplegable

"Rectángulo", "Botón con imagen" y "Editar"  <Controls\ComboBox.mqh>

Campo incremento/decremento

Enumeración de valores

"Rectángulo" y "Botón con imagen"  <Controls\SpinEdit.mqh>

Botón radio

Interruptor "Botón con imagen" y "Encabezado"  <Controls\RadioButton.mqh>
Grupo de botón de radio Editar campos de tipo enumeración "Rectángulo" y "Botón radio"  <Controls\RadioGroup.mqh>

Casilla de verificación

Opción de selección

"Botón con imagen" y "Encabezado"  <Controls\CheckBox.mqh>

Grupo de casilla de verificación

Editar una serie de marcas

 "Rectángulo" y "Casilla de verificación"  <Controls\CheckGroup.mqh>
 Diálogo  Formulario de diálogo  "Rectángulo", "Botón con imagen" y "Editar"  <Controls\Dialog.mqh>



Crear un panel gráfico

Vamos a definir primero los términos. El panel gráfico (Display) es un término que usaremos para describir una representación personalizada en una ventana separada que no tiene buffer de dibujado. Este panel simplemente muestra en pantalla la información necesaria usando los objetos del gráfico incrustados en el terminal. La información puede mostrarse:

  • de forma numérica,
  • como texto,
  • como color,
  • etc.

veremos en detalle cada paso necesario y crearemos un panel gráfico de la siguiente forma:



Para crear un panel gráfico necesitaremos dos archivos:

  1. El archivo include que contiene la descripción de la clase del panel gráfico.
  2. El archivo del código fuente del indicador.

Las plantillas de estos archivos pueden obtenerse usando el MQL5 Wizard. En la carpeta de indicadores (MQL5\Indicators), cree una carpeta separada MyIndicators y una subcarpeta MyPanel. El proceso de creación de carpetas no será tratado aquí ya que se describe adecuadamente en la ayuda.


Descripción de la clase

Ya hemos creado la carpeta de trabajo. Vamos ahora a localizarla en la ventana del navegador y a hacer clic con el botón derecho del ratón sobre ella. Seleccione "Nuevo archivo" en el menú que aparece. Seleccione la "Nueva clase" entre las opciones que proporciona MQL5 Wizard y haga clic en "Próximo". Complete el diálogo de descripción de la clase como se muestra a continuación:

Creando una nueva clase en el MQL5 Wizard

Haga clic en "Finalizar". Obtendremos como resultado el siguiente código:

//+------------------------------------------------------------------+
//|                                                  PanelDialog.mqh |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CPanelDialog : public CAppDialog
  {
private:

public:
                     CPanelDialog();
                    ~CPanelDialog();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CPanelDialog::CPanelDialog()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CPanelDialog::~CPanelDialog()
  {
  }
//+------------------------------------------------------------------+


Añada el archivo include <Controls\Dialog.mqh> de la librería estándar con la descripción de la clase base CAppDialog y los comentarios.

//+------------------------------------------------------------------+
//|                                                  PanelDialog.mqh |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Controls\Dialog.mqh>
//+------------------------------------------------------------------+
//| CPanelDialog class                                               |
//| Función: diálogo de la aplicación principal                      |
//+------------------------------------------------------------------+
class CPanelDialog : public CAppDialog
  {
private:

public:
                     CPanelDialog(void);
                    ~CPanelDialog(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPanelDialog::CPanelDialog(void)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CPanelDialog::~CPanelDialog(void)
  {
  }
//+------------------------------------------------------------------+

Ahora tenemos la descripción de todas las clases que nos permitirá usar un cuadro de diálogo en su indicador. Nuestro diálogo está actualmente vacío pero le añadiremos controles un poco más tarde. De momento vamos a proceder con el indicador.


El código fuente del indicador.

El indicador también se creará usando el MQL5 Wizard. Nuestras acciones serán similares a las requeridas cuando escribimos la descripción de la clase. Solo hay una diferencia: seleccionamos "indicador personalizado"de entre las opciones que proporciona el MQL5 Wizard. Para crear un indicador deben completarse tres diálogos.

El primero requiere especificar el nombre del indicador:

Creando un nuevo indicador en el MQL5 Wizard


En el segundo diálogo deseleccione "OnChartEvent" (requerido) y "Ontimer":

Estableciendo controladores de eventos para indicador personalizado en el MQL5 Wizard



Deseleccione el "Indicador de ventana separada" (requerido) en el tercer diálogo:

Estableciendo las propiedades de dibujado del indicador en el MQL5 Wizard


Haga clic en "Finalizar". El código es como se muestra a continuación:

//+------------------------------------------------------------------+
//|                                               PanelIndicator.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function           |
//+------------------------------------------------------------------+
int OnInit()
  {
//---indicator buffers mapping
   
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
              const int prev_calculated,
              const int begin,
              const double &price[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Timer function                                                    |
//+------------------------------------------------------------------+
void OnTimer() 
  {
//---   

  }
//+------------------------------------------------------------------+
//| ChartEvent function                                               |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                const long &lparam,
                const double &dparam,
                const string &sparam)
  {
//---   

  }
//+------------------------------------------------------------------+


Nuestra plantilla puede ahora completarse añadiendo:

  • descripciones omitidas de las propiedades del indicador;
  • archivo include con la descripción de la clase de nuestro diálogo;
  • una variable global - el objeto de clase de nuestro diálogo;
  • código para crear el diálogo, iniciando la aplicación y creando el temporizador para el cuerpo de la función OnInit().
  • Función OnDeinit() con un código que destruye el diálogo y mata el temporizador;
  • Función OnChartEvent(...) para el código de llamada al controlador de evento;
  • comentarios.

Tenemos el indicador listo para su uso:

//+------------------------------------------------------------------+
//|                                               PanelIndicator.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_plots               0
#property indicator_buffers             0
#property indicator_minimum             0.0
#property indicator_maximum             0.0
//+------------------------------------------------------------------+
//| Include files                                                 |
//+------------------------------------------------------------------+
#include "PanelDialog.mqh"
//+------------------------------------------------------------------+
//| Global variables                                               |
//+------------------------------------------------------------------+
CPanelDialog ExtDialog;
//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- creating the application dialog
   if(!ExtDialog.Create(0,"Panel Indicator",0,0,0,0,130))
     return(-1);
//--- starting the application
   if(!ExtDialog.Run())
     return(-2);
//--- creating the timer
   EventSetTimer(1);
//--- éxito
   return(0);
  }
//+------------------------------------------------------------------+
//| Deinitialización                                                 |
//+------------------------------------------------------------------+
int OnDeinit()
  {
//--- destruyendo el diálogo
   ExtDialog.Destroy();
//--- matando el temporizador
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Iteración                                                        |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
              const int prev_calculated,
              const int begin,
              const double &price[])
  {  
//--- devolviendo el valor de prev_calculated para la próxima llamada
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Controlador de evento del temporizador                           |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
  }
//+------------------------------------------------------------------+
//| Controlador de evento del gráfico                                |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                const long &lparam,
                const double &dparam,
                const string &sparam)
  {
//--- gestionando el evento
   ExtDialog.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+

El indicador en el formulario anterior no muestra nada aún. Cuando se compile y se sitúe en el gráfico se mostrará como un diálogo vacío en una ventana separada.

A pesar de que el diálogo esté vacío ha adquirido ya algunas características:

  • se ha ajustado la altura de la subventana a la altura del diálogo por parte del indicador durante la creación;
  • la anchura del diálogo siempre es igual a la anchura del gráfico;
  • el indicador puede minimizar y maximizar su propia subventana.

Hagamos que se muestre en pantalla

Para que nuestro panel comience a mostrar algún tipo de información debemos responder a tres preguntas:

  1. ¿Qué tipo de información queremos mostrar?
  2. ¿Qué elementos adicionales y/o control hay que incluir en nuestro diálogo?
  3. ¿Como van a interaccionar estos elementos/controles adicionales entre sí?

Otro factor importante es que nuestro diálogo debe ser visualmente atractivo y de fácil uso. No afecta a a funcionalidad del diálogo pero muestra que nos preocupamos por los usuarios del futuro programa MQL5.

   Paso 1. ¿Qué tipo de información queremos mostrar?

Como este artículo es una herramienta de aprendizaje, vamos a centrarnos en la funcionalidad del indicador. El color se mostrará en pantalla como una función de tres parámetros. No vamos a complicar demasiado los parámetros y estos serán de niveles "rojo", "verde" y "azul".

Los valores de los parámetros se establecerán de la siguiente forma:

  • El valor del nivel "rojo" se establecerá en un rango de 0 a 255, cambiando aleatoriamente en cada evento Calculate;
  • El valor del nivel "verde" se establecerá en un rango de 0 a 255, cambiando aleatoriamente en cada evento Timer;
  • El valor del nivel "azul" se establecerá en un rango de 0 a 255 y cambiará manualmente por medio de un control especial.

A propósito, los valores de estos niveles se mostrarán también en nuestro indicador.


   Paso 2. ¿Qué controles adicionales serán necesarios?

  1. El color se mostrará en pantalla usando el control "Panel".
  2. Los niveles "rojo" y "verde" se mostrarán en pantalla usando el control "Edit" en el modo "Solo lectura".
  3. El nivel "azul" será gestionado por el control "Spin Edit". El mismo control ayudará a mostrar el valor del nivel.
  4. Ambos controles "Edit" y "Spin Edit" se mejorarán con encabezados explicativos a través del control "Caption".

Añada los archivos include de la librería estándar y los controles y variables necesarios que guardan los valores de los parámetros para la descripción de la clase en que se han suministrado los comentarios.

Tendremos:

//+------------------------------------------------------------------+
//|                                                  PanelDialog.mqh |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Controls\Dialog.mqh>
#include <Controls\Panel.mqh>
#include <Controls\Edit.mqh>
#include <Controls\Label.mqh>
#include <Controls\SpinEdit.mqh>
//+------------------------------------------------------------------+
//| Clase CPanelDialog                                               |
//| Función: diálogo de la aplicación principal                      |
//+------------------------------------------------------------------+
class CPanelDialog : public CAppDialog
  {
private:
   //--- controles adicionales
   CPanel            m_color;                         // objeto para mostrar el color en pantalla
   CLabel            m_label_red;                     // objeto de encabezado de nivel "rojo"
   CEdit             m_field_red;                     // objeto para mostrar en pantalla de valor "rojo"
   CLabel            m_label_green;                   // objeto de encabezado de nivel "verde"
   CEdit             m_field_green;                   // objeto para mostrar en pantalla de valor "verde"
   CLabel            m_label_blue;                    // objeto de encabezado de nivel "azul"
   CSpinEdit         m_edit_blue;                     // objeto de control de valor "azul"
   //--- valores del parámetro
   int               m_red;                           // "rojo" valor
   int               m_green;                         // "verde" valor
   int               m_blue;                          // valor "azul"

public:
                     CPanelDialog(void);
                    ~CPanelDialog(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPanelDialog::CPanelDialog(void)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CPanelDialog::~CPanelDialog(void)
  {
  }
//+------------------------------------------------------------------+


   Paso 3. ¿Cómo van a interaccionar estos controles de diálogo adicionales?
El principio de la interacción entre los controles de diálogo será muy simple: "El diálogo deberá mostrar los cambios en cualquier parámetro (niveles "rojo", "verde" y "azul"). Más tarde veremos la implementación de los algoritmos de interacción ya que ahora es el momento de comenzar con la creación del diálogo.


Unas palabras sobre la apariencia visual

Antes de proceder con la creación del diálogo, valor a ver rápidamente algo sobre su aspecto. O mejor dicho, una disposición y (posible) configuración futura de los controles de diálogo. Named constants (#define) sirve mejor para este propósito..

Las constantes con nombres predefinidos ofrecen algunas ventajas:

  • determinados valores numéricos usados en casos específicos no tienen por qué ser recordados. Los nombres de las constantes elegidos con precisión proporcionan una forma rápida de acceder a ellas a través de los "nombres de la lista automáticos";
  • cuando los valores de las constantes se modifican posteriormente, no hay que buscar ni reemplazar muchas inclusiones de valores numéricos. Es suficiente con cambiar solo la descripción de la constante.

Se aconseja el uso de las siguientes constantes:

//+------------------------------------------------------------------+
//| define                                                           |
//+------------------------------------------------------------------+
//--- sangrados y espaciado
#define INDENT_LEFT                         (11)      // sangrado izquierdo (incluyendo el ancho del borde)
#define INDENT_TOP                          (11)      // sangrado superior (incluyendo el ancho del borde)
#define INDENT_RIGHT                        (11)      // sangrado derecho (incluyendo el ancho del borde)
#define INDENT_BOTTOM                       (11)      // sangrado inferior (incluyendo el ancho del borde)
#define CONTROLS_GAP_X                      (10)      // espaciado a lo largo del eje X
#define CONTROLS_GAP_Y                      (10)      // espaciado a lo largo del eje Y
//--- para las etiquetas
#define LABEL_WIDTH                         (50)      // tamaño a la largo del eje X
//--- para los campos edit
#define EDIT_WIDTH                          (50)      // tamaño a lo largo del eje Y
#define EDIT_HEIGHT                         (20)      // a lo largo del eje Y
//--- para los colores base (RGB)
#define BASE_COLOR_MIN                      (0)       // valor mínimo del componente del color
#define BASE_COLOR_MAX                      (255)     // máximo valor del componente del color


Rellenando el Panel

Antes hemos creado la clase del panel para mostrar en pantalla y ahora, para lograr la funcionalidad requerida necesitamos hacer lo siguiente:

1. Redefinir el método Create(...) de la clase matriz: originariamente nuestro método sería como se muestra a continuación:

//+------------------------------------------------------------------+
//| Creación                                                         |
//+------------------------------------------------------------------+
bool CPanelDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
//--- llamando al método de la clase matriz
   if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))  return(false);
//--- los controles adicionales deben crearse aquí

//--- éxito
   return(true);
  }


2. Crear controles adicionales.

Un ligero paréntesis lírico. Los códigos para crear todos los controles adicionales pueden, por supuesto, ser insertados directamente en el cuerpo del método Create(...), pero de esta forma nos arriesgamos a obtener una gran "masa" imposible de leer.

Por tanto vamos a dividir el proceso de creación en partes autocontenidas representadas por métodos:

  • bool CreateColor(void)  - creación del color del panel,
  • bool CreateRed(void)    - crear el elemento para mostrar en pantalla "Rojo" con encabezado explicativo,
  • bool CreateGreen(void) - crear el elemento para mostrar en pantalla "Verde" con encabezado explicativo,
  • bool CreateBlue(void)    - crear el control "Azul" con encabezado explicativo,

Estos métodos son llamados secuencialmente desde el método Create(...):

//+------------------------------------------------------------------+
//| Creación                                                         |
//+------------------------------------------------------------------+
bool CPanelDialog::Create(const long chart,const string name,const int subwin,
                             const int x1,const int y1,const int x2,const int y2)
  {
//--- llamando al método de la clase matriz
   if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2)) return(false);

//--- creando elementos adicionales
   if(!CreateColor()) return(false);
   if(!CreateRed())   return(false);
   if(!CreateGreen()) return(false);
   if(!CreateBlue())  return(false);
//--- éxito
   return(true);
  }


Creación de controles

No vamos a revisar la creación de cada control adicional pero vamos a ver en detalle el método booleano CreateBlue (void).

Es como se muestra a continuación:

//+------------------------------------------------------------------+
//| Creando el control "Azul" con encabezado explicativo             |
//+------------------------------------------------------------------+
bool CPanelDialog::CreateBlue(void)
  {
//--- coordenadas
   int x1=INDENT_LEFT;
   int y1=INDENT_TOP+2*(EDIT_HEIGHT+CONTROLS_GAP_Y);
   int x2=x1+EDIT_WIDTH;
   int y2=y1+EDIT_HEIGHT;
//--- creando el encabezado
   if(!m_label_blue.Create(m_chart_id,m_name+"LabelBlue",m_subwin,x1,y1+1,x2,y2)) return(false);
   if(!m_label_blue.Text("Blue")) return(false);
   if(!Add(m_label_blue)) return(false);
//--- ajustando las coordenadas
   x1+=LABEL_WIDTH+CONTROLS_GAP_X;
   x2=x1+EDIT_WIDTH;
//--- creando el control
   if(!m_edit_blue.Create(m_chart_id,m_name+"Blue",m_subwin,x1,y1,x2,y2)) return(false);
   if(!Add(m_edit_blue)) return(false);
   m_edit_blue.MinValue(BASE_COLOR_MIN);
   m_edit_blue.MaxValue(BASE_COLOR_MAX);
   m_edit_blue.Value(m_blue);
//--- éxito
   return(true);
  }

Hay dos matices:

  1. El control se crea con coordenadas relativas, es decir, el desplazamiento se establece con relación a la esquina superior izquierda del contenedor (elemento complejo) al que el control será añadido después de la creación.
  2. Siguiendo la creación, es necesario añadir el control a un contenedor usando el método Add (...). En nuestro caso, el diálogo sirve como contenedor.


Cambiar los parámetros

Añada el método void SetColor (void) para cambiar el color del panel.

Para poder cambiar los parámetros (niveles de los colores base) externamente, añadiremos tres métodos públicos:

  • void SetRed(const int value)     - cambia el nivel "rojo" y muestra el cambio en el indicador,
  • void SetGreen(const int value)  - cambia el nivel "verde" y muestra el cambio en el indicador,
  • void SetBlue(const int value)    - cambia el nivel "azul" y muestra el cambio en el indicador,

La frase "muestra el cambio en el indicador" significa que un nuevo valor del nivel de color base se muestra en pantalla de forma numérica en el color correspondiente y el panel cambia su color.

A continuación se muestra el código de uno de los métodos que sirve como ejemplo:

//+------------------------------------------------------------------+
//| Estableciendo el valor "Rojo"                                    |
//+------------------------------------------------------------------+
void CPanelDialog::SetRed(const int value)
  {
//--- comprobando
   if(value<0 || value>255) return;
//--- guardando
   m_red=value;
//--- estableciendo
   m_field_red.Text(IntegerToString(value));
//--- estableciendo el color del panel
   SetColor();
  }

Como acordamos antes:

  • El nivel del color "rojo" cambiará de forma aleatoria con cada evento calculate;
  • El nivel del color "verde" cambiará de forma aleatoria con cada evento timer;

Vamos a añadir el código importante en el indicador original:

//+------------------------------------------------------------------+
//|                                               PanelIndicator.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_plots               0
#property indicator_buffers             0
#property indicator_minimum             0.0
#property indicator_maximum             0.0
//+------------------------------------------------------------------+
//| Archivos include                                                 |
//+------------------------------------------------------------------+
#include "PanelDialog.mqh"
//+------------------------------------------------------------------+
//| variables globales                                               |
//+------------------------------------------------------------------+
CPanelDialog ExtDialog;
//+------------------------------------------------------------------+
//| Inicialización                                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- creando el diálogo de la aplicación
   if(!ExtDialog.Create(0,"Panel Indicator",0,0,0,0,130))
      return(-1);
//--- iniciando la aplicación
   if(!ExtDialog.Run())
      return(-2);
//--- creando el temporizador
   EventSetTimer(1);
//--- éxito
   return(0);
  }
//+------------------------------------------------------------------+
//| Deinicialización                                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destruyendo el diálogo
   ExtDialog.Destroy();
//--- deteniendo el temporizador
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Iteración                                                        |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//--- cambiando la propiedad del diálogo
   ExtDialog.SetRed(MathRand()%256);
//--- devolviendo el valor de prev_calculated para la próxima llamada
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Controlador del evento timer                                     |
//+------------------------------------------------------------------+
void OnTimer()
  {
//--- cambiando la propiedad del diálogo
   ExtDialog.SetGreen(MathRand()%256);
  }
//+------------------------------------------------------------------+
//| Controlador del evento del gráfico                               |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---controlando el evento
   ExtDialog.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+


Gestionar los eventos.

Toda la interacción entre el diálogo y el terminal así como la interacción entre los controles del diálogo está basada en el mecanismo del evento. No vamos a revisar sus funciones sino simplemente a usarlo.

Los eventos pueden dividirse habitualmente en dos grupos:

  • Eventos internos que se gestionan pasando por encima de la cola del evento del terminal;
  • Eventos externos que se gestionan pasando a través de la cola del evento del terminal;

Vamos a gestionar ambos tipos de eventos.

Entre los eventos internos solo se requiere gestionar los eventos que modifican el tamaño. Para esta finalidad, recargue el método OnResize() de la clase matriz. Nuestro método será simple ya que no hay cambio en la altura del diálogo. Si cambia el ancho del diálogo solo tenemos que modificar el ancho del panel de color:

//+------------------------------------------------------------------+
//| Controlador de redimensionado                                    |
//+------------------------------------------------------------------+
bool CPanelDialog::OnResize(void)
  {
//--- llamando al método de la clase matriz
   if(!CAppDialog::OnResize()) return(false);
//--- cambiando el ancho del panel de color
   m_color.Width(ClientAreaWidth()-(INDENT_RIGHT+LABEL_WIDTH+CONTROLS_GAP_X+EDIT_WIDTH+CONTROLS_GAP_X+INDENT_LEFT));
//--- éxito
   return(true);
  }

La lista de eventos externos también se limitará a un elemento, el evento de cambiar el nivel "azul". Los requisitos para el controlador de eventos externos son mínimos: el controlador debe ser el método de la clase sin parámetros del tipo void.

Vamos a describir el controlador de este evento:

//+------------------------------------------------------------------+
//| Controlador del evento para cambiar el nivel "azul"              |
//+------------------------------------------------------------------+
void CPanelDialog::OnChangeBlue(void)
  {
//--- guardando
   m_blue=m_edit_blue.Value();
//--- estableciendo el color del panel
   SetColor();
  }

Como puede verse, no hay nada difícil en ello.

Para que nuestro diálogo controle eventos externos, debe recargarse el método de la clase padre:

virtual bool  OnEvent(const int id,const long &lparam,
                       const double &dparam,const string &sparam);

Y ahora un poco de misterio. Si ya ha abierto el archivo PanelDialog.mqh en el Editor, verá que no hay cuerpo en el método OnEvent(...).

No se confunda, esto es así porque se ha creado un conjunto de macros para la descripción del control de eventos externos (vea el archivo de la librería estándar <Controls\Defines.mqh>).

Nuestro controlador de evento es:

//+------------------------------------------------------------------+
//| Controlando eventos                                              |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CPanelDialog)
   ON_EVENT(ON_CHANGE,m_edit_blue,OnChangeBlue)
EVENT_MAP_END(CAppDialog)

Este seudocódigo, que puede ser poco claro a primera, vista hace lo siguiente:

  • Cuando el evento ON_CHANGE es recibido del control m_edit_blue, se llama al método OnChangeBlue y se completa el control del evento (devolviendo verdadero).
  • Cuando se recibe cualquier otro evento, el control es transferido al método de la clase padre.

Conclusión

Este artículo ha realizado una revisión del proceso de creación de un panel para su representación en pantalla usando las clases de la librería estándar.

Es poco probable que tenga que utilizar el indicador tal y como lo hemos creado, a pesar de que no lo hemos sobrecargado con información innecesaria y que hemos tratado de cubrir todas las peculiaridades del proceso al crearlo.

En las siguientes carpetas del terminal puede encontrar ejemplos más complejos:

  • Experts\Examples\Controls\
  • Indicators\Examples\Panels\ChartPanel\
  • Indicators\Examples\Panels\SimplePanel\

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

Archivos adjuntos |
paneldialog.mqh (26.79 KB)
panelindicator.mq5 (6.81 KB)
Las bases de la programación orientada a objetos Las bases de la programación orientada a objetos
No necesita saber qué es poliformismo, encapsulación, etc. para usar la programación orientada a objetos (OOP)... puede simplemente utilizar estas funciones. Este artículo trata las bases de la OOP con ejemplos prácticos.
MQL5 Wizard: Nueva Versión MQL5 Wizard: Nueva Versión
Este artículo contiene descripciones de los nuevos elementos disponibles en el MQL5 Wizard actualizado. La arquitectura actualizada de señales nos permite crear robots de trading basados en la combinación de varios patrones de mercado. El ejemplo que contiene este artículo explica el procedimiento de creación interactiva de un Asesor Experto.
El enfoque orientado a objeto para construir paneles multiperíodo y multidivisa El enfoque orientado a objeto para construir paneles multiperíodo y multidivisa
Este artículo describe cómo la programación orientada a objeto puede usarse para crear paneles multiperíodo y multidivisa para Meta Trader 5. El objetivo principal es construir un panel universal que pueda ser usado para mostrar en pantalla diferentes tipos de datos como precios, cambios en los precios, valores de indicador o condiciones sell/buy personalizadas sin necesidad de modificar el código del propio panel.
Uso de los recursos en MQL5 Uso de los recursos en MQL5
Los programas MQL5 no solo automatizan cálculos rutinarios, sino que también pueden crear un entorno gráfico completo. Las funciones para crear controles realmente interactivos son ahora virtualmente tan ricas como las de los lenguajes de programación. Si desea escribir un programa entero e independiente en MQL5, use los recursos disponibles en ellos. Los programas con recursos son más fáciles de mantener y distribuir.