Discusión sobre el artículo "Interfaces gráficas II: Controles "Línea separadora" y "Menú contextual" (Capítulo 2)"

 

Artículo publicado Interfaces gráficas II: Controles "Línea separadora" y "Menú contextual" (Capítulo 2):

En este artículo nos ocuparemos de la creación del control llamado “Línea separadora”. Se podrá utilizarlo no sólo como un elemento independiente de la interfaz, sino también como parte de otros controles. Después de eso, tendremos todo lo necesario para desarrollar la clase del menú contextual, que también será considerado al detalle en el presente artículo. Además, vamos a introducir adiciones necesarias en la clase que sirve de base para almacenar los punteros a todos los controles de la interfaz gráfica de la aplicació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 biblioteca (Capítulo 1).

Desarrollando la clase para crear una línea separadora

En el menú contextual, aparte de varios tipos de elementos del menú, a menudo se puede observar un control más: es la línea separadora. Este control puede encontrarse no sólo en los menús contextuales. Por ejemplo, también podemos ver las líneas separadoras verticales en la barra de estado del terminal comercial MetaTrader y editor de códigos MetaEditor. Por eso, para este objeto vamos a crear una clase individual para tener la posibilidad de utilizarla en cualquier otro control, o incluso para usarla como un control separado del diseño de la interfaz gráfica.

Para imitar el relieve, una línea separadora debe componerse como mínimo de dos partes. Si hacemos una línea más clara que el fondo y la otra va a ser más oscura, obtendremos visualmente una canaleta en la superficie. Hay dos modos de crear una línea separadora: (1) usar dos objetos primitivos tipo CRectLabel que ya tenemos en el archivo Objects.mqh, o (2) crear un objeto tipo OBJ_BITMAP_LABEL y usarlo como lienzo para dibujar. Nosotros vamos a utilizar la segunda opción. Para dibujar, la librería estándar propone la clase CCanvas. Esta clase ya contiene todos los métodos necesarios para dibujar las figuras geométricas simples, lo que facilitará considerablemente la implementación de nuestra idea y nos ahorrará un montón de tiempo. 

La clase CCanvas tiene que ser integrada en la librería que desarrollamos de tal manera que haya posibilidad de usarla igual que los objetos primitivos que ahora se encuentran en el archivo Objects.mqh. Es fácil de conseguir si hacemos que la clase CCanvas sea derivada de la clase CChartObjectBmpLabel. Pero habrá que introducir una pequeña modificación en la clase CCanvas para que luego no aparezcan errores o advertencias durante la compilación del programa. Es que en la clase CCanvas, igual que en la clase CChartObject que es base para la clase CChartObjectBmpLabel, hay campo (variable) m_chart_id. Por eso, el compilador mostrará la advertencia diciendo que la variable con este nombre ya existe:

Fig. 1. Advertencia del compilador diciendo que la variable con este nombre ya existe.

Autor: Anatoli Kazharski

 
¿Existe algún mecanismo para vincular/delegar acciones/comandos a diferentes controles? Por ejemplo, ¿a un botón de la barra de herramientas y a un elemento del menú contextual? El patrón "comando" sería adecuado para esto. Al mismo tiempo, es posible implementar el mecanismo de Deshacer/Rehacer a través del almacenamiento en el historial de comandos ejecutados, guardando los valores iniciales del destinatario.

También es bueno introducir el concepto de un modelo, que es escuchado por tal o cual control (observador del patrón). Esto permitirá que todos los controles de la interfaz reaccionen de forma transparente a los cambios en el modelo.

Por ejemplo, hasta que el modelo de gráfico no haya sido inicializado por el usuario, todos los controles relacionados con la gestión del gráfico tendrán una vista desactivada. Esto elimina la necesidad de acceder directamente a los controles y a la lógica responsable de su comportamiento en determinados casos.
 
Igor Volodin:
¿Existe algún mecanismo para vincular/delegar acciones/comandos a diferentes controles? Por ejemplo, ¿a un botón de la barra de herramientas y a un elemento del menú contextual? El patrón "comando" sería adecuado para esto. Al mismo tiempo, es posible implementar el mecanismo de Deshacer/Rehacer a través del almacenamiento en el historial de comandos ejecutados, guardando los valores iniciales del destinatario.

También es bueno introducir el concepto de un modelo, que es escuchado por tal o cual control (observador del patrón). Esto permitirá que todos los controladores de la interfaz reaccionen de forma transparente a los cambios en el modelo.

Por ejemplo, hasta que el modelo de gráfico no haya sido inicializado por el usuario, todos los controladores relacionados con la gestión del gráfico tendrán una vista desactivada. Esto elimina la necesidad de acceder directamente a los controles y a la lógica responsable de su comportamiento en determinados casos.

En la versión actual de la librería en algunos casos el intercambio de comandos entre elementos se implementa a través de eventos personalizados. En el próximo artículo se hablará más de ello.

En cuanto a los mecanismos adicionales, todo es negociable. Después de la publicación de toda la serie, se puede ir a través de todos los elementos del esquema y hacer una lista de lo que debe ser cambiado o añadido, si hay argumentos por qué sería mejor / fiable / conveniente, etc.

Puede que haya entendido mal la pregunta. Entonces necesitas que te aclare qué es exactamente lo que necesitas conseguir y cómo debería ser.

 
¿Por qué un array de variables?
color             m_area_color_array[];
Y en el constructor de CContextMenu() necesitas establecer la variable m_item_Ysize a un tamaño mayor que cero por defecto.