0% found this document useful (0 votes)
231 views24 pages

MQL5 GUI and Data Visualization Guide

The document provides a comprehensive guide on advanced GUI and data visualization techniques in MQL5, highlighting the transition from MQL4's synchronous graphics architecture to MQL5's asynchronous, event-driven model. It emphasizes the use of an asynchronous command queue for graphical updates and promotes best practices through the MQL5 Standard Library for object-oriented programming. Additionally, it covers the implementation of interactive elements using the OnChartEvent() function, detailing how to create a dynamic trading panel with drag-and-drop functionality.

Uploaded by

arcmods9
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
231 views24 pages

MQL5 GUI and Data Visualization Guide

The document provides a comprehensive guide on advanced GUI and data visualization techniques in MQL5, highlighting the transition from MQL4's synchronous graphics architecture to MQL5's asynchronous, event-driven model. It emphasizes the use of an asynchronous command queue for graphical updates and promotes best practices through the MQL5 Standard Library for object-oriented programming. Additionally, it covers the implementation of interactive elements using the OnChartEvent() function, detailing how to create a dynamic trading panel with drag-and-drop functionality.

Uploaded by

arcmods9
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 24

A Developer's Guide to Advanced GUI

and Data Visualization in MQL5

1. The MQL5 Graphics Architecture

The graphics architecture in MQL5 is a fundamental departure from the model used in its
predecessor, MQL4. MQL4's design was procedural, direct, and synchronous; a function call
to modify a graphical object would often pause the program's execution until the operation
was complete.1 This approach was a direct reflection of the platform's overall single-threaded
architecture, which could lead to the entire program freezing during time-consuming
calculations or graphical updates.1

In contrast, the MQL5 graphics architecture is a direct consequence of the platform's overall
shift to a non-blocking, event-driven model designed to overcome MQL4's single-threaded
limitations.1 MQL5's core philosophy is centered on asynchronicity to ensure a responsive user
interface and to leverage multi-core processors. If graphical operations remained
synchronous, they would undermine this core objective by blocking the main execution
thread. Consequently, the graphics system was engineered as an object-oriented,
asynchronous system where commands are queued and processed separately from the main
program logic, ensuring that even complex GUI updates do not introduce lag or freeze the
application.1

1.1. The Asynchronous Command Queue and Procedural Functions

At the procedural level, MQL5 provides a set of core functions for direct manipulation of
graphical objects on a chart. The primary functions are:
●​ ObjectCreate(): Creates a new graphical object of a specified type.
●​ ObjectDelete(): Removes a specified graphical object from the chart.
●​ ObjectSetInteger(): Sets an integer-type property of an object (e.g., color, width,
Z-order).
●​ ObjectSetDouble(): Sets a double-type property of an object (e.g., price level).
●​ ObjectSetString(): Sets a string-type property of an object (e.g., text, font name). 2

A critical concept for developers to understand is that these functions do not modify the
chart visually in real-time.2 Instead, when called, they send a command to an asynchronous
chart event queue.2 The client terminal processes this queue independently, applying the
visual updates in response to other events, such as the arrival of a new tick or the resizing of
the chart window.2 This decoupling prevents the Expert Advisor from being blocked while
waiting for the chart to be rendered.

To ensure that visual changes are applied immediately when required, the ChartRedraw()
function is essential. Calling ChartRedraw() forces the client terminal to process its event
queue and redraw the specified chart, making all pending graphical changes visible without
delay. It is standard practice to call this function after a block of object modifications to
ensure the user interface reflects the program's current state.2

1.2. Best Practice: The Standard Library for Graphical Objects

While the procedural functions provide direct control, the modern and recommended
best-practice approach is to use the object-oriented classes provided in the MQL5 Standard
Library.1 Located in the Include\ChartObjects directory, this library contains a comprehensive
set of classes that encapsulate the properties and methods for various graphical objects.8

Examples include:
●​ CChartObjectButton: For creating and managing button controls.9
●​ CChartObjectRectangle: For shape objects.11
●​ CChartObjectLabel: For text labels anchored by pixel coordinates.12
●​ CChartObjectTrend: For trend lines.12

These classes abstract the underlying procedural calls into a more intuitive, object-oriented
interface. They handle the details of setting properties and managing object state, leading to
cleaner, more maintainable, and less error-prone code. This aligns with the overall design
philosophy of MQL5, which encourages the use of Object-Oriented Programming (OOP) to
build complex, scalable trading systems.1

2. Mastering OnChartEvent() for Interactivity


MQL5's event-driven programming model is the foundation for creating interactive graphical
user interfaces. The central component of this model is the OnChartEvent() event handler.
This function acts as a dispatcher, receiving notifications about a wide range of user activities
on the chart, such as mouse clicks, object dragging, and key presses. Properly implementing
this handler is essential for building responsive and dynamic GUIs.1

2.1. Enabling Chart Events

For performance optimization, the MetaTrader 5 terminal disables certain high-frequency


events by default. Specifically, CHARTEVENT_MOUSE_MOVE, which can fire hundreds of times
per second as the user moves the cursor, must be explicitly enabled for the chart on which
the MQL5 program is running.15

