Problem Description
Solution
To add a clickable button in MQL4, you need to utilize the Event Handling system. Specifically, you will create an object of type OBJ_BUTTON and then listen for the CHARTEVENT_OBJECT_CLICK event within the OnChartEvent() function.
Here is the complete, copy-pasteable code for an Expert Advisor (EA) that creates a button. When clicked, it triggers a specific action (in this example, printing a message and sending an alert).
MQL4 Code: Clickable Button Example
//+------------------------------------------------------------------+
//| SimpleButtonEvent.mq4 |
//| Copyright 2023, MetaQuotes |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters for Button Customization
input string ButtonName = "MyActionBtn"; // Unique Object Name
input string ButtonText = "Execute"; // Text on Button
input color BtnColor = clrCornflowerBlue; // Background Color
input color TextColor = clrWhite; // Text Color
input int BtnX = 50; // X Distance from corner
input int BtnY = 50; // Y Distance from corner
input int BtnWidth = 100; // Button Width
input int BtnHeight = 30; // Button Height
input ENUM_BASE_CORNER BtnCorner = CORNER_LEFT_UPPER; // Chart Corner
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Create the button when the EA is loaded
if(!CreateButton())
{
Print("Failed to create button!");
return(INIT_FAILED);
}
// Force chart redraw to show button immediately
ChartRedraw();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Remove the button when the EA is removed to keep the chart clean
ObjectDelete(0, ButtonName);
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Standard OnTick logic goes here
// We don't need this for the button to work, as buttons use Event handling
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//| This function listens for mouse clicks and keystrokes |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
// Check if the event is an object click
if(id == CHARTEVENT_OBJECT_CLICK)
{
// Check if the clicked object is OUR button
if(sparam == ButtonName)
{
// --- EXECUTE SPECIFIC ACTION HERE ---
ExecuteMyAction();
// Reset the button state (unpress it)
// If we don't do this, the button stays "pressed" in
ObjectSetInteger(0, ButtonName, OBJPROP_STATE, false);
// Redraw chart to reflect the unpressed state
ChartRedraw();
}
}
}
//+------------------------------------------------------------------+
//| Custom Function: The Action to Perform |
//+------------------------------------------------------------------+
void ExecuteMyAction()
{
// Example actions:
Print("Button was clicked at: ", TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS));
Alert("Action Executed Successfully!");
// You can place trade logic here, e.g., OrderSend(...)
}
//+------------------------------------------------------------------+
//| Helper Function: Create the Button Object |
//+------------------------------------------------------------------+
bool CreateButton()
{
// Check if object already exists
if(ObjectFind(0, ButtonName) >= 0)
{
// If it exists, delete it to recreate with new inputs
ObjectDelete(0, ButtonName);
}
// Create the Object
if(!ObjectCreate(0, ButtonName, OBJ_BUTTON, 0, 0, 0))
{
return(false);
}
// Set Properties
ObjectSetInteger(0, ButtonName, OBJPROP_XDISTANCE, BtnX);
ObjectSetInteger(0, ButtonName, OBJPROP_YDISTANCE, BtnY);
ObjectSetInteger(0, ButtonName, OBJPROP_XSIZE, BtnWidth);
ObjectSetInteger(0, ButtonName, OBJPROP_YSIZE, BtnHeight);
ObjectSetInteger(0, ButtonName, OBJPROP_CORNER, BtnCorner);
// Styling
ObjectSetString(0, ButtonName, OBJPROP_TEXT, ButtonText);
ObjectSetString(0, ButtonName, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, ButtonName, OBJPROP_FONTSIZE, 10);
ObjectSetInteger(0, ButtonName, OBJPROP_COLOR, TextColor);
ObjectSetInteger(0, ButtonName, OBJPROP_BGCOLOR, BtnColor);
ObjectSetInteger(0, ButtonName, OBJPROP_BORDER_COLOR, clrBlack);
// Interaction settings
ObjectSetInteger(0, ButtonName, OBJPROP_BACK, false); // Foreground
ObjectSetInteger(0, ButtonName, OBJPROP_STATE, false); // Default state: unpressed
ObjectSetInteger(0, ButtonName, OBJPROP_SELECTABLE, false); // Prevent manual selection
ObjectSetInteger(0, ButtonName, OBJPROP_ZORDER, 0); // Z-Order
return(true);
}
Key Components Explained
OnInit(): This is where we call theCreateButton()helper function. It ensures the button appears as soon as you attach the EA to the chart.OnDeinit(): It is crucial to callObjectDeletehere. If you don't, the button will remain stuck on the chart even after you remove the EA.OnChartEvent(): This is the most important part.id == CHARTEVENT_OBJECT_CLICK: Filters the events to only listen for mouse clicks on objects.sparam == ButtonName:sparamcontains the name of the object that was clicked. We verify it matches our button's name.ObjectSetInteger(..., OBJPROP_STATE, false): Buttons in MT4 are "sticky" by default (toggle switches). To make it act like a momentary push-button, we programmatically set its state back tofalse(unpressed) immediately after the click.
CreateButton(): This helper function handles the verbose setup ofOBJ_BUTTON, setting coordinates, size, colors, and anchoring corners.
How to Use This
- Open MetaEditor in MT4.
- Create a new Expert Advisor.
- Paste the code above into the file, replacing everything.
- Compile the code (F7).
- Drag the EA onto a chart. You will see a blue button labeled "Execute".
- Click the button to see the Alert and Print log messages.
Q&A: MQL4 Chart Buttons
Q: Can I use this code in a Custom Indicator instead of an Expert Advisor?
A: Yes. The OnChartEvent function works exactly the same way in Indicators. However, ensure you manage OnDeinit carefully, as indicators are re-initialized more frequently than EAs.
Q: Why does the button stay pressed down when I click it?
A: OBJ_BUTTON has a boolean state (On/Off). If you want it to act like a trigger (click and release), you must manually reset the state in your code using ObjectSetInteger(0, ButtonName, OBJPROP_STATE, false); inside the click event.
Q: How do I place the button in the bottom-right corner?
A: Change the input parameter BtnCorner to CORNER_RIGHT_LOWER. The X and Y coordinates will then be calculated relative to that specific corner.
Q: Can I add an image to the button?
A: OBJ_BUTTON only supports text and background colors. If you need an image, you should use OBJ_BITMAP_LABEL. However, OBJ_BITMAP_LABEL requires handling CHARTEVENT_CLICK (coordinates) rather than CHARTEVENT_OBJECT_CLICK, or using OBJ_BITMAP_LABEL with OnChartEvent logic to detect if the click coordinates fall within the image boundaries.