Build your first panel
This page builds a small chart-hosted panel using ModernUI fast wrappers and the recommended event bus.
It assumes you have already completed Quick Start and have a working MuiRoot lifecycle.
What you will build
You will build a simple settings-style panel with:
- a moveable app window
- a section title
- a labelled spin edit
- Save and Reset buttons
- a status row
- toast feedback
- central event routing with
OnMuiEvent(...)
This is UI-only. It does not place, modify, or close real orders.
Full EA example
#property strict
#include <ModernUI\ModernUI.mqh>
enum FIRST_PANEL_ACTION
{
FP_ACTION_SAVE,
FP_ACTION_RESET,
FP_ACTION_RISK_CHANGED
};
class CFirstPanel : public MuiEventSink
{
private:
MuiRoot m_ui;
MuiSpinEditHost *m_seRisk;
MuiButtonAction *m_bSave;
MuiButtonAction *m_bReset;
public:
ENUM_INIT_RETCODE OnInitEvent(void)
{
if(!m_ui.Init(ChartID(),0,"FirstPanel_",512,16))
return INIT_FAILED;
m_ui.SetEventSink((MuiEventSink*)GetPointer(this));
CreateGUI();
EventSetMillisecondTimer(16);
return INIT_SUCCEEDED;
}
void OnDeinitEvent(const int reason) { EventKillTimer(); m_ui.Shutdown(); }
void OnTimerEvent(void) { m_ui.OnTimer(); }
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
m_ui.OnChartEvent(id,lparam,dparam,sparam);
}
void CreateGUI(void)
{
MuiAppWindow app=Mui::AppWindow(m_ui,"First Panel",20,40,340,360,true);
MuiSection settings=Mui::Section(app.content,"Settings","A small ModernUI panel.");
MuiLabeledSpinEdit risk=Mui::LabeledSpinEdit(settings.body,"Risk %",0.1,10.0,0.1,1.0,1);
m_seRisk=risk.control;
if(m_seRisk!=NULL)
m_seRisk.Id(FP_ACTION_RISK_CHANGED);
MuiContainer *row=Mui::Row(app.content,8.0);
row.FullWidth(true);
m_bSave=Mui::ButtonPrimary(row,"Save");
m_bSave.Id(FP_ACTION_SAVE);
m_bSave.Flex(1.0);
m_bReset=Mui::Button(row,"Reset");
m_bReset.Id(FP_ACTION_RESET);
m_bReset.Flex(1.0);
Mui::StatusRow(app.content,"Status","Ready","success");
}
virtual void OnMuiEvent(MuiRoot &root,const MuiEventData &event)
{
if(event.EventId()==MUI_EVENT_CLICK && event.ControlId()==FP_ACTION_SAVE)
{
Mui::ToastSuccess(root,"Settings saved");
root.RefreshAll();
}
else if(event.EventId()==MUI_EVENT_CLICK && event.ControlId()==FP_ACTION_RESET)
{
if(m_seRisk!=NULL)
m_seRisk.Value(1.0);
Mui::Toast(root,"Settings reset");
root.RefreshAll();
}
else if(event.EventId()==MUI_EVENT_VALUE_CHANGED && event.ControlId()==FP_ACTION_RISK_CHANGED)
{
Mui::Toast(root,"Risk "+DoubleToString(event.Value(),1)+"%",1200);
}
}
};
CFirstPanel Panel;
int OnInit() { return Panel.OnInitEvent(); }
void OnDeinit(const int reason) { Panel.OnDeinitEvent(reason); }
void OnTimer() { Panel.OnTimerEvent(); }
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
Panel.OnChartEvent(id,lparam,dparam,sparam);
}
What this demonstrates
| Part | Purpose |
|---|---|
Mui::AppWindow |
Creates the window shell and attaches it to the root. |
Mui::Section |
Creates a grouped block inside the window. |
Mui::LabeledSpinEdit |
Creates a caption, spin edit, and optional hint in one call. |
.Id(...) |
Assigns an app-level event ID to a control. |
OnMuiEvent(...) |
Handles button clicks and spin edit value changes centrally. |
Mui::ToastSuccess |
Shows feedback after clicking Save. |
Why this is the recommended first panel
This example uses fast wrappers for structure and the event bus for behaviour.
That combination keeps EA code readable: create controls first, assign IDs, then route user actions from OnMuiEvent(...).
Customising after creation
MuiLabeledSpinEdit risk=Mui::LabeledSpinEdit(settings.body,"Risk %",0.1,10.0,0.1,1.0);
if(risk.control!=NULL)
{
risk.control.Id(FP_ACTION_RISK_CHANGED);
risk.control.Value(2.0);
}
Common setters include Id(...), Text(...), Value(...), Checked(...), Selected(...), Pad(...), Radius(...), SizePt(...), and AccentColor(...).
Common mistakes
Forgetting SetEventSink
If controls respond visually but your app action does not run, make sure the panel is connected:
m_ui.SetEventSink((MuiEventSink*)GetPointer(this));
Forgetting control IDs
Interactive controls should get IDs when you want them to emit app-level events.
m_bSave.Id(FP_ACTION_SAVE);
m_seRisk.Id(FP_ACTION_RISK_CHANGED);
API reference
Mui::LabeledSpinEdit·Mui::Section- Inputs · Event Bus
- Controls reference
- Full runnable panel: Showcase trade panel
Next step
Read Recommended EA Structure, then continue to Build UIs Faster.