English Русский 中文 Español Deutsch Português
preview
DoEasy-コントロール(第12部):基本リストオブジェクト、ListBoxおよびButtonListBox WinFormsオブジェクト

DoEasy-コントロール(第12部):基本リストオブジェクト、ListBoxおよびButtonListBox WinFormsオブジェクト

MetaTrader 5 | 31 10月 2022, 10:28
126 0
Artyom Trishkin
Artyom Trishkin

内容


概念

この記事では、ライブラリ内のWinFormsオブジェクトに関する作業を続けます。前回の記事では、CheckedListBoxオブジェクトを作成しました。これは、本質的にはCheckBoxオブジェクトのリストです。さらにWinFormsオブジェクトのさまざまなリストを作成するので、WinFormsオブジェクトの基本オブジェクトリストのクラスを作成し、それに基づいて他のすべてのクラスを作成するのが合理的です。このクラスには、WinFormsオブジェクトのリストを処理するための主な機能と、それに続くコントロール(MSVisualStudioのDataBindings)に結合されたさまざまなデータを処理するための主な機能が含まれます。このデータは、要素のリストを行に表示するために使用されます。これにより、ライブラリ自体とターミナルおよびそのデータ基本の両方の環境から完全に異なるデータを表示でき、もちろんこれらのリストからそれらにアクセスできます。

このクラスに基づいて、特定のデータコレクションを表示する単純なリストであるListBox WinFormsオブジェクトを作成します。今のところ、リストには、作成中に作成されたリストアイテムの名前のみが表示されます。これらのアイテムを使用すると、マウスを操作できます(カーソルを合わせた時および選択時に背景色を変更)。WinFormsオブジェクトのイベント機能を作成するには、イベントハンドラに渡す必要があるデータを特定するために特定の数のオブジェクトを順番に作成する必要があるため、オブジェクトにはまだ実用的な用途はありません(オブジェクトの将来の機能を視覚的に表示するだけです)。異なるオブジェクトがより多く作成されるほど、WinFormsオブジェクトのイベント機能を正しく作成するために必要なデータとその構造についてのアイデアが得られます。

また、ボタンリストオブジェクトを作成します。ListBox(その行)はCButtonオブジェクトのクラスに正確に基づいて作成されるため、リストに一連のボタンを表示する追加のオブジェクトを作成することは非常に論理的です(リストに CheckBoxオブジェクトを表示するCheckedListBoxオブジェクトに似ています)。MS VisualStudioの標準コントロールのリストにはそのようなオブジェクトが含まれていないため、これは実験になります。


ライブラリクラスの改善

クライアントターミナルを最後に更新した後で、ライブラリの取引クラスCTradingが機能しなくなりました。継承されたクラスからのOpenPosition()およびPlaceOrder() privateメソッドへのアクセスが無効になりました。
したがって、\MQL5\Include\DoEasy\Trading.mqhで、これらのメソッドのためにクラスのprotectedセクションを設定します。

//--- Return the error handling method
   ENUM_ERROR_CODE_PROCESSING_METHOD   ResultProccessingMethod(const uint result_code);
//--- Correct errors
   ENUM_ERROR_CODE_PROCESSING_METHOD   RequestErrorsCorrecting(MqlTradeRequest &request,const ENUM_ORDER_TYPE order_type,const uint spread_multiplier,CSymbol *symbol_obj,CTradeObj *trade_obj);
   
//--- (1) Open a position, (2) place a pending order
protected:
   template<typename SL,typename TP> 
   bool                 OpenPosition(const ENUM_POSITION_TYPE type,
                                    const double volume,
                                    const string symbol,
                                    const ulong magic=ULONG_MAX,
                                    const SL sl=0,
                                    const TP tp=0,
                                    const string comment=NULL,
                                    const ulong deviation=ULONG_MAX,
                                    const ENUM_ORDER_TYPE_FILLING type_filling=WRONG_VALUE);
   template<typename PR,typename PL,typename SL,typename TP>
   bool                 PlaceOrder( const ENUM_ORDER_TYPE order_type,
                                    const double volume,
                                    const string symbol,
                                    const PR price,
                                    const PL price_limit=0,
                                    const SL sl=0,
                                    const TP tp=0,
                                    const ulong magic=ULONG_MAX,
                                    const string comment=NULL,
                                    const datetime expiration=0,
                                    const ENUM_ORDER_TYPE_TIME type_time=WRONG_VALUE,
                                    const ENUM_ORDER_TYPE_FILLING type_filling=WRONG_VALUE);
private:                                    
//--- Return the request object index in the list by (1) ID,
//--- (2) order ticket, (3) position ticket in the request
   int                  GetIndexPendingRequestByID(const uchar id);
   int                  GetIndexPendingRequestByOrder(const ulong ticket);
   int                  GetIndexPendingRequestByPosition(const ulong ticket);

public:


ここでは、privateセクション内に後でprivateセクションを返すprotectedセクションを作成しました


\MQL5\Include\DoEasy\Defines.mqhで、グラフィック要素型の列挙に3つの新しい型を追加します。

//+------------------------------------------------------------------+
//| 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_SHADOW_OBJ,                     // Shadow object
   GRAPH_ELEMENT_TYPE_ELEMENT,                        // Element
   GRAPH_ELEMENT_TYPE_FORM,                           // Form
   GRAPH_ELEMENT_TYPE_WINDOW,                         // Window
   //--- WinForms
   GRAPH_ELEMENT_TYPE_WF_UNDERLAY,                    // Panel object underlay
   GRAPH_ELEMENT_TYPE_WF_BASE,                        // Windows Forms Base
   //--- 'Container' object types are to be set below
   GRAPH_ELEMENT_TYPE_WF_CONTAINER,                   // Windows Forms container base object
   GRAPH_ELEMENT_TYPE_WF_PANEL,                       // Windows Forms Panel
   GRAPH_ELEMENT_TYPE_WF_GROUPBOX,                    // Windows Forms GroupBox
   //--- 'Standard control' object types are to be set below
   GRAPH_ELEMENT_TYPE_WF_COMMON_BASE,                 // Windows Forms base standard control
   GRAPH_ELEMENT_TYPE_WF_LABEL,                       // Windows Forms Label
   GRAPH_ELEMENT_TYPE_WF_BUTTON,                      // Windows Forms Button
   GRAPH_ELEMENT_TYPE_WF_CHECKBOX,                    // Windows Forms CheckBox
   GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON,                 // Windows Forms RadioButton
   GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX,           // Base list object of Windows Forms elements
   GRAPH_ELEMENT_TYPE_WF_LIST_BOX,                    // Windows Forms ListBox
   GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX,            // Windows Forms CheckedListBox
   GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX,             // Windows Forms ButtonListBox
  };
//+------------------------------------------------------------------+



キャンバス上のグラフィック要素の整数プロパティのリストの最後に、2つの新しいプロパティを追加し、整数プロパティの数を83から85に増やします

//+------------------------------------------------------------------+
//| Integer properties of the graphical element on the canvas        |
//+------------------------------------------------------------------+
enum ENUM_CANV_ELEMENT_PROP_INTEGER
  {
   CANV_ELEMENT_PROP_ID = 0,                          // Element ID
   CANV_ELEMENT_PROP_TYPE,                            // Graphical element type
   //---...
   //---...
   CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN,     // Color of control checkbox when clicking on the control
   CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER,     // Color of control checkbox when hovering the mouse over the control
   CANV_ELEMENT_PROP_LIST_BOX_MULTI_COLUMN,           // Horizontal display of columns in the ListBox control
   CANV_ELEMENT_PROP_LIST_BOX_COLUMN_WIDTH,           // Width of each ListBox control column
  };
#define CANV_ELEMENT_PROP_INTEGER_TOTAL (85)          // Total number of integer properties
#define CANV_ELEMENT_PROP_INTEGER_SKIP  (0)           // Number of integer properties not used in sorting
//+------------------------------------------------------------------+



キャンバス上のグラフィック要素を並べ替えるための基準の列挙にこれらの2つの新しいプロパティを追加します

//+------------------------------------------------------------------+
//| 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 integer properties
   SORT_BY_CANV_ELEMENT_ID = 0,                       // Sort by element ID
   SORT_BY_CANV_ELEMENT_TYPE,                         // Sort by graphical element type
   //---...
   //---...
   SORT_BY_CANV_ELEMENT_CHECK_FLAG_COLOR_MOUSE_DOWN,  // Sort by color of control checkbox when clicking on the control
   SORT_BY_CANV_ELEMENT_CHECK_FLAG_COLOR_MOUSE_OVER,  // Sort by color of control checkbox when hovering the mouse over the control
   SORT_BY_CANV_ELEMENT_LIST_BOX_MULTI_COLUMN,        // Sort by horizontal column display flag in the ListBox control
   SORT_BY_CANV_ELEMENT_LIST_BOX_COLUMN_WIDTH,        // Sort by the width of each ListBox control column
//--- Sort by real properties

//--- Sort by string properties
   SORT_BY_CANV_ELEMENT_NAME_OBJ = FIRST_CANV_ELEMENT_STR_PROP,// Sort by an element object name
   SORT_BY_CANV_ELEMENT_NAME_RES,                     // Sort by the graphical resource name
   SORT_BY_CANV_ELEMENT_TEXT,                         // Sort by graphical element text
  };
//+------------------------------------------------------------------+


