English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
CChartObject 클래스 기반의 새로운 GUI 위젯 설계 및 구현

CChartObject 클래스 기반의 새로운 GUI 위젯 설계 및 구현

MetaTrader 5지표 | 4 8월 2021, 16:41
61 0
investeo
investeo

소개

이전 GUI 인터페이스가 있는 반자동 Expert Advisor에 대한 글을 작성한 후 더 복잡한 지표와 Expert Advisor에 대한 몇 가지 새로운 기능으로 인터페이스를 향상시키는 것이 바람직하다는 것이 밝혀졌습니다. MQL5 표준 라이브러리 클래스에 익숙해 진 후 새로운 위젯을 구현했습니다.

이 글에서는 GUI 개체에 대해 MQL5 표준 라이브러리 클래스를 사용하는 프로세스와 CChartObjectEdit 클래스 (CChartObjectProgressBar, CChartObjectSpinner 및 CChartEditTable)에서 파생된 새 클래스를 구현하는 방법에 대해 설명합니다. CChartEditTable 클래스는 객체의 동적 2 차원 배열을 사용합니다. 이것은 MQL5에서 객체의 동적 2D 배열을 구현하는 방법에 대한 작업 예제입니다.

 

1. CChartObject 및 그 자손

표준 MQL5 라이브러리 클래스를 사용하지 않는 경우 개체 함수를 사용하여 차트에 개체를 만들고 유지 관리해야 합니다.

객체는 ObjectCreate() 함수로 생성되고 객체 유형은 ENUM_OBJECT 값으로 ObjectCreate() 함수에 전달됩니다. 차트의 모든 개체에는 Integer, Double 또는 String 유형일 수있는 고유한 속성이 있습니다. 모든 속성은 전용 함수를 통해 설정 및 검색됩니다. ObjectGetInteger(), ObjectSetInteger(), ObjectGetDouble(), ObjectSetDouble(), ObjectGetString(), ObjectSetString(). 주어진 차트에서 개체 삭제, 이동계산 기능도 있습니다. 

MQL5의 OOP 패러다임으로 인해 CChartObject 클래스와 그 자손을 사용하여 다양한 차트 개체를 처리 할 수 ​​있습니다.

CChartObject 클래스는 차트에 넣을 수 있는 그래픽 개체의 기본 클래스입니다. 아래 CChartObject에 대한 기본 상속 다이어그램을 참조하십시오.

 

CChartObject 클래스의 상속 다이어그램 

그림 1. CChartObject 클래스의 상속 다이어그램


보시다시피 오른쪽 하단에 작은 삼각형으로 표시된 클래스가 몇 개 있습니다.

이들은 다른 클래스의 부모인 클래스입니다. 기본적으로 자손 클래스는 개체에서 작동하는 새 변수와 메소드를 추가하여 기본 클래스의 가능성을 향상시킵니다. 또한 Create() 및 Type() 메소드에서 파생 개체를 만들고 해당 형식을 반환하는 방법이 다를 수 있습니다

예를 들어 보여 드리겠습니다. CChartObjectTrend 클래스는 CChartObjectTrendByAngle, CChartObjectChannel, CChartObjectStdDevChannel, CChartObjectRegressionCChartObjectPitchfork 클래스의 부모입니다.

CChartObjectTrend는 속성 OBJPROP_RAY_RIGHT OBJPROP_RAY_LEFT가 있고 다음과 같이 정의된 개체의 기본 클래스입니다.

class CChartObjectTrend : public CChartObject
  {
public:
   //--- methods of access to properties of the object
   bool              RayLeft() const;
   bool              RayLeft(bool new_sel);
   bool              RayRight() const;
   bool              RayRight(bool new_sel);
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,
                                datetime time1,double price1,datetime time2,double price2);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_TREND); }
   //--- methods for working with files
   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
  };

다른 유형의 메소드를 구별 할 수 있도록 정의에 주석이 있습니다.

객체의 속성에 액세스하는 방법은 RayLeft() 및 RayRight()입니다. 이들의 구현은 CChartObjectTrend 객체에서 작동하는 ObjectGetInteger()ObjectSetInteger() 메소드를 호출하는 것입니다

bool CChartObjectTrend::RayLeft(bool new_ray)
  {
//--- checking
   if(m_chart_id==-1) return(false);
//---
   return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_LEFT,new_ray));
  }

Create() 메소드는 차트에 개체를 만들고 첨부하는 역할을 합니다.