This is accomplished by using the ChartSetInteger() function, typically within the OnInit()
function, to set the CHART_EVENT_MOUSE_MOVE property to true.

Code snippet

//+------------------------------------------------------------------+​
//| EnableMouseEvents_EA.mq5 |​
//| Copyright 2023, MetaQuotes Software Corp. |​
//| https://www.mql5.com |​
//+------------------------------------------------------------------+​
#property copyright "Copyright 2023, MetaQuotes Software Corp."​
#property link "https://www.mql5.com"​
#property version "1.00"​

//+------------------------------------------------------------------+​
//| Expert initialization function |​
//+------------------------------------------------------------------+​
int OnInit()​
{​
//--- Enable mouse move events for the current chart​
ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);​
Print("Mouse move events have been enabled.");​

//---​
return(INIT_SUCCEEDED);​
}​
//+------------------------------------------------------------------+​
//| Expert deinitialization function |​
//+------------------------------------------------------------------+​
void OnDeinit(const int reason)​
{​
//--- Disable mouse move events on exit​
ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, false);​
Print("Mouse move events have been disabled.");​
}​
//+------------------------------------------------------------------+​
//| ChartEvent function |​
//+------------------------------------------------------------------+​
void OnChartEvent(const int id,​
const long &lparam,​
const double &dparam,​
const string &sparam)​
{​
//--- If a mouse move event is received, print the coordinates​
if(id == CHARTEVENT_MOUSE_MOVE)​
{​
PrintFormat("Mouse Move Event: X=%d, Y=%d", lparam, dparam);​
}​
}​
//+------------------------------------------------------------------+​

2.2. OnChartEvent Parameter Reference

The OnChartEvent() function receives four parameters: id, lparam, dparam, and sparam. The
id parameter contains the event type, while the other three parameters contain event-specific
data. Understanding how to interpret these parameters is crucial for handling GUI interactions
correctly.

Event ID lparam dparam sparam Primary Use


Content Content Content Case
CHARTEVENT_ Mouse Mouse Empty Detecting a
CLICK X-coordinate Y-coordinate generic click
(pixels) (pixels) anywhere on
the chart
background.

CHARTEVENT_ Mouse Mouse Name of the Detecting a


OBJECT_CLICK X-coordinate Y-coordinate clicked object click on a
(pixels) (pixels) specific GUI
element like a
button or
panel.

CHARTEVENT_ Mouse Mouse Bitmask of Creating hover


MOUSE_MOVE X-coordinate Y-coordinate mouse button effects,
(pixels) (pixels) states custom
cursors, or
drag-and-drop
operations.

CHARTEVENT_ Not used (0) Not used (0.0) Name of the Notifying that
OBJECT_DRAG dragged a standard
object object drag
operation has
been
completed.

17

3. Practical Tutorial: Building an Interactive Trading


Panel

This tutorial demonstrates the end-to-end process of creating a functional, interactive GUI
panel, applying the architectural and event-handling concepts previously discussed.
3.1. Part 1: Layout and Creation in OnInit()

All graphical objects for the panel are created once in the OnInit() function. This is the most
efficient approach, as it avoids redundant object creation calls on every tick or chart event.23
The panel will consist of a main background rectangle, two buttons for buy and sell actions,
and two labels to display live prices.

Code snippet

//+------------------------------------------------------------------+​
//| TradingPanel_P1.mq5 |​
//| Copyright 2023, MetaQuotes Software Corp. |​
//| https://www.mql5.com |​
//+------------------------------------------------------------------+​
#property copyright "Copyright 2023, MetaQuotes Software Corp."​
#property link "https://www.mql5.com"​
#property version "1.00"​

//--- Panel object names​
#define PANEL_NAME "TradingPanel"​
#define BTN_BUY_NAME "BtnBuy"​
#define BTN_SELL_NAME "BtnSell"​
#define LBL_BID_NAME "LblBid"​
#define LBL_ASK_NAME "LblAsk"​

//+------------------------------------------------------------------+​
//| Expert initialization function |​
//+------------------------------------------------------------------+​
int OnInit()​
{​
//--- Create the main panel background (OBJ_RECTANGLE_LABEL)​
ObjectCreate(0, PANEL_NAME, OBJ_RECTANGLE_LABEL, 0, 0, 0);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_XDISTANCE, 20);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_YDISTANCE, 50);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_XSIZE, 150);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_YSIZE, 120);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_BGCOLOR, clrDarkSlateGray);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_BORDER_COLOR, clrGray);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_SELECTABLE, true);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_SELECTED, false);​

//--- Create the Buy button (OBJ_BUTTON)​
ObjectCreate(0, BTN_BUY_NAME, OBJ_BUTTON, 0, 0, 0);​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_XDISTANCE, 30);​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_YDISTANCE, 70);​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_XSIZE, 60);​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_YSIZE, 25);​
ObjectSetString(0, BTN_BUY_NAME, OBJPROP_TEXT, "BUY");​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_BGCOLOR, clrGreen);​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_COLOR, clrWhite);​

//--- Create the Sell button (OBJ_BUTTON)​
ObjectCreate(0, BTN_SELL_NAME, OBJ_BUTTON, 0, 0, 0);​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_XDISTANCE, 100);​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_YDISTANCE, 70);​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_XSIZE, 60);​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_YSIZE, 25);​
ObjectSetString(0, BTN_SELL_NAME, OBJPROP_TEXT, "SELL");​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_BGCOLOR, clrRed);​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_COLOR, clrWhite);​

