English Русский 中文 Español Deutsch Português
preview
DoEasy - コントロール(第1部):最初のステップ

DoEasy - コントロール(第1部):最初のステップ

MetaTrader 5 | 21 6月 2022, 14:24
892 0
Artyom Trishkin
Artyom Trishkin

内容


概念

本稿では、Windows Formsスタイルのコントロールを作成するための新しい連載を開始します。もちろん、MS Visual Studioのコントロールのリストに含まれるすべての要素を再現することは不可能です。MQL5を使用してアプリGUIを開発するための最も一般的な要素を実装する予定です。

前のトピックを完了せずに新しいトピックに切り替えたのは、前のトピックで説明したライブラリグラフィカルオブジェクトの開発を続行するためにコントロールを使用する必要があるためです。コントロールなしで物事を管理することはすでに困難になっています。したがって、可能なすべてのコントロールをWindows Formsスタイルで作成します。次に、必要なすべての開発ツールが揃ったら、前のトピックに戻ります。

MS Visual Studioで要素のパネルを開くと、コントロールグループがリスト表示されます。

  • すべてのWindows Forms - 実装に利用できるすべてのフォーム
  • 標準コントロール
  • コンテナ
  • メニューとツールバー
  • データ
  • コンポーネント
  • 印刷
  • ダイアログボックス

MS Visual Studio要素パネルのリストで使用可能なグループはこれだけではありません。このような各グループには、多数の要素が含まれています。それらのすべてがライブラリに必要なわけではないので、絶対必要なものに焦点を当てます。

Panel要素はウィンドウ要素の基礎として機能するため、ここから始めます。さらに、パネルは他のコントロールを格納するためのコンテナであり、すべての要素が格納されたパネルは親パネルに配置でき、その親パネルは別のパネル内のオブジェクトにすることができる、などです。

キャンバス上のグラフィック要素オブジェクトのクラスはすでにあり、CCanvasクラスに基づく他のすべてのグラフィカルオブジェクトの親クラスとなっています。フォームクラスオブジェクトは、グラフィック要素に基づいています。フォームオブジェクトにはすでに、それを操作および移動するための一連の関数が含まれています。パネルオブジェクトは、フォームオブジェクトに基づいて作成されます。フォームオブジェクトに新しいプロパティが追加され、その機能が実装されます。

パネルには、ライブラリ開発の説明の現在のセクション内に作成するコントロールをすべて保存する機能が備わることになります。このパネルでは、ターミナルで動作するアプリケーションの基本ウィンドウとダイアログウィンドウを実装することもできます。

パネルクラスを開発する前に、すでに開発されているライブラリオブジェクトクラスを改善しなければなりません。結局のところ、前のトピックの仕事が終わっていません。既存のライブラリオブジェクトを徐々に完成させ、検出されたエラーを修正していきます。


ライブラリクラスの改善

ターミナルバージョン3260の最後の更新では、銘柄と口座の新しいプロパティが追加されています。

  • MQL5:特定の銘柄のクオート配信の遅延のために、SYMBOL_SUBSCRIPTION_DELAY値をENUM_SYMBOL_INFO_INTEGER列挙に追加しました。
    サブスクリプションに基づいた取引銘柄にのみ使用されます。遅延は通常、デモモードで提供されるデータに適用されます。
    プロパティは、気配値表示で選択された銘柄に対してのみリクエストできます。それ以外に対しては、ERR_MARKET_NOT_SELECTED (4302)エラーが返されます。

  • MQL5:ACCOUNT_HEDGE_ALLOWEDプロパティをENUM_ACCOUNT_INFO_INTEGER列挙に追加しました。反対のポジションと指標注文を開くことができます。プロパティは、口座は同じ銘柄に対して反対のポジションを持つことはできないが同じ方向のポジションを持つことはできるという特定の規制要件にヘッジ口座が準拠するためにのみ使用されます。
    このオプションが無効になっている場合、口座は同じ金融商品に対して反対方向のポジションと注文を持つことはできません。たとえば、口座に買いポジションがある場合、売りポジションを開いたり、売り指値注文を出すことはできません。そのような操作を実行しようとすると、TRADE_RETCODE_HEDGE_PROHIBITEDエラーが返されます。

これらのプロパティを銘柄およびライブラリ口座オブジェクトに追加してみましょう。

\MQL5\Include\DoEasy\Data.mqhに、新しいメッセージインデックスを追加します。