매개 변수 중 하나로 OBJ_TREND을 사용하여 ObjectCreate() 메소드를 호출합니다.

bool CChartObjectTrend::Create(long chart_id,string name,int window,
                                   datetime time1,double price1,datetime time2,double price2)
  {
   bool result=ObjectCreate(chart_id,name,OBJ_TREND,window,time1,price1,time2,price2);
   if(result) result&=Attach(chart_id,name,window,2);
//---
   return(result);
  }

Save() 및 Load() 메소드는 FileWriteInteger()FileLoadInteger() 함수를 사용하여 하드 드라이브에 개체 데이터를 저장하고 로드합니다.

bool CChartObjectTrend::Save(int file_handle)
  {
   bool result;
//--- checking
   if(file_handle<=0) return(false);
   if(m_chart_id==-1) return(false);
//--- writing
   result=CChartObject::Save(file_handle);
   if(result)
     {
      //--- writing value of the "Ray left" property
      if(FileWriteInteger(file_handle,(int) ObjectGetInteger(m_chart_id,m_name,
                                                        OBJPROP_RAY_LEFT),CHAR_VALUE)!=sizeof(char))
      return(false);
      //--- writing value of the "Ray right" property
      if(FileWriteInteger(file_handle,(int) ObjectGetInteger(m_chart_id,m_name, 
                                                                OBJPROP_RAY_RIGHT),CHAR_VALUE)!=sizeof(char))
       return(false);
     }
//---
   return(result);
  }

bool CChartObjectTrend::Load(int file_handle)
  {
   bool result;
//--- checking
   if(file_handle<=0) return(false);
   if(m_chart_id==-1) return(false);
//--- reading
   result=CChartObject::Load(file_handle);
   if(result)
     {
      //--- reading value of the "Ray left" property
      if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_LEFT,
                                                 FileReadInteger(file_handle,CHAR_VALUE)))return(false);
      //--- reading value of the "Ray right" property
      if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_RIGHT,
                                                 FileReadInteger(file_handle,CHAR_VALUE))) return(false);
     }
//---
   return(result);
  }

CChartObjectTrend에서 자손 클래스의 정의를 빠르게 살펴 보겠습니다.

CChartObjectTrendByAngle 클래스는 Angle() 속성 수정자를 추가하고 OBJ_TRENDBYANGLE 객체 유형을 반환합니다.

class CChartObjectTrendByAngle : public CChartObjectTrend
  {
public:
   //--- methods of access to properties of the object
   double            Angle() const;
   bool              Angle(double angle);
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,datetime time1,double price1,
                               datetime time2,double price2);
   //--- method of identifying the object
   virtual int       Type() { return(OBJ_TRENDBYANGLE); }
  };

CChartObjectChannel 클래스는 OBJ_CHANNEL 객체 유형을 반환하고 채널을 처리하기 때문에 세 쌍의 가격 / 날짜 매개 변수가 Create() 메소드에 전달됩니다.

class CChartObjectChannel : public CChartObjectTrend
  {
public:
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,datetime time1,double price1,
                               datetime time2,double price2,datetime time3,double price3);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_CHANNEL); }
  };

CChartObjectStdDevChannel 클래스는 Create() 메소드에 Deviations() 속성 마디파이어와 추가 편차 매개 변수를 추가합니다.

class CChartObjectStdDevChannel : public CChartObjectTrend
  {
public:
   //--- methods of access to properties of the object
   double            Deviations() const;
   bool              Deviations(double deviation);
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,
                           datetime time1,datetime time2,double deviation);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_STDDEVCHANNEL); }
   //--- methods for working with files
   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
  };

CChartObjectRegression 클래스는 회귀 추세선을 생성하며 Create() 및 Type() 메소드만 CChartObjectTrend 클래스의 메소드에서 재정의됩니다.

class CChartObjectRegression : public CChartObjectTrend
  {
public:
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,datetime time1,datetime time2);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_REGRESSION); }
  };

CChartObjectPitchfork 클래스는 갈퀴 유형을 처리하며 Create() 및 Type() 메소드만 변경되었습니다.

class CChartObjectPitchfork : public CChartObjectTrend
  {
public:
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,datetime time1,double price1,
                               datetime time2,double price2,datetime time3,double price3);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_CHANNEL); }
  };

 이 빠른 스캔은 다른 클래스를 기반으로 새 그래픽 객체 클래스를 작성할 때 적용되는 기본 규칙을 보여줍니다.

  • 객체 생성을 위한 Create() 메소드 변경
  • 객체 유형 반환을위한 Type() 메소드 변경
  • 속성 액세스 마디파이어 추가 