これで、これら2つの新しいプロパティでオブジェクトを選択して並べ替えることができます。実際、グラフィカルオブジェクトを処理してGUIを構築する場合、これは特に必要ありません(これらのプロパティによる検索を使用するためのオプションはありません)。ただし、GUIオブジェクトのすべてのプロパティをこれらのリストに完全に入力して、チャートウィンドウで直接グラフィカルシェルを作成および処理するプログラムのGUIを構築できるようにします。ここでは、グラフィック要素のすべてのプロパティを完全に取得および変更する必要があります。

\MQL5\Include\DoEasy\Data.mqhで、ライブラリの新しいメッセージインデックスを追加し、インデックスの名前をMSG_CHECKED_LIST_ERR_FAILED_CREATE_CHECK_BOX_OBJに変更し、インデックスMSG_CHECKED_LIST_ERR_FAILED_GET_CHECK_BOX_OBJを削除します。

//--- WinForms standard
   MSG_GRAPH_ELEMENT_TYPE_WF_COMMON_BASE,             // WinForms base standard control
   MSG_GRAPH_ELEMENT_TYPE_WF_LABEL,                   // Label control
   MSG_GRAPH_ELEMENT_TYPE_WF_CHECKBOX,                // CheckBox control
   MSG_GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON,             // RadioButton control
   MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON,                  // Button control
   MSG_GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX,       // Base list object of Windows Forms elements
   MSG_GRAPH_ELEMENT_TYPE_WF_LIST_BOX,                // ListBox control
   MSG_GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX,        // CheckedListBox control
   MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX,         // ButtonListBox 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


...

//--- CPanel
   MSG_PANEL_OBJECT_ERR_FAILED_CREATE_UNDERLAY_OBJ,   // Failed to create the underlay object
   MSG_PANEL_OBJECT_ERR_OBJ_MUST_BE_WFBASE,           // Error. The created object should be of WinForms Base type or be derived from it

//--- ElementsListBox
   MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ,     // Failed to get a graphical element 
                                                 

//--- CButtonListBox
   MSG_BUTT_LIST_ERR_FAILED_SET_GROUP_BUTTON,         // Failed to set the group for the button with the index 
   MSG_BUTT_LIST_ERR_FAILED_SET_TOGGLE_BUTTON,        // Failed to set the Toggle flag to the button with the index 

//--- Integer properties of graphical elements


...

   MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN, // Color of control checkbox when clicking on the control
   MSG_CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER, // Color of control checkbox when hovering the mouse over the control
   MSG_CANV_ELEMENT_PROP_LIST_BOX_MULTI_COLUMN,       // Horizontal display of columns in the ListBox control
   MSG_CANV_ELEMENT_PROP_LIST_BOX_COLUMN_WIDTH,       // Width of each ListBox control column
//--- Real properties of graphical elements

//--- String properties of graphical elements
   MSG_CANV_ELEMENT_PROP_NAME_OBJ,                    // Graphical element object name
   MSG_CANV_ELEMENT_PROP_NAME_RES,                    // Graphical resource name
   MSG_CANV_ELEMENT_PROP_TEXT,                        // Graphical element text

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



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

//--- WinForms standard
   {"Базовый стандартный элемент управления WinForms","Basic Standard WinForms Control"},
   {"Элемент управления \"Label\"","Control element \"Label\""},
   {"Элемент управления \"CheckBox\"","Control element \"CheckBox\""},
   {"Элемент управления \"RadioButton\"","Control element \"RadioButton\""},
   {"Элемент управления \"Button\"","Control element \"Button\""},
   {"Базовый объект-список Windows Forms элементов","Basic Windows Forms List Object"},
   {"Элемент управления \"ListBox\"","Control element \"ListBox\""},
   {"Элемент управления \"CheckedListBox\"","Control element \"CheckedListBox\""},
   {"Элемент управления \"ButtonListBox\"","Control element \"ButtonListBox\""},
   
   {"Графический объект принадлежит программе","The graphic object belongs to the program"},
   {"Графический объект не принадлежит программе","The graphic object does not belong to the program"},


...

//--- CPanel
   {"Не удалось создать объект-подложку","Failed to create underlay object"},
   {"Ошибка. Создаваемый объект должен иметь тип WinForms Base или быть его наследником","Error. The object being created must be of type WinForms Base or be derived from it"},

//--- ElementsListBox
   {"Не удалось получить графический элемент ","Failed to get graphic element "},
                                                                                 
//--- CButtonListBox
   {"Не удалось установить группу кнопке с индексом ","Failed to set group for button with index "},
   {"Не удалось установить флаг \"Переключатель\" кнопке с индексом ","Failed to set the \"Toggle\" flag on the button with index "},
   
//--- Integer properties of graphical elements


...

   {"Цвет флажка проверки элемента управления при нажатии мышки на элемент управления","Control Checkbox Colorl when the mouse is pressed on the control"},
   {"Цвет флажка проверки элемента управления при наведении мышки на элемент управления","Control Checkbox Colorl when hovering the mouse over the control"},
   {"Горизонтальное отображение столбцов в элементе управления ListBox","Display columns horizontally in a ListBox control"},
   {"Ширина каждого столбца элемента управления ListBox","The width of each column of the ListBox control"},
   
//--- String properties of graphical elements
   {"Имя объекта-графического элемента","The name of the graphic element object"},
   {"Имя графического ресурса","Image resource name"},
   {"Текст графического элемента","Text of the graphic element"},

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



グラフィック要素の指定された型の説明を返す必要があります。現時点では、ライブラリの基本グラフィカルオブジェクトのクラスにはTypeElementDescription()メソッドがあり、現在のグラフィカルオブジェクトの型の説明、つまり、それ自体の型の説明を返します。ただし、メソッドの入力パラメータで指定されたグラフィック要素の説明を返す必要があります。したがって、これをおこないましょう。オブジェクトの型を渡す既存のメソッドに正式なパラメータを追加し、現在のオブジェクトの型を返すオーバーロードされたメソッドを実装します。

\MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqhで必要な変更をおこないます。
publicセクションで、新しいオーバーロードされたメソッドを宣言します。このメソッドではオブジェクト型を渡しますが、前のメソッドは現在のオブジェクト型を新しいメソッドに渡します。

//--- Return the graphical object type (ENUM_OBJECT) calculated from the object type (ENUM_OBJECT_DE_TYPE) passed to the method
   ENUM_OBJECT       GraphObjectType(const ENUM_OBJECT_DE_TYPE obj_type) const
                       { 
                        return ENUM_OBJECT(obj_type-OBJECT_DE_TYPE_GSTD_OBJ-1);
                       }
   
//--- Return the description of the type of the graphical object (1) type, (2, 3) element, (4) affiliation and (5) species
string               TypeGraphObjectDescription(void);
string               TypeElementDescription(const ENUM_GRAPH_ELEMENT_TYPE type);
string               TypeElementDescription(void);
string               BelongDescription(void);
string               SpeciesDescription(void);


クラス本体の外で両方のメソッドを完成します。

仮パラメータを持つメソッドで、指定された型に従って新しい型のライブラリグラフィック要素の説明を返すようにします。

//+------------------------------------------------------------------+
//| Return the description of the graphical element type             |
//+------------------------------------------------------------------+
string CGBaseObj::TypeElementDescription(const ENUM_GRAPH_ELEMENT_TYPE type)
  {
   return
     (
      type==GRAPH_ELEMENT_TYPE_STANDARD               ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD)              :
      type==GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED      ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED)     :
      type==GRAPH_ELEMENT_TYPE_ELEMENT                ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_ELEMENT)               :
      type==GRAPH_ELEMENT_TYPE_SHADOW_OBJ             ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_SHADOW_OBJ)            :
      type==GRAPH_ELEMENT_TYPE_FORM                   ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_FORM)                  :
      type==GRAPH_ELEMENT_TYPE_WINDOW                 ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WINDOW)                :
      //--- WinForms
      type==GRAPH_ELEMENT_TYPE_WF_UNDERLAY            ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_UNDERLAY)           :
      type==GRAPH_ELEMENT_TYPE_WF_BASE                ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BASE)               :
      //--- Containers
      type==GRAPH_ELEMENT_TYPE_WF_CONTAINER           ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CONTAINER)          :
      type==GRAPH_ELEMENT_TYPE_WF_GROUPBOX            ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_GROUPBOX)           :
      type==GRAPH_ELEMENT_TYPE_WF_PANEL               ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_PANEL)              :
      //--- Standard controls
      type==GRAPH_ELEMENT_TYPE_WF_COMMON_BASE         ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_COMMON_BASE)        :
      type==GRAPH_ELEMENT_TYPE_WF_LABEL               ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LABEL)              :
      type==GRAPH_ELEMENT_TYPE_WF_CHECKBOX            ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CHECKBOX)           :
      type==GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON         ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON)        :
      type==GRAPH_ELEMENT_TYPE_WF_BUTTON              ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON)             :
      type==GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX   ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX)  :
      type==GRAPH_ELEMENT_TYPE_WF_LIST_BOX            ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LIST_BOX)           :
      type==GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX    ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX)   :
      type==GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX     ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX)    :
      "Unknown"
     );
  }  
//+------------------------------------------------------------------+


現在のオブジェクト型を返す以前のメソッドは、現在のオブジェクト型が渡されるオーバーロードされたメソッドを呼び出した結果を返します

//+------------------------------------------------------------------+
//| Return the description of the graphical element type             |
//+------------------------------------------------------------------+
string CGBaseObj::TypeElementDescription(void)
  {
   return this.TypeElementDescription(this.TypeGraphElement());
  }