//+------------------------------------------------------------------+
//| List of the library's text message indices                       |
//+------------------------------------------------------------------+
enum ENUM_MESSAGES_LIB
  {
   MSG_LIB_PARAMS_LIST_BEG=ERR_USER_ERROR_FIRST,      // Beginning of the parameter list
   MSG_LIB_PARAMS_LIST_END,                           // End of the parameter list
   MSG_LIB_PROP_NOT_SUPPORTED,                        // Property not supported
   MSG_LIB_PROP_NOT_SUPPORTED_MQL4,                   // Property not supported in MQL4
   MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_2155,          // Property not supported in MetaTrader 5 versions lower than 2155
   MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_3245,          // Property not supported in MetaTrader 5 versions lower than 3245
   MSG_LIB_PROP_NOT_SUPPORTED_POSITION,               // Property not supported for position

...

  
   MSG_SYM_PROP_BACKGROUND_COLOR,                     // Background color of the symbol in Market Watch
   MSG_SYM_PROP_SUBSCRIPTION_DELAY,                   // Delay for quotes passed by symbol for instruments working on subscription basis
   //---

...

   MSG_ACC_PROP_FIFO_CLOSE,                           // Flag of a position closure by FIFO rule only
   MSG_ACC_PROP_HEDGE_ALLOWED,                        // Permission to open opposite positions and set pending orders
   //---
   MSG_ACC_PROP_BALANCE,                              // Account balance

...

   MSG_GRAPH_ELEMENT_TYPE_FORM,                       // Form
   MSG_GRAPH_ELEMENT_TYPE_WINDOW,                     // Window
   MSG_GRAPH_ELEMENT_TYPE_PANEL,                      // Panel control
   MSG_GRAPH_OBJ_BELONG_PROGRAM,                      // Graphical object belongs to a program
   MSG_GRAPH_OBJ_BELONG_NO_PROGRAM,                   // Graphical object does not belong to a program
//---

また、新しく追加されたインデックスに対応するテキストメッセージも追加します。

   {"Свойство не поддерживается в MetaTrader5 версии ниже 2155","The property is not supported in MetaTrader5, build lower than 2155"},
   {"Свойство не поддерживается в MetaTrader5 версии ниже 3245","The property is not supported in MetaTrader5, build lower than 3245"},
   {"Свойство не поддерживается у позиции","Property not supported for position"},

...

   {"Цвет фона символа в Market Watch","Background color of the symbol in Market Watch"},
   {"Размер задержки у котировок, передаваемых по символу, для инструментов, работающих по подписке","Delay size for quotes transmitted per symbol for instruments working by subscription"},
   {"Максимальный Bid за день","Maximum Bid of the day"},

...

   {"Тип торгового сервера","Type of trading server"},
   {"Признак закрытия позиций только по правилу FIFO","Sign of closing positions only according to the FIFO rule"},
   {"Разрешение на открытие встречных позиций и отложенных ордеров","Permission to open opposite positions and pending orders"},
   //---
   {"Баланс счета","Account balance"},

...

   {"Форма","Form"},
   {"Окно","Window"},
   {"Элемент управления \"Panel\"","Control element \"Panel\""},
   {"Графический объект принадлежит программе","The graphic object belongs to the program"},
   {"Графический объект не принадлежит программе","The graphic object does not belong to the program"},


本稿で作成されたパネルオブジェクトには、テキストメッセージのデフォルトパラメータが表示されます。これらのパラメータは、パネルまたはその子孫オブジェクトに表示されるテキスト、またはこれらのオブジェクトのコンテナであると見なされる場合はパネルに添付されるテキストに使用されます。フォント名、サイズ、色のデフォルト値を設定する必要があります。

\MQL5\Include\DoEasy\Defines.mqhを開き、パネル上のこれらのテキストプロパティの新しいマクロ置換を追加します。

//--- Canvas parameters
#define PAUSE_FOR_CANV_UPDATE          (16)                       // Canvas update frequency
#define CLR_CANV_NULL                  (0x00FFFFFF)               // Zero for the canvas with the alpha channel
#define CLR_FORE_COLOR                 (C'0x2D,0x43,0x48')        // Default color for texts of objects on canvas
#define DEF_FONT                       ("Calibri")                // Default font
#define DEF_FONT_SIZE                  (8)                        // Default font size
#define OUTER_AREA_SIZE                (16)                       // Size of one side of the outer area around the form workspace
//--- Graphical object parameters

ライブラリオブジェクトタイプのリストに新しいタイプを追加します。

//+------------------------------------------------------------------+
//| List of library object types                                     |
//+------------------------------------------------------------------+
enum ENUM_OBJECT_DE_TYPE
  {
//--- Graphics
   OBJECT_DE_TYPE_GBASE =  COLLECTION_ID_LIST_END+1,              // "Base object of all library graphical objects" object type
   OBJECT_DE_TYPE_GELEMENT,                                       // "Graphical element" object type
   OBJECT_DE_TYPE_GFORM,                                          // Form object type
   OBJECT_DE_TYPE_GFORM_CONTROL,                                  // "Form for managing pivot points of graphical object" object type
   OBJECT_DE_TYPE_GSHADOW,                                        // Shadow object type
   //--- WinForms
   OBJECT_DE_TYPE_GWF_PANEL,                                      // WinForms Panel object type
//--- Animation
   OBJECT_DE_TYPE_GFRAME,                                         // "Single animation frame" object type
   OBJECT_DE_TYPE_GFRAME_TEXT,                                    // "Single text animation frame" object type
   OBJECT_DE_TYPE_GFRAME_QUAD,                                    // "Single rectangular animation frame" object type
   OBJECT_DE_TYPE_GFRAME_GEOMETRY,                                // "Single geometric animation frame" object type
   OBJECT_DE_TYPE_GANIMATIONS,                                    // "Animations" object type
//--- Managing graphical objects

このセクション(WinForms)では、作成時に新しいオブジェクトタイプを追加します。

口座の整数プロパティの列挙で新しいプロパティを追加し、整数オブジェクトプロパティの数を11から12に増やします

//+------------------------------------------------------------------+
//| Account integer properties                                       |
//+------------------------------------------------------------------+
enum ENUM_ACCOUNT_PROP_INTEGER
  {
   ...
   ACCOUNT_PROP_FIFO_CLOSE,                                 // Flag of a position closure by FIFO rule only
   ACCOUNT_PROP_HEDGE_ALLOWED                               // Permission to open opposite positions and set pending orders
  };
#define ACCOUNT_PROP_INTEGER_TOTAL    (12)                  // Total number of integer properties
#define ACCOUNT_PROP_INTEGER_SKIP     (0)                   // Number of integer account properties not used in sorting
//+------------------------------------------------------------------+

可能な口座の並べ替え基準のリストに新しいプロパティを追加します。

//+------------------------------------------------------------------+
//| Possible account sorting criteria                                |
//+------------------------------------------------------------------+
#define FIRST_ACC_DBL_PROP            (ACCOUNT_PROP_INTEGER_TOTAL-ACCOUNT_PROP_INTEGER_SKIP)
#define FIRST_ACC_STR_PROP            (ACCOUNT_PROP_INTEGER_TOTAL-ACCOUNT_PROP_INTEGER_SKIP+ACCOUNT_PROP_DOUBLE_TOTAL-ACCOUNT_PROP_DOUBLE_SKIP)
enum ENUM_SORT_ACCOUNT_MODE
  {
   ... 
   SORT_BY_ACCOUNT_FIFO_CLOSE,                              // Sort by the flag of a position closure by FIFO rule only
   SORT_BY_ACCOUNT_HEDGE_ALLOWED,                           // Sort by permission to open opposite positions and set pending orders
//--- Sort by real properties
   SORT_BY_ACCOUNT_BALANCE = FIRST_ACC_DBL_PROP,            // Sort by an account balance in the deposit currency
   SORT_BY_ACCOUNT_CREDIT,                                  // Sort by credit in a deposit currency
   ... 
   SORT_BY_ACCOUNT_COMPANY                                  // Sort by a name of a company serving an account
  };
//+------------------------------------------------------------------+


銘柄の整数プロパティの列挙に新しいプロパティを追加し、整数プロパティの数を40から41に増やします

//+------------------------------------------------------------------+
//| Symbol integer properties                                        |
//+------------------------------------------------------------------+
enum ENUM_SYMBOL_PROP_INTEGER
  {
   //--- ...
   SYMBOL_PROP_OPTION_MODE,                                 // Option type (from the ENUM_SYMBOL_OPTION_MODE enumeration)
   SYMBOL_PROP_OPTION_RIGHT,                                // Option right (Call/Put) (from the ENUM_SYMBOL_OPTION_RIGHT enumeration)
   SYMBOL_PROP_SUBSCRIPTION_DELAY,                          // Delay for quotes passed by symbol for instruments working on subscription basis
   //--- skipped property
   SYMBOL_PROP_BACKGROUND_COLOR                             // The color of the background used for the symbol in Market Watch
  }; 
#define SYMBOL_PROP_INTEGER_TOTAL    (41)                   // Total number of integer properties
#define SYMBOL_PROP_INTEGER_SKIP     (1)                    // Number of symbol integer properties not used in sorting
//+------------------------------------------------------------------+

新しいプロパティによる並べ替えを、可能な銘柄の並べ替え基準の列挙に追加します。

//+------------------------------------------------------------------+
//| Possible symbol sorting criteria                                 |
//+------------------------------------------------------------------+
#define FIRST_SYM_DBL_PROP          (SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_INTEGER_SKIP)
#define FIRST_SYM_STR_PROP          (SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_INTEGER_SKIP+SYMBOL_PROP_DOUBLE_TOTAL-SYMBOL_PROP_DOUBLE_SKIP)
enum ENUM_SORT_SYMBOLS_MODE
  {
   ... 
   SORT_BY_SYMBOL_OPTION_MODE,                              // Sort by option type (from the ENUM_SYMBOL_OPTION_MODE enumeration)
   SORT_BY_SYMBOL_OPTION_RIGHT,                             // Sort by option right (Call/Put) (from the ENUM_SYMBOL_OPTION_RIGHT enumeration)
   SORT_BY_SYMBOL_SUBSCRIPTION_DELAY,                       // Sort by delay for quotes passed by symbol for instruments working on subscription basis


グラフィック要素タイプのリストに新しい要素タイプを追加します。

//+------------------------------------------------------------------+
//| The list of graphical element types                              |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_ELEMENT_TYPE
  {
   GRAPH_ELEMENT_TYPE_STANDARD,                       // Standard graphical object
   GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED,              // Extended standard graphical object
   GRAPH_ELEMENT_TYPE_ELEMENT,                        // Element
   GRAPH_ELEMENT_TYPE_SHADOW_OBJ,                     // Shadow object
   GRAPH_ELEMENT_TYPE_FORM,                           // Form
   GRAPH_ELEMENT_TYPE_WINDOW,                         // Window
   //--- WinForms
   GRAPH_ELEMENT_TYPE_PANEL,                          // Windows Forms Panel
  };
//+------------------------------------------------------------------+

後続の各コントロールを作成するとき、そのタイプは列挙のこのサブセクション(WinForms)に入力されます。

別のオブジェクト(コンテナパネルよりも大きい)がパネルオブジェクトに追加され、そのサイズの自動変更がパネルで許可されている場合、次の2つのサイズ変更オプションがあります。

  1. パネルサイズの増加のみ
  2. パネルサイズの増加および減少

前者の場合、配置されたオブジェクトを含まないパネルの側面は、オブジェクトが完全に収まるように拡大されます。後者の場合、上記のアクションに加えて、内部に配置されたオブジェクトよりも大きい辺を短くすることができます。

可能なグラフィカルオブジェクトの並べ替え基準を列挙したすぐ後に、インターフェイス要素のサイズを自動変更するモードを設定する新しい列挙を追加します。

//+------------------------------------------------------------------+
//| Mode of automatic interface element resizing                     |
//+------------------------------------------------------------------+
enum ENUM_CANV_ELEMENT_AUTO_SIZE_MODE
  {
   CANV_ELEMENT_AUTO_SIZE_MODE_GROW,                  // Increase only
   CANV_ELEMENT_AUTO_SIZE_MODE_GROW_SHRINK,           // Increase and decrease
  };
//+------------------------------------------------------------------+

パネル内にオブジェクトを配置する場合、オブジェクトはコンテナの任意の側面(上、下、右、左)に接続することができます。この場合、最も近い側がコンテナオブジェクトの対応する側に「固定」され、接続されたオブジェクトの寸法は、オブジェクトが接続された側に垂直なコンテナ側に引き伸ばされます。たとえば、オブジェクトがコンテナの上端に接続されている場合、オブジェクトの上端はコンテナの上端に引っ張られ、オブジェクトの左側と右側はコンテナの対応する側に引き伸ばされます。オブジェクトの高さは変わりません。コンテナの反対側への接続も同様に機能します。

サイズの自動変更のモードを列挙したすぐ後に、新しい列挙を追加します。

//+------------------------------------------------------------------+
//| Control borders bound to the container                           |
//+------------------------------------------------------------------+
enum ENUM_CANV_ELEMENT_DOCK_MODE
  {
   CANV_ELEMENT_DOCK_MODE_TOP,                        // Attaching to the top and stretching along the container width
   CANV_ELEMENT_DOCK_MODE_BOTTOM,                     // Attaching to the bottom and stretching along the container width
   CANV_ELEMENT_DOCK_MODE_LEFT,                       // Attaching to the left and stretching along the container height
   CANV_ELEMENT_DOCK_MODE_RIGHT,                      // Attaching to the right and stretching along the container height
   CANV_ELEMENT_DOCK_MODE_FILL,                       // Stretching along the entire container width and height
   CANV_ELEMENT_DOCK_MODE_NONE,                       // Attached to the specified coordinates, size does not change
  };
//+------------------------------------------------------------------+

オブジェクトをコンテナに接続する上記の4つのメソッドとは別に、塗りつぶし(オブジェクトのサイズはコンテナのサイズに調整)と接続なし(オブジェクトは、コンテナ内の指定された座標にのみ接続しサイズが変更しない)の2つがあります。

コントロールにユーザーと対話する機能がある場合、そのようなオブジェクトは、特定の条件下(例:ボタンが非アクティブ)では対話できないと見なされる場合があります。要素との相互作用の可能性を示すために、新しいグラフィックプロパティを追加します。

グラフィック要素の整数プロパティの列挙で 新しいプロパティを追加し、オブジェクトの整数プロパティの数を24から25に増やします

//+------------------------------------------------------------------+
//| Integer properties of the graphical element on the canvas        |
//+------------------------------------------------------------------+
enum ENUM_CANV_ELEMENT_PROP_INTEGER
  {
   ... 
   CANV_ELEMENT_PROP_ZORDER,                          // Priority of a graphical object for receiving the event of clicking on a chart
   CANV_ELEMENT_PROP_ENABLED,                         // Element availability flag
  };
#define CANV_ELEMENT_PROP_INTEGER_TOTAL (25)          // Total number of integer properties
#define CANV_ELEMENT_PROP_INTEGER_SKIP  (0)           // Number of integer properties not used in sorting
//+------------------------------------------------------------------+


キャンバス上のグラフィック要素を並べ替える可能性のある基準の列挙に新しいプロパティによる並べ替えを追加します。

//+------------------------------------------------------------------+
//| Possible sorting criteria of graphical elements on the canvas    |
//+------------------------------------------------------------------+
#define FIRST_CANV_ELEMENT_DBL_PROP  (CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP)
#define FIRST_CANV_ELEMENT_STR_PROP  (CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP+CANV_ELEMENT_PROP_DOUBLE_TOTAL-CANV_ELEMENT_PROP_DOUBLE_SKIP)
enum ENUM_SORT_CANV_ELEMENT_MODE
  {
   ... 
   SORT_BY_CANV_ELEMENT_ZORDER,                       // Sort by the priority of a graphical object for receiving the event of clicking on a chart
   SORT_BY_CANV_ELEMENT_ENABLED,                      // Sort by the element availability flag
   ... 
  };
//+------------------------------------------------------------------+


新しい銘柄と口座のプロパティができたので、オブジェクトクラスを改善する必要があります。

\MQL5\Include\DoEasy\Objects\Accounts\Account.mqhを開き、口座オブジェクトクラスを改善します。

オブジェクトプロパティ構造体に新しい整数プロパティを追加します。

//+------------------------------------------------------------------+
//| Account class                                                    |
//+------------------------------------------------------------------+
class CAccount : public CBaseObjExt
  {
private:
   struct SData
     {
      //--- Account integer properties
      ... 
      bool           fifo_close;                   // ACCOUNT_FIFO_CLOSE (The flag indicating that positions can be closed only by the FIFO rule)
      bool           hedge_allowed;                // ACCOUNT_HEDGE_ALLOWED (Permission to open opposite positions and set pending orders)
      ... 
     };
   SData             m_struct_obj;                                      // Account object structure
   uchar             m_uchar_array[];                                   // uchar array of the account object structure
   
//--- Object properties


口座オブジェクトのプロパティへのアクセスを簡素化するために、メソッドのブロックに新しいメソッドを追加します。

//+------------------------------------------------------------------+
//| Methods of a simplified access to the account object properties  |
//+------------------------------------------------------------------+
//--- Return the account's integer properties
   ... 
   bool              FIFOClose(void)                                 const { return (bool)this.GetProperty(ACCOUNT_PROP_FIFO_CLOSE);                              }
   bool              IsHedge(void)                                   const { return this.MarginMode()==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING;                        }
   bool              HedgeAllowed(void)                              const { return (bool)this.GetProperty(ACCOUNT_PROP_HEDGE_ALLOWED);                           }
   ... 

このメソッドは、オブジェクトプロパティ配列に格納されている値を返すだけです。

クラスコンストラクタのオブジェクトプロパティの配列に値を追加します。

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CAccount::CAccount(void)
  {
   this.m_type=OBJECT_DE_TYPE_ACCOUNT;
//--- Initialize control data
   this.SetControlDataArraySizeLong(ACCOUNT_PROP_INTEGER_TOTAL);
   this.SetControlDataArraySizeDouble(ACCOUNT_PROP_DOUBLE_TOTAL);
   this.ResetChangesParams();
   this.ResetControlsParams();
   ... 
   this.m_long_prop[ACCOUNT_PROP_SERVER_TYPE]                        = (::TerminalInfoString(TERMINAL_NAME)=="MetaTrader 5" ? 5 : 4);
   this.m_long_prop[ACCOUNT_PROP_FIFO_CLOSE]                         = (#ifdef __MQL5__::TerminalInfoInteger(TERMINAL_BUILD)<2155 ? false : ::AccountInfoInteger(ACCOUNT_FIFO_CLOSE) #else false #endif );
   this.m_long_prop[ACCOUNT_PROP_HEDGE_ALLOWED]                      = (#ifdef __MQL5__::TerminalInfoInteger(TERMINAL_BUILD)<3245 ? false : ::AccountInfoInteger(ACCOUNT_HEDGE_ALLOWED) #else false #endif );  
   ... 
//--- Update the base object data and search for changes
   CBaseObjExt::Refresh();
  }
//+-------------------------------------------------------------------+

MQL5バージョンが3245未満の場合、そのようなプロパティはないので、falseに設定します。ターミナルバージョンが3245以上の場合は、新しい口座プロパティから値を取得し、それをオブジェクト整数プロパティの配列に設定します。MQL4の場合、そのようなプロパティや他の多くのプロパティがないため、常にfalseに設定します。

すべての口座データを更新するメソッドで、まったく同じ方法で値を新しいオブジェクトプロパティに設定します

//+------------------------------------------------------------------+
//| Update all account data                                          |
//+------------------------------------------------------------------+
void CAccount::Refresh(void)
  {
//--- Initialize event data
   this.m_is_event=false;
   this.m_hash_sum=0;
   ... 
   this.m_long_prop[ACCOUNT_PROP_FIFO_CLOSE]                            = (#ifdef __MQL5__::TerminalInfoInteger(TERMINAL_BUILD)<2155 ? false : ::AccountInfoInteger(ACCOUNT_FIFO_CLOSE) #else false #endif );
   this.m_long_prop[ACCOUNT_PROP_HEDGE_ALLOWED]                         = (#ifdef __MQL5__::TerminalInfoInteger(TERMINAL_BUILD)<3245 ? false : ::AccountInfoInteger(ACCOUNT_HEDGE_ALLOWED) #else false #endif );
   ... 
   CBaseObjExt::Refresh();
   this.CheckEvents();
  }
//+------------------------------------------------------------------+


口座オブジェクト構造体を作成するメソッドで、 構造体の2つのフィールドに入力データを追加します

//+------------------------------------------------------------------+
//| Create the account object structure                              |
//+------------------------------------------------------------------+
bool CAccount::ObjectToStruct(void)
  {
//--- Save integer properties
   ... 
   this.m_struct_obj.server_type=(int)this.ServerType();
   this.m_struct_obj.fifo_close=this.FIFOClose();
   this.m_struct_obj.hedge_allowed=this.HedgeAllowed();
   ... 
   //--- Save the structure to the uchar array
   ::ResetLastError();
   if(!::StructToCharArray(this.m_struct_obj,this.m_uchar_array))
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_SAVE_OBJ_STRUCT_TO_UARRAY),(string)::GetLastError());
      return false;
     }
   return true;
  }
//+------------------------------------------------------------------+

ここでは、オブジェクト構造体の整数フィールドに新しいプロパティを追加し、バージョン2155に追加されたFIFOClose口座プロパティを設定します。

構造体から口座オブジェクトを作成するメソッドで構造体フィールドの値の設定を新しいプロパティのオブジェクトプロパティに追加します

//+------------------------------------------------------------------+
//| Create the account object from the structure                     |
//+------------------------------------------------------------------+
void CAccount::StructToObject(void)
  {
//--- Save integer properties
   ... 
   this.m_long_prop[ACCOUNT_PROP_FIFO_CLOSE]                         = this.m_struct_obj.fifo_close;
   this.m_long_prop[ACCOUNT_PROP_HEDGE_ALLOWED]                      = this.m_struct_obj.hedge_allowed;
   ... 
  }
//+------------------------------------------------------------------+


口座オブジェクトの整数プロパティの説明を返すメソッドで新しいプロパティの説明を表示するようにします。

//+------------------------------------------------------------------+
//| Return the description of the account integer property           |
//+------------------------------------------------------------------+
string CAccount::GetPropertyDescription(ENUM_ACCOUNT_PROP_INTEGER property)
  {
   return
     (
      ... 
      property==ACCOUNT_PROP_FIFO_CLOSE      ?  CMessage::Text(MSG_ACC_PROP_FIFO_CLOSE)+": "+
                                                   (this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))  :
      property==ACCOUNT_PROP_HEDGE_ALLOWED   ?  CMessage::Text(MSG_ACC_PROP_HEDGE_ALLOWED)+": "+
                                                   (this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))  :
      ""
     );
  }
//+------------------------------------------------------------------+


\MQL5\Include\DoEasy\Objects\Symbols\Symbol.mqhの銘柄オブジェクトファイルにも同様の改善を加えます。

クラスのprotectedセクションで新しい銘柄プロパティの値を返すメソッドを宣言します

protected:
//--- Protected parametric constructor
                     CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name,const int index);

//--- Get and return integer properties of a selected symbol from its parameters
   ... 
   long              SymbolCalcMode(void)                const;
   long              SymbolSwapMode(void)                const;
   long              SymbolSubscriptionDelay(void)       const;
   long              SymbolDigitsLot(void);
   int               SymbolDigitsBySwap(void);
   ... 
//--- Search for a symbol and return the flag indicating its presence on the server
   bool              Exist(void)                         const;

public:


クラスのpublicセクションのオブジェクトプロパティを簡単にアクセスするためのブロックで、新しいプロパティを返すメソッドを設定します。

//+------------------------------------------------------------------+
//| Methods for a simplified access to symbol object properties      |
//+------------------------------------------------------------------+
//--- Integer properties
   ... 
   ENUM_SYMBOL_OPTION_MODE OptionMode(void)                       const { return (ENUM_SYMBOL_OPTION_MODE)this.GetProperty(SYMBOL_PROP_OPTION_MODE);        }
   ENUM_SYMBOL_OPTION_RIGHT OptionRight(void)                     const { return (ENUM_SYMBOL_OPTION_RIGHT)this.GetProperty(SYMBOL_PROP_OPTION_RIGHT);      }
   long              SubscriptionDelay(void)                      const { return this.GetProperty(SYMBOL_PROP_SUBSCRIPTION_DELAY);                          }
//--- Real properties

ここでは、GetProperty()メソッドを使用して、銘柄オブジェクトの整数プロパティの配列に設定された値を返すだけです。

クローズドパラメトリックコンストラクタで、 オブジェクト整数プロパティの配列に新しいプロパティを設定します

//+------------------------------------------------------------------+
//| Closed parametric constructor                                    |
//+------------------------------------------------------------------+
CSymbol::CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name,const int index)
  {
//--- Save integer properties
   ... 
   this.m_long_prop[SYMBOL_PROP_BOOKDEPTH_STATE]                                    = this.m_book_subscribed;
   this.m_long_prop[SYMBOL_PROP_SUBSCRIPTION_DELAY]                                 = this.SymbolSubscriptionDelay();
   ... 
//--- Initializing default values of a trading object
   this.m_trade.Init(this.Name(),0,this.LotsMin(),5,0,0,false,this.GetCorrectTypeFilling(),this.GetCorrectTypeExpiration(),LOG_LEVEL_ERROR_MSG);
  }
//+------------------------------------------------------------------+


以下は、サブスクリプションベースの銘柄で、銘柄によって渡されたクォートの遅延サイズを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the delay size for quotes passed by symbol                |
//| in case of subscription-based symbols                            |
//+------------------------------------------------------------------+
long CSymbol::SymbolSubscriptionDelay(void) const
  {
   return
     (
      #ifdef __MQL5__ (::TerminalInfoInteger(TERMINAL_BUILD)>=3245 ? ::SymbolInfoInteger(this.m_name,SYMBOL_SUBSCRIPTION_DELAY) : 0)
      #else 0
      #endif 
     );
  }
//+------------------------------------------------------------------+

ここで、MQL5ターミナルバージョンが3245以上の場合は、新しい銘柄プロパティの値を返しそれ以外の場合は、ゼロを返します
MQL4では、常にゼロを返します
。そのようなプロパティがないためです。

銘柄の整数プロパティの説明を返すメソッドで新しいプロパティの説明を返すコードブロックを追加します

//+------------------------------------------------------------------+
//| Return the description of the symbol integer property            |
//+------------------------------------------------------------------+
string CSymbol::GetPropertyDescription(ENUM_SYMBOL_PROP_INTEGER property)
  {
   return
     (
      ... 
      property==SYMBOL_PROP_BACKGROUND_COLOR    ?  CMessage::Text(MSG_SYM_PROP_BACKGROUND_COLOR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
         #ifdef __MQL5__
         (this.GetProperty(property)==CLR_MW_DEFAULT || this.GetProperty(property)==CLR_NONE ?  ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": "+::ColorToString((color)this.GetProperty(property),true))
         #else ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED_MQL4) #endif 
         )  :
      property==SYMBOL_PROP_SUBSCRIPTION_DELAY  ?  CMessage::Text(MSG_SYM_PROP_SUBSCRIPTION_DELAY)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
         #ifdef __MQL5__
         (::TerminalInfoInteger(TERMINAL_BUILD)<3245 ?  ": ("+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_3245)+")" : ": "+(string)this.GetProperty(property))
         #else ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED_MQL4) #endif 
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+


\MQL5\Include\DoEasy\GraphINI.mqhのGUI要素の配色の場合、テキストの色の値を追加し、配色のパラメータの数を4から5に増やし、テキスト 配色の値を配色の値の配列に追加します。

//+------------------------------------------------------------------+
//| List of indices of color scheme parameters                       |
//+------------------------------------------------------------------+
enum ENUM_COLOR_THEME_COLORS
  {
   COLOR_THEME_COLOR_FORM_BG,                   // Form background color
   COLOR_THEME_COLOR_FORM_FRAME,                // Form frame color
   COLOR_THEME_COLOR_FORM_RECT_OUTER,           // Form outline rectangle color
   COLOR_THEME_COLOR_FORM_SHADOW,               // Form shadow color
   COLOR_THEME_COLOR_FORM_TEXT,                 // Form text color
  };
#define TOTAL_COLOR_THEME_COLORS       (5)      // Number of parameters in the color theme
//+------------------------------------------------------------------+
//| The array containing color schemes                               |
//+------------------------------------------------------------------+
color array_color_themes[TOTAL_COLOR_THEMES][TOTAL_COLOR_THEME_COLORS]=
  {
//--- Parameters of the "Blue steel" color scheme
   {
      C'134,160,181',                           // Form background color
      C'134,160,181',                           // Form frame color
      clrDimGray,                               // Form outline rectangle color
      clrGray,                                  // Form shadow color
      C'0x3E,0x3E,0x3E',                        // Form text color
   },
//--- Parameters of the "Light cyan gray" color scheme
   {
      C'181,196,196',                           // Form background color
      C'181,196,196',                           // Form frame color
      clrGray,                                  // Form outline rectangle color
      clrGray,                                  // Form shadow color
      C'0x3E,0x3E,0x3E',                        // Form text color
   },
  };
//+------------------------------------------------------------------+


フレームスタイルの列挙で、フレームがないことを示すフィールドを追加します

//+------------------------------------------------------------------+
//| Frame styles                                                     |
//+------------------------------------------------------------------+
enum ENUM_FRAME_STYLE
  {
   FRAME_STYLE_NONE,                            // No frame
   FRAME_STYLE_SIMPLE,                          // Simple frame
   FRAME_STYLE_FLAT,                            // Flat frame
   FRAME_STYLE_BEVEL,                           // Embossed (convex)
   FRAME_STYLE_STAMP,                           // Embossed (concave)
  };
//+------------------------------------------------------------------+


\MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqhにあるすべてのライブラリグラフィカルオブジェクトの基本オブジェクトのクラスを改善します。

現在のチャートIDを指定するときは、カスタムプログラムで0またはNULLを設定できる必要があります。また、数値ID値を指定したり、ChartID()関数を渡す代わりに、SetChartID()メソッドに渡される値の検証を追加します。

public:
//--- Return the prefix name
   string            NamePrefix(void)                    const { return this.m_name_prefix;           }
//--- Set the values of the class variables
   void              SetObjectID(const long value)             { this.m_object_id=value;              }
   void              SetBelong(const ENUM_GRAPH_OBJ_BELONG belong){ this.m_belong=belong;             }
   void              SetTypeGraphObject(const ENUM_OBJECT obj) { this.m_type_graph_obj=obj;           }
   void              SetTypeElement(const ENUM_GRAPH_ELEMENT_TYPE type) { this.m_type_element=type;   }
   void              SetSpecies(const ENUM_GRAPH_OBJ_SPECIES species){ this.m_species=species;        }
   void              SetGroup(const int group)                 { this.m_group=group;                  }
   void              SetName(const string name)                { this.m_name=name;                    }
   void              SetDigits(const int value)                { this.m_digits=value;                 }
   void              SetChartID(const long chart_id)
                       { this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id);    }
   
//--- Set the "Background object" flag

ここではメソッドに渡された値を確認します。0またはNULLの場合は、現在のチャートIDを変数に割り当てます。それ以外の場合は、メソッドに渡された値を割り当てます。

グラフィック要素タイプの説明を返すメソッドでパネルオブジェクトの説明を返すようにします

//+------------------------------------------------------------------+
//| Return the description of the graphical element type             |
//+------------------------------------------------------------------+
string CGBaseObj::TypeElementDescription(void)
  {
   return
     (
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_STANDARD           ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD)           :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED  ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED)  :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_ELEMENT            ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_ELEMENT)            :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_SHADOW_OBJ         ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_SHADOW_OBJ)         :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_FORM               ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_FORM)               :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WINDOW             ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WINDOW)             :
      //---
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_PANEL              ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_PANEL)              :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+