모든 규칙을 적용해야 하는 것은 아닙니다. 새 액세스 마디파이어만 추가하거나 클래스에 새 변수 및 / 또는 객체를 추가 할 수 있습니다.

더 나아가기 전에 그래픽 객체에서 CChartObject 메소드를 사용하는 방법을 설명하겠습니다.

ObjectSet 및 ObjectGet 메소드 패밀리를 사용하고 개체 속성을 사용하는 대신 CChartObject 또는 자손 개체를 선언하고 원하는 속성을 변경하는 메소드를 호출하는 것으로 충분합니다. 더 쉽게 하기 위해 일반 라벨의 예를 제공합니다. 

쓰는 대신:

void OnStart()
  {
//---
   string label_name="my_OBJ_LABEL_object";
   if(ObjectFind(0,label_name)<0)
     {
      Print("Object ",label_name," not found. Error code = ",GetLastError());
      ObjectCreate(0,label_name,OBJ_LABEL,0,0,0);           
      ObjectSetInteger(0,label_name,OBJPROP_XDISTANCE,200);
      ObjectSetInteger(0,label_name,OBJPROP_YDISTANCE,300);
      ObjectSetInteger(0,label_name,OBJPROP_COLOR,White);
      ObjectSetString(0,label_name,OBJPROP_TEXT,UP);
      ObjectSetString(0,label_name,OBJPROP_FONT,"Wingdings");
      ObjectSetInteger(0,label_name,OBJPROP_FONTSIZE,10);
      ObjectSetDouble(0,label_name,OBJPROP_ANGLE,-45);
      ObjectSetInteger(0,label_name,OBJPROP_SELECTABLE,false);
      ChartRedraw(0);                                      
     }
  }

OOP 패러다임을 사용하여 구현할 수 있습니다.

1. CChartObjectLabel 개체 선언:

CChartObjectLabel label;

2. 개체에서 작동: 

int OnInit()
  {
//---
   label.Create(0, label_name, 0, 0);
   label.X_Distance(200);
   label.Y_Distance(300);
   label.Color(White);
   label.Description(UP);
   label.Font("Wingdings");
   label.FontSize(10);
   label.Angle(-45);
   label.Selectable(false);
//---
   return(0);
  }

보시다시피 주요 차이점은 우리가 더 이상 label_ name 문자열에서 작동하지 않는다는 것입니다. 

string label_name="my_OBJ_LABEL_object";

label_name을 하나로 사용하여 ObjectSetInteger(), ObjectGetInteger(), ObjectSetDouble(), ObjectGetDouble() 함수를 호출합니다. 그러나 우리는 CChartObjectLabel 객체를 선언하고 그 메소드를 사용합니다. 이것은 기억하기 간단 할 뿐만 아니라 구현하기에 논리적 일뿐만 아니라 쓰기도 더 빠릅니다.

MQL5 코드 편집기는 객체 인스턴스 뒤에 점 (.)을 넣을 때 코드 완성 기능을 제공합니다. 주어진 속성을 설정하거나 가져 오기 위해 어떤 OBJPROP 속성을 ​​넣을지 보기 위해 MQL5 문서를 앞뒤로 탐색 할 필요가 없습니다.

앞서 설명한 CChartObjectTrend 클래스의 경우와 유사하게 광선을 왼쪽 또는 오른쪽으로 가져 오거나 설정하려면 CChartObjectTrend 객체를 선언하고 RayRight() 또는 RayLeft() 메소드를 호출하면 됩니다.

CChartObjectTrend trendline;
trendline.RayRight(true); 


2. ProgressBar

우리가 구현할 첫 번째 위젯은 ProgressBar입니다. 진행률 표시 줄은 일부 작업의 진행률을 0에서 x %까지 표시합니다.

더 강력하게 만들기 위해 최대 값을 100으로 제한하지 않고 양의 정수 값으로 제한하겠습니다. 진행률 값에 따라 크기를 변경할 컬러 스트립이 필요합니다. 가장 먼저 떠오르는 것은 두 개의 직사각형을 사용하는 것이지만 다른 경로를 사용했습니다. 다른 배경색을 가진 두 개의 CChartObjectEdit 개체를 다른 내부에 사용하는 것입니다.

