Cree sus propios paneles gráficos en MQL5
MetaQuotes | 26 diciembre, 2013
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.
- Un panel gráfico en una subventana gráfica separada;
- Un panel de control para un asesor experto;
- 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:
- El archivo include que contiene la descripción de la clase del panel gráfico.
- 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:
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:
En el segundo diálogo deseleccione "OnChartEvent" (requerido) y "Ontimer":
Deseleccione el "Indicador de ventana separada" (requerido) en el tercer diálogo:
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:
- ¿Qué tipo de información queremos mostrar?
- ¿Qué elementos adicionales y/o control hay que incluir en nuestro diálogo?
- ¿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?
Paso 3. ¿Cómo van a interaccionar estos controles de diálogo adicionales?
- El color se mostrará en pantalla usando el control "Panel".
- Los niveles "rojo" y "verde" se mostrarán en pantalla usando el control "Edit" en el modo "Solo lectura".
- El nivel "azul" será gestionado por el control "Spin Edit". El mismo control ayudará a mostrar el valor del nivel.
- 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) { } //+------------------------------------------------------------------+
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:
- 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.
- 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\