How to bond a CGraphics chart to a CAppDialog window

 

Hi,

I can't figure out how to bond a CGraphics chart to a CAppDialog window so that it follows the window when it is moved.

The following is a minimal code:

//+------------------------------------------------------------------+
//|                                                        Chart.mq5 |
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| File imports                                                     |
//+------------------------------------------------------------------+
#include "Gui.mqh"


//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
CGui Gui;


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void) {
  Gui.create_app();
  Gui.Run();
    
  return(INIT_SUCCEEDED);
}
  
  
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
  Gui.Destroy(reason);
}


//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
}
  
  
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam) {
  Gui.ChartEvent(id, lparam, dparam, sparam);
}
//+------------------------------------------------------------------+
//|                                                          Gui.mqh |
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| File imports                                                     |
//+------------------------------------------------------------------+
#include <Controls\Dialog.mqh>
#include <Graphics\Graphic.mqh>


//+------------------------------------------------------------------+
//| Constant definitions                                             |
//+------------------------------------------------------------------+
// App dialog dimensions
#define X1 (0)
#define Y1 (0)
#define X2 (1000)
#define Y2 (500)


//+------------------------------------------------------------------+
//| Class CGui                                                       |
//+------------------------------------------------------------------+
class CGui : public CAppDialog {
  private:
    CGraphic chart;
    static const double data_1[];
    static const double data_2[];
  public:
    CGui();
    ~CGui();
    virtual bool create_app();
  protected:
    bool create_chart();
};
 

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CGui::CGui() {}

static const double CGui::data_1[] = {1, 3, 5, 2, 0, -3, -5, -1, 1, 4};
static const double CGui::data_2[] = {-1, 2, 6, 7, 4, 1, -1, -2, 0, 2};


//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CGui::~CGui() {
  chart.Destroy();
}


//+------------------------------------------------------------------+
//| Create the main application dialog.                              |
//+------------------------------------------------------------------+
bool CGui::create_app() {
  CAppDialog::Create(0, MQLInfoString(MQL_PROGRAM_NAME), 0, X1, Y1, X2, Y2);
  create_chart();
  
  return(true);
}


//+------------------------------------------------------------------+
//| Create button chart.                                             |
//+------------------------------------------------------------------+
bool CGui::create_chart() {
  int x1 = 50;
  int y1 = 50;
  int x2 = x1 + X2 - 100;
  int y2 = y1 + Y2 - 100;
  chart.Create(0, "chart", 0, x1, y1, x2, y2);

  CCurve *curve1 = chart.CurveAdd(data_1, clrBlue, CURVE_LINES);
  CCurve *curve2 = chart.CurveAdd(data_2, clrRed, CURVE_LINES);
  chart.CurvePlotAll();
  chart.Update();
  
  return(true);
}
 

First, look here - https://www.mql5.com/en/articles/6603, in the section "The "chart" control (CPlot)".

Then you may find an update here - https://www.mql5.com/en/articles/7656

Applying OLAP in trading (part 2): Visualizing the interactive multidimensional data analysis results
Applying OLAP in trading (part 2): Visualizing the interactive multidimensional data analysis results
  • www.mql5.com
In this article, we consider the creation of an interactive graphical interface for an MQL program, which is designed for the processing of account history and trading reports using OLAP techniques. To obtain a visual result, we will use maximizable and scalable windows, an adaptive layout of rubber controls and a new control for displaying diagrams. To provide the visualization functionality, we will implement a GUI with the selection of variables along coordinate axes, as well as with the selection of aggregate functions, diagram types and sorting options.
 

Thank you for the links. The example Plot.mqh, in the first link, was worth reading.
Below is the solution to my question.

//+------------------------------------------------------------------+
//|                                                     AppChart.mq5 |
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| File imports                                                     |
//+------------------------------------------------------------------+
#include "Gui.mqh"


//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
input ENUM_CURVE_TYPE CURVE_TYPE = CURVE_LINES;

CGui Gui;


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
  if (!Gui.Create(0, "AppChart", 0, 50, 50, 850, 650, CURVE_TYPE)) {
    return(INIT_FAILED);
  }
  
  if (!Gui.Run()) {
    return(INIT_FAILED);
  }

  return(INIT_SUCCEEDED);
}


//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
  Gui.Destroy(reason);
}


//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
}