코딩을 단순화하고 진행률 표시 줄에 값을 표시 할 수있는 텍스트를 추가합니다. 필요에 따라 진행률 표시 줄이 수평 또는 수직 일 수 있다면 좋을 것입니다.


2.1. ProgressBar 구현

CChartObjectProgress 클래스는 CChartObjectEdit 클래스에서 파생됩니다.

m_value, m_min, m_max라는 값에 대한 값과 제약 조건을 유지하기 위해 개인 내부 변수를 추가했습니다.

진행률 표시 줄의 방향은 정수 값으로 설정되며 m_direction 변수로 유지됩니다. 색상은 m_color 변수에 의해 유지됩니다. Type() 메소드는 OBJ_EDIT 값을 반환합니다. 어쨌든 우리의 목적으로 인식되는 값이 없기 때문입니다. 클래스 정의 내에서 CChartObjectEdit m_bar 변수를 볼 수 있습니다. 이것은 m_value에 따라 크기가 변경되는 내부 바입니다. 추가 변수 m_name 및 m_chart는 내부적으로 m_bar 변수 값을 보유합니다.

class CChartObjectProgressBar : public CChartObjectEdit
  {
private:
   int               m_value;
   int               m_min;
   int               m_max;
   int               m_direction;
   color             m_color;
   CChartObjectEdit  m_bar;
   string            m_name;
   long              m_chart_id;

public:
   int               GetValue();
   int               GetMin();
   int               GetMax();

   void              SetValue(int val);
   void              SetMin(int val);
   void              SetMax(int val);

   void              SetColor(color bgcol,color fgcol);
   bool              Create(long chart_id,string name,int window,int X,int Y,
                           int sizeX,int sizeY,int direction);

   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_EDIT); }
};

Create() 메소드는 ProgressBar 객체를 만들어 차트에 첨부합니다.

수직 바가 그려진 경우 Y 변수가 sizeY 변수에서 차감되는 것을 알 수 있습니다. 이는 일반적으로 CChartObjectEdit이 위에서 아래로 그려지고 내부 사각형을 아래에서 위로 그리려고 하기 때문입니다.

bool CChartObjectProgressBar::Create(long chart_id,string name,int window,int X,int Y,
                                          int sizeX,int sizeY,int direction=0)
  {
   bool result=ObjectCreate(chart_id,name,(ENUM_OBJECT)Type(),window,0,0,0);

   m_name=name;
   m_chart_id=chart_id;
   m_direction=direction;

   if(direction!=0)
     {
      Y=Y-sizeY;
     }

   ObjectSetInteger(chart_id,name,OBJPROP_BGCOLOR,White);
   ObjectSetInteger(chart_id,name,OBJPROP_COLOR,White);
   ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false);
   ObjectSetInteger(chart_id,name,OBJPROP_READONLY,true);

   result&=m_bar.Create(chart_id,name+"m_bar",window,X,Y,sizeX,sizeY);
   m_bar.Color(White);
   m_bar.ReadOnly(true);
   m_bar.Selectable(false);

//---
   if(result) result&=Attach(chart_id,name,window,1);
   result&=X_Distance(X);
   result&=Y_Distance(Y);
   result&=X_Size(sizeX);
   result&=Y_Size(sizeY);
//---
   return(result);
  }

SetColor() 메소드는 두 사각형에 배경색과 전경색을 설정합니다.

void CChartObjectProgressBar::SetColor(color bgCol,color fgCol=White)
  {
   m_color=bgCol;
   m_bar.BackColor(m_color);
   m_bar.Color(fgCol);
  }

SetValue() 메소드는 m_val 값을 설정하고 내부 사각형 객체 크기를 다시 계산합니다.

가로 및 세로 바의 크기는 다르게 계산됩니다.

void CChartObjectProgressBar::SetValue(int val)
  {
   if(m_direction==0) // horizontal ProgressBar
     {
      double sizex=(double)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XSIZE,0);

      double stepSize=sizex/(m_max-m_min);

      m_value=val;
      m_bar.Create(m_bar.ChartId(),m_bar.Name(),m_bar.Window(),
                   m_bar.X_Distance(),m_bar.Y_Distance(),(int)MathFloor(stepSize*m_value),m_bar.Y_Size());
        } else {
      double sizey=(double)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YSIZE,0);

      double stepSize=sizey/(m_max-m_min);
      m_value=val;
      m_bar.Create(m_bar.ChartId(),m_bar.Name(),m_bar.Window(),
                   m_bar.X_Distance(),(int)(this.Y_Distance()+sizey-MathFloor(stepSize*m_value)),
                   m_bar.X_Size(),(int)MathFloor(stepSize*m_value));

     }

   m_bar.Description(IntegerToString(m_value));
  }