//--- Create the Bid price label (OBJ_LABEL)​
ObjectCreate(0, LBL_BID_NAME, OBJ_LABEL, 0, 0, 0);​
ObjectSetInteger(0, LBL_BID_NAME, OBJPROP_XDISTANCE, 30);​
ObjectSetInteger(0, LBL_BID_NAME, OBJPROP_YDISTANCE, 110);​
ObjectSetString(0, LBL_BID_NAME, OBJPROP_TEXT, "Bid: -");​
ObjectSetInteger(0, LBL_BID_NAME, OBJPROP_COLOR, clrWhite);​

//--- Create the Ask price label (OBJ_LABEL)​
ObjectCreate(0, LBL_ASK_NAME, OBJ_LABEL, 0, 0, 0);​
ObjectSetInteger(0, LBL_ASK_NAME, OBJPROP_XDISTANCE, 30);​
ObjectSetInteger(0, LBL_ASK_NAME, OBJPROP_YDISTANCE, 130);​
ObjectSetString(0, LBL_ASK_NAME, OBJPROP_TEXT, "Ask: -");​
ObjectSetInteger(0, LBL_ASK_NAME, OBJPROP_COLOR, clrWhite);​

//--- Enable mouse move events for interactivity​
ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);​

ChartRedraw();​
return(INIT_SUCCEEDED);​
}​
//+------------------------------------------------------------------+​
//| Expert deinitialization function |​
//+------------------------------------------------------------------+​
void OnDeinit(const int reason)​
{​
//--- Clean up all created objects​
ObjectsDeleteAll(0, PANEL_NAME);​
ObjectsDeleteAll(0, BTN_BUY_NAME);​
ObjectsDeleteAll(0, BTN_SELL_NAME);​
ObjectsDeleteAll(0, LBL_BID_NAME);​
ObjectsDeleteAll(0, LBL_ASK_NAME);​
ChartRedraw();​
}​
//+------------------------------------------------------------------+​
//| ChartEvent function |​
//+------------------------------------------------------------------+​
void OnChartEvent(const int id,​
const long &lparam,​
const double &dparam,​
const string &sparam)​
{​
//--- Event handling logic will be added here​
}​
//+------------------------------------------------------------------+​

3.2. Part 2: Drag-and-Drop Functionality in OnChartEvent()

To make the panel movable, state variables are used to track the dragging process. The logic
is handled within OnChartEvent() and follows these steps:
1.​ Detect Click: When a CHARTEVENT_OBJECT_CLICK event occurs on the main panel
background (PANEL_NAME), the dragging state is initiated. The initial mouse coordinates
and the panel's current position are stored.
2.​ Track Mouse Move: While in the dragging state, every CHARTEVENT_MOUSE_MOVE
event is processed. The change (delta) in mouse position from the initial click point is
calculated.
3.​ Update Positions: The calculated delta is applied to the initial positions of all panel
elements (OBJPROP_XDISTANCE, OBJPROP_YDISTANCE), moving them together as a
single unit.
4.​ Detect Release: The dragging state is terminated when a CHARTEVENT_MOUSE_MOVE
event is received where the left mouse button is no longer pressed. This is checked by
inspecting the sparam bitmask.

Code snippet

// --- Add these global variables for state management ---​


bool isPanelDragging = false;​
int dragStartX = 0;​
int dragStartY = 0;​
int panelStartX = 0;​
int panelStartY = 0;​

// --- Replace the empty OnChartEvent() with this implementation ---​
void OnChartEvent(const int id,​
const long &lparam,​
const double &dparam,​
const string &sparam)​
{​
//--- Start dragging the panel​
if(id == CHARTEVENT_OBJECT_CLICK && sparam == PANEL_NAME)​
{​
isPanelDragging = true;​
dragStartX = (int)lparam;​
dragStartY = (int)dparam;​
panelStartX = (int)ObjectGetInteger(0, PANEL_NAME, OBJPROP_XDISTANCE);​
panelStartY = (int)ObjectGetInteger(0, PANEL_NAME, OBJPROP_YDISTANCE);​
//--- Bring panel to front for event priority​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_ZORDER, 1);​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_ZORDER, 0);​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_ZORDER, 0);​
}​

//--- Process dragging​
if(isPanelDragging && id == CHARTEVENT_MOUSE_MOVE)​
{​
int currentX = (int)lparam;​
int currentY = (int)dparam;​

int deltaX = currentX - dragStartX;​
int deltaY = currentY - dragStartY;​

//--- Move the main panel​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_XDISTANCE, panelStartX + deltaX);​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_YDISTANCE, panelStartY + deltaY);​

//--- Move child elements relative to the panel​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_XDISTANCE, panelStartX + deltaX + 10);​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_YDISTANCE, panelStartY + deltaY + 20);​

ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_XDISTANCE, panelStartX + deltaX + 80);​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_YDISTANCE, panelStartY + deltaY + 20);​

