
Creación de un Panel de administración de operaciones en MQL5 (Parte III): Mejora de la interfaz gráfica de usuario con estilización visual (I)
Contenido:
- Introducción
- Importancia de una interfaz gráfica de usuario visualmente atractiva
- Aplicación de las funciones de estilo de la GUI MQL5
- Personalización de colores y fuentes
- Lógica de gestión de temas
- Ajustar el diseño de los nuevos botones
- Mejora avanzada de la interfaz gráfica de usuario
- Conclusión
Introducción
Si examinamos los objetivos esbozados en nuestro artículo anterior, ¿podemos decir con seguridad que hemos hecho lo suficiente? En mi opinión, lo que veo inspira un impulso para avanzar más allá de nuestras ofertas actuales. Imagina lo beneficioso que sería implementar una alternancia entre temas oscuros y claros para nuestro Panel de Administración. Además, podríamos mejorar la experiencia del usuario añadiendo botones elegantes, ofreciendo una selección variada de fuentes y permitiendo el cambio de idioma entre las principales lenguas. Esto haría que nuestro panel fuera más fácil de usar para todos.
Nuestro objetivo es ofrecer a los administradores de operaciones una solución de comunicación completa integrada en la plataforma de operaciones. Los conceptos que pretendemos incorporar se inspiran en influyentes investigaciones y desarrollos de interfaces gráficas de usuario (GUI) desde los años setenta. Entre los colaboradores más destacados se encuentran Alan Kay, Xerox PARC, Apple (macOS), Microsoft (Windows), CSS (Cascading Style Sheets), y Material Design de Google. Aprovechando esta información, podemos crear un panel de administración que satisfaga las necesidades de los usuarios y mejore su experiencia general.
El panel de administración básico que hemos desarrollado hasta ahora.
Resumen de lo que hemos conseguido hasta ahora:
- Creación de un Panel de administración de operaciones en MQL5 (Parte I): Creación de una interfaz de mensajería.
- Agregar botones esenciales a la interfaz, como minimizar, maximizar, cerrar y botones de mensajes rápidos.
Al final de este artículo, tendremos un panel de administrador de operaciones totalmente personalizado y con estilo visual en MQL5. Aprenderá a implementar diversas técnicas de estilo que mejoran tanto la apariencia como la funcionalidad de la interfaz, creando un entorno profesional y fácil de usar para los comerciantes.
Estos son los principales objetivos de este artículo:- Aplicación de técnicas básicas de estilo utilizando MQL5.
- Personalización de fuentes, colores y diseños.
- Mejorar la interacción del usuario con elementos visuales.
- Incorporando personalización entre el modo de tema claro y oscuro.
- Agregar funciones dinámicas como animaciones y transiciones.
Aplicación de las funciones de estilo de la GUI MQL5
MQL5 proporciona varias funciones y características para diseñar la GUI de su aplicación comercial. Estos incluyen opciones para personalizar colores, fuentes y diseños para adaptarse a las necesidades de sus usuarios y la estética general del diseño que desea lograr.
Dar estilo a la GUI en MQL5 implica el uso de varias funciones y técnicas clave. Analizaremos las funciones que permiten cambiar las propiedades de objetos gráficos, como botones, etiquetas y paneles. Con estos, podemos personalizar el color de fondo, el estilo del borde, el tamaño de la fuente y otros aspectos visuales para crear una apariencia cohesiva.
- Personalización de colores y fuentes
- Lógica de gestión de temas
- Ajustar el diseño de los nuevos botones
Personalización de colores y fuentes:
Matriz e índice de fuentes:
Comenzamos definiendo un array availableFonts y un currentFontIndex para gestionar las selecciones de fuentes para el Panel de Administración. La matriz availableFonts incluye nombres de fuentes como «Arial», «Courier New», «Verdana» y «Times New Roman», que ofrecen a los usuarios diversas opciones para personalizar el aspecto del panel. El currentFontIndex mantiene la pista de la fuente seleccionada indexando en este array. Esta configuración nos permite recorrer fácilmente los tipos de letra y aplicarlos a los componentes de la interfaz de usuario cada vez que el usuario cambia el tipo de letra, asegurándonos de que la experiencia del usuario sigue siendo dinámica y coherente.
// Array of available fonts string availableFonts[] = {"Arial", "Courier New", "Verdana", "Times New Roman"}; // Index of the current font in use int currentFontIndex = 0;
Creación del botón de cambio de fuente:
Vamos a crear un botón llamado «Font<>», que posicionaremos estratégicamente dentro del Panel de Administración. Este botón no es un botón cualquiera; es clave para cambiar de fuente. Nos aseguramos de que encaje bien en el diseño del panel y nos ocupamos de cualquier problema relacionado con su creación. Al añadir este botón, proporcionamos a los usuarios una forma intuitiva de pasar de un tipo de letra a otro, lo que mejora la facilidad de uso y la flexibilidad estética del panel. Si se produce algún contratiempo al crear el botón, imprimimos un mensaje de error para controlar cualquier problema.
// Create a button for changing the font CButton changeFontButton; changeFontButton.Create(panel, "ChangeFontButton", 0, 10, 10, 100, 30); changeFontButton.Text("Font<>"); // Verify button creation and handle errors if(!changeFontButton.IsCreated()) { Print("Error creating Font<> button."); }
Manejo del botón de cambio de fuente:
Cuando implementamos la función OnChangeFontButtonClick, nuestro objetivo es gestionar el proceso de cambio de fuente sin problemas. Esta función actualiza currentFontIndex para seleccionar la siguiente fuente en la matriz availableFonts, volviendo al principio si es necesario. Después de actualizar el índice, aplicamos la nueva fuente a todos los componentes de la interfaz de usuario relevantes, como el cuadro de entrada, el botón de borrar y el botón de enviar, lo que garantiza una apariencia uniforme en todo el panel. Para finalizar los cambios, utilizamos ChartRedraw para actualizar la pantalla e imprimir un mensaje de confirmación, haciendo saber a los usuarios que el cambio de fuente se ha realizado correctamente.
// Function to handle the font change button click void OnChangeFontButtonClick() { // Update the font index, wrapping around if necessary currentFontIndex = (currentFontIndex + 1) % ArraySize(availableFonts); string newFont = availableFonts[currentFontIndex]; // Apply the new font to UI components inputBox.Font(newFont); clearButton.Font(newFont); sendButton.Font(newFont); // Refresh the display to apply the changes ChartRedraw(); // Print confirmation of the font change Print("Font changed to ", newFont); }
OnChartEvent para manejar los clics de los botones:
En la función OnChartEvent, manejamos las interacciones del usuario con varios objetos del gráfico, incluyendo nuestro botón de cambio de fuente. Esta función escucha eventos de clic de botón y comprueba qué botón se ha pulsado inspeccionando la cadena sparam. Cuando se pulsa el botón «ChangeFontButton», llamamos a la función OnChangeFontButtonClick para gestionar el cambio de fuente. Este enfoque basado en eventos mantiene nuestra interfaz de usuario receptiva e interactiva, garantizando que las acciones del usuario desencadenen las respuestas adecuadas y mantengan una interfaz atractiva.
// Function to handle chart events void OnChartEvent(const int id, const int sub_id, const int type, const int x, const int y, const int state) { // Handle button clicks if(type == CHARTEVENT_OBJECT_CLICK) { string buttonName = ObjectGetString(0, "ChangeFontButton", OBJPROP_TEXT); if(buttonName == "Font<>") { OnChangeFontButtonClick(); } } }
Funcionamiento del cambio de fuentes.
Lógica de gestión de temas:
Lógica de cambio de tema:
Comenzamos configurando el sistema de gestión de temas con dos temas distintos: claro y oscuro. Para gestionar el cambio, utilizamos una variable booleana, isDarkMode, que realiza un seguimiento de qué tema está activo actualmente. La conmutación es sencilla: cuando el usuario hace clic en el botón del tema, el valor isDarkMode cambia, modificando por completo el aspecto del Panel de administración. Al definir los colores de cada tema por separado, agilizamos el proceso, facilitando el mantenimiento y la aplicación de nuevos estilos siempre que sea necesario.
bool isDarkMode = false; // Tracks the current theme mode (light or dark) color lightBackgroundColor = clrWhite; // Background color for light mode color darkBackgroundColor = clrBlack; // Background color for dark mode color lightTextColor = clrBlack; // Text color for light mode color darkTextColor = clrWhite; // Text color for dark mode
Crear el botón de cambio de tema:
Pasemos a crear un botón llamado "Theme<>". Este botón se coloca dentro del Panel de administración, y proporciona a los usuarios una forma sencilla de cambiar entre los modos claro y oscuro. Si algo sale mal durante su creación, nos aseguramos de gestionar el error con un mensaje impreso. Esto facilita la resolución de problemas y garantiza que la interfaz siga siendo intuitiva y receptiva.
//Creating the theme switch button if(!CreateButton("ToggleThemeButton", "Theme<>", 50, 220, 100, 30)) { Print("Error: Failed to create theme toggle button"); // Error handling if button creation fails }
Manejar el botón de cambio de tema:
A continuación, manejamos el cambio de tema real implementando la función OnToggleModeButtonClick. Esta función invierte la variable isDarkMode, cambiando entre los temas claro y oscuro. Una vez que sabemos qué tema está activo, aplicamos los colores de fondo y texto correspondientes a todos los elementos de la interfaz de usuario, como el panel, los botones y el texto. El cambio de tema se produce en tiempo real gracias a una actualización rápida, lo que hace que la interfaz sea fluida y sensible. También imprimimos un mensaje de confirmación para que los usuarios sepan cuándo ha cambiado el modo.//Theme switching handler void OnToggleModeButtonClick() { isDarkMode = !isDarkMode; // Toggle the theme mode if(isDarkMode) { ApplyTheme(darkBackgroundColor, darkTextColor); // Apply dark mode colors } else { ApplyTheme(lightBackgroundColor, lightTextColor); // Apply light mode colors } Print("Theme has been switched"); // Inform the user that the theme has changed }
OnChartEvent para gestionar los clics del botón de alternancia de tema:
En la función OnChartEvent, detectamos cuando un usuario hace clic en el botón «Toggle Theme» y activamos la función OnToggleModeButtonClick. Este enfoque basado en eventos garantiza que el panel responda instantáneamente a las acciones del usuario. Al escuchar los eventos de clic de los botones, nos aseguramos de que el panel de administración siga siendo interactivo y atractivo, permitiendo a los usuarios cambiar fácilmente entre temas claros y oscuros según sea necesario.
//The OneChartEvent for the theme void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id == CHARTEVENT_OBJECT_CLICK) // Check if the event is a button click { if(sparam == "ToggleThemeButton") // Check if the clicked button is the theme toggle button { OnToggleModeButtonClick(); // Call the function to handle the theme change } } }
Aplicar tema sin recrear objetos:
Una de nuestras principales decisiones de diseño es actualizar el tema sin recrear ninguno de los objetos del panel. En lugar de derribar y construir nuevos componentes de UI, simplemente aplicamos el nuevo esquema de colores a los elementos existentes. Esto mantiene el sistema eficiente, reduciendo el retraso y manteniendo una experiencia de usuario fluida. También garantiza que el panel siga respondiendo a medida que aplicamos los nuevos colores dinámicamente.
//Applying theme void ApplyTheme(color backgroundColor, color textColor) { // Update background and text colors of existing objects ObjectSetInteger(0, "AdminPanelBackground", OBJPROP_COLOR, backgroundColor); // Change background color ObjectSetInteger(0, "ClearButton", OBJPROP_COLOR, textColor); // Change text color of clear button ObjectSetInteger(0, "SendButton", OBJPROP_COLOR, textColor); // Change text color of send button ObjectSetInteger(0, "InputBox", OBJPROP_COLOR, textColor); // Change text color of input box ChartRedraw(); // Redraw the chart to reflect the changes }
Ajuste del nuevo diseño de los botones.
Botón de cambio de fuente:
El botón sobre cambiar de fuente lo posicionamos en el panel de administración con su esquina superior izquierda en (95, 95) y su esquina inferior derecha en (230, 115). Esto lo sitúa a la izquierda de los botones Enviar (Send) y Borrar (Clear). Sus dimensiones lo hacen lo suficientemente ancho para la etiqueta «Font<>» y la interacción con el usuario. El botón permite a los usuarios recorrer diferentes opciones de fuente para todos los elementos de texto dentro del panel.if (!changeFontButton.Create(chart_id, "ChangeFontButton", 0, 95, 95, 230, 115))
Botón de cambio de tema:
En cuanto al botón de cambio de tema, lo colocamos en las coordenadas (5, 95) para la parte superior izquierda y (90, 115) para la parte inferior derecha. Esto coloca el botón en el extremo izquierdo del panel, ligeramente por encima del botón de cambio de fuente, proporcionando una clara separación. El tamaño compacto y la proximidad a otros botones facilitan a los usuarios el cambio entre temas oscuros y claros sin saturar la interfaz.if (!toggleThemeButton.Create(chart_id, "ToggleThemeButton", 0, 5, 95, 90, 115))
Aquí está nuestro programa completo con todas las nuevas funciones perfectamente integradas.
//+------------------------------------------------------------------+ //| Admin Panel.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com/en/users/billionaire2024/seller | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Clemence Benjamin" #property link "https://www.mql5.com/en/users/billionaire2024/seller" #property description "A responsive Admin Panel. Send messages to your telegram clients without leaving MT5" #property version "1.11" #include <Trade\Trade.mqh> #include <Controls\Dialog.mqh> #include <Controls\Button.mqh> #include <Controls\Edit.mqh> #include <Controls\Label.mqh> // Input parameters input string QuickMessage1 = "Updates"; input string QuickMessage2 = "Close all"; input string QuickMessage3 = "In deep profits"; input string QuickMessage4 = "Hold position"; input string QuickMessage5 = "Swing Entry"; input string QuickMessage6 = "Scalp Entry"; input string QuickMessage7 = "Book profit"; input string QuickMessage8 = "Invalid Signal"; input string InputChatId = "Enter Chat ID from Telegram bot API"; input string InputBotToken = "Enter BOT TOKEN from your Telegram bot"; // Global variables CDialog adminPanel; CButton sendButton, clearButton, changeFontButton, toggleThemeButton; CButton quickMessageButtons[8], minimizeButton, maximizeButton, closeButton; CEdit inputBox; CLabel charCounter; #define BG_RECT_NAME "BackgroundRect" bool minimized = false; bool darkTheme = false; int MAX_MESSAGE_LENGTH = 4096; string availableFonts[] = { "Arial", "Courier New", "Verdana", "Times New Roman" }; int currentFontIndex = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Initialize the Dialog if (!adminPanel.Create(ChartID(), "Admin Panel", 0, 30, 30, 500, 500)) { Print("Failed to create dialog"); return INIT_FAILED; } // Create controls if (!CreateControls()) { Print("Control creation failed"); return INIT_FAILED; } adminPanel.Show(); // Initialize with the default theme CreateOrUpdateBackground(ChartID(), darkTheme ? clrBlack : clrWhite); Print("Initialization complete"); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Create necessary UI controls | //+------------------------------------------------------------------+ bool CreateControls() { long chart_id = ChartID(); // Create the input box if (!inputBox.Create(chart_id, "InputBox", 0, 5, 25, 460, 95)) { Print("Failed to create input box"); return false; } adminPanel.Add(inputBox); // Character counter if (!charCounter.Create(chart_id, "CharCounter", 0, 380, 5, 460, 25)) { Print("Failed to create character counter"); return false; } charCounter.Text("0/" + IntegerToString(MAX_MESSAGE_LENGTH)); adminPanel.Add(charCounter); // Clear button if (!clearButton.Create(chart_id, "ClearButton", 0, 235, 95, 345, 125)) { Print("Failed to create clear button"); return false; } clearButton.Text("Clear"); adminPanel.Add(clearButton); // Send button if (!sendButton.Create(chart_id, "SendButton", 0, 350, 95, 460, 125)) { Print("Failed to create send button"); return false; } sendButton.Text("Send"); adminPanel.Add(sendButton); // Change font button if (!changeFontButton.Create(chart_id, "ChangeFontButton", 0, 95, 95, 230, 115)) { Print("Failed to create change font button"); return false; } changeFontButton.Text("Font<>"); adminPanel.Add(changeFontButton); // Toggle theme button if (!toggleThemeButton.Create(chart_id, "ToggleThemeButton", 0, 5, 95, 90, 115)) { Print("Failed to create toggle theme button"); return false; } toggleThemeButton.Text("Theme<>"); adminPanel.Add(toggleThemeButton); // Minimize button if (!minimizeButton.Create(chart_id, "MinimizeButton", 0, 375, -22, 405, 0)) { Print("Failed to create minimize button"); return false; } minimizeButton.Text("_"); adminPanel.Add(minimizeButton); // Maximize button if (!maximizeButton.Create(chart_id, "MaximizeButton", 0, 405, -22, 435, 0)) { Print("Failed to create maximize button"); return false; } maximizeButton.Text("[ ]"); adminPanel.Add(maximizeButton); // Close button if (!closeButton.Create(chart_id, "CloseButton", 0, 435, -22, 465, 0)) { Print("Failed to create close button"); return false; } closeButton.Text("X"); adminPanel.Add(closeButton); // Quick messages return CreateQuickMessageButtons(); } //+------------------------------------------------------------------+ //| Create quick message buttons | //+------------------------------------------------------------------+ bool CreateQuickMessageButtons() { string quickMessages[8] = { QuickMessage1, QuickMessage2, QuickMessage3, QuickMessage4, QuickMessage5, QuickMessage6, QuickMessage7, QuickMessage8 }; int startX = 5, startY = 160, width = 222, height = 65, spacing = 5; for (int i = 0; i < 8; i++) { if (!quickMessageButtons[i].Create(ChartID(), "QuickMessageButton" + IntegerToString(i + 1), 0, startX + (i % 2) * (width + spacing), startY + (i / 2) * (height + spacing), startX + (i % 2) * (width + spacing) + width, startY + (i / 2) * (height + spacing) + height)) { Print("Failed to create quick message button ", i + 1); return false; } quickMessageButtons[i].Text(quickMessages[i]); adminPanel.Add(quickMessageButtons[i]); } return true; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { adminPanel.Destroy(); ObjectDelete(ChartID(), BG_RECT_NAME); Print("Deinitialization complete"); } //+------------------------------------------------------------------+ //| Handle chart events | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { switch (id) { case CHARTEVENT_OBJECT_CLICK: if (sparam == "SendButton") OnSendButtonClick(); else if (sparam == "ClearButton") OnClearButtonClick(); else if (sparam == "ChangeFontButton") OnChangeFontButtonClick(); else if (sparam == "ToggleThemeButton") OnToggleThemeButtonClick(); else if (sparam == "MinimizeButton") OnMinimizeButtonClick(); else if (sparam == "MaximizeButton") OnMaximizeButtonClick(); else if (sparam == "CloseButton") OnCloseButtonClick(); else if (StringFind(sparam, "QuickMessageButton") != -1) { int index = StringToInteger(StringSubstr(sparam, 18)); OnQuickMessageButtonClick(index - 1); } break; case CHARTEVENT_OBJECT_ENDEDIT: if (sparam == "InputBox") OnInputChange(); break; } } //+------------------------------------------------------------------+ //| Handle custom message send button click | //+------------------------------------------------------------------+ void OnSendButtonClick() { string message = inputBox.Text(); if (message != "") { if (SendMessageToTelegram(message)) Print("Custom message sent: ", message); else Print("Failed to send custom message."); } else { Print("No message entered."); } } //+------------------------------------------------------------------+ //| Handle clear button click | //+------------------------------------------------------------------+ void OnClearButtonClick() { inputBox.Text(""); // Clear the text in the input box OnInputChange(); // Update the character counter Print("Input box cleared."); } //+------------------------------------------------------------------+ //| Handle quick message button click | //+------------------------------------------------------------------+ void OnQuickMessageButtonClick(int index) { string quickMessages[8] = { QuickMessage1, QuickMessage2, QuickMessage3, QuickMessage4, QuickMessage5, QuickMessage6, QuickMessage7, QuickMessage8 }; string message = quickMessages[index]; if (SendMessageToTelegram(message)) Print("Quick message sent: ", message); else Print("Failed to send quick message."); } //+------------------------------------------------------------------+ //| Update character counter | //+------------------------------------------------------------------+ void OnInputChange() { int currentLength = StringLen(inputBox.Text()); charCounter.Text(IntegerToString(currentLength) + "/" + IntegerToString(MAX_MESSAGE_LENGTH)); ChartRedraw(); } //+------------------------------------------------------------------+ //| Handle toggle theme button click | //+------------------------------------------------------------------+ void OnToggleThemeButtonClick() { darkTheme = !darkTheme; color bgColor = darkTheme ? clrBlack : clrWhite; color textColor = darkTheme ? clrWhite : clrBlack; // Set text color appropriate to the theme inputBox.Color(textColor); clearButton.Color(textColor); sendButton.Color(textColor); toggleThemeButton.Color(textColor); changeFontButton.Color(textColor); for(int i = 0; i < ArraySize(quickMessageButtons); i++) { quickMessageButtons[i].Color(textColor); } charCounter.Color(textColor); CreateOrUpdateBackground(ChartID(), bgColor); ChartRedraw(); } //+------------------------------------------------------------------+ //| Create and update background rectangle | //+------------------------------------------------------------------+ void CreateOrUpdateBackground(long chart_id, color bgColor) { if (!ObjectFind(chart_id, BG_RECT_NAME)) { if (!ObjectCreate(chart_id, BG_RECT_NAME, OBJ_RECTANGLE, 0, 0, 0)) Print("Failed to create background rectangle"); } ObjectSetInteger(chart_id, BG_RECT_NAME, OBJPROP_COLOR, bgColor); ObjectSetInteger(chart_id, BG_RECT_NAME, OBJPROP_BACK, true); ObjectSetInteger(chart_id, BG_RECT_NAME, OBJPROP_SELECTABLE, false); ObjectSetInteger(chart_id, BG_RECT_NAME, OBJPROP_SELECTED, false); ObjectSetInteger(chart_id, BG_RECT_NAME, OBJPROP_HIDDEN, false); ObjectSetInteger(chart_id, BG_RECT_NAME, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(chart_id, BG_RECT_NAME, OBJPROP_XOFFSET, 25); ObjectSetInteger(chart_id, BG_RECT_NAME, OBJPROP_YOFFSET, 25); } //+------------------------------------------------------------------+ //| Handle change font button click | //+------------------------------------------------------------------+ void OnChangeFontButtonClick() { currentFontIndex = (currentFontIndex + 1) % ArraySize(availableFonts); inputBox.Font(availableFonts[currentFontIndex]); clearButton.Font(availableFonts[currentFontIndex]); sendButton.Font(availableFonts[currentFontIndex]); toggleThemeButton.Font(availableFonts[currentFontIndex]); changeFontButton.Font(availableFonts[currentFontIndex]); for(int i = 0; i < ArraySize(quickMessageButtons); i++) { quickMessageButtons[i].Font(availableFonts[currentFontIndex]); } Print("Font changed to: ", availableFonts[currentFontIndex]); ChartRedraw(); } //+------------------------------------------------------------------+ //| Handle minimize button click | //+------------------------------------------------------------------+ void OnMinimizeButtonClick() { minimized = true; adminPanel.Hide(); minimizeButton.Hide(); maximizeButton.Show(); closeButton.Show(); Print("Panel minimized."); } //+------------------------------------------------------------------+ //| Handle maximize button click | //+------------------------------------------------------------------+ void OnMaximizeButtonClick() { if (minimized) { adminPanel.Show(); minimizeButton.Show(); maximizeButton.Hide(); closeButton.Hide(); Print("Panel maximized."); } } //+------------------------------------------------------------------+ //| Handle close button click | //+------------------------------------------------------------------+ void OnCloseButtonClick() { ExpertRemove(); // Completely remove the EA Print("Admin Panel closed."); } //+------------------------------------------------------------------+ //| Send the message to Telegram | //+------------------------------------------------------------------+ bool SendMessageToTelegram(string message) { string url = "https://api.telegram.org/bot" + InputBotToken + "/sendMessage"; string jsonMessage = "{\"chat_id\":\"" + InputChatId + "\", \"text\":\"" + message + "\"}"; char post_data[]; ArrayResize(post_data, StringToCharArray(jsonMessage, post_data, 0, WHOLE_ARRAY) - 1); int timeout = 5000; char result[]; string responseHeaders; int res = WebRequest("POST", url, "Content-Type: application/json\r\n", timeout, post_data, result, responseHeaders); if (res == 200) // HTTP 200 OK { Print("Message sent successfully: ", message); return true; } else { Print("Failed to send message. HTTP code: ", res, " Error code: ", GetLastError()); Print("Response: ", CharArrayToString(result)); return false; } }
Nuevas funciones probadas en XAUUSD.
Una vez aplicadas estas técnicas básicas de estilización, podemos explorar opciones de personalización más avanzadas que aporten mayor interactividad y atractivo visual a la interfaz gráfica de usuario. De la imagen anterior, podemos ver que nuestro tema sólo está trabajando en el texto en primer plano, sin embargo, queremos que también afectan el fondo del panel. En el próximo segmento, abordaremos las formas de resolver este problema.
Mejora avanzada de la interfaz gráfica de usuario
Ampliación de la clase de diálogo para la gestión de temas:
Para ampliar Dialog para la gestión de temas, podemos personalizar la clase de diálogo existente para que admita cambios dinámicos de tema, de forma similar a como gestionamos los temas en el Panel de administración. Esto implicaría modificar o subclasificar la clase CDialog para incluir propiedades para los colores de fondo y texto, así como métodos para aplicar diferentes temas (claro u oscuro). Anulando el constructor o añadiendo métodos como "ApplyTheme", podemos asegurarnos de que los cuadros de diálogo creados con esta clase respondan a los cambios de tema sin tener que volver a crear los objetos de diálogo.
Personalización de los colores en la clase Dialog.
¿Por qué es importante?
La ampliación de la clase Dialog para la gestión de temas permite una experiencia de usuario más fluida y cohesiva en todos los elementos de la interfaz de usuario, no solo en el Panel de administración. Asegura que todas las partes de la aplicación, incluidos los cuadros de diálogo, se adhieran al tema elegido, mejorando tanto la usabilidad como la consistencia visual. Esta característica se vuelve particularmente importante en aplicaciones comerciales donde los usuarios pueden pasar períodos prolongados interactuando con la interfaz, y los temas personalizables pueden reducir la fatiga visual y mejorar la satisfacción general del usuario.
Panel de administración: Tema de fondo después de modificar la clase Dialog.
Otras opciones:
Si bien ampliar la clase Dialog es un enfoque directo y flexible, otra opción es aplicar la gestión de temas a un nivel superior. Por ejemplo, podríamos crear un sistema de gestión de temas global que actualice automáticamente las propiedades de todos los elementos de la interfaz de usuario, incluidos los cuadros de diálogo, sin necesidad de realizar cambios en los componentes individuales. Además, aprovechar bibliotecas externas o diseñar un marco de diálogo personalizado podría ofrecer un control más granular sobre los elementos de la interfaz de usuario si surgen necesidades de estilo específicas.
Clase CEdit
Según la búsqueda en Google, la longitud máxima de un mensaje de Telegram es de 4096 caracteres y debe estar codificado en UTF-8. Al intentar implementar el valor en este proyecto, nos vimos limitados a un máximo de 63 caracteres y el problema debe estar dentro de la limitación de la clase CEdit que abordaremos en el próximo artículo.
Conclusión
En conclusión, nuestra implementación de la gestión de fuentes y temas en el programa Admin Panel ha demostrado resultados prometedores. Aunque el fondo estático de la clase de diálogo nos planteaba limitaciones, el primer plano de texto se adaptaba con éxito a los cambios de tema, lo que mejoraba la experiencia del usuario. La gestión dinámica de fuentes también funcionó bien, permitiendo a los usuarios cambiar entre diferentes fuentes con facilidad.De ahora en adelante, nuestro próximo objetivo será ampliar la clase de diálogo para que admita totalmente los cambios de tema, incluidas las actualizaciones dinámicas de fondo. Esta mejora tiene como objetivo superar las limitaciones actuales y proporcionar una interfaz más cohesiva y visualmente atractiva. ¡Permanezca atento mientras abordamos estos desafíos en nuestros próximos artículos!
Pruebe estas técnicas de estilo en sus propios paneles comerciales y explore opciones de personalización adicionales en MQL5. Me encantaría conocer sus experiencias y conocimientos, así que no dude en compartirlos en los comentarios a continuación mientras profundizamos en desafíos de diseño de GUI más avanzados. Se adjunta el archivo fuente de este proyecto: no dudes en revisarlo.
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/15419
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
línea de código:
pregunta: ¿mover la ventana en el gráfico no está implementado?