DoEasy - コントロール(第1部):最初のステップ
内容
概念
本稿では、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つのサイズ変更オプションがあります。
- パネルサイズの増加のみ
- パネルサイズの増加および減少
前者の場合、配置されたオブジェクトを含まないパネルの側面は、オブジェクトが完全に収まるように拡大されます。後者の場合、上記のアクションに加えて、内部に配置されたオブジェクトよりも大きい辺を短くすることができます。
可能なグラフィカルオブジェクトの並べ替え基準を列挙したすぐ後に、インターフェイス要素のサイズを自動変更するモードを設定する新しい列挙を追加します。
//+------------------------------------------------------------------+ //| 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オブジェクトクラスの開発を続けます。
*前の連載の最後の記事:
DoEasyライブラリのグラフィックス(第100部):拡張された標準グラフィカルオブジェクトの処理を改善する
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/10663
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索