
DoEasy-コントロール(第12部):基本リストオブジェクト、ListBoxおよびButtonListBox WinFormsオブジェクト
内容
概念
この記事では、ライブラリ内の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.mqhのGroupBoxコンテナオブジェクトクラスの同じCreateNewGObject()メソッドに追加されました。ここではそれらについては詳しく説明しません。すべての変更は以下に添付されているファイルでご覧になれます。
グラフィック要素コレクションクラスの\MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqhにButtonListBoxオブジェクトクラスファイルをインクルードします。
//+------------------------------------------------------------------+ //| 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プログラムのグラフィック要素に関する作業を続けます。
**連載のこれまでの記事:
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





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