Skip to content
ModernUI A DaneTrades developer library

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

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

UI build fragment
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:

Reference excerpt
m_ui.SetEventSink((MuiEventSink*)GetPointer(this));

Forgetting control IDs

Interactive controls should get IDs when you want them to emit app-level events.

UI build fragment
m_bSave.Id(FP_ACTION_SAVE);
m_seRisk.Id(FP_ACTION_RISK_CHANGED);

API reference

Next step

Read Recommended EA Structure, then continue to Build UIs Faster.