CChartObject クラスに基づく新規GUIウィジェット設計と実装
はじめに
前稿『GUI インターフェースを使用した半自動Expert Advisor』を書いてのち、より複雑なインディケータやExpert Advisorsに新しい関数を伴うインターフェースを強化したいと思うようになりました。MQL5 標準ライブラリクラスを知ってから、新しいウィジェットを実装しました。
本稿ではGUIオブジェクトに MQL5 標準ライブラリ クラスを使用するプロセス、CChartObjectEdit クラスから派生した新しいクラスの実装法について述べます。派生クラスは CChartObjectProgressBar、 CChartObjectSpinner a、 CChartEditTableです。CChartEditTable クラスはオブジェクトの動的二次元配列を使い、これはMQL5にオブジェクトの動的二次元配列を実装する方法の動作例です。
1. CChartObject とその派生クラス
標準MQL5 ライブラリクラスを使用しなければ、 チャート上にオブジェクトを作成し保持するのにオブジェクト関数 を使う必要があります。
オブジェクトは ObjectCreate() 関数を用いて作成され、オブジェクトタイプはENUM_OBJECT 値としてObjectCreate() 関数に渡されます。 チャート上のすべてのオブジェクトは独自のプロパティを持ち、それは 整数、ダブル値、または文字列 タイプです。プロパティはすべて設定され、専用の関数で読み出されます。: ObjectGetInteger()、 ObjectSetInteger()、 ObjectGetDouble()、ObjectSetDouble()、 ObjectGetString()、ObjectSetString()です。また与えられるチャートには、削除、移動、 カウント オブジェクトもあります。
MQL5のOOP パラダイムにより、チャートオブジェクトの処理は CChartObject クラスとその派生クラスによって行われます。
CChartObject クラスはチャートに載せられるグラフィックオブジェクトの基本クラスです。以下で CChartObject の基本継承図を確認ください。
図1 CChartObject クラスの継承図
見てのとおり、右下角に小さな三角印のついたクラスがいくつかあります。
これらはその他クラスの親クラスです。基本的に、派生クラスはオブジェクト上で処理を行う変数やメソッドを追加することで基本クラスの機能を高めます。また、オブジェクトを作成し、そのタイプを返すのに Create() メソッドと Type() メソッドでは相違があります。
例で見ていきます。 CChartObjectTrend クラスは以下の基本クラスです。: CChartObjectTrendByAngle、 CChartObjectChannel、 CChartObjectStdDevChannel、 CChartObjectRegression 、 CChartObjectPitchfork classes。
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 オブジェクトタイプを返します。また、これはチャネルを処理するので、3つの 価格/日付ペアが 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 クラスは Deviations() プロパティ モディファイアや、さらにCreate() メソッドの偏差値パラメータを追加します。
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 ラベル
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までに制限せず、任意の正の整数値とします。進捗値に従いサイズを変える色つきの細長い表示が必要です。まず頭に浮かぶのが、長方形を2つ使うことですが、私は別の方法を選択しました。CChartObjectEdit オブジェクトを2つ使うのです。一つはもう一つの内側に配置しそれぞれ別の背景色にします。
これでコードを書くことや値を表示するため進捗バーの内側に入れるテキストを追加することが簡素化されます。必要に応じて進捗バーは水平、または垂直とするとよいでしょう。
2.1. ProgressBar の実装
CChartObjectEdit クラスからCChartObjectProgress クラスを派生させます。
値: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 変数から Y 変数が引き算されるのがおわかりでしょう。これは通常、上から下に 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 value を設定し、内側の長方形のオブジェクトサイズを計算します。
サイズは横向きの場合と縦向きの場合で計算の仕方が異なります。
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. スピナー
スピナーウィジェットはフィールドとボタンを2つ持つウィジェットです。ボタンの一つをクリックすることで、編集フィールドの値をインクリメントまたはデクリメントするのに使われます。
オブジェクト設計中は整数値のみで操作をしたくありませんでしたので、ダブルタイプ値で操作するのに「スピナー」を作成しました。「スピナー」はまたステップサイズを定義する機能もあります。それは現在値をインクリメントまたはデクリメントする値です。また、それには越えてはいけない最小値および最大値もあります。
3.1. 「スピナー」の実装
MQL5 には CChartObjectEdit クラスおよび CChartObjectButton クラスがあり、それらはCChartObjectSpinner クラスとして一つに合成することが可能です。CChartObjectSpinner は CChartObjectEdit から派生し、プライベートメンバCChartObjectButton オブジェクトを2つ持ちます。
m_min および m_max メンバ変数に格納された最大、最小のm_value には制約があり、m_precision 変数が n番目の digit値への計算精度を格納します。必要なメソッドは値のアクセス用で、インクリメントとデクリメントのステップサイズを設定し、値を設定します。
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 が2つあります。それぞれ 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 値以上にはなりません。
与えられた精度とダブル値を比較するのに 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);
私は「スピナー」ウィジェットを3つ使い、「スピナー」ボタンのどれかが押されると値を加えるデモを準備しました。
これは 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) Expert Advisors の多くには、個別に時間枠を表示するインディケータ値があります。
書く時間枠は色の異なる長方形や正方形の二次元テーブル形式で表示される異なるインディケータ設定を持つことがあります。私は CChartObjectEditTable クラスを作成し、そのようなオブジェクトの汎用的な2Dテーブルをデザインしました。オブジェクトの2D動的配列を使用しているので、このクラスは行列の任意量を保持することが可能です。
設計中、私はそれぞれのセル色を個別に定義し、すべてのセルに異なるテキスト文字列を入れる機能を追加することにしました。セルサイズは同一ですが、高さと幅、またセル間のスペースは定義したいと思いました。
4.1. CChartObjectEditTable の実装
CChartObjectEditTable クラスにはオブジェクトの二次元配列に対する 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 オブジェクトの二次元動的テーブルを作成します。
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 Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/196
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索