- Descripción de recursos mediante la directiva #resource
- Uso compartido de recursos de distintos programas MQL
- Variables de recursos
- Conectar indicadores personalizados como recursos
- Creación de recursos dinámicos: ResourceCreate
- Eliminar recursos dinámicos: ResourceFree
- Leer y modificar datos de recursos: RecursoReadImage
- Guardar imágenes en un archivo: ResourceSave
- Fuentes y salida de texto a recursos gráficos
- Aplicación de recursos gráficos en trading
Variables de recursos
La directiva #resource tiene una forma especial con la que se pueden declarar archivos externos como variables de recursos y acceder a ellos dentro del programa como variables normales del tipo correspondiente. El formato de la declaración es:
#resource "path_file_name" as resource_variable_type resource_variable_name |
He aquí algunos ejemplos de declaraciones:
#resource "data.bin" as int Data[] //array of int type with data from the file data.bin
|
Demos algunas explicaciones. Las variables de recursos son constantes (no se pueden modificar en el código MQL5). Por ejemplo, para editar imágenes antes de mostrarlas en pantalla, debe crear copias de variables de array de recursos.
En el caso de los archivos de texto (recursos de tipo string), la codificación se determina automáticamente por la presencia de un encabezado de BOM. Si no hay BOM, la codificación viene determinada por el contenido del archivo. Se admiten las codificaciones ANSI, UTF-8 y UTF-16. Al leer datos de archivos, todas las cadenas se convierten a Unicode.
El uso de variables de cadena de recursos puede facilitar enormemente la escritura de programas basados no solo en MQL5 puro, sino también en tecnologías adicionales. Por ejemplo, puede escribir código OpenCL (que está admitido en MQL5 como una extensión) en un archivo separado y, a continuación, incluirlo como una cadena en los recursos de un programa MQL. En el ejemplo de Asesor Experto hemos utilizado ya cadenas de recursos para incluir plantillas HTML.
Para las imágenes se ha introducido un tipo especial bitmap; este tipo tiene varias características.
El tipo bitmap describe un único punto o píxel en una imagen y se representa mediante un entero sin signo de 4 bytes (uint). El píxel contiene 4 bytes que corresponden a los componentes de color en formato ARGB o XRGB (una letra = un byte), donde R es rojo, G es verde, B es azul, A es transparencia (canal alfa), X es un byte ignorado (sin transparencia). La transparencia puede utilizarse para obtener diversos efectos al superponer imágenes en un gráfico y unas sobre otras.
Estudiaremos la definición de los formatos ARGB y XRGB en la sección dedicada a la creación dinámica de recursos gráficos (véase ResourceCreate). Por ejemplo, para ARGB, el número hexadecimal 0xFFFF0000 especifica un píxel totalmente opaco (el byte más alto es 0xFF) de color rojo (el byte siguiente también es 0xFF) y los bytes siguientes para los componentes verde y azul son cero.
Es importante señalar que la codificación del color del píxel es diferente de la representación en bytes del tipo color. Recordemos que el valor del tipo color puede escribirse en forma hexadecimal de la siguiente manera: 0x00BBGGRR, donde BB, GG, RR son los componentes azul, verde y rojo, respectivamente (en cada byte, el valor 255 da la intensidad máxima del componente). Con un registro similar de un píxel, hay un orden inverso de bytes: 0xAARRGGBB. La transparencia total se obtiene cuando el byte alto (aquí denotado AA) es 0 y el valor 255 es un color sólido. La función ColorToARGB se puede utilizar para convertir color a ARGB.
Los archivos BMP pueden tener varios métodos de codificación (si los crea o edita en cualquier editor, compruebe este tema en la documentación de este programa). Los recursos MQL5 no admiten todos los métodos de codificación existentes. Puede comprobar si un archivo concreto es compatible utilizando la función ResourceCreate. Si se especifica en la directiva un archivo de formato BMP no compatible, se producirá un error de compilación.
Al cargar un archivo con codificación de color de 24 bits, todos los píxeles del componente del canal alfa se establecen en 255 (opaco). Cuando se carga un archivo con una codificación de color de 32 bits sin canal alfa, tampoco implica transparencia, es decir, para todos los píxeles de la imagen, el componente del canal alfa se establece en 255. Cuando se carga un archivo codificado en color de 32 bits con un canal alfa, no se manipula ningún píxel.
Las imágenes pueden describirse mediante arrays unidimensionales y bidimensionales. Esto solo afecta al método de direccionamiento, mientras que la cantidad de memoria ocupada será la misma. En ambos casos, los tamaños de los arrays se establecen automáticamente en función de los datos del archivo BMP. El tamaño de un array unidimensional será igual al producto de la altura y la anchura de la imagen (height * width), y un array bidimensional obtendrá dimensiones separadas [height][width]: el primer índice es el número de línea; el segundo, un punto de la línea.
¡Atención! Al declarar un recurso vinculado a una variable de recurso, la única forma de acceder al recurso es a través de esa variable, y la forma estándar de leer a través del nombre «::nombre_del_recurso» (o más generalmente «nombre_del_archivo_de_la_ruta.ex5::nombre_del_recurso») ya no funciona. Esto también significa que dichos recursos no pueden utilizarse como recursos compartidos de otros programas.
Vamos a considerar dos indicadores como ejemplo; ambos carecen de búfer. Este tipo de programa MQL fue elegido solo por razones de conveniencia, ya que se puede aplicar al gráfico sin conflicto además de otros indicadores, mientras que un Asesor Experto requeriría un gráfico sin otro Asesor Experto. Además, permanecen en el gráfico y están disponibles para posteriores cambios de configuración, a diferencia de los scripts.
El indicador BmpOwner.mq5 contiene una descripción de tres recursos:
- Una imagen «search1.bmp» con una simple directiva #resource accesible desde otros programas.
- Una imagen «search2.bmp» como variable de array de recursos de tipo bitmap, inaccesible desde el exterior
- Un archivo de texto «message.txt» como cadena de recursos para mostrar una advertencia al usuario.
Ambas imágenes no se utilizan en modo alguno en este indicador. La línea de advertencia es necesaria en la función OnInit para llamar a Alert, ya que el indicador no está pensado para un uso independiente, sino que solo actúa como proveedor de un recurso de imagen.
Si la variable de recurso no se utiliza en el código fuente, es posible que el compilador no incluya el recurso en absoluto en el código binario del programa, pero esto no se aplica a las imágenes.
#resource "search1.bmp"
|
Los tres archivos se encuentran en el mismo directorio en el que se encuentra el código fuente del indicador: MQL5/Indicators/MQL5Book/p7/.
Si el usuario intenta ejecutar el indicador, éste muestra una advertencia e inmediatamente deja de funcionar. La advertencia está contenida en la variable de cadena del recurso Mensaje.
int OnInit()
|
En el segundo indicador BmpUser.mq5, intentaremos utilizar los recursos externos especificados en las variables de entrada ResourceOff y ResourceOn, para mostrarlos en el objeto OBJ_BITMAP_LABEL.
input string ResourceOff = "BmpOwner.ex5::search1.bmp";
|
De manera predeterminada, el estado del objeto es desactivado/liberado («Off»), y la imagen para él se toma del indicador anterior «BmpOwner.ex5::search1.bmp». Esta ruta y el nombre del recurso son similares a la notación completa «\\Indicators\MQL5Book\p7\BmpOwner.ex5::search1.bmp». La forma abreviada es aceptable en este caso, dado que los indicadores están situados uno al lado del otro. Si posteriormente abre el cuadro de diálogo de propiedades del objeto, verá la notación completa en los campos Bitmap file (On/Off).
Para el estado pulsado, en ResourceOn debemos leer el recurso «BmpOwner.ex5::search2.bmp» (veamos qué ocurre).
En otras variables de entrada, puede seleccionar la esquina del gráfico, respecto a la cual se establece el posicionamiento de la imagen, y las sangrías horizontal y vertical.
input int X = 25;
|
La creación del objeto OBJ_BITMAP_LABEL y la configuración de sus propiedades, incluido el nombre del recurso como imagen para OBJPROP_BMPFILE, se realizan en OnInit.
const string Prefix = "BMP_";
|
Recuerde que al especificar imágenes en OBJPROP_BMPFILE, el estado pulsado se indica mediante el modificador 0, y el estado liberado (no pulsado) (predeterminado) se indica mediante el modificador 1, lo cual es hasta cierto punto inesperado.
El manejador OnDeinit borra el objeto al descargar el indicador.
void OnDeinit(const int)
|
Vamos a compilar ambos indicadores y ejecutar BmpUser.ex5 con la configuración por defecto. La imagen del archivo gráfico search1.bmp debería aparecer en el gráfico (véase a la izquierda).
Visualización normal (izquierda) e incorrecta (derecha) de los recursos gráficos de un objeto en un gráfico
Si hace clic en la imagen, es decir, la cambia al estado pulsado, el programa intentará acceder al recurso «BmpOwner.ex5::search2.bmp» (que no está disponible debido al array de recursos bitmap adjunto). Como resultado, veremos un cuadrado rojo, que indica un objeto vacío sin imagen (véase arriba, a la derecha). Siempre se producirá una situación similar si el parámetro de entrada especifica una ruta o un nombre con un recurso a sabiendas inexistente o no compartido. Puede crear su propio programa, describir en él un recurso que haga referencia a algún archivo bmp existente y, a continuación, especificar en el indicador los parámetros de entrada BmpUser. En este caso, el indicador podrá mostrar la imagen en el gráfico.