//+------------------------------------------------------------------+



グループ内のボタンの操作は、ボタンが属するグループに直接依存するため、グループインデックスのログへの出力をテキストメッセージとして実装し、ボタングループの正しい選択を制御します。

\MQL5\Include\DoEasy\Objects\Graph\WForms\CommonControls\Button.mqh、つまり「カーソルがアクティブ領域内にあり、マウスの左ボタンがクリックされた」イベントハンドラに、グループで動作するボタンの処理を追加しますボタングループインデックスをログデータ出力文字列に書き込みます

//+------------------------------------------------------------------+
//| 'The cursor is inside the active area,                           |
//| left mouse button released                                       |
//+------------------------------------------------------------------+
void CButton::MouseActiveAreaReleasedHandler(const int id,const long& lparam,const double& dparam,const string& sparam)
  {
//--- The mouse button released outside the element means refusal to interact with the element
   if(lparam<this.CoordX() || lparam>this.RightEdge() || dparam<this.CoordY() || dparam>this.BottomEdge())
     {
      //--- If this is a simple button, set the initial background color
      if(!this.Toggle())
         this.SetBackgroundColor(this.BackgroundColorInit(),false);
      //--- If this is the toggle button, set the initial color depending on whether the button is pressed or not
      else
         this.SetBackgroundColor(!this.State() ? this.BackgroundColorInit() : this.BackgroundColorToggleONInit(),false);
      //--- Set the initial frame color
      this.SetBorderColor(this.BorderColorInit(),false);
      //--- Send the test message to the journal
      Print(DFUN_ERR_LINE,TextByLanguage("Отмена","Cancel"));
     }
//--- The mouse button released within the element means a  click on the control
   else
     {
      //--- If this is a simple button, set the color for "The cursor is over the active area" status
      if(!this.Toggle())
         this.SetBackgroundColor(this.BackgroundColorMouseOver(),false);
      //--- If this is the toggle button,
      else
        {
         //--- if the button does not work in the group, set its state to the opposite,
         if(!this.GroupButtonFlag())
            this.SetState(!this.State());
         //--- if the button is not pressed yet, set it to the pressed state
         else if(!this.State())
            this.SetState(true);
         //--- set the background color for "The cursor is over the active area" status depending on whether the button is clicked or not
         this.SetBackgroundColor(this.State() ? this.BackgroundColorToggleONMouseOver() : this.BackgroundColorMouseOver(),false);
        }
      //--- Send the test message to the journal
      Print(DFUN_ERR_LINE,TextByLanguage("Щелчок","Click"),", this.State()=",this.State(),", ID=",this.ID(),", Group=",this.Group());
      //--- Set the frame color for "The cursor is over the active area" status
      this.SetBorderColor(this.BorderColorMouseOver(),false);
     }
//--- Redraw the object
   this.Redraw(false);
  }
//+------------------------------------------------------------------+


トグルボタンにはいくつかの操作モードがあります。1つのトグルボタンは押したり離したりできます。同じコンテナ内に同じグループを持つ複数のトグルボタンがある場合、それらのボタンの1つを押すと、このグループの残りのボタンが解放されるように動作します。すでに押されたボタンをもう一度押すと、解放されます。


ボタンの各グループにグループボタンフラグを追加し、それぞれが同じグループを持つ場合、そのようなボタンの動作は少し異なります。同様に、1つのボタンを押すと残りのボタンが解放されますが、既に押されているボタンを押しても解放されません。この場合、いずれかのボタンが常に押されていることになります。

グループ番号のログはデバッグメッセージです。デバッグ後は削除されますが、動作の正当性を確認するために、クリックされたボタンが属するグループを確認する必要があることがあります。

グループボタンフラグを返すGroupButton()メソッドの名前を変更して、メソッドがグループ番号ではなくフラグを正確に返すことを明確にします。

   bool              State(void)                         const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_STATE);                                }
   
//--- (1) Set and (2) return the group flag
   void              SetGroupButtonFlag(const bool flag)       { this.SetProperty(CANV_ELEMENT_PROP_BUTTON_GROUP,flag);                                        }
   bool              GroupButtonFlag(void)               const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_GROUP);                                }
   
//--- (1,2) Set and (3) return the main background color for the 'enabled' status
   void              SetBackgroundColorToggleON(const color colour,const bool set_init_color)



WinFormsオブジェクトリストの基本クラス

WinFormsオブジェクトリストオブジェクトは同様の機能を持っているため、子孫に共通の機能を持つ基本オブジェクトを作成し、そこから残りを継承し、子クラスに固有の独自の機能を作成することをお勧めします。

\MQL5\Include\DoEasy\Objects\Graph\WForms\CommonControls\ライブラリフォルダで、CElementsListBoxクラスの新しいElementsListBox.mqhファイルを作成します。

クラスは基本コンテナクラスから継承し、クラスファイルをそれにインクルードする必要があります。

//+------------------------------------------------------------------+
//|                                              ElementsListBox.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4 
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\Containers\Container.mqh"
//+------------------------------------------------------------------+
//| Class of the base object of the WForms control list              |
//+------------------------------------------------------------------+
class CElementsListBox : public CContainer
  {
  }


クラスのprivateセクションで、リスト内で次に作成されるオブジェクトの座標を返すメソッドを宣言します。protectedセクションでは、指定された数の指定されたWinFormsオブジェクトを作成するメソッドを宣言します。publicセクションで、パラメトリックコンストラクタと、リスト内のオブジェクトを複数の列に配置するアクセス許可を設定および返すためのメソッドと、各列の幅を設定するメソッドを宣言します。

//+------------------------------------------------------------------+
//| Class of the base object of the WForms control list              |
//+------------------------------------------------------------------+
class CElementsListBox : public CContainer
  {
private:
//--- Return the coordinates of the next object placed in the list
   void              GetCoordsObj(CWinFormBase *obj,int &x,int &y);
protected:
//--- Create the specified number of specified WinForms objects
   void              CreateElements(ENUM_GRAPH_ELEMENT_TYPE element_type,
                                    const int count,
                                    const int x,
                                    const int y,
                                    const int w,
                                    const int h,
                                    uint new_column_width=0,
                                    const bool autosize=true);
public:
//--- Constructor
                     CElementsListBox(const long chart_id,
                                      const int subwindow,
                                      const string name,
                                      const int x,
                                      const int y,
                                      const int w,
                                      const int h);
//--- (1) Set and (2) return the flag of horizontal display of columns
   void              SetMultiColumn(const bool flag)        { this.SetProperty(CANV_ELEMENT_PROP_LIST_BOX_MULTI_COLUMN,flag);          }
   bool              MultiColumn(void)                const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_LIST_BOX_MULTI_COLUMN);  }
//--- (1) Set and (2) return the width of each column
   void              SetColumnWidth(const uint value)       { this.SetProperty(CANV_ELEMENT_PROP_LIST_BOX_COLUMN_WIDTH,value);         }
   uint              ColumnWidth(void)                const { return (uint)this.GetProperty(CANV_ELEMENT_PROP_LIST_BOX_COLUMN_WIDTH);  }
   
  };
//+------------------------------------------------------------------+



宣言されたメソッドを詳しく見てみましょう。

クラスコンストラクタで、グラフィック要素の型とライブラリのグラフィカルオブジェクトの型を指定し、1ピクセルの単純なフレームのサイズを設定し、オブジェクト内のフレームとテキストのデフォルトの色を設定します。列ごとのリストの配置を無効にして、列幅をゼロに指定します。

//+------------------------------------------------------------------+
//| Constructor indicating the chart and subwindow ID                |
//+------------------------------------------------------------------+
CElementsListBox::CElementsListBox(const long chart_id,
                                   const int subwindow,
                                   const string name,
                                   const int x,
                                   const int y,
                                   const int w,
                                   const int h) : CContainer(chart_id,subwindow,name,x,y,w,h)
  {
   CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX);
   CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX);
   this.m_type=OBJECT_DE_TYPE_GWF_COMMON;
   this.SetBorderSizeAll(1);
   this.SetBorderStyle(FRAME_STYLE_SIMPLE);
   this.SetBorderColor(CLR_DEF_BORDER_COLOR,true);
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
   this.SetMultiColumn(false);
   this.SetColumnWidth(0);
  }
//+------------------------------------------------------------------+



以下は、指定された数の特定のWinFormsオブジェクトを作成するメソッドです。

//+------------------------------------------------------------------+
//| Create the specified number of certain WinForms objects          |
//+------------------------------------------------------------------+
void CElementsListBox::CreateElements(ENUM_GRAPH_ELEMENT_TYPE element_type,
                                      const int count,
                                      const int x,
                                      const int y,
                                      const int w,
                                      const int h,
                                      uint new_column_width=0,
                                      const bool autosize=true)
  {
//--- Set the width of columns if the value greater than zero has been passed
   if(new_column_width>0)
     {
      if(this.ColumnWidth()!=new_column_width)
         this.SetColumnWidth(new_column_width);
     }
//--- Create a pointer to the created WinFormBase object
   CWinFormBase *obj=NULL;
//--- In the loop through the specified number of objects
   for(int i=0;i<count;i++)
     {
      //--- Get the coordinates of the created object
      int coord_x=x, coord_y=y;
      this.GetCoordsObj(obj,coord_x,coord_y);
      //--- If the object could not be created, send the appropriate message to the log and move on to the next one
      if(!this.CreateNewElement(element_type,coord_x,coord_y,w,h,clrNONE,255,true,false))
        {
         ::Print(DFUN,MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ,this.TypeElementDescription(element_type));
         continue;
        }
      //--- Get the created object from the list by the loop index
      obj=this.GetElement(i);
      //--- If the object could not be obtained, send the appropriate message to the log and move on to the next one
      if(obj==NULL)
        {
         ::Print(DFUN,MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ,this.TypeElementDescription(element_type));
         continue;
        }
      //--- Set the frame size of the created object to zero
      obj.SetBorderSizeAll(0);
      //--- Set the opacity of the base object and the default background color
      obj.SetOpacity(this.Opacity());
      obj.SetBackgroundColor(this.BackgroundColor(),true);
      obj.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_STD_MOUSE_OVER);
      obj.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_STD_MOUSE_DOWN);
     }