//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, 
                  const long &lparam, 
                  const double &dparam, 
                  const string &sparam) {
  Gui.ChartEvent(id, lparam, dparam, sparam);
}
//+------------------------------------------------------------------+
//|                                                          Gui.mqh |
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| File imports                                                     |
//+------------------------------------------------------------------+
#include <Controls\Dialog.mqh>
#include "Core.mqh"


//+------------------------------------------------------------------+
//| Class CGui                                                       |
//+------------------------------------------------------------------+
class CGui: public CAppDialog {
  private:
    CPlot Plot;

  public:
    CGui();
    ~CGui();

    virtual bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2, const ENUM_CURVE_TYPE type);
    virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
};


//+------------------------------------------------------------------+
//| Event Handling                                                   |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CGui)
EVENT_MAP_END(CAppDialog)


//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CGui::CGui() {}


//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CGui::~CGui() {}


//+------------------------------------------------------------------+
//| Create the main application dialog.                              |
//+------------------------------------------------------------------+
bool CGui::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2, const ENUM_CURVE_TYPE type) {
  if (!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) {
    return(false);
  }
  
  if (!Plot.Create(m_chart_id, m_name + "Plot", m_subwin, 0, 0, ClientAreaWidth(), ClientAreaHeight())) {
    return(false);
  }
  
  if (!Add(Plot)) {
      return(false);
  }
  
  double data_1[] = {1, 3, 5, 2, 0, -3, -5, -1, 1, 4};
  double data_2[] = {-1, 3, 6, 7, 4, 1, -1, -2, 0, 2};
  
  Plot.CurveAdd(data_1, clrRed, type, "data 1");
  Plot.CurveAdd(data_2, clrBlue, type, "data 2");
  Plot.Refresh();
  
  return(true);
}
//+------------------------------------------------------------------+
//|                                                         Core.mqh |
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| File imports                                                     |
//+------------------------------------------------------------------+
#include <Controls\WndClient.mqh>
#include <Graphics\Graphic.mqh>


//+------------------------------------------------------------------+
//| Class CGraph                                                     |
//+------------------------------------------------------------------+
class CGraph: public CGraphic {
  protected:
    long m_chart_id;  // chart ID

  public:
    CGraph();
    ~CGraph();
    
    virtual bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2);
    virtual bool Shift(const int dx, const int dy);
    virtual bool Show(void);
    virtual bool Hide(void);
};


//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CGraph::CGraph() {}


//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CGraph::~CGraph() {}


//+------------------------------------------------------------------+
//| Create graphic                                                   |
//+------------------------------------------------------------------+
bool CGraph::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) {
  if(!CGraphic::Create(chart, name, subwin, x1, y1, x2, y2)) {
    return(false);
  }
  
  m_chart_id = chart;
  
  return(true);
}


//+------------------------------------------------------------------+
//| Show graphic                                                     |
//+------------------------------------------------------------------+
bool CGraph::Show(void) {
    string obj_name = ChartObjectName();
    
    if (obj_name == NULL || ObjectFind(m_chart_id, obj_name) < 0) {
      return(false);
    }
    
    if (!ObjectSetInteger(m_chart_id, obj_name, OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS)) {
      return(false);
    }
    
    Update(false);
    
    return(true);
}


//+------------------------------------------------------------------+
//| Hide graphic                                                     |
//+------------------------------------------------------------------+
bool CGraph::Hide(void) {
  string obj_name = ChartObjectName();
  
  if (obj_name == NULL || ObjectFind(m_chart_id, obj_name) < 0) {
    return(false);
  }
  
  return(ObjectSetInteger(m_chart_id, obj_name, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS));
}


//+------------------------------------------------------------------+
//| Shift graphic                                                    |
//+------------------------------------------------------------------+
bool CGraph::Shift(const int dx, const int dy) {
  string obj_name = ChartObjectName();
  
  if (obj_name == NULL || ObjectFind(m_chart_id, obj_name) < 0) {
    return(false);
  }

  int x = (int)ObjectGetInteger(m_chart_id, obj_name, OBJPROP_XDISTANCE) + dx;
  int y = (int)ObjectGetInteger(m_chart_id, obj_name, OBJPROP_YDISTANCE) + dy;
  
  if (!ObjectSetInteger(m_chart_id, obj_name, OBJPROP_XDISTANCE, x)) {
    return(false);
  }
  
  if (!ObjectSetInteger(m_chart_id, obj_name, OBJPROP_YDISTANCE, y)) {
    return(false);
  }

  return(true);
}


