
DoEasyライブラリのグラフィックス(第90部): 標準グラフィカルオブジェクトのイベント基本機能
目次
概念
クライアントターミナルによって提供されるグラフィカルオブジェクトを使用する場合、これらのオブジェクトのいくつかのプロパティ値をプログラムで定義する必要性が生じることがあります。プログラムでグラフィカルオブジェクトラインの値を追跡し、たとえばラインが価格と交差した場合に埋め込みアルゴリズムを実行するかもしれません。ターミナルユーザーがグラフィッカルオブジェクトを移動すれば、線がずれるので、プログラムはこれにも対応する必要があります。ただし、プログラムは、追跡されたラインの値が変更されたことを認識するか、グラフィカルオブジェクトのプロパティ値を常に調査する必要があります。これは、リソースを大量に消費するアクションであり、そのことはヘルプで明確に述べられています。
グラフィッカルオブジェクトの変更を通知する機能があればはるかに便利です。ターミナルには、このような機能がOnChartEvent()イベントハンドラの形式で存在します。そのツールキットをいくつかのイベントで補足して、ライブラリでグラフィカルオブジェクトで何が起こったのかを明確にしてみましょう。ライブラリ制御プログラムは、グラフィカルオブジェクトで何が起こったか、どのプロパティが変更されたかを正確に知ることができます。
この機能の開発は2つの段階に分けます。まず、グラフィカルオブジェクトに発生する可能性のある一般的なイベントを作成して、次に、オブジェクトに何が起こったのかを明確にし、ユーザーがプログラムでそれをすばやく見つけられるようにする機能を追加します。そのような機能を作成する準備はほとんど整っており、ライブラリクラスを少し改善し、イベントハンドラに場所を作成するだけです。ここで、グラフィカルオブジェクトに発生するイベントが処理されます。
基本的なグラフィカルオブジェクトイベントは次のように定義されます。
- グラフィカルオブジェクトの新規作成
- グラフィカルオブジェクトのプロパティの変更
- グラフィカルオブジェクトの名前変更
- グラフィカルオブジェクトの削除
- グラフィカルオブジェクトとチャーとウィンドウの削除
これらは、本稿で実装するイベントで、OnChartEvent()ハンドラに送信されます。次の記事では、各イベントの処理を実装して、グラフィカルオブジェクトで変更されたプロパティを正確に把握できるようにします。
グラフィッカルオブジェクトの名前を変更すると、Nameプロパティが変更されます。ただし、名前を変更すると複数のイベントが連続して発生するため、処理を簡素化するために別のイベントに配置することにしました。グラフィカルオブジェクトを削除し、新しいオブジェクトを作成し、そのプロパティを変更します。これらの状態はすべて、ライブラリですでに処理されていて、名前変更イベントは正しく計算されているため、イベントをさらにプログラムで処理するために送信します。
グラフィカルオブジェクトを削除すると、削除されたオブジェクトを正確に特定して、その名前を報告できます。ただし、グラフィカルオブジェクトを含むチャートウィンドウを削除する場合、未だに削除されたチャートにあるグラフィカルオブジェクトの数しかわかりません。今のところ、これら2つのイベントは、グラフィッカルオブジェクトの削除についてのみ通知します。おそらく、将来的には、削除されたオブジェクトのプロパティを記憶する必要があると思いますが、今のところ、この機能を実装する緊急の必要性はないでしょう。
ライブラリクラスの改善
グラフィカルオブジェクトの割り当てを追跡するには、グラフィカルオブジェクトのクリックイベントのハンドラを追加する必要があります。未選択のグラフィッカルオブジェクトはダブルクリックすると編集対象として選択され、選択済みのオブジェクトはダブルクリックするとその選択が解除されます。現在のチャートでこのようなオブジェクトイベントを処理するには、イベントハンドラに新しいイベントIDを追加する必要があります。他のチャートでこのようなイベントを処理するには、新しく開いたチャートウィンドウごとに自動的に設定されるイベント制御指標を改善する必要があります。
\MQL5\Indicators\DoEasy\EventControl.mq5指標ファイルを開き、制御プログラムチャートに送信される新しいイベントIDを追加します。
//+------------------------------------------------------------------+ //| EventControl.mq5 | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property indicator_chart_window #property indicator_plots 0 //--- input parameters input long InpChartSRC = 0; input long InpChartDST = 0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator shortname IndicatorSetString(INDICATOR_SHORTNAME,"EventSend_From#"+(string)InpChartSRC+"_To#"+(string)InpChartDST); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { return rates_total; } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- if(id==CHARTEVENT_OBJECT_CHANGE || id==CHARTEVENT_OBJECT_DRAG || id==CHARTEVENT_OBJECT_CLICK) { EventChartCustom(InpChartDST,(ushort)id,InpChartSRC,dparam,sparam); } } //+------------------------------------------------------------------+
\MQL5\Include\DoEasy\Data.mqhに、新しいメッセージインデックスを追加します。
//--- CGraphElementsCollection MSG_GRAPH_OBJ_FAILED_GET_ADDED_OBJ_LIST, // Failed to get the list of newly added objects MSG_GRAPH_OBJ_FAILED_DETACH_OBJ_FROM_LIST, // Failed to remove a graphical object from the list MSG_GRAPH_OBJ_CREATE_EVN_CTRL_INDICATOR, // Indicator for controlling and sending events created MSG_GRAPH_OBJ_FAILED_CREATE_EVN_CTRL_INDICATOR, // Failed to create the indicator for controlling and sending events MSG_GRAPH_OBJ_ADDED_EVN_CTRL_INDICATOR, // Indicator for controlling and sending events successfully added to the chart MSG_GRAPH_OBJ_FAILED_ADD_EVN_CTRL_INDICATOR, // Failed to add the indicator for controlling and sending events MSG_GRAPH_OBJ_CLOSED_CHARTS, // Chart windows closed: MSG_GRAPH_OBJ_OBJECTS_ON_CLOSED_CHARTS, // Objects removed together with charts: MSG_GRAPH_OBJ_FAILED_CREATE_EVN_OBJ, // Failed to create the event object for a graphical object MSG_GRAPH_OBJ_FAILED_ADD_EVN_OBJ, // Failed to add the event object to the list MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_CREATE, // New graphical object created MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_CHANGE, // Changed the graphical object property MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_RENAME, // Graphical object renamed MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_DELETE, // Graphical object removed MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_DEL_CHART, // Graphical object removed together with the chart }; //+------------------------------------------------------------------+
新しく追加したインデックスに対応するメッセージテキストも追加します。
//--- CGraphElementsCollection {"Не удалось получить список вновь добавленных объектов","Failed to get the list of newly added objects"}, {"Не удалось изъять графический объект из списка","Failed to detach graphic object from the list"}, {"Создан индикатор контроля и отправки событий","An indicator for monitoring and sending events has been created"}, {"Не удалось создать индикатор контроля и отправки событий","Failed to create indicator for monitoring and sending events"}, {"Индикатор контроля и отправки событий успешно добавлен на график ","The indicator for monitoring and sending events has been successfully added to the chart"}, {"Не удалось добавить индикатор контроля и отправки событий на график ","Failed to add the indicator of monitoring and sending events to the chart "}, {"Закрыто окон графиков: ","Closed chart windows: "}, {"С ними удалено объектов: ","Objects removed with them: "}, {"Не удалось создать объект-событие для графического объекта","Failed to create event object for graphic object"}, {"Не удалось добавить объект-событие в список","Failed to add event object to list"}, {"Создан новый графический объект","New graphic object created"}, {"Изменено свойство графического объекта","Changed graphic object property"}, {"Графический объект переименован","Graphic object renamed"}, {"Графический объект удалён","Graphic object deleted"}, {"Графический объект удалён вместе с графиком","The graphic object has been removed along with the chart"}, }; //+---------------------------------------------------------------------+
\MQL5\Include\DoEasy\Defines.mqhを修正しましょう。
オブジェクト再配置イベントを可能なグラフィカルオブジェクトイベントのリストから削除します。このプロパティの変更は、グラフィカルオブジェクトイベントの列挙にすでに存在するためです。
//+------------------------------------------------------------------+ //| List of possible graphical object events | //+------------------------------------------------------------------+ enum ENUM_GRAPH_OBJ_EVENT { GRAPH_OBJ_EVENT_NO_EVENT = CHART_OBJ_EVENTS_NEXT_CODE,// No event GRAPH_OBJ_EVENT_CREATE, // "Creating a new graphical object" event GRAPH_OBJ_EVENT_CHANGE, // "Changing graphical object properties" event GRAPH_OBJ_EVENT_MOVE, // "Moving graphical object" event GRAPH_OBJ_EVENT_RENAME, // "Renaming graphical object" event GRAPH_OBJ_EVENT_DELETE, // "Removing graphical object" event };
チャートと一緒にグラフィカルオブジェクトを削除するイベントのリストに新しい定数を追加します。
//+------------------------------------------------------------------+ //| Data for handling graphical elements | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| List of possible graphical object events | //+------------------------------------------------------------------+ enum ENUM_GRAPH_OBJ_EVENT { GRAPH_OBJ_EVENT_NO_EVENT = CHART_OBJ_EVENTS_NEXT_CODE,// No event GRAPH_OBJ_EVENT_CREATE, // "Creating a new graphical object" event GRAPH_OBJ_EVENT_CHANGE, // "Changing graphical object properties" event GRAPH_OBJ_EVENT_RENAME, // "Renaming graphical object" event GRAPH_OBJ_EVENT_DELETE, // "Removing graphical object" event GRAPH_OBJ_EVENT_DEL_CHART, // "Removing a graphical object together with the chart window" event }; #define GRAPH_OBJ_EVENTS_NEXT_CODE (GRAPH_OBJ_EVENT_DEL_CHART+1) // The code of the next event after the last graphical object event code //+------------------------------------------------------------------+
グラフィカルオブジェクトイベントのコードの後の次のイベントのコードは、列挙に追加された最後の値から計算されるようになりました。
標準のグラフィカルオブジェクトを作成する場合、そのコンストラクタで、チャート上の物理オブジェクトからデータを読み取り、クラスオブジェクトのプロパティに書き込みます。一部のグラフィカルオブジェクトプロパティは、すべてのグラフィカルオブジェクトに共通として設定されています。それらは各オブジェクトにあり、すべてのライブラリグラフィカルオブジェクトの基本クラスに設定されています。
アルゴリズムは次のとおりです。パラメータは、まず標準のObjectGetXXX関数(Integer、 Double、String)を使用してグラフィカルオブジェクトから読み取られます。データが正常に受信されると、これらのパラメータはまずCGBaseObjグラフィカルオブジェクト基本クラスオブジェクトのプロパティに設定されてから、その子孫プロパティに設定されます。標準のグラフィカルオブジェクトの場合、これはCGStdGraphObjクラスです。
ここで矛盾に直面します。グラフィカルオブジェクトパラメータを設定するためのメソッドがあります。これらのメソッドは、渡されたプロパティ値をグラフィカルオブジェクト自体と適切なクラスオブジェクトプロパティに設定します。パラメータがObjectSetXXX関数(Integer、Double、String)を使用してグラフィカルオブジェクトに正常に設定された場合にはです。ただし、グラフィカルオブジェクトパラメータの既知の値をクラスプロパティに設定する必要がある場合もあります。これを実現するためには、この値を再度読み取る必要もグラフィカルオブジェクトに割り当てる必要もなく、代わりにその値をクラス変数に割り当てるだけです。ライブラリの基本グラフィカルオブジェクトのSetメソッドは、最初に値をグラフィカルオブジェクトパラメータに設定してからそれらをクラス変数に書き込みます。既知のグラフィカルオブジェクトプロパティの設定を回避して代わりにクラス変数に設定するために、そのようなメソッドにbool変数only_propを追加します。変数は、値を変数値のみ、グラフィカルオブジェクトパラメータ、またはクラスオブジェクトプロパティのいずれかに設定する必要があることを示します。入力がtrueの場合、パラメータは最初にクラス変数にのみ設定されます。それ以外の場合、値は最初にグラフィカルオブジェクトに設定されます。クラス変数が2番目に来ます。
すべてのライブラリグラフィカルオブジェクトの基本オブジェクトクラス(\MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqh)で、そのようなメソッドに変数を追加し、メソッドロジックを変更します。
//--- Set the "Background object" flag bool SetFlagBack(const bool flag,const bool only_prop) { ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_BACK,flag)) || only_prop) { this.m_back=flag; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; }
ここで、変数がfalseで、プロパティがグラフィカルオブジェクトに設定されている場合または変数がtrueの場合、メソッドに渡された値をクラス変数に書き込みます。
すべてのクラスメソッドは次のように変更されています。
//--- Set the "Background object" flag bool SetFlagBack(const bool flag,const bool only_prop) { ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_BACK,flag)) || only_prop) { this.m_back=flag; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; } //--- Set the "Object selection" flag bool SetFlagSelected(const bool flag,const bool only_prop) { ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_SELECTED,flag)) || only_prop) { this.m_selected=flag; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; } //--- Set the "Object selection" flag bool SetFlagSelectable(const bool flag,const bool only_prop) { ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_SELECTABLE,flag)) || only_prop) { this.m_selectable=flag; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; } //--- Set the "Disable displaying the name of a graphical object in the terminal object list" flag bool SetFlagHidden(const bool flag,const bool only_prop) { ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_SELECTABLE,flag)) || only_prop) { this.m_hidden=flag; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; } //--- Set the priority of a graphical object for receiving the event of clicking on a chart bool SetZorder(const long value,const bool only_prop) { ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_ZORDER,value)) || only_prop) { this.m_zorder=value; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; } //--- Set object visibility on all timeframes bool SetVisible(const bool flag,const bool only_prop) { long value=(flag ? OBJ_ALL_PERIODS : OBJ_NO_PERIODS); ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_TIMEFRAMES,value)) || only_prop) { this.m_visible=flag; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; } //--- Set visibility flags on timeframes specified as flags bool SetVisibleOnTimeframes(const int flags,const bool only_prop) { ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_TIMEFRAMES,flags)) || only_prop) { this.m_timeframes_visible=flags; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; } //--- Add the visibility flag on a specified timeframe bool SetVisibleOnTimeframe(const ENUM_TIMEFRAMES timeframe,const bool only_prop) { int flags=this.m_timeframes_visible; switch(timeframe) { case PERIOD_M1 : flags |= OBJ_PERIOD_M1; break; case PERIOD_M2 : flags |= OBJ_PERIOD_M2; break; case PERIOD_M3 : flags |= OBJ_PERIOD_M3; break; case PERIOD_M4 : flags |= OBJ_PERIOD_M4; break; case PERIOD_M5 : flags |= OBJ_PERIOD_M5; break; case PERIOD_M6 : flags |= OBJ_PERIOD_M6; break; case PERIOD_M10 : flags |= OBJ_PERIOD_M10; break; case PERIOD_M12 : flags |= OBJ_PERIOD_M12; break; case PERIOD_M15 : flags |= OBJ_PERIOD_M15; break; case PERIOD_M20 : flags |= OBJ_PERIOD_M20; break; case PERIOD_M30 : flags |= OBJ_PERIOD_M30; break; case PERIOD_H1 : flags |= OBJ_PERIOD_H1; break; case PERIOD_H2 : flags |= OBJ_PERIOD_H2; break; case PERIOD_H3 : flags |= OBJ_PERIOD_H3; break; case PERIOD_H4 : flags |= OBJ_PERIOD_H4; break; case PERIOD_H6 : flags |= OBJ_PERIOD_H6; break; case PERIOD_H8 : flags |= OBJ_PERIOD_H8; break; case PERIOD_H12 : flags |= OBJ_PERIOD_H12; break; case PERIOD_D1 : flags |= OBJ_PERIOD_D1; break; case PERIOD_W1 : flags |= OBJ_PERIOD_W1; break; case PERIOD_MN1 : flags |= OBJ_PERIOD_MN1; break; default : return true; } ::ResetLastError(); if((!only_prop && ::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_TIMEFRAMES,flags)) || only_prop) { this.m_timeframes_visible=flags; return true; } else CMessage::ToLog(DFUN,::GetLastError(),true); return false; }
これで、プロパティの記述方法を選択できます。グラフィカルオブジェクトとクラス変数に新しいプロパティを設定するか(新しく設定された値に対応するように)、既知のグラフィカルオブジェクトのパラメータ値をクラス変数に設定します(新しいグラフィカルオブジェクトを作成するときにクラスコンストラクタで実行されるように)。これにより、同期のためにグラフィカルオブジェクトを処理するためのかなり低速な関数への過度のアクセスを回避できます。
\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqh で、改善されたメソッドの呼び出しを修正します。
//--- Return (1) the element ID, (2) element index in the list, (3) flag of the form shadow presence and (4) the chart background color int ID(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ID); } int Number(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_NUM); } bool IsShadow(void) const { return this.m_shadow; } color ChartColorBackground(void) const { return this.m_chart_color_bg; } //--- Set the object above all void BringToTop(void) { CGBaseObj::SetVisible(false,false); CGBaseObj::SetVisible(true,false);} //--- (1) Show and (2) hide the element virtual void Show(void) { CGBaseObj::SetVisible(true,false); } virtual void Hide(void) { CGBaseObj::SetVisible(false,false); } //+------------------------------------------------------------------+ //| The methods of receiving raster data | //+------------------------------------------------------------------+
\MQL5\Include\DoEasy\Objects\Graph\Form.mqhで、2つのメソッドを修正します。
//+------------------------------------------------------------------+ //| Create the shadow object | //+------------------------------------------------------------------+ void CForm::CreateShadowObj(const color colour,const uchar opacity) { //--- If the shadow flag is disabled or the shadow object already exists, exit if(!this.m_shadow || this.m_shadow_obj!=NULL) return; //--- Calculate the shadow object coordinates according to the offset from the top and left int x=this.CoordX()-OUTER_AREA_SIZE; int y=this.CoordY()-OUTER_AREA_SIZE; //--- Calculate the width and height in accordance with the top, bottom, left and right offsets int w=this.Width()+OUTER_AREA_SIZE*2; int h=this.Height()+OUTER_AREA_SIZE*2; //--- Create a new shadow object and set the pointer to it in the variable this.m_shadow_obj=new CShadowObj(this.ChartID(),this.SubWindow(),this.CreateNameDependentObject("Shadow"),x,y,w,h); if(this.m_shadow_obj==NULL) { ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_ERR_FAILED_CREATE_SHADOW_OBJ)); return; } //--- Set the properties for the created shadow object this.m_shadow_obj.SetID(this.ID()); this.m_shadow_obj.SetNumber(-1); this.m_shadow_obj.SetOpacityShadow(opacity); this.m_shadow_obj.SetColorShadow(colour); this.m_shadow_obj.SetMovable(true); this.m_shadow_obj.SetActive(false); this.m_shadow_obj.SetVisible(false,false); //--- Move the form object to the foreground this.BringToTop(); } //+------------------------------------------------------------------+ //| Draw the shadow | //+------------------------------------------------------------------+ void CForm::DrawShadow(const int shift_x,const int shift_y,const color colour,const uchar opacity=127,const uchar blur=4) { //--- If the shadow flag is disabled, exit if(!this.m_shadow) return; //--- If there is no shadow object, create it if(this.m_shadow_obj==NULL) this.CreateShadowObj(colour,opacity); //--- If the shadow object exists, draw the shadow on it, //--- set the shadow object visibility flag and //--- move the form object to the foreground if(this.m_shadow_obj!=NULL) { this.m_shadow_obj.DrawShadow(shift_x,shift_y,blur); this.m_shadow_obj.SetVisible(true,false); this.BringToTop(); } } //+------------------------------------------------------------------+
標準のグラフィカルオブジェクトクラスで、グラフィカルオブジェクトのプロパティを設定するすべてのメソッドがブール型の戻り値を持つようにします(現在、メソッドは値を返さずvoid型です)。これは、bool戻り型も持つ適切な親クラスメソッドが子クラスで再割り当てされるようにするために必要です。ヒントには基本オブジェクトからのbool型とその子孫からのvoid型の2つのメソッドが含まれていないため、コードを記述する際の混乱を避けることができます。
例として、サブウィンドウインデックスを として設定するためのメソッドを使用してこれを考えてみましょう。
//--- Chart subwindow index int SubWindow(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_WND_NUM,0); } bool SetSubWindow(void) { if(!CGBaseObj::SetSubwindow(CGBaseObj::ChartID(),CGBaseObj::Name())) return false; this.SetProperty(GRAPH_OBJ_PROP_WND_NUM,0,CGBaseObj::SubWindow()); return true; }
サブウィンドウインデックスはチャートIDとオブジェクト名で検索されるため、基本オブジェクトにすでに設定されているチャートIDとグラフィカルオブジェクト名は、サブウィンドウインデックスを設定するための基本クラスメソッドに渡されるだけです。基本オブジェクトに値を設定できなかった場合はfalseを返し、そうでない場合は基本オブジェクトに新しく設定した値をオブジェクトプロパティに設定してtrueを返します。
例として、すべての時間枠でオブジェクトの可視性を設定するメソッドを使用してこれを考えてみましょう。
//--- Object visibility on timeframes bool Visible(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0); } bool SetFlagVisible(const bool flag,const bool only_prop) { if(!CGBaseObj::SetVisible(flag,only_prop)) return false; this.SetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0,flag); return true; }
ここで、メソッドは、パラメータが設定される値(オブジェクトプロパティのみ、またはグラフィカルオブジェクトパラメータとクラスプロパティ)を指定するために、以前に追加した新しいパラメータを受け取ります。次に、これらのプロパティを基本オブジェクトに設定します。失敗した場合は、falseを返します。
それ以外の場合は、クラスオブジェクトプロパティに値を書き込み、trueを返します
他のすべてのメソッドは、上記で検討したものと同じように変更されます。
//--- Background object bool Back(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_BACK,0); } bool SetFlagBack(const bool flag,const bool only_prop) { if(!CGBaseObj::SetFlagBack(flag,only_prop)) return false; this.SetProperty(GRAPH_OBJ_PROP_BACK,0,flag); return true; } //--- Priority of a graphical object for receiving the event of clicking on a chart long Zorder(void) const { return this.GetProperty(GRAPH_OBJ_PROP_ZORDER,0); } bool SetZorder(const long value,const bool only_prop) { if(!CGBaseObj::SetZorder(value,only_prop)) return false; this.SetProperty(GRAPH_OBJ_PROP_ZORDER,0,value); return true; } //--- Disable displaying the name of a graphical object in the terminal object list bool Hidden(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_HIDDEN,0); } bool SetFlagHidden(const bool flag,const bool only_prop) { if(!CGBaseObj::SetFlagHidden(flag,only_prop)) return false; this.SetProperty(GRAPH_OBJ_PROP_HIDDEN,0,flag); return true; } //--- Object selection bool Selected(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTED,0); } bool SetFlagSelected(const bool flag,const bool only_prop) { if(!CGBaseObj::SetFlagSelected(flag,only_prop)) return false; this.SetProperty(GRAPH_OBJ_PROP_SELECTED,0,flag); return true; } //--- Object availability bool Selectable(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTABLE,0); } bool SetFlagSelectable(const bool flag,const bool only_prop) { if(!CGBaseObj::SetFlagSelectable(flag,only_prop)) return false; this.SetProperty(GRAPH_OBJ_PROP_SELECTABLE,0,flag); return true; } //--- Time coordinate datetime Time(const int modifier) const { return (datetime)this.GetProperty(GRAPH_OBJ_PROP_TIME,modifier); } bool SetTime(const datetime time,const int modifier) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_TIME,modifier,time)) return false; this.SetProperty(GRAPH_OBJ_PROP_TIME,modifier,time); return true; } //--- Color color Color(void) const { return (color)this.GetProperty(GRAPH_OBJ_PROP_COLOR,0); } bool SetColor(const color colour) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_COLOR,colour)) return false; this.SetProperty(GRAPH_OBJ_PROP_COLOR,0,colour); return true; } //--- Style ENUM_LINE_STYLE Style(void) const { return (ENUM_LINE_STYLE)this.GetProperty(GRAPH_OBJ_PROP_STYLE,0); } bool SetStyle(const ENUM_LINE_STYLE style) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_STYLE,style)) return false; this.SetProperty(GRAPH_OBJ_PROP_STYLE,0,style); return true; } //--- Line width int Width(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_WIDTH,0); } bool SetWidth(const int width) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_WIDTH,width)) return false; this.SetProperty(GRAPH_OBJ_PROP_WIDTH,0,width); return true; } //--- Object color filling bool Fill(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_FILL,0); } bool SetFlagFill(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_FILL,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_FILL,0,flag); return true; } //--- Ability to edit text in the Edit object bool ReadOnly(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_READONLY,0); } bool SetFlagReadOnly(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_READONLY,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_READONLY,0,flag); return true; } //--- Number of levels int Levels(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_LEVELS,0); } bool SetLevels(const int levels) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELS,levels)) return false; this.SetProperty(GRAPH_OBJ_PROP_LEVELS,0,levels); return true; } //--- Line level color color LevelColor(const int modifier) const { return (color)this.GetProperty(GRAPH_OBJ_PROP_LEVELCOLOR,modifier); } bool SetLevelColor(const color colour,const int modifier) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELCOLOR,modifier,colour)) return false; this.SetProperty(GRAPH_OBJ_PROP_LEVELCOLOR,modifier,colour); return true; } //--- Level line style ENUM_LINE_STYLE LevelStyle(const int modifier)const { return (ENUM_LINE_STYLE)this.GetProperty(GRAPH_OBJ_PROP_LEVELSTYLE,modifier); } bool SetLevelStyle(const ENUM_LINE_STYLE style,const int modifier) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELSTYLE,modifier,style)) return false; this.SetProperty(GRAPH_OBJ_PROP_LEVELSTYLE,modifier,style); return true; } ///--- Level line width int LevelWidth(const int modifier)const { return (int)this.GetProperty(GRAPH_OBJ_PROP_LEVELWIDTH,modifier); } bool SetLevelWidth(const int width,const int modifier) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELWIDTH,modifier,width)) return false; this.SetProperty(GRAPH_OBJ_PROP_LEVELWIDTH,modifier,width); return true; } //--- Horizontal text alignment in the Edit object (OBJ_EDIT) ENUM_ALIGN_MODE Align(void) const { return (ENUM_ALIGN_MODE)this.GetProperty(GRAPH_OBJ_PROP_ALIGN,0); } bool SetAlign(const ENUM_ALIGN_MODE align) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ALIGN,align)) return false; this.SetProperty(GRAPH_OBJ_PROP_ALIGN,0,align); return true; } //--- Font size int FontSize(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_FONTSIZE,0); } bool SetFontSize(const int size) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_FONTSIZE,size)) return false; this.SetProperty(GRAPH_OBJ_PROP_FONTSIZE,0,size); return true; } //--- Ray goes to the left bool RayLeft(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_RAY_LEFT,0); } bool SetFlagRayLeft(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_RAY_LEFT,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_RAY_LEFT,0,flag); return true; } //--- Ray goes to the right bool RayRight(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_RAY_RIGHT,0); } bool SetFlagRayRight(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_RAY_RIGHT,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_RAY_RIGHT,0,flag); return true; } //--- Vertical line goes through all windows of a chart bool Ray(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_RAY,0); } bool SetFlagRay(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_RAY,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_RAY,0,flag); return true; } //--- Display the full ellipse of the Fibonacci Arc object bool Ellipse(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_ELLIPSE,0); } bool SetFlagEllipse(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ELLIPSE,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_ELLIPSE,0,flag); return true; } //--- Arrow code for the "Arrow" object uchar ArrowCode(void) const { return (uchar)this.GetProperty(GRAPH_OBJ_PROP_ARROWCODE,0); } bool SetArrowCode(const uchar code) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ARROWCODE,code)) return false; this.SetProperty(GRAPH_OBJ_PROP_ARROWCODE,0,code); return true; } //--- Position of the graphical object anchor point int Anchor(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_ANCHOR,0); } bool SetAnchor(const int anchor) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ANCHOR,anchor)) return false; this.SetProperty(GRAPH_OBJ_PROP_ANCHOR,0,anchor); return true; } //--- Distance from the base corner along the X axis in pixels int XDistance(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_XDISTANCE,0); } bool SetXDistance(const int distance) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_XDISTANCE,distance)) return false; this.SetProperty(GRAPH_OBJ_PROP_XDISTANCE,0,distance); return true; } //--- Distance from the base corner along the Y axis in pixels int YDistance(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_YDISTANCE,0); } bool SetYDistance(const int distance) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_YDISTANCE,distance)) return false; this.SetProperty(GRAPH_OBJ_PROP_YDISTANCE,0,distance); return true; } //--- Gann object trend ENUM_GANN_DIRECTION Direction(void) const { return (ENUM_GANN_DIRECTION)this.GetProperty(GRAPH_OBJ_PROP_DIRECTION,0); } bool SetDirection(const ENUM_GANN_DIRECTION direction) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DIRECTION,direction)) return false; this.SetProperty(GRAPH_OBJ_PROP_DIRECTION,0,direction); return true; } //--- Elliott wave marking level ENUM_ELLIOT_WAVE_DEGREE Degree(void) const { return (ENUM_ELLIOT_WAVE_DEGREE)this.GetProperty(GRAPH_OBJ_PROP_DEGREE,0); } bool SetDegree(const ENUM_ELLIOT_WAVE_DEGREE degree) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DEGREE,degree)) return false; this.SetProperty(GRAPH_OBJ_PROP_DEGREE,0,degree); return true; } //--- Display lines for Elliott wave marking bool DrawLines(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_DRAWLINES,0); } bool SetFlagDrawLines(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DRAWLINES,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_DRAWLINES,0,flag); return true; } //--- Button state (pressed/released) bool State(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_STATE,0); } bool SetFlagState(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_STATE,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_STATE,0,flag); return true; } //--- Chart object ID (OBJ_CHART) long ChartObjChartID(void) const { return this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_CHART_ID,0); } bool SetChartObjChartID(const long chart_id) { this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_CHART_ID,0,chart_id); return true; } //--- Chart object period ENUM_TIMEFRAMES ChartObjPeriod(void) const { return (ENUM_TIMEFRAMES)this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PERIOD,0); } bool SetChartObjPeriod(const ENUM_TIMEFRAMES timeframe) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_PERIOD,timeframe)) return false; this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PERIOD,0,timeframe); return true; } //--- Time scale display flag for the Chart object bool ChartObjDateScale(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE,0); } bool SetFlagChartObjDateScale(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DATE_SCALE,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE,0,flag); return true; } //--- Price scale display flag for the Chart object bool ChartObjPriceScale(void) const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE,0); } bool SetFlagPriceScale(const bool flag) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_PRICE_SCALE,flag)) return false; this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE,0,flag); return true; } //--- Chart object scale int ChartObjChartScale(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE,0); } bool SetChartObjChartScale(const int scale) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_CHART_SCALE,scale)) return false; this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE,0,scale); return true; } //--- Object width along the X axis in pixels int XSize(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_XSIZE,0); } bool SetXSize(const int size) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_XSIZE,size)) return false; this.SetProperty(GRAPH_OBJ_PROP_XSIZE,0,size); return true; } //--- Object height along the Y axis in pixels int YSize(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_YSIZE,0); } bool SetYSize(const int size) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_YSIZE,size)) return false; this.SetProperty(GRAPH_OBJ_PROP_YSIZE,0,size); return true; } //--- X coordinate of the upper-left corner of the visibility area int XOffset(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_XOFFSET,0); } bool SetXOffset(const int offset) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_XOFFSET,offset)) return false; this.SetProperty(GRAPH_OBJ_PROP_XOFFSET,0,offset); return true; } //--- Y coordinate of the upper-left corner of the visibility area int YOffset(void) const { return (int)this.GetProperty(GRAPH_OBJ_PROP_YOFFSET,0); } bool SetYOffset(const int offset) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_YOFFSET,offset)) return false; this.SetProperty(GRAPH_OBJ_PROP_YOFFSET,0,offset); return true; } //--- Background color for OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL color BGColor(void) const { return (color)this.GetProperty(GRAPH_OBJ_PROP_BGCOLOR,0); } bool SetBGColor(const color colour) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_BGCOLOR,colour)) return false; this.SetProperty(GRAPH_OBJ_PROP_BGCOLOR,0,colour); return true; } //--- Chart corner for attaching a graphical object ENUM_BASE_CORNER Corner(void) const { return (ENUM_BASE_CORNER)this.GetProperty(GRAPH_OBJ_PROP_CORNER,0); } bool SetCorner(const ENUM_BASE_CORNER corner) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_CORNER,corner)) return false; this.SetProperty(GRAPH_OBJ_PROP_CORNER,0,corner); return true; } //--- Border type for the Rectangle label object ENUM_BORDER_TYPE BorderType(void) const { return (ENUM_BORDER_TYPE)this.GetProperty(GRAPH_OBJ_PROP_BORDER_TYPE,0); } bool SetBorderType(const ENUM_BORDER_TYPE type) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_BORDER_TYPE,type)) return false; this.SetProperty(GRAPH_OBJ_PROP_BORDER_TYPE,0,type); return true; } //--- Border color for OBJ_EDIT and OBJ_BUTTON color BorderColor(void) const { return (color)this.GetProperty(GRAPH_OBJ_PROP_BORDER_COLOR,0); } bool SetBorderColor(const color colour) { if(!::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_BORDER_COLOR,colour)) return false; this.SetProperty(GRAPH_OBJ_PROP_BORDER_COLOR,0,colour); return true; } //--- Price coordinate double Price(const int modifier) const { return this.GetProperty(GRAPH_OBJ_PROP_PRICE,modifier); } bool SetPrice(const double price,const int modifier) { if(!::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_PRICE,modifier,price)) return false; this.SetProperty(GRAPH_OBJ_PROP_PRICE,modifier,price); return true; } //--- Level value double LevelValue(const int modifier)const { return this.GetProperty(GRAPH_OBJ_PROP_LEVELVALUE,modifier); } bool SetLevelValue(const double value,const int modifier) { if(!::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELVALUE,modifier,value)) return false; this.SetProperty(GRAPH_OBJ_PROP_LEVELVALUE,modifier,value); return true; } //--- Scale double Scale(void) const { return this.GetProperty(GRAPH_OBJ_PROP_SCALE,0); } bool SetScale(const double scale) { if(!::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_SCALE,scale)) return false; this.SetProperty(GRAPH_OBJ_PROP_SCALE,0,scale); return true; } //--- Angle double Angle(void) const { return this.GetProperty(GRAPH_OBJ_PROP_ANGLE,0); } bool SetAngle(const double angle) { if(!::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ANGLE,angle)) return false; this.SetProperty(GRAPH_OBJ_PROP_ANGLE,0,angle); return true; } //--- Deviation of the standard deviation channel double Deviation(void) const { return this.GetProperty(GRAPH_OBJ_PROP_DEVIATION,0); } bool SetDeviation(const double deviation) { if(!::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DEVIATION,deviation)) return false; this.SetProperty(GRAPH_OBJ_PROP_DEVIATION,0,deviation); return true; } //--- Object name string Name(void) const { return this.GetProperty(GRAPH_OBJ_PROP_NAME,0); } bool SetName(const string name) { if(CGBaseObj::Name()==name) return true; if(CGBaseObj::Name()=="") { CGBaseObj::SetName(name); this.SetProperty(GRAPH_OBJ_PROP_NAME,0,name); return true; } else { if(!::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_NAME,name)) return false; CGBaseObj::SetName(name); this.SetProperty(GRAPH_OBJ_PROP_NAME,0,name); return true; } } //--- Object description (text contained in the object) string Text(void) const { return this.GetProperty(GRAPH_OBJ_PROP_TEXT,0); } bool SetText(const string text) { if(!::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_TEXT,text)) return false; this.SetProperty(GRAPH_OBJ_PROP_TEXT,0,text); return true; } //--- Tooltip text string Tooltip(void) const { return this.GetProperty(GRAPH_OBJ_PROP_TOOLTIP,0); } bool SetTooltip(const string tooltip) { if(!::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_TOOLTIP,tooltip)) return false; this.SetProperty(GRAPH_OBJ_PROP_TOOLTIP,0,tooltip); return true; } //--- Level description string LevelText(const int modifier) const { return this.GetProperty(GRAPH_OBJ_PROP_LEVELTEXT,modifier); } bool SetLevelText(const string text,const int modifier) { if(!::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELTEXT,modifier,text)) return false; this.SetProperty(GRAPH_OBJ_PROP_LEVELTEXT,modifier,text); return true; } //--- Font string Font(void) const { return this.GetProperty(GRAPH_OBJ_PROP_FONT,0); } bool SetFont(const string font) { if(!::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_FONT,font)) return false; this.SetProperty(GRAPH_OBJ_PROP_FONT,0,font); return true; } //--- BMP file name for the "Bitmap Level" object string BMPFile(const int modifier) const { return this.GetProperty(GRAPH_OBJ_PROP_BMPFILE,modifier); } bool SetBMPFile(const string bmp_file,const int modifier) { if(!::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_BMPFILE,bmp_file)) return false; this.SetProperty(GRAPH_OBJ_PROP_BMPFILE,modifier,bmp_file); return true; } //--- Symbol for the Chart object string ChartObjSymbol(void) const { return this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL,0); } bool SetChartObjSymbol(const string symbol) { if(!::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_SYMBOL,symbol)) return false; this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL,0,symbol); return true; }
整数プロパティを受け取って保存するメソッドでは、まず基本オブジェクトに存在するデータを基本オブジェクトプロパティに書き込みます。次に、そのオブジェクトの値をグラフィカルオブジェクトクラスのプロパティに書き込みます。
//+------------------------------------------------------------------+ //| Get and save the integer properties | //+------------------------------------------------------------------+ void CGStdGraphObj::GetAndSaveINT(void) { //--- Properties inherent in all graphical objects and present in a graphical object CGBaseObj::SetVisibleOnTimeframes((int)::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_TIMEFRAMES),true); // Write Object visibility on timeframes to the base object CGBaseObj::SetFlagBack(::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_BACK),true); // Write Background object flag to the base object CGBaseObj::SetZorder(::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_ZORDER),true); // Write Priority of a graphical object for receiving the event of clicking on a chart to the base object CGBaseObj::SetFlagHidden(::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_HIDDEN),true); // Write Disable displaying the name of a graphical object in the terminal object list to the base object CGBaseObj::SetFlagSelectable(::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_SELECTABLE),true); // Write Object availability to the base object CGBaseObj::SetFlagSelected(::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_SELECTED),true); // Write Object selection to the base object this.SetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0,CGBaseObj::VisibleOnTimeframes()); // Object visibility on timeframes this.SetProperty(GRAPH_OBJ_PROP_BACK,0,CGBaseObj::IsBack()); // Background object this.SetProperty(GRAPH_OBJ_PROP_ZORDER,0,CGBaseObj::Zorder()); // Priority of a graphical object for receiving the event of clicking on a chart this.SetProperty(GRAPH_OBJ_PROP_HIDDEN,0,CGBaseObj::IsHidden()); // Disable displaying the name of a graphical object in the terminal object list this.SetProperty(GRAPH_OBJ_PROP_SELECTABLE,0,CGBaseObj::IsSelectable()); // Object availability this.SetProperty(GRAPH_OBJ_PROP_SELECTED,0,CGBaseObj::IsSelected()); // Object selection this.SetProperty(GRAPH_OBJ_PROP_CREATETIME,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_CREATETIME)); // Object creation time for(int i=0;i<this.m_pivots;i++) // Point time coordinates this.SetTimePivot(i); this.SetProperty(GRAPH_OBJ_PROP_COLOR,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_COLOR)); // Color this.SetProperty(GRAPH_OBJ_PROP_STYLE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_STYLE)); // Style this.SetProperty(GRAPH_OBJ_PROP_WIDTH,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_WIDTH)); // Line width //--- Properties belonging to different graphical objects this.SetProperty(GRAPH_OBJ_PROP_FILL,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_FILL)); // Fill an object with color this.SetProperty(GRAPH_OBJ_PROP_READONLY,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_READONLY)); // Ability to edit text in the Edit object this.SetProperty(GRAPH_OBJ_PROP_LEVELS,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_LEVELS)); // Number of levels if(this.GetProperty(GRAPH_OBJ_PROP_LEVELS,0)!=this.GetPropertyPrev(GRAPH_OBJ_PROP_LEVELS,0)) // Check if the number of levels has changed { this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELCOLOR,this.Levels()); this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELSTYLE,this.Levels()); this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELWIDTH,this.Levels()); this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELVALUE,this.Levels()); this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELTEXT,this.Levels()); } for(int i=0;i<this.Levels();i++) // Level data { this.SetLevelColor(i); this.SetLevelStyle(i); this.SetLevelWidth(i); } this.SetProperty(GRAPH_OBJ_PROP_ALIGN,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_ALIGN)); // Horizontal text alignment in the Edit object (OBJ_EDIT) this.SetProperty(GRAPH_OBJ_PROP_FONTSIZE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_FONTSIZE)); // Font size this.SetProperty(GRAPH_OBJ_PROP_RAY_LEFT,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_RAY_LEFT)); // Ray goes to the left this.SetProperty(GRAPH_OBJ_PROP_RAY_RIGHT,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_RAY_RIGHT)); // Ray goes to the right this.SetProperty(GRAPH_OBJ_PROP_RAY,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_RAY)); // Vertical line goes through all windows of a chart this.SetProperty(GRAPH_OBJ_PROP_ELLIPSE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_ELLIPSE)); // Display the full ellipse of the Fibonacci Arc object this.SetProperty(GRAPH_OBJ_PROP_ARROWCODE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_ARROWCODE)); // Arrow code for the "Arrow" object this.SetProperty(GRAPH_OBJ_PROP_ANCHOR,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_ANCHOR)); // Position of the binding point of the graphical object this.SetProperty(GRAPH_OBJ_PROP_XDISTANCE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_XDISTANCE)); // Distance from the base corner along the X axis in pixels this.SetProperty(GRAPH_OBJ_PROP_YDISTANCE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_YDISTANCE)); // Distance from the base corner along the Y axis in pixels this.SetProperty(GRAPH_OBJ_PROP_DIRECTION,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_DIRECTION)); // Gann object trend this.SetProperty(GRAPH_OBJ_PROP_DEGREE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_DEGREE)); // Elliott wave marking level this.SetProperty(GRAPH_OBJ_PROP_DRAWLINES,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_DRAWLINES)); // Display lines for Elliott wave marking this.SetProperty(GRAPH_OBJ_PROP_STATE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_STATE)); // Button state (pressed/released) this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_CHART_ID,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_CHART_ID));// Chart object ID (OBJ_CHART). this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PERIOD,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_PERIOD)); // Chart object period this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_DATE_SCALE)); // Time scale display flag for the Chart object this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_PRICE_SCALE));// Price scale display flag for the Chart object this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_CHART_SCALE));// Chart object scale this.SetProperty(GRAPH_OBJ_PROP_XSIZE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_XSIZE)); // Object width along the X axis in pixels. this.SetProperty(GRAPH_OBJ_PROP_YSIZE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_YSIZE)); // Object height along the Y axis in pixels. this.SetProperty(GRAPH_OBJ_PROP_XOFFSET,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_XOFFSET)); // X coordinate of the upper-left corner of the visibility area. this.SetProperty(GRAPH_OBJ_PROP_YOFFSET,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_YOFFSET)); // Y coordinate of the upper-left corner of the visibility area. this.SetProperty(GRAPH_OBJ_PROP_BGCOLOR,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_BGCOLOR)); // Background color for OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL this.SetProperty(GRAPH_OBJ_PROP_CORNER,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_CORNER)); // Chart corner for binding a graphical object this.SetProperty(GRAPH_OBJ_PROP_BORDER_TYPE,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_BORDER_TYPE));// Border type for "Rectangle border" this.SetProperty(GRAPH_OBJ_PROP_BORDER_COLOR,0,::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_BORDER_COLOR));// Border color for OBJ_EDIT and OBJ_BUTTON } //+------------------------------------------------------------------+
したがって、基本クラスとその子孫で複製されたすべてのプロパティを入力します。それ以外の場合、オブジェクトプロパティを受け取るときは、基本オブジェクトメソッドを使用します。グラフィカルオブジェクトデータは書き込まれていません。
標準のグラフィカルオブジェクトイベントを追跡する機能を作成する際に考慮すべきいくつかの改善点を残しておきます。
標準グラフィカルオブジェクトのイベント
グラフィカルオブジェクトイベントを処理するロジックは、オブジェクトプロパティで発生するすべてのイベントを定義できるという概念に基づいています。グラフィカルオブジェクト基本イベントの小さなクラスを作成しましょう。グラフィカルオブジェクトイベントを定義すると、以下を受け取る新しいイベントオブジェクトが作成されます。
- イベントID
- イベントが発生したグラフィカルオブジェクトを含むチャートのID
- イベントが発生したオブジェクトの名前
EventChartCustom()関数によって指定されたチャートに送信されるカスタムイベントには、次の5つのパラメータがあります。
//+------------------------------------------------------------------+ bool EventChartCustom( long chart_id, // event receiving chart ID ushort custom_event_id, // event ID long lparam, // long parameter double dparam, // double parameter string sparam // event string parameter ); //+------------------------------------------------------------------+
入力するIDは、グラフィカルオブジェクトイベントIDの場合はcustom_event_id 、イベントが発生したグラフィカルオブジェクトを含むチャートのIDの場合はlparam、グラフィカルオブジェクト名の場合はsparamです。また、1つの自由パラメータdparamがあります。これを使用して、変更されたプロパティの定数の値、または閉じたチャートウィンドウとともに削除されたグラフィカルオブジェクトの数を指定します。
イベントオブジェクトは、オブジェクトイベントごとに作成(およびイベントリストに設定)されます。オブジェクトのプロパティで変更を確認した後、グラフィカルオブジェクトで発生したすべてのイベントの完全なリストが表示されます。すべてのオブジェクトプロパティの検証が完了すると、新しく作成されたイベントリストに沿って移動し、各イベントを制御プログラムチャートに送信します。ここで、グラフィカル要素コレクションクラスのOnChartEvent()イベントハンドラメソッドが順番に呼び出されます。ハンドラを使用すると、作成されたグラフィカルオブジェクトイベントのリストから送信された各イベントを処理できます。したがって、このような各イベントには、イベントID、変更されたグラフィカルオブジェクトが配置されているチャートのID、その名前が含まれます。グラフィカルオブジェクトが正確に定義されますが、変更されたプロパティ定数の知識は変更されたプロパティを正確に指し示すため、コレクション内のオブジェクトへのポインタを取得して変更されたプロパティの新しい値を読み取ることができます。これにより、グラフィカルオブジェクト自体と変更されたプロパティの両方を正確に参照して、固有のロジックに従ってプログラム内のイベントをさらに処理できるようになります。
本稿では、イベントの作成とグラフィカルオブジェクトコレクションイベントのハンドラへの送信のみを実装します。これらのイベントは、次の記事でそれらのコンポーネントに分解されます。
基本グラフィカルオブジェクトファイル( \MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqh)の最初に、グラフィカルライブラリオブジェクトの基本イベントの新しいクラスを追加します。
//+------------------------------------------------------------------+ //| GBaseObj.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "..\..\Services\DELib.mqh" #include <Graphics\Graphic.mqh> //+------------------------------------------------------------------+ //| Graphical object event class | //+------------------------------------------------------------------+ class CGBaseEvent : public CObject { private: ushort m_id; long m_lparam; double m_dparam; string m_sparam; public: void ID(ushort id) { this.m_id=id; } ushort ID(void) const { return this.m_id; } void LParam(const long value) { this.m_lparam=value; } long Lparam(void) const { return this.m_lparam; } void DParam(const double value) { this.m_dparam=value; } double Dparam(void) const { return this.m_dparam; } void SParam(const string value) { this.m_sparam=value; } string Sparam(void) const { return this.m_sparam; } bool Send(const long chart_id) { ::ResetLastError(); return ::EventChartCustom(chart_id,m_id,m_lparam,m_dparam,m_sparam); } CGBaseEvent (const ushort event_id,const long lparam,const double dparam,const string sparam) : m_id(event_id),m_lparam(lparam),m_dparam(dparam),m_sparam(sparam){} ~CGBaseEvent (void){} }; //+------------------------------------------------------------------+ //| Class of the base object of the library graphical objects | //+------------------------------------------------------------------+ class CGBaseObj : public CObject
上記のすべてのイベントオブジェクトプロパティを格納するためのクラスメンバー変数は、クラスのprivateセクションで宣言されます。一方、publicセクションには、変数の値を設定および返すためのメソッドおよび指定したチャートにカスタムイベントを送信するメソッドが含まれます。
クラスコンストラクタは、クラス変数に割り当てられるすべての値を受け取ります。値は、コンストラクタ初期化リストの変数にすぐに割り当てられます。
基本グラフィカルオブジェクトクラスのprotectedセクションで、オブジェクトイベントを格納するためのリストを宣言し、リストとグラフィカルオブジェクトイベントを処理するためのメソッドを記述します。
//+------------------------------------------------------------------+ //| Class of the base object of the library graphical objects | //+------------------------------------------------------------------+ class CGBaseObj : public CObject { protected: CArrayObj m_list_events; // Object event list ENUM_OBJECT m_type_graph_obj; // Graphical object type ENUM_GRAPH_ELEMENT_TYPE m_type_element; // Graphical element type ENUM_GRAPH_OBJ_BELONG m_belong; // Program affiliation ENUM_GRAPH_OBJ_GROUP m_group; // Graphical object group string m_name_prefix; // Object name prefix string m_name; // Object name long m_chart_id; // Object chart ID long m_object_id; // Object ID long m_zorder; // Priority of a graphical object for receiving the mouse click event int m_subwindow; // Subwindow index int m_shift_y; // Subwindow Y coordinate shift int m_type; // Object type int m_timeframes_visible; // Visibility of an object on timeframes (a set of flags) int m_digits; // Number of decimal places in a quote bool m_visible; // Object visibility bool m_back; // "Background object" flag bool m_selected; // "Object selection" flag bool m_selectable; // "Object availability" flag bool m_hidden; // "Disable displaying the name of a graphical object in the terminal object list" flag datetime m_create_time; // Object creation time //--- Create (1) the object structure and (2) the object from the structure virtual bool ObjectToStruct(void) { return true; } virtual void StructToObject(void){;} //--- Return the list of object events CArrayObj *GetListEvents(void) { return &this.m_list_events; } //--- Create a new object event CGBaseEvent *CreateNewEvent(const ushort event_id,const long lparam,const double dparam,const string sparam) { CGBaseEvent *event=new CGBaseEvent(event_id,lparam,dparam,sparam); return event; } //--- Create a new object event and add it to the event list bool CreateAndAddNewEvent(const ushort event_id,const long lparam,const double dparam,const string sparam) { return this.AddEvent(new CGBaseEvent(event_id,lparam,dparam,sparam)); } //--- Add an event object to the event list bool AddEvent(CGBaseEvent *event) { return this.m_list_events.Add(event);} //--- Clear the event list void ClearEventsList(void) { this.m_list_events.Clear(); } //--- Return the number of events in the list int EventsTotal(void) { return this.m_list_events.Total(); } public:
提供されているすべてのメソッドは非常にシンプルで理解しやすいものです。質問がある場合は、下のコメント欄でお気軽にお問い合わせください。
クラスコンストラクタで、オブジェクトイベントのリストをクリアし、並べ替えリストフラグを設定します。
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CGBaseObj::CGBaseObj() : m_shift_y(0),m_visible(false), m_name_prefix(::MQLInfoString(MQL_PROGRAM_NAME)+"_"),m_belong(GRAPH_OBJ_BELONG_PROGRAM) { this.m_list_events.Clear(); // Clear the event list this.m_list_events.Sort(); // Sorted list flag this.m_type=OBJECT_DE_TYPE_GBASE; // Object type this.m_type_graph_obj=WRONG_VALUE; // Graphical object type this.m_type_element=WRONG_VALUE; // Graphical object type this.m_belong=WRONG_VALUE; // Program/terminal affiliation this.m_name_prefix=""; // Object name prefix this.m_name=""; // Object name this.m_chart_id=0; // Object chart ID this.m_object_id=0; // Object ID this.m_zorder=0; // Priority of a graphical object for receiving the mouse click event this.m_subwindow=0; // Subwindow index this.m_shift_y=0; // Subwindow Y coordinate shift this.m_timeframes_visible=OBJ_ALL_PERIODS; // Visibility of an object on timeframes (a set of flags) this.m_visible=true; // Object visibility this.m_back=false; // "Background object" flag this.m_selected=false; // "Object selection" flag this.m_selectable=false; // "Object availability" flag this.m_hidden=true; // "Disable displaying the name of a graphical object in the terminal object list" flag this.m_create_time=0; // Object creation time } //+------------------------------------------------------------------+
標準グラフィカルオブジェクトクラス(\MQL5\Include\DoEasy\Objects\Graph\Standard\GStdGraphObj.mqh)、つまりオブジェクトプロパティの変更を確認するメソッドでは、イベントリストをクリアし、イベントオブジェクトの作成とリストへの追加を設定して、作成されたリストからグラフィカルオブジェクトコレクションイベントのハンドラに送信します。
//+------------------------------------------------------------------+ //| Check object property changes | //+------------------------------------------------------------------+ void CGStdGraphObj::PropertiesCheckChanged(void) { CGBaseObj::ClearEventsList(); bool changed=false; int begin=0, end=GRAPH_OBJ_PROP_INTEGER_TOTAL; for(int i=begin; i<end; i++) { ENUM_GRAPH_OBJ_PROP_INTEGER prop=(ENUM_GRAPH_OBJ_PROP_INTEGER)i; if(!this.SupportProperty(prop)) continue; for(int j=0;j<Prop.CurrSize(prop);j++) { if(this.GetProperty(prop,j)!=this.GetPropertyPrev(prop,j)) { changed=true; this.CreateAndAddNewEvent(GRAPH_OBJ_EVENT_CHANGE,this.ChartID(),prop,this.Name()); } } } begin=end; end+=GRAPH_OBJ_PROP_DOUBLE_TOTAL; for(int i=begin; i<end; i++) { ENUM_GRAPH_OBJ_PROP_DOUBLE prop=(ENUM_GRAPH_OBJ_PROP_DOUBLE)i; if(!this.SupportProperty(prop)) continue; for(int j=0;j<Prop.CurrSize(prop);j++) { if(this.GetProperty(prop,j)!=this.GetPropertyPrev(prop,j)) { changed=true; this.CreateAndAddNewEvent(GRAPH_OBJ_EVENT_CHANGE,this.ChartID(),prop,this.Name()); } } } begin=end; end+=GRAPH_OBJ_PROP_STRING_TOTAL; for(int i=begin; i<end; i++) { ENUM_GRAPH_OBJ_PROP_STRING prop=(ENUM_GRAPH_OBJ_PROP_STRING)i; if(!this.SupportProperty(prop)) continue; for(int j=0;j<Prop.CurrSize(prop);j++) { if(this.GetProperty(prop,j)!=this.GetPropertyPrev(prop,j) && prop!=GRAPH_OBJ_PROP_NAME) { changed=true; this.CreateAndAddNewEvent(GRAPH_OBJ_EVENT_CHANGE,this.ChartID(),prop,this.Name()); } } } if(changed) { for(int i=0;i<this.m_list_events.Total();i++) { CGBaseEvent *event=this.m_list_events.At(i); if(event==NULL) continue; ::EventChartCustom(::ChartID(),event.ID(),event.Lparam(),event.Dparam(),event.Sparam()); } PropertiesCopyToPrevData(); } } //+------------------------------------------------------------------+
ここでは、すべてのオブジェクトプロパティのループ内で、各オブジェクトプロパティに変更があるかどうかを確認します。変更が検出された場合は、イベントオブジェクトを作成し、それをオブジェクトイベントのリストに追加します。少なくとも1つの変更がある場合は、各イベントオブジェクトを取得し、作成されたリストのループ内で制御プログラムチャートに送信します。次に、これらのイベントは、グラフィカル要素コレクションクラスのOnChartEvent()ハンドラで送信および処理されます。
グラフィック要素コレクションクラスのファイル(\MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqh)を開きます。チャートオブジェクトをチェックするグラフィカルオブジェクト管理クラスメソッドを少し改善しましょう。
//+------------------------------------------------------------------+ //| CChartObjectsControl: Check objects on a chart | //+------------------------------------------------------------------+ void CChartObjectsControl::Refresh(void) { //--- Graphical objects on the chart this.m_total_objects=::ObjectsTotal(this.ChartID()); this.m_delta_graph_obj=this.m_total_objects-this.m_last_objects; //--- If an object is added to the chart if(this.m_delta_graph_obj>0) { //--- find the last added graphical object, select it and write its name string name=this.LastAddedGraphObjName(); //--- Handle only non-programmatically created objects if(name!="" && ::StringFind(name,m_name_program)==WRONG_VALUE) { //--- Create the object of the graphical object class corresponding to the added graphical object type ENUM_OBJECT type=(ENUM_OBJECT)::ObjectGetInteger(this.ChartID(),name,OBJPROP_TYPE); ENUM_OBJECT_DE_TYPE obj_type=ENUM_OBJECT_DE_TYPE(type+OBJECT_DE_TYPE_GSTD_OBJ+1); CGStdGraphObj *obj=this.CreateNewGraphObj(type,name); if(obj==NULL) { CMessage::ToLog(DFUN,MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_CLASS_OBJ); return; } //--- Set the object affiliation and add the created object to the list of new objects obj.SetBelong(GRAPH_OBJ_BELONG_NO_PROGRAM); if(this.m_list_new_graph_obj.Search(obj)==WRONG_VALUE) { //--- If failed to add the object to the list, inform of that, delete the object and leave if(!this.m_list_new_graph_obj.Add(obj)) { CMessage::ToLog(DFUN_ERR_LINE,MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST); delete obj; return; } //--- Send an event to the control program chart ::EventChartCustom(this.m_chart_id_main,GRAPH_OBJ_EVENT_CREATE,this.ChartID(),0,obj.Name()); } } } //--- save the index of the last added graphical object and the difference with the last check this.m_last_objects=this.m_total_objects; this.m_is_graph_obj_event=(bool)this.m_delta_graph_obj; } //+------------------------------------------------------------------+
ここでは、操作ログにエラーメッセージを表示するようにして、オブジェクト作成イベントを制御プログラムチャートに送信するようにしました。
グラフィカル要素コレクションクラスのpublicセクションで、チャート管理オブジェクトリストを返すメソッドを追加します。
//--- Return the number of new graphical objects, (3) the flag of the occurred change in the list of graphical objects int NewObjects(void) const { return this.m_delta_graph_obj; } bool IsEvent(void) const { return this.m_is_graph_obj_event; } //--- Return a graphical object by chart name and ID CGStdGraphObj *GetStdGraphObject(const string name,const long chart_id); //--- Return the chart management object list CArrayObj *GetListChartsControl(void) { return &this.m_list_charts_control; } //--- Constructor CGraphElementsCollection();
前の記事で作成された標準グラフィカルオブジェクトを作成するメソッドには、大きな繰り返しコードチャンクがあります。別のprivateメソッドに移動してみましょう。
//--- Event handler void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam); private: //--- Create a new graphical object, return the pointer to the chart management object CChartObjectsControl *CreateNewStdGraphObjectAndGetCtrlObj(const long chart_id, const string name, int subwindow, const ENUM_OBJECT type_object, const datetime time1, const double price1, const datetime time2=0, const double price2=0, const datetime time3=0, const double price3=0, const datetime time4=0, const double price4=0, const datetime time5=0, const double price5=0) { //--- If an object with a chart ID and name is already present in the collection, inform of that and return NULL if(this.IsPresentGraphObjInList(chart_id,name)) { ::Print(DFUN,CMessage::Text(MSG_GRAPH_ELM_COLLECTION_ERR_GR_OBJ_ALREADY_EXISTS)," ChartID ",(string)chart_id,", ",name); return NULL; } //--- If failed to create a new standard graphical object, inform of that and return NULL if(!this.CreateNewStdGraphObject(chart_id,name,type_object,subwindow,time1,0)) { ::Print(DFUN,CMessage::Text(MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_STD_GRAPH_OBJ),StdGraphObjectTypeDescription(type_object)); CMessage::ToLog(::GetLastError(),true); return NULL; } //--- If failed to get a chart management object, inform of that CChartObjectsControl *ctrl=this.GetChartObjectCtrlObj(chart_id); if(ctrl==NULL) ::Print(DFUN,CMessage::Text(MSG_GRAPH_ELM_COLLECTION_ERR_FAILED_GET_CTRL_OBJ),(string)chart_id); //--- Return the pointer to a chart management object or NULL in case of a failed attempt to get it return ctrl; } //--- Add a newly created object to the list bool AddCreatedObjToList(const string source,const long chart_id,const string name,CGStdGraphObj *obj) { bool res=true; if(!this.m_list_all_graph_obj.Add(obj)) { CMessage::ToLog(source,MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST); ::ObjectDelete(chart_id,name); delete obj; res=false; } ::ChartRedraw(chart_id); return res; } public: //--- Create the "Vertical line" graphical object
標準グラフィカルオブジェクトを作成するためのすべてのメソッドで、メソッドの操作結果を返します。
public: //--- Create the "Vertical line" graphical object bool CreateLineVertical(const long chart_id,const string name,const int subwindow,const datetime time) { //--- Set the name and type of a created object string nm=this.m_name_program+"_"+name; ENUM_OBJECT type_object=OBJ_VLINE; //--- Create a new graphical object and get the pointer to the chart management object CChartObjectsControl *ctrl=this.CreateNewStdGraphObjectAndGetCtrlObj(chart_id,nm,subwindow,type_object,time,0); if(ctrl==NULL) return false; //--- Create a new class object corresponding to the newly created graphical object CGStdVLineObj *obj=ctrl.CreateNewGraphObj(type_object,nm); if(obj==NULL) { ::Print(DFUN,CMessage::Text(MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_CLASS_OBJ),StdGraphObjectTypeDescription(type_object)); return false; } //--- Set the necessary minimal parameters for an object obj.SetBelong(GRAPH_OBJ_BELONG_PROGRAM); obj.SetFlagSelectable(true,false); obj.SetFlagSelected(true,false); obj.SetObjectID(this.GetFreeGraphObjID(true)); obj.PropertiesCopyToPrevData(); //--- Return the result of adding the object to the list return this.AddCreatedObjToList(DFUN,chart_id,nm,obj); }
また、グラフィカルオブジェクトのプロパティの値を設定するために新しく変更されたメソッドの正しい操作に必要なフラグを設定します。
標準グラフィカルオブジェクトを作成するための他のすべてのメソッドは、同じように変更されます。 ここでそれらを検討する意味はありません。以下の添付ファイルでご覧ください。
指定したチャートのグラフィカルオブジェクトを管理してリストに追加する新しいオブジェクトを作成するメソッドでは、イベント制御指標がチャートに追加されたときに操作ログにメッセージを追加するようにします 。
//+------------------------------------------------------------------+ //| Create a new graphical object management object | //| for a specified and add it to the list | //+------------------------------------------------------------------+ CChartObjectsControl *CGraphElementsCollection::CreateChartObjectCtrlObj(const long chart_id) { //--- Create a new object for managing chart objects by ID CChartObjectsControl *obj=new CChartObjectsControl(chart_id); //--- If the object is not created, inform of the error and return NULL if(obj==NULL) { ::Print(DFUN,CMessage::Text(MSG_GRAPH_ELM_COLLECTION_ERR_FAILED_CREATE_CTRL_OBJ),(string)chart_id); return NULL; } //--- If failed to add the object to the list, inform of the error, remove the object and return NULL if(!this.m_list_charts_control.Add(obj)) { CMessage::ToLog(DFUN,MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST); delete obj; return NULL; } if(obj.ChartID()!=CBaseObj::GetMainChartID() && obj.CreateEventControlInd(CBaseObj::GetMainChartID())) if(!obj.AddEventControlInd()) { CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_FAILED_ADD_EVN_CTRL_INDICATOR); CMessage::ToLog(DFUN,::GetLastError(),true); } else ::Print(DFUN,CMessage::Text(MSG_GRAPH_OBJ_ADDED_EVN_CTRL_INDICATOR),obj.Symbol()," #",obj.ChartID()); //--- Return the pointer to the object that was created and added to the list return obj; } //+------------------------------------------------------------------+
すべてのグラフィカルオブジェクトのリストを更新するメソッドでは、削除された検出済みコレクションリストオブジェクトを単に操作ログに表示するのではなく、グラフィカルオブジェクト削除イベントを送信します。
//+------------------------------------------------------------------+ //| Update the list of all graphical objects | //+------------------------------------------------------------------+ void CGraphElementsCollection::Refresh(void) { this.RefreshForExtraObjects(); //--- Declare variables to search for charts long chart_id=0; int i=0; //--- In the loop by all open charts in the terminal (no more than 100) while(i<CHARTS_MAX) { //--- Get the chart ID chart_id=::ChartNext(chart_id); if(chart_id<0) break; //--- Get the pointer to the object for managing graphical objects //--- and update the list of graphical objects by chart ID CChartObjectsControl *obj_ctrl=this.RefreshByChartID(chart_id); //--- If failed to get the pointer, move on to the next chart if(obj_ctrl==NULL) continue; //--- If the number of objects on the chart changes if(obj_ctrl.IsEvent()) { //--- If a graphical object is added to the chart if(obj_ctrl.Delta()>0) { //--- Get the list of added graphical objects and move them to the collection list //--- (if failed to move the object to the collection, move on to the next object) if(!this.AddGraphObjToCollection(DFUN_ERR_LINE,obj_ctrl)) continue; } //--- If the graphical object has been removed else if(obj_ctrl.Delta()<0) { // Find an extra object in the list CGStdGraphObj *obj=this.FindMissingObj(chart_id); if(obj!=NULL) { //--- Send an event to the control program chart ::EventChartCustom(this.m_chart_id_main,GRAPH_OBJ_EVENT_DELETE,obj.ChartID(),0,obj.Name()); //--- Remove the class object of a removed graphical object from the collection list if(!this.DeleteGraphObjFromList(obj)) CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_FAILED_DETACH_OBJ_FROM_LIST); } } } //--- Increase the loop index i++; } } //+------------------------------------------------------------------+
イベント文字列パラメータで、削除されたオブジェクトの名前を渡します。おそらく、削除されたオブジェクトを別のリストに保存するための実装をおこないます。これにより、削除イベントを受け取ったときに、削除されたオブジェクトとそのプロパティを定義したり、プログラムで復元したりできるようになります。
チャートウィンドウの削除を処理するメソッドでは、単純な操作ログメッセージの代わりに、制御プログラムチャートにもイベントを送信します。
//+------------------------------------------------------------------+ //| Handle removing the chart window | //+------------------------------------------------------------------+ void CGraphElementsCollection::RefreshForExtraObjects(void) { for(int i=this.m_list_charts_control.Total()-1;i>WRONG_VALUE;i--) { CChartObjectsControl *obj_ctrl=this.m_list_charts_control.At(i); if(obj_ctrl==NULL) continue; if(!this.IsPresentChartWindow(obj_ctrl.ChartID())) { long chart_id=obj_ctrl.ChartID(); string chart_symb=obj_ctrl.Symbol(); int total_ctrl=this.m_list_charts_control.Total(); this.DeleteGraphObjCtrlObjFromList(obj_ctrl); int total_obj=this.m_list_all_graph_obj.Total(); this.DeleteGraphObjectsFromList(chart_id); int del_ctrl=total_ctrl-this.m_list_charts_control.Total(); int del_obj=total_obj-this.m_list_all_graph_obj.Total(); ::EventChartCustom(this.m_chart_id_main,GRAPH_OBJ_EVENT_DEL_CHART,chart_id,del_obj,chart_symb); } } } //+------------------------------------------------------------------+
ここでは、閉じられたチャートのID、そのチャートと一緒に削除されたグラフィカルオブジェクトの数、閉じられたチャートの銘柄をパラメータの形式で渡します。
グラフィカル要素コレクションクラスイベントのハンドラで、グラフィカルオブジェクトの処理基本イベントを追加します。
//+------------------------------------------------------------------+ //| Event handler | //+------------------------------------------------------------------+ void CGraphElementsCollection::OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { CGStdGraphObj *obj=NULL; ushort idx=ushort(id-CHARTEVENT_CUSTOM); if(id==CHARTEVENT_OBJECT_CHANGE || id==CHARTEVENT_OBJECT_DRAG || id==CHARTEVENT_OBJECT_CLICK || idx==CHARTEVENT_OBJECT_CHANGE || idx==CHARTEVENT_OBJECT_DRAG || idx==CHARTEVENT_OBJECT_CLICK) { //--- Calculate the chart ID //--- If the event ID corresponds to an event from the current chart, the chart ID is received from ChartID //--- If the event ID corresponds to a user event, the chart ID is received from lparam //--- Otherwise, the chart ID is assigned to -1 long param=(id==CHARTEVENT_OBJECT_CLICK ? ::ChartID() : idx==CHARTEVENT_OBJECT_CLICK ? lparam : WRONG_VALUE); long chart_id=(param==WRONG_VALUE ? (lparam==0 ? ::ChartID() : lparam) : param); //--- Get the object, whose properties were changed or which was relocated, //--- from the collection list by its name set in sparam obj=this.GetStdGraphObject(sparam,chart_id); //--- If failed to get the object by its name, it is not on the list, //--- which means its name has been changed if(obj==NULL) { //--- Let's search the list for the object that is not on the chart obj=this.FindMissingObj(chart_id); //--- If failed to find the object here as well, exit if(obj==NULL) return; //--- Get the name of the renamed graphical object on the chart, which is not in the collection list string name_new=this.FindExtraObj(chart_id); //--- Send an event with the old name of an object to the control program chart and //--- set a new name for the collection list object, which does not correspond to any graphical object on the chart ::EventChartCustom(this.m_chart_id_main,GRAPH_OBJ_EVENT_RENAME,obj.ChartID(),0,obj.Name()); obj.SetName(name_new); } //--- Update the properties of the obtained object //--- and check their change obj.PropertiesRefresh(); obj.PropertiesCheckChanged(); } //--- Handle standard graphical object events if(idx>GRAPH_OBJ_EVENT_NO_EVENT && idx<GRAPH_OBJ_EVENTS_NEXT_CODE) { //--- Depending on the event type, display an appropriate message in the journal switch(idx) { case GRAPH_OBJ_EVENT_CREATE : ::Print(DFUN,CMessage::Text(MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_CREATE)); obj=this.GetStdGraphObject(sparam,lparam); if(obj!=NULL) obj.PrintShort(); break; case GRAPH_OBJ_EVENT_CHANGE : ::Print(DFUN,CMessage::Text(MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_CHANGE)); obj=this.GetStdGraphObject(sparam,lparam); if(obj!=NULL) obj.PrintShort(); break; case GRAPH_OBJ_EVENT_RENAME : ::Print(DFUN,CMessage::Text(MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_RENAME)); obj=this.GetStdGraphObject(sparam,lparam); if(obj!=NULL) obj.PrintShort(); break; case GRAPH_OBJ_EVENT_DELETE : ::Print(DFUN,CMessage::Text(MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_DELETE)); break; case GRAPH_OBJ_EVENT_DEL_CHART: ::Print(DFUN,CMessage::Text(MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_DEL_CHART),": ChartID: ",lparam,", ChartSymbol: ",sparam); break; default: break; } } } //+------------------------------------------------------------------+
メソッドのロジックは、コードのコメントで説明されています。ここで、チャートをクリックしたときの応答を追加しました。ダブルクリックの場合、オブジェクトは選択ステータスを変更し、オブジェクトパラメータ変更イベントを引き起こします。したがって、オブジェクトの選択/選択解除イベントを処理できます。
最後に、すでに処理されたグラフィカルオブジェクトイベント(基本イベントが作成されている)が同じメソッドに到着します。これらの基本イベントは、新しいコードブロックで処理されます。現在、ここでは操作ログにのみメッセージを送信しています。以降の記事では、プログラムが変更されたオブジェクトとそのプロパティを認識してすばやくアクセスできるように、各イベントの本格的な処理を作成します。
グラフィカルオブジェクトの処理を簡素化するには、\MQL5\Include\DoEasy\Engine.mqhにあるCEngineライブラリのメインクラスにグラフィカルオブジェクトを処理するためのメソッドを作成します。
標準グラフィカルオブジェクトクラスを使用して開いているチャートを定義するには、チャート管理オブジェクトのリストを確認できます。このリストを使用すると、開いているすべてのチャートのIDをオブジェクトから取得できるため、それらにアクセスできるようになります。プログラムでのIDの受信を簡素化するために、渡された、コントロールオブジェクトが作成され開かれたチャートIDのlong配列を設定するメソッドを作成します。
//--- Launch the new pause countdown void Pause(const ulong pause_msc,const datetime time_start=0) { this.PauseSetWaitingMSC(pause_msc); this.PauseSetTimeBegin(time_start*1000); while(!this.PauseIsCompleted() && !::IsStopped()){} } //--- Return the graphical object collection CGraphElementsCollection *GetGraphicObjCollection(void) { return &this.m_graph_objects; } //--- Fill in the array with IDs of the charts opened in the terminal void GraphGetArrayChartsID(long &array_charts_id[]) { CArrayObj *list=this.m_graph_objects.GetListChartsControl(); if(list==NULL) return; ::ArrayResize(array_charts_id,list.Total()); ::ArrayInitialize(array_charts_id,WRONG_VALUE); for(int i=0;i<list.Total();i++) { CChartObjectsControl *obj=list.At(i); if(obj==NULL) continue; array_charts_id[i]=obj.ChartID(); } } //--- Create the "Vertical line" graphical object
ここでは、すぐに渡された配列のサイズをチャート管理オブジェクトリストのサイズと等しく設定し、配列を-1の値で初期化します。これは、ループでチャート管理オブジェクトを受信するときにエラーが発生した場合に、取得できなかったチャート管理オブジェクトのインデックスに対応する配列セルに-1を設定するために必要で、オブジェクトを取得するときのエラー信号として機能します。
もちろん、ループ内の配列サイズはオブジェクトが正常に受信された場合にのみ増やすことができますが、ループ内でArrayResize()を呼び出すと、パフォーマンスが低下するため、リストサイズに応じてすぐに配列を増やします。エラーが発生した場合、適切な配列セルには-1が含まれます。
次に、取得したリストのループで、次のチャート管理オブジェクトを取得し、チャートID(チャート管理オブジェクトに含まれる)をループインデックスに対応する配列セルに書き込みます。
標準グラフィカルオブジェクトを作成するためのメソッドに簡単にアクセスするには、オブジェクトごとに2つの作成メソッドを記述します。 最初のメソッドは同じ名前のグラフィカル要素コレクションクラスを呼び出して標準グラフィカルオブジェクトを作成し、2番目のメソッドは現在のチャートIDを指定して最初のメソッドを呼び出します 。
//--- Create the "Vertical line" graphical object bool CreateLineVertical(const long chart_id,const string name,const int subwindow,const datetime time) { return this.m_graph_objects.CreateLineVertical(chart_id,name,subwindow,time); } bool CreateLineVertical(const string name,const int subwindow,const datetime time) { return this.CreateLineVertical(::ChartID(),name,subwindow,time); } //--- Create the "Horizontal line" graphical object bool CreateLineHorizontal(const long chart_id,const string name,const int subwindow,const double price) { return this.m_graph_objects.CreateLineHorizontal(chart_id,name,subwindow,price); } bool CreateLineHorizontal(const string name,const int subwindow,const double price) { return this.CreateLineHorizontal(::ChartID(),name,subwindow,price); } //--- Create the "Trend line" graphical object bool CreateLineTrend(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.m_graph_objects.CreateLineTrend(chart_id,name,subwindow,time1,price1,time2,price2); } bool CreateLineTrend(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.CreateLineTrend(::ChartID(),name,subwindow,time1,price1,time2,price2); } //--- Create the "Trend line by angle" graphical object bool CreateLineTrendByAngle(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const double angle) { return this.m_graph_objects.CreateLineTrendByAngle(chart_id,name,subwindow,time1,price1,time2,price2,angle); } bool CreateLineTrendByAngle(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const double angle) { return this.CreateLineTrendByAngle(::ChartID(),name,subwindow,time1,price1,time2,price2,angle); } //--- Create the "Cyclic lines" graphical object bool CreateLineCycle(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.m_graph_objects.CreateLineCycle(chart_id,name,subwindow,time1,price1,time2,price2); } bool CreateLineCycle(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.CreateLineCycle(::ChartID(),name,subwindow,time1,price1,time2,price2); } //--- Create the "Arrowed line" graphical object bool CreateLineArrowed(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.m_graph_objects.CreateLineArrowed(chart_id,name,subwindow,time1,price1,time2,price2); } bool CreateLineArrowed(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.CreateLineArrowed(::ChartID(),name,subwindow,time1,price1,time2,price2); } //--- Create the "Equidistant channel" graphical object bool CreateChannel(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const datetime time3,const double price3) { return this.m_graph_objects.CreateChannel(chart_id,name,subwindow,time1,price1,time2,price2,time3,price3); } bool CreateChannel(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const datetime time3,const double price3) { return this.CreateChannel(::ChartID(),name,subwindow,time1,price1,time2,price2,time3,price3); } //--- Create the "Standard deviation channel" graphical object bool CreateChannelStdDeviation(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const double deviation=1.5) { return this.m_graph_objects.CreateChannelStdDeviation(chart_id,name,subwindow,time1,price1,time2,price2,deviation); } bool CreateChannelStdDeviation(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const double deviation=1.5) { return this.CreateChannelStdDeviation(::ChartID(),name,subwindow,time1,price1,time2,price2,deviation); } //--- Create the "Linear regression channel" graphical object bool CreateChannelRegression(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.m_graph_objects.CreateChannelRegression(chart_id,name,subwindow,time1,price1,time2,price2); } bool CreateChannelRegression(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.CreateChannelRegression(::ChartID(),name,subwindow,time1,price1,time2,price2); } //--- Create the "Andrews' Pitchfork" graphical object bool CreatePitchforkAndrews(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const datetime time3,const double price3) { return this.m_graph_objects.CreatePitchforkAndrews(chart_id,name,subwindow,time1,price1,time2,price2,time3,price3); } bool CreatePitchforkAndrews(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const datetime time3,const double price3) { return this.CreatePitchforkAndrews(::ChartID(),name,subwindow,time1,price1,time2,price2,time3,price3); } //--- Create the "Gann line" graphical object bool CreateGannLine(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const double angle) { return this.m_graph_objects.CreateGannLine(chart_id,name,subwindow,time1,price1,time2,price2,angle); } bool CreateGannLine(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const double angle) { return this.CreateGannLine(::ChartID(),name,subwindow,time1,price1,time2,price2,angle); } //--- Create the "Gann fan" graphical object bool CreateGannFan(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const ENUM_GANN_DIRECTION direction,const double scale) { return this.m_graph_objects.CreateGannFan(chart_id,name,subwindow,time1,price1,time2,price2,direction,scale); } bool CreateGannFan(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const ENUM_GANN_DIRECTION direction,const double scale) { return this.CreateGannFan(::ChartID(),name,subwindow,time1,price1,time2,price2,direction,scale); } //--- Create the "Gann grid" graphical object bool CreateGannGrid(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2, const ENUM_GANN_DIRECTION direction,const double scale) { return this.m_graph_objects.CreateGannGrid(chart_id,name,subwindow,time1,price1,time2,direction,scale); } bool CreateGannGrid(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2, const ENUM_GANN_DIRECTION direction,const double scale) { return this.CreateGannGrid(::ChartID(),name,subwindow,time1,price1,time2,direction,scale); } //--- Create the "Fibo levels" graphical object bool CreateFiboLevels(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.m_graph_objects.CreateFiboLevels(chart_id,name,subwindow,time1,price1,time2,price2); } bool CreateFiboLevels(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.CreateFiboLevels(::ChartID(),name,subwindow,time1,price1,time2,price2); } //--- Create the "Fibo Time Zones" graphical object bool CreateFiboTimeZones(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.m_graph_objects.CreateFiboTimeZones(chart_id,name,subwindow,time1,price1,time2,price2); } bool CreateFiboTimeZones(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.CreateFiboTimeZones(::ChartID(),name,subwindow,time1,price1,time2,price2); } //--- Create the "Fibo fan" graphical object bool CreateFiboFan(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.m_graph_objects.CreateFiboFan(chart_id,name,subwindow,time1,price1,time2,price2); } bool CreateFiboFan(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.CreateFiboFan(::ChartID(),name,subwindow,time1,price1,time2,price2); } //--- Create the "Fibo arc" graphical object bool CreateFiboArc(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const double scale,const bool ellipse) { return this.m_graph_objects.CreateFiboArc(chart_id,name,subwindow,time1,price1,time2,price2,scale,ellipse); } bool CreateFiboArc(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const double scale,const bool ellipse) { return this.CreateFiboArc(::ChartID(),name,subwindow,time1,price1,time2,price2,scale,ellipse); } //--- Create the "Fibo channel" graphical object bool CreateFiboChannel(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const datetime time3,const double price3) { return this.m_graph_objects.CreateFiboChannel(chart_id,name,subwindow,time1,price1,time2,price2,time3,price3); } bool CreateFiboChannel(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const datetime time3,const double price3) { return this.CreateFiboChannel(::ChartID(),name,subwindow,time1,price1,time2,price2,time3,price3); } //--- Create the "Fibo extension" graphical object bool CreateFiboExpansion(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const datetime time3,const double price3) { return this.m_graph_objects.CreateFiboExpansion(chart_id,name,subwindow,time1,price1,time2,price2,time3,price3); } bool CreateFiboExpansion(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const datetime time3,const double price3) { return this.CreateFiboExpansion(::ChartID(),name,subwindow,time1,price1,time2,price2,time3,price3); } //--- Create the "Elliott 5 waves" graphical object bool CreateElliothWave5(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const datetime time3,const double price3,const datetime time4,const double price4, const datetime time5,const double price5,const ENUM_ELLIOT_WAVE_DEGREE degree, const bool draw_lines) { return this.m_graph_objects.CreateElliothWave5(chart_id,name,subwindow,time1,price1,time2,price2,time3,price3,time4,price4,time5,price5,degree,draw_lines); } bool CreateElliothWave5(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2, const datetime time3,const double price3,const datetime time4,const double price4, const datetime time5,const double price5,const ENUM_ELLIOT_WAVE_DEGREE degree, const bool draw_lines) { return this.CreateElliothWave5(::ChartID(),name,subwindow,time1,price1,time2,price2,time3,price3,time4,price4,time5,price5,degree,draw_lines); } //--- Create the "Elliott 3 waves" graphical object bool CreateElliothWave3(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2, const double price2,const datetime time3,const double price3, const ENUM_ELLIOT_WAVE_DEGREE degree,const bool draw_lines) { return this.m_graph_objects.CreateElliothWave3(chart_id,name,subwindow,time1,price1,time2,price2,time3,price3,degree,draw_lines); } bool CreateElliothWave3(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2, const double price2,const datetime time3,const double price3, const ENUM_ELLIOT_WAVE_DEGREE degree,const bool draw_lines) { return this.CreateElliothWave3(::ChartID(),name,subwindow,time1,price1,time2,price2,time3,price3,degree,draw_lines); } //--- Create the Rectangle graphical object bool CreateRectangle(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.m_graph_objects.CreateRectangle(chart_id,name,subwindow,time1,price1,time2,price2); } bool CreateRectangle(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2) { return this.CreateRectangle(::ChartID(),name,subwindow,time1,price1,time2,price2); } //--- Create the Triangle graphical object bool CreateTriangle(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const datetime time3,const double price3) { return this.m_graph_objects.CreateTriangle(chart_id,name,subwindow,time1,price1,time2,price2,time3,price3); } bool CreateTriangle(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const datetime time3,const double price3) { return this.CreateTriangle(::ChartID(),name,subwindow,time1,price1,time2,price2,time3,price3); } //--- Create the Ellipse graphical object bool CreateEllipse(const long chart_id,const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const datetime time3,const double price3) { return this.m_graph_objects.CreateEllipse(chart_id,name,subwindow,time1,price1,time2,price2,time3,price3); } bool CreateEllipse(const string name,const int subwindow, const datetime time1,const double price1,const datetime time2,const double price2,const datetime time3,const double price3) { return this.CreateEllipse(::ChartID(),name,subwindow,time1,price1,time2,price2,time3,price3); } //--- Create the "Thumb up" graphical object bool CreateThumbUp(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreateThumbUp(chart_id,name,subwindow,time,price); } bool CreateThumbUp(const string name,const int subwindow,const datetime time,const double price) { return this.CreateThumbUp(::ChartID(),name,subwindow,time,price); } //--- Create the "Thumb down" graphical object bool CreateThumbDown(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreateThumbDown(chart_id,name,subwindow,time,price); } bool CreateThumbDown(const string name,const int subwindow,const datetime time,const double price) { return this.CreateThumbDown(::ChartID(),name,subwindow,time,price); } //--- Create the "Arrow up" graphical object bool CreateArrowUp(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreateArrowUp(chart_id,name,subwindow,time,price); } bool CreateArrowUp(const string name,const int subwindow,const datetime time,const double price) { return this.CreateArrowUp(::ChartID(),name,subwindow,time,price); } //--- Create the "Arrow down" graphical object bool CreateArrowDown(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreateArrowDown(chart_id,name,subwindow,time,price); } bool CreateArrowDown(const string name,const int subwindow,const datetime time,const double price) { return this.CreateArrowDown(::ChartID(),name,subwindow,time,price); } //--- Create the Stop graphical object bool CreateSignalStop(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreateSignalStop(chart_id,name,subwindow,time,price); } bool CreateSignalStop(const string name,const int subwindow,const datetime time,const double price) { return this.CreateSignalStop(::ChartID(),name,subwindow,time,price); } //--- Create the "Check mark" graphical object bool CreateSignalCheck(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreateSignalCheck(chart_id,name,subwindow,time,price); } bool CreateSignalCheck(const string name,const int subwindow,const datetime time,const double price) { return this.CreateSignalCheck(::ChartID(),name,subwindow,time,price); } //--- Create the "Left price label" graphical object bool CreatePriceLabelLeft(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreatePriceLabelLeft(chart_id,name,subwindow,time,price); } bool CreatePriceLabelLeft(const string name,const int subwindow,const datetime time,const double price) { return this.CreatePriceLabelLeft(::ChartID(),name,subwindow,time,price); } //--- Create the "Right price label" graphical object bool CreatePriceLabelRight(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreatePriceLabelRight(chart_id,name,subwindow,time,price); } bool CreatePriceLabelRight(const string name,const int subwindow,const datetime time,const double price) { return this.CreatePriceLabelRight(::ChartID(),name,subwindow,time,price); } //--- Create the Buy graphical object bool CreateSignalBuy(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreateSignalBuy(chart_id,name,subwindow,time,price); } bool CreateSignalBuy(const string name,const int subwindow,const datetime time,const double price) { return this.CreateSignalBuy(::ChartID(),name,subwindow,time,price); } //--- Create the Sell graphical object bool CreateSignalSell(const long chart_id,const string name,const int subwindow,const datetime time,const double price) { return this.m_graph_objects.CreateSignalSell(chart_id,name,subwindow,time,price); } bool CreateSignalSell(const string name,const int subwindow,const datetime time,const double price) { return this.CreateSignalSell(::ChartID(),name,subwindow,time,price); } //--- Create the Arrow graphical object bool CreateArrow(const long chart_id,const string name,const int subwindow,const datetime time,const double price, const uchar arrow_code,const ENUM_ARROW_ANCHOR anchor) { return this.m_graph_objects.CreateArrow(chart_id,name,subwindow,time,price,arrow_code,anchor); } bool CreateArrow(const string name,const int subwindow,const datetime time,const double price, const uchar arrow_code,const ENUM_ARROW_ANCHOR anchor) { return this.CreateArrow(::ChartID(),name,subwindow,time,price,arrow_code,anchor); } //--- Create the Text graphical object bool CreateText(const long chart_id,const string name,const int subwindow,const datetime time,const double price, const string text,const int size,const ENUM_ANCHOR_POINT anchor_point,const double angle) { return this.m_graph_objects.CreateText(chart_id,name,subwindow,time,price,text,size,anchor_point,angle); } bool CreateText(const string name,const int subwindow,const datetime time,const double price, const string text,const int size,const ENUM_ANCHOR_POINT anchor_point,const double angle) { return this.CreateText(::ChartID(),name,subwindow,time,price,text,size,anchor_point,angle); } //--- Create the "Text label" graphical object bool CreateTextLabel(const long chart_id,const string name,const int subwindow,const int x,const int y, const string text,const int size,const ENUM_BASE_CORNER corner, const ENUM_ANCHOR_POINT anchor_point,const double angle) { return this.m_graph_objects.CreateTextLabel(chart_id,name,subwindow,x,y,text,size,corner,anchor_point,angle); } bool CreateTextLabel(const string name,const int subwindow,const int x,const int y, const string text,const int size,const ENUM_BASE_CORNER corner, const ENUM_ANCHOR_POINT anchor_point,const double angle) { return this.CreateTextLabel(::ChartID(),name,subwindow,x,y,text,size,corner,anchor_point,angle); } //--- Create the Button graphical object bool CreateButton(const long chart_id,const string name,const int subwindow,const int x,const int y,const int w,const int h, const ENUM_BASE_CORNER corner,const int font_size,const bool button_state) { return this.m_graph_objects.CreateButton(chart_id,name,subwindow,x,y,w,h,corner,font_size,button_state); } bool CreateButton(const string name,const int subwindow,const int x,const int y,const int w,const int h, const ENUM_BASE_CORNER corner,const int font_size,const bool button_state) { return this.CreateButton(::ChartID(),name,subwindow,x,y,w,h,corner,font_size,button_state); } //--- Create the Chart graphical object bool CreateChart(const long chart_id,const string name,const int subwindow,const int x,const int y,const int w,const int h, const ENUM_BASE_CORNER corner,const int scale,const string symbol,const ENUM_TIMEFRAMES timeframe) { return this.m_graph_objects.CreateChart(chart_id,name,subwindow,x,y,w,h,corner,scale,symbol,timeframe); } bool CreateChart(const string name,const int subwindow,const int x,const int y,const int w,const int h, const ENUM_BASE_CORNER corner,const int scale,const string symbol,const ENUM_TIMEFRAMES timeframe) { return this.CreateChart(::ChartID(),name,subwindow,x,y,w,h,corner,scale,symbol,timeframe); } //--- Create the Bitmap graphical object bool CreateBitmap(const long chart_id,const string name,const int subwindow,const datetime time,const double price, const string image1,const string image2,const ENUM_ANCHOR_POINT anchor) { return this.m_graph_objects.CreateBitmap(chart_id,name,subwindow,time,price,image1,image2,anchor); } bool CreateBitmap(const string name,const int subwindow,const datetime time,const double price, const string image1,const string image2,const ENUM_ANCHOR_POINT anchor) { return this.CreateBitmap(::ChartID(),name,subwindow,time,price,image1,image2,anchor); } //--- Create the "Bitmap label" graphical object bool CreateBitmapLabel(const long chart_id,const string name,const int subwindow,const int x,const int y,const int w,const int h, const string image1,const string image2,const ENUM_BASE_CORNER corner,const ENUM_ANCHOR_POINT anchor, const bool state) { return this.m_graph_objects.CreateBitmapLabel(chart_id,name,subwindow,x,y,w,h,image1,image2,corner,anchor,state); } bool CreateBitmapLabel(const string name,const int subwindow,const int x,const int y,const int w,const int h, const string image1,const string image2,const ENUM_BASE_CORNER corner,const ENUM_ANCHOR_POINT anchor, const bool state) { return this.CreateBitmapLabel(::ChartID(),name,subwindow,x,y,w,h,image1,image2,corner,anchor,state); } //--- Create the "Input field" graphical object bool CreateEditField(const long chart_id,const string name,const int subwindow,const int x,const int y,const int w,const int h, const int font_size,const ENUM_BASE_CORNER corner,const ENUM_ALIGN_MODE align,const bool readonly) { return this.m_graph_objects.CreateEditField(chart_id,name,subwindow,x,y,w,h,font_size,corner,align,readonly); } bool CreateEditField(const string name,const int subwindow,const int x,const int y,const int w,const int h, const int font_size,const ENUM_BASE_CORNER corner,const ENUM_ALIGN_MODE align,const bool readonly) { return this.CreateEditField(::ChartID(),name,subwindow,x,y,w,h,font_size,corner,align,readonly); } //--- Create the "Economic calendar event" graphical object bool CreateCalendarEvent(const long chart_id,const string name,const int subwindow,const datetime time) { return this.m_graph_objects.CreateCalendarEvent(chart_id,name,subwindow,time); } bool CreateCalendarEvent(const string name,const int subwindow,const datetime time) { return this.CreateCalendarEvent(::ChartID(),name,subwindow,time); } //--- Create the "Rectangular label" graphical object bool CreateRectangleLabel(const long chart_id,const string name,const int subwindow,const int x,const int y,const int w,const int h, const ENUM_BASE_CORNER corner,const ENUM_BORDER_TYPE border) { return this.m_graph_objects.CreateRectangleLabel(chart_id,name,subwindow,x,y,w,h,corner,border); } bool CreateRectangleLabel(const string name,const int subwindow,const int x,const int y,const int w,const int h, const ENUM_BASE_CORNER corner,const ENUM_BORDER_TYPE border) { return this.CreateRectangleLabel(::ChartID(),name,subwindow,x,y,w,h,corner,border); } //--- Constructor/destructor CEngine(); ~CEngine();
今のところ、グラフィカルオブジェクトイベントの追跡を目的とした基本機能を作成するために必要な改善はこれですべてです。
テスト
テストを実行するには、前の記事のEAを使用して\MQL5\Experts\TestDoEasy\Part90\ TestDoEasyPart90.mq5として保存します。
前回の記事では、Ctrlキーを押しながらチャートをクリックすると縦線が作成されました。これをターミナルで開いているすべてのチャートに作成するようにします。
OnChartEvent()ハンドラのチャートクリック処理コードブロックに、開いているすべてのチャートのIDを配列に入力するためのコードを追加します。取得した配列によるループでは各チャートに垂直線を作成します。
if(id==CHARTEVENT_CLICK) { if(!IsCtrlKeyPressed()) return; datetime time=0; double price=0; int sw=0; if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,sw,time,price)) { long array[]; engine.GraphGetArrayChartsID(array); for(int i=0;i<ArraySize(array);i++) engine.CreateLineVertical(array[i],"LineVertical",0,time); } } engine.GetGraphicObjCollection().OnChartEvent(id,lparam,dparam,sparam); } //+------------------------------------------------------------------+
EAをコンパイルし、別のチャートを開いて両方のチャートを水平に配置した後、EAをチャート上で起動します。EAのあるチャートをクリックすると、垂直線が作成されます(チャートごとに1本の線)。次に、プロパティを変更して、取得したイベントに関するメッセージが操作ログにどのように表示されるかを確認します。
ご覧のとおり、オブジェクトイベントに関するメッセージが操作ログに表示されています。プログラムでオブジェクトを作成する場合、プログラマーはグラフィカルオブジェクトが作成される時点をすでに知っているため、オブジェクト作成イベントは作成されません。したがって、イベントを送信してファクトを複製する必要はありません。
もちろん、操作ログ内の一般化されたメッセージの単純な表示は、イベントを処理するには不十分です。ただし、これらは、後で定義されたイベントに関するすべてのデータがパラメータに含まれている基本イベントに関するメッセージのみです。
次の段階
次の記事では、グラフィカルオブジェクトイベントでの作業を継続し、取得した各イベントの処理を実装します。
*連載のこれまでの記事:
DoEasyライブラリのグラフィックス(第86部): グラフィカルオブジェクトコレクション - プロパティ変更の管理
DoEasyライブラリのグラフィックス(第87部): グラフィカルオブジェクトコレクション - プロパティ変更の管理
DoEasyライブラリのグラフィックス(第88部): グラフィカルオブジェクトコレクション - 動的に変化するオブジェクトのプロパティを格納するための2次元動的配列
DoEasyライブラリのグラフィックス(第89部): 抽象標準グラフィカルオブジェクトのプログラミング基本機能
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/10139





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索