//--- If the flag of auto resizing the base object is passed to the method,
//--- set the auto resize mode to "increase and decrease"
   if(autosize)
      this.SetAutoSizeMode(CANV_ELEMENT_AUTO_SIZE_MODE_GROW_SHRINK,false);
  }
//+------------------------------------------------------------------+


メソッドのロジックは、コードのコメントで説明されています。ここではすべてが明確であると思います。作成されたオブジェクトが構築されているパネルの自動サイズ変更は、パネルの寸法を作成された要素に合わせるために必要です。一部のクラスはこれを必要としないため、パネルの寸法をそのコンテンツに合わせる必要があることを示すフラグが導入されています。


以下は、リストに配置された次のオブジェクトの座標を返すメソッドです。

//+------------------------------------------------------------------+
//| Return the coordinates of the next object placed in the list     |
//+------------------------------------------------------------------+
void CElementsListBox::GetCoordsObj(CWinFormBase *obj,int &x,int &y)
  {
//--- Save the coordinates passed to the method in the variables
   int coord_x=x;
   int coord_y=y;
//--- If the flag of using multiple columns is not set,
   if(!this.MultiColumn())
     {
      //--- set the X coordinate the same as the one passed to the method,
      //--- set the Y coordinate for the first object in the list to be equal to the one passed to the method,
      //--- set the rest 4 pixels lower than the bottom edge of the previous object located above.
      //--- After setting the coordinates to the variables, leave the method
      x=coord_x;
      y=(obj==NULL ? coord_y : obj.BottomEdgeRelative()+4);
      return;
     }
//--- If multiple columns can be used
//--- If this is the first object in the list, 
   if(obj==NULL)
     {
      //--- set the coordinates the same as those passed to the method and leave
      x=coord_x;
      y=coord_y;
      return;
     }
//--- If this is not the first object in the list
//--- If (the bottom border of the previous object + 4 pixels) is below the bottom border of the ListBox panel (the next object will go beyond the borders),
   if(obj.BottomEdge()+4>this.BottomEdge())
     {
      //--- If the columns width is zero, then the X coordinate of the created object will be the right border of the previous object + 6 pixels
      //--- Otherwise, if the width of the columns is greater than zero, then the X coordinate of the created object will be the X coordinate of the previous one + the column width
      //--- The Y coordinate will be the value passed to the method (start placing objects in a new column)
      x=(this.ColumnWidth()==0 ? obj.RightEdgeRelative()+6 : int(obj.CoordXRelative()+this.ColumnWidth()));
      y=coord_y;
     }
//--- If the created object is placed within the ListBox panel,
   else
     {
      //--- the X coordinate of the created object will be the offset of the previous one from the panel edge minus the width of its frame,
      //--- the Y coordinate will be the lower border of the previous object located above plus 4 pixels
      x=obj.CoordXRelative()-this.BorderSizeLeft();
      y=obj.BottomEdgeRelative()+4;
     }
  }
//+------------------------------------------------------------------+


ここで、メソッドのロジックは、コードへのコメントで詳細に説明されています。このメソッドでは、リストの最初のオブジェクトが配置される初期座標と、リストに既に配置されている前のオブジェクトの座標に基づいて、次のオブジェクトの座標を計算します。さらに、オブジェクトを複数の列に配置できるフラグが設定されている場合、メソッドは、次に作成されるオブジェクトがそのパネルの領域に収まるかどうかを計算します(オブジェクト全体ではなく、その位置座標のみが考慮されます)。オブジェクト(そのY座標)がパネル内に収まる場合、そのオブジェクトは前のオブジェクトの下に構築されます。座標がパネルを超える場合、オブジェクトは初期Y座標で前のオブジェクトの右境界線に対して右に構築されます。これは、新しい列の建設の始まりを意味します。オブジェクトがパネル内に配置された後、そのサイズは、現在のオブジェクトが呼び出されたメソッドの内部コンテンツに合わせて調整されます。したがって、最も低いオブジェクトの位置のすべての不正確さが修正されます。不正確さ(一番下のオブジェクトのY座標がパネルの内側にあり、残りの部分が制限の外にあります)は、リスト内の1つのオブジェクトの高さが他のオブジェクトと異なる可能性があるため、形成される可能性があります。リストにさまざまなオブジェクトを配置できます。したがって、将来のオブジェクトの寸法を計算し、それがパネル領域に完全に収まるかどうか、およびその下端からパネルの下端までの距離が正しいかどうかを考慮する代わりに、パネルのサイズを、パネル内に既に作成されているコンテンツに合わせて調整するだけです。これははるかに簡単です。


WinFormsリストオブジェクトの基本オブジェクトができたので、既に作成されているCheckedListBoxリストオブジェクトを変更する必要があります。

\MQL5\Include\DoEasy\Objects\Graph\WForms\CommonControls\CheckedListBox.mqhのオブジェクトクラスを改善しましょう。

パネルオブジェクトクラスをクラスファイルに含める代わりに、

#include "..\Containers\Panel.mqh"

代わりに、新しく作成されたクラスのファイルをインクルードして、ここから継承します

//+------------------------------------------------------------------+
//|                                               CheckedListBox.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ElementsListBox.mqh"
//+------------------------------------------------------------------+
//| CheckedListBox object class of the WForms controls               |
//+------------------------------------------------------------------+
class CCheckedListBox : public CElementsListBox
  {



指定された数のCheckBoxオブジェクトを作成するメソッドの宣言で、作成されたオブジェクトの幅新しい列幅の値を指定するための仮パラメータを追加します。

public:
//--- Create the specified number of CheckBox objects
   void              CreateCheckBox(const int count,const int width,const int new_column_width=0);
//--- Constructor



クラスコンストラクタの初期化リストで、パラメータを新しい親クラスに渡します

//+------------------------------------------------------------------+
//| Constructor indicating the chart and subwindow ID                |
//+------------------------------------------------------------------+
CCheckedListBox::CCheckedListBox(const long chart_id,
                                 const int subwindow,
                                 const string name,
                                 const int x,
                                 const int y,
                                 const int w,
                                 const int h) : CElementsListBox(chart_id,subwindow,name,x,y,w,h)
  {
   CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX);
   CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX);
   this.m_type=OBJECT_DE_TYPE_GWF_COMMON;
   this.SetBorderSizeAll(1);
   this.SetBorderStyle(FRAME_STYLE_SIMPLE);
   this.SetBorderColor(CLR_DEF_BORDER_COLOR,true);
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
  }
//+------------------------------------------------------------------+



指定された数のCheckBoxオブジェクトを作成するメソッドは、新しい親クラスが指定された型で指定された数のオブジェクトを作成するメソッドを備えているため、再設計されました。

//+------------------------------------------------------------------+
//| Create the specified number of CheckBox objects                  |
//+------------------------------------------------------------------+
void CCheckedListBox::CreateCheckBox(const int count,const int width,const int new_column_width=0)
  {
//--- Create a pointer to the CheckBox object
   CCheckBox *obj=NULL;
//--- Create the specified number of CheckBox objects
   CElementsListBox::CreateElements(GRAPH_ELEMENT_TYPE_WF_CHECKBOX,count,2,2,width,DEF_CHECK_SIZE+1,new_column_width);
//--- In the loop by the created number of objects
   for(int i=0;i<this.ElementsTotal();i++)
     {
      //--- Get the created object from the list by the loop index
      obj=this.GetElement(i);
      //--- If the object could not be obtained, send the appropriate message to the log and move on to the next one
      if(obj==NULL)
        {
         ::Print(DFUN,MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ,this.TypeElementDescription(GRAPH_ELEMENT_TYPE_WF_CHECKBOX));
         continue;
        }
      //--- Set the left center alignment of the checkbox and the text
      obj.SetCheckAlign(ANCHOR_LEFT);
      obj.SetTextAlign(ANCHOR_LEFT);
      //--- Set the object text
      obj.SetText("CheckBox"+string(i+1));
     }
  }
//+------------------------------------------------------------------+


したがって、まずオブジェクトリストを作成してから、各オブジェクトに必要なパラメータを作成されたオブジェクトによるループで指定します。

メソッドが短くなり、読みやすくなりました。


ListBoxおよびButtonListBox WinFormsオブジェクトクラス

新しいListBoxWinFormsオブジェクトクラスの開発を始めましょう。

このオブジェクトは単純なテキストリストで、任意の項目を選択できます。リストの行がマウスと対話できるようにする必要があるため、そのような機能を持たないテキストラベルオブジェクト(CLabelライブラリのクラス)の代わりに、ボタンオブジェクトのクラスを使用してリストを表示することが論理的です。.マウスのカーソルを合わせると反応し、選択されます(ボタンを押下)。