2.2. ProgressBar 데모

CChartObjectProgressBar 클래스를 이미 구현했으므로 이제 실제로 작동하는 것을 볼 때입니다.

차트에 새 진행률 표시 줄을 배치하려면 CChartObjectProgressBar 개체를 선언하고 Create() 및 적절한 속성 메소드를 사용하면 됩니다.

progressBar.Create(0, "progressBar1", 0, 10, 10, 200, 40);
progressBar.SetColor(YellowGreen);
progressBar.SetMin(0);
progressBar.SetMax(100);
progressBar.SetValue(0);

저는 차트에 6개의 다른 진행률 표시 줄을 놓고 화면에서 개체를 클릭 한 후 값을 변경하는 데모 Expert Advisor를 작성했습니다.

이 데모와 기타 데모에 대한 전체 소스 코드는 첨부 파일에 있습니다. 아래 프레젠테이션을 참조하십시오. 

 


3. 스피너

스피너 위젯은 필드와 두 개의 버튼이 포함된 위젯입니다. 버튼 중 하나를 클릭하여 편집 필드의 값을 늘리거나 줄이는 데 사용되었습니다.

객체를 디자인하는 동안 정수 값으로만 작동하고 싶지 않았기 때문에 스피너는 이중 유형으로 작동하도록 설계되었습니다. 스피너는 또한 현재 값을 증가 또는 감소시키는 값인 단계 크기를 정의할 수 있습니다. 또한 교차할 수 없는 최소값과 최대 값이 있어야 합니다.


3.1. Spinner 구현

MQL5에는 CChartObjectEdit>CChartObjectButton 클래스가 있으며 하나의 CChartObjectSpinner 클래스로 결합할 수 있습니다. CChartObjectSpinner는 CChartObjectEdit에서 상속되며 두 개의 개인 멤버 CChartObjectButton 개체를 포함합니다.

m_min 및 m_max 멤버 변수에 저장된 최소 및 최대 m_value에 대한 제약 조건이 있으며 m_precision 변수는 n 번째 숫자 값에 계산 정밀도를 저장합니다. 필요한 방법은 값 액세스, 증감 단계 크기 및 설정 값 설정입니다.

class CChartObjectSpinner: public CChartObjectEdit
  {

private:
   double            m_value;
   double            m_stepSize;
   double            m_min;
   double            m_max;
   int               m_precision;
   string            m_name;
   long              m_chart_id;
   CChartObjectButton m_up,m_down;

public:
   double            GetValue();
   double            GetMin();
   double            GetMax();

   void              SetValue(double val);
   void              SetMin(double val);
   void              SetMax(double val);

   double            Inc();
   double            Dec();

   bool              Create(long chart_id,string name,int window,int X,int Y,
                               int sizeX,int sizeY,double val,double stepSize,int precision);

   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_EDIT); }
   
  };

Create() 메소드는 새 CChartObjectSpinner를 만들고 차트에 연결합니다.

CChartObjectEdit의 오른쪽에 생성된 두 개의 CChartObjectButtons가 있으며, 각각 CChartObjectEdit 높이의 절반 높이를 가집니다.

증가 버튼에는 '+' 기호와 감소 버튼 '-' 기호가 있습니다.

bool CChartObjectSpinner::Create(long chart_id,string name,int window,int X,int Y,
                                     int sizeX,int sizeY,double val=0.0,double stepSize=1.0,int precision=8)
  {
   bool result=ObjectCreate(chart_id,name,(ENUM_OBJECT)Type(),window,0,0,0);

   m_name=name;
   m_chart_id=chart_id;
   m_value=val;
   m_stepSize=stepSize;
   m_precision=precision;

   ObjectSetInteger(chart_id,name,OBJPROP_BGCOLOR,White);
   ObjectSetInteger(chart_id,name,OBJPROP_COLOR,Black);
   ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false);
   ObjectSetInteger(chart_id,name,OBJPROP_READONLY,true);

   result&=m_up.Create(chart_id, name+"_up", window, X+sizeX, Y, 15, sizeY/2);
   result&=m_down.Create(chart_id, name+"_down", window, X+sizeX, Y+sizeY/2, 15, sizeY/2);
   m_up.Description("+");
   m_down.Description("-");
   ObjectSetString(chart_id,name,OBJPROP_TEXT,0,(DoubleToString(m_value,precision)));

