
DoEasy-コントロール(第21部):SplitContainerコントロール。パネルセパレータ
内容
概念
前回の記事で、SplitContainerコントロールの開発を開始しました。現時点では、ライブラリは、デフォルトのパラメータ値を持つ2つのパネルを持つ静的オブジェクトなどのコントロールを作成できます。オブジェクトには、2つのパネルとセパレータがあります。MS Visual Studioの元のオブジェクトでは、セパレータを移動して、パネルのサイズを変更できます。
セパレータ領域にマウスカーソルを合わせると、セパレータを移動できることを示す特徴的なカーソル()が表示され、マウスでキャプチャすると、移動可能なハッチング領域でセパレータが塗りつぶされ、セパレータの新しい位置が示されます。マウスボタンを放すと、パネルのサイズが変更され、新しいセパレータ位置に合わせられます。
MQL5はカーソルの外観を変更する機能を提供しないため、今のところ「グラブアンドドラッグシグナル」は作成しません。代わりに、ハッチングされた領域をセパレータ領域に重ねるだけで、移動の可能性を示します。SplitContainer MS Visual Studioでは、アクションの順序は次のとおりです。
- カーソルをセパレータ領域の上に置くと、移動できることを示すカーソルが表示されます。
- マウスボタンを(カーソルを動かさずに)押したままにすると、セパレータ領域の輪郭を示す点線の四角形が表示されます。
- マウスカーソルが移動すると、セパレータのサイズのハッチング領域が表示され、マウスボタンを離したときに設定されるセパレータの新しい位置を示すカーソルに従います。
- マウスボタンを離すと、パネルのサイズが変更され、新しいセパレータ位置に収まるようになります。
私のアルゴリズムはより簡単です。
- マウスをセパレータ領域の上に置くと、ハッチングされた領域が表示されます。
- ハッチングされた領域をマウスでキャプチャして移動すると、セパレータの新しい位置に従ってパネルの寸法がすぐに変更されます。
- マウスボタンを離してカーソルをセパレータ領域から離すと、ハッチングされた領域が非表示になり、パネルは新しいサイズのままになります。
セパレータオブジェクトは、すべてのWinFormsライブラリオブジェクトの基本オブジェクトから派生したオブジェクトとして構築されます。オブジェクトをクリアおよび再描画するための仮想メソッドがオーバーライドされるCWinFormBaseクラスから、オブジェクトの領域全体を埋める破線のフィールドを描画します。オブジェクトの可視性は、SplitContainerコントロールのイベントハンドラから管理されます。コントロール領域にマウスを合わせると、オブジェクトが表示されます。カーソルをこの領域から離すと非表示になります。このような領域には、このオブジェクトのセパレータ自体と、将来のライブラリオブジェクトでウィンドウを最小化/最大化/閉じるなど、他のオブジェクトのコントロールボタンの両方を含めることができます。
ライブラリクラスの改善
コントロール領域の座標とサイズを指定するには、グラフィック要素オブジェクトの新しい整数プロパティと、イベントとマウスの状態の新しいIDを追加します。
\MQL5\Include\DoEasy\Defines.mqhで、フォームに関連する可能なマウス状態のリストに新しいIDを追加します。
//+------------------------------------------------------------------+ //| The list of possible mouse states relative to the form | //+------------------------------------------------------------------+ enum ENUM_MOUSE_FORM_STATE { MOUSE_FORM_STATE_NONE = 0, // Undefined state //--- Outside the form MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED, // The cursor is outside the form, the mouse buttons are not clicked MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED, // The cursor is outside the form, the mouse button (any) is clicked MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL, // The cursor is outside the form, the mouse wheel is being scrolled //--- Within the form MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED, // The cursor is inside the form, no mouse buttons are clicked MOUSE_FORM_STATE_INSIDE_FORM_PRESSED, // The cursor is inside the form, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_FORM_WHEEL, // The cursor is inside the form, the mouse wheel is being scrolled //--- Within the window header area MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED, // The cursor is inside the active area, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED, // The cursor is inside the active area, any mouse button is clicked MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL, // The cursor is inside the active area, the mouse wheel is being scrolled MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED, // The cursor is inside the active area, left mouse button is released //--- Within the window scrolling area MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_NOT_PRESSED, // The cursor is within the window scrolling area, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_PRESSED, // The cursor is within the window scrolling area, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_WHEEL, // The cursor is within the window scrolling area, the mouse wheel is being scrolled //--- Within the window resizing area MOUSE_FORM_STATE_INSIDE_RESIZE_AREA_NOT_PRESSED, // The cursor is within the window resizing area, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_RESIZE_AREA_PRESSED, // The cursor is within the window resizing area, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_RESIZE_AREA_WHEEL, // The cursor is within the window resizing area, the mouse wheel is being scrolled //--- Within the window separator area MOUSE_FORM_STATE_INSIDE_SPLITTER_AREA_NOT_PRESSED, // The cursor is within the window resizing area, the mouse buttons are not clicked MOUSE_FORM_STATE_INSIDE_SPLITTER_AREA_PRESSED, // The cursor is within the window resizing area, the mouse button (any) is clicked MOUSE_FORM_STATE_INSIDE_SPLITTER_AREA_WHEEL, // The cursor is within the window separator area, the mouse wheel is being scrolled }; //+------------------------------------------------------------------+
ウィンドウのサイズ変更領域は、上下左右の領域です。その上にカーソルを合わせると、構造的にそのような可能性が提供されているグラフィック要素のサイズを変更することが可能になります。IDは、将来を見据えてここに設定されています。マウスを使用してウィンドウのサイズ変更をおこなう必要があるため、IDを今から入力することにしました。
可能なマウスイベントのリストに、フォームに関する新しいマウス状態に対応する新しいイベントIDを追加します。
//+------------------------------------------------------------------+ //| List of possible mouse events | //+------------------------------------------------------------------+ enum ENUM_MOUSE_EVENT { MOUSE_EVENT_NO_EVENT = CHART_OBJ_EVENTS_NEXT_CODE, // No event //--- MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED, // The cursor is outside the form, the mouse buttons are not clicked MOUSE_EVENT_OUTSIDE_FORM_PRESSED, // The cursor is outside the form, the mouse button (any) is clicked MOUSE_EVENT_OUTSIDE_FORM_WHEEL, // The cursor is outside the form, the mouse wheel is being scrolled //--- Within the form MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED, // The cursor is inside the form, no mouse buttons are clicked MOUSE_EVENT_INSIDE_FORM_PRESSED, // The cursor is inside the form, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_FORM_WHEEL, // The cursor is inside the form, the mouse wheel is being scrolled //--- Within the window header area MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED, // The cursor is inside the active area, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_ACTIVE_AREA_PRESSED, // The cursor is inside the active area, any mouse button is clicked MOUSE_EVENT_INSIDE_ACTIVE_AREA_WHEEL, // The cursor is inside the active area, the mouse wheel is being scrolled MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED, // The cursor is inside the active area, left mouse button is released //--- Within the window scrolling area MOUSE_EVENT_INSIDE_SCROLL_AREA_NOT_PRESSED, // The cursor is within the window scrolling area, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_SCROLL_AREA_PRESSED, // The cursor is within the window scrolling area, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_SCROLL_AREA_WHEEL, // The cursor is within the window scrolling area, the mouse wheel is being scrolled //--- Within the window resizing area MOUSE_EVENT_INSIDE_RESIZE_AREA_NOT_PRESSED, // The cursor is within the window resizing area, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_RESIZE_AREA_PRESSED, // The cursor is within the window resizing area, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_RESIZE_AREA_WHEEL, // The cursor is within the window resizing area, the mouse wheel is being scrolled //--- Within the window separator area MOUSE_EVENT_INSIDE_SPLITTER_AREA_NOT_PRESSED, // The cursor is within the window resizing area, the mouse buttons are not clicked MOUSE_EVENT_INSIDE_SPLITTER_AREA_PRESSED, // The cursor is within the window resizing area, the mouse button (any) is clicked MOUSE_EVENT_INSIDE_SPLITTER_AREA_WHEEL, // The cursor is within the window separator area, the mouse wheel is being scrolled }; #define MOUSE_EVENT_NEXT_CODE (MOUSE_EVENT_INSIDE_SPLITTER_AREA_WHEEL+1) // The code of the next event after the last mouse event code //+------------------------------------------------------------------+
新しい列挙定数がここに表示されるため、前のMOUSE_EVENT_INSIDE_SCROLL_AREA_WHEELの代わりに、最後のMOUSE_EVENT_INSIDE_SPLITTER_AREA_WHEEL列挙定数をMOUSE_EVENT_NEXT_CODEマクロ置換に追加する必要があります。
ここで実装する新しいタイプの補助オブジェクトを追加しましょう。
//+------------------------------------------------------------------+ //| 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 GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL, // Windows Forms TabControl GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER, // Windows Forms SplitContainer //--- '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 //--- Auxiliary elements of WinForms objects GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM, // Windows Forms ListBoxItem GRAPH_ELEMENT_TYPE_WF_TAB_HEADER, // Windows Forms TabHeader GRAPH_ELEMENT_TYPE_WF_TAB_FIELD, // Windows Forms TabField GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL, // Windows Forms SplitContainerPanel GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON, // Windows Forms ArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP, // Windows Forms UpArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN, // Windows Forms DownArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT, // Windows Forms LeftArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT, // Windows Forms RightArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX, // Windows Forms UpDownArrowButtonsBox GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX, // Windows Forms LeftRightArrowButtonsBox GRAPH_ELEMENT_TYPE_WF_SPLITTER, // Windows Forms Splitter }; //+------------------------------------------------------------------+
可能なWinFormsコントロールイベントのリストに新しいイベント(セパレータの再配置)を追加します。
//+------------------------------------------------------------------+ //| List of possible WinForms control events | //+------------------------------------------------------------------+ enum ENUM_WF_CONTROL_EVENT { WF_CONTROL_EVENT_NO_EVENT = GRAPH_OBJ_EVENTS_NEXT_CODE,// No event WF_CONTROL_EVENT_CLICK, // "Click on the control" event WF_CONTROL_EVENT_CLICK_CANCEL, // "Canceling the click on the control" event WF_CONTROL_EVENT_TAB_SELECT, // "TabControl tab selection" event WF_CONTROL_EVENT_CLICK_SCROLL_LEFT, // "Clicking the control left button" event WF_CONTROL_EVENT_CLICK_SCROLL_RIGHT, // "Clicking the control right button" event WF_CONTROL_EVENT_CLICK_SCROLL_UP, // "Clicking the control up button" event WF_CONTROL_EVENT_CLICK_SCROLL_DOWN, // "Clicking the control down button" event WF_CONTROL_EVENT_SPLITTER_MOVE, // "Control separator relocation" event }; #define WF_CONTROL_EVENTS_NEXT_CODE (WF_CONTROL_EVENT_SPLITTER_MOVE+1) // The code of the next event after the last graphical element event code //+------------------------------------------------------------------+
ここでは、最後のWF_CONTROL_EVENT_SPLITTER_MOVE列挙定数をWF_CONTROL_EVENTS_NEXT_CODEマクロ置換に追加する必要もあります。これは、列挙の最後の定数であるためです。
セパレータをオブジェクトに配置する方法を設定できる列挙型を記述します。
//+------------------------------------------------------------------+ //| Separator location in Split Container | //+------------------------------------------------------------------+ enum ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION { CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL, // Vertical CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL, // Horizontal }; //+------------------------------------------------------------------+ //| Integer properties of the graphical element on the canvas | //+------------------------------------------------------------------+
グラフィック要素の整数プロパティのリストに新しいプロパティを追加し、合計数を122まで増やします。
//+------------------------------------------------------------------+ //| 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_VISIBLE_AREA_WIDTH, // Visibility scope width CANV_ELEMENT_PROP_VISIBLE_AREA_HEIGHT, // Visibility scope height CANV_ELEMENT_PROP_CONTROL_AREA_X, // Control area X coordinate CANV_ELEMENT_PROP_CONTROL_AREA_Y, // Control area Y coordinate CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH, // Control area width CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT, // Control area height CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT, // Right scroll area X coordinate CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT, // Right scroll area Y coordinate CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT, // Right scroll area width CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT, // Right scroll area height CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM, // Bottom scroll area X coordinate CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM, // Bottom scroll area Y coordinate CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM, // Bottom scroll area width CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM, // Bottom scroll area height CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH, // Left edge area width CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH, // Bottom edge area width CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH, // Right edge area width CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH, // Upper edge area width CANV_ELEMENT_PROP_DISPLAYED, // Non-hidden control display flag CANV_ELEMENT_PROP_GROUP, // Group the graphical element belongs to //---... //---... CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE,// Distance from edge to separator CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH, // Separator width CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,// Separator location CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,// Flag for collapsed panel 1 CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE, // Panel 1 minimum size CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,// Flag for collapsed panel 2 CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE, // Panel 2 minimum size }; #define CANV_ELEMENT_PROP_INTEGER_TOTAL (122) // Total number of integer properties #define CANV_ELEMENT_PROP_INTEGER_SKIP (0) // Number of integer properties not used in sorting //+------------------------------------------------------------------+
グラフィック要素の可能な並び替え基準のリストに新しい基準を追加します。
//+------------------------------------------------------------------+ //| Possible sorting criteria of graphical elements on the canvas | //+------------------------------------------------------------------+ #define FIRST_CANV_ELEMENT_DBL_PROP (CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP) #define FIRST_CANV_ELEMENT_STR_PROP (CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP+CANV_ELEMENT_PROP_DOUBLE_TOTAL-CANV_ELEMENT_PROP_DOUBLE_SKIP) enum ENUM_SORT_CANV_ELEMENT_MODE { //--- Sort by 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_VISIBLE_AREA_WIDTH, // Sort by visibility scope width SORT_BY_CANV_ELEMENT_VISIBLE_AREA_HEIGHT, // Sort by visibility scope height SORT_BY_CANV_ELEMENT_CONTROL_AREA_X, // Sort by control area X coordinate SORT_BY_CANV_ELEMENT_CONTROL_AREA_Y, // Sort by control area Y coordinate SORT_BY_CANV_ELEMENT_CONTROL_AREA_WIDTH, // Sort by control area width SORT_BY_CANV_ELEMENT_CONTROL_AREA_HEIGHT, // Sort by control area height SORT_BY_CANV_ELEMENT_SCROLL_AREA_X_RIGHT, // Sort by right scroll area X coordinate SORT_BY_CANV_ELEMENT_SCROLL_AREA_Y_RIGHT, // Sort by right scroll area Y coordinate SORT_BY_CANV_ELEMENT_SCROLL_AREA_WIDTH_RIGHT, // Sort by right scroll area width SORT_BY_CANV_ELEMENT_SCROLL_AREA_HEIGHT_RIGHT, // Sort by right scroll area height SORT_BY_CANV_ELEMENT_SCROLL_AREA_X_BOTTOM, // Sort by bottom scroll area X coordinate SORT_BY_CANV_ELEMENT_SCROLL_AREA_Y_BOTTOM, // Sort by bottom scroll area Y coordinate SORT_BY_CANV_ELEMENT_SCROLL_AREA_WIDTH_BOTTOM, // Sort by bottom scroll area width SORT_BY_CANV_ELEMENT_SCROLL_AREA_HEIGHT_BOTTOM, // Sort by bottom scroll area height SORT_BY_CANV_ELEMENT_BORDER_LEFT_AREA_WIDTH, // Sort by left edge area width SORT_BY_CANV_ELEMENT_BORDER_BOTTOM_AREA_WIDTH, // Sort by bottom edge area width SORT_BY_CANV_ELEMENT_BORDER_RIGHT_AREA_WIDTH, // Sort by right edge area width SORT_BY_CANV_ELEMENT_BORDER_TOP_AREA_WIDTH, // Sort by upper edge area width SORT_BY_CANV_ELEMENT_DISPLAYED, // Sort by non-hidden control display flag SORT_BY_CANV_ELEMENT_GROUP, // Sort by a group the graphical element belongs to //---... //---... SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_SPLITTER_DISTANCE,// Sort by distance from edge to separator SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_SPLITTER_WIDTH, // Sort by separator width SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_SPLITTER_ORIENTATION,// Sort by separator location SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_PANEL1_COLLAPSED,// Sort by flag for collapsed panel 1 SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_PANEL1_MIN_SIZE, // Sort by panel 1 minimum size SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_PANEL2_COLLAPSED,// Sort by flag for collapsed panel 2 SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_PANEL2_MIN_SIZE, // Sort by panel 2 minimum size //--- 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 SORT_BY_CANV_ELEMENT_DESCRIPTION, // Sort by graphical element description }; //+------------------------------------------------------------------+
これで、これら2つの新しいプロパティでオブジェクトを選択して並べ替えることができるようになります。
\MQL5\Include\DoEasy\Data.mqhに、新しいメッセージインデックスを追加します。
MSG_LIB_TEXT_TOP, // Top MSG_LIB_TEXT_BOTTOM, // Bottom MSG_LIB_TEXT_LEFT, // Left MSG_LIB_TEXT_RIGHT, // Right MSG_LIB_TEXT_VERTICAL, // Vertically MSG_LIB_TEXT_HORISONTAL, // Horizontally
...
MSG_GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL, // SplitContainer control panel MSG_GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER, // SplitContainer control MSG_GRAPH_ELEMENT_TYPE_WF_SPLITTER, // Splitter control MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON, // ArrowButton control MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP, // UpArrowButton control
...
MSG_CANV_ELEMENT_PROP_VISIBLE_AREA_WIDTH, // Visibility scope width MSG_CANV_ELEMENT_PROP_VISIBLE_AREA_HEIGHT, // Visibility scope height MSG_CANV_ELEMENT_PROP_CONTROL_AREA_X, // Control area X coordinate MSG_CANV_ELEMENT_PROP_CONTROL_AREA_Y, // Control area Y coordinate MSG_CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH, // Control area width MSG_CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT, // Control area height MSG_CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT, // Right scroll area X coordinate MSG_CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT, // Right scroll area Y coordinate MSG_CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT, // Right scroll area width MSG_CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT, // Right scroll area height MSG_CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM, // Bottom scroll area X coordinate MSG_CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM, // Bottom scroll area Y coordinate MSG_CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM, // Bottom scroll area width MSG_CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM, // Bottom scroll area height MSG_CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH, // Left edge area width MSG_CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH, // Bottom edge area width MSG_CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH, // Right edge area width MSG_CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH, // Upper edge area width MSG_CANV_ELEMENT_PROP_DISPLAYED, // Non-hidden control display flag MSG_CANV_ELEMENT_PROP_ENABLED, // Element availability flag
...
MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE, // Distance from edge to separator MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH, // Separator width MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION, // Separator location MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED, // Flag for collapsed panel 1 MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE, // Panel 1 minimum size
また、新しく追加されたインデックスに対応するテキストも追加します。
{"Сверху","Top"}, {"Снизу","Bottom"}, {"Слева","Left"}, {"Справа","Right"}, {"Вертикально","Vertical"}, {"Горизонтально","Horisontal"},
...
{"Панель элемента управления \"SplitContainer\"","Panel of the Control element \"SplitContainer\""}, {"Элемент управления \"SplitContainer\"","Control element \"SplitContainer\""}, {"Элемент управления \"Splitter\"","Control element \"Splitter\""}, {"Элемент управления \"ArrowButton\"","Control element \"ArrowButton\""}, {"Элемент управления \"UpArrowButton\"","Control element \"UpArrowButton\""},
...
{"Ширина области видимости","Width of object visibility area"}, {"Высота области видимости","Height of object visibility area"}, {"X-координата области управления","X-coordinate of the control area"}, {"Y-координата области управления","Y-coordinate of the control area"}, {"Ширина области управления","Control area width"}, {"Высота области управления","Control area height"}, {"X-координата области прокрутки справа","X-coordinate of the right scroll area"}, {"Y-координата области прокрутки справа","Y-coordinate of the right scroll area"}, {"Ширина области прокрутки справа","Width of the right scroll area"}, {"Высота области прокрутки справа","Height of the right scroll area"}, {"X-координата области прокрутки снизу","X-coordinate of the bottom scroll area"}, {"Y-координата области прокрутки снизу","Y-coordinate of the bottom scroll area"}, {"Ширина области прокрутки снизу","Width of the bottom scroll area"}, {"Высота области прокрутки снизу","Height of the bottom scroll area"}, {"Ширина области левой грани","Width of the left border area"}, {"Ширина области нижней грани","Width of the bottom border area"}, {"Ширина области правой грани","Width of the right border area"}, {"Ширина области верхней грани","Width of the top border area"}, {"Флаг отображения не скрытого элемента управления","Flag that sets the display of a non-hidden control"}, {"Флаг доступности элемента","Element Availability Flag"},
...
{"Расстояние от края до разделителя","Distance from edge to splitter"}, {"Толщина разделителя","Splitter Width"}, {"Расположение разделителя","Splitter orientation"}, {"Флаг свёрнутости панели 1","Flag to indicate that panel 1 is collapsed"}, {"Минимальный размер панели 1","Min size of Panel 1"},
\MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqhで、グラフィック要素タイプの説明を返すメソッドに新しいオブジェクトタイプの説明の表示を追加します。
//+------------------------------------------------------------------+ //| 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) : type==GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL) : type==GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER) : //--- 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_LIST_BOX_ITEM ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM) : 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) : //--- Auxiliary control objects type==GRAPH_ELEMENT_TYPE_WF_TAB_HEADER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_HEADER) : type==GRAPH_ELEMENT_TYPE_WF_TAB_FIELD ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_FIELD) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX) : type==GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL) : type==GRAPH_ELEMENT_TYPE_WF_SPLITTER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLITTER) : "Unknown" ); } //+------------------------------------------------------------------+
このメソッドは、渡されたグラフィック要素のタイプに応じて、適切なテキストメッセージを返します。
グラフィック要素の新しいプロパティがあるため、それらをオブジェクト構造体に追加してファイルに正しく保存してファイルから読み取れるようにします。
\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqhでオブジェクト構造体に新しいプロパティを追加します。
private: int m_shift_coord_x; // Offset of the X coordinate relative to the base object int m_shift_coord_y; // Offset of the Y coordinate relative to the base object struct SData { //--- Object integer properties int id; // Element ID int type; // Graphical element type //---... //---... bool displayed; // Non-hidden control display flag int split_container_fixed_panel; // Panel that retains its size when the container is resized bool split_container_splitter_fixed; // Separator moveability flag int split_container_splitter_distance; // Distance from edge to separator int split_container_splitter_width; // Separator width int split_container_splitter_orientation; // Separator location bool split_container_panel1_collapsed; // Flag for collapsed panel 1 int split_container_panel1_min_size; // Panel 1 minimum size bool split_container_panel2_collapsed; // Flag for collapsed panel 2 int split_container_panel2_min_size; // Panel 2 minimum size int control_area_x; // Control area X coordinate int control_area_y; // Control area Y coordinate int control_area_width; // Control area width int control_area_height; // Control area height int scroll_area_x_right; // Right scroll area X coordinate int scroll_area_y_right; // Right scroll area Y coordinate int scroll_area_width_right; // Right scroll area width int scroll_area_height_right; // Right scroll area height int scroll_area_x_bottom; // Bottom scroll area X coordinate int scroll_area_y_bottom; // Bottom scroll area Y coordinate int scroll_area_width_bottom; // Bottom scroll area width int scroll_area_height_bottom; // Bottom scroll area height int border_left_area_width; // Left edge area width int border_bottom_area_width; // Bottom edge area width int border_right_area_width; // Right edge area width int border_top_area_width; // Upper edge area width //--- Object real properties //--- Object string properties uchar name_obj[64]; // Graphical element object name uchar name_res[64]; // Graphical resource name uchar text[256]; // Graphical element text uchar descript[256]; // Graphical element description }; SData m_struct_obj; // Object structure
クラスのpublicセクションで、要素のコントロール領域に相対的なカーソル位置を返すメソッドを宣言します。
//--- (1) Save the graphical resource to the array and (2) restore the resource from the array bool ResourceStamp(const string source); virtual bool Reset(void); //--- Return the cursor position relative to the (1) entire element, (2) the element active area and (3) control area bool CursorInsideElement(const int x,const int y); bool CursorInsideActiveArea(const int x,const int y); bool CursorInsideControlArea(const int x,const int y); //--- Create the element bool Create(const long chart_id, const int wnd_num, const int x, const int y, const int w, const int h, const bool redraw=false);
このメソッドは、カーソルがコントロール領域内にあることを示すフラグを返します。この領域には、さまざまなコントロールがあります(この場合はセパレータ)。
非表示要素フラグを返すメソッドに以前に省略された定数修飾子を追加します。
//--- (1) Set and (2) return the flag for displaying a non-hidden control void SetDisplayed(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_DISPLAYED,flag); } bool Displayed(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_DISPLAYED); } //--- (1) Set and (2) return the graphical element type
publicセクションで新しいオブジェクトプロパティを返すメソッドを追加します。
//--- Return the coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element active area int ActiveAreaLeft(void) const { return int(this.CoordX()+this.ActiveAreaLeftShift()); } int ActiveAreaRight(void) const { return int(this.RightEdge()-this.ActiveAreaRightShift()); } int ActiveAreaTop(void) const { return int(this.CoordY()+this.ActiveAreaTopShift()); } int ActiveAreaBottom(void) const { return int(this.BottomEdge()-this.ActiveAreaBottomShift()); } //--- Return the (1) X, (2) Y coordinates, (3) width and (4) height of the element control area height int ControlAreaX(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X); } int ControlAreaY(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y); } int ControlAreaWidth(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH); } int ControlAreaHeight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT); } //--- Return the (1) X, (2) Y coordinates, (3) width and (4) height of the element right scroll area height int ScrollAreaXRight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT); } int ScrollAreaYRight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT); } int ScrollAreaWidthRight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT); } int ScrollAreaHeightRight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT); } //--- Return the (1) X, (2) Y coordinates, (3) width and (4) height of the element bottom scroll area height int ScrollAreaXBottom(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM); } int ScrollAreaYBottom(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM); } int ScrollAreaWidthBottom(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM); } int ScrollAreaHeightBottom(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM); } //--- Return the width of the (1) left, (2) right, (3) upper and (4) lower element edge area int BorderResizeAreaLeft(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH); } int BorderResizeAreaRight(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH); } int BorderResizeAreaTop(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH); } int BorderResizeAreaBottom(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH); } //--- Return the number of colors set for the gradient filling of the (1) main background, when clicking (2), (3) when hovering the mouse over the control
クラスコンストラクタのすべての新しいオブジェクトプロパティにデフォルト値を追加します。
//+------------------------------------------------------------------+ //| Parametric constructor | //+------------------------------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id, const int element_num, const long chart_id, const int wnd_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable=true, const bool activity=true, const bool redraw=false) : m_shadow(false) { this.SetTypeElement(element_type); this.m_type=OBJECT_DE_TYPE_GELEMENT; this.m_element_main=NULL; this.m_element_base=NULL; this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND); this.m_name=this.CreateNameGraphElement(element_type); this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id); this.m_subwindow=wnd_num; this.SetFont(DEF_FONT,DEF_FONT_SIZE); this.m_text_anchor=0; this.m_text_x=0; this.m_text_y=0; this.SetBackgroundColor(colour,true); this.SetOpacity(opacity); this.m_shift_coord_x=0; this.m_shift_coord_y=0; if(::ArrayResize(this.m_array_colors_bg,1)==1) this.m_array_colors_bg[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_dwn,1)==1) this.m_array_colors_bg_dwn[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_ovr,1)==1) this.m_array_colors_bg_ovr[0]=this.BackgroundColor(); if(this.Create(chart_id,wnd_num,x,y,w,h,redraw)) { this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,this.m_canvas.ResourceName()); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_CHART_ID,CGBaseObj::ChartID()); // Chart ID this.SetProperty(CANV_ELEMENT_PROP_WND_NUM,CGBaseObj::SubWindow()); // Chart subwindow index //---... //---... this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,CGBaseObj::Name()); // Element object name this.SetProperty(CANV_ELEMENT_PROP_TYPE,element_type); // Graphical element type this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_HEIGHT,h); // Visibility scope height this.SetProperty(CANV_ELEMENT_PROP_DISPLAYED,true); // Non-hidden control display flag this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,0); // Control area X coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,0); // Control area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,0); // Control area width this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,0); // Control area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT,0); // Right scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT,0); // Right scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT,0); // Right scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT,0); // Right scroll area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM,0); // Bottom scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM,0); // Bottom scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM,0); // Bottom scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM,0); // Bottom scroll area height this.SetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH,0); // Left edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH,0); // Bottom edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,0); // Right edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,0); // Top edge area width //--- this.SetProperty(CANV_ELEMENT_PROP_BELONG,ENUM_GRAPH_OBJ_BELONG::GRAPH_OBJ_BELONG_PROGRAM); // Graphical element affiliation this.SetProperty(CANV_ELEMENT_PROP_ZORDER,0); // Priority of a graphical object for receiving the event of clicking on a chart this.SetProperty(CANV_ELEMENT_PROP_BOLD_TYPE,FW_NORMAL); // Font width type //---... //---... this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE,50); // Distance from edge to separator this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH,4); // Separator width this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,0); // Separator location this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,false); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE,25); // Panel 1 minimum size this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,false); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE,25); // Panel 2 minimum size this.SetVisibleFlag(false,false); } else { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj()); } } //+------------------------------------------------------------------+ //| Protected constructor | //+------------------------------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const long chart_id, const int wnd_num, const string descript, const int x, const int y, const int w, const int h) : m_shadow(false) { this.m_type=OBJECT_DE_TYPE_GELEMENT; this.m_element_main=NULL; this.m_element_base=NULL; this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND); this.m_name=this.CreateNameGraphElement(element_type); this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id); this.m_subwindow=wnd_num; this.m_type_element=element_type; this.SetFont(DEF_FONT,DEF_FONT_SIZE); this.m_text_anchor=0; this.m_text_x=0; this.m_text_y=0; this.SetBackgroundColor(CLR_CANV_NULL,true); this.SetOpacity(0); this.m_shift_coord_x=0; this.m_shift_coord_y=0; if(::ArrayResize(this.m_array_colors_bg,1)==1) this.m_array_colors_bg[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_dwn,1)==1) this.m_array_colors_bg_dwn[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_ovr,1)==1) this.m_array_colors_bg_ovr[0]=this.BackgroundColor(); if(this.Create(chart_id,wnd_num,x,y,w,h,false)) { this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,this.m_canvas.ResourceName()); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_CHART_ID,CGBaseObj::ChartID()); // Chart ID this.SetProperty(CANV_ELEMENT_PROP_WND_NUM,CGBaseObj::SubWindow()); // Chart subwindow index //---... //---... this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,CGBaseObj::Name()); // Element object name this.SetProperty(CANV_ELEMENT_PROP_TYPE,element_type); // Graphical element type this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_HEIGHT,h); // Visibility scope height this.SetProperty(CANV_ELEMENT_PROP_DISPLAYED,true); // Non-hidden control display flag this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,0); // Control area X coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,0); // Control area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,0); // Control area width this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,0); // Control area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT,0); // Right scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT,0); // Right scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT,0); // Right scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT,0); // Right scroll area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM,0); // Bottom scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM,0); // Bottom scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM,0); // Bottom scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM,0); // Bottom scroll area height this.SetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH,0); // Left edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH,0); // Bottom edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,0); // Right edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,0); // Top edge area width //--- this.SetProperty(CANV_ELEMENT_PROP_BELONG,ENUM_GRAPH_OBJ_BELONG::GRAPH_OBJ_BELONG_PROGRAM); // Graphical element affiliation this.SetProperty(CANV_ELEMENT_PROP_ZORDER,0); // Priority of a graphical object for receiving the event of clicking on a chart this.SetProperty(CANV_ELEMENT_PROP_BOLD_TYPE,FW_NORMAL); // Font width type //---... //---... this.SetProperty(CANV_ELEMENT_PROP_BORDER_STYLE,FRAME_STYLE_NONE); // Control frame style this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_TOP,0); // Control frame top size this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE,50); // Distance from edge to separator this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH,4); // Separator width this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,0); // Separator location this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,false); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE,25); // Panel 1 minimum size this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,false); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE,25); // Panel 2 minimum size this.SetVisibleFlag(false,false); } else { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj()); } } //+------------------------------------------------------------------+
デフォルトでは、すべてのプロパティがゼロに設定されています。Separator Orientationプロパティの場合、0はセパレータの垂直位置を意味します。
オブジェクトの構造体を作成するメソッドで新しい要素のプロパティの値を構造体フィールドに設定します。
//+------------------------------------------------------------------+ //| Create the object structure | //+------------------------------------------------------------------+ bool CGCnvElement::ObjectToStruct(void) { //--- Save integer properties this.m_struct_obj.id=(int)this.GetProperty(CANV_ELEMENT_PROP_ID); // Element ID this.m_struct_obj.type=(int)this.GetProperty(CANV_ELEMENT_PROP_TYPE); // Graphical element type this.m_struct_obj.belong=(int)this.GetProperty(CANV_ELEMENT_PROP_BELONG); // Graphical element affiliation this.m_struct_obj.number=(int)this.GetProperty(CANV_ELEMENT_PROP_NUM); // Element ID in the list //---... //---... this.m_struct_obj.split_container_splitter_distance=(int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE); // Distance from edge to separator this.m_struct_obj.split_container_splitter_width=(int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH); // Separator width this.m_struct_obj.split_container_splitter_orientation=(int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION); // Separator location this.m_struct_obj.split_container_panel1_collapsed=(bool)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED); // Flag for collapsed panel 1 this.m_struct_obj.split_container_panel1_min_size=(int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE); // Panel 1 minimum size this.m_struct_obj.split_container_panel2_collapsed=(bool)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED); // Flag for collapsed panel 1 this.m_struct_obj.split_container_panel2_min_size=(int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE); // Panel 2 minimum size this.m_struct_obj.control_area_x=(int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X); // Control area X coordinate this.m_struct_obj.control_area_y=(int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y); // Control area Y coordinate this.m_struct_obj.control_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH); // Control area width this.m_struct_obj.control_area_height=(int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT); // Control area height this.m_struct_obj.scroll_area_x_right=(int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT); // Right scroll area X coordinate this.m_struct_obj.scroll_area_y_right=(int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT); // Right scroll area Y coordinate this.m_struct_obj.scroll_area_width_right=(int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT); // Right scroll area width this.m_struct_obj.scroll_area_height_right=(int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT); // Right scroll area height this.m_struct_obj.scroll_area_x_bottom=(int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM); // Bottom scroll area X coordinate this.m_struct_obj.scroll_area_y_bottom=(int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM); // Bottom scroll area Y coordinate this.m_struct_obj.scroll_area_width_bottom=(int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM); // Bottom scroll area width this.m_struct_obj.scroll_area_height_bottom=(int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM);// Bottom scroll area height this.m_struct_obj.border_left_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH); // Left edge area width this.m_struct_obj.border_bottom_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH); // Bottom edge area width this.m_struct_obj.border_right_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH); // Right edge area width this.m_struct_obj.border_top_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH); // Top edge area width //--- Save real properties //--- Save string properties ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_NAME_OBJ),this.m_struct_obj.name_obj); // Graphical element object name ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_NAME_RES),this.m_struct_obj.name_res); // Graphical resource name ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TEXT),this.m_struct_obj.text); // Graphical element text ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_DESCRIPTION),this.m_struct_obj.descript);// Graphical element description //--- Save the structure to the uchar array ::ResetLastError(); if(!::StructToCharArray(this.m_struct_obj,this.m_uchar_array)) { CMessage::ToLog(DFUN,MSG_LIB_SYS_FAILED_SAVE_OBJ_STRUCT_TO_UARRAY,true); return false; } return true; } //+------------------------------------------------------------------+
構造体からオブジェクトを作成するメソッドで、適切な構造体フィールドの値をオブジェクトプロパティに設定します。
//+------------------------------------------------------------------+ //| Create the object from the structure | //+------------------------------------------------------------------+ void CGCnvElement::StructToObject(void) { //--- Save integer properties this.SetProperty(CANV_ELEMENT_PROP_ID,this.m_struct_obj.id); // Element ID this.SetProperty(CANV_ELEMENT_PROP_TYPE,this.m_struct_obj.type); // Graphical element type this.SetProperty(CANV_ELEMENT_PROP_BELONG,this.m_struct_obj.belong); // Graphical element affiliation this.SetProperty(CANV_ELEMENT_PROP_NUM,this.m_struct_obj.number); // Element index in the list //---... //---... this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE,this.m_struct_obj.split_container_splitter_distance); // Distance from edge to separator this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH,this.m_struct_obj.split_container_splitter_width); // Separator width this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,this.m_struct_obj.split_container_splitter_orientation); // Separator location this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,this.m_struct_obj.split_container_panel1_collapsed); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE,this.m_struct_obj.split_container_panel1_min_size); // Panel 1 minimum size this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,this.m_struct_obj.split_container_panel2_collapsed); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE,this.m_struct_obj.split_container_panel2_min_size); // Panel 2 minimum size this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,this.m_struct_obj.control_area_x); // Control area X coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,this.m_struct_obj.control_area_y); // Control area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,this.m_struct_obj.control_area_width); // Control area width this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,this.m_struct_obj.control_area_height); // Control area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT,this.m_struct_obj.scroll_area_x_right); // Right scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT,this.m_struct_obj.scroll_area_y_right); // Right scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT,this.m_struct_obj.scroll_area_width_right); // Right scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT,this.m_struct_obj.scroll_area_height_right); // Right scroll area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM,this.m_struct_obj.scroll_area_x_bottom); // Bottom scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM,this.m_struct_obj.scroll_area_y_bottom); // Bottom scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM,this.m_struct_obj.scroll_area_width_bottom); // Bottom scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM,this.m_struct_obj.scroll_area_height_bottom); // Bottom scroll area height this.SetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH,this.m_struct_obj.border_left_area_width); // Left edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH,this.m_struct_obj.border_bottom_area_width); // Bottom edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,this.m_struct_obj.border_right_area_width); // Right edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,this.m_struct_obj.border_top_area_width); // Top edge area width //--- Save real properties //--- Save string properties this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,::CharArrayToString(this.m_struct_obj.name_obj)); // Graphical element object name this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,::CharArrayToString(this.m_struct_obj.name_res)); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_TEXT,::CharArrayToString(this.m_struct_obj.text)); // Graphical element text this.SetProperty(CANV_ELEMENT_PROP_DESCRIPTION,::CharArrayToString(this.m_struct_obj.descript));// Graphical element description } //+------------------------------------------------------------------+
クラス本体を超えて、要素コントロール領域に相対的なカーソル位置を返すメソッドの実装を記述します。
//+------------------------------------------------------------------+ //|Return the cursor position relative to the element control area | //+------------------------------------------------------------------+ bool CGCnvElement::CursorInsideControlArea(const int x,const int y) { return(x>=this.ControlAreaX() && x<=this.ControlAreaX()+this.ControlAreaWidth() && y>=this.ControlAreaY() && y<=this.ControlAreaY()+this.ControlAreaHeight()); } //+------------------------------------------------------------------+
カーソル座標はメソッドに渡され、カーソルのX座標とY座標の値を検出するフラグは、オブジェクトに設定されたコントロール領域の範囲内にあります。
\MQL5\Include\DoEasy\Objects\Graph\Form.mqhフォームオブジェクトクラスファイルにあるフォームを表示するメソッドで、接続オブジェクトの確認を追加して、表示フラグがオブジェクトに設定されていることを確認します。
//+------------------------------------------------------------------+ //| Show the form | //+------------------------------------------------------------------+ void CForm::Show(void) { //--- If the element should not be displayed (hidden inside another control), leave if(!this.Displayed()) return; //--- If the object has a shadow, display it if(this.m_shadow_obj!=NULL) this.m_shadow_obj.Show(); //--- Display the main form CGCnvElement::Show(); //--- In the loop by all bound graphical objects, for(int i=0;i<this.m_list_elements.Total();i++) { //--- get the next graphical element CGCnvElement *element=this.m_list_elements.At(i); if(element==NULL || !element.Displayed()) continue; //--- and display it element.Show(); } //--- Update the form CGCnvElement::Update(); } //+------------------------------------------------------------------+
フォームに関連するマウスステータスを設定して返すメソッドで、コントロール領域内のカーソルの位置を担当するm_mouse_state_flags変数のビットを埋めるコードブロックを追加します。
//+------------------------------------------------------------------+ //| Set and get the mouse status relative to the form | //+------------------------------------------------------------------+ ENUM_MOUSE_FORM_STATE CForm::MouseFormState(const int id,const long lparam,const double dparam,const string sparam) { //--- Get the mouse status relative to the form, as well as the states of mouse buttons and Shift/Ctrl keys this.m_mouse_form_state=MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED; ENUM_MOUSE_BUTT_KEY_STATE state=this.m_mouse.ButtonKeyState(id,lparam,dparam,sparam); //--- Get the mouse status flags from the CMouseState class object and save them in the variable this.m_mouse_state_flags=this.m_mouse.GetMouseFlags(); //--- If the cursor is inside the form if(CGCnvElement::CursorInsideElement(this.m_mouse.CoordX(),this.m_mouse.CoordY())) { //--- Set bit 8 responsible for the "cursor inside the form" flag this.m_mouse_state_flags |= (0x0001<<8); //--- If the cursor is inside the active area, set bit 9 "cursor inside the active area" if(CGCnvElement::CursorInsideActiveArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<9); //--- otherwise, release the bit "cursor inside the active area" else this.m_mouse_state_flags &=0xFDFF; //--- If the cursor is inside the control area, set bit 10 "cursor inside the control area", if(CGCnvElement::CursorInsideControlArea(this.m_mouse.CoordX(),this.m_mouse.CoordY())) this.m_mouse_state_flags |= (0x0001<<10); //--- otherwise, remove the "cursor inside the control area" bit else this.m_mouse_state_flags &=0xFBFF; //--- If one of the mouse buttons is clicked, check the cursor location in the active area and //--- return the appropriate value of the pressed key (in the active area or the form area) if((this.m_mouse_state_flags & 0x0001)!=0 || (this.m_mouse_state_flags & 0x0002)!=0 || (this.m_mouse_state_flags & 0x0010)!=0) this.m_mouse_form_state=((this.m_mouse_state_flags & 0x0200)!=0 ? MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED : MOUSE_FORM_STATE_INSIDE_FORM_PRESSED); //--- otherwise, if not a single mouse button is pressed else { //--- if the mouse wheel is scrolled, return the appropriate wheel scrolling value (in the active area or the form area) if((this.m_mouse_state_flags & 0x0080)!=0) this.m_mouse_form_state=((this.m_mouse_state_flags & 0x0200)!=0 ? MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL : MOUSE_FORM_STATE_INSIDE_FORM_WHEEL); //--- otherwise, return the appropriate value of the unpressed key (in the active area or the form area) else this.m_mouse_form_state=((this.m_mouse_state_flags & 0x0200)!=0 ? MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED : MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED); } } //--- If the cursor is outside the form else { //--- return the appropriate button value in an inactive area this.m_mouse_form_state= ( ((this.m_mouse_state_flags & 0x0001)!=0 || (this.m_mouse_state_flags & 0x0002)!=0 || (this.m_mouse_state_flags & 0x0010)!=0) ? MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED ); } return this.m_mouse_form_state; } //+------------------------------------------------------------------+
CursorInsideControlArea()メソッドがtrueを返す場合、カーソルがフォームコントロール領域内にあることが意味されます。この場合、それを示すビット10(1に設定)を設定する必要があります。カーソルが制御域の外にある場合は、ビット10が除去されます(ゼロに設定)。
すべてのswitch演算子のcaseを1つの文字列に記述して、マウスイベントハンドラを短縮します。
//+------------------------------------------------------------------+ //| Mouse event handler | //+------------------------------------------------------------------+ void CForm::OnMouseEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { switch(id) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_EVENT_OUTSIDE_FORM_PRESSED : case MOUSE_EVENT_OUTSIDE_FORM_WHEEL : break; //--- The cursor is inside the form, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED : this.MouseInsideNotPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the form, any mouse button is clicked case MOUSE_EVENT_INSIDE_FORM_PRESSED : this.MouseInsidePressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the form, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_FORM_WHEEL : this.MouseInsideWhellHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED : this.MouseActiveAreaNotPressedHandler(id,lparam,dparam,sparam);break; //--- The cursor is inside the active area, any mouse button is clicked case MOUSE_EVENT_INSIDE_ACTIVE_AREA_PRESSED : this.MouseActiveAreaPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_ACTIVE_AREA_WHEEL : this.MouseActiveAreaWhellHandler(id,lparam,dparam,sparam); break; //--- The cursor is inside the active area, left mouse button is released case MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED : this.MouseActiveAreaReleasedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area, the mouse buttons are not clicked case MOUSE_EVENT_INSIDE_SCROLL_AREA_NOT_PRESSED : this.MouseScrollAreaNotPressedHandler(id,lparam,dparam,sparam);break; //--- The cursor is within the window scrolling area, any mouse button is clicked case MOUSE_EVENT_INSIDE_SCROLL_AREA_PRESSED : this.MouseScrollAreaPressedHandler(id,lparam,dparam,sparam); break; //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled case MOUSE_EVENT_INSIDE_SCROLL_AREA_WHEEL : this.MouseScrollAreaWhellHandler(id,lparam,dparam,sparam); break; //--- MOUSE_EVENT_NO_EVENT default: break; } this.m_mouse_event_last=(ENUM_MOUSE_EVENT)id; } //+------------------------------------------------------------------+
したがって、メソッドはより読みやすくなります。
最後のマウスイベントハンドラに、新しい「前の」状態を処理するための空白を追加します。
//+------------------------------------------------------------------+ //| Last mouse event handler | //+------------------------------------------------------------------+ void CForm::OnMouseEventPostProcessing(void) { if(!this.IsVisible() || !this.Enabled()) return; ENUM_MOUSE_FORM_STATE state=this.GetMouseState(); switch(state) { //--- The cursor is outside the form, the mouse buttons are not clicked //--- The cursor is outside the form, any mouse button is clicked //--- The cursor is outside the form, the mouse wheel is being scrolled case MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL : case MOUSE_FORM_STATE_NONE : if(this.MouseEventLast()==MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED || this.MouseEventLast()==MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED || this.MouseEventLast()==MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED || this.MouseEventLast()==MOUSE_EVENT_NO_EVENT) { this.SetBackgroundColor(this.BackgroundColorInit(),false); this.SetBorderColor(this.BorderColorInit(),false); this.m_mouse_event_last=ENUM_MOUSE_EVENT(state+MOUSE_EVENT_NO_EVENT); } break; //--- The cursor is inside the form, the mouse buttons are not clicked //--- The cursor is inside the form, any mouse button is clicked //--- The cursor is inside the form, the mouse wheel is being scrolled //--- The cursor is inside the active area, the mouse buttons are not clicked //--- The cursor is inside the active area, any mouse button is clicked //--- The cursor is inside the active area, the mouse wheel is being scrolled //--- The cursor is inside the active area, left mouse button is released //--- The cursor is within the window scrolling area, the mouse buttons are not clicked //--- The cursor is within the window scrolling area, any mouse button is clicked //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled //--- The cursor is within the window resizing area, the mouse buttons are not clicked //--- The cursor is within the window resizing area, the mouse button (any) is clicked //--- The cursor is within the window resizing area, the mouse wheel is being scrolled //--- The cursor is within the window resizing area, the mouse buttons are not clicked //--- The cursor is within the window resizing area, the mouse button (any) is clicked //--- The cursor is within the window separator area, the mouse wheel is being scrolled case MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_FORM_PRESSED : case MOUSE_FORM_STATE_INSIDE_FORM_WHEEL : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL : case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_WHEEL : case MOUSE_FORM_STATE_INSIDE_RESIZE_AREA_NOT_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_RESIZE_AREA_WHEEL : case MOUSE_FORM_STATE_INSIDE_SPLITTER_AREA_NOT_PRESSED: case MOUSE_FORM_STATE_INSIDE_SPLITTER_AREA_PRESSED : case MOUSE_FORM_STATE_INSIDE_SPLITTER_AREA_WHEEL : break; //--- MOUSE_EVENT_NO_EVENT default: break; } } //+------------------------------------------------------------------+
将来、オブジェクトに関連する最後のイベントであるこれらのイベントを処理する必要がある可能性があるため、これらのイベントハンドラの空白をここに追加しました。現時点では、それらはまったく処理されません。
\MQL5\Include\DoEasy\Objects\Graph\WForms\WinFormBase.mqh基本WinFormsオブジェクトクラスファイルにある、オブジェクトを再描画するメソッドで、オブジェクト表示フラグの確認を追加します。オブジェクトが表示されない場合は、再描画する必要もありません。
//+------------------------------------------------------------------+ //| Redraw the object | //+------------------------------------------------------------------+ void CWinFormBase::Redraw(bool redraw) { //--- If the object type is less than the "Base WinForms object", exit if(this.TypeGraphElement()<GRAPH_ELEMENT_TYPE_WF_BASE || !this.Displayed()) return; //--- Get the "Shadow" object CShadowObj *shadow=this.GetShadowObj(); //--- If the object has a shadow and the "Shadow" object exists, redraw it if(this.IsShadow() && shadow!=NULL) { //--- remove the previously drawn shadow, shadow.Erase(); //--- save the relative shadow coordinates, int x=shadow.CoordXRelative(); int y=shadow.CoordYRelative(); //--- redraw the shadow, if(redraw) shadow.Draw(0,0,shadow.Blur(),redraw); //--- restore relative shadow coordinates shadow.SetCoordXRelative(x); shadow.SetCoordYRelative(y); } //--- If the redraw flag is set, if(redraw) { //--- completely redraw the object and save its new initial look this.Erase(this.m_array_colors_bg,this.Opacity(),this.m_gradient_v,this.m_gradient_c,redraw); this.Done(); } //--- otherwise, remove the object else this.Erase(); //--- Redraw all bound objects with the redraw flag for(int i=0;i<this.ElementsTotal();i++) { CWinFormBase *element=this.GetElement(i); if(element==NULL) continue; if(redraw) element.Redraw(redraw); } //--- If the redraw flag is set and if this is the main object the rest are bound to, //--- redraw the chart to display changes immediately if(redraw && this.GetMain()==NULL) ::ChartRedraw(this.ChartID()); } //+------------------------------------------------------------------+
要素の整数プロパティの説明を返すメソッドに、新しいグラフィック要素のプロパティの説明を返すコードブロックを追加します。
//+------------------------------------------------------------------+ //| Return the description of the control integer property | //+------------------------------------------------------------------+ string CWinFormBase::GetPropertyDescription(ENUM_CANV_ELEMENT_PROP_INTEGER property,bool only_prop=false) { return ( property==CANV_ELEMENT_PROP_ID ? CMessage::Text(MSG_CANV_ELEMENT_PROP_ID)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TYPE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TYPE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+this.TypeElementDescription() ) : //---... //---... property==CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_CONTROL_AREA_X ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CONTROL_AREA_X)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_CONTROL_AREA_Y ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CONTROL_AREA_Y)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT ? CMessage::Text(MSG_CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH ? CMessage::Text(MSG_CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : "" ); } //+------------------------------------------------------------------+
メソッドに渡されたプロパティに応じて、説明文字列が作成されて返されます。プロパティがオブジェクトでサポートされていない場合、プロパティの値の代わりに、プロパティがサポートされていないことを示すエントリが表示されます。only_propフラグに応じて、プロパティ名のみを表示するか、割り当てられた値と一緒に表示します。
これで、新しいライブラリオブジェクトの作成を開始できます。
補助セパレータオブジェクトクラス
補助ライブラリオブジェクトは完全なコントロールではありませんが、そのようなオブジェクトを構築するために使用されます。SplitContainerコントロールで2つのパネルを分離する領域を移動できることを示すために、セパレータオブジェクトが必要です。このオブジェクトをマウスで移動すると、SplitContainerコントロールのイベントハンドラが呼び出され、そこでこのイベントが処理され、パネルのサイズが変更されます。同時に、他のコントロールと対話するためにそのようなオブジェクトが必要になる場合があるため、補助オブジェクトフォルダに配置され、必要なコントロールで使用されます。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\で、CSplitterクラスの新しいSplitter.mqhファイルを作成します。
このクラスは、ライブラリのすべてのWinFormsオブジェクトの基本クラスから継承する必要があり、そのファイルは作成されたクラスにインクルードされる必要があります。
//+------------------------------------------------------------------+ //| Splitter.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "..\WinFormBase.mqh" //+------------------------------------------------------------------+ //| Splitter object class of the WForms controls | //+------------------------------------------------------------------+ class CSplitter : public CWinFormBase { }
クラスのprotectedセクションでは、グリッド(オブジェクトのハッチング)を描画する仮想メソッドとprotectedコンストラクタを宣言します。クラスのpublicセクションで、グラフィック要素の背景を再描画およびクリアするためのパラメトリックコンストラクタとメソッドを宣言します。
//+------------------------------------------------------------------+ //| Splitter object class of the WForms controls | //+------------------------------------------------------------------+ class CSplitter : public CWinFormBase { private: protected: //--- Draw the grid virtual void DrawGrid(void); //--- Protected constructor with object type, chart ID and subwindow CSplitter(const ENUM_GRAPH_ELEMENT_TYPE type, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); public: //--- Constructor CSplitter(const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); //--- Redraw the object virtual void Redraw(bool redraw); //--- Clear the element filling it with color and opacity virtual void Erase(const color colour,const uchar opacity,const bool redraw=false); //--- Clear the element with a gradient fill virtual void Erase(color &colors[],const uchar opacity,const bool vgradient,const bool cycle,const bool redraw=false); }; //+------------------------------------------------------------------+
別のレンダリングで派生クラスを作成する必要がある場合に備えて、オブジェクトのグリッドを描画するメソッドはvirtualとして宣言されます。
宣言されたメソッドを詳しく見てみましょう。
以下は、protectedクラスコンストラクタです。
//+------------------------------------------------------------------+ //| Protected constructor with an object type, | //| chart ID and subwindow | //+------------------------------------------------------------------+ CSplitter::CSplitter(const ENUM_GRAPH_ELEMENT_TYPE type, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CWinFormBase(type,chart_id,subwindow,descript,x,y,w,h) { //--- Set the specified graphical element type for the object and assign the library object type to the current object this.SetTypeElement(type); this.m_type=OBJECT_DE_TYPE_GWF_HELPER; this.SetPaddingAll(0); this.SetMarginAll(0); this.SetBorderSizeAll(0); } //+------------------------------------------------------------------+
コンストラクタの仮パラメータで、作成されたオブジェクトの型を渡します。これは、初期化文字列で親クラスのコンストラクタに渡されます。コンストラクタに渡される型はクラス本体で設定され、ライブラリのグラフィカルオブジェクトの型は補助オブジェクトとして設定されます。パディングとマージンの値、およびフレームサイズはゼロに設定されます。
以下は、パラメトリックコンストラクタです。
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSplitter::CSplitter(const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h) : CWinFormBase(GRAPH_ELEMENT_TYPE_WF_SPLITTER,chart_id,subwindow,descript,x,y,w,h) { this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_SPLITTER); this.m_type=OBJECT_DE_TYPE_GWF_HELPER; this.SetPaddingAll(0); this.SetMarginAll(0); this.SetBorderSizeAll(0); this.SetDisplayed(false); } //+------------------------------------------------------------------+
ここではすべてがprotectedコンストラクタに似ていますが、グラフィック要素の型は直接設定され、仮パラメータには渡されません。
以下は、オブジェクトを再描画するメソッドです。
//+------------------------------------------------------------------+ //| Redraw the object | //+------------------------------------------------------------------+ void CSplitter::Redraw(bool redraw) { //--- If the element should not be displayed (hidden inside another control), leave if(!this.Displayed()) return; //--- Fill the object with background color having transparency this.Erase(this.BackgroundColor(),this.Opacity(),true); } //+------------------------------------------------------------------+
可視でアクセス可能なコントロールにオブジェクトを表示するフラグが無効になっている場合、オブジェクトを再描画する必要はありません。メソッドを終了するだけです。表示フラグが設定されている場合は、オブジェクトを色で塗りつぶすメソッドを呼び出します。
以下は、色と不透明度で要素をクリアする仮想メソッドです。
//+------------------------------------------------------------------+ //| Clear the element filling it with color and opacity | //+------------------------------------------------------------------+ void CSplitter::Erase(const color colour,const uchar opacity,const bool redraw=false) { //--- If the element should not be displayed (hidden inside another control), leave if(!this.Displayed()) return; //--- Fill the element having the specified color and the redrawing flag CGCnvElement::EraseNoCrop(colour,opacity,false); //--- Draw the grid this.DrawGrid(); //--- Crop and update the element with the specified redraw flag this.Crop(); this.Update(redraw); } //+------------------------------------------------------------------+ //| Clear the element with a gradient fill | //+------------------------------------------------------------------+ void CSplitter::Erase(color &colors[],const uchar opacity,const bool vgradient,const bool cycle,const bool redraw=false) { //--- If the element should not be displayed (hidden inside another control), leave if(!this.Displayed()) return; //--- Fill the element having the specified color array and the redrawing flag CGCnvElement::EraseNoCrop(colors,opacity,vgradient,cycle,false); //--- Draw the grid this.DrawGrid(); //--- Crop and update the element with the specified redraw flag this.Crop(); this.Update(redraw); } //+------------------------------------------------------------------+
メソッドのロジックは、コード内で完全にコメントされています。最初のメソッドは背景を単色で塗りつぶし、2番目のメソッドはグラデーションで塗りつぶします。
以下は、フレームを描画するメソッドです。
//+------------------------------------------------------------------+ //| Draw the grid | //+------------------------------------------------------------------+ void CSplitter::DrawGrid(void) { for(int y=0;y<this.Height()-1;y++) for(int x=0;x<this.Width();x++) this.SetPixel(x,y,this.ForeColor(),uchar(y%2==0 ? (x%2==0 ? 255 : 0) : (x%2==0 ? 0 : 255))); } //+------------------------------------------------------------------+
オブジェクトの背景を市松模様のドットで塗りつぶす必要があります。これをおこなうには、行を通るループと列を通るループの2つのループを配置します。
- 文字列が偶数の場合:
- 列が偶数の場合は、完全に不透明なドットを設定し、
- 列が奇数の場合は、完全に透明なドットを設定します。
- 文字列が奇数の場合:
- 列が偶数の場合は、完全に透明なドットを設定し、
- 列が奇数の場合は、完全に不透明なドットを設定します。
したがって、背景全体を市松模様に配置されたドットで塗りつぶします。
この段階でセパレータオブジェクトクラスが機能するために必要なのは、これだけです。
これをSplitContainerコントロールクラスにインクルードして、作成および管理する必要があります。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\SplitContainer.mqhにあるクラスのprivateセクションで、パネルとセパレータの座標とサイズを格納する変数を宣言し、パネルパラメータを設定するメソッドを宣言します。
//+------------------------------------------------------------------+ //| SplitContainer.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "Container.mqh" #include "..\Helpers\SplitContainerPanel.mqh" #include "..\Helpers\Splitter.mqh" //+------------------------------------------------------------------+ //| SplitContainer WForms control object class | //+------------------------------------------------------------------+ class CSplitContainer : public CContainer { private: int m_panel1_x; // panel1 X coordinate int m_panel1_y; // panel1 Y coordinate int m_panel1_w; // panel1 width int m_panel1_h; // panel1 height int m_panel2_x; // panel2 X coordinate int m_panel2_y; // panel2 Y coordinate int m_panel2_w; // panel2 width int m_panel2_h; // panel2 height int m_splitter_x; // Separator X coordinate int m_splitter_y; // Separator Y coordinate int m_splitter_w; // separator width int m_splitter_h; // separator height //--- Create a new graphical object virtual CGCnvElement *CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int element_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity); //--- Set the panel parameters bool SetsPanelParams(void); public:
クラスのpublicセクションで、新しいメソッドを宣言/記述し、返されたメソッドの型を変更してパネル上のポインタを受け取ります(CSplitContainerPanelクラスファイルの個別のコンパイル中に発生するエラーを修正するため)。メソッドはクラスの外で作成され、メソッドの宣言のみがここに残されます。
public: //--- Create the panels void CreatePanels(void); //--- Returns pointer to the specified panel CWinFormBase *GetPanel(const int index) { return CForm::GetElement(index); } //--- Return the pointer to the (1) panel1 and (2) panel2 CWinFormBase *GetPanel1(void) { return this.GetPanel(0); } CWinFormBase *GetPanel2(void) { return this.GetPanel(1); } //--- Return the element from the specified panel (1) by index, (2) by type and index and (3) by name CGCnvElement *GetPanelElement(const int panel,const int index); CGCnvElement *GetPanelElementByType(const int panel,const ENUM_GRAPH_ELEMENT_TYPE type,const int index); CGCnvElement *GetPanelElementByName(const int panel,const string name); //--- Return the pointer to the separator CSplitter *GetSplitter(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SPLITTER,0); } //--- (1) set and (2) return the minimum possible size of the panel 1 and 2 void SetPanel1MinSize(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE,value); } int Panel1MinSize(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE); } void SetPanel2MinSize(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE,value); } int Panel2MinSize(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE); } //--- (1) set and (2) return the flag of collapsed panel 1 void SetPanel1Collapsed(const int flag); bool Panel1Collapsed(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED); } //--- (1) set and (2) return the flag of collapsed panel 2 void SetPanel2Collapsed(const int flag); bool Panel2Collapsed(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED); } //--- (1) set and (2) return the separator distance from the edge void SetSplitterDistance(const int value); int SplitterDistance(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE); } //--- (1) set and (2) return the separator non-removability flag void SetSplitterFixed(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_FIXED,flag); } bool SplitterFixed(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_FIXED); } //--- (1) set and (2) return the separator width void SetSplitterWidth(const int value); int SplitterWidth(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH); } //--- (1) set and (2) return the separator location void SetSplitterOrientation(const ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION value) { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,value); } ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION SplitterOrientation(void) const { return(ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION); } //--- (1) set and (2) return the panel that does not change its size when the container is resized void SetFixedPanel(const ENUM_CANV_ELEMENT_SPLIT_CONTAINER_FIXED_PANEL value) { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_FIXED_PANEL,value); } ENUM_CANV_ELEMENT_SPLIT_CONTAINER_FIXED_PANEL FixedPanel(void) const { return(ENUM_CANV_ELEMENT_SPLIT_CONTAINER_FIXED_PANEL)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_FIXED_PANEL); } //--- Create a new attached element on the specified panel bool CreateNewElement(const int panel_index, 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); //--- Event handler virtual void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam); //--- 'The cursor is inside the active area, the mouse buttons are not clicked' event handler virtual void MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- Constructor CSplitContainer(const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); }; //+------------------------------------------------------------------+
新しいグラフィカルオブジェクトを作成するメソッドで、作成可能な別のオブジェクトタイプを追加します。
//+------------------------------------------------------------------+ //| Create a new graphical object | //+------------------------------------------------------------------+ CGCnvElement *CSplitContainer::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int obj_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity) { CGCnvElement *element=NULL; switch(type) { case GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL : element=new CSplitContainerPanel(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_SPLITTER : element=new CSplitter(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; default : break; } if(element==NULL) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),this.TypeElementDescription(type)); return element; } //+------------------------------------------------------------------+
パネルに加えてオブジェクト内にセパレータを作成する必要があるため、メソッドはこれを実行できる必要があります。追加された文字列によって、新しいセパレータオブジェクトが作成されます。
パネルを作成するメソッドで、セパレータオブジェクトを作成するためのコードブロックを追加します。
//+------------------------------------------------------------------+ //| Create the panels | //+------------------------------------------------------------------+ void CSplitContainer::CreatePanels(void) { this.m_list_elements.Clear(); if(this.SetsPanelParams()) { if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL,this.m_panel1_x,this.m_panel1_y,this.m_panel1_w,this.m_panel1_h,clrNONE,255,true,false)) return; if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL,this.m_panel2_x,this.m_panel2_y,this.m_panel2_w,this.m_panel2_h,clrNONE,255,true,false)) return; //--- if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SPLITTER,this.m_splitter_x,this.m_splitter_y,this.m_splitter_w,this.m_splitter_h,clrNONE,255,true,false)) return; CSplitter *splitter=this.GetSplitter(); if(splitter!=NULL) { splitter.SetMovable(true); splitter.SetDisplayed(false); splitter.Hide(); } } } //+------------------------------------------------------------------+
ここ:セパレータオブジェクトの作成に失敗した場合は、メソッドを終了します。次に、作成されたセパレータオブジェクトへのポインタを取得し、再配置フラグを設定し(これもマウスで移動する必要)、表示する必要がないことを示すフラグを設定し、作成されたオブジェクトを非表示にします。
パネルの作成も変更されました。ここで、まず新しいメソッドSetsPanelParams()でパラメータをパネルに設定します。これについては以下で説明します。セパレータと折りたたまれたパネルフラグの位置に応じて、その初期座標とサイズが、この目的のために設計された新しい変数に設定されます。これらの値は、パネル作成メソッドに渡されます。
以下は、パネルパラメータを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the panel parameters | //+------------------------------------------------------------------+ bool CSplitContainer::SetsPanelParams(void) { switch(this.SplitterOrientation()) { //--- The separator is positioned vertically case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL : //--- If both panels are not collapsed, if(!this.Panel1Collapsed() && !this.Panel2Collapsed()) { //--- set the panel1 coordinates and size this.m_panel1_x=0; this.m_panel1_y=0; this.m_panel1_w=this.SplitterDistance(); this.m_panel1_h=this.Height(); //--- set the panel2 coordinates and size this.m_panel2_x=this.SplitterDistance()+this.SplitterWidth(); this.m_panel2_y=0; this.m_panel2_w=this.Width()-this.m_panel2_x; this.m_panel2_h=this.Height(); //--- write separator coordinates and size this.m_splitter_x=this.SplitterDistance(); this.m_splitter_y=0; this.m_splitter_w=this.SplitterWidth(); this.m_splitter_h=this.Height(); } //--- If panel2 is collapsed else if(this.Panel2Collapsed()) { //--- set the panel1 coordinates and size this.m_panel1_x=0; this.m_panel1_y=0; this.m_panel1_w=this.Width(); this.m_panel1_h=this.Height(); //--- set the panel2 coordinates and size this.m_panel2_x=this.SplitterDistance()+this.SplitterWidth(); this.m_panel2_y=0; this.m_panel2_w=this.Width()-this.m_panel2_x; this.m_panel2_h=this.Height(); //--- write separator coordinates and size this.m_splitter_x=-this.SplitterWidth(); this.m_splitter_y=0; this.m_splitter_w=this.SplitterWidth(); this.m_splitter_h=this.Height(); } //--- If panel1 is collapsed else if(this.Panel1Collapsed()) { //--- set the panel1 coordinates and size this.m_panel1_x=0; this.m_panel1_y=0; this.m_panel1_w=this.SplitterDistance(); this.m_panel1_h=this.Height(); //--- set the panel2 coordinates and size this.m_panel2_x=0; this.m_panel2_y=0; this.m_panel2_w=this.Width(); this.m_panel2_h=this.Height(); //--- write separator coordinates and size this.m_splitter_x=-this.SplitterWidth(); this.m_splitter_y=0; this.m_splitter_w=this.SplitterWidth(); this.m_splitter_h=this.Height(); } break; //--- The separator is located horizontally case CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL : if(!this.Panel1Collapsed() && !this.Panel2Collapsed()) { //--- set the panel1 coordinates and size this.m_panel1_x=0; this.m_panel1_y=0; this.m_panel1_w=this.Width(); this.m_panel1_h=this.SplitterDistance(); //--- set the panel2 coordinates and size this.m_panel2_x=0; this.m_panel2_y=this.SplitterDistance()+this.SplitterWidth(); this.m_panel2_w=this.Width(); this.m_panel2_h=this.Height()-this.m_panel2_y; //--- write separator coordinates and size this.m_splitter_x=0; this.m_splitter_y=this.SplitterDistance(); this.m_splitter_w=this.Width(); this.m_splitter_h=this.SplitterWidth(); } //--- If panel2 is collapsed else if(this.Panel2Collapsed()) { //--- set the panel1 coordinates and size this.m_panel1_x=0; this.m_panel1_y=0; this.m_panel1_w=this.Width(); this.m_panel1_h=this.Height(); //--- set the panel2 coordinates and size this.m_panel2_x=0; this.m_panel2_y=this.SplitterDistance()+this.SplitterWidth(); this.m_panel2_w=this.Width(); this.m_panel2_h=this.Height()-this.m_panel2_y; //--- write separator coordinates and size this.m_splitter_x=0; this.m_splitter_y=-this.SplitterDistance(); this.m_splitter_w=this.Width(); this.m_splitter_h=this.SplitterWidth(); } //--- If panel1 is collapsed else if(this.Panel1Collapsed()) { //--- set the panel1 coordinates and size this.m_panel1_x=0; this.m_panel1_y=0; this.m_panel1_w=this.Width(); this.m_panel1_h=this.SplitterDistance(); //--- set the panel2 coordinates and size this.m_panel2_x=0; this.m_panel2_y=0; this.m_panel2_w=this.Width(); this.m_panel2_h=this.Height(); //--- write separator coordinates and size this.m_splitter_x=0; this.m_splitter_y=-this.SplitterDistance(); this.m_splitter_w=this.Width(); this.m_splitter_h=this.SplitterWidth(); } break; default: return false; break; } //--- Set the coordinates and sizes of the control area equal to the properties set by the separator this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,this.m_splitter_x); this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,this.m_splitter_y); this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,this.m_splitter_w); this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,this.m_splitter_h); return true; } //+------------------------------------------------------------------+
セパレータの位置(垂直または水平)とパネルの状態(両方のパネルが折りたたまれているか片方のみが折りたたまれているか)に応じて、パネルとセパレータの座標とサイズをサービス変数に設定します。メソッドの最後に、メソッドで設定されたセパレータパラメータが、コントロール領域の座標と寸法のプロパティに書き込まれます。
以下は、パネル1の折りたたみフラグを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the flag of collapsed panel 1 | //+------------------------------------------------------------------+ void CSplitContainer::SetPanel1Collapsed(const int flag) { //--- Set the flag, passed to the method, to the object property this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,flag); //--- If panel1 should be collapsed if(this.Panel1Collapsed()) { //--- set the expanded flag for panel2 this.SetPanel2Collapsed(false); //--- If the pointer to panel1 is received if(this.GetPanel1()!=NULL) { //--- set the flag for not displaying the panel and hide it this.GetPanel1().SetDisplayed(false); this.GetPanel1().Hide(); } //--- If the pointer to panel2 is received, if(this.GetPanel2()!=NULL) { //--- set the panel display flag, display it and bring it to the foreground this.GetPanel2().SetDisplayed(true); this.GetPanel2().Show(); this.GetPanel2().BringToTop(); } } } //+------------------------------------------------------------------+
このメソッドは、コード内で完全にコメントされています。パネルを折りたたむためのフラグを設定することに加えて(メソッドにfalseが渡された場合)、パネルを非表示にして非表示フラグを設定します。パネル2は、表示フラグで最前面に表示されます。
以下は、パネル2の折りたたみフラグを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the flag of collapsed panel 2 | //+------------------------------------------------------------------+ void CSplitContainer::SetPanel2Collapsed(const int flag) { //--- Set the flag, passed to the method, to the object property this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,flag); //--- If panel2 should be collapsed, if(Panel2Collapsed()) { //--- set the expanded flag for panel1 this.SetPanel1Collapsed(false); //--- If the pointer to panel2 is received, if(this.GetPanel2()!=NULL) { //--- set the flag for not displaying the panel and hide it this.GetPanel2().SetDisplayed(false); this.GetPanel2().Hide(); } //--- If the pointer to panel1 is received if(this.GetPanel1()!=NULL) { //--- set the panel display flag, display it and bring it to the foreground this.GetPanel1().SetDisplayed(true); this.GetPanel1().Show(); this.GetPanel1().BringToTop(); } } } //+------------------------------------------------------------------+
この方法のロジックは、上で説明したものと似ていますが、パネル2に適用されます。
以下は、エッジからセパレータの距離を設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the separator distance from the edge | //+------------------------------------------------------------------+ void CSplitContainer::SetSplitterDistance(const int value) { //--- Set the value, passed to the method, to the object property this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE,value); //--- Depending on the direction of the separator (vertical or horizontal), //--- set the values to the coordinates of the object control area switch(this.SplitterOrientation()) { case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL : this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,this.SplitterDistance()); this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,0); break; //---CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL default: this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,0); this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,this.SplitterDistance()); break; } } //+------------------------------------------------------------------+
オブジェクトコントロール領域の座標の原点はセパレータの位置に依存するため、セパレータの方向に応じて、セパレータの座標をコントロール領域に設定します。これは、この仮想領域の物理的な表現です。
以下は、セパレータの幅を設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the separator width | //+------------------------------------------------------------------+ void CSplitContainer::SetSplitterWidth(const int value) { //--- Set the value, passed to the method, to the object property this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH,value); //--- Depending on the direction of the separator (vertical or horizontal), //--- set the values to the object control area width and height switch(this.SplitterOrientation()) { case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL : this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,this.SplitterWidth()); this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,this.Height()); break; //---CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL default: this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,this.Width()); this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,this.SplitterWidth()); break; } } //+------------------------------------------------------------------+
このメソッドは上記のものと同じです。セパレータの方向に応じて、セパレータの寸法をコントロール領域に設定するため、この仮想領域が物理的に表示されます。
以下は、イベントハンドラです。
//+------------------------------------------------------------------+ //| Event handler | //+------------------------------------------------------------------+ void CSplitContainer::OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Adjust subwindow Y shift CGCnvElement::OnChartEvent(id,lparam,dparam,sparam); //--- If the event ID is moving the separator if(id==WF_CONTROL_EVENT_SPLITTER_MOVE) { //--- Get the pointer to the separator object CSplitter *splitter=this.GetSplitter(); if(splitter==NULL) return; //--- Declare the variables for separator coordinates int x=(int)lparam; int y=(int)dparam; //--- Depending on the separator direction, switch(this.SplitterOrientation()) { //--- vertical position case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL : //--- Set the Y coordinate equal to the Y coordinate of the control element y=this.CoordY(); //--- Adjust the X coordinate so that the separator does not go beyond the control element //--- taking into account the resulting minimum width of the panels if(x<this.CoordX()+this.Panel1MinSize()) x=this.CoordX()+this.Panel1MinSize(); if(x>this.CoordX()+this.Width()-this.Panel2MinSize()-this.SplitterWidth()) x=this.CoordX()+this.Width()-this.Panel2MinSize()-this.SplitterWidth(); break; //---CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL //--- horizontal position of the separator default: //--- Set the X coordinate equal to the X coordinate of the control element x=this.CoordX(); //--- Adjust the Y coordinate so that the separator does not go beyond the control element //--- taking into account the resulting minimum height of the panels if(y<this.CoordY()+this.Panel1MinSize()) y=this.CoordY()+this.Panel1MinSize(); if(y>this.CoordY()+this.Height()-this.Panel2MinSize()-this.SplitterWidth()) y=this.CoordY()+this.Height()-this.Panel2MinSize()-this.SplitterWidth(); break; } //--- If the separator is shifted by the calculated coordinates, if(splitter.Move(x,y,true)) { //--- set the separator relative coordinates splitter.SetCoordXRelative(splitter.CoordX()-this.CoordX()); splitter.SetCoordYRelative(splitter.CoordY()-this.CoordY()); //--- Get the pointers to both panels CSplitContainerPanel *p1=this.GetPanel1(); CSplitContainerPanel *p2=this.GetPanel2(); if(p1==NULL || p2==NULL) return; //--- Depending on the direction of the separator, set its new coordinates this.SetSplitterDistance(!this.SplitterOrientation() ? splitter.CoordX()-this.CoordX() : splitter.CoordY()-this.CoordY()); //--- Set the panel new coordinates and sizes depending on the separator coordinates if(this.SetsPanelParams()) { //--- If panel 1 is resized successfully if(p1.Resize(this.m_panel1_w,this.m_panel1_h,true)) { //--- If panel 2 coordinates are changed to new ones if(p2.Move(this.CoordX()+this.m_panel2_x,this.CoordY()+this.m_panel2_y,true)) { //--- if panel 2 has been successfully resized, if(p2.Resize(this.m_panel2_w,this.m_panel2_h,true)) { //--- set new relative coordinates of panel 2 p2.SetCoordXRelative(p2.CoordX()-this.CoordX()); p2.SetCoordYRelative(p2.CoordY()-this.CoordY()); } } } } } } } //+------------------------------------------------------------------+
メソッドのロジックはコードのコメントで完全に説明されています。つまり、ハンドラは「セパレータ移動」イベントIDを受け取り、パネルの新しい座標とサイズを計算します。パネル1は常にその座標にとどまり、セパレータが移動したときにのみサイズが変更されます。パネル2は、サイズ変更に加えて、初期座標がセパレータに関連付けられているため、セパレータの後に移動する必要があります。したがって、パネルはセパレータをたどるときに常にコンテナー内に留まるようにサイズ変更されます。
以下は、「カーソルがアクティブ領域内にあり、マウスボタンがクリックされていない」イベントのハンドラです。
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| no mouse buttons are clicked' event handler | //+------------------------------------------------------------------+ void CSplitContainer::MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { //--- Get the pointer to the separator CSplitter *splitter=this.GetSplitter(); if(splitter==NULL) { ::Print(DFUN,CMessage::Text(MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ),": ",this.TypeElementDescription(GRAPH_ELEMENT_TYPE_WF_SPLITTER)); return; } //--- If the separator is not displayed if(!splitter.Displayed()) { //--- Enable the display of the separator, show and redraw it splitter.SetDisplayed(true); splitter.Show(); splitter.Redraw(true); } } //+------------------------------------------------------------------+
メソッドのロジックは、コードのコメントで説明されています。マウスカーソルをコントロール領域上に移動すると、CFormクラスのフォームオブジェクトのマウスイベントハンドラに送信されるイベントが生成されます。ハンドラ内には、各イベントを独自の仮想メソッドで処理するためのリダイレクトがあります。フォームオブジェクトでは、これらのメソッドはすべて何もしません。派生クラスでオーバーライドする必要があります。SplitContainerコントロールのこのクラスでは、このようなハンドラはセパレータオブジェクトへのポインタを受け取り、それが表示されていない(表示フラグがリセットされている)場合は、表示フラグが設定されます。オブジェクト自体が表示され、再描画されます。
SplitContainerコントロールパネルのオブジェクトクラスをわずかに改善しました。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\SplitContainerPanel.mqhクラスファイルのpublicセクションで、折りたたみパネルフラグを設定するメソッドを設定し、パネルを表示するメソッドと「カーソルがアクティブ領域内にあり、マウスボタンがクリックされていない」イベントのハンドラを宣言します。
//+------------------------------------------------------------------+ //| SplitContainerPanel object class | //| of the SplitContainer WForms control | //+------------------------------------------------------------------+ class CSplitContainerPanel : public CContainer { private: //--- Create a new graphical object virtual CGCnvElement *CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int element_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity); protected: //--- Protected constructor with object type, chart ID and subwindow CSplitContainerPanel(const ENUM_GRAPH_ELEMENT_TYPE type, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); public: //--- (1) Set and (2) return the flag of collapsed panel void SetCollapsed(const bool flag) { this.SetDisplayed(!flag); } bool Collapsed(void) const { return !this.Displayed(); } //--- Display the panel virtual void Show(void); //--- Draw the panel frame virtual void DrawFrame(void); //--- Clear the element filling it with color and opacity virtual void Erase(const color colour,const uchar opacity,const bool redraw=false); //--- Clear the element with a gradient fill virtual void Erase(color &colors[],const uchar opacity,const bool vgradient,const bool cycle,const bool redraw=false); //--- 'The cursor is inside the active area, the mouse buttons are not clicked' event handler virtual void MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam); //--- Constructor CSplitContainerPanel(const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); }; //+------------------------------------------------------------------+
SetCollapsed()およびCollapsed()メソッドは、SetDisplayed()およびDisplayed()メソッドの反対です。したがって、それらは宣言されたメソッド内で呼び出されますが、メソッドに渡されるフラグまたはメソッドから返されるフラグは反転されます。
新しいグラフィカルオブジェクトを作成するメソッドで、セパレータオブジェクトの作成を追加します。
//+------------------------------------------------------------------+ //| Create a new graphical object | //+------------------------------------------------------------------+ CGCnvElement *CSplitContainerPanel::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int obj_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity) { CGCnvElement *element=NULL; switch(type) { case GRAPH_ELEMENT_TYPE_ELEMENT : element=new CGCnvElement(type,this.ID(),obj_num,this.ChartID(),this.SubWindow(),descript,x,y,w,h,colour,opacity,movable,activity); break; case GRAPH_ELEMENT_TYPE_FORM : element=new CForm(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_CONTAINER : element=new CContainer(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_GROUPBOX : element=new CGroupBox(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_PANEL : element=new CPanel(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_LABEL : element=new CLabel(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_CHECKBOX : element=new CCheckBox(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON : element=new CRadioButton(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_BUTTON : element=new CButton(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_LIST_BOX : element=new CListBox(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM : element=new CListBoxItem(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX : element=new CCheckedListBox(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX : element=new CButtonListBox(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TAB_HEADER : element=new CTabHeader(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TAB_FIELD : element=new CTabField(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL : element=new CTabControl(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON : element=new CArrowButton(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP : element=new CArrowUpButton(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN : element=new CArrowDownButton(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT : element=new CArrowLeftButton(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT : element=new CArrowRightButton(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX : element=new CArrowUpDownBox(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX : element=new CArrowLeftRightBox(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER : element=new CSplitContainer(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_SPLITTER : element=new CSplitter(this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; default : break; } if(element==NULL) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),this.TypeElementDescription(type)); return element; } //+------------------------------------------------------------------+
すべての補助オブジェクトが個別に取得された値を表すわけではないことは明らかですが、すべてのコンテナオブジェクトは、可能なすべてのオブジェクトを内部で作成できる必要があります。したがって、オブジェクトが属するライブラリオブジェクトのカテゴリに関係なく、コンテナオブジェクト内のすべての既存および新規オブジェクトの作成を実装します。
以下は、パネルを表示するメソッドです。
//+------------------------------------------------------------------+ //| Display the panel | //+------------------------------------------------------------------+ void CSplitContainerPanel::Show(void) { //--- If the panel is collapsed, leave if(this.Collapsed()) return; //--- Display the panel and all objects attached to it CForm::Show(); } //+------------------------------------------------------------------+
ここでは、まず折りたたまれたパネルのフラグを確認し、パネルが折りたたまれた状態の場合は表示するものが何もないため、終了します。それ以外の場合は、フォームオブジェクトの親クラスのメソッドを使用してパネルを表示します。
以下は、「カーソルがアクティブ領域内にあり、マウスボタンがクリックされていない」イベントのハンドラです。
//+------------------------------------------------------------------+ //| 'The cursor is inside the active area, | //| no mouse buttons are clicked' event handler | //+------------------------------------------------------------------+ void CSplitContainerPanel::MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam) { //--- Get the pointer to the base object CSplitContainer *base=this.GetBase(); if(base==NULL) return; //--- Get the pointer to the separator object from the base object CSplitter *splitter=base.GetSplitter(); if(splitter==NULL) { ::Print(DFUN,CMessage::Text(MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ),": ",this.TypeElementDescription(GRAPH_ELEMENT_TYPE_WF_SPLITTER)); return; } //--- If the separator is displayed if(splitter.Displayed()) { //--- Disable the display of the separator and hide it splitter.SetDisplayed(false); splitter.Hide(); } } //+------------------------------------------------------------------+
メソッドのロジックは、コードにコメントされています。つまり、カーソルをSplitContainerコントロールのコントロール領域から離すと、カーソルはすぐにそのコントロールの最初または2番目のパネルの領域に置かれます。したがって、カーソルがコントロール領域を離れたことをCSplitContainerクラスのオブジェクトで判断することはできません。カーソルは、コンテナに接続されたパネルオブジェクトにすぐに落ちます。これは、フォームまたはそのアクティブ領域上にあるカーソルのイベントが再トリガーされるパネルオブジェクトです。したがって、マウスイベントハンドラで基本オブジェクトからセパレータへのポインタを取得し、受信したセパレータを非表示にする必要があります。これはここでおこなわれます。
コンテナオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Container.mqhファイルにある、バインドされたオブジェクトのパラメータを設定するメソッドで、新しい作成されたセパレータオブジェクトのパラメータを設定する新しいコードブロックを追加します。
//+------------------------------------------------------------------+ //| Set parameters for the attached object | //+------------------------------------------------------------------+ void CContainer::SetObjParams(CWinFormBase *obj,const color colour) { obj.SetMain(this.GetMain()==NULL ? this.GetObject() : this.GetMain()); obj.SetBase(this.GetObject()); //--- 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_SPLIT_CONTAINER) 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 : 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 : 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 "Button", "TabHeader", TabField and "ListBoxItem" WinForms objects case GRAPH_ELEMENT_TYPE_WF_BUTTON : case GRAPH_ELEMENT_TYPE_WF_TAB_HEADER : case GRAPH_ELEMENT_TYPE_WF_TAB_FIELD : case GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM : 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 : 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; //--- For "TabControl" WinForms object case GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL : obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_TAB_BACK_COLOR : colour,true); obj.SetBorderColor(CLR_DEF_CONTROL_TAB_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); obj.SetOpacity(CLR_DEF_CONTROL_TAB_OPACITY); break; //--- For "SplitContainer" WinForms object case GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER : obj.SetBackgroundColor(colour==clrNONE ? CLR_CANV_NULL : colour,true); obj.SetBorderColor(CLR_CANV_NULL,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); obj.SetOpacity(0); break; //--- For "SplitContainerPanel" WinForms object case GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL: obj.SetBackgroundColor(colour==clrNONE ? CLR_DEF_CONTROL_SPLIT_CONTAINER_BACK_COLOR : colour,true); obj.SetBorderColor(CLR_DEF_CONTROL_SPLIT_CONTAINER_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); break; //--- For "Splitter" WinForms object case GRAPH_ELEMENT_TYPE_WF_SPLITTER : obj.SetBackgroundColor(colour==clrNONE ? CLR_CANV_NULL : colour,true); obj.SetBorderColor(CLR_CANV_NULL,true); obj.SetForeColor(CLR_DEF_FORE_COLOR,true); obj.SetOpacity(0); obj.SetDisplayed(false); obj.Hide(); break; //--- For the "ArrowButton" WinForms object case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON : case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP : case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN : case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT : case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT : obj.SetBorderColor(CLR_DEF_CONTROL_TAB_HEAD_BORDER_COLOR,true); obj.SetBorderStyle(FRAME_STYLE_SIMPLE); break; default: break; } obj.Crop(); } //+------------------------------------------------------------------+
新しく作成されたセパレータオブジェクトに対して、透明な背景色(色がclrNONEメソッドに渡される場合)と透明なフレームの色を設定し、オブジェクトを完全な透明度に設定し、非表示フラグを設定して、作成されたオブジェクトを非表示にします—最初は、セパレータオブジェクトが表示されないようにする必要があります。
グラフィック要素のコレクションクラスの\MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqhファイルにあるイベントハンドラで、セパレータオブジェクトの移動を処理するコードブロックを追加します。
//--- In case of the mouse movement event if(id==CHARTEVENT_MOUSE_MOVE) { //--- If the cursor is above the form if(form!=NULL) { //--- If the move flag is set if(move) { //--- calculate the cursor movement relative to the form coordinate origin int x=this.m_mouse.CoordX()-form.OffsetX(); int y=this.m_mouse.CoordY()-form.OffsetY(); //--- get the width and height of the chart the form is located at int chart_width=(int)::ChartGetInteger(form.ChartID(),CHART_WIDTH_IN_PIXELS,form.SubWindow()); int chart_height=(int)::ChartGetInteger(form.ChartID(),CHART_HEIGHT_IN_PIXELS,form.SubWindow()); //--- If the form is not within an extended standard graphical object if(form_index==WRONG_VALUE) { //--- If the form is a separator object, if(form.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SPLITTER) { //--- get its base object CWinFormBase *base=form.GetBase(); if(base==NULL) return; //--- and send the "Separator movement" event to the event handler of the base object const long lp=x; const double dp=y; base.OnChartEvent(WF_CONTROL_EVENT_SPLITTER_MOVE,lp,dp,sparam); } //--- Adjust the calculated form coordinates if the form is out of the chart range if(x<0) x=0; if(x>chart_width-form.Width()) x=chart_width-form.Width(); if(y<0) y=0; if(y>chart_height-form.Height()) y=chart_height-form.Height(); //--- If the one-click trading panel is not present on the chart, if(!::ChartGetInteger(form.ChartID(),CHART_SHOW_ONE_CLICK)) { //--- calculate the form coordinates so that the form does not overlap with the one-click trading panel button
このメソッドでは、グラフィカルオブジェクトの移動を処理するブロック内で、移動するオブジェクトのタイプを確認し、それがセパレータオブジェクトである場合は、そのイベントハンドラを呼び出して、それにWF_CONTROL_EVENT_SPLITTER_MOVEイベントを送信します。このグラフィック要素のイベントハンドラ内で、このイベントは上記のように処理されます。
本稿で計画したライブラリの変更と改善はこれですべてです。
結果をテストしてみましょう。
検証
テストを実行するには、前の記事のEAを\MQL5\Experts\TestDoEasy\Part121\でTestDoEasy121.mq5として保存します。
EAで変更する必要があるのは、SplitContainerコントロールパネルのテキストラベルの座標とサイズだけです。
//--- On each of the control panels... for(int j=0;j<2;j++) { CSplitContainerPanel *panel=split_container.GetPanel(j); if(panel==NULL) continue; //--- ...create a text label with the panel name if(split_container.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_LABEL,3,3,panel.Width()-6,panel.Height()-6,clrDodgerBlue,255,true,false)) { CLabel *label=split_container.GetPanelElementByType(j,GRAPH_ELEMENT_TYPE_WF_LABEL,0); if(label==NULL) continue; label.SetTextAlign(ANCHOR_CENTER); label.SetText(TextByLanguage("Панель","Panel")+string(j+1)); } }
なぜでしょうか。テキストラベルのサイズが、それらが作成されたパネルのサイズと一致する場合、カーソルがコントロール領域を離れたときに、パネル領域ではなくテキストラベル領域に移動します。したがって、セパレータオブジェクトを非表示にすることはできません。これは修正が必要な欠陥です。SplitContainerコントロールをさらに開発しながら、修正します。
EAをコンパイルし、チャート上で起動します。
再描画の遅延を除いて、すべて正常に動作します。残念ながら、私の貧弱な古いラップトップでこれらのフリーズが発生する理由は見つけることができませんでした。おそらく、ラップトップがプロセスで過負荷になり、パネルの座標とサイズの変更をスムーズに表示できなかったか、コードをさらに最適化する必要がある可能性があります。このようなフリーズが時折あることに気付きましたが、いずれにしても、ライブラリコードは、開発が完了した後に最適化の対象となります。また、セパレータオブジェクトの表示/非表示は常に確実に機能するとは限りません。コントロールを開発するときにこれも解決します。
次の段階
次の記事では、SplitContainerコントロールの開発を続け、既に作成されたコントロールのパラメータを変更する機能の作成を開始します。
連載のこれまでの記事
DoEasy.コントロール(第13部):WinFormsオブジェクトとマウスの相互作用を最適化し、TabControlWinFormsオブジェクトの開発を開始
DoEasy.コントロール(第14部):グラフィック要素に名前を付けるための新しいアルゴリズム。TabControlWinFormsオブジェクトの継続作業
DoEasy.コントロール(第15部):TabControlWinFormsオブジェクト—複数行のタブヘッダー、タブ処理メソッド
DoEasy.コントロール(第16部):TabControlWinFormsオブジェクト—複数行のタブヘッダー、コンテナに合わせてヘッダーをストレッチ
DoEasy.コントロール(第17部):非表示のオブジェクト部分のトリミング、補助矢印ボタンのWinFormsオブジェクト
DoEasy.コントロール(第18部):TabControlでタブをスクロールする機能
DoEasy.コントロール(第19部):TabControl、WinFormsオブジェクトイベントでのタブのスクロール
DoEasy.コントロール(第20部):SplitContainerWinFormsオブジェクト
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/11564





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