forked from animatedread/Warrior_EA
153 lines
7.5 KiB
MQL5
153 lines
7.5 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| ControlPanel.mqh |
|
||
|
|
//| AnimateDread |
|
||
|
|
//| https://www.mql5.com |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//--- Built on the standard MQL5 Controls library (CAppDialog/CButton). Per the library's own source
|
||
|
|
//--- (Controls\Wnd.mqh CWnd::OnEvent, Controls\Dialog.mqh CAppDialog::ChartEvent), every control in
|
||
|
|
//--- this framework - including the dialog's own caption drag and close/minimize buttons - detects
|
||
|
|
//--- clicks exclusively through CHARTEVENT_MOUSE_MOVE hit-testing, which raises an internal
|
||
|
|
//--- EventChartCustom(CONTROLS_SELF_MESSAGE, ON_CLICK, control.Id(), ...) event; CAppDialog::ChartEvent()
|
||
|
|
//--- explicitly ignores CHARTEVENT_OBJECT_CLICK outright ("we are working with the CHARTEVENT_MOUSE_MOVE
|
||
|
|
//--- events"). So button clicks are wired the same way CDialog wires its own Close button - an
|
||
|
|
//--- EVENT_MAP/ON_EVENT(ON_CLICK, control, handler) entry - not by matching object names against
|
||
|
|
//--- CHARTEVENT_OBJECT_CLICK's sparam in the EA's OnChartEvent().
|
||
|
|
#include <Controls\Dialog.mqh>
|
||
|
|
#include <Controls\Button.mqh>
|
||
|
|
#define CP_PANEL_W 176
|
||
|
|
#define CP_ROW_H 24
|
||
|
|
#define CP_MARGIN 8
|
||
|
|
#define CP_BTN_H 20
|
||
|
|
#define CP_CAPTION_H 20
|
||
|
|
#define CP_NUM_BUTTONS 6
|
||
|
|
//--- total outer height needed for the dialog (caption bar + top margin + N button rows + bottom margin)
|
||
|
|
#define CP_PANEL_H (CP_CAPTION_H + CP_MARGIN + CP_NUM_BUTTONS * CP_ROW_H + CP_MARGIN)
|
||
|
|
//--- one action per button click; the EA's OnChartEvent() consumes this right after ExtPanel.ChartEvent()
|
||
|
|
enum ENUM_CP_ACTION
|
||
|
|
{
|
||
|
|
CP_ACTION_NONE,
|
||
|
|
CP_ACTION_TOGGLE_SIGNALS,
|
||
|
|
CP_ACTION_TOGGLE_PAUSE,
|
||
|
|
CP_ACTION_TOGGLE_STOP,
|
||
|
|
CP_ACTION_SAVE,
|
||
|
|
CP_ACTION_LOAD,
|
||
|
|
CP_ACTION_RESET
|
||
|
|
};
|
||
|
|
class CControlPanel : public CAppDialog
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
CButton m_signalsBtn;
|
||
|
|
CButton m_pauseBtn;
|
||
|
|
CButton m_stopBtn;
|
||
|
|
CButton m_saveBtn;
|
||
|
|
CButton m_loadBtn;
|
||
|
|
CButton m_resetBtn;
|
||
|
|
ENUM_CP_ACTION m_pendingAction;
|
||
|
|
bool CreateOneButton(CButton &btn, const string name, const int y, const string text);
|
||
|
|
bool CreateButtons(void);
|
||
|
|
protected:
|
||
|
|
//--- ON_CLICK handlers (see EVENT_MAP below) - just record which button fired; the EA polls
|
||
|
|
//--- ConsumeAction() once per OnChartEvent() call and performs the actual work
|
||
|
|
void OnClickSignals(void) { m_pendingAction = CP_ACTION_TOGGLE_SIGNALS; }
|
||
|
|
void OnClickPause(void) { m_pendingAction = CP_ACTION_TOGGLE_PAUSE; }
|
||
|
|
void OnClickStop(void) { m_pendingAction = CP_ACTION_TOGGLE_STOP; }
|
||
|
|
void OnClickSave(void) { m_pendingAction = CP_ACTION_SAVE; }
|
||
|
|
void OnClickLoad(void) { m_pendingAction = CP_ACTION_LOAD; }
|
||
|
|
void OnClickReset(void) { m_pendingAction = CP_ACTION_RESET; }
|
||
|
|
public:
|
||
|
|
CControlPanel(void) : m_pendingAction(CP_ACTION_NONE) {}
|
||
|
|
~CControlPanel(void) {}
|
||
|
|
virtual bool Create(const long chart, const string name, const int subwin,
|
||
|
|
const int x1, const int y1, const int x2, const int y2);
|
||
|
|
//--- chart event handler (EVENT_MAP macro below generates the body)
|
||
|
|
virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
|
||
|
|
//--- CAppDialog's default OnClickButtonClose() calls Destroy(), which for a PROGRAM_EXPERT calls
|
||
|
|
//--- ExpertRemove() - i.e. the caption bar's "x" would silently detach this EA from the chart and
|
||
|
|
//--- stop live trading/training. Redirect it to Minimize() so "x" behaves like the native "-" button
|
||
|
|
//--- instead of destroying the EA.
|
||
|
|
virtual void OnClickButtonClose(void) override { Minimize(); }
|
||
|
|
//--- keeps button labels synced with live training/signal-visibility state
|
||
|
|
void SetSignalsText(const string text) { m_signalsBtn.Text(text); }
|
||
|
|
void SetPauseText(const string text) { m_pauseBtn.Text(text); }
|
||
|
|
void SetStopText(const string text) { m_stopBtn.Text(text); }
|
||
|
|
//--- returns and clears whichever button (if any) was clicked since the last call
|
||
|
|
ENUM_CP_ACTION ConsumeAction(void) { ENUM_CP_ACTION a = m_pendingAction; m_pendingAction = CP_ACTION_NONE; return a; }
|
||
|
|
//--- Maximize() is protected in CAppDialog; expose it so the EA can defensively un-minimize on creation
|
||
|
|
void ForceMaximize(void) { Maximize(); }
|
||
|
|
};
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Event map - same mechanism CDialog uses internally for its own |
|
||
|
|
//| Close button (Controls\Dialog.mqh) |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
EVENT_MAP_BEGIN(CControlPanel)
|
||
|
|
ON_EVENT(ON_CLICK, m_signalsBtn, OnClickSignals)
|
||
|
|
ON_EVENT(ON_CLICK, m_pauseBtn, OnClickPause)
|
||
|
|
ON_EVENT(ON_CLICK, m_stopBtn, OnClickStop)
|
||
|
|
ON_EVENT(ON_CLICK, m_saveBtn, OnClickSave)
|
||
|
|
ON_EVENT(ON_CLICK, m_loadBtn, OnClickLoad)
|
||
|
|
ON_EVENT(ON_CLICK, m_resetBtn, OnClickReset)
|
||
|
|
EVENT_MAP_END(CAppDialog)
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CControlPanel::Create(const long chart, const string name, const int subwin,
|
||
|
|
const int x1, const int y1, const int x2, const int y2)
|
||
|
|
{
|
||
|
|
if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2))
|
||
|
|
{
|
||
|
|
Print("CControlPanel: CAppDialog::Create() failed, error " + IntegerToString(GetLastError()));
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if(!Caption("Warrior EA Control Panel"))
|
||
|
|
{
|
||
|
|
Print("CControlPanel: Caption() failed, error " + IntegerToString(GetLastError()));
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if(!CreateButtons())
|
||
|
|
return false;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CControlPanel::CreateOneButton(CButton &btn, const string name, const int y, const string text)
|
||
|
|
{
|
||
|
|
if(!btn.Create(m_chart_id, m_name + name, m_subwin, CP_MARGIN, y, CP_PANEL_W - CP_MARGIN, y + CP_BTN_H))
|
||
|
|
{
|
||
|
|
Print("CControlPanel: button '" + name + "' Create() failed, error " + IntegerToString(GetLastError()));
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if(!btn.Text(text))
|
||
|
|
{
|
||
|
|
Print("CControlPanel: button '" + name + "' Text() failed, error " + IntegerToString(GetLastError()));
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if(!Add(btn))
|
||
|
|
{
|
||
|
|
Print("CControlPanel: button '" + name + "' Add() failed, error " + IntegerToString(GetLastError()));
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CControlPanel::CreateButtons(void)
|
||
|
|
{
|
||
|
|
int y = CP_MARGIN;
|
||
|
|
if(!CreateOneButton(m_signalsBtn, "Signals", y, "Hide Signals"))
|
||
|
|
return false;
|
||
|
|
y += CP_ROW_H;
|
||
|
|
if(!CreateOneButton(m_pauseBtn, "Pause", y, "Pause Training"))
|
||
|
|
return false;
|
||
|
|
y += CP_ROW_H;
|
||
|
|
if(!CreateOneButton(m_stopBtn, "Stop", y, "Stop Training"))
|
||
|
|
return false;
|
||
|
|
y += CP_ROW_H;
|
||
|
|
if(!CreateOneButton(m_saveBtn, "Save", y, "Save Weights Now"))
|
||
|
|
return false;
|
||
|
|
y += CP_ROW_H;
|
||
|
|
if(!CreateOneButton(m_loadBtn, "Load", y, "Load Weights From Disk"))
|
||
|
|
return false;
|
||
|
|
y += CP_ROW_H;
|
||
|
|
if(!CreateOneButton(m_resetBtn, "Reset", y, "Delete && Reset Weights"))
|
||
|
|
return false;
|
||
|
|
if(!m_resetBtn.ColorBackground(clrDarkRed) || !m_resetBtn.Color(clrWhite))
|
||
|
|
return false;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|