//---
   if(result) result&=Attach(chart_id,name,window,1);
   result&=X_Distance(X);
   result&=Y_Distance(Y);
   result&=X_Size(sizeX);
   result&=Y_Size(sizeY);
//---
   return(result);
  }

SetValue() 메소드는 개인 변수 m_value가 <m_min, m_max> 범위 내에 있다는 조건으로 두 배 값으로 설정합니다.

void CChartObjectSpinner::SetValue(double val)
  {
   if(val>=m_min && val<=m_max) m_value=val;
   this.Description(DoubleToString(m_value));
  }

Inc() 메소드는 주어진 단계 크기만큼 값을 증가 시키지만 m_max 값 이하입니다.

주어진 정밀도와 double 값을 비교하기 위해 NormalizeDouble() 함수를 사용해야 했습니다.

double CChartObjectSpinner::Inc(void)
  {
   if(NormalizeDouble(m_max-m_value-m_stepSize,m_precision)>0.0) m_value+=m_stepSize;
   else m_value=m_max;
   this.Description(DoubleToString(m_value, m_precision));
   m_up.State(false);
   return m_value;
  }

Dec() 메소드는 주어진 단계 크기만큼 값을 감소 시키지만 m_min 값 이상입니다.

double CChartObjectSpinner::Dec(void)
  {
   if(NormalizeDouble(m_value-m_stepSize-m_min,m_precision)>0.0)
      m_value-=m_stepSize; else m_value=m_min;
   this.Description(DoubleToString(m_value,m_precision));
   m_down.State(false);

   return m_value;
  }


3.2. 스피너 데모

스피너 개체를 테스트 할 시간입니다. 이를 사용하기 위해서는 CChartObjectSpinner 객체를 선언하고 Create(), SetMin() 및 SetMax() 메소드를 사용하면 됩니다.

   spinner.Create(0, "spinner1", 0, 10, 10, 200, 40, 0.0, 0.4);
   spinner.SetMin(0);
   spinner.SetMax(100);

세 개의 스피너 위젯을 사용하고 스피너 버튼을 클릭 한 후 모든 값을 추가하는 데모를 준비했습니다.

이 작업은 OnChartEvent() 함수 내에서 수행됩니다.

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- Check the event by pressing a mouse button
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
     
     if (sparam=="spinner1_up") spinner.Inc();
     if (sparam=="spinner1_down") spinner.Dec();
     if (sparam=="spinner2_up") spinner2.Inc();
     if (sparam=="spinner2_down") spinner2.Dec();
     if (sparam=="spinner3_up") spinner3.Inc();
     if (sparam=="spinner3_down") spinner3.Dec();
     
     label.Description(DoubleToString(NormalizeDouble(spinner.GetValue()+spinner2.GetValue()+spinner3.GetValue(),10),10));
   
   ChartRedraw();
     }
  }

 첨부된 데모를 참조하십시오.

 

 

4. CChartObjectEditTable

많은 MTF (Multi Time Frame) Expert Advisors에는 각 시간 프레임에 대해 개별적으로 표시되는 표시기 값이 있습니다.

때때로 각 시간 프레임에는 서로 다른 색상의 사각형 또는 정사각형의 2D 테이블 형태로 표시되는 다른 표시기 설정이 있습니다. CChartObjectEditTable 클래스를 생성하여 이러한 객체의 범용 2D 테이블을 설계했습니다. 이 클래스는 2D 동적 객체 배열을 사용하기 때문에 임의의 양의 행과 열을 보유할 수 있습니다.

디자인하는 동안 각 셀의 색상을 개별적으로 정의하고 모든 셀에 다른 텍스트 문자열을 넣을 수있는 가능성을 추가하기로 결정했습니다. 셀의 크기는 같지만 높이와 너비, 셀 사이의 간격을 정의하고 싶었습니다.


4.1. CChartObjectEditTable 구현

CChartObjectEditTable 클래스는 2 차원 객체 배열에 대한 CArrayObj 포인터를 보유하고, m_rows 및 m_columns 멤버 변수는 테이블의 행과 열 수를 보유합니다.

테이블 내 모든 셀 CChartObjectEdit 개체의 접두사를 보유하는 m_baseName 멤버 변수가 있습니다. GetColor(), SetColor(), GetText(), SetText() 메소드는 원하는 셀에 색상 및 텍스트 값을 설정하고 가져 오는 데 사용됩니다. Delete() 메소드는 Create() 메소드에 의해 생성된 모든 객체를 삭제합니다.