ObjectSetInteger(0, LBL_BID_NAME, OBJPROP_XDISTANCE, panelStartX + deltaX + 10);​
ObjectSetInteger(0, LBL_BID_NAME, OBJPROP_YDISTANCE, panelStartY + deltaY + 60);​

ObjectSetInteger(0, LBL_ASK_NAME, OBJPROP_XDISTANCE, panelStartX + deltaX + 10);​
ObjectSetInteger(0, LBL_ASK_NAME, OBJPROP_YDISTANCE, panelStartY + deltaY + 80);​

ChartRedraw();​
}​

//--- Stop dragging (mouse button released)​
if(isPanelDragging && id == CHARTEVENT_MOUSE_MOVE && (int)sparam == 0)​
{​
isPanelDragging = false;​
//--- Reset Z-order​
ObjectSetInteger(0, PANEL_NAME, OBJPROP_ZORDER, 0);​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_ZORDER, 1);​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_ZORDER, 1);​
}​
}​

3.3. Part 3: Responsiveness and Hover Effects

To handle button clicks, the CHARTEVENT_OBJECT_CLICK event is checked. The sparam


parameter contains the name of the object that was clicked, allowing the code to differentiate
between the buy and sell buttons.
Code snippet

// --- Add this code inside the OnChartEvent() function ---​


// --- Handle button clicks​
if(id == CHARTEVENT_OBJECT_CLICK)​
{​
if(sparam == BTN_BUY_NAME)​
{​
Print("Buy Button Clicked!");​
//--- Reset button state to allow for another click​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_STATE, false);​
ChartRedraw();​
}​
if(sparam == BTN_SELL_NAME)​
{​
Print("Sell Button Clicked!");​
//--- Reset button state​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_STATE, false);​
ChartRedraw();​
}​
}​

A hover effect provides important visual feedback to the user. This is achieved by tracking the
mouse cursor's position during CHARTEVENT_MOUSE_MOVE events and changing the
button's background color when the cursor enters or leaves its area. State variables
(isHoverBuy, isHoverSell) are crucial to prevent flooding the event queue with redundant color
change commands on every mouse movement.25

Code snippet

// --- Add these global variables for hover state management ---​
bool isHoverBuy = false;​
bool isHoverSell = false;​

// --- Add this code inside the OnChartEvent() function, after the dragging logic ---​
// --- Handle hover effects for buttons​
if(id == CHARTEVENT_MOUSE_MOVE &&!isPanelDragging)​
{​
int x = (int)lparam;​
int y = (int)dparam;​

//--- Check Buy Button​
int buyX = (int)ObjectGetInteger(0, BTN_BUY_NAME, OBJPROP_XDISTANCE);​
int buyY = (int)ObjectGetInteger(0, BTN_BUY_NAME, OBJPROP_YDISTANCE);​
int buyXSize = (int)ObjectGetInteger(0, BTN_BUY_NAME, OBJPROP_XSIZE);​
int buyYSize = (int)ObjectGetInteger(0, BTN_BUY_NAME, OBJPROP_YSIZE);​

if(x >= buyX && x <= buyX + buyXSize && y >= buyY && y <= buyY + buyYSize)​
{​
if(!isHoverBuy)​
{​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_BGCOLOR, clrDarkGreen);​
ChartRedraw();​
isHoverBuy = true;​
}​
}​
else​
{​
if(isHoverBuy)​
{​
ObjectSetInteger(0, BTN_BUY_NAME, OBJPROP_BGCOLOR, clrGreen);​
ChartRedraw();​
isHoverBuy = false;​
}​
}​

//--- Check Sell Button​
int sellX = (int)ObjectGetInteger(0, BTN_SELL_NAME, OBJPROP_XDISTANCE);​
int sellY = (int)ObjectGetInteger(0, BTN_SELL_NAME, OBJPROP_YDISTANCE);​
int sellXSize = (int)ObjectGetInteger(0, BTN_SELL_NAME, OBJPROP_XSIZE);​
int sellYSize = (int)ObjectGetInteger(0, BTN_SELL_NAME, OBJPROP_YSIZE);​

if(x >= sellX && x <= sellX + sellXSize && y >= sellY && y <= sellY + sellYSize)​
{​
if(!isHoverSell)​
{​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_BGCOLOR, clrDarkRed);​
ChartRedraw();​
isHoverSell = true;​
}​
}​
else​
{​
if(isHoverSell)​
{​
ObjectSetInteger(0, BTN_SELL_NAME, OBJPROP_BGCOLOR, clrRed);​
ChartRedraw();​
isHoverSell = false;​
}​
}​
}​

3.4. Part 4: Displaying Live Data with OnTick()

The OnTick() function is the ideal place to update information that changes with every new
price quote. Here, it is used to fetch the current bid and ask prices using SymbolInfoDouble()
and update the text of the corresponding labels on the panel.

Code snippet

//+------------------------------------------------------------------+​
//| Expert tick function |​
//+------------------------------------------------------------------+​
void OnTick()​
{​
//--- Get current bid and ask prices​
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);​
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);​

//--- Update the text of the labels​
string bidText = "Bid: " + DoubleToString(bid, _Digits);​
string askText = "Ask: " + DoubleToString(ask, _Digits);​

