
CChartObject 클래스 기반의 새로운 GUI 위젯 설계 및 구현
소개
이전 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에 대한 기본 상속 다이어그램을 참조하십시오.
그림 1. CChartObject 클래스의 상속 다이어그램
보시다시피 오른쪽 하단에 작은 삼각형으로 표시된 클래스가 몇 개 있습니다.
이들은 다른 클래스의 부모인 클래스입니다. 기본적으로 자손 클래스는 개체에서 작동하는 새 변수와 메소드를 추가하여 기본 클래스의 가능성을 향상시킵니다. 또한 Create() 및 Type() 메소드에서 파생 개체를 만들고 해당 형식을 반환하는 방법이 다를 수 있습니다
예를 들어 보여 드리겠습니다. CChartObjectTrend 클래스는 CChartObjectTrendByAngle, CChartObjectChannel, CChartObjectStdDevChannel, CChartObjectRegression 및 CChartObjectPitchfork 클래스의 부모입니다.
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 동적 객체 배열을 사용하기 때문에 임의의 양의 행과 열을 보유할 수 있습니다.
디자인하는 동안 각 셀의 색상을 개별적으로 정의하고 모든 셀에 다른 텍스트 문자열을 넣을 수있는 가능성을 추가하기로 결정했습니다. 셀의 크기는 같지만 높이와 너비, 셀 사이의 간격을 정의하고 싶었습니다.
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