\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqhのグラフィック要素オブジェクトのクラス、つまりオブジェクト構造体で要素の可用性プロパティの新しいフィールドを追加します

//+------------------------------------------------------------------+
//| Class of the graphical element object                            |
//+------------------------------------------------------------------+
class CGCnvElement : public CGBaseObj
  {
protected:
   CCanvas           m_canvas;                                 // CCanvas class object
   CPause            m_pause;                                  // Pause class object
   bool              m_shadow;                                 // Shadow presence
   color             m_chart_color_bg;                         // Chart background color
   uint              m_duplicate_res[];                        // Array for storing resource data copy

//--- Create (1) the object structure and (2) the object from the structure
   virtual bool      ObjectToStruct(void);
   virtual void      StructToObject(void);
   
private:
   struct SData
     {
      //--- Object integer properties
      ... 
      int            coord_act_bottom;                         // Bottom border of the element active area
      long           zorder;                                   // Priority of a graphical object for receiving the event of clicking on a chart
      bool           enabled;                                  // Element availability flag
      //--- Object real properties

      //--- Object string properties
      uchar          name_obj[64];                             // Graphical element object name
      uchar          name_res[64];                             // Graphical resource name
     };
   SData             m_struct_obj;                             // Object structure
   uchar             m_uchar_array[];                          // uchar array of the object structure


オブジェクトプロパティへのアクセスを簡素化するために、メソッドのブロックに要素の可用性値を設定して返すための新しいメソッドを 追加します。

//+------------------------------------------------------------------+
//| Methods of simplified access to object properties                |
//+------------------------------------------------------------------+
   ... 
//--- Set (1) object movability, (2) activity, (3) interaction,
//--- (4) element ID, (5) element index in the list, (6) availability and (7) shadow flag
   void              SetMovable(const bool flag)               { this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,flag);                     }
   void              SetActive(const bool flag)                { this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,flag);                      }
   void              SetInteraction(const bool flag)           { this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,flag);                 }
   void              SetID(const int id)                       { this.SetProperty(CANV_ELEMENT_PROP_ID,id);                            }
   void              SetNumber(const int number)               { this.SetProperty(CANV_ELEMENT_PROP_NUM,number);                       }
   void              SetEnabled(const bool flag)               { this.SetProperty(CANV_ELEMENT_PROP_ENABLED,flag);                     }
   void              SetShadow(const bool flag)                { this.m_shadow=flag;                                                   } 
   ... 