class CChartObjectEditTable
  {

private:
   CArrayObj        *array2D;
   int               m_rows;
   int               m_cols;
   string            m_baseName;

public:

   bool              Create(long chart_id,string name,int window,int rows,int cols,int startX,int startY,
                                int sizeX,int sizeY,color Bg,int deltaX,int deltaY);
   bool              Delete();
   bool              SetColor(int row,int col,color newColor);
   color             GetColor(int row,int col);
   bool              SetText(int row,int col,string newText);
   string            GetText(int row,int col);


  };

Create() 메소드는 CChartObjectEdit 개체의 2차원 동적 테이블을 만듭니다.

MQL5에서 객체의 2D 배열을 만드는 방법을 관찰하십시오. 먼저 2D 배열에 대한 포인터를 선언한 다음 배열을 여러 CArrayObj() 객체로 채웁니다. 즉, 우리는 배열 안에 배열을 만들어냅니다. 모든 배열은 테이블 열의 홀더로 볼 수 있습니다.

각 열에는 CChartObjectEdit 개체를 포함하는 행이 포함되며 각 개체는 표시할 단일 셀입니다. 

bool CChartObjectEditTable::Create(long chart_id,string name,int window,int rows=1,int cols=1,
                                       int startX=0,int startY=0,int sizeX=15,int sizeY=15,
                                  color Bg=White,int deltaX=5,int deltaY=5)
  {
   m_rows=rows;
   m_cols=cols;
   m_baseName=name;
   int i=0,j=0;

   array2D=new CArrayObj();
   if (array2D==NULL) return false;
   
   for(j=0; j<m_cols; j++)
     {
      CArrayObj *new_array=new CArrayObj();
      if (array2D==NULL) return false;
   
      array2D.Add(new_array);
      for(i=0; i<m_rows; i++)
        {
         CChartObjectEdit *new_edit=new CChartObjectEdit();

         new_edit.Create(chart_id, name+IntegerToString(i)+":"+IntegerToString(j), window, 
                         startX+j*(sizeX+deltaX), startY+i*(sizeY+deltaY), sizeX, sizeY);
         new_edit.BackColor(Bg);
         new_edit.Color(White);
         new_edit.Selectable(false);
         new_edit.ReadOnly(true);
         new_edit.Description("");
         new_array.Add(new_edit);
        }
     }

   return true;
  }

SetColor() 메소드는 단일 셀의 색상을 설정합니다. 처음에는 열 배열을 찾은 다음 열 배열에서 n 번째 요소를 찾습니다.

그런 다음 BackColor() 메소드를 호출하여 요소의 색상 값을 변경합니다.

bool CChartObjectEditTable::SetColor(int row,int col,color newColor)
  {
   CArrayObj *sub_array;
   CChartObjectEdit *element;

   if((row>=0 && row<m_rows) && (col>=0 && col<m_cols))
     {
      if(array2D!=NULL)
        {
         sub_array=array2D.At(col);
         element=(CChartObjectEdit*)sub_array.At(row);
         element.BackColor(newColor);

         return true;
        }
     }

   return false;
  }

GetColor() 메소드는 SetColor() 메소드와 동일한 알고리즘을 사용하여 셀을 찾지만 주어진 셀의 색상 값을 반환합니다. 

color CChartObjectEditTable::GetColor(int row,int col)
  {
   CArrayObj *sub_array;
   CChartObjectEdit *element;

   if((row>=0 && row<m_rows) && (col>=0 && col<m_cols))
     {
      if(array2D!=NULL)
        {
         sub_array=array2D.At(col);
         element=(CChartObjectEdit*)sub_array.At(row);
         return element.BackColor();
        }
     }

   return NULL;
  }

SetText() 메소드는 요소를 찾고 Description() 메소드를 호출하여 텍스트 값을 설정합니다.

bool CChartObjectEditTable::SetText(int row,int col,string newText)
  {
   CArrayObj *sub_array;
   CChartObjectEdit *element;

   if((row>=0 && row<m_rows) && (col>=0 && col<m_cols))
     {
      if(array2D!=NULL)
        {
         sub_array=array2D.At(col);
         element=(CChartObjectEdit*)sub_array.At(row);
         element.Description(newText);

         return true;
        }
     }

   return false;
  }