ボタンをテキストリストアイテムのように見せるには、境界線の色を背景色と一致させる必要があります。この場合、ボタンは背景に溶け込み、ボタン上のテキストのみが表示されます。ボタン領域(視覚的にはテキスト上)にカーソルを合わせると、テキストの背景色が変わります。テキスト(ボタン)をクリックすると、選択されます(ボタンが押下)。

ボタンから作成されたリストがMSVisualStudioのListBoxのように動作するようにするには、リストのすべてのボタンをグループに含め(それらのグループフラグを設定)、それらをトグルにする必要があります(2つの機能を持つことができます)。状態-オン/オフ)。各ボタン(リスト行)には、パネルのグループ番号に対応するグループインデックスがありますが、各リストボタンに設定されたグループフラグでは、既に選択されているリスト項目を選択解除することはできません。

\MQL5\Include\DoEasy\Objects\Graph\WForms\CommonControls\ライブラリフォルダで、CListBoxクラスの新しいListBox.mqhファイルを作成します。

クラスはリストオブジェクトの基本クラスから派生する必要があり、そのファイルは作成されたクラスファイルに含まれる必要があります

//+------------------------------------------------------------------+
//|                                                      ListBox.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ElementsListBox.mqh"
//+------------------------------------------------------------------+
//| Class of the base object of the WForms control list              |
//+------------------------------------------------------------------+
class CListBox : public CElementsListBox
  {
  }



クラスのprivateセクションでは、新しいグラフィカルオブジェクトを作成するための仮想メソッドを宣言し、publicセクションでは、リストとパラメトリックコンストラクタを作成するためのメソッドを宣言します。

//+------------------------------------------------------------------+
//| Class of the base object of the WForms control list              |
//+------------------------------------------------------------------+
class CListBox : public CElementsListBox
  {
private:
//--- Create a new graphical object
   virtual 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);
public:
//--- Create a list from the specified number of rows (Label objects)
   void              CreateList(const int line_count);
//--- Constructor
                     CListBox(const long chart_id,
                              const int subwindow,
                              const string name,
                              const int x,
                              const int y,
                              const int w,
                              const int h);
  };
//+------------------------------------------------------------------+



パラメトリックコンストラクタで、グラフィック要素の型ライブラリオブジェクトの型を指定し、オブジェクトフレーム、フレームの色、およびテキストの既定値を設定し、複数の列の作成を無効にします。列幅をゼロに設定します。

//+------------------------------------------------------------------+
//| Constructor indicating the chart and subwindow ID                |
//+------------------------------------------------------------------+
CListBox::CListBox(const long chart_id,
                   const int subwindow,
                   const string name,
                   const int x,
                   const int y,
                   const int w,
                   const int h) : CElementsListBox(chart_id,subwindow,name,x,y,w,h)
  {
   CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_LIST_BOX);
   CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_LIST_BOX);
   this.m_type=OBJECT_DE_TYPE_GWF_COMMON;
   this.SetBorderSizeAll(1);
   this.SetBorderStyle(FRAME_STYLE_SIMPLE);
   this.SetBorderColor(CLR_DEF_BORDER_COLOR,true);
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
   this.SetMultiColumn(false);
   this.SetColumnWidth(0);
  }
//+------------------------------------------------------------------+



以下は、指定された行数からリストを作成するメソッドです。

//+--------------------------------------------------------------------+
//| Create the list from the specified number of rows (Button objects) |
//+--------------------------------------------------------------------+
void CListBox::CreateList(const int count)
  {
//--- Create the pointer to the Button object
   CButton *obj=NULL;
//--- Create the specified number of Button objects
   CElementsListBox::CreateElements(GRAPH_ELEMENT_TYPE_WF_BUTTON,count,2,2,this.Width()-4,12,0,false);
//--- In the loop by the created number of objects
   for(int i=0;i<this.ElementsTotal();i++)
     {
      //--- Get the created object from the list by the loop index
      obj=this.GetElement(i);
      //--- If the object could not be obtained, send the appropriate message to the log and move on to the next one
      if(obj==NULL)
        {
         ::Print(DFUN,MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ,this.TypeElementDescription(GRAPH_ELEMENT_TYPE_WF_BUTTON));
         continue;
        }
      //--- Set left center text alignment
      obj.SetTextAlign(ANCHOR_LEFT);
      //--- Set the object text
      obj.SetFontSize(8);
      obj.SetText("ListBoxItem"+string(i+1));
      //--- Set the frame colors equal to the background colors and the flag of the toggle button
      obj.SetBorderColor(obj.BackgroundColor(),true);
      obj.SetBorderColorMouseDown(obj.BackgroundColorMouseDown());
      obj.SetBorderColorMouseOver(obj.BackgroundColorMouseOver());
      obj.SetToggleFlag(true);
      obj.SetGroupButtonFlag(true);
     }
  }
//+------------------------------------------------------------------+


このメソッドは、上記の改訂されたCheckedListBoxメソッドと同じです。ボタンオブジェクトを行として作成し、それらの境界線の色を設定して、背景色とブレンドします。トグルボタンフラググループで動作するボタンのフラグは、作成されたボタンごとに設定されます。各ボタンのグループインデックスは、配置されているパネルから継承されます。


以下は、新しいグラフィカルオブジェクトを作成する仮想メソッドです。

//+------------------------------------------------------------------+
//| Create a new graphical object                                    |
//+------------------------------------------------------------------+
CGCnvElement *CListBox::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                         const int obj_num,
                                         const string obj_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)
  {
   string name=this.CreateNameDependentObject(obj_name);
//--- create the Button object
   CGCnvElement *element=new CButton(this.ChartID(),this.SubWindow(),name,x,y,w,h);
   if(element==NULL)
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),": ",name);
//--- set the object relocation flag and relative coordinates
   element.SetMovable(movable);
   element.SetCoordXRelative(element.CoordX()-this.CoordX());
   element.SetCoordYRelative(element.CoordY()-this.CoordY());
   return element;
  }
//+------------------------------------------------------------------+


メソッドでボタンオブジェクトが作成され、オブジェクトの再配置フラグと相対座標などの最小限のパラメータが設定されます。

この段階では、このクラスが機能するために必要なのはこれだけです。少し後で、選択したオブジェクトを取得してメッセージを送信するために必要な機能を使用して、リストオブジェクトのクラスを拡張します。


次に、ボタンオブジェクトのリストオブジェクトクラスを作成しましょう。このようなオブジェクトでは、パネル上に作成されたボタンが結合します。ボタンはさまざまなグループに割り当てることができ、グループボタンフラグをそれらのプロパティの他のパラメータと一緒に設定できます。したがって、1つのオブジェクト(1つのパネル)に異なるグループのボタンを作成することができます。

\MQL5\Include\DoEasy\Objects\Graph\WForms\CommonControls\ライブラリフォルダで、CButtonListBoxクラスの新しいButtonListBox.mqhファイルを作成します。

クラスは基本リストオブジェクトクラスから継承する必要があり、そのファイルは作成されたクラスファイルに含める必要があります

//+------------------------------------------------------------------+
//|                                                ButtonListBox.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ElementsListBox.mqh"
//+------------------------------------------------------------------+
//| ButtonListBox object class of WForms controls                    |
//+------------------------------------------------------------------+
class CButtonListBox : public CElementsListBox
  {
  }

クラスのprivateセクションで、新しいグラフィカルオブジェクトを作成するメソッドを宣言します。publicセクションで、指定された数のボタンを作成するメソッド、パラメトリックコンストラクタ、およびpanelで作成されたボタンを処理するメソッドを宣言します。

//+------------------------------------------------------------------+
//| ButtonListBox object class of WForms controls                    |
//+------------------------------------------------------------------+
class CButtonListBox : public CElementsListBox
  {
private:
//--- Create a new graphical object
   virtual 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);
public:
//--- Create the specified number of CheckBox objects
   void              CreateButton(const int count,const int width,const int height,const int new_column_width=0);
//--- Constructor
                     CButtonListBox(const long chart_id,
                                    const int subwindow,
                                    const string name,
                                    const int x,
                                    const int y,
                                    const int w,
                                    const int h);

//--- (1) Set and (2) return the group of the button specified by index
   void              SetButtonGroup(const int index,const int group);
   int               ButtonGroup(const int index);
//--- (1) Set and (2) return the flag of the group button specified by the button index
   void              SetButtonGroupFlag(const int index,const bool flag);
   bool              ButtonGroupFlag(const int index);
//--- Sets the specified button "multiselect" mode
   void              SetMultiSelect(const bool flag);
//--- (1) Set and (2) return the "Toggle button" flag of the button specified by index
   void              SetButtonToggle(const int index,const bool flag);
   bool              ButtonToggle(const int index);
//--- Set the "Toggle button" flag for all buttons of the object
   void              SetToggle(const bool flag);
   
  };
//+------------------------------------------------------------------+


宣言されたメソッドを詳しく見てみましょう。

パラメトリックコンストラクタ、グラフィック要素の型ライブラリオブジェクトの型を指定し、パネルフレームとその色とスタイルのデフォルト値、およびパネル上のオブジェクトテキストの色を設定します。