//+------------------------------------------------------------------+
//| Class CPlot                                                      |
//+------------------------------------------------------------------+
class CPlot: public CWndClient {
  private:
    CGraph *m_graphic;

  public:
    CPlot();
    ~CPlot();

    bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2);
    bool Refresh();
    
    virtual void Destroy(const int reason = 0) override;
    virtual bool Shift(const int dx, const int dy) override;
    virtual bool Show(void);
    virtual bool Hide(void);

    CCurve *CurveAdd(const double &y[], const uint clr, ENUM_CURVE_TYPE type, const string name = NULL);
};


//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPlot::CPlot() {}


//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CPlot::~CPlot() {
  if(CheckPointer(m_graphic) != POINTER_INVALID) {
    m_graphic.Destroy();
    delete m_graphic;
  }
}


//+------------------------------------------------------------------+
//| Remove graphic from chart                                        |
//+------------------------------------------------------------------+
void CPlot::Destroy(const int reason = 0) {
  if (CheckPointer(m_graphic) != POINTER_INVALID) {
    m_graphic.Destroy();
    delete m_graphic;
    m_graphic = NULL;
  }
  
  CWndClient::Destroy(reason);
}


//+------------------------------------------------------------------+
//| Create window                                                    |
//+------------------------------------------------------------------+
bool CPlot::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) {
  if(!CWndClient::Create(chart, name, subwin, x1, y1, x2, y2)) {
    return(false);
  }

  int width = Width();
  int height = Height();

  string obj_name = m_name + "_0_0";
  int obj_x1 = m_rect.left;
  int obj_y1 = m_rect.top;
  int obj_x2 = obj_x1 + width;
  int obj_y2 = obj_y1 + height;

  m_graphic = new CGraph();
  if (CheckPointer(m_graphic) == POINTER_INVALID) {
    return(false);
  }
  if (!m_graphic.Create(m_chart_id, obj_name, m_subwin, obj_x1, obj_y1, obj_x2, obj_y2)) {
    return(false);
  }
  
  m_graphic.IndentUp(50);

  return(true);
}


//+------------------------------------------------------------------+
//| Plot all the curves and refresh the chart                        |
//+------------------------------------------------------------------+
bool CPlot::Refresh() {
  if (CheckPointer(m_graphic) == POINTER_INVALID) {
    return(false);
  }

  if (!m_graphic.CurvePlotAll()) {
    return(false);
  }
  
  m_graphic.Update();

  ChartRedraw(m_chart_id);

  return(true);
}


//+------------------------------------------------------------------+
//| Hide window                                                      |
//+------------------------------------------------------------------+
bool CPlot::Hide(void) {
  if(CheckPointer(m_graphic) == POINTER_INVALID) {
    return(false);
  }

  if(!m_graphic.Hide()) {
    returnfalse);
  }

  return(CWndClient::Hide());
}


//+------------------------------------------------------------------+
//| Show window                                                      |
//+------------------------------------------------------------------+
bool CPlot::Show(void) {
  if (!CWndClient::Show()) {
    return(false);
  }

  if (CheckPointer(m_graphic) == POINTER_INVALID) {
    return(false);
  }
  
  if (m_graphic.Show()) {
    return(false);
  }

  return(true);
}


//+------------------------------------------------------------------+
//| Shift window                                                     |
//+------------------------------------------------------------------+
bool CPlot::Shift(const int dx, const int dy) {
  if (CheckPointer(m_graphic) == POINTER_INVALID) {
    return(false);
  }
  
  if (!m_graphic.Shift(dx, dy)) {
    return(false);
  }

  return(CWndClient::Shift(dx, dy));
}


//+------------------------------------------------------------------+
//| Add curve to chart                                               |
//+------------------------------------------------------------------+
CCurve *CPlot::CurveAdd(const double &y[], const uint clr, ENUM_CURVE_TYPE type, const string name = NULL) {
  if (CheckPointer(m_graphic) == POINTER_INVALID) {
    return(NULL);
  }
  
  return(m_graphic.CurveAdd(y, clr, type, name));
}
chart in dialog