Delete() 메소드는 Create() 메소드에 의해 생성된 모든 객체를 삭제합니다.

처음에는 모든 열 배열을 지우고 메모리에서 array2D 객체를 삭제합니다.

bool CChartObjectEditTable::Delete(void)
  {
   for(int j=0; j<m_cols; j++)
     {
      CArrayObj *column_array=array2D.At(j);
      column_array.Clear();
      delete column_array;
     }
   delete array2D;
   return true;
  }


4.2. CChartObjectEditTable 데모

CChartObjectEditTable 위젯을 사용하려면 CChartEditTable 객체를 선언하고 테이블에 포함되어야 하는 행과 열 수를 나타내는 매개 변수와 함께 Create() 메소드를 사용해야 합니다.

그런 다음 속성 수정자를 사용하여 셀의 색상과 텍스트를 간단히 변경할 수 있습니다.

table.Create(0,"t",0,1,10,10,10,15,15,Yellow);
table.SetColor(2,2,Red);
table.SetText(2,2,"2");

CChartObjectEditTable 개체 사용 가능성을 보여주는 스크립트를 참조하십시오.

스크립트의 소스 코드는 첨부 파일에 있습니다.

 


결론

이 글에서 CChartObject 클래스에서 파생 된 새 차트 위젯을 만드는 프로세스를 설명하고 소개했습니다. 

구현된 위젯을 사용하는 프로세스는 매우 간단하며 몇 줄의 코드만 있으면 됩니다.

위젯을 사용하려면 Expert Advisor 또는 표시기 코드에 ChartObjectsExtControls.mqh 파일을 포함하십시오.


MetaQuotes 소프트웨어 사를 통해 영어가 번역됨
원본 기고글: https://www.mql5.com/en/articles/196

MetaTrader 5의 병렬 계산 MetaTrader 5의 병렬 계산
시간은 인류 내역을 통틀어 큰 가치로 여겨져 왔으며, 불필요하게 낭비하지 않도록 노력하고 있습니다. 이 글에서는 컴퓨터에 멀티 코어 프로세서가 있는 경우 Expert Advisor의 작업을 가속화하는 방법에 대해 설명합니다. 또한 제안된 방법의 구현에는 MQL5 외에 다른 언어에 대한 지식이 필요하지 않습니다.
사전 정의된 위험 및 R/R 비율을 기반으로 인터랙티브 반자동 드래그 앤 드롭 Expert Advisor 구축 사전 정의된 위험 및 R/R 비율을 기반으로 인터랙티브 반자동 드래그 앤 드롭 Expert Advisor 구축
일부 거래자는 모든 거래를 자동으로 실행하고 일부는 여러 지표의 출력을 기반으로 자동 및 수동 거래를 혼합합니다. 후자 그룹의 일원이기 때문에 동적으로 위험을 평가하고 차트에서 직접 가격 수준을 보상 할 수 있는 대화형 도구가 필요했습니다. 이 글에서는 사전 정의된 주식 위험 및 R/R 비율을 사용하여 대화형 반자동 Expert Advisor를 구현하는 방법을 설명합니다. Expert Advisor 위험, R/R 및 랏 크기 매개 변수는 EA 패널에서 런타임 중에 변경할 수 있습니다.
채널 그리기 - 내부 및 외부 보기 채널 그리기 - 내부 및 외부 보기
채널이 시장 분석과 이동 평균 이후 거래 결정을 위한 가장 인기있는 도구라고 말하면 과장이 아닐 것 같습니다. 채널과 그 구성 요소를 사용하는 대량의 거래 전략에 깊이 들어 가지 않고 수학적 기반과 지표의 실제 구현에 대해 논의 할 것입니다.
MQL5 트레이딩 시스템과 윌리엄 블라우의 인디케이터. 파트 1: 인디케이터 MQL5 트레이딩 시스템과 윌리엄 블라우의 인디케이터. 파트 1: 인디케이터
이 글은 윌리엄 블라우의 저서 'Momentum, Direction, and Divergence'에서 다루어진 인디케이터에 대한 소개입니다. 윌리엄 블라우의 접근법을 이용하면 수요 곡선 상의 변동을 빠르고 정확하게 계산할 수 있으며, 가격 변동 추세와 전환점을 판단하고, 노이즈를 제거할 수 있습니다. 이와 동시에 시장의 과매수/과매도 상태와 추세의 끝과 가격 움직임의 반전을 나타내는 신호를 감지할 수도 있죠.