//+------------------------------------------------------------------+
//| Constructor indicating the chart and subwindow ID                |
//+------------------------------------------------------------------+
CButtonListBox::CButtonListBox(const long chart_id,
                               const int subwindow,
                               const string name,
                               const int x,
                               const int y,
                               const int w,
                               const int h) : CElementsListBox(chart_id,subwindow,name,x,y,w,h)
  {
   CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX);
   CGCnvElement::SetProperty(CANV_ELEMENT_PROP_TYPE,GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX);
   this.m_type=OBJECT_DE_TYPE_GWF_COMMON;
   this.SetBorderSizeAll(1);
   this.SetBorderStyle(FRAME_STYLE_SIMPLE);
   this.SetBorderColor(CLR_DEF_BORDER_COLOR,true);
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
  }
//+------------------------------------------------------------------+



以下は、指定された数のButtonオブジェクトを作成するメソッドです。

//+------------------------------------------------------------------+
//| Create the specified number of Button objects                    |
//+------------------------------------------------------------------+
void CButtonListBox::CreateButton(const int count,const int width,const int height,const int new_column_width=0)
  {
//--- Create the pointer to the Button object
   CButton *obj=NULL;
//--- Create the specified number of Button objects
   CElementsListBox::CreateElements(GRAPH_ELEMENT_TYPE_WF_BUTTON,count,2,2,width,height,new_column_width);
//--- In the loop by the created number of objects
   for(int i=0;i<this.ElementsTotal();i++)
     {
      //--- Get the created object from the list by the loop index
      obj=this.GetElement(i);
      //--- If the object could not be obtained, send the appropriate message to the log and move on to the next one
      if(obj==NULL)
        {
         ::Print(DFUN,MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ,this.TypeElementDescription(GRAPH_ELEMENT_TYPE_WF_BUTTON));
         continue;
        }
      //--- Set left center text alignment
      obj.SetTextAlign(ANCHOR_CENTER);
      //--- Set the object text
      obj.SetText("Button"+string(i+1));
     }
  }
//+------------------------------------------------------------------+


このメソッドは、上記のリストオブジェクトの同様のメソッドと同じです。まず、指定された数のボタンオブジェクトが作成され、次に、作成されたオブジェクトの数によるループ内でデフォルト値に設定されます。


以下は、新しいグラフィカルオブジェクトを作成する仮想メソッドです。

//+------------------------------------------------------------------+
//| Create a new graphical object                                    |
//+------------------------------------------------------------------+
CGCnvElement *CButtonListBox::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                               const int obj_num,
                                               const string obj_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)
  {
   string name=this.CreateNameDependentObject(obj_name);
//--- create the CButton object
   CGCnvElement *element=new CButton(this.ChartID(),this.SubWindow(),name,x,y,w,h);
   if(element==NULL)
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),": ",name);
//--- set the object relocation flag and relative coordinates
   element.SetMovable(movable);
   element.SetCoordXRelative(element.CoordX()-this.CoordX());
   element.SetCoordYRelative(element.CoordY()-this.CoordY());
   return element;
  }
//+------------------------------------------------------------------+


ここではすべてがリストオブジェクトクラスの同様のメソッドとまったく同じです。


以下は、インデックスで指定されたボタンのグループを設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the group of the button specified by index                   |
//+------------------------------------------------------------------+
void CButtonListBox::SetButtonGroup(const int index,const int group)
  {
   CButton *butt=this.GetElement(index);
   if(butt==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_BUTT_LIST_ERR_FAILED_SET_GROUP_BUTTON),(string)index);
      return;
     }
   butt.SetGroup(group);
  }
//+------------------------------------------------------------------+


指定されたインデックスによってリストからオブジェクトを取得しますオブジェクトを取得できなかった場合は、ログでそれを通知し、メソッドを終了します。
取得したオブジェクトのメソッドに渡されるグループインデックスを設定します


以下は、インデックスで指定されたボタンのグループを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the group of the button specified by index                |
//+------------------------------------------------------------------+
int CButtonListBox::ButtonGroup(const int index)
  {
   CButton *butt=this.GetElement(index);
   return(butt!=NULL ? butt.Group() : WRONG_VALUE);
  }
//+------------------------------------------------------------------+


リストからインデックスでオブジェクトを取得しますオブジェクトが受信された場合はそのグループを取得しそうでない場合は-1を返します。


以下は、インデックスで指定されたグループボタンのフラグを設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the flag of the group button specified by the button index   |
//+------------------------------------------------------------------+
void CButtonListBox::SetButtonGroupFlag(const int index,const bool flag)
  {
   CButton *butt=this.GetElement(index);
   if(butt==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_BUTT_LIST_ERR_FAILED_SET_GROUP_BUTTON),(string)index);
      return;
     }
   butt.SetGroupButtonFlag(flag);
  }
//+------------------------------------------------------------------+


指定されたインデックスによってリストからオブジェクトを取得しますオブジェクトを取得できなかった場合は、ログでそれを通知し、メソッドを終了します。
取得したオブジェクトに対して、メソッドに渡されたフラグを設定します


以下は、ボタンインデックスで指定されたグループボタンのフラグを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the flag of the group button specified by the button index|
//+------------------------------------------------------------------+
bool CButtonListBox::ButtonGroupFlag(const int index)
  {
   CButton *butt=this.GetElement(index);
   return(butt!=NULL ? butt.GroupButtonFlag() : false);
  }
//+------------------------------------------------------------------+


指定されたインデックスによってリストからオブジェクトを取得しますオブジェクトが受信された場合はグループボタンフラグを返し、それ以外の場合はfalseを返します


以下は、ボタンの「複数選択」モードを設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the "multiselect" mode of the buttons                        |
//+------------------------------------------------------------------+
void CButtonListBox::SetMultiSelect(const bool flag)
  {
   int group=this.Group()+(flag ? 1 : 0);
   for(int i=0;i<this.ElementsTotal();i++)
      this.SetButtonGroup(i,group+(flag ? i : 0));
  }
//+------------------------------------------------------------------+


このメソッドでは、パネルに配置されたボタンを互いに独立して動作させることができるため、パネル上の他のボタンとは独立して、それぞれのボタンを押したり離したりできます。これをおこなうには、各ボタンに独自のグループが必要です。

最初に、最初のボタンのグループの初期値を、パネルのグループに1を加えた値(ボタンの複数選択を許可する場合)、またはボタンが相互に依存する必要がある場合は0に設定します。次に、作成されたすべてのボタンによるループで、パネルグループ番号とループインデックスとして計算された後続の各ボタンに新しいグループを設定する(これは、各ボタンがリスト内のボタン位置+1に等しいグループを持つことを意味します)、または、パネルグループ番号にゼロを追加します(これは、すべてのボタンがパネルグループと同じグループを持つことを意味します)。


以下は、インデックスで指定されたボタンの「トグルボタン」フラグを設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the "Toggle button" flag                                     |
//| button specified by index                                        |
//+------------------------------------------------------------------+
void CButtonListBox::SetButtonToggle(const int index,const bool flag)
  {
   CButton *butt=this.GetElement(index);
   if(butt==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_BUTT_LIST_ERR_FAILED_SET_TOGGLE_BUTTON),(string)index);
      return;
     }
   butt.SetToggleFlag(flag);
  }
//+------------------------------------------------------------------+


リストから指定されたインデックスでボタンを取得しますボタンを取得できなかった場合は、ログでそのことを通知し、メソッドを終了します。
メソッドで渡されたフラグは、取得したボタンに設定されます


以下は、インデックスで指定されたボタンの「トグルボタン」フラグを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the "Toggle button" flag                                  |
//| button specified by index                                        |
//+------------------------------------------------------------------+
bool CButtonListBox::ButtonToggle(const int index)
  {
   CButton *butt=this.GetElement(index);
   return(butt!=NULL ? butt.Toggle() : false);
  }
//+------------------------------------------------------------------+


リストから指定されたインデックスでボタンを取得しますボタンが受信された場合は、そのトグルボタンフラグを返します。それ以外の場合はfalseを返します


以下は、オブジェクトのすべてのボタンに「トグルボタン」フラグを設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the "Toggle button" flag to all buttons of the object        |
//+------------------------------------------------------------------+
void CButtonListBox::SetToggle(const bool flag)
  {
   for(int i=0;i<this.ElementsTotal();i++)
      this.SetButtonToggle(i,flag);
  }
//+------------------------------------------------------------------+


すべてのリストオブジェクトによるループで、上記のSetButtonToggle()メソッドを使用して、次のボタンごとに指定されたフラグを設定します

現在の記事で計画されているすべてのオブジェクトを作成しました。

次に、ライブラリがそれらについて「認識」しており、プログラムからそれらを作成できることを確認する必要があります。

基本コンテナオブジェクトの\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Container.mqhを少し改善しましょう。後で、コンテナ内に新しいオブジェクトを作成するのではなく、以前に作成したオブジェクトをコンテナに追加する必要があります。このアクションを単純化するために、新しい接続されたオブジェクトを作成するメソッドを2つに分割する必要があります。1つのメソッドは新しいオブジェクトを作成し、もう1つのメソッドはいくつかの既定のプロパティを新しいオブジェクトに設定します。オブジェクトを追加するとき、新しいオブジェクトを作成するのではなく、指定されたオブジェクトをリストに追加し、必要に応じてそのパラメータを変更します。

クラスのprotectedセクションで、新しいメソッドを宣言して、作成されたオブジェクトのパラメータを設定します。

protected:
//--- Adjust the element size to fit its content
   bool              AutoSizeProcess(const bool redraw);
//--- Set parameters for the attached object
   void              SetObjParams(CWinFormBase *obj,const color colour);
   
public:


クラス本体の外側で実装しましょう。