//--- Return the (1) element movability, (2) activity, (3) interaction and (4) availability flag
   bool              Movable(void)                       const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_MOVABLE);             }
   bool              Active(void)                        const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_ACTIVE);              }
   bool              Interaction(void)                   const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_INTERACTION);         }
   bool              Enabled(void)                       const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_ENABLED);             }
//--- Return (1) the object name, (2) the graphical resource name, (3) the chart ID and (4) the chart subwindow index



キャンバスのクリアメソッドの1つで、デフォルトのフラグ値を削除します。

//+------------------------------------------------------------------+
//| The methods of filling, clearing and updating raster data        |
//+------------------------------------------------------------------+
//--- Clear the element filling it with color and opacity
   void              Erase(const color colour,const uchar opacity,const bool redraw=false);
//--- Clear the element with a gradient fill
   void              Erase(color &colors[],const uchar opacity,const bool vgradient,const bool cycle,const bool redraw=false);
//--- Clear the element completely
   void              Erase(const bool redraw=false);
//--- Update the element
   void              Update(const bool redraw=false)           { this.m_canvas.Update(redraw);                                         }

以前は、メソッドは次のようでした。

void              Erase(color &colors[],const uchar opacity,const bool vgradient=true,const bool cycle=false,const bool redraw=false);

コンパイラが正しいオーバーロードされたメソッドを選択できなかったため、これは使用できませんでした。

パラメトリックコンストラクタで、渡されたチャートID値の検証を追加し、要素の可用性フラグデフォルトのフォント値を設定します

//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+
CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                           const int      element_id,
                           const int      element_num,
                           const long     chart_id,
                           const int      wnd_num,
                           const string   name,
                           const int      x,
                           const int      y,
                           const int      w,
                           const int      h,
                           const color    colour,
                           const uchar    opacity,
                           const bool     movable=true,
                           const bool     activity=true,
                           const bool     redraw=false) : m_shadow(false)
  {
   this.m_type=OBJECT_DE_TYPE_GELEMENT; 
   this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND);
   this.m_name=(::StringFind(name,this.m_name_prefix)<0 ? this.m_name_prefix : "")+name;
   this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id);
   this.m_subwindow=wnd_num;
   this.m_type_element=element_type;
   this.SetFont(DEF_FONT,DEF_FONT_SIZE);
   this.m_text_anchor=0;
   this.m_text_x=0;
   this.m_text_y=0;
   this.m_color_bg=colour;
   this.m_opacity=opacity;
   if(this.Create(chart_id,wnd_num,this.m_name,x,y,w,h,colour,opacity,redraw))
     {
      ... 
      this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,activity);                       // Element activity flag
      this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,false);                     // Flag of interaction with the outside environment
      this.SetProperty(CANV_ELEMENT_PROP_ENABLED,true);                          // Element availability flag
      this.SetProperty(CANV_ELEMENT_PROP_RIGHT,this.RightEdge());                // Element right border
   ... 
  }
//+------------------------------------------------------------------+

protectedコンストラクタでも同じことをおこないます。

//+------------------------------------------------------------------+
//| Protected constructor                                            |
//+------------------------------------------------------------------+
CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                           const long    chart_id,
                           const int     wnd_num,
                           const string  name,
                           const int     x,
                           const int     y,
                           const int     w,
                           const int     h) : m_shadow(false)
  {
   this.m_type=OBJECT_DE_TYPE_GELEMENT; 
   this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND);
   this.m_name=(::StringFind(name,this.m_name_prefix)<0 ? this.m_name_prefix : "")+name;
   this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id);
   this.m_subwindow=wnd_num;
   this.m_type_element=element_type;
   this.SetFont(DEF_FONT,DEF_FONT_SIZE);
   this.m_text_anchor=0;
   this.m_text_x=0;
   this.m_text_y=0;
   this.m_color_bg=CLR_CANV_NULL;
   this.m_opacity=0;
   if(this.Create(chart_id,wnd_num,this.m_name,x,y,w,h,this.m_color_bg,this.m_opacity,false))
     {
      ... 
      this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,false);                          // Element activity flag
      this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,false);                     // Flag of interaction with the outside environment
      this.SetProperty(CANV_ELEMENT_PROP_ENABLED,true);                          // Element availability flag
      this.SetProperty(CANV_ELEMENT_PROP_RIGHT,this.RightEdge());                // Element right border
      ... 

  }
//+------------------------------------------------------------------+


オブジェクト構造体を作成するメソッドで、新しい構造体フィールドに新しい要素の可用性フラグを追加します

//+------------------------------------------------------------------+
//| Create the object structure                                      |
//+------------------------------------------------------------------+
bool CGCnvElement::ObjectToStruct(void)
  {
//--- Save integer properties
   ... 
   this.m_struct_obj.active=(bool)this.GetProperty(CANV_ELEMENT_PROP_ACTIVE);                   // Element activity flag
   this.m_struct_obj.interaction=(bool)this.GetProperty(CANV_ELEMENT_PROP_INTERACTION);         // Flag of interaction with the outside environment
   this.m_struct_obj.enabled=(bool)this.GetProperty(CANV_ELEMENT_PROP_ENABLED);                 // Element availability flag
   this.m_struct_obj.coord_act_x=(int)this.GetProperty(CANV_ELEMENT_PROP_COORD_ACT_X);          // X coordinate of the element active area
   this.m_struct_obj.coord_act_y=(int)this.GetProperty(CANV_ELEMENT_PROP_COORD_ACT_Y);          // Y coordinate of the element active area
   ... 
   return true;
  }
//+------------------------------------------------------------------+

 

構造体からオブジェクトを作成するメソッドで、適切な構造体フィールドから値オブジェクトの可用性プロパティにエントリを追加します

//+------------------------------------------------------------------+
//| Create the object from the structure                             |
//+------------------------------------------------------------------+
void CGCnvElement::StructToObject(void)
  {
//--- Save integer properties
   ... 
   this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,this.m_struct_obj.active);                         // Element activity flag
   this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,this.m_struct_obj.interaction);               // Flag of interaction with the outside environment
   this.SetProperty(CANV_ELEMENT_PROP_ENABLED,this.m_struct_obj.enabled);                       // Element availability flag
   this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_X,this.m_struct_obj.coord_act_x);               // X coordinate of the element active area
   this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_Y,this.m_struct_obj.coord_act_y);               // Y coordinate of the element active area
   this.SetProperty(CANV_ELEMENT_PROP_ACT_RIGHT,this.m_struct_obj.coord_act_right);             // Right border of the element active area
   this.SetProperty(CANV_ELEMENT_PROP_ACT_BOTTOM,this.m_struct_obj.coord_act_bottom);           // Bottom border of the element active area
   this.m_color_bg=this.m_struct_obj.color_bg;                                                  // Element background color
   this.m_opacity=this.m_struct_obj.opacity;                                                    // Element opacity
   this.m_zorder=this.m_struct_obj.zorder;                                                      // Priority of a graphical object for receiving the on-chart mouse click event
   ... 
