Generate code in 3 minutes
Enter your idea and AI generates runnable code.
To create custom images or graphics directly within your MQL4 code without loading external files, you need to use Dynamic Resources.
The process involves three main steps:
uint (unsigned integer) representing the pixels.ResourceCreate() to convert that array into a graphical resource in memory.OBJ_BITMAP_LABEL) and bind it to that resource.This Expert Advisor demonstrates how to generate a gradient background with a moving circle directly in the code.
//+------------------------------------------------------------------+
//| DynamicGraphicsDemo.mq4 |
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative AI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input int CanvasWidth = 300; // Width of the image
input int CanvasHeight = 200; // Height of the image
input color CircleColor = clrRed;// Color of the moving circle
//--- Global Variables
uint g_pixels[]; // The pixel array (buffer)
string g_resourceName = "::MyDynamicImage"; // Resource name must start with "::"
string g_objectName = "MyBitmapLabel"; // Name of the chart object
int g_circleX = 0; // Current X position of circle
int g_circleY = 100; // Current Y position of circle
int g_direction = 5; // Movement speed/direction
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// 1. Resize the pixel array to fit the dimensions
ArrayResize(g_pixels, CanvasWidth * CanvasHeight);
// 2. Create the chart object to display the image
if(!ObjectCreate(0, g_objectName, OBJ_BITMAP_LABEL, 0, 0, 0))
{
Print("Failed to create object");
return(INIT_FAILED);
}
// 3. Configure Object Properties
ObjectSetInteger(0, g_objectName, OBJPROP_XDISTANCE, 50); // 50 pixels from left
ObjectSetInteger(0, g_objectName, OBJPROP_YDISTANCE, 50); // 50 pixels from top
ObjectSetInteger(0, g_objectName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, g_objectName, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
// 4. Bind the object to the dynamic resource name
// Note: The resource doesn't exist yet, but we bind the name now.
ObjectSetString(0, g_objectName, OBJPROP_BMPFILE, g_resourceName);
// 5. Enable timer for animation (every 50 milliseconds)
EventSetMillisecondTimer(50);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
// Clean up the object
ObjectDelete(0, g_objectName);
// Free the memory used by the resource
ResourceFree(g_resourceName);
}
//+------------------------------------------------------------------+
//| Timer function (Animation Loop) |
//+------------------------------------------------------------------+
void OnTimer()
{
// Update logic: Move the circle back and forth
g_circleX += g_direction;
if(g_circleX > CanvasWidth - 20 || g_circleX < 20) g_direction *= -1;
// Redraw the scene
DrawScene();
}
//+------------------------------------------------------------------+
//| Function to draw pixels into the array and update resource |
//+------------------------------------------------------------------+
void DrawScene()
{
// --- Step A: Clear the background (Fill with a gradient) ---
for(int y = 0; y < CanvasHeight; y++)
{
for(int x = 0; x < CanvasWidth; x++)
{
// Calculate array index: y * width + x
int i = y * CanvasWidth + x;
// Create a gradient color based on X position
// Alpha (transparency) is the highest byte (0xFF = fully opaque)
uchar alpha = 255;
uchar red = (uchar)((double)x / CanvasWidth * 255.0);
uchar green = (uchar)((double)y / CanvasHeight * 255.0);
uchar blue = 50;
// Combine channels into one uint color (ARGB format)
g_pixels[i] = ColorToARGB(C'0,0,0', alpha) | (red << 16) | (green << 8) | blue;
}
}
// --- Step B: Draw a Circle ---
int radius = 20;
uint circleColorUint = ColorToARGB(CircleColor, 255); // Convert MQL color to ARGB
for(int y = -radius; y <= radius; y++)
{
for(int x = -radius; x <= radius; x++)
{
if(x*x + y*y <= radius*radius) // Circle equation
{
int drawX = g_circleX + x;
int drawY = g_circleY + y;
// Boundary checks to prevent array out of range
if(drawX >= 0 && drawX < CanvasWidth && drawY >= 0 && drawY < CanvasHeight)
{
int i = drawY * CanvasWidth + drawX;
g_pixels[i] = circleColorUint;
}
}
}
}
// --- Step C: Update the Resource ---
// This pushes the pixel array into the resource memory
if(!ResourceCreate(g_resourceName, g_pixels, CanvasWidth, CanvasHeight, 0, 0, 0, COLOR_FORMAT_ARGB_NORMALIZE))
{
Print("ResourceCreate failed");
return;
}
// --- Step D: Force Chart Redraw ---
ChartRedraw();
}
uint[])Images in MQL4 are essentially 1-dimensional arrays of unsigned integers.
Width * Height.(x, y), the formula is index = y * Width + x.Standard MQL4 colors (like clrRed) are just integers, but for resources, you must explicitly handle the Alpha channel (transparency).
0xAARRGGBB (Alpha, Red, Green, Blue).ColorToARGB(color_value, alpha_value) converts standard colors to this format.
alpha=255: Fully Opaque.alpha=0: Fully Transparent (invisible).ResourceCreateThis is the engine of the operation.
:: (e.g., "::MyImage"). This tells MT4 it is a dynamic resource in memory, not a file on the disk.ResourceCreate repeatedly with the same name updates the image. This allows for animation (as shown in the OnTimer function).OBJ_BITMAP_LABELThis is the graphical object used to display the resource.
OBJPROP_BMPFILE property to the resource name ("::MyImage").OBJ_LABEL (which is text), this object renders raw pixel data.Q: Can I load an image from the disk and then modify it?
A: Yes. You can use ResourceReadImage to load a .bmp file into a uint array, modify the pixels in the array using the logic above, and then save it back using ResourceCreate.
Q: Why do colors look wrong when I manually set the integer?
A: You might be mixing up RGB and BGR, or forgetting the Alpha channel. If the Alpha channel is 0, the pixel will be invisible. Always use ColorToARGB or ensure you bitwise shift the Alpha byte (0xFF << 24) correctly.
Q: Is this CPU intensive?
A: It can be. Iterating through 60,000 pixels (300x200) every 50ms is generally fine, but generating full-screen HD graphics (1920x1080) in MQL4 on every tick will lag the terminal. Keep your canvas size reasonable.