//+------------------------------------------------------------------+
//| Set parameters for the attached object                           |
//+------------------------------------------------------------------+
void CContainer::SetObjParams(CWinFormBase *obj,const color colour)
  {
//--- Set the text color of the object to be the same as that of the base container
   obj.SetForeColor(this.ForeColor(),true);
//--- If the created object is not a container, set the same group for it as the one for its base object
   if(obj.TypeGraphElement()<GRAPH_ELEMENT_TYPE_WF_CONTAINER || obj.TypeGraphElement()>GRAPH_ELEMENT_TYPE_WF_GROUPBOX)
      obj.SetGroup(this.Group());
//--- Depending on the object type
   switch(obj.TypeGraphElement())
     {
      //--- For the Container, Panel and GroupBox WinForms objects
      case GRAPH_ELEMENT_TYPE_WF_CONTAINER         :
      case GRAPH_ELEMENT_TYPE_WF_PANEL             :
      case GRAPH_ELEMENT_TYPE_WF_GROUPBOX          :
        //--- set the frame color equal to the background color 
        obj.SetBorderColor(obj.BackgroundColor(),true);
        break;
      //--- For "Label", "CheckBox" and "RadioButton" WinForms objects
      case GRAPH_ELEMENT_TYPE_WF_LABEL             :
      case GRAPH_ELEMENT_TYPE_WF_CHECKBOX          :
      case GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON       :
        //--- set the object text color depending on the one passed to the method:
        //--- either the container text color, or the one passed to the method.
        //--- The frame color is set equal to the text color
        //--- Set the background color to transparent
        obj.SetForeColor(colour==clrNONE ? this.ForeColor() : colour,true);
        obj.SetBorderColor(obj.ForeColor(),true);
        obj.SetBackgroundColor(CLR_CANV_NULL,true);
        obj.SetOpacity(0,false);
        break;
      //--- For the Button WinForms object
      case GRAPH_ELEMENT_TYPE_WF_BUTTON            :
        //--- set the object text color as a container text color depending on the one passed to the method:
        //--- set the background color depending on the one passed to the method:
        //--- either the default standard control background color, or the one passed to the method.
        //--- The frame color is set equal to the text color
        obj.SetForeColor(this.ForeColor(),true);
        obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_STD_BACK_COLOR : colour,true);
        obj.SetBorderColor(obj.ForeColor(),true);
        obj.SetBorderStyle(FRAME_STYLE_SIMPLE);
        break;
      //--- For "ListBox", "CheckedListBox" and "ButtonListBox" WinForms object
      case GRAPH_ELEMENT_TYPE_WF_LIST_BOX          :
      case GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX  :
      case GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX   :
        //--- set the object text color as a container text color depending on the one passed to the method:
        //--- set the background color depending on the one passed to the method:
        //--- either the default standard control background color, or the one passed to the method.
        //--- The frame color is set equal to the text color
        obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_STD_BACK_COLOR : colour,true);
        obj.SetBorderColor(CLR_DEF_BORDER_COLOR,true);
        obj.SetForeColor(CLR_DEF_FORE_COLOR,true);
        break;
      default:
        break;
     }
  }
//+------------------------------------------------------------------+


ここでは、オブジェクトパラメータを設定するコードブロックをCreateNewElement()メソッドから移動しただけです。作成されたオブジェクトへのポインタと、CreateNewElement()メソッドに渡された色をメソッドに渡します。新しいオブジェクトの処理も追加しました。これは、以前に作成したCheckedListBoxオブジェクトの処理に似ているため、余分なものを書く必要はありませんでした。これらのオブジェクトが1つの「switch」ケースでCheckedListBoxオブジェクトと同様に処理されることを示しただけです。

以下は、新しい結合された要素を作成する変更されたメソッドです。

//+------------------------------------------------------------------+
//| Create a new attached element                                    |
//+------------------------------------------------------------------+
bool CContainer::CreateNewElement(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                                  const int x,
                                  const int y,
                                  const int w,
                                  const int h,
                                  const color colour,
                                  const uchar opacity,
                                  const bool activity,
                                  const bool redraw)
  {
//--- If the object type is less than the base WinForms object
   if(element_type<GRAPH_ELEMENT_TYPE_WF_BASE)
     {
      //--- report the error and return 'false'
      CMessage::ToLog(DFUN,MSG_PANEL_OBJECT_ERR_OBJ_MUST_BE_WFBASE);
      return false;
     }
//--- If failed to create a new graphical element, return 'false'
   CWinFormBase *obj=CForm::CreateAndAddNewElement(element_type,x,y,w,h,colour,opacity,activity);
   if(obj==NULL)
      return false;
//--- Set parameters for the created object
   this.SetObjParams(obj,colour);
//--- If the panel has auto resize enabled and features bound objects, call the resize method
   if(this.AutoSize() && this.ElementsTotal()>0)
      this.AutoSizeProcess(redraw);
//--- Redraw the panel and all added objects, and return 'true'
   this.Redraw(redraw);
   return true;
  }
//+------------------------------------------------------------------+


これで、新しいメソッドに移動したコードブロックの代わりに、新しいメソッドを呼び出すことができます。コードはより短く、よりシンプルで明確になり、1つのメソッドを2つに分割して、既に作成されたオブジェクトをリストに追加できるようになりました。


\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Panel.mqhのパネルオブジェクトクラスを改善します。

今日作成された新しいオブジェクトファイルをインクルードファイルのリストに追加します。

//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "Container.mqh"
#include "GroupBox.mqh"
#include "..\..\WForms\Common Controls\ListBox.mqh"
#include "..\..\WForms\Common Controls\CheckedListBox.mqh"
#include "..\..\WForms\Common Controls\ButtonListBox.mqh"
//+------------------------------------------------------------------+



新しいグラフィカルオブジェクトを作成するメソッドに、新しいオブジェクトを作成するためのコードブロックを追加します。