//--- Save string properties
   this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,::CharArrayToString(this.m_struct_obj.name_obj));// Graphical element object name
   this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,::CharArrayToString(this.m_struct_obj.name_res));// Graphical resource name
  }
//+------------------------------------------------------------------+


グラフィック要素オブジェクトを作成するメソッドで、渡されたチャートID値の検証も追加 します。

//+------------------------------------------------------------------+
//| Create the graphical element object                              |
//+------------------------------------------------------------------+
bool CGCnvElement::Create(const long chart_id,     // Chart ID
                          const int wnd_num,       // Chart subwindow
                          const string name,       // Element name
                          const int x,             // X coordinate
                          const int y,             // Y coordinate
                          const int w,             // Width
                          const int h,             // Height
                          const color colour,      // Background color
                          const uchar opacity,     // Opacity
                          const bool redraw=false) // Flag indicating the need to redraw
                         
  {
   ::ResetLastError();
   if(this.m_canvas.CreateBitmapLabel((chart_id==NULL ? ::ChartID() : chart_id),wnd_num,name,x,y,w,h,COLOR_FORMAT_ARGB_NORMALIZE))
     {
      this.Erase(CLR_CANV_NULL);
      this.m_canvas.Update(redraw);
      this.m_shift_y=(int)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_WINDOW_YDISTANCE,wnd_num);
      return true;
     }
   CMessage::ToLog(DFUN,::GetLastError(),true);
   return false;
  }
//+------------------------------------------------------------------+


次に、\MQL5\Include\DoEasy\Objects\Graph\Form.mqhのフォームオブジェクトクラスを改善しましょう。

以下は、privateの変数初期化メソッドです。

//+------------------------------------------------------------------+
//| Form object class                                                |
//+------------------------------------------------------------------+
class CForm : public CGCnvElement
  {
private:
   CArrayObj         m_list_elements;                          // List of attached elements
   CAnimations      *m_animations;                             // Pointer to the animation object
   CShadowObj       *m_shadow_obj;                             // Pointer to the shadow object
   CMouseState       m_mouse;                                  // "Mouse status" class object
   ENUM_MOUSE_FORM_STATE m_mouse_form_state;                   // Mouse status relative to the form
   ushort            m_mouse_state_flags;                      // Mouse status flags
   color             m_color_frame;                            // Form frame color
   int               m_frame_width_left;                       // Form frame width to the left
   int               m_frame_width_right;                      // Form frame width to the right
   int               m_frame_width_top;                        // Form frame width at the top
   int               m_frame_width_bottom;                     // Form frame width at the bottom
   int               m_offset_x;                               // Offset of the X coordinate relative to the cursor
   int               m_offset_y;                               // Offset of the Y coordinate relative to the cursor
   
//--- Initialize the variables
   void              Initialize(void);
//--- Reset the array size of (1) text, (2) rectangular and (3) geometric animation frames
   void              ResetArrayFrameT(void);
   void              ResetArrayFrameQ(void);
   void              ResetArrayFrameG(void);

メソッドは子孫オブジェクトで必要になるため、クラスのprotectedセクションに移動し、クラスオブジェクトを非初期化するための新しいメソッドを宣言します

//--- Reset the array size of (1) text, (2) rectangular and (3) geometric animation frames
   void              ResetArrayFrameT(void);
   void              ResetArrayFrameQ(void);
   void              ResetArrayFrameG(void);
   
//--- Return the name of the dependent object
   string            CreateNameDependentObject(const string base_name)  const
                       { return ::StringSubstr(this.NameObj(),::StringLen(::MQLInfoString(MQL_PROGRAM_NAME))+1)+"_"+base_name;   }
  
//--- Create a new graphical object
   CGCnvElement     *CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                      const int element_num,
                                      const string name,
                                      const int x,
                                      const int y,
                                      const int w,
                                      const int h,
                                      const color colour,
                                      const uchar opacity,
                                      const bool movable,
                                      const bool activity);

//--- Create a shadow object
   void              CreateShadowObj(const color colour,const uchar opacity);
   
protected:
//--- Initialize the variables
   void              Initialize(void);
   void              Deinitialize(void);
   
public:
//--- Return (1) the mouse status relative to the form, as well as (2) X and (3) Y coordinate of the cursor


接続されたオブジェクトのリストを返すGetList()メソッドをGetListElements()に名前変更します。これは、その関数の観点からより適切です。

//--- Return (1) the list of attached objects and (2) the shadow object
   CForm            *GetObject(void)                                          { return &this;                  }
   CArrayObj        *GetListElements(void)                                    { return &this.m_list_elements;  }
   CGCnvElement     *GetShadowObj(void)                                       { return this.m_shadow_obj;      }
//--- Return the pointer to (1) the animation object, the list of (2) text and (3) rectangular animation frames


クラスのpublicセクションで新しい添付要素を添付フォーム要素のリストに追加するメソッドを宣言します。

//--- Create a new attached element
   bool              CreateNewElement(const int element_num,
                                      const string name,
                                      const int x,
                                      const int y,
                                      const int w,
                                      const int h,
                                      const color colour,
                                      const uchar opacity,
                                      const bool movable,
                                      const bool activity);
//--- Add a new attached element
   bool              AddNewElement(CGCnvElement *obj,const int x,const int y);

//--- Draw an object shadow
   void              DrawShadow(const int shift_x,const int shift_y,const color colour,const uchar opacity=127,const uchar blur=4);


使用されているすべての動的クラスオブジェクトを削除するコードブロックをクラスデストラクタから

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CForm::~CForm()
  {
   if(this.m_shadow_obj!=NULL)
      delete this.m_shadow_obj;
   if(this.m_animations!=NULL)
      delete this.m_animations;
  }
//+------------------------------------------------------------------+

新しい非初期化メソッドに移動します。

//+------------------------------------------------------------------+
//| Deinitialize the variables                                       |
//+------------------------------------------------------------------+
void CForm::Deinitialize(void)
  {
   if(this.m_shadow_obj!=NULL)
      delete this.m_shadow_obj;
   if(this.m_animations!=NULL)
      delete this.m_animations;
  }  
//+------------------------------------------------------------------+

デストラクタで次のメソッドを呼び出します。

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CForm::~CForm()
  {
   this.Deinitialize();
  }
//+------------------------------------------------------------------+

これにより、継承されたクラスから不要な親クラスの動的オブジェクトを削除できるようになります。

以下は、接続されたオブジェクト要素のリストに新しい接続された要素を追加するメソッドです。

//+------------------------------------------------------------------+
//| Add a new attached element                                       |
//+------------------------------------------------------------------+
bool CForm::AddNewElement(CGCnvElement *obj,const int x,const int y)
  {
   if(obj==NULL)
      return false;
   this.m_list_elements.Sort(SORT_BY_CANV_ELEMENT_NAME_OBJ);
   int index=this.m_list_elements.Search(obj);
   if(index>WRONG_VALUE)
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_OBJ_ALREADY_IN_LIST),": ",obj.NameObj());
      return false;
     }
   if(!this.m_list_elements.Add(obj))
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST),": ",obj.NameObj());
      return false;
     }
   return true;
  }
//+------------------------------------------------------------------+

このメソッドは、接続されたオブジェクトのリストに追加されるオブジェクトへのポインタを受け取ります。
要素のリストを指定されたオブジェクトの名前で並べ替え、リスト内でそのようなオブジェクトを検索します。
同じオブジェクトがすでにリストに存在する場合は、そのことを通知してfalseを返します。
接続されたオブジェクトのリストにオブジェクトを配置できなかった場合は、そのことを通知し、falseを返します。
結果としてtrueを返します。

新しい接続された要素を作成するメソッドは、作成されたオブジェクトをリストに追加するメソッドを呼び出すようになりました

//+------------------------------------------------------------------+
//| Create a new attached element                                    |
//+------------------------------------------------------------------+
bool CForm::CreateNewElement(const int element_num,
                             const string element_name,
                             const int x,
                             const int y,
                             const int w,
                             const int h,
                             const color colour,
                             const uchar opacity,
                             const bool movable,
                             const bool activity)
  {
   CGCnvElement *obj=this.CreateNewGObject(GRAPH_ELEMENT_TYPE_ELEMENT,element_num,element_name,x,y,w,h,colour,opacity,movable,activity);
   if(obj==NULL)
      return false;
   if(!this.AddNewElement(obj,x,y))
     {
      delete obj;
      return false;
     }
   return true;
  }
//+------------------------------------------------------------------+

以前、このメソッドのリストに新しく作成したオブジェクトを追加しましたが、(オブジェクトを作成するときだけでなく)他のプログラムパーツから接続されたオブジェクトのリストにグラフィック要素を追加できるため、これは不合理でした。

シャドウオブジェクトを作成するメソッドでは、移動可能性フラグがtrueに設定されており、シャドウオブジェクトが移動可能になっていました。この動作は正しくないと思います。代わりに、プロパティ値は、シャドウオブジェクトが構築されているオブジェクトから継承する必要があります。これを修正しましょう。

//+------------------------------------------------------------------+
//| 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(this.Movable());
   this.m_shadow_obj.SetActive(false);
   this.m_shadow_obj.SetVisible(false,false);
//--- Move the form object to the foreground
   this.BringToTop();
  }
//+------------------------------------------------------------------+

すべての準備段階が完了しました。


WinForms Panelオブジェクトクラス

パネルオブジェクトは、フォームオブジェクトクラスから派生します。つまり、フォームの機能とプロパティ全体を備えることになります。その上、新しいプロパティと機能を追加します。パネルでは、他のオブジェクトを配置したり、コンテンツに合わせてサイズを変更したり、コンテンツがパネルを超えた場合に自動スクロールを有効にしたりすることができます。

現在の記事でおこなうのは、パネルオブジェクトの準備のみです。すべてのプロパティを定義し、それらを設定して返すためのメソッドを作成します。以降の記事では、パネルオブジェクトの機能をすべて徐々に追加していきます。ここでは、コンストラクタを使用してのみパネルオブジェクトを作成できます。

すべてのWinForms管理要素について、新しいライブラリディレクトリを定義します。

記事の冒頭で定義したMS Visual Studioコントロールグループにちなんで名付けられたサブフォルダを使用して、新しいフォルダー\MQL5\Include\DoEasy\Objects\Graph\WForms\を作成します。

  • \MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\
  • \MQL5\Include\DoEasy\Objects\Graph\WForms\Components\
  • \MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\
  • \MQL5\Include\DoEasy\Objects\Graph\WForms\Data\
  • \MQL5\Include\DoEasy\Objects\Graph\WForms\Dialogs\
  • \MQL5\Include\DoEasy\Objects\Graph\WForms\Menu & Toolbars\
  • \MQL5\Include\DoEasy\Objects\Graph\WForms\Printing     

パネルは他のオブジェクトのコンテナであるため、オブジェクトクラスファイルは適切なフォルダ(\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\)にあります。

指定されたファイルに、ファイルを含める必要があるCFormから派生したCPanelの新しいファイルPanel.mqhを作成します。

//+------------------------------------------------------------------+
//|                                                        Panel.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 "..\..\Form.mqh"
//+------------------------------------------------------------------+
//| Panel object class of WForms controls                            |
//+------------------------------------------------------------------+
class CPanel : public CForm
  {
  }

クラスのprivateセクションで、必要なすべての変数と配列を宣言します。