ObjectSetString(0, LBL_BID_NAME, OBJPROP_TEXT, bidText);​
ObjectSetString(0, LBL_ASK_NAME, OBJPROP_TEXT, askText);​

// No ChartRedraw() is needed here, as the terminal redraws on new ticks.​
}​

4. Advanced On-Chart Visualization Techniques

Beyond standard GUI controls, MQL5 offers powerful features for visualizing complex data
sets directly on the chart.

4.1. Nested Sub-Charts with OBJ_CHART

The OBJ_CHART graphical object allows a developer to embed a fully functional chart of a
different symbol and timeframe directly within the main chart window. This is useful for
creating multi-timeframe analysis tools or dashboards that display correlated instruments.26

Code snippet

//+------------------------------------------------------------------+​
//| ObjChart_Demo.mq5 |​
//| Copyright 2023, MetaQuotes Software Corp. |​
//| https://www.mql5.com |​
//+------------------------------------------------------------------+​
#property copyright "Copyright 2023, MetaQuotes Software Corp."​
#property link "https://www.mql5.com"​
#property version "1.00"​
#property script_show_inputs​

input string InpSymbol = "EURUSD"; // Symbol for the nested chart​
input ENUM_TIMEFRAMES InpTf = PERIOD_H1; // Timeframe for the nested chart​

//+------------------------------------------------------------------+​
//| Script program start function |​
//+------------------------------------------------------------------+​
void OnStart()​
{​
string obj_name = "NestedChart";​

//--- Create the OBJ_CHART object​
ObjectCreate(0, obj_name, OBJ_CHART, 0, 0, 0);​

//--- Set its position and size (in pixels)​
ObjectSetInteger(0, obj_name, OBJPROP_XDISTANCE, 50);​
ObjectSetInteger(0, obj_name, OBJPROP_YDISTANCE, 50);​
ObjectSetInteger(0, obj_name, OBJPROP_XSIZE, 400);​
ObjectSetInteger(0, obj_name, OBJPROP_YSIZE, 250);​

//--- Set the symbol and timeframe for the nested chart​
ObjectSetString(0, obj_name, OBJPROP_SYMBOL, InpSymbol);​
ObjectSetInteger(0, obj_name, OBJPROP_PERIOD, InpTf);​

//--- Set other visual properties​
ObjectSetInteger(0, obj_name, OBJPROP_CHART_SCALE, 3);​
ObjectSetInteger(0, obj_name, OBJPROP_DATE_SCALE, true);​
ObjectSetInteger(0, obj_name, OBJPROP_PRICE_SCALE, true);​

ChartRedraw();​
}​
//+------------------------------------------------------------------+​

The primary limitation of OBJ_CHART is that it is impossible to programmatically create other


graphical objects (such as lines, labels, or Fibonacci tools) inside the nested chart object. The
nested chart is a self-contained visual element, and its contents cannot be manipulated via
MQL5 code running on the main chart.27

4.2. Leveraging Custom Indicator Drawing Styles

To visualize dense or complex data sets, such as a custom representation of candlesticks or a


filled area between two lines, creating hundreds of individual graphical objects is highly
inefficient. Each ObjectCreate() and ObjectSet...() call adds a command to the chart queue,
which can lead to significant performance degradation.2

A far more performant and powerful technique is to delegate the rendering to the terminal's
native graphics engine. This is achieved by encapsulating the visualization logic within a
custom indicator that uses one of MQL5's advanced built-in drawing styles, such as
DRAW_CANDLES, DRAW_BARS, or DRAW_FILLING.30 The Expert Advisor can then simply call
this indicator using the iCustom() function. This single call instructs the terminal to handle all
the complex drawing internally using its highly optimized code, which is orders of magnitude
faster than managing hundreds of MQL objects from an EA.31

4.3. Data Layering and Event Priority with Z-Order

Dynamic visualizations can be created by programmatically changing the properties of


existing objects. For example, a heat map could be implemented by creating a grid of
OBJ_RECTANGLE_LABEL objects and then updating their OBJPROP_BGCOLOR property in
OnTick() or OnTimer() based on changing market data.33

When graphical objects overlap, MQL5 provides a mechanism to control which object receives
mouse click events. This is managed by the OBJPROP_ZORDER property. OBJPROP_ZORDER
is an integer value that determines the priority for receiving mouse events like
CHARTEVENT_OBJECT_CLICK. When multiple objects are stacked in the same location, the
click event is delivered only to the object with the highest OBJPROP_ZORDER value.35

It is critical to note that OBJPROP_ZORDER controls only the event priority and does not
affect the visual drawing order of the objects.35 Objects are always drawn on the chart in
the order they were created. This can lead to situations where an object is visually obscured
by another, yet it is the one that receives the mouse click because it has a higher Z-order.

5. Platform Evolution & Code Maintenance

The MetaTrader 5 platform is under continuous development, with new features and compiler
behaviors introduced in periodic builds. Staying current with these changes is essential for
long-term code maintenance.

Recent platform builds have introduced GUI-related enhancements that developers can
leverage. For example, build 5200 (released August 2025) added the ability for the terminal to
automatically switch between its light and dark themes based on the host operating system's
settings. A modern, professionally designed GUI should detect and adapt to this setting to
provide a consistent user experience.40
5.1. Clarification: The 'Deprecated Behavior' Compiler Warning