//+------------------------------------------------------------------+
//| Create a new graphical object                                    |
//+------------------------------------------------------------------+
CGCnvElement *CPanel::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                       const int obj_num,
                                       const string obj_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)
  {
   string name=this.CreateNameDependentObject(obj_name);
   CGCnvElement *element=NULL;
   switch(type)
     {
      case GRAPH_ELEMENT_TYPE_ELEMENT :
         element=new CGCnvElement(type,this.ID(),obj_num,this.ChartID(),this.SubWindow(),name,x,y,w,h,colour,opacity,movable,activity);
        break;
      case GRAPH_ELEMENT_TYPE_FORM :
         element=new CForm(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_CONTAINER         :
         element=new CContainer(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_GROUPBOX          :
         element=new CGroupBox(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_PANEL             :
         element=new CPanel(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_LABEL             :
         element=new CLabel(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_CHECKBOX          :
         element=new CCheckBox(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON       :
         element=new CRadioButton(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_BUTTON            :
         element=new CButton(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_LIST_BOX          :
         element=new CCheckedListBox(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX  :
         element=new CCheckedListBox(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX   :
         element=new CButtonListBox(this.ChartID(),this.SubWindow(),name,x,y,w,h);
        break;
      default:
        break;
     }
   if(element==NULL)
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),": ",name);
   return element;
  }
//+------------------------------------------------------------------+



新しいオブジェクトの作成に関する同じ変更が、\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\GroupBox.mqhGroupBoxコンテナオブジェクトクラスの同じCreateNewGObject()メソッドに追加されました。ここではそれらについては詳しく説明しません。すべての変更は以下に添付されているファイルでご覧になれます。

グラフィック要素コレクションクラスの\MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqhButtonListBoxオブジェクトクラスファイルをインクルードします。

//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ListObj.mqh"
#include "..\Services\Select.mqh"
#include "..\Objects\Graph\WForms\Containers\GroupBox.mqh"
#include "..\Objects\Graph\WForms\Containers\Panel.mqh"
#include "..\Objects\Graph\WForms\Common Controls\CheckedListBox.mqh"
#include "..\Objects\Graph\WForms\Common Controls\ButtonListBox.mqh"
#include "..\Objects\Graph\Standard\GStdVLineObj.mqh"


その後、現在の記事で作成された他のすべてのオブジェクトが、ライブラリに基づいて作成されたプログラムで表示されるようになります。

今日予定されているオブジェクトと改善はこれですべてです。


検証

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

2番目のオブジェクトグループGroupBox2で、新しいButtonListBoxおよびListBoxリストオブジェクトを作成します。コンテナ内の最後のオブジェクトの位置座標は、CheckedListBoxおよびButtonListBoxオブジェクトの外観によって異なります。複数の列でリストを作成できることを示すフラグが有効になっている場合、ListBoxオブジェクトは最初の2つの列の下に配置されます。それ以外の場合は、右側に配置されます。

また、グループボタンの操作を確認します。別のグループでの動作の可能性と、ボタンをもう一度押したときにボタンが解放されるかどうかを確認します。

EA入力に、2つの新しいパラメータを追加します。

//--- input parameters
sinput   bool                          InpMovable           =  true;                   // Panel Movable flag
sinput   ENUM_INPUT_YES_NO             InpAutoSize          =  INPUT_YES;              // Panel Autosize
sinput   ENUM_AUTO_SIZE_MODE           InpAutoSizeMode      =  AUTO_SIZE_MODE_GROW;    // Panel Autosize mode
sinput   ENUM_BORDER_STYLE             InpFrameStyle        =  BORDER_STYLE_SIMPLE;    // Label border style
sinput   ENUM_ANCHOR_POINT             InpTextAlign         =  ANCHOR_CENTER;          // Label text align
sinput   ENUM_INPUT_YES_NO             InpTextAutoSize      =  INPUT_NO;               // Label autosize
sinput   ENUM_ANCHOR_POINT             InpCheckAlign        =  ANCHOR_LEFT;            // Check flag align
sinput   ENUM_ANCHOR_POINT             InpCheckTextAlign    =  ANCHOR_LEFT;            // Check label text align
sinput   ENUM_CHEK_STATE               InpCheckState        =  CHEK_STATE_UNCHECKED;   // Check flag state
sinput   ENUM_INPUT_YES_NO             InpCheckAutoSize     =  INPUT_YES;              // CheckBox autosize
sinput   ENUM_BORDER_STYLE             InpCheckFrameStyle   =  BORDER_STYLE_NONE;      // CheckBox border style
sinput   ENUM_ANCHOR_POINT             InpButtonTextAlign   =  ANCHOR_CENTER;          // Button text align
sinput   ENUM_INPUT_YES_NO             InpButtonAutoSize    =  INPUT_YES;              // Button autosize
sinput   ENUM_AUTO_SIZE_MODE           InpButtonAutoSizeMode=  AUTO_SIZE_MODE_GROW;    // Button Autosize mode
sinput   ENUM_BORDER_STYLE             InpButtonFrameStyle  =  BORDER_STYLE_NONE;      // Button border style
sinput   bool                          InpButtonToggle      =  false;                  // Button toggle flag
sinput   bool                          InpListBoxMColumn    =  false;                  // ListBox MultiColumn flag
sinput   bool                          InpButtListMSelect   =  false;                  // ButtonListBox Button MultiSelect flag
//--- global variables
CEngine        engine;
color          array_clr[];
//+------------------------------------------------------------------+


最初のパラメータは、複数の列で構成されるリストを作成する可能性を示します(すべてのオブジェクトがパネルの高さに収まらない場合)。2番目のパラメータは、グループ内のボタンを複数選択する可能性を設定します。

新しいオブジェクトを作成するためのコードブロックをEAのOnInit()ハンドラに追加します(コードの一部のみが示されています)。

      if(pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_GROUPBOX,x,2,w,h,C'0x91,0xAA,0xAE',0,true,false))
        {
         //--- get the pointer to the GroupBox object by its index in the list of bound GroupBox type objects
         gbox2=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_GROUPBOX,1);
         if(gbox2!=NULL)
           {
            //--- set the "indented frame" type, the frame color matches the main panel background color,
            //--- while the text color is the background color of the last attached panel darkened by 1
            gbox2.SetBorderStyle(FRAME_STYLE_STAMP);
            gbox2.SetBorderColor(pnl.BackgroundColor(),true);
            gbox2.SetForeColor(gbox2.ChangeColorLightness(obj.BackgroundColor(),-1),true);
            gbox2.SetText("GroupBox2");
            //--- Create the CheckedListBox object
            gbox2.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX,4,12,160,20,clrNONE,255,true,false);
            //--- get the pointer to the CheckedListBox object by its index in the list of bound objects of the CheckBox type
            CCheckedListBox *clbox=gbox2.GetElementByType(GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX,0);
            //--- If CheckedListBox is created and the pointer to it is received
            if(clbox!=NULL)
              {
               clbox.SetMultiColumn(InpListBoxMColumn);
               clbox.SetColumnWidth(0);
               clbox.CreateCheckBox(4,66);
              }
            //--- Create the ButtonListBox object
            gbox2.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX,4,clbox.BottomEdgeRelative()+6,160,30,clrNONE,255,true,false);
            //--- get the pointer to the ButtonListBox object by its index in the list of attached objects of the Button type
            CButtonListBox *blbox=gbox2.GetElementByType(GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX,0);
            //--- If ButtonListBox is created and the pointer to it is received
            if(blbox!=NULL)
              {
               blbox.SetMultiColumn(InpListBoxMColumn);
               blbox.SetColumnWidth(0);
               blbox.CreateButton(4,66,16);
               blbox.SetMultiSelect(InpButtListMSelect);
               blbox.SetToggle(InpButtonToggle);
               for(int i=0;i<blbox.ElementsTotal();i++)
                 {
                  blbox.SetButtonGroup(i,(i % 2==0 ? blbox.Group()+1 : blbox.Group()+2));
                  blbox.SetButtonGroupFlag(i,(i % 2==0 ? true : false));
                 }
              }
            //--- Create the ListBox object
            int lbx=4;
            int lby=blbox.BottomEdgeRelative()+6;
            int lbw=146;
            if(!InpListBoxMColumn)
              {
               lbx=blbox.RightEdgeRelative()+6;
               lby=14;
               lbw=100;
              }
            gbox2.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_LIST_BOX,lbx,lby,lbw,70,clrNONE,255,true,false);
            //--- get the pointer to the ListBox object by its index in the list of attached objects of Button type
            CListBox *lbox=gbox2.GetElementByType(GRAPH_ELEMENT_TYPE_WF_LIST_BOX,0);
            //--- If ListBox has been created and the pointer to it has been received
            if(lbox!=NULL)
              {
               lbox.CreateList(4);
              }
           }
        }
      //--- Redraw all objects according to their hierarchy
      pnl.Redraw(true);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+


ここでは、GroupBox2オブジェクトに2つの新しいリストオブジェクトを作成します。それらが正常に作成されたら、それぞれに4つのオブジェクトを作成します。

EAのOnInit()ハンドラの完全なコードは、以下に添付されたファイルにあります。


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


ここで、上の2つのButtonListBoxボタンの動作が下の2つとは少し異なることがわかります。これは、設定されているフラグによって異なります。最初の場合、もう一度押してもボタンを無効にすることはできません。1つのボタンを無効にするには、2つ目のボタンを押すことが必要です。2番目の場合、2番目のボタンをクリックするか、すでに有効になっているボタンをもう一度押すことで、ボタンを無効にすることができます。これは、グループボタンフラグの影響を受けます。このフラグが設定されている場合、ボタンはグループ内で機能するため、ボタンは互いに完全に依存しています。

リストオブジェクトは正しく動作します。ただし、外観は完璧とはほど遠いものです。MS VisualStudioでは、リストがより圧縮され、オブジェクトが互いに近くなります。ただし、オブジェクトを互いに近づけて配置すると、マウスを操作するときにオブジェクトの背景色を変更しても、常に正しく機能するとは限らないため、ここではまだそうすることができません。これを見つけて修正するとすぐに、作成されたオブジェクトの外観を調整できるようになります。


次の段階

次回の記事では、ライブラリに基づくGUIプログラムのグラフィック要素に関する作業を続けます。

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

目次に戻る

**連載のこれまでの記事:

DoEasyコントロール(第1部):最初のステップ
DoEasyコントロール(第2部):CPanelクラスでの作業
DoEasyコントロール(第3部):結合されたコントロールの作成
DoEasyコントロール(第4部):パネルコントロール、Padding、Dockパラメータ
DoEasyコントロール(第5部):WinForms基本オブジェクト、Panelコントロール、AutoSizeパラメータ
DoEasyコントロール(第6部):パネルコントロール、内部コンテンツに合わせたコンテナサイズの自動変更
DoEasy.コントロール(第7部):テキストラベルコントロール
DoEasy.コントロール(第8部):カテゴリ(GroupBoxおよびCheckBoxのコントロール)による基本WinFormsオブジェクト
DoEasy.コントロール(第9部):WinFormsオブジェクトメソッド、RadioButtonおよびButtonコントロールの再配置
DoEasy.コントロール(第10部):WinFormsオブジェクト—インターフェイスのアニメーション化
DoEasy.コントロール(第11部):WinFormsオブジェクト—グループ、CheckedListBoxWinFormsオブジェクト



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

添付されたファイル |
MQL5.zip (4405.07 KB)
ニューラルネットワークが簡単に(第21部):変分オートエンコーダ(Variational autoencoder、VAE) ニューラルネットワークが簡単に(第21部):変分オートエンコーダ(Variational autoencoder、VAE)
前回の記事で、オートエンコーダアルゴリズムについて学びました。他のアルゴリズム同様、このアルゴリズムには長所と短所があります。元の実装では、オートエンコーダは、訓練標本からオブジェクトを可能な限り分離するために使用されます。今回はその短所への対処法についてお話します。
一からの取引エキスパートアドバイザーの開発(第24部):システムの堅牢性の提供(I) 一からの取引エキスパートアドバイザーの開発(第24部):システムの堅牢性の提供(I)
この記事では、堅牢で安全な使用を保証するために、システムの信頼性を高めます。望ましい堅牢性を実現する方法の1つは、コードを可能な限り再利用して、常にさまざまな場合にテストされるようにすることです。しかし、これは方法の1つにすぎません。もう1つは、OOPを使用することです。
一からの取引エキスパートアドバイザーの開発(第25部):システムの堅牢性の提供(II) 一からの取引エキスパートアドバイザーの開発(第25部):システムの堅牢性の提供(II)
この記事では、エキスパートアドバイザー(EA)のパフォーマンスを仕上げます。長くなるのでご準備ください。EAを信頼できるものにするために、まず取引システムの一部でないコードをすべて削除します。
標準偏差による取引システムの設計方法を学ぶ 標準偏差による取引システムの設計方法を学ぶ
これは、MetaTrader 5取引プラットフォームで最も人気のあるテクニカル指標による取引システムの設計方法に関する連載の新しい記事です。この新しい記事では、標準偏差指標による取引システムの設計方法を学びます。