//+------------------------------------------------------------------+
//| Panel object class of WForms controls                            |
//+------------------------------------------------------------------+
class CPanel : public CForm
  {
private:
   color             m_fore_color;                                   // Default text color for all panel objects
   ENUM_FRAME_STYLE  m_border_style;                                 // Panel frame style
   bool              m_autoscroll;                                   // Auto scrollbar flag
   int               m_autoscroll_margin[2];                         // Array of fields around the control during an auto scroll
   bool              m_autosize;                                     // Flag of the element auto resizing depending on the content
   ENUM_CANV_ELEMENT_AUTO_SIZE_MODE m_autosize_mode;                 // Mode of the element auto resizing depending on the content
   ENUM_CANV_ELEMENT_DOCK_MODE m_dock_mode;                          // Mode of binding element borders to the container
   int               m_margin[4];                                    // Array of gaps of all sides between the fields of the current and adjacent controls
   int               m_padding[4];                                   // Array of gaps of all sides inside controls
public:

Margin、Padding、AutoSizeという用語を理解するために、MS Windows Forms .NETFramework4.Xヘルプの次の例を考えてみましょう。

...最も重要な3つは、すべてのWindows Formsコントロールに存在するMargin、Padding、AutoSizeプロパティです。

Marginプロパティは、他のコントロールをコントロールの境界から指定された距離に保つ、コントロールの周囲のスペースを定義します。

Paddingプロパティは、コントロールのコンテンツ(例:Textプロパティの値)をコントロールの境界から指定された距離に保つ、コントロールの内部のスペースを定義します。

AutoSizeプロパティは、その内容に合わせて自動的にサイズを変更するようにコントロールに指示します。元のSizeプロパティの値よりも小さくなるようにサイズを変更することはなく、Paddingプロパティの値を考慮します。


クラスのpublicセクションで、宣言されたすべてのクラス変数の値を設定および返すためのメソッドを記述します。

public:
//--- (1) Set and (2) return the default text color of all panel objects
   void              ForeColor(const color clr)                      { this.m_fore_color=clr;               }
   color             ForeColor(void)                           const { return this.m_fore_color;            }

//--- (1) Set and (2) return the frame style
   void              BorderStyle(const ENUM_FRAME_STYLE style)       { this.m_border_style=style;           }
   ENUM_FRAME_STYLE  BorderStyle(void)                         const { return this.m_border_style;          }

//--- (1) Set and (2) return the auto scrollbar flag
   void              AutoScroll(const bool flag)                     { this.m_autoscroll=flag;              }
   bool              AutoScroll(void)                                { return this.m_autoscroll;            }
//--- Set the (1) field width, (2) height, (3) the height of all fields around the control during auto scrolling
   void              AutoScrollMarginWidth(const int value)          { this.m_autoscroll_margin[0]=value;   }
   void              AutoScrollMarginHeight(const int value)         { this.m_autoscroll_margin[1]=value;   }
   void              AutoScrollMarginAll(const int value)
                       {
                        this.AutoScrollMarginWidth(value); this.AutoScrollMarginHeight(value);
                       }
//--- Return the (1) field width and (2) height around the control during auto scrolling
   int               AutoScrollMarginWidth(void)               const { return this.m_autoscroll_margin[0];  }
   int               AutoScrollMarginHeight(void)              const { return this.m_autoscroll_margin[1];  }
   
//--- (1) Set and (2) return the flag of the element auto resizing depending on the content
   void              AutoSize(const bool flag)                       { this.m_autosize=flag;                }
   bool              AutoSize(void)                                  { return this.m_autosize;              }
//--- (1) Set and (2) return the mode of the element auto resizing depending on the content
   void              AutoSizeMode(const ENUM_CANV_ELEMENT_AUTO_SIZE_MODE mode) { this.m_autosize_mode=mode; }
   ENUM_CANV_ELEMENT_AUTO_SIZE_MODE AutoSizeMode(void)         const { return this.m_autosize_mode;         }
   
//--- (1) Set and (2) return the mode of binding element borders to the container
   void              DockMode(const ENUM_CANV_ELEMENT_DOCK_MODE mode){ this.m_dock_mode=mode;               }
   ENUM_CANV_ELEMENT_DOCK_MODE DockMode(void)                  const { return this.m_dock_mode;             }

//--- Set the gap (1) to the left, (2) at the top, (3) to the right, (4) at the bottom and (5) on all sides between the fields of this and another control
   void              MarginLeft(const int value)                     { this.m_margin[0]=value;              }
   void              MarginTop(const int value)                      { this.m_margin[1]=value;              }
   void              MarginRight(const int value)                    { this.m_margin[2]=value;              }
   void              MarginBottom(const int value)                   { this.m_margin[3]=value;              }
   void              MarginAll(const int value)
                       {
                        this.MarginLeft(value); this.MarginTop(value); this.MarginRight(value); this.MarginBottom(value);
                       }
//--- Return the gap (1) to the left, (2) at the top, (3) to the right and (4) at the bottom between the fields of this and another control
   int               MarginLeft(void)                          const { return this.m_margin[0];             }
   int               MarginTop(void)                           const { return this.m_margin[1];             }
   int               MarginRight(void)                         const { return this.m_margin[2];             }
   int               MarginBottom(void)                        const { return this.m_margin[3];             }

//--- Set the gap (1) to the left, (2) at the top, (3) to the right, (4) at the bottom and (5) on all sides inside the control
   void              PaddingLeft(const int value)                     { this.m_padding[0]=value;            }
   void              PaddingTop(const int value)                      { this.m_padding[1]=value;            }
   void              PaddingRight(const int value)                    { this.m_padding[2]=value;            }
   void              PaddingBottom(const int value)                   { this.m_padding[3]=value;            }
   void              PaddingAll(const int value)
                       {
                        this.PaddingLeft(value); this.PaddingTop(value); this.PaddingRight(value); this.PaddingBottom(value);
                       }
//--- Return the gap (1) to the left, (2) at the top, (3) to the right and (4) at the bottom between the fields inside the control
   int               PaddingLeft(void)                          const { return this.m_padding[0];           }
   int               PaddingTop(void)                           const { return this.m_padding[1];           }
   int               PaddingRight(void)                         const { return this.m_padding[2];           }
   int               PaddingBottom(void)                        const { return this.m_padding[3];           }
   
//--- Constructors
                     CPanel(const long chart_id,
                           const int subwindow,
                           const string name,
                           const int x,
                           const int y,
                           const int w,
                           const int h);
                     CPanel(const int subwindow,
                           const string name,
                           const int x,
                           const int y,
                           const int w,
                           const int h);
                     CPanel(const string name,
                           const int x,
                           const int y,
                           const int w,
                           const int h);
                     CPanel(const string name) : CForm(::ChartID(),0,name,0,0,0,0)
                       {
                        CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_PANEL);
                        this.m_type=OBJECT_DE_TYPE_GWF_PANEL; 
                        this.m_fore_color=CLR_FORE_COLOR;
                        this.MarginAll(3);
                        this.PaddingAll(0);
                        this.Initialize(); 
                       }
//--- Destructor
                    ~CPanel();
  };
//+------------------------------------------------------------------+

それらのいくつかについては、オブジェクトの各側に対応する各プロパティを同時に設定することもできます。

たとえば、MS Visual StudioのMargin値の場合、各プロパティを個別に設定し、4つすべてを同時に設定することができます。


(1)チャートID、チャートサブウィンドウ、オブジェクト名とサイズ付きの座標、(2)現在のチャートサブウィンドウ、オブジェクト名とサイズ付きの座標、(3)オブジェクト名とサイズ付きの座標、(4)座標とサイズがゼロのオブジェクト名をそれぞれ指定する、4つのクラスコンストラクタがあります。

//+------------------------------------------------------------------+
//| Constructor indicating the chart and subwindow ID                |
//+------------------------------------------------------------------+
CPanel::CPanel(const long chart_id,
               const int subwindow,
               const string name,
               const int x,
               const int y,
               const int w,
               const int h) : CForm(chart_id,subwindow,name,x,y,w,h)
  {
   CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_PANEL);
   this.m_type=OBJECT_DE_TYPE_GWF_PANEL;
   this.m_fore_color=CLR_FORE_COLOR;
   this.MarginAll(3);
   this.PaddingAll(0);
   this.Initialize();
  }
//+------------------------------------------------------------------+
//| Current chart constructor specifying the subwindow               |
//+------------------------------------------------------------------+
CPanel::CPanel(const int subwindow,
               const string name,
               const int x,
               const int y,
               const int w,
               const int h) : CForm(::ChartID(),subwindow,name,x,y,w,h)
  {
   CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_PANEL);
   this.m_type=OBJECT_DE_TYPE_GWF_PANEL; 
   this.m_fore_color=CLR_FORE_COLOR;
   this.MarginAll(3);
   this.PaddingAll(0);
   this.Initialize();
  }
//+------------------------------------------------------------------+
//| Constructor on the current chart in the main chart window        |
//+------------------------------------------------------------------+
CPanel::CPanel(const string name,
               const int x,
               const int y,
               const int w,
               const int h) : CForm(::ChartID(),0,name,x,y,w,h)
  {
   CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_PANEL);
   this.m_type=OBJECT_DE_TYPE_GWF_PANEL; 
   this.m_fore_color=CLR_FORE_COLOR;
   this.MarginAll(3);
   this.PaddingAll(0);
   this.Initialize();
  }
//+------------------------------------------------------------------+

各コンストラクタの初期化文字列で、必要なパラメータを親クラスコンストラクタに渡します
次に、コンストラクタ本体でグラフィック要素タイプライブラリオブジェクトタイプデフォルトのパネルテキストの色を設定し、すべての辺のMarginを3に設定し、Paddingを0に設定して、親クラス変数を初期化します

これは、ターミナルチャート上に簡単なパネルオブジェクトを作成するのに十分です。Panelオブジェクトの他のすべては、今後の記事で実装されます。

クラスデストラクタで、次の親クラスの初期化解除メソッドを呼び出します。

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CPanel::~CPanel()
  {
   CForm::Deinitialize();
  }
//+------------------------------------------------------------------+


\MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqhのグラフィック要素のコレクションクラスを改善しましょう。

フォームオブジェクトファイルの代わりにパネルオブジェクトファイルを含めます。

//+------------------------------------------------------------------+
//|                                      GraphElementsCollection.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"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ListObj.mqh"
#include "..\Services\Select.mqh"
#include "..\Objects\Graph\WForms\Containers\Panel.mqh"
#include "..\Objects\Graph\Standard\GStdVLineObj.mqh"

パネルオブジェクトはフォームオブジェクトから派生しているため、その親階層のすべてのオブジェクトがコレクションクラスからアクセスできます。

クラスのpublicセクションで、チャートIDとオブジェクトIDおよびチャートIDとオブジェクト名でグラフィック要素のリストを返す2つのメソッドを記述します。

//--- Return the list of graphical objects by chart ID and group
   CArrayObj        *GetListStdGraphObjByGroup(const long chart_id,const int group)
                       {
                        CArrayObj *list=GetList(GRAPH_OBJ_PROP_CHART_ID,0,chart_id,EQUAL);
                        return CSelect::ByGraphicStdObjectProperty(list,GRAPH_OBJ_PROP_GROUP,0,group,EQUAL);
                       }
//--- Return the list of graphical elements by chart and object IDs
   CArrayObj        *GetListCanvElementByID(const long chart_id,const int element_id)
                       {
                        CArrayObj *list=CSelect::ByGraphCanvElementProperty(this.GetListCanvElm(),CANV_ELEMENT_PROP_CHART_ID,chart_id,EQUAL);
                        return CSelect::ByGraphCanvElementProperty(list,CANV_ELEMENT_PROP_ID,element_id,EQUAL);;
                       }