A common warning that appears during compilation is: deprecated behavior, hidden method
calling will be disabled in a future MQL compiler version. This warning is frequently
misinterpreted and is not related to the deprecation of core graphical functions like
ObjectCreate or ObjectSetInteger.41

This warning is triggered by a specific Object-Oriented Programming scenario called method


hiding (or shadowing) in class inheritance. It occurs when a method in a derived class is given
the same name as a method in its base class. This action in the derived class "hides" all
methods of the same name from the base class, including any overloads with different
parameters.43

The warning serves as a forward-compatibility notice from MetaQuotes. The compiler


currently allows this ambiguous behavior but indicates that in a future version, it will be
treated as a compilation error to align more closely with strict C++ standards. Developers
should treat this warning as a requirement to refactor their code to be more explicit, ensuring
it remains compilable on future platform updates.

Example of Code Triggering the Warning:

Code snippet

class CBase​
{​
public:​
void PrintMessage(string msg) { Print("Base: ", msg); }​
void PrintMessage(int val) { Print("Base: ", val); }​
};​

class CDerived : public CBase​
{​
public:​
// This method hides BOTH PrintMessage methods in CBase​
void PrintMessage(string msg) { Print("Derived: ", msg); }​
};​

void OnStart()​
{​
CDerived derived;​
derived.PrintMessage("Hello"); // Calls CDerived::PrintMessage​
derived.PrintMessage(123); // COMPILER WARNING HERE​
}​

In the example above, the compiler issues a warning because CDerived::PrintMessage(string)


hides CBase::PrintMessage(int).

Corrected Version:
To resolve the warning, the developer can either rename the method in the derived class or
explicitly bring the hidden base class methods into the derived class's scope with the using
keyword.

Code snippet

class CBase​
{​
public:​
void PrintMessage(string msg) { Print("Base: ", msg); }​
void PrintMessage(int val) { Print("Base: ", val); }​
};​

class CDerived : public CBase​
{​
public:​
using CBase::PrintMessage; // Makes base methods visible​

// This now correctly OVERLOADS, not hides​
void PrintMessage(string msg) { Print("Derived: ", msg); }​
};​

void OnStart()​
{​
CDerived derived;​
derived.PrintMessage("Hello"); // Calls CDerived::PrintMessage​
derived.PrintMessage(123); // No warning, correctly calls CBase::PrintMessage​
}​
6. Developer Ecosystem & Best Practices

6.1. Using Third-Party GUI Libraries

The MQL5 Code Base and Market offer numerous third-party libraries designed to simplify
and accelerate GUI development. While these can be powerful tools, their use involves a
trade-off analysis.
●​ Advantages:
○​ Faster Development Time: Libraries often provide complex, pre-built controls (e.g.,
tabs, data grids, advanced charts) that would take significant time to develop from
scratch.46
○​ Access to Complex Controls: They can offer sophisticated UI elements that are not
available through standard MQL5 graphical objects.
●​ Disadvantages:
○​ External Dependency: The project becomes dependent on an external codebase
that the developer does not control.
○​ Potential for Bugs and Performance Overhead: A poorly written library can
introduce bugs, memory leaks, or performance bottlenecks into the application,
causing terminal lag.46
○​ Lack of Customization: The library may not offer the specific look, feel, or
functionality required, limiting creative control.
○​ Abandonment Risk: The library's author may cease development, leaving the
project dependent on outdated or unsupported code.47

6.2. Expert-Recommended Best Practices

To produce robust, maintainable, and high-performance GUI applications in MQL5, adhere to


the following best practices:
●​ Encapsulation: Encapsulate all GUI logic, state management, and event handling within
dedicated classes. This separates the user interface code from the core trading logic,
making the entire application more modular, easier to debug, and simpler to maintain.48
●​ Error Checking: After every call to an object creation or modification function (e.g.,
ObjectCreate, ObjectSetInteger), check for potential failures by calling GetLastError().
This allows for the robust handling of runtime errors, such as attempting to modify an
object that does not exist (error 4202).50
●​ Resource Management: Ensure that all created graphical objects are cleanly and
completely removed from the chart in the OnDeinit() function. Use ObjectDelete() for
individual objects or ObjectsDeleteAll() with a unique prefix to prevent orphaned objects
from remaining on the chart after the program is closed or reinitialized.53
●​ Performance Optimization: Code inside high-frequency event handlers, particularly
OnTick() and OnChartEvent() (for CHARTEVENT_MOUSE_MOVE), must be extremely
lightweight. Avoid complex calculations, loops, or any operations that could cause delay.
Use state variables to ensure that GUI update commands are only sent when a change is
necessary, rather than on every event, to prevent flooding the event queue and causing
terminal lag.16

Works cited

1.​ MQL5 History and Evolution Report.pdf


2.​ Object Functions - MQL5 Reference - Reference on algorithmic/automated
trading language for MetaTrader 5, accessed October 11, 2025,
https://www.mql5.com/en/docs/objects
3.​ Object Functions - MQL4参考, accessed October 11, 2025,
https://docs.mql4.com/cn/objects
4.​ ObjectCreate - Object Functions - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/objects/objectcreate
5.​ ObjectSetString - Object Functions - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/objects/objectsetstring
6.​ www.mql5.com, accessed October 11, 2025,
https://www.mql5.com/en/book/applications/charts/charts_redraw#:~:text=Theref
ore%2C%20the%20MQL5%20API%20provides,a%20redrawing%20of%20the%2
0chart.&text=The%20function%20causes%20a%20forced,0%20means%20the%
20current%20chart).
7.​ ChartRedraw - Chart Operations - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/chart_operations/chartredraw
8.​ Graphic Objects - Standard Library - MQL5 Reference, accessed October 11,
2025, https://www.mql5.com/en/docs/standardlibrary/chart_object_classes
9.​ State - CChartObjectButton - Control Objects - Graphic Objects - Standard
Library - MQL5 Reference - Reference on algorithmic/automated trading
language for MetaTrader 5, accessed October 11, 2025,
https://www.mql5.com/en/docs/standardlibrary/chart_object_classes/obj_controls
/cchartobjectbutton/cchartobjectbuttonstate
10.​CChartObjectButton - Objects Controls - 图形对象- 标准程序库- MQL5参考,
accessed October 11, 2025,
https://www.mql5.com/zh/docs/standardlibrary/chart_object_classes/obj_controls
/cchartobjectbutton
11.​ Shape Objects - Graphic Objects - Standard Library - MQL5 Reference -
Reference on algorithmic/automated trading language for MetaTrader 5,
accessed October 11, 2025,
https://www.mql5.com/en/docs/standardlibrary/chart_object_classes/obj_shapes
12.​グラフィックオブジェクト | MQL5リファレンス, accessed October 11, 2025,
https://metasys-seeker.com/index/%E6%A8%99%E6%BA%96%E3%83%A9%E3%8
2%A4%E3%83%96%E3%83%A9%E3%83%AA/%E3%82%B0%E3%83%A9%E3%83
%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%AA%E3%83%96%E3%82%B
8%E3%82%A7%E3%82%AF%E3%83%88/%E3%82%B0%E3%83%A9%E3%83%95
%E3%82%A3%E3%83%83%E3%82%AF%E3%82%AA%E3%83%96%E3%82%B8%E
3%82%A7%E3%82%AF%E3%83%88/
13.​Event Handling Functions - Functions - Language Basics - MQL5 Reference,
accessed October 11, 2025, https://www.mql5.com/en/docs/basis/function/events
14.​Improve Your Trading Charts With Interactive GUI's in MQL5 (Part II): Movable GUI
(II), accessed October 11, 2025, https://www.mql5.com/en/articles/12880
15.​Event handling function OnChartEvent - Creating application programs - MQL5,
accessed October 11, 2025,
https://www.mql5.com/en/book/applications/events/events_onchartevent
16.​OnChartEvent - Event Handling - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/event_handlers/onchartevent
17.​Types of Chart Events - Chart Constants - Constants, Enumerations and
Structures - MQL5 Reference - Reference on algorithmic/automated trading
language for MetaTrader 5, accessed October 11, 2025,
https://www.mql5.com/en/docs/constants/chartconstants/enum_chartevents
18.​EventChartCustom - Working with Events - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/eventfunctions/eventchartcustom
19.​Event Handling Functions - Functions - Language Basics - MQL4 Reference,
accessed October 11, 2025, https://docs.mql4.com/basis/function/events
20.​CHARTEVENT_OBJECT_CLICK - MT4 - General - MQL5 programming forum,
accessed October 11, 2025, https://www.mql5.com/en/forum/99659
21.​OnChartEvent Mouse Move - Moving Average, MA - General - MQL5
programming forum, accessed October 11, 2025,
https://www.mql5.com/en/forum/425628
22.​List of MQL5 Constants - MQL5 Reference - Reference on algorithmic/automated
trading language for MetaTrader 5, accessed October 11, 2025,
https://www.mql5.com/en/docs/constant_indices
23.​Effect of placing one Object within OnInit() - VPS for Forex - Technical Indicators -
MQL5 programming forum, accessed October 11, 2025,
https://www.mql5.com/en/forum/480165
24.​How to Create Object Label - Symbols - General - MQL5 programming forum,
accessed October 11, 2025, https://www.mql5.com/en/forum/231088
25.​Event handling OnTick and OnChartEvent - Best Expert Advisors - General -
MQL5 programming forum, accessed October 11, 2025,
https://www.mql5.com/en/forum/87874
26.​MQL5 charts - MQL4 Reference, accessed October 11, 2025,
https://docs.mql4.com/mql5_language/mql5_charts
27.​Can i create objects (example OBJ_HLINE) inside OBJ_CHART? - Symbols -
General - MQL5 programming forum, accessed October 11, 2025,
https://www.mql5.com/en/forum/219079
28.​Object Properties: MQL5 Reference / Constants, Enumerations and Structures /
Objects Constants / Object Properties | PDF | Cartesian Coordinate System | Pixel
- Scribd, accessed October 11, 2025,
https://www.scribd.com/document/518783358/Obj
29.​Asynchronous and multi-threaded programming in MQL - page 26, accessed
October 11, 2025, https://www.mql5.com/en/forum/414192/page26
30.​Drawing Styles - Indicator Constants - Constants, Enumerations and Structures -
MQL5 Reference - Reference on algorithmic/automated trading language for
MetaTrader 5, accessed October 11, 2025,
https://www.mql5.com/en/docs/constants/indicatorconstants/drawstyles
31.​iCustom - Technical Indicators - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/indicators/icustom
32.​Using a custom indicator in an EA - Expert Advisor - MQL5, accessed October 11,
2025, https://www.mql5.com/en/forum/39777
33.​Main object properties - Creating application programs - MQL5, accessed
October 11, 2025,
https://www.mql5.com/en/book/applications/objects/objects_properties_main
34.​MQL5 Trading Tools (Part 6): Dynamic Holographic Dashboard with Pulse
Animations and Controls, accessed October 11, 2025,
https://www.mql5.com/en/articles/18880
35.​Priority of objects (Z-Order) - Creating application programs - MQL5, accessed
October 11, 2025,
https://www.mql5.com/en/book/applications/objects/objects_z_order
36.​OBJ_EVENT - Object Types - Objects Constants - Constants, Enumerations and
Structures - MQL5 Reference - Reference on algorithmic/automated trading
language for MetaTrader 5, accessed October 11, 2025,
https://www.mql5.com/en/docs/constants/objectconstants/enum_object/obj_even
t
37.​Z-order meaning - Rectangles - MQL4 and MetaTrader 4 - MQL5, accessed
October 11, 2025, https://www.mql5.com/en/forum/240496
38.​Zorder Function - Paper Trading - Technical Indicators - MQL5 programming
forum, accessed October 11, 2025, https://www.mql5.com/en/forum/472234
39.​Object Properties - Objects Constants - Constants, Enumerations and Structures
- MQL4 Reference, accessed October 11, 2025,
https://docs.mql4.com/constants/objectconstants/enum_object_property
40.​New MT5 platform build offers extended OpenBLAS support and enhanced
control in MQL5, accessed October 11, 2025,
https://fxnewsgroup.com/forex-news/platforms/new-mt5-platform-build-offers-e
xtended-openblas-support-and-enhanced-control-in-mql5/
41.​deprecated behavior, hidden method calling will be disabled in a future MQL
compiler version - Indices - General - MQL5 programming forum, accessed
October 11, 2025, https://www.mql5.com/en/forum/322750
42.​StringReplace() deprecated?? [warning 91: deprecated behavior, hidden method
calling will be disabled in a future MQL compiler version] - MetaTrader 4 - General
- MQL5 programming forum, accessed October 11, 2025,
https://www.mql5.com/en/forum/324471
43.​Deprecated behavior, hidden method calling will be disabled in a future MQL
compiler version - page 3, accessed October 11, 2025,
https://www.mql5.com/en/forum/479024/page3
44.​Deprecated behavior, hidden method calling will be disabled in a future MQL
compiler version - Futures Trading - Expert Advisors and Automated Trading -
MQL5 programming forum, accessed October 11, 2025,
https://www.mql5.com/en/forum/479024
45.​New MetaTrader 5 Platform Build 5200: Extended OpenBLAS support and
enhanced control in MQL5, accessed October 11, 2025,
https://www.mql5.com/en/forum/492297
46.​Best GUI library for MQL5 - Best EA - General - MQL5 programming forum,
accessed October 11, 2025, https://www.mql5.com/en/forum/427996
47.​No Good Go GUI. Created Saturday 14 May 2022 | by 3-Toed-Sloth | Medium,
accessed October 11, 2025,
https://medium.com/@balle.johannes/no-good-go-gui-9f54813e9bf
48.​OOP fundamentals: Encapsulation - Object Oriented Programming - MQL5,
accessed October 11, 2025,
https://www.mql5.com/en/book/oop/classes_and_interfaces/classes_encapsulatio
n
49.​Encapsulation and Extensibility of Types - Object-Oriented Programming -
Language Basics, accessed October 11, 2025,
https://www.mql5.com/en/docs/basis/oop/incapsulation
50.​Runtime Errors - Codes of Errors and Warnings - Constants, Enumerations and
Structures - MQL5 Reference - Reference on algorithmic/automated trading
language for MetaTrader 5, accessed October 11, 2025,
https://www.mql5.com/en/docs/constants/errorswarnings/errorcodes
51.​GetLastError - Checkup - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/check/getlasterror
52.​if ErrorDescription(GetLastError()) returns "no error"....how on EARTH can you test
to solve for the error? - MQL5, accessed October 11, 2025,
https://www.mql5.com/en/forum/124523
53.​OnDeinit - Event Handling - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/event_handlers/ondeinit
54.​Graphical objects - Creating application programs - MQL5, accessed October 11,
2025, https://www.mql5.com/en/book/applications/objects
55.​Reference events of indicators and Expert Advisors: OnInit and OnDeinit -
Creating application programs - MQL5, accessed October 11, 2025,
https://www.mql5.com/en/book/applications/runtime/runtime_oninit_ondeinit
56.​OnTick - Event Handling - MQL5 Reference - Reference on
algorithmic/automated trading language for MetaTrader 5, accessed October 11,
2025, https://www.mql5.com/en/docs/event_handlers/ontick

You might also like