//--- Return the list of graphical elements by chart ID and object name
   CArrayObj        *GetListCanvElementByName(const long chart_id,const string name)
                       {
                        CArrayObj *list=CSelect::ByGraphCanvElementProperty(this.GetListCanvElm(),CANV_ELEMENT_PROP_CHART_ID,chart_id,EQUAL);
                        return CSelect::ByGraphCanvElementProperty(list,CANV_ELEMENT_PROP_NAME_OBJ,name,EQUAL);;
                       }
   
//--- Constructor

そのようなメソッドのロジックは以前に繰り返し検討しました。ここでは、必要なパラメータでリストを並べ替えて、結果のリストを返します。これは、コレクションリストで見つかったオブジェクトへのポインタを特徴とするものです。
オブジェクトが見つからない場合はNULLを返します。

クラス本体の最後に、 グラフィック要素フォームパネルオブジェクトを作成するためのメソッドを記述します。

//--- Create a graphical element object on canvas on a specified chart and subwindow
   int               CreateElement(const long chart_id,
                                   const int subwindow,
                                   const string name,
                                   const int x,
                                   const int y,
                                   const int w,
                                   const int h,
                                   const color clr,
                                   const uchar opacity,
                                   const bool movable,
                                   const bool activity,
                                   const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CGCnvElement *obj=new CGCnvElement(GRAPH_ELEMENT_TYPE_ELEMENT,id,0,chart_id,subwindow,name,x,y,w,h,clr,opacity,movable,activity,redraw);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.Erase(clr,opacity,redraw);
                        return obj.ID();
                       }
//--- Create a graphical element object on canvas on a specified chart and subwindow with the vertical gradient filling
   int               CreateElementVGradient(const long chart_id,
                                            const int subwindow,
                                            const string name,
                                            const int x,
                                            const int y,
                                            const int w,
                                            const int h,
                                            color &clr[],
                                            const uchar opacity,
                                            const bool movable,
                                            const bool activity,
                                            const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CGCnvElement *obj=new CGCnvElement(GRAPH_ELEMENT_TYPE_ELEMENT,id,0,chart_id,subwindow,name,x,y,w,h,clr[0],opacity,movable,activity,redraw);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.Erase(clr,opacity,true,false,redraw);
                        return obj.ID();
                       }
//--- Create a graphical element object on canvas on a specified chart and subwindow with the horizontal gradient filling
   int               CreateElementHGradient(const long chart_id,
                                            const int subwindow,
                                            const string name,
                                            const int x,
                                            const int y,
                                            const int w,
                                            const int h,
                                            color &clr[],
                                            const uchar opacity,
                                            const bool movable,
                                            const bool activity,
                                            const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CGCnvElement *obj=new CGCnvElement(GRAPH_ELEMENT_TYPE_ELEMENT,id,0,chart_id,subwindow,name,x,y,w,h,clr[0],opacity,movable,activity,redraw);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.Erase(clr,opacity,false,false,redraw);
                        return obj.ID();
                       }
//--- Create a graphical element object on canvas on a specified chart and subwindow with the cyclic vertical gradient filling
   int               CreateElementVGradientCicle(const long chart_id,
                                                 const int subwindow,
                                                 const string name,
                                                 const int x,
                                                 const int y,
                                                 const int w,
                                                 const int h,
                                                 color &clr[],
                                                 const uchar opacity,
                                                 const bool movable,
                                                 const bool activity,
                                                 const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CGCnvElement *obj=new CGCnvElement(GRAPH_ELEMENT_TYPE_ELEMENT,id,0,chart_id,subwindow,name,x,y,w,h,clr[0],opacity,movable,activity,redraw);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.Erase(clr,opacity,true,true,redraw);
                        return obj.ID();
                       }
//--- Create a graphical element object on canvas on a specified chart and subwindow with the cyclic horizontal gradient filling
   int               CreateElementHGradientCicle(const long chart_id,
                                                 const int subwindow,
                                                 const string name,
                                                 const int x,
                                                 const int y,
                                                 const int w,
                                                 const int h,
                                                 color &clr[],
                                                 const uchar opacity,
                                                 const bool movable,
                                                 const bool activity,
                                                 const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CGCnvElement *obj=new CGCnvElement(GRAPH_ELEMENT_TYPE_ELEMENT,id,0,chart_id,subwindow,name,x,y,w,h,clr[0],opacity,movable,activity,redraw);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.Erase(clr,opacity,false,true,redraw);
                        return obj.ID();
                       }
 
//--- Create a graphical object form object on canvas on a specified chart and subwindow
   int               CreateForm(const long chart_id,
                                const int subwindow,
                                const string name,
                                const int x,
                                const int y,
                                const int w,
                                const int h,
                                const color clr,
                                const uchar opacity,
                                const bool movable,
                                const bool activity,
                                const bool shadow=false,
                                const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CForm *obj=new CForm(chart_id,subwindow,name,x,y,w,h);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.SetID(id);
                        obj.SetActive(activity);
                        obj.SetMovable(movable);
                        obj.SetColorBackground(clr);
                        obj.SetColorFrame(clr);
                        obj.SetOpacity(opacity,false);
                        obj.SetShadow(shadow);
                        obj.DrawRectangle(0,0,obj.Width()-1,obj.Height()-1,obj.ColorFrame(),obj.Opacity());
                        obj.Done();
                        obj.Erase(clr,opacity,redraw);
                        return obj.ID();
                       }
//--- Create a graphical object form object on canvas on a specified chart and subwindow with the vertical gradient filling
   int               CreateFormVGradient(const long chart_id,
                                         const int subwindow,
                                         const string name,
                                         const int x,
                                         const int y,
                                         const int w,
                                         const int h,
                                         color &clr[],
                                         const uchar opacity,
                                         const bool movable,
                                         const bool activity,
                                         const bool shadow=false,
                                         const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CForm *obj=new CForm(chart_id,subwindow,name,x,y,w,h);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.SetID(id);
                        obj.SetActive(activity);
                        obj.SetMovable(movable);
                        obj.SetColorBackground(clr[0]);
                        obj.SetColorFrame(clr[0]);
                        obj.SetOpacity(opacity,false);
                        obj.SetShadow(shadow);
                        obj.DrawRectangle(0,0,obj.Width()-1,obj.Height()-1,obj.ColorFrame(),obj.Opacity());
                        obj.Done();
                        obj.Erase(clr,opacity,true,false,redraw);
                        return obj.ID();
                       }
//--- Create a graphical object form object on canvas on a specified chart and subwindow with the horizontal gradient filling
   int               CreateFormHGradient(const long chart_id,
                                         const int subwindow,
                                         const string name,
                                         const int x,
                                         const int y,
                                         const int w,
                                         const int h,
                                         color &clr[],
                                         const uchar opacity,
                                         const bool movable,
                                         const bool activity,
                                         const bool shadow=false,
                                         const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CForm *obj=new CForm(chart_id,subwindow,name,x,y,w,h);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.SetID(id);
                        obj.SetActive(activity);
                        obj.SetMovable(movable);
                        obj.SetColorBackground(clr[0]);
                        obj.SetColorFrame(clr[0]);
                        obj.SetOpacity(opacity,false);
                        obj.SetShadow(shadow);
                        obj.DrawRectangle(0,0,obj.Width()-1,obj.Height()-1,obj.ColorFrame(),obj.Opacity());
                        obj.Done();
                        obj.Erase(clr,opacity,false,false,redraw);
                        return obj.ID();
                       }
//--- Create a graphical object form object on canvas on a specified chart and subwindow with the cyclic vertical gradient filling
   int               CreateFormVGradientCicle(const long chart_id,
                                              const int subwindow,
                                              const string name,
                                              const int x,
                                              const int y,
                                              const int w,
                                              const int h,
                                              color &clr[],
                                              const uchar opacity,
                                              const bool movable,
                                              const bool activity,
                                              const bool shadow=false,
                                              const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CForm *obj=new CForm(chart_id,subwindow,name,x,y,w,h);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.SetID(id);
                        obj.SetActive(activity);
                        obj.SetMovable(movable);
                        obj.SetColorBackground(clr[0]);
                        obj.SetColorFrame(clr[0]);
                        obj.SetOpacity(opacity,false);
                        obj.SetShadow(shadow);
                        obj.DrawRectangle(0,0,obj.Width()-1,obj.Height()-1,obj.ColorFrame(),obj.Opacity());
                        obj.Done();
                        obj.Erase(clr,opacity,true,true,redraw);
                        return obj.ID();
                       }
//--- Create a graphical object form object on canvas on a specified chart and subwindow with the cyclic horizontal gradient filling
   int               CreateFormHGradientCicle(const long chart_id,
                                              const int subwindow,
                                              const string name,
                                              const int x,
                                              const int y,
                                              const int w,
                                              const int h,
                                              color &clr[],
                                              const uchar opacity,
                                              const bool movable,
                                              const bool activity,
                                              const bool shadow=false,
                                              const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CForm *obj=new CForm(chart_id,subwindow,name,x,y,w,h);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.SetID(id);
                        obj.SetActive(activity);
                        obj.SetMovable(movable);
                        obj.SetColorBackground(clr[0]);
                        obj.SetColorFrame(clr[0]);
                        obj.SetOpacity(opacity,false);
                        obj.SetShadow(shadow);
                        obj.DrawRectangle(0,0,obj.Width()-1,obj.Height()-1,obj.ColorFrame(),obj.Opacity());
                        obj.Done();
                        obj.Erase(clr,opacity,false,true,redraw);
                        return obj.ID();
                       }
 
//--- Create graphical object WinForms Panel object on canvas on a specified chart and subwindow
   int               CreatePanel(const long chart_id,
                                 const int subwindow,
                                 const string name,
                                 const int x,
                                 const int y,
                                 const int w,
                                 const int h,
                                 const color clr,
                                 const uchar opacity,
                                 const bool movable,
                                 const bool activity,
                                 const bool shadow=false,
                                 const bool redraw=false)
                       {
                        int id=this.m_list_all_canv_elm_obj.Total();
                        CPanel *obj=new CPanel(chart_id,subwindow,name,x,y,w,h);
                        if(!this.AddCanvElmToCollection(obj))
                          {
                           delete obj;
                           return WRONG_VALUE;
                          }
                        obj.SetID(id);
                        obj.SetActive(activity);
                        obj.SetMovable(movable);
                        obj.SetColorBackground(clr);
                        obj.SetColorFrame(clr);
                        obj.SetOpacity(opacity,false);
                        obj.SetShadow(shadow);
                        obj.DrawRectangle(0,0,obj.Width()-1,obj.Height()-1,obj.ColorFrame(),obj.Opacity());
                        obj.Done();
                        obj.Erase(clr,opacity,redraw);
                        return obj.ID();
                       }

  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+

要素とフォームを作成するメソッドはほとんど同じです。唯一の違いは、背景を色で塗りつぶすメソッドにあります。これは、単一の永続的な色またはグラデーションで塗りつぶされています。グラデーションでの塗りつぶしには、垂直、水平、循環垂直および水平のいくつかのタイプがあります。作成されたオブジェクトは、直後にグラフィック要素のコレクションリストに追加され、必要最小限のプロパティ(呼び出されたときにメソッドに渡される)が設定されます。

指定されたフォームを除くすべてのフォームのインタラクションフラグをリセットするメソッドで は、オブジェクトタイプを要素に変更します。これは、グラフィック要素がGUI要素を構築するための最小オブジェクトであるためです。

//+--------------------------------------------------------------------+
//| Reset all interaction flags for all forms except the specified one |
//+--------------------------------------------------------------------+
void CGraphElementsCollection::ResetAllInteractionExeptOne(CGCnvElement *form_exept)
  {
   //--- In the loop by all graphical element collection class objects
   int total=this.m_list_all_canv_elm_obj.Total();
   for(int i=0;i<total;i++)
     {
      //--- get the pointer to the object
      CGCnvElement *obj=this.m_list_all_canv_elm_obj.At(i);
      //--- if failed to receive the pointer, or it is not a form, or it is not a form whose pointer has been passed to the method, move on
      if(obj==NULL || obj.TypeGraphElement()!=GRAPH_ELEMENT_TYPE_FORM || (obj.Name()==form_exept.Name() && obj.ChartID()==form_exept.ChartID()))
         continue;
      //--- Reset the interaction flag for the current form in the loop
      obj.SetInteraction(false);
     }
  }
//+------------------------------------------------------------------+


グラフィック要素、フォーム、およびパネルを作成するためのメソッドが用意されたため、メインCEngineライブラリオブジェクトの\MQL5\Include\DoEasy\Engine.mqh のコレクションリストにグラフィック要素を追加するメソッドは不要になりました。それを削除しましょう

//--- Return the list of graphical elements on canvas
   CArrayObj           *GetListCanvElement(void)                           { return this.m_graph_objects.GetListCanvElm();                }
//--- Add the graphical element on canvas to the collection
   bool                 GraphAddCanvElmToCollection(CGCnvElement *element) { return this.m_graph_objects.AddCanvElmToCollection(element); }
   
//--- Fill in the array with IDs of the charts opened in the terminal
   void              GraphGetArrayChartsID(long &array_charts_id[])

これは、チャートとオブジェクトIDによってグラフィック要素のリストを返し、チャートIDとオブジェクト名によってグラフィック要素のリストを返すメソッドに置き換えられます。

//--- Return the list of graphical elements on canvas
   CArrayObj           *GetListCanvElement(void)                           { return this.m_graph_objects.GetListCanvElm();                }
//--- Return the list of graphical elements by chart and object IDs
   CArrayObj           *GetListCanvElementByID(const long chart_id,const int element_id)
                          {
                           return this.m_graph_objects.GetListCanvElementByID(chart_id,element_id);
                          }
//--- Return the list of graphical elements by chart ID and object name
   CArrayObj           *GetListCanvElementByName(const long chart_id,const string name)
                          {
                           return this.m_graph_objects.GetListCanvElementByName(chart_id,name);
                          }
   
//--- Fill in the array with IDs of the charts opened in the terminal
   void              GraphGetArrayChartsID(long &array_charts_id[])

これらの2つのメソッドは、上記で検討したグラフィック要素のコレクションクラスの同名のメソッドからのリクエストの結果を返すだけです。

これで、検証する準備が整いました。


検証

テストを実行するには、前の記事のEAを使用して、\MQL5\Experts\TestDoEasy\Part101\TestDoEasyPart101.mq5として保存します。

前の記事の3つのフォームオブジェクトの作成を残し、3つの要素オブジェクトと1つのパネルオブジェクトを追加します。

各オブジェクトの上で、グラフィック要素コレクションに名前とIDを含むテキストを表示します。

OnInit()ハンドラで、現在の記事のメソッドコレクションクラスに追加されたメソッドを使用して、すべてのオブジェクトの作成を追加します。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Set EA global variables
   ArrayResize(array_clr,2);        // Array of gradient filling colors
   array_clr[0]=C'26,100,128';      // Original ≈Dark-azure color
   array_clr[1]=C'35,133,169';      // Lightened original color
//--- Create the array with the current symbol and set it to be used in the library
   string array[1]={Symbol()};
   engine.SetUsedSymbols(array);
   //--- Create the timeseries object for the current symbol and period, and show its description in the journal
   engine.SeriesCreate(Symbol(),Period());
   engine.GetTimeSeriesCollection().PrintShort(false); // Short descriptions
//--- Create form objects
   int obj_id=WRONG_VALUE;
   CArrayObj *list=NULL;
   CForm *form=NULL;
   for(int i=0;i<FORMS_TOTAL;i++)
     {
      obj_id=engine.GetGraphicObjCollection().CreateFormVGradient(ChartID(),0,"Form_0"+string(i+1),30,(form==NULL ? 100 : form.BottomEdge()+20),100,30,array_clr,245,true,true);
      list=engine.GetListCanvElementByID(ChartID(),obj_id);
      form=list.At(0);
      if(form==NULL)
         continue;
      //--- Set ZOrder to zero, display the text describing the gradient type and update the form
      //--- Text parameters: the text coordinates and the anchor point in the form center
      //--- Create a new text animation frame with the ID of 0 and display the text on the form
      form.SetZorder(0,false);
      form.TextOnBG(0,"Form: ID "+(string)form.ID()+", ZOrder "+(string)form.Zorder(),form.Width()/2,form.Height()/2,FRAME_ANCHOR_CENTER,C'211,233,149',255,true,false);
     }
//--- Create four graphical elements
   CGCnvElement *elm=NULL;
   array_clr[0]=C'0x65,0xA4,0xA9';
   array_clr[1]=C'0x48,0x75,0xA2';
//--- Vertical gradient
   obj_id=engine.GetGraphicObjCollection().CreateElementVGradient(NULL,0,"CElmVG",form.RightEdge()+50,20,200,50,array_clr,127,true,true,true);
   list=engine.GetGraphicObjCollection().GetListCanvElementByID(ChartID(),obj_id);
   elm=list.At(0);
   if(elm!=NULL)
     {
      elm.SetFontSize(10);
      elm.Text(elm.Width()/2,elm.Height()/2,"Element: ID "+(string)elm.ID(),C'0xDB,0xEE,0xF2',elm.Opacity(),FRAME_ANCHOR_CENTER);
      elm.Update();
     }
//--- Vertical cyclic gradient
   obj_id=engine.GetGraphicObjCollection().CreateElementVGradientCicle(NULL,0,"CElmVGC",form.RightEdge()+50,80, 200,50,array_clr,127,true,true,true);
   list=engine.GetGraphicObjCollection().GetListCanvElementByID(ChartID(),obj_id);
   elm=list.At(0);
   if(elm!=NULL)
     {
      elm.SetFontSize(10);
      elm.Text(elm.Width()/2,elm.Height()/2,"Element: ID "+(string)elm.ID(),C'0xDB,0xEE,0xF2',elm.Opacity(),FRAME_ANCHOR_CENTER);
      elm.Update();
     }
//--- Horizontal gradient
   obj_id=engine.GetGraphicObjCollection().CreateElementHGradient(NULL,0,"CElmHG",form.RightEdge()+50,140,200,50,array_clr,127,true,true,true);
   list=engine.GetGraphicObjCollection().GetListCanvElementByID(ChartID(),obj_id);
   elm=list.At(0);
   if(elm!=NULL)
     {
      elm.SetFontSize(10);
      elm.Text(elm.Width()/2,elm.Height()/2,"Element: ID "+(string)elm.ID(),C'0xDB,0xEE,0xF2',elm.Opacity(),FRAME_ANCHOR_CENTER);
      elm.Update();
     }
//--- Horizontal cyclic gradient
   obj_id=engine.GetGraphicObjCollection().CreateElementHGradientCicle(NULL,0,"CElmHGC",form.RightEdge()+50,200,200,50,array_clr,127,true,true,false);
   list=engine.GetGraphicObjCollection().GetListCanvElementByID(ChartID(),obj_id);
   elm=list.At(0);
   if(elm!=NULL)
     {
      elm.SetFontSize(10);
      elm.Text(elm.Width()/2,elm.Height()/2,"Element: ID "+(string)elm.ID(),C'0xDB,0xEE,0xF2',elm.Opacity(),FRAME_ANCHOR_CENTER);
      elm.Update();
     }

//--- Create WinForms Panel object
   CPanel *pnl=NULL;
   obj_id=engine.GetGraphicObjCollection().CreatePanel(ChartID(),0,"WFPanel",elm.RightEdge()+50,50,150,150,array_clr[0],200,true,true,false,true);
   list=engine.GetListCanvElementByID(ChartID(),obj_id);
   pnl=list.At(0);
   if(pnl!=NULL)
     {
      pnl.SetFontSize(10);
      pnl.TextOnBG(0,"WinForm Panel: ID "+(string)pnl.ID(),4,2,FRAME_ANCHOR_LEFT_TOP,pnl.ForeColor(),pnl.Opacity());
      pnl.Update(true);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+

シェイプオブジェクトは垂直方向のグラデーションで塗りつぶされますが、各要素オブジェクトは独自のタイプのグラデーションで塗りつぶされます。パネルオブジェクトは1つの色で塗りつぶされます

EAをコンパイルし、チャート上で起動します。


フォームはマウスの動きに反応し、チャートに追加されたグラフィカルオブジェクトの上に常に配置されます。要素オブジェクトのグラデーションでの塗りつぶしは正しく描画され、パネルオブジェクトの色は1つだけです。ただし、要素もパネルもマウスに反応せず、すべてのグラフィカルオブジェクトの下で背景に配置されます。これが起こるのは、フォームオブジェクトのマウスイベントのみを処理したからです。CFormクラスのみを明示的に処理するため、パネルが本質的にフォームであるという事実は重要ではありません。これは後ですべて修正します。


次の段階

次の記事では、WinForms Panelオブジェクトクラスの開発を続けます。

現在のライブラリバージョン、テストEA、およびMQL5のチャートイベントコントロール指標のすべてのファイルが、テストおよびダウンロードできるように以下に添付されています。質問や提案はコメント欄にお願いします。

目次に戻る

*前の連載の最後の記事:

DoEasyライブラリのグラフィックス(第100部):拡張された標準グラフィカルオブジェクトの処理を改善する


MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/10663

添付されたファイル |
MQL5.zip (4381.34 KB)
DoEasy - コントロール(第2部):CPanelクラスでの作業 DoEasy - コントロール(第2部):CPanelクラスでの作業
今回は、グラフィック要素の処理に関連するエラーを取り除き、CPanelコントロールの開発を継続する予定です。特に、すべてのパネルテキストオブジェクトにデフォルトで使用されるフォントのパラメータを設定するメソッドを実装します。
一からの取引エキスパートアドバイザーの開発(第7部):価格別出来高の追加(I) 一からの取引エキスパートアドバイザーの開発(第7部):価格別出来高の追加(I)
価格別出来高は、現存する最も強力なインジケータの1つです。ある程度の自信を持って取引するには、チャートにはこのインジケータが必須です。このインジケータはよく「テープリーディング」を好むトレーダーに使われますが、プライスアクションのみを使用して取引する場合にも活用できます。
一からの取引エキスパートアドバイザーの開発(第8部):概念的な飛躍 一からの取引エキスパートアドバイザーの開発(第8部):概念的な飛躍
新しい機能を実装する最も簡単な方法は何でしょうか。この記事では、1歩後退してから2歩前進します。
DoEasyライブラリのグラフィックス(第100部):拡張された標準グラフィックオブジェクトの処理を改善する DoEasyライブラリのグラフィックス(第100部):拡張された標準グラフィックオブジェクトの処理を改善する
現在の記事では、拡張(および標準)グラフィックオブジェクトとキャンバス上のフォームオブジェクトの同時処理における明らかな欠陥を排除し、前の記事で実行されたテスト中に検出されたエラーを修正します。ライブラリの説明のこのセクションは本稿で締めくくります。