English Русский 中文 Español Deutsch Português
preview
DoEasy - コントロール(第30部):ScrollBarコントロールのアニメーション化

DoEasy - コントロール(第30部):ScrollBarコントロールのアニメーション化

MetaTrader 5 | 13 2月 2023, 14:47
159 0
Artyom Trishkin
Artyom Trishkin

内容


概念

前回はScrollBar補助コントロールの開発に着手しました。今回は、マウスによるコントロール要素のインタラクションを実装してみます。WinForms ScrollBarオブジェクトの構成要素は、スクロールボタンとキャプチャ領域です。スクロールボタンについては、補助オブジェクト(矢印ボタン)のクラスを別に用意していますが、キャプチャ領域は単純なボタンの形で作りました。ここでは、キャプチャ領域オブジェクトを作成するために、ボタンオブジェクトをベースにした別のクラスを実装してみることにします。スクロールバースライダーのイベントを正しく処理するために、オブジェクトはそれ自身の型を持つ必要があります。したがって、ボタンオブジェクトから派生し、そのプロパティを継承して、独自の型を持つ独立したオブジェクトとなります。

大部分は、コントロールのサイズ変更とスクロールバーによるマウス操作の処理に関する機能を作成するための準備作業です。マウスの状態とそのイベントのリストを拡張してみましょう。これらにより、以降の記事でルーチンワークに気を取られることなく、コントロールとその機能の開発に取り組むことができます。


ライブラリクラスの改善

\MQL5\Include\DoEasy\Defines.mqhで、ScrollBarオブジェクトの状態に関するデフォルトの色定数を追加しました。

#define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR   (C'0xF0,0xF0,0xF0')  // ScrollBar control background color
#define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR (C'0xFF,0xFF,0xFF')  // ScrollBar control frame color
#define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR   (C'0x60,0x60,0x60')  // ScrollBar control text color
#define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_DOWN (C'0x00,0x00,0x00')// Color of ScrollBar control text when clicking on the control
#define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_OVER (C'0x00,0x00,0x00')// Color of ScrollBar control text when hovering the mouse over the control

#define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR        (C'0xCD,0xCD,0xCD')  // ScrollBar control capture area color
#define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_BORDER_COLOR (C'0xCD,0xCD,0xCD')  // ScrollBar control capture area frame color
#define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN   (C'0x60,0x60,0x60')  // Color of ScrollBar control capture area when clicking on the control
#define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER   (C'0xA6,0xA6,0xA6')  // Color of ScrollBar control capture area when hovering over the control
#define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR   (C'0x60,0x60,0x60')  // ScrollBar control capture area text color
#define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN (C'0xFF,0xFF,0xFF')// Color of ScrollBar control capture area text when clicking on the control
#define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER (C'0x00,0x00,0x00')// Color of ScrollBar control capture area text when hovering the mouse over the control

#define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR         (C'0xF0,0xF0,0xF0')  // ScrollBar control button color
#define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_BORDER_COLOR  (C'0xCD,0xCD,0xCD')  // ScrollBar control button frame color
#define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN    (C'0x60,0x60,0x60')  // Color of ScrollBar control buttons when clicking on the control
#define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER    (C'0xDA,0xDA,0xDA')  // Color of ScrollBar control buttons when hovering the mouse over the control
#define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR    (C'0x60,0x60,0x60')  // ScrollBar control button text color
#define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN (C'0xFF,0xFF,0xFF')// Color of ScrollBar control button text when clicking on the control
#define CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER (C'0x00,0x00,0x00')// Color of ScrollBar control button text when hovering the mouse over the control

#define DEF_CONTROL_SCROLL_BAR_WIDTH                  (11)                 // Default ScrollBar control width
#define DEF_CONTROL_CORNER_AREA                       (4)                  // Number of pixels defining the corner area to resize
#define DEF_CONTROL_LIST_MARGIN_X                     (1)                  // Gap between columns in ListBox controls
#define DEF_CONTROL_LIST_MARGIN_Y                     (0)                  // Gap between rows in ListBox controls

各スクロール領域には幅があります。縦スクロールバーの場合はオブジェクトの幅、横スクロールバーの場合は高さです。このパラメータには、デフォルトの11を設定しましょう。スクロールバーには境界があり、インターフェイスに重ねたときにインターフェイスから分離されるようになっています。幅の値が11ピクセルの場合、スクロールバーのアクティブ領域は9ピクセル(上下左右の境界ごとに1ピクセル)になります。矢印ボタンとスライダーはスクロールバー上に作るので、矢印の三角形が均等に美しく描かれる9ピクセルが十分な奇数です。一般に、中心軸に沿った図形が描かれたオブジェクトのサイズを変更する場合、奇数のピクセル数を使用することで、均一できれいな描画を維持することができるようにする必要があります。角の領域とは、カーソルが角に位置しているとみなされるフォームの部分です。例えば、オブジェクトのサイズを変更する場合、カーソルが四隅のいずれかにあれば、そのサイズの2つのパラメータ(高さと幅)を一度に変更することができます。

形状に関連して可能なマウスの状態のリストに新しい値を追加します。オブジェクトの寸法は8方向にリサイズ可能です

  1. カーソルがオブジェクトの上端 = 端を上にずらして高さを変更
  2. カーソルがオブジェクトの下端 = 端を下にずらして高さを変更
  3. カーソルがオブジェクトの左端 = 端を左にずらして高さを変更
  4. カーソルがオブジェクトの右端 = 端を右にずらして高さを変更
  5. カーソルがオブジェクトの左上 = 左と上にずらして高さと幅を変更
  6. カーソルがオブジェクトの右上 = 右と上にずらして高さと幅を変更
  7. カーソルがオブジェクトの左下 = 左と下にずらして高さと幅を変更
  8. カーソルがオブジェクトの右下 = 右と下にずらして高さと幅を変更

スクロール可能なコンテンツを持つコンテナの右側と下側にスクロールバーが表示されます。カーソルが右と下のどちらのスクロールバー上にあるかを判断し、それらの状態をマウスの状態に設定する必要があります。

//+------------------------------------------------------------------+
//| 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 to the right
   MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED,// The cursor is within the window scrolling area to the right, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED,    // The cursor is within the window scrolling area to the right, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL,      // The cursor is within the window scrolling area to the right, the mouse wheel is being scrolled
//--- Within the window scrolling area at the bottom
   MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED,// The cursor is within the window scrolling area at the bottom, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED,   // The cursor is within the window scrolling area at the bottom, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL,     // The cursor is within the window scrolling area at the bottom, the mouse wheel is being scrolled

//--- Within the window resizing area at the top
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED,  // The cursor is within the window resizing area at the top, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED,      // The cursor is within the window resizing area at the top, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_WHEEL,        // The cursor is within the window resizing area at the top, the mouse wheel is being scrolled
//--- Within the window resizing area at the bottom
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED,   // The cursor is within the window resizing area at the bottom, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_WHEEL,     // The cursor is within the window resizing area at the bottom, the mouse wheel is being scrolled
//--- Within the window resizing area to the left
   MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED, // The cursor is within the window resizing area to the left, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED,     // The cursor is within the window resizing area to the left, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_WHEEL,       // The cursor is within the window resizing area to the left, the mouse wheel is being scrolled
//--- Within the window resizing area to the right
   MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED,// The cursor is within the window resizing area to the right, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED,    // The cursor is within the window resizing area to the right, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_WHEEL,      // The cursor is within the window resizing area to the right, the mouse wheel is being scrolled
//--- Within the window resizing area to the top-left
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED,   // The cursor is within the window resizing area at the top-left, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED,       // The cursor is within the window resizing area at the top-left, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL,         // The cursor is within the window resizing area at the top-left, the mouse wheel is being scrolled
//--- Within the window resizing area to the top-right
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED,  // The cursor is within the window resizing area at the top-right, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED,      // The cursor is within the window resizing area at the top-right, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL,        // The cursor is within the window resizing area at the top-right, the mouse wheel is being scrolled
//--- Within the window resizing area at the bottom left
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom-left, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED,    // The cursor is within the window resizing area at the bottom-left, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL,      // The cursor is within the window resizing area at the bottom-left, the mouse wheel is being scrolled
//--- Within the window resizing area at the bottom-right
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom-right, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED,   // The cursor is within the window resizing area at the bottom-right, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL,     // The cursor is within the window resizing area at the bottom-right, the mouse wheel is being scrolled
   
//--- Within the control area
   MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED,  // The cursor is within the control area, the mouse buttons are not clicked
   MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED,      // The cursor is within the control area, the mouse button (any) is clicked
   MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL,        // The cursor is within the control area, the mouse wheel is being scrolled
  };
//+------------------------------------------------------------------+

これらの新しい状態はすべて、オブジェクトに対するマウスの相対的な状態として定義され、記録されることになります。

マウスが所定の状態にあるイベントが登録されると、そのイベントがライブラリに送られ、マウスイベントを処理する機能を持つ各オブジェクトで、そのイベントに対応するハンドラが呼び出されます。
可能なマウスイベントのリストに新しい状態を書き込んでみましょう

//+--------------------------------------------+
//| 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 active 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 to the right
   MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED,  // The cursor is within the window scrolling area to the right, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_PRESSED,      // The cursor is within the window scrolling area to the right, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_WHEEL,        // The cursor is within the window scrolling area to the right, the mouse wheel is being scrolled
//--- Within the window scrolling area at the bottom
   MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED, // The cursor is within the window scrolling area at the bottom, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_PRESSED,     // The cursor is within the window scrolling area at the bottom, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_WHEEL,       // The cursor is within the window scrolling area at the bottom, the mouse wheel is being scrolled

//--- Within the window resizing area at the top
   MOUSE_EVENT_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED,    // The cursor is within the window resizing area at the top, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_RESIZE_TOP_AREA_PRESSED,        // The cursor is within the window resizing area at the top, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_RESIZE_TOP_AREA_WHEEL,          // The cursor is within the window resizing area at the top, the mouse wheel is being scrolled
//--- Within the window resizing area at the bottom
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED, // The cursor is within the window resizing area at the bottom, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_AREA_PRESSED,     // The cursor is within the window resizing area at the bottom, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_AREA_WHEEL,       // The cursor is within the window resizing area at the bottom, the mouse wheel is being scrolled
//--- Within the window resizing area to the left
   MOUSE_EVENT_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED,   // The cursor is within the window resizing area to the left, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_RESIZE_LEFT_AREA_PRESSED,       // The cursor is within the window resizing area to the left, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_RESIZE_LEFT_AREA_WHEEL,         // The cursor is within the window resizing area to the left, the mouse wheel is being scrolled
//--- Within the window resizing area to the right
   MOUSE_EVENT_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED,  // The cursor is within the window resizing area to the right, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_RESIZE_RIGHT_AREA_PRESSED,      // The cursor is within the window resizing area to the right, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_RESIZE_RIGHT_AREA_WHEEL,        // The cursor is within the window resizing area to the right, the mouse wheel is being scrolled
//--- Within the window resizing area to the top-left
   MOUSE_EVENT_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the top-left, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED,   // The cursor is within the window resizing area at the top-left, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL,     // The cursor is within the window resizing area at the top-left, the mouse wheel is being scrolled
//--- Within the window resizing area to the top-right
   MOUSE_EVENT_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the top-right, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED,  // The cursor is within the window resizing area at the top-right, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL,    // The cursor is within the window resizing area at the top-right, the mouse wheel is being scrolled
//--- Within the window resizing area at the bottom left
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom-left, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED,// The cursor is within the window resizing area at the bottom-left, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL,  // The cursor is within the window resizing area at the bottom-left, the mouse wheel is being scrolled
//--- Within the window resizing area at the bottom-right
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED,// The cursor is within the window resizing area at the bottom-right, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED,// The cursor is within the window resizing area at the bottom-right, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL, // The cursor is within the window resizing area at the bottom-right, the mouse wheel is being scrolled
//--- Within the control area
   MOUSE_EVENT_INSIDE_CONTROL_AREA_NOT_PRESSED,       // The cursor is within the control area, the mouse buttons are not clicked
   MOUSE_EVENT_INSIDE_CONTROL_AREA_PRESSED,           // The cursor is within the control area, the mouse button (any) is clicked
   MOUSE_EVENT_INSIDE_CONTROL_AREA_WHEEL,             // The cursor is within the control area, the mouse wheel is being scrolled
  };
#define MOUSE_EVENT_NEXT_CODE  (MOUSE_EVENT_INSIDE_CONTROL_AREA_WHEEL+1)   // The code of the next event after the last mouse event 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
   GRAPH_ELEMENT_TYPE_WF_TOOLTIP,                     // Windows Forms ToolTip
   GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,                // Windows Forms ProgressBar
   //--- 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
   GRAPH_ELEMENT_TYPE_WF_HINT_BASE,                   // Windows Forms HintBase
   GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT,              // Windows Forms HintMoveLeft
   GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT,             // Windows Forms HintMoveRight
   GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP,                // Windows Forms HintMoveUp
   GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN,              // Windows Forms HintMoveDown
   GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR,            // Windows Forms BarProgressBar
   GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ,                   // Glare object
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,            // Windows Forms ScrollBarThumb
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR,                  // Windows Forms ScrollBar
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,       // Windows Forms ScrollBarHorisontal
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,         // Windows Forms ScrollBarVertical
  };
//+------------------------------------------------------------------+

これは、新しい「キャプチャ領域」ヘルパー(スクロールバースライダー)コントロールになります。

グラフィック要素の整数プロパティの列挙に2つの新しいプロパティを追加し、それらの合計数を138から140に増やしました。

//+------------------------------------------------------------------+
//| 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_ZORDER,                          // Priority of a graphical object for receiving the event of clicking on a chart
   CANV_ELEMENT_PROP_ENABLED,                         // Element availability flag
   CANV_ELEMENT_PROP_RESIZABLE,                       // Resizable element flag
   CANV_ELEMENT_PROP_FORE_COLOR,                      // Default text color for all control objects
   CANV_ELEMENT_PROP_FORE_COLOR_OPACITY,              // Default text color opacity for all control objects

   //---...
   //---...

   CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,              // Current ProgressBar value from Min to Max
   CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED, // Progress bar animation speed in case of Marquee style
   CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,               // Size of the arrow drawn on the button
  };
#define CANV_ELEMENT_PROP_INTEGER_TOTAL (140)         // Total number of integer properties
#define CANV_ELEMENT_PROP_INTEGER_SKIP  (0)           // Number of integer properties not used in sorting
//+------------------------------------------------------------------+

各グラフィック要素には、マウスでサイズ変更が可能であることを示すフラグが表示されます。要素に描画される矢印(例えば、矢印付きボタン)は、このパラメータで指定された相対的な大きさを持つことになります。例えば、サイズ1の矢印は、中心点から1ピクセルのバーテックスインデントで描画されます。サイズ2の矢印は、中心点から2ピクセルずつインデントして描かれます。

例えば、サイズ1の上矢印の場合、次のようになります。

⊡⊠⊡
⊠⊠⊠

サイズ2の上矢印は次のようになります。

⊡⊡⊠⊡⊡
⊡⊠⊠⊠⊡
⊠⊠⊠⊠⊠

サイズ3の上矢印は次のようになります。

⊡⊡⊡⊠⊡⊡⊡
⊡⊡⊠⊠⊠⊡⊡
⊡⊠⊠⊠⊠⊠⊡
⊠⊠⊠⊠⊠⊠⊠

三角形の底面の中心を1ピクセルとし、その各辺に図形の相対的な大きさに等しいピクセル数を設定すると、三角形の3つの頂点が得られ、それに沿って図形が構築されることになります。したがって、三角形の大きさは、三角形の底面の中心から、各頂点の座標を示す上下左右のピクセル数となります。

下、左、右の矢印も同じように作られています。

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

   MSG_GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,            // ProgressBar control
   MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR,              // ScrollBar control
   MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,        // ScrollBar control capture area
   MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,     // ScrollBarVertical control
   MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,   // ScrollBarHorisontal control

...

   MSG_CANV_ELEMENT_PROP_DISPLAY_DURATION,            // Control display duration
   MSG_CANV_ELEMENT_PROP_ENABLED,                     // Element availability flag
   MSG_CANV_ELEMENT_PROP_RESIZABLE,                   // Control size changeability flag
   MSG_CANV_ELEMENT_PROP_FORE_COLOR,                  // Default text color for all control objects
   MSG_CANV_ELEMENT_PROP_FORE_COLOR_OPACITY,          // Default text color opacity for all control objects

...

   MSG_CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,          // Current ProgressBar value from Min to Max
   MSG_CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,// Progress bar animation speed in case of Marquee style
   MSG_CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,           // Size of the arrow drawn on the button
//--- Real properties of graphical elements

//--- String properties of graphical elements

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

   {"Элемент управления \"ProgressBar\"","Control element \"ProgressBar\""},
   {"Элемент управления \"ScrollBar\"","Control element \"ScrollBar\""},
   {"Область захвата элемента управления \"ScrollBar\"","The grip area of the \"ScrollBar\" control"},
   {"Элемент управления \"ScrollBarVertical\"","Control element \"ScrollBarVertical\""},
   {"Элемент управления \"ScrollBarHorisontal\"","Control element \"ScrollBarHorisontal\""},

...

   {"Продолжительность процесса отображения элемента управления","Duration of the process of displaying the control"},
   {"Флаг доступности элемента","Element Availability flag"},
   {"Флаг изменяемости размеров элемента","Element Resizable flag"},
   {"Цвет текста по умолчанию для всех объектов элемента управления","Default text color for all objects in the control"},
   {"Непрозрачность цвета текста по умолчанию для всех объектов элемента управления","Default text color opacity for all objects in the control"},

...

   {"Текущее начение элемента ProgressBar в диапазоне от Min до Max","Current value of the ProgressBar in the range from Min to Max"},
   {"Скорость анимации полосы прогресса при стиле Marquee","Marquee style progress bar animation speed"},
   {"Размер стрелки, рисуемой на кнопке","Size of arrow drawn on the button"},
   
//--- String properties of graphical elements


新しいオブジェクトタイプの説明を表示するために\MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqhTypeElementDescription()メソッド内に、メソッドに渡されたオブジェクトタイプの説明を返す文字列を追加します

//+------------------------------------------------------------------+
//| 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)       :
      type==GRAPH_ELEMENT_TYPE_WF_TOOLTIP                ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TOOLTIP)               :
      type==GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR           ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR)          :
      //--- 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)              :
      type==GRAPH_ELEMENT_TYPE_WF_HINT_BASE              ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_BASE)             :
      type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT         ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT)        :
      type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT        ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT)       :
      type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP           ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP)          :
      type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN         ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN)        :
      type==GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR       ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR)      :
      type==GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ              ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ)             :
      type==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR             ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR)            :
      type==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL    ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL)   :
      type==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL  ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL) :
      type==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB       ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB)      :
      "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

      //---...
      //---...

      long           zorder;                                   // Priority of a graphical object for receiving the event of clicking on a chart
      bool           enabled;                                  // Element availability flag
      bool           resizable;                                // Size changeability flag
      color          fore_color;                               // Default text color for all control objects
      uchar          fore_color_opacity;                       // Default text color opacity for all control objects

      //---...
      //---...

      int            progress_bar_value;                       // Current ProgressBar value from Min to Max
      int            progress_bar_marquee_speed;               // Progress bar animation speed in case of Marquee style
      uchar          button_arrow_size;                        // Size of the arrow drawn on the button
      //---
      ulong          tooltip_initial_delay;                    // Tooltip display delay
      ulong          tooltip_auto_pop_delay;                   // Tooltip display duration
      ulong          tooltip_reshow_delay;                     // One element new tooltip display delay
      bool           tooltip_show_always;                      // Display a tooltip in inactive window
      int            tooltip_icon;                             // Icon displayed in a tooltip
      bool           tooltip_is_balloon;                       // Tooltip in the form of a "cloud"
      bool           tooltip_use_fading;                       // Fade when showing/hiding a tooltip
      //--- 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
      uchar          tooltip_title[256];                       // Element tooltip title
      uchar          tooltip_text[256];                        // Element tooltip text
     };
   SData             m_struct_obj;                             // Object structure
   uchar             m_uchar_array[];                          // uchar array of the object structure

クラスのpublicセクションで、グラフィック要素に対するカーソル位置のフラグを返す新しいメソッドを宣言します。

//--- Return the cursor position relative to the (1) entire element, (2) visible part, (3) active area and (4) element control area
   bool              CursorInsideElement(const int x,const int y);
   bool              CursorInsideVisibleArea(const int x,const int y);
   bool              CursorInsideActiveArea(const int x,const int y);
   bool              CursorInsideControlArea(const int x,const int y);
//--- Return the cursor position relative to the (1) right, (2) bottom element scroll area
   bool              CursorInsideScrollRightArea(const int x,const int y);
   bool              CursorInsideScrollBottomArea(const int x,const int y);
//--- Return the cursor position relative to the (1) upper, (2) lower, (3) left and (4) right element resize area
   bool              CursorInsideResizeTopArea(const int x,const int y);
   bool              CursorInsideResizeBottomArea(const int x,const int y);
   bool              CursorInsideResizeLeftArea(const int x,const int y);
   bool              CursorInsideResizeRightArea(const int x,const int y);
//--- Return the cursor position relative to the (1) top-left, (2) top-right,
//--- (3) bottom-left, (4) bottom-right element resize area corner
   bool              CursorInsideResizeTopLeftArea(const int x,const int y);
   bool              CursorInsideResizeTopRightArea(const int x,const int y);
   bool              CursorInsideResizeBottomLeftArea(const int x,const int y);
   bool              CursorInsideResizeBottomRightArea(const int x,const int y);

//--- Create the element
   bool              Create(const long chart_id,

オブジェクトプロパティへのアクセスを簡略化するメソッドブロックに、新しい領域とグラフィック要素ゾーンの座標を返すメソッド、およびサイズ変更可能フラグを返すメソッドを設定します。

//--- Set (1) object movability, (2) activity, (3) interaction,
//--- (4) element ID, (5) element index in the list, the flag of (6) availability, (7) changeable size, (8) shadow
   void              SetMovable(const bool flag)               { this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,flag);                     }
   void              SetActive(const bool flag)                { this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,flag);                      }
   void              SetInteraction(const bool flag)           { this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,flag);                 }
   void              SetID(const int id)                       { this.SetProperty(CANV_ELEMENT_PROP_ID,id);                            }
   void              SetNumber(const int number)               { this.SetProperty(CANV_ELEMENT_PROP_NUM,number);                       }
   void              SetEnabled(const bool flag)               { this.SetProperty(CANV_ELEMENT_PROP_ENABLED,flag);                     }
   void              SetResizable(const bool flag)             { this.SetProperty(CANV_ELEMENT_PROP_RESIZABLE,flag);                   }
   void              SetShadow(const bool flag)                { this.m_shadow=flag;                                                   }
   
//--- Set the (1) X, (2) Y coordinates, (3) width and (4) height of the element control area
   void              SetControlAreaX(const int value)          { this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,value);             }
   void              SetControlAreaY(const int value)          { this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,value);             }
   void              SetControlAreaWidth(const int value)      { this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,value);         }
   void              SetControlAreaHeight(const int value)     { this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,value);        }
   
//--- Return the shift (1) of the left, (2) right, (3) top and (4) bottom edge of the element active area
   int               ActiveAreaLeftShift(void)           const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT);       }
   int               ActiveAreaRightShift(void)          const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT);      }
   int               ActiveAreaTopShift(void)            const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP);        }
   int               ActiveAreaBottomShift(void)         const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM);     }
//--- 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 shift of the (1) X, (2) Y coordinates, (3) width, (4) height of the element control area
   int               ControlAreaXShift(void)             const { return (int)this.GetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X);       }
   int               ControlAreaYShift(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 coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area
   int               ControlAreaLeft(void)               const { return this.CoordX()+this.ControlAreaXShift();                        }
   int               ControlAreaRight(void)              const { return this.ControlAreaLeft()+this.ControlAreaWidth();                }
   int               ControlAreaTop(void)                const { return this.CoordY()+this.ControlAreaYShift();                        }
   int               ControlAreaBottom(void)             const { return this.ControlAreaTop()+this.ControlAreaHeight();                }
//--- Return the relative coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area
   int               ControlAreaLeftRelative(void)       const { return this.ControlAreaLeft()-this.CoordX();                          }
   int               ControlAreaRightRelative(void)      const { return this.ControlAreaRight()-this.CoordX();                         }
   int               ControlAreaTopRelative(void)        const { return this.ControlAreaTop()-this.CoordY();                           }
   int               ControlAreaBottomRelative(void)     const { return this.ControlAreaBottom()-this.CoordY();                        }
   
//--- Return the shift of the (1) X, (2) Y coordinates, (3) width, (4) height of the element scroll area to the right
   int               ScrollAreaRightXShift(void)         const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT);     }
   int               ScrollAreaRightYShift(void)         const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT);     }
   int               ScrollAreaRightWidth(void)          const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT); }
   int               ScrollAreaRightHeight(void)         const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT);}
//--- Return the coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area
   int               ScrollAreaRightLeft(void)           const { return this.CoordX()+this.ScrollAreaRightXShift();                       }
   int               ScrollAreaRightRight(void)          const { return this.ScrollAreaRightLeft()+this.ScrollAreaRightWidth();           }
   int               ScrollAreaRightTop(void)            const { return this.CoordY()+this.ScrollAreaRightYShift();                       }
   int               ScrollAreaRightBottom(void)         const { return this.ScrollAreaRightTop()+this.ScrollAreaRightHeight();           }
//--- Return the relative coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area
   int               ScrollAreaRightLeftRelative(void)   const { return this.ScrollAreaRightLeft()-this.CoordX();                         }
   int               ScrollAreaRightRightRelative(void)  const { return this.ScrollAreaRightRight()-this.CoordX();                        }
   int               ScrollAreaRightTopRelative(void)    const { return this.ScrollAreaRightTop()-this.CoordY();                          }
   int               ScrollAreaRightBottomRelative(void) const { return this.ScrollAreaRightBottom()-this.CoordY();                       }
   
//--- Return the shift of the (1) X, (2) Y coordinates, (3) width, (4) height of the element scroll area at the bottom
   int               ScrollAreaBottomXShift(void)        const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM);    }
   int               ScrollAreaBottomYShift(void)        const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM);    }
   int               ScrollAreaBottomWidth(void)         const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM);}
   int               ScrollAreaBottomHeight(void)        const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM);}
//--- Return the coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area
   int               ScrollAreaBottomLeft(void)          const { return this.CoordX()+this.ScrollAreaBottomXShift();                      }
   int               ScrollAreaBottomRight(void)         const { return this.ScrollAreaBottomLeft()+this.ScrollAreaBottomWidth();         }
   int               ScrollAreaBottomTop(void)           const { return this.CoordY()+this.ScrollAreaBottomYShift();                      }
   int               ScrollAreaBottomBottom(void)        const { return this.ScrollAreaBottomTop()+this.ScrollAreaBottomHeight();         }
//--- Return the relative coordinate (1) of the left, (2) right, (3) top and (4) bottom edge of the element control area
   int               ScrollAreaBottomLeftRelative(void)  const { return this.ScrollAreaBottomLeft()-this.CoordX();                        }
   int               ScrollAreaBottomRightRelative(void) const { return this.ScrollAreaBottomRight()-this.CoordX();                       }
   int               ScrollAreaBottomTopRelative(void)   const { return this.ScrollAreaBottomTop()-this.CoordY();                         }
   int               ScrollAreaBottomBottomRelative(void)const { return this.ScrollAreaBottomBottom()-this.CoordY();                      }

//--- 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 (1) element movability, (2) activity, (3) interaction, (4) availability and (5) size changeability flag
   bool              Movable(void)                       const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_MOVABLE);             }
   bool              Active(void)                        const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_ACTIVE);              }
   bool              Interaction(void)                   const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_INTERACTION);         }
   bool              Enabled(void)                       const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_ENABLED);             }
   bool              Resizable(void)                     const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_RESIZABLE);           }
//--- Return (1) the object name, (2) the graphical resource name, (3) the chart ID and (4) the chart subwindow index

矢印描画メソッドの宣言を変更します

//+------------------------------------------------------------------+
//| Methods for drawing predefined standard images                   |
//+------------------------------------------------------------------+
//--- Draw the Info icon
   void              DrawIconInfo(const int coord_x,const int coord_y,const uchar opacity);
//--- Draw the Warning icon
   void              DrawIconWarning(const int coord_x,const int coord_y,const uchar opacity);
//--- Draw the Error icon
   void              DrawIconError(const int coord_x,const int coord_y,const uchar opacity);
//--- Draw the left arrow
   void              DrawArrowLeft(const int base_x,const int base_y,const int size,const color clr,const uchar opacity);
//--- Draw the right arrow
   void              DrawArrowRight(const int base_x,const int base_y,const int size,const color clr,const uchar opacity);
//--- Draw the up arrow
   void              DrawArrowUp(const int base_x,const int base_y,const int size,const color clr,const uchar opacity);
//--- Draw the down arrow
   void              DrawArrowDown(const int base_x,const int base_y,const int size,const color clr,const uchar opacity);
  };
//+------------------------------------------------------------------+

これで、メソッドは中心点の座標相対的な矢印の大きさを受け取ることができます。

オブジェクトのプロパティを初期化するメソッドで、マウスカーソルがこれらの領域にあるかどうかを定義するために、オブジェクトの上下左右の端の領域の幅をデフォルト値として2ピクセルに設定しますデフォルトでは、マウスカーソルを使ってオブジェクトのサイズを変更する機能は無効になっており、描画される矢印のサイズは3になっています。

//+--------------------------------------------+
//| Initialize the properties                  |
//+--------------------------------------------+
void CGCnvElement::Initialize(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                              const int element_id,const int element_num,
                              const int x,const int y,const int w,const int h,
                              const string descript,const bool movable,const bool activity)
  {
   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_ID,element_id);                         // Element ID
   this.SetProperty(CANV_ELEMENT_PROP_NUM,element_num);                       // Element index in the list
   this.SetProperty(CANV_ELEMENT_PROP_COORD_X,x);                             // Element's X coordinate on the chart
   this.SetProperty(CANV_ELEMENT_PROP_COORD_Y,y);                             // Element's Y coordinate on the chart
   this.SetProperty(CANV_ELEMENT_PROP_WIDTH,w);                               // Element width
   this.SetProperty(CANV_ELEMENT_PROP_HEIGHT,h);                              // Element height
   this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT,0);                      // Active area offset from the left edge of the element
   this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP,0);                       // Active area offset from the upper edge of the element
   this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT,0);                     // Active area offset from the right edge of the element
   this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM,0);                    // Active area offset from the bottom edge of the element
   this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,movable);                       // Element moveability flag
   this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,activity);                       // Element activity flag
   this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,false);                     // Flag of interaction with the outside environment
   this.SetProperty(CANV_ELEMENT_PROP_ENABLED,true);                          // Element availability flag
   this.SetProperty(CANV_ELEMENT_PROP_RESIZABLE,false);                       // Element changeable size flag
   this.SetProperty(CANV_ELEMENT_PROP_RIGHT,this.RightEdge());                // Element right border
   this.SetProperty(CANV_ELEMENT_PROP_BOTTOM,this.BottomEdge());              // Element bottom border
   this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_X,this.ActiveAreaLeft());     // X coordinate of the element active area
   this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_Y,this.ActiveAreaTop());      // Y coordinate of the element active area
   this.SetProperty(CANV_ELEMENT_PROP_ACT_RIGHT,this.ActiveAreaRight());      // Right border of the element active area
   this.SetProperty(CANV_ELEMENT_PROP_ACT_BOTTOM,this.ActiveAreaBottom());    // Bottom border of the element active area
   this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_X,0);                      // Visibility scope X coordinate
   this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_Y,0);                      // Visibility scope Y coordinate
   this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_WIDTH,w);                  // Visibility scope width
   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_DISPLAY_STATE,CANV_ELEMENT_DISPLAY_STATE_NORMAL);// Control display state
   this.SetProperty(CANV_ELEMENT_PROP_DISPLAY_DURATION,DEF_CONTROL_PROCESS_DURATION);  // Control display duration
   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,2);              // Left edge area width 
   this.SetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH,2);            // Bottom edge area width
   this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,2);             // Right edge area width
   this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,2);               // 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_BORDER_SIZE_BOTTOM,0);                  // Control frame bottom size
   this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_LEFT,0);                    // Control frame left size
   this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_RIGHT,0);                   // Control frame right size
   this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR,this.BackgroundColor());   // Control frame color
   this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE,false);                        // Flag of the element auto resizing depending on the content
   this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE_MODE,CANV_ELEMENT_AUTO_SIZE_MODE_GROW); // Mode of the element auto resizing depending on the content
   this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL,false);                      // Auto scrollbar flag
   this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL_MARGIN_W,0);                 // Width of the field inside the element during auto scrolling
   this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL_MARGIN_H,0);                 // Height of the field inside the element during auto scrolling
   this.SetProperty(CANV_ELEMENT_PROP_DOCK_MODE,CANV_ELEMENT_DOCK_MODE_NONE); // Mode of binding control borders to the container
   this.SetProperty(CANV_ELEMENT_PROP_MARGIN_TOP,0);                          // Top margin between the fields of this and another control
   this.SetProperty(CANV_ELEMENT_PROP_MARGIN_BOTTOM,0);                       // Bottom margin between the fields of this and another control
   this.SetProperty(CANV_ELEMENT_PROP_MARGIN_LEFT,0);                         // Left margin between the fields of this and another control
   this.SetProperty(CANV_ELEMENT_PROP_MARGIN_RIGHT,0);                        // Right margin between the fields of this and another control
   this.SetProperty(CANV_ELEMENT_PROP_PADDING_TOP,0);                         // Top margin inside the control
   this.SetProperty(CANV_ELEMENT_PROP_PADDING_BOTTOM,0);                      // Bottom margin inside the control
   this.SetProperty(CANV_ELEMENT_PROP_PADDING_LEFT,0);                        // Left margin inside the control
   this.SetProperty(CANV_ELEMENT_PROP_PADDING_RIGHT,0);                       // Right margin inside the control
   this.SetProperty(CANV_ELEMENT_PROP_TEXT_ALIGN,ANCHOR_LEFT_UPPER);          // Text position within text label boundaries
   this.SetProperty(CANV_ELEMENT_PROP_CHECK_ALIGN,ANCHOR_LEFT_UPPER);         // Position of the checkbox within control borders
   this.SetProperty(CANV_ELEMENT_PROP_CHECKED,false);                         // Control checkbox status
   this.SetProperty(CANV_ELEMENT_PROP_CHECK_STATE,CANV_ELEMENT_CHEK_STATE_UNCHECKED);  // Status of a control having a checkbox
   this.SetProperty(CANV_ELEMENT_PROP_AUTOCHECK,true);                        // Auto change flag status when it is selected
   //---
   //---...
   //---...

   this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,50);                 // Current ProgressBar value from Min to Max
   this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,10);    // Progress bar animation speed in case of Marquee style
   this.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,3);                   // Size of the arrow drawn on the button
  }
//+------------------------------------------------------------------+

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

//+--------------------------------------------+
//| 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.zorder=this.GetProperty(CANV_ELEMENT_PROP_ZORDER);                            // Priority of a graphical object for receiving the on-chart mouse click event
   this.m_struct_obj.enabled=(bool)this.GetProperty(CANV_ELEMENT_PROP_ENABLED);                    // Element availability flag
   this.m_struct_obj.resizable=(bool)this.GetProperty(CANV_ELEMENT_PROP_RESIZABLE);                // Element size changeability flag
   this.m_struct_obj.fore_color=(color)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR);             // Default text color for all control objects
   this.m_struct_obj.fore_color_opacity=(uchar)this.GetProperty(CANV_ELEMENT_PROP_FORE_COLOR_OPACITY); // Opacity of the default text color for all control objects
   
   //---...
   //---...

   this.m_struct_obj.progress_bar_value=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE);     // Current ProgressBar value from Min to Max
   this.m_struct_obj.progress_bar_marquee_speed=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED);// Progress bar animation speed in case of Marquee style
   this.m_struct_obj.button_arrow_size=(uchar)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE);     // Size of the arrow drawn on the button
//--- 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
   ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE),this.m_struct_obj.tooltip_title);// Tooltip title for the element
   ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT),this.m_struct_obj.tooltip_text);  // Tooltip text for the element
   //--- 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_ZORDER,this.m_struct_obj.zorder);                            // Priority of a graphical object for receiving the event of clicking on a chart
   this.SetProperty(CANV_ELEMENT_PROP_ENABLED,this.m_struct_obj.enabled);                          // Element availability flag
   this.SetProperty(CANV_ELEMENT_PROP_RESIZABLE,this.m_struct_obj.resizable);                      // Element size changeability flag
   this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR,this.m_struct_obj.fore_color);                    // Default text color for all control objects
   this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_OPACITY,this.m_struct_obj.fore_color_opacity);    // Opacity of the default text color for all control objects
   
   //---...
   //---...

   this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,this.m_struct_obj.progress_bar_value); // Current ProgressBar value from Min to Max
   this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,this.m_struct_obj.progress_bar_marquee_speed);  // Progress bar animation speed in case of Marquee style
   this.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,this.m_struct_obj.button_arrow_size);   // Size of the arrow drawn on the button
//--- 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
   this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE,::CharArrayToString(this.m_struct_obj.tooltip_title));// Tooltip title for the element
   this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT,::CharArrayToString(this.m_struct_obj.tooltip_text));  // Tooltip text for the element
  }
//+------------------------------------------------------------------+

スクロール領域に対するカーソル位置フラグを返すメソッドと、要素のリサイズをおこなうメソッドを実装します。

//+------------------------------------------------------------------+
//|Return the cursor position relative to the element control area   |
//+------------------------------------------------------------------+
bool CGCnvElement::CursorInsideControlArea(const int x,const int y)
  {
   return(x>=this.ControlAreaLeft() && x<=this.ControlAreaRight() && y>=this.ControlAreaTop() && y<=this.ControlAreaBottom());
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element right scrolling area               |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideScrollRightArea(const int x,const int y)
  {
   return(x>=this.ScrollAreaRightLeft() && x<=this.ScrollAreaRightRight() && y>=this.ScrollAreaRightTop() && y<=this.ScrollAreaRightBottom());
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element bottom scrolling area              |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideScrollBottomArea(const int x,const int y)
  {
   return(x>=this.ScrollAreaBottomLeft() && x<=this.ScrollAreaBottomRight() && y>=this.ScrollAreaBottomTop() && y<=this.ScrollAreaBottomBottom());
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element resize upper area                  |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideResizeTopArea(const int x,const int y)
  {
   return(x>=this.CoordX()+DEF_CONTROL_CORNER_AREA && x<=this.RightEdge()-DEF_CONTROL_CORNER_AREA && y>=this.CoordY() && y<=this.CoordY()+this.BorderResizeAreaTop());
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element resize lower area                  |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideResizeBottomArea(const int x,const int y)
  {
   return(x>=this.CoordX()+DEF_CONTROL_CORNER_AREA && x<=this.RightEdge()-DEF_CONTROL_CORNER_AREA && y>=this.BottomEdge()-this.BorderResizeAreaBottom() && y<=this.BottomEdge());
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element resize lower area                  |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideResizeLeftArea(const int x,const int y)
  {
   return(x>=this.CoordX() && x<=this.CoordX()+this.BorderResizeAreaLeft() && y>=this.CoordY()+DEF_CONTROL_CORNER_AREA && y<=this.BottomEdge()-DEF_CONTROL_CORNER_AREA);
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element resize right area                  |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideResizeRightArea(const int x,const int y)
  {
   return(x>=this.RightEdge()-this.BorderResizeAreaRight() && x<=this.RightEdge() && y>=this.CoordY()+DEF_CONTROL_CORNER_AREA && y<=this.BottomEdge()-DEF_CONTROL_CORNER_AREA);
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element resize area upper left corner      |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideResizeTopLeftArea(const int x,const int y)
  {
   return
     (
      (x>=this.CoordX() && x<this.CoordX()+DEF_CONTROL_CORNER_AREA && y>=this.CoordY() && y<=this.CoordY()+this.BorderResizeAreaTop()) ||
      (x>=this.CoordX() && x<=this.BorderResizeAreaLeft() && y>=this.CoordY() && y<=this.CoordY()+DEF_CONTROL_CORNER_AREA)
     );
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element resize area upper right corner     |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideResizeTopRightArea(const int x,const int y)
  {
   return
     (
      (x>this.RightEdge()-DEF_CONTROL_CORNER_AREA && x<=this.RightEdge() && y>=this.CoordY() && y<=this.CoordY()+this.BorderResizeAreaTop()) ||
      (x>=this.RightEdge()-this.BorderResizeAreaRight() && x<=this.RightEdge() && y>=this.CoordY() && y<=this.CoordY()+DEF_CONTROL_CORNER_AREA)
     );
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element resize area lower left corner      |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideResizeBottomLeftArea(const int x,const int y)
  {
   return
     (
      (x>=this.CoordX() && x<this.CoordX()+DEF_CONTROL_CORNER_AREA && y>=this.BottomEdge()-this.BorderResizeAreaBottom() && y<=this.BottomEdge()) ||
      (x>=this.CoordX() && x<=this.CoordX()+this.BorderResizeAreaLeft() && y>this.BottomEdge()-DEF_CONTROL_CORNER_AREA && y<=this.BottomEdge())
     );
  }
//+--------------------------------------------+
//| Return the cursor position relative to the |
//| element resize area lower right corner     |
//+--------------------------------------------+
bool CGCnvElement::CursorInsideResizeBottomRightArea(const int x,const int y)
  {
   return
     (
      (x>this.RightEdge()-DEF_CONTROL_CORNER_AREA && x<=this.RightEdge() && y>=this.BottomEdge()-this.BorderResizeAreaBottom() && y<=this.BottomEdge()) ||
      (x>=this.RightEdge()-this.BorderResizeAreaRight() && x<=this.RightEdge() && y>this.BottomEdge()-DEF_CONTROL_CORNER_AREA && y<=this.BottomEdge())
     );
  }
//+--------------------------------------------+
//| Update the coordinate elements             |
//+--------------------------------------------+

カーソルの位置の座標に応じて、メソッドはカーソルがその値で囲まれた領域内にあることを示すフラグを返します。

矢印を描画するメソッドは、開始座標(三角形の底辺中心)指定された矢印のサイズに応じて三角形を描画するようになりました。

//+--------------------------------------------+
//| Draw the left arrow                        |
//+--------------------------------------------+
void CGCnvElement::DrawArrowLeft(const int base_x,const int base_y,const int size,const color clr,const uchar opacity)
  {
   int x=base_x;
   int y=base_y;
   int s=(size<1 ? 1 : size);
   this.DrawTriangleFill(x-s,y,x,y-s,x,y+s,clr,opacity);
   this.DrawTriangleWu(  x-s,y,x,y-s,x,y+s,clr,opacity);
  }
//+--------------------------------------------+
//| Draw the right arrow                       |
//+--------------------------------------------+
void CGCnvElement::DrawArrowRight(const int base_x,const int base_y,const int size,const color clr,const uchar opacity)
  {
   int x=base_x;
   int y=base_y;
   int s=(size<1 ? 1 : size);
   this.DrawTriangleFill(x+s,y,x,y+s,x,y-s,clr,opacity);
   this.DrawTriangleWu(  x+s,y,x,y+s,x,y-s,clr,opacity);
  }
//+--------------------------------------------+
//| Draw the up arrow                          |
//+--------------------------------------------+
void CGCnvElement::DrawArrowUp(const int base_x,const int base_y,const int size,const color clr,const uchar opacity)
  {
   int x=base_x;
   int y=base_y;
   int s=(size<1 ? 1 : size);
   this.DrawTriangleFill(x,y-s,x+s,y,x-s,y,clr,opacity);
   this.DrawTriangleWu(  x,y-s,x+s,y,x-s,y,clr,opacity);
  }
//+--------------------------------------------+
//| Draw the down arrow                        |
//+--------------------------------------------+
void CGCnvElement::DrawArrowDown(const int base_x,const int base_y,const int size,const color clr,const uchar opacity)
  {
   int x=base_x;
   int y=base_y;
   int s=(size<1 ? 1 : size);
   this.DrawTriangleFill(x,y+s,x-s,y,x+s,y,clr,opacity);
   this.DrawTriangleWu(  x,y+s,x-s,y,x+s,y,clr,opacity);
  }
//+------------------------------------------------------------------+

各頂点の座標を計算するには、中心点の座標にパラメータで渡された矢印の大きさを加減するだけです。
サイズは下限(1)のみで制限され、上限はないことに留意してください。ここで、矢印の実際の大きさは、指定された2つのサイズ+中央の1ピクセルとして得られるので、通常の大きさで描画されることを確認する必要があります。つまり、サイズが1の場合、実サイズは1+1+1になります。サイズが2の場合、実サイズは2+1+2、サイズが3の場合は3+1+3、などです。

要素に対する新しいマウスの状態とそれに対応するイベントができたので、それらを最後のマウスイベントのハンドラメソッドに反映させる必要があります。

\MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\Button.mqhで、新しいイベントのリストをメソッドに追加します。

//+--------------------------------------------+
//| Last mouse event handler                   |
//+--------------------------------------------+
void CButton::OnMouseEventPostProcessing(void)
  {
   if(!this.IsVisible() || !this.Enabled())
      return;
   ENUM_MOUSE_FORM_STATE state=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       :
        if(this.MouseEventLast()==MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED || this.MouseEventLast()==MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED)
          {
           this.SetBackgroundColor(this.State() ? this.BackgroundStateOnColor() : this.BackgroundColorInit(),false);
           this.SetForeColor(this.State() ? this.ForeStateOnColor() : this.ForeColorInit(),false);
           this.SetBorderColor(this.BorderColorInit(),false);
           this.m_mouse_event_last=ENUM_MOUSE_EVENT(state+MOUSE_EVENT_NO_EVENT);
           this.Redraw(false);
          }
        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                           :
//--- Within the active area
      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                 :
//--- Within the scrolling area at the bottom
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED       :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED           :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL             :
//--- Within the scrolling area to the right
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED            :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL              :
//--- Within the window resizing area at the top
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED          :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED              :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_WHEEL                :
//--- Within the window resizing area at the bottom
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED       :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED           :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_WHEEL             :
//--- Within the window resizing area to the left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED         :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED             :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_WHEEL               :
//--- Within the window resizing area to the right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED            :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_WHEEL              :
//--- Within the window resizing area to the top-left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED     :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED         :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL           :
//--- Within the window resizing area to the top-right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED    :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL          :
//--- Within the window resizing area at the bottom left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED  :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED      :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL        :
//--- Within the window resizing area at the bottom-right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED     :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL       :
//--- Within the control area
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED             :
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED                 :
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL                   :
        break;
      //--- MOUSE_EVENT_NO_EVENT
      default:
        break;
     }
  }
//+------------------------------------------------------------------+

ここでは、これらのイベントはすべて処理されませんが、必要であれば、いつでも各イベントの下にその処理を追加することができます。

TabHeader.mqh CheckBox.mqhSplitContainer.mqhで既に同様のメソッドの変更がおこなわれています。

矢印ボタンクラスで描画される矢印の色を指定するために、private変数m_arrow_colorを使用しました。ForeColor()メソッドで色を指定すれば、描画されるテキストの色も制御できるので、この変数の使用は余分なものです。そのため、\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowButton.mqh変数とその処理メソッドを削除します

//+------------------------------------------------------------------+
//| Arrow Button object class of WForms controls                     |
//+------------------------------------------------------------------+
class CArrowButton : public CButton
  {
private:
   color             m_arrow_color;                      // Arrow color
protected:
   //--- Draw the arrow
   virtual void      DrawArrow(void){return;}
//--- Protected constructor with object type, chart ID and subwindow
                     CArrowButton(const ENUM_GRAPH_ELEMENT_TYPE type,
                                  CGCnvElement *main_obj,CGCnvElement *base_obj,
                                  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 arrow color
   void              SetArrowColor(const color clr)      { this.m_arrow_color=clr;     }
   color             ArrowColor(void)              const { return this.m_arrow_color;  }
//--- Constructor


また、リモートメソッドの呼び出しを、文字色を扱うメソッドに置き換えます

//+--------------------------------------------+
//| Protected constructor with an object type, |
//| chart ID and subwindow                     |
//+--------------------------------------------+
CArrowButton::CArrowButton(const ENUM_GRAPH_ELEMENT_TYPE type,
                           CGCnvElement *main_obj,CGCnvElement *base_obj,
                           const long chart_id,
                           const int subwindow,
                           const string descript,
                           const int x,
                           const int y,
                           const int w,
                           const int h) : CButton(type,main_obj,base_obj,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(1);
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
  }
//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CArrowButton::CArrowButton(CGCnvElement *main_obj,CGCnvElement *base_obj,
                           const long chart_id,
                           const int subwindow,
                           const string descript,
                           const int x,
                           const int y,
                           const int w,
                           const int h) : CButton(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON);
   this.m_type=OBJECT_DE_TYPE_GWF_HELPER;
   this.SetPaddingAll(0);
   this.SetMarginAll(0);
   this.SetBorderSizeAll(1);
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
  }
//+------------------------------------------------------------------+

\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowRightButton.mqhにあるクラスコンストラクタで、描画する矢印のサイズを 3に設定します

//+--------------------------------------------+
//| Protected constructor with an object type, |
//| chart ID and subwindow                     |
//+--------------------------------------------+
CArrowRightButton::CArrowRightButton(const ENUM_GRAPH_ELEMENT_TYPE type,
                                     CGCnvElement *main_obj,CGCnvElement *base_obj,
                                     const long chart_id,
                                     const int subwindow,
                                     const string descript,
                                     const int x,
                                     const int y,
                                     const int w,
                                     const int h) : CArrowButton(type,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
//--- Set the specified graphical element type for the object and the size of the drawn arrow to 3
   this.SetTypeElement(type);
   this.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,3);
  }
//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CArrowRightButton::CArrowRightButton(CGCnvElement *main_obj,CGCnvElement *base_obj,
                                     const long chart_id,
                                     const int subwindow,
                                     const string descript,
                                     const int x,
                                     const int y,
                                     const int w,
                                     const int h) : CArrowButton(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT);
   this.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,3);
  }
//+------------------------------------------------------------------+

矢印を描画するメソッドでは、呼び出す際のパラメータを変更します。

//+--------------------------------------------+
//| Draw the arrow                             |
//+--------------------------------------------+
void CArrowRightButton::DrawArrow(void)
  {
   CGCnvElement::DrawArrowRight(this.Width()/2-1,this.Height()/2,(int)this.GetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE),this.ForeColor(),this.Opacity());
  }
//+------------------------------------------------------------------+

矢印の中心点として、オブジェクトの中心を渡し(水平方向に1ピクセル左にずらす)、オブジェクトのプロパティで設定した描画矢印のサイズその文字色と不透明度を指定します。

同様の変更は、他の矢印ボタンオブジェクトのクラスであるArrowLeftButton.mqhArrowDownButton.mqhArrowUpButton.mqhでも既におこなわれています。

スクロールバー領域の座標やサイズの設定を簡略化するために、フォームオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\Form.mqhファイルに、publicメソッドを追加します

//--- Set the frame size (1) to the left, (2) at the top, (3) to the right, (4) at the bottom and (5) on all sides
   virtual void      SetBorderSizeLeft(const uint value)       { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_LEFT,value);        }
   virtual void      SetBorderSizeTop(const uint value)        { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_TOP,value);         }
   virtual void      SetBorderSizeRight(const uint value)      { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_RIGHT,value);       }
   virtual void      SetBorderSizeBottom(const uint value)     { this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_BOTTOM,value);      }

//--- Set the (1) X, (2) Y coordinates, (3) width and (4) height of the element scrolling right area
   void              SetScrollAreaRightX(const int value)      { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT,value);     }
   void              SetScrollAreaRightY(const int value)      { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT,value);     }
   void              SetScrollAreaRightWidth(const int value)  { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT,value); }
   void              SetScrollAreaRightHeight(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT,value);}
//--- Set the (1) X, (2) Y coordinates, (3) width and (4) height of the element scrolling lower area
   void              SetScrollAreaBottomX(const int value)     { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM,value);    }
   void              SetScrollAreaBottomY(const int value)     { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM,value);    }
   void              SetScrollAreaBottomWidth(const int value) { this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM,value);}
   void              SetScrollAreaBottomHeight(const int value){ this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM,value);}

//--- Update the coordinates (shift the canvas)
   virtual bool      Move(const int x,const int y,const bool redraw=false);

フォームに対するマウスの状態を設定し返すメソッドでは、マウスカーソルの位置を確認し、フォームの各領域の座標と比較し、その状態のフラグを変数に設定します。さらに、これらのフラグを基に、オブジェクトに対するマウスカーソルの大まかな状態を形成します。メソッドにコードブロックを追加し、要素のサイズを変更するためにドラッグする際にマウスでオブジェクトの端をつかむことができる領域:で、スクロールバーと境界に対するカーソルの位置を追跡できるようにします。

//+------------------------------------------------------------------+
//| 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)
  {
//--- Data location in the ushort value of the button status
   //---------------------------------------------------------------------------
   //   bit    |    byte   |            state            |    dec    |   hex   |
   //---------------------------------------------------------------------------
   //    0     |     0     | left mouse button           |     1     |    1    |
   //---------------------------------------------------------------------------
   //    1     |     0     | right mouse button          |     2     |    2    |
   //---------------------------------------------------------------------------
   //    2     |     0     | SHIFT key                   |     4     |    4    |
   //---------------------------------------------------------------------------
   //    3     |     0     | CTRL key                    |     8     |    8    |
   //---------------------------------------------------------------------------
   //    4     |     0     | middle mouse button         |    16     |   10    |
   //---------------------------------------------------------------------------
   //    5     |     0     | 1 add. mouse button         |    32     |   20    |
   //---------------------------------------------------------------------------
   //    6     |     0     | 2 add. mouse button         |    64     |   40    |
   //---------------------------------------------------------------------------
   //    7     |     0     | scrolling the wheel         |    128    |   80    |
   //---------------------------------------------------------------------------
   //---------------------------------------------------------------------------
   //    0     |     1     | cursor inside the form      |    256    |   100   |
   //---------------------------------------------------------------------------
   //    1     |     1     | cursor inside active area   |    512    |   200   |
   //---------------------------------------------------------------------------
   //    2     |     1     | cursor in the control area  |   1024    |   400   |
   //---------------------------------------------------------------------------
   //    3     |     1     | cursor in the scrolling area|   2048    |   800   |
   //---------------------------------------------------------------------------
   //    4     |     1     | cursor at the left edge     |   4096    |  1000   |
   //---------------------------------------------------------------------------
   //    5     |     1     | cursor at the bottom edge   |   8192    |  2000   |
   //---------------------------------------------------------------------------
   //    6     |     1     | cursor at the right edge    |   16384   |  4000   |
   //---------------------------------------------------------------------------
   //    7     |     1     | cursor at the top edge      |   32768   |  8000   |
   //---------------------------------------------------------------------------
//--- 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 the cursor is inside the scroll area, set bit 11 "cursor inside the scroll area"
      if(CGCnvElement::CursorInsideScrollRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()) || CGCnvElement::CursorInsideScrollBottomArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
         this.m_mouse_state_flags |= (0x0001<<11);
      //--- otherwise, remove the "cursor inside the scroll area" bit
      else this.m_mouse_state_flags &=0xF7FF;
      
      //--- If the cursor is on the upper left corner, set bit 15 "cursor on the upper side" and bit 12 "cursor on the left side"
      if(CGCnvElement::CursorInsideResizeTopLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
        {
         this.m_mouse_state_flags |= (0x0001<<15);
         this.m_mouse_state_flags |= (0x0001<<12);
        }
      //--- otherwise, check "cursor on the left face" and "cursor on the top face" separately
      else
        {
         //--- If the cursor is on the left side, set bit 12 "cursor on the left face"
         if(CGCnvElement::CursorInsideResizeLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
            this.m_mouse_state_flags |= (0x0001<<12);
         //--- otherwise, remove the "cursor on the left face" bit
         else this.m_mouse_state_flags &=0xEFFF;
         //--- If the cursor is on the top edge, set bit 15 "cursor on the top face"
         if(CGCnvElement::CursorInsideResizeTopArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
            this.m_mouse_state_flags |= (0x0001<<15);
         //--- otherwise, remove the "cursor on the top face" bit
         else this.m_mouse_state_flags &=0x7FFF;
        }
      
      //--- If the cursor is on the upper left corner, set bit 15 "cursor on the upper face" and bit 12 "cursor on the left face"
      if(CGCnvElement::CursorInsideResizeTopRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
        {
         this.m_mouse_state_flags |= (0x0001<<15);
         this.m_mouse_state_flags |= (0x0001<<14);
        }
      //--- otherwise, check "cursor on the left face" and "cursor on the top face" separately
      else
        {
         //--- If the cursor is on the left side, set bit 12 "cursor on the right face"
         if(CGCnvElement::CursorInsideResizeRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
            this.m_mouse_state_flags |= (0x0001<<14);
         //--- otherwise, remove the "cursor on the right face" bit
         else this.m_mouse_state_flags &=0xBFFF;
         //--- If the cursor is on the top edge, set bit 15 "cursor on the top face"
         if(CGCnvElement::CursorInsideResizeTopArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
            this.m_mouse_state_flags |= (0x0001<<15);
         //--- otherwise, remove the "cursor on the top face" bit
         else this.m_mouse_state_flags &=0x7FFF;
        }
      
      //--- If the cursor is on the lower left corner, set bit 13 "cursor on the lower face" and bit 12 "cursor on the left face"
      if(CGCnvElement::CursorInsideResizeBottomLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
        {
         this.m_mouse_state_flags |= (0x0001<<13);
         this.m_mouse_state_flags |= (0x0001<<12);
        }
      //--- otherwise, check "cursor on the left face" and "cursor on the lower face" separately
      else
        {
         //--- If the cursor is on the left side, set bit 12 "cursor on the left face"
         if(CGCnvElement::CursorInsideResizeLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
            this.m_mouse_state_flags |= (0x0001<<12);
         //--- otherwise, remove the "cursor on the left face" bit
         else this.m_mouse_state_flags &=0xEFFF;
         //--- If the cursor is on the lower side, set bit 13 "cursor on the lower face"
         if(CGCnvElement::CursorInsideResizeLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
            this.m_mouse_state_flags |= (0x0001<<13);
         //--- otherwise, remove the "cursor on the lower face" bit
         else this.m_mouse_state_flags &=0xDFFF;
        }
      
      //--- If the cursor is on the lower right corner, set bit 13 "cursor on the lower face" and bit 14 "cursor on the right face"
      if(CGCnvElement::CursorInsideResizeBottomRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
        {
         this.m_mouse_state_flags |= (0x0001<<13);
         this.m_mouse_state_flags |= (0x0001<<14);
        }
      //--- otherwise, check "cursor on the right face" and "cursor on the lower face" separately
      else
        {
         //--- If the cursor is on the left side, set bit 12 "cursor on the right face"
         if(CGCnvElement::CursorInsideResizeRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
            this.m_mouse_state_flags |= (0x0001<<14);
         //--- otherwise, remove the "cursor on the right face" bit
         else this.m_mouse_state_flags &=0xBFFF;
         //--- If the cursor is on the lower side, set bit 13 "cursor on the lower face"
         if(CGCnvElement::CursorInsideResizeLeftArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
            this.m_mouse_state_flags |= (0x0001<<13);
         //--- otherwise, remove the "cursor on the lower face" bit
         else this.m_mouse_state_flags &=0xDFFF;
        }
      
      //--- If one of the three mouse buttons is pressed, check the location of the cursor in the form areas and
      //--- return the appropriate value of the pressed key
      if((this.m_mouse_state_flags & 0x0001)!=0 || (this.m_mouse_state_flags & 0x0002)!=0 || (this.m_mouse_state_flags & 0x0010)!=0)
        {
         //--- If the cursor is inside the form
         if((this.m_mouse_state_flags & 0x0100)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_FORM_PRESSED;
         //--- If the cursor is inside the active area of the form
         if((this.m_mouse_state_flags & 0x0200)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED;
         //--- If the cursor is inside the form control area
         if((this.m_mouse_state_flags & 0x0400)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED;
            
         //--- If the cursor is inside the form scrolling area
         if((this.m_mouse_state_flags & 0x0800)!=0)
           {
            //--- If above the right area
            if(CGCnvElement::CursorInsideScrollRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED;
            //--- otherwise, above the bottom one
            else
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED;
           }
            
         //--- If there are cursor flags on the top and left faces
         if((this.m_mouse_state_flags & 0x8000)!=0 && (this.m_mouse_state_flags & 0x1000)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED;
         //--- Check the cursor flags on the top and left faces separately
         else
           {
            //--- If the cursor is on the top face
            if((this.m_mouse_state_flags & 0x8000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED;
            //--- If the cursor is on the left face
            if((this.m_mouse_state_flags & 0x1000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED;
           }
         //--- If there are cursor flags on the top and right faces
         if((this.m_mouse_state_flags & 0x8000)!=0 && (this.m_mouse_state_flags & 0x4000)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED;
         //--- Check the cursor flags on the top and right faces separately
         else
           {
            //--- If the cursor is on the top face
            if((this.m_mouse_state_flags & 0x8000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED;
            //--- If the cursor is on the right face
            if((this.m_mouse_state_flags & 0x4000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED;
           }
         
         //--- If there are cursor flags on the bottom and left faces
         if((this.m_mouse_state_flags & 0x2000)!=0 && (this.m_mouse_state_flags & 0x1000)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED;
         //--- Check the cursor flags on the bottom and left faces separately
         else
           {
            //--- If the cursor is on the bottom face
            if((this.m_mouse_state_flags & 0x2000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED;
            //--- If the cursor is on the left face
            if((this.m_mouse_state_flags & 0x1000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED;
           }
         //--- If there are cursor flags on the bottom and right faces
         if((this.m_mouse_state_flags & 0x2000)!=0 && (this.m_mouse_state_flags & 0x4000)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED;
         //--- Check the cursor flags on the bottom and right faces separately
         else
           {
            //--- If the cursor is on the bottom face
            if((this.m_mouse_state_flags & 0x2000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED;
            //--- If the cursor is on the right face
            if((this.m_mouse_state_flags & 0x4000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_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, control or form area)
         //--- If the cursor is inside the form
         if((this.m_mouse_state_flags & 0x0100)!=0)
           {
            //--- If the mouse wheel is being scrolled
            if((this.m_mouse_state_flags & 0x0080)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_FORM_WHEEL;
            else
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED;
           }
         //--- If the cursor is inside the active area of the form
         if((this.m_mouse_state_flags & 0x0200)!=0)
           {
            //--- If the mouse wheel is being scrolled
            if((this.m_mouse_state_flags & 0x0080)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL;
            else
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED;
           }
         //--- If the cursor is inside the form control area
         if((this.m_mouse_state_flags & 0x0400)!=0)
           {
            //--- If the mouse wheel is being scrolled
            if((this.m_mouse_state_flags & 0x0080)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL;
            else
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED;
           }
           
           
         //--- If the cursor is inside the form scrolling area
         if((this.m_mouse_state_flags & 0x0800)!=0)
           {
            //--- If above the right area
            if(CGCnvElement::CursorInsideScrollRightArea(this.m_mouse.CoordX(),this.m_mouse.CoordY()))
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED;
            //--- otherwise, above the bottom one
            else
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED;
           }
            
         //--- If there are cursor flags on the top and left faces
         if((this.m_mouse_state_flags & 0x8000)!=0 && (this.m_mouse_state_flags & 0x1000)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED;
         //--- Check the cursor flags on the top and left faces separately
         else
           {
            //--- If the cursor is on the top face
            if((this.m_mouse_state_flags & 0x8000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED;
            //--- If the cursor is on the left face
            if((this.m_mouse_state_flags & 0x1000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED;
           }
         //--- If there are cursor flags on the top and right faces
         if((this.m_mouse_state_flags & 0x8000)!=0 && (this.m_mouse_state_flags & 0x4000)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED;
         //--- Check the cursor flags on the top and right faces separately
         else
           {
            //--- If the cursor is on the top face
            if((this.m_mouse_state_flags & 0x8000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED;
            //--- If the cursor is on the right face
            if((this.m_mouse_state_flags & 0x4000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED;
           }
         
         //--- If there are cursor flags on the bottom and left faces
         if((this.m_mouse_state_flags & 0x2000)!=0 && (this.m_mouse_state_flags & 0x1000)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED;
         //--- Check the cursor flags on the bottom and left faces separately
         else
           {
            //--- If the cursor is on the bottom face
            if((this.m_mouse_state_flags & 0x2000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED;
            //--- If the cursor is on the left face
            if((this.m_mouse_state_flags & 0x1000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED;
           }
         //--- If there are cursor flags on the bottom and right faces
         if((this.m_mouse_state_flags & 0x2000)!=0 && (this.m_mouse_state_flags & 0x4000)!=0)
            this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED;
         //--- Check the cursor flags on the bottom and right faces separately
         else
           {
            //--- If the cursor is on the bottom face
            if((this.m_mouse_state_flags & 0x2000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED;
            //--- If the cursor is on the right face
            if((this.m_mouse_state_flags & 0x4000)!=0)
               this.m_mouse_form_state=MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_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;
  }
//+------------------------------------------------------------------+

すべてのコードブロックは詳細にコメントされており、実際、その中ではすべてがシンプルです。たとえば、スクロールなどの領域の座標に対するカーソルの座標の位置を確認し、カーソルが領域内にあれば、適切なフラグを設定しています。そうでない場合は、フラグを削除します。フラグをチェックして設定した結果、マウスカーソルの位置を決定するために使用するフラグのセットが出来上がりました。オブジェクトの上面と右面に位置するフラグが設定されている場合、カーソルは右上にあることを示します。そのため、それぞれのフラグを別々に書き込むにはushort値のビットが足りないため、フラグを結合する必要があるのです。

マウスイベントハンドラで、スクロール領域内のカーソルを見つけるためのイベント処理メソッドの呼び出しを変更します。この領域は2つあるので、スクロール領域にあるマウスの状態の名前を変更しました。これで、カーソルが右と上のどちらのスクロールバー上にあるか、正確に表示されるようになりました。

//+--------------------------------------------+
//| 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 to the right, the mouse buttons are not clicked
      case MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED :  this.MouseScrollAreaNotPressedHandler(id,lparam,dparam,sparam);break;
      //--- The cursor is within the window scrolling area to the right, the mouse button (any) is clicked
      case MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_PRESSED     :  this.MouseScrollAreaPressedHandler(id,lparam,dparam,sparam);   break;
      //--- The cursor is within the window scrolling area to the right, the mouse wheel is being scrolled
      case MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_WHEEL       :  this.MouseScrollAreaWhellHandler(id,lparam,dparam,sparam);     break;
      
      //--- The cursor is within the window scrolling area at the bottom, the mouse buttons are not clicked
      case MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED:  this.MouseScrollAreaNotPressedHandler(id,lparam,dparam,sparam);break;
      //--- The cursor is within the window scrolling area at the bottom, the mouse button (any) is clicked
      case MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_PRESSED    :  this.MouseScrollAreaPressedHandler(id,lparam,dparam,sparam);   break;
      //--- The cursor is within the window scrolling area at the bottom, the mouse wheel is being scrolled
      case MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_WHEEL      :  this.MouseScrollAreaWhellHandler(id,lparam,dparam,sparam);     break;
      
      //--- The cursor is within the control area, the mouse buttons are not clicked
      case MOUSE_EVENT_INSIDE_CONTROL_AREA_NOT_PRESSED   :  this.MouseControlAreaNotPressedHandler(id,lparam,dparam,sparam);  break;
      //--- The cursor is within the control area, the mouse button (any) is clicked
      case MOUSE_EVENT_INSIDE_CONTROL_AREA_PRESSED       :  this.MouseControlAreaPressedHandler(id,lparam,dparam,sparam);     break;
      //--- The cursor is within the control area, the mouse wheel is being scrolled
      case MOUSE_EVENT_INSIDE_CONTROL_AREA_WHEEL         :  this.MouseControlAreaWhellHandler(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() || !this.Displayed())
      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                           :
//--- Within the active area
      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                 :
//--- Within the scrolling area at the bottom
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED       :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED           :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL             :
//--- Within the scrolling area to the right
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED            :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL              :
//--- Within the window resizing area at the top
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED          :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED              :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_WHEEL                :
//--- Within the window resizing area at the bottom
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED       :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED           :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_WHEEL             :
//--- Within the window resizing area to the left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED         :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED             :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_WHEEL               :
//--- Within the window resizing area to the right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED            :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_WHEEL              :
//--- Within the window resizing area to the top-left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED     :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED         :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL           :
//--- Within the window resizing area to the top-right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED    :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL          :
//--- Within the window resizing area at the bottom left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED  :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED      :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL        :
//--- Within the window resizing area at the bottom-right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED     :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL       :
//--- Within the control area
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED             :
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED                 :
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL                   :
        break;
      //--- MOUSE_EVENT_NO_EVENT
      default:
        break;
     }
  }
//+------------------------------------------------------------------+

イベントメッセージを送信するメソッドで、基本オブジェクト型の受信を修正します。

//+--------------------------------------------+
//| Send a message about the event             |
//+--------------------------------------------+
bool CForm::SendEvent(const long chart_id,const ushort event_id)
  {
   //--- Create the event:
   //--- Get the base and main objects
   CGCnvElement *base=this.GetBase();
   CGCnvElement *main=this.GetMain();
   //--- find the names of the main and base objects
   string name_main=(main!=NULL ? main.Name() : this.IsMain() ? this.Name() : "Lost name of object");
   string name_base=(base!=NULL ? base.Name() : "Lost name of object");
   ENUM_GRAPH_ELEMENT_TYPE base_base_type=(base!=NULL ? (base.GetBase()!=NULL ? base.GetBase().TypeGraphElement() : base.TypeGraphElement()) : this.TypeGraphElement());
   //--- pass the object ID in the event 'long' parameter
   //--- pass the object type in the event 'double' parameter
   //--- in the event 'string' parameter, pass the names of the main, base and current objects separated by ";"
   long lp=this.ID();
   double dp=base_base_type;
   string sp=::StringSubstr(name_main,::StringLen(this.NamePrefix()))+";"+
             ::StringSubstr(name_base,::StringLen(this.NamePrefix()))+";"+
             ::StringSubstr(this.Name(),::StringLen(this.NamePrefix()));
   //--- Send the event of clicking on the control to the control program chart
   bool res=true;
   ::ResetLastError();
   res=::EventChartCustom(chart_id,event_id,lp,dp,sp);
   if(res)
      return true;
   ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_ENQUEUE_EVENT),". ",CMessage::Text(MSG_LIB_SYS_ERROR),": ",CMessage::Text(::GetLastError()));
   return false;
  }
//+------------------------------------------------------------------+

取得に成功した基本オブジェクトがそれ自身の基本オブジェクトを持っている場合その型を取得します。それ以外の場合は、基本オブジェクトの型を取得します。この修正前は、基本オブジェクトが自身の基本オブジェクトを持っていない場合(例えば、基本オブジェクトがメインの場合)、無効なポインタでオブジェクトにアクセスしたため、プログラムがクリティカルエラーで終了していました。現在は修正されています。

前回は、WinFormsの基本オブジェクトクラスのサイズ変更メソッドで、スクロールバーオブジェクトの位置を調整しました。オブジェクトのサイズを変更すると、その辺の座標が変化します。スクロールバーはオブジェクトの右下に結合されているため、必要に応じて座標を調整する必要があります。なぜなら、コンテナオブジェクトだけが添付オブジェクトを含むことができ、コンテナの可視領域に収まらない場合はスクロールが必要になることがあるからです。このような処理は、コンテナオブジェクトのクラスに移しましょう。ここは、それに最も適した場所なのです。

基本WinFormsオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\WForms\WinFormBase.mqhファイルにある、 "Setting new sizes "メソッドにある 新しいサイズを設定するメソッドで、スクロールバーのサイズと座標を調整するコードブロックを削除します

//+--------------------------------------------+
//| Set the new size for the current object    |
//+--------------------------------------------+
bool CWinFormBase::Resize(const int w,const int h,const bool redraw)
  {
//--- If the object width and height are equal to the passed ones, return 'true'
   if(this.Width()==w && this.Height()==h)
      return true;
//--- Declare the variable with the property change result
   bool res=true;
//--- Save the panel initial size
   int prev_w=this.Width();
   int prev_h=this.Height();
//--- Set the property change result to the 'res' variable
//--- (if the property value is not equal to the passed value)
   if(this.Width()!=w)
      res &=this.SetWidth(w);
   if(this.Height()!=h)
      res &=this.SetHeight(h);
   if(!res)
      return false;
//--- Get the vertical scrollbar and
   CWinFormBase *scroll_v=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0);
   if(scroll_v!=NULL)
     {
      //--- change the vertical size to the size of the container workspace
      scroll_v.Resize(scroll_v.Width(),this.Height()-this.BorderSizeTop()-this.BorderSizeBottom(),false);
      //--- Get a button object with the down arrow from the vertical scrollbar object
      CWinFormBase *arr_d=scroll_v.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0);
      //--- If the button has been received
      if(arr_d!=NULL)
        {
         //--- Move it to the bottom edge of the vertical scrollbar
         if(arr_d.Move(arr_d.CoordX(),scroll_v.BottomEdge()-2*arr_d.Height()))
           {
            arr_d.SetCoordXRelative(arr_d.CoordX()-scroll_v.CoordX());
            arr_d.SetCoordYRelative(arr_d.CoordY()-scroll_v.CoordY());
           }
        }
     }
//--- Get the horizontal scrollbar and
   CWinFormBase *scroll_h=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0);
   if(scroll_h!=NULL)
     {
      //--- change the horizontal size to the size of the container workspace
      scroll_h.Resize(this.Width()-this.BorderSizeLeft()-this.BorderSizeRight(),scroll_h.Height(),false);
      //--- Get a button object with the right arrow from the horizontal scrollbar object
      CWinFormBase *arr_r=scroll_h.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0);
      //--- If the button has been received
      if(arr_r!=NULL)
        {
         //--- Move it to the right edge of the horizontal scrollbar
         if(arr_r.Move(scroll_h.RightEdge()-2*arr_r.Width(),arr_r.CoordY()))
           {
            arr_r.SetCoordXRelative(arr_r.CoordX()-scroll_h.CoordX());
            arr_r.SetCoordYRelative(arr_r.CoordY()-scroll_h.CoordY());
           }
        }
     }
//--- Calculate the value, by which the size should be changed
   int excess_w=this.Width()-prev_w;
   int excess_h=this.Height()-prev_h;
//--- Get the "Shadow" object
   CShadowObj *shadow=this.GetShadowObj();
//--- If the object has a shadow and the "Shadow" object has been received,
   if(this.IsShadow() && shadow!=NULL)
     {
      //--- save shadow shifts by X and Y,
      int x=shadow.CoordXRelative();
      int y=shadow.CoordYRelative();
      //--- set the shadow new width and height
      res &=shadow.SetWidth(shadow.Width()+excess_w);
      res &=shadow.SetHeight(shadow.Height()+excess_h);
      //--- If the res variable contains 'false',
      //--- there was a resize error - return 'false'
      if(!res)
         return false;
      //--- If there is no need to redraw, remove the shadow
      if(!redraw)
         shadow.Erase();
      //--- Save the previously set shadow shift values relative to the panel
      shadow.SetCoordXRelative(x);
      shadow.SetCoordYRelative(y);
     }
//--- Redraw the entire element with new size
   if(redraw)
      this.Redraw(true);
//--- All is successful - return 'true'
   return true;
  }
//+------------------------------------------------------------------+

このコードブロックは、コンテナオブジェクトのクラスに完全に移動されます。

要素の整数プロパティの説明を返すメソッドに、新しいグラフィック要素のプロパティの説明を返すコードブロックを追加します

//+------------------------------------------------------------------+
//| 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_ENABLED                      ?  CMessage::Text(MSG_CANV_ELEMENT_PROP_ENABLED)+
         (only_prop ? "" : !this.SupportProperty(property)     ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)(bool)this.GetProperty(property)
         )  :
      property==CANV_ELEMENT_PROP_RESIZABLE                    ?  CMessage::Text(MSG_CANV_ELEMENT_PROP_RESIZABLE)+
         (only_prop ? "" : !this.SupportProperty(property)     ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)(bool)this.GetProperty(property)
         )  :
      property==CANV_ELEMENT_PROP_FORE_COLOR                   ?  CMessage::Text(MSG_CANV_ELEMENT_PROP_FORE_COLOR)+
         (only_prop ? "" : !this.SupportProperty(property)     ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+ColorToString((color)this.GetProperty(property),true)
         )  :

      //---...
      //---...

      property==CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED ?  CMessage::Text(MSG_CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED)+
         (only_prop ? "" : !this.SupportProperty(property)     ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE            ?  CMessage::Text(MSG_CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE)+
         (only_prop ? "" : !this.SupportProperty(property)     ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+


ScrollBarコントロールのキャプチャ領域クラス

前回は、ScrollBarオブジェクトを作成する際に、そのスライダーにボタンオブジェクトクラスを使用しました。実際、このオブジェクトはこのような用途に適しています。しかし、イベントを処理する場合、正しいハンドラを呼び出すために、処理されるオブジェクトの型を知っておく必要があります。ボタンオブジェクトにはそのようなハンドラがありますが、スライダーには適していません。スライダーはずらす必要があります。そのシフトの間、スクロールバーによって可視範囲が制御されているオブジェクトの座標は再計算される必要があります。そこで、ボタンオブジェクトのクラスを元に、新しいクラスを作成することにします。キャプチャ領域オブジェクトのクラスです。そのオブジェクトの中に、必要なマウスイベントのハンドラを自作することができます。

\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ライブラリフォルダで、CScrollBarThumbクラスのファイルScrollBarThumb.mqhを新規作成します。

クラスはボタンオブジェクトクラスから派生するので、そのファイルを作成されたクラスファイルにインクルードする必要があります。

//+------------------------------------------------------------------+
//|                                               ScrollBarThumb.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+--------------------------------------------+
//| Include files                              |
//+--------------------------------------------+
#include "..\Common Controls\Button.mqh"
//+--------------------------------------------+
//| Label object class of WForms controls      |
//+--------------------------------------------+
class CScrollBarThumb : public CButton
  {
  }

クラスのprotectedセクションでprotectedコンストラクタを宣言、publicセクションでパラメトリックコンストラクタを宣言します。

//+--------------------------------------------+
//| Label object class of WForms controls      |
//+--------------------------------------------+
class CScrollBarThumb : public CButton
  {
private:

protected:
//--- Protected constructor with object type, chart ID and subwindow
                     CScrollBarThumb(const ENUM_GRAPH_ELEMENT_TYPE type,
                                     CGCnvElement *main_obj,CGCnvElement *base_obj,
                                     const long chart_id,
                                     const int subwindow,
                                     const string descript,
                                     const int x,
                                     const int y,
                                     const int w,
                                     const int h);
                             
public:
//--- Constructor
                     CScrollBarThumb(CGCnvElement *main_obj,CGCnvElement *base_obj,
                                     const long chart_id,
                                     const int subwindow,
                                     const string descript,
                                     const int x,
                                     const int y,
                                     const int w,
                                     const int h);
  };
//+------------------------------------------------------------------+

今のところ、このオブジェクトに必要なのはそれだけです。その型はクラスのコンストラクタで設定され、キャプチャ領域オブジェクトというユニークなものになります。

以下はprotectedコンストラクタです。

//+--------------------------------------------+
//| Protected constructor with an object type, |
//| chart ID and subwindow                     |
//+--------------------------------------------+
CScrollBarThumb::CScrollBarThumb(const ENUM_GRAPH_ELEMENT_TYPE type,
                                 CGCnvElement *main_obj,CGCnvElement *base_obj,
                                 const long chart_id,
                                 const int subwindow,
                                 const string descript,
                                 const int x,
                                 const int y,
                                 const int w,
                                 const int h) : CButton(type,main_obj,base_obj,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.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true);
   this.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN);
   this.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER);
   this.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true);
   this.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN);
   this.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER);
  }
//+------------------------------------------------------------------+

コンストラクタは、親クラスのコンストラクタに渡された生成オブジェクトの型を受け取ります。グラフィック要素タイプライブラリグラフィカルオブジェクトタイプはコンストラクタ本体に設定されます。さらに、マウスカーソルで操作する際のさまざまなオブジェクトの状態に対するすべてのデフォルトの色値も設定されています。

以下は、パラメトリックコンストラクタです。

//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CScrollBarThumb::CScrollBarThumb(CGCnvElement *main_obj,CGCnvElement *base_obj,
                                 const long chart_id,
                                 const int subwindow,
                                 const string descript,
                                 const int x,
                                 const int y,
                                 const int w,
                                 const int h) : CButton(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB);
   this.m_type=OBJECT_DE_TYPE_GWF_HELPER;
   this.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true);
   this.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN);
   this.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER);
   this.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true);
   this.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN);
   this.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER);
  }
//+------------------------------------------------------------------+

ここでは、 オブジェクトの型がキャプチャ領域として厳格に設定されることを除いて、すべてがprotectedコンストラクタと同様です。

\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ScrollBar.mqhにあるスクロールバーオブジェクトの抽象クラスを改善してみましょう。

キャプチャ領域オブジェクトクラスファイルをインクルードします。privateセクションで、スクロールバーの幅を格納する変数を宣言し、protectedセクションで、スクロールボタンの大きさを設定するメソッドを宣言します。publicセクションで、スクロールバーの幅を設定して返すために、キャプチャ領域オブジェクトを返すメソッドと、スクロールバーボタンに描かれる矢印の大きさを設定するメソッドを宣言します。

//+------------------------------------------------------------------+
//|                                                    ScrollBar.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+--------------------------------------------+
//| Include files                              |
//+--------------------------------------------+
#include "..\WinFormBase.mqh"
#include "ScrollBarThumb.mqh"
#include "ArrowDownButton.mqh"
#include "ArrowUpButton.mqh"
#include "ArrowLeftButton.mqh"
#include "ArrowRightButton.mqh"
//+--------------------------------------------+
//| CScrollBar object class of WForms controls |
//+--------------------------------------------+
class CScrollBar : public CWinFormBase
  {
private:
   int               m_thickness;         // Scrollbar width (Width - vertical, Height - horizontal)
//--- Create the ArrowButton objects
   virtual void      CreateArrowButtons(const int width,const int height) { return; }
//--- 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);
//--- Calculate the capture area size
   virtual int       CalculateThumbAreaSize(void);
//--- Initialize the element properties
   void              Initialize(void);

protected:
//--- Set the scroll buttons size
   void              SetArrowButtonsSize(const int size);
//--- Create the capture area object
   virtual void      CreateThumbArea(void);
//--- Protected constructor with object type, chart ID and subwindow
                     CScrollBar(const ENUM_GRAPH_ELEMENT_TYPE type,
                                CGCnvElement *main_obj,CGCnvElement *base_obj,
                                const long chart_id,
                                const int subwindow,
                                const string descript,
                                const int x,
                                const int y,
                                const int w,
                                const int h);
public:
//--- Supported object properties (1) integer, (2) real and (3) string ones
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_INTEGER property) { return true; }
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_DOUBLE property)  { return true; }
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_STRING property)  { return true; }
   
//--- Return the capture area object
   CScrollBarThumb  *GetThumb(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,0);  }
   
//--- (1) Set and (2) return the scrollbar width
   virtual void      SetThickness(const int value);
   int               Thickness(void)                        const { return this.m_thickness; }
//--- Set the size of drawn arrows on scroll buttons
   void              SetArrowSize(const uchar size);
   
//--- Constructor
                     CScrollBar(CGCnvElement *main_obj,CGCnvElement *base_obj,
                                const long chart_id,
                                const int subwindow,
                                const string descript,
                                const int x,
                                const int y,
                                const int w,
                                const int h);
//--- Timer
   virtual void      OnTimer(void);
  };
//+------------------------------------------------------------------+

要素プロパティの初期化メソッドに、デフォルトの色値、スクロールバーの幅ボタンと矢印のサイズの設定を追加します。

//+--------------------------------------------+
//| Initialize the element properties          |
//+--------------------------------------------+
void CScrollBar::Initialize(void)
  {
   this.SetBorderSizeAll(1);
   this.SetBorderStyle(FRAME_STYLE_SIMPLE);
   this.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR,true);
   this.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR);
   this.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR);
   this.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR,true);
   this.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR,true);
   this.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_DOWN);
   this.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_OVER);
   this.SetThickness(DEF_CONTROL_SCROLL_BAR_WIDTH);
   this.SetArrowButtonsSize(this.m_thickness);
   this.SetArrowSize(uchar(this.m_thickness<4 ? 1 : this.m_thickness<6 ? 2 : this.m_thickness<8 ? 3 : this.m_thickness<10 ? 4 : this.m_thickness<12 ? 5 : 6));
  }
//+------------------------------------------------------------------+

新しいグラフィックオブジェクトを作成するメソッドで、キャプチャ領域オブジェクトを作成するためのコードブロックを実装します。

//+--------------------------------------------+
//| Create a new graphical object              |
//+--------------------------------------------+
CGCnvElement *CScrollBar::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_SCROLL_BAR_THUMB     :
         element=new CScrollBarThumb(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN    :
         element=new CArrowDownButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP      :
         element=new CArrowUpButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT    :
         element=new CArrowLeftButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT   :
         element=new CArrowRightButton(this.GetMain(),this.GetObject(),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;
  }
//+------------------------------------------------------------------+

これで、オブジェクトは、矢印ボタンオブジェクトに加え、コントロールインターフェイスを作成するためのスライダーも作成できるようになります。

以下は、スクロールバーの幅を設定するメソッドです。

//+--------------------------------------------+
//| Set the scrollbar width                    |
//+--------------------------------------------+
void CScrollBar::SetThickness(const int value)
  {
//--- Depending on the type
   switch(this.TypeGraphElement())
     {
      //--- For the vertical scrollbar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  :
        //--- set the width equal to the value passed to the method and write it as the width of the object
        this.m_thickness=value;
        this.SetWidth(this.m_thickness);
        this.Redraw(false);
        break;
      //--- For the horizontal scroll bar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL:
        //--- set the width equal to the value passed to the method and write it as the height of the object
        this.m_thickness=value;
        this.SetHeight(this.m_thickness);
        this.Redraw(false);
        break;
      default:
        break;
     }
  }
//+------------------------------------------------------------------+

垂直スクロールバーの場合、オブジェクトの幅はバーの幅とみなされます。水平スクロールバーの場合、オブジェクトの幅はその高さになります。このメソッドは、オブジェクトに設定される値を受け取ります。スクロールバーの種類によって、幅と高さのどちらかが設定されます。

以下は、スクロールボタンの大きさを設定するメソッドです。

//+--------------------------------------------+
//| Set the size of the scroll buttons         |
//+--------------------------------------------+
void CScrollBar::SetArrowButtonsSize(const int size)
  {
//--- Declare the pointers to arrow buttons
   CArrowUpButton    *bu=NULL;
   CArrowDownButton  *bd=NULL;
   CArrowLeftButton  *bl=NULL;
   CArrowRightButton *br=NULL;
//--- Depending on the type
   switch(this.TypeGraphElement())
     {
      //--- For the vertical scrollbar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  :
        //--- Get the pointer to the up arrow button and set its size equal to 'size'
        bu=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,0);
        if(bu!=NULL)
           bu.Resize(size,size,false);
        //--- Get the pointer to the down arrow button and set its size equal to 'size'
        bd=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0);
        if(bd!=NULL)
           bd.Resize(size,size,false);
        break;
      //--- For the horizontal scroll bar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL:
        //--- Get the pointer to the left arrow button and set its size equal to 'size'
        bl=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,0);
        if(bl!=NULL)
           bl.Resize(size,size,false);
        //--- Get the pointer to the right arrow button and set its size equal to 'size'
        br=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0);
        if(br!=NULL)
           br.Resize(size,size,false);
        break;
      default:
        break;
     }
  }
//+------------------------------------------------------------------+

スクロールバーオブジェクトのボタンは、同じ辺を持ちます。サイズはメソッドに渡され、オブジェクトの種類に応じて、左/右または上/下ボタンへのポインタを取得し、それらにメソッドに渡されたサイズを設定します(幅と高さの両方について)。

以下は、スクロールボタンに描画される矢印の大きさを設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the size of drawn arrows on scroll buttons                   |
//+------------------------------------------------------------------+
void CScrollBar::SetArrowSize(const uchar size)
  {
//--- Declare the pointers to arrow buttons
   CArrowUpButton    *bu=NULL;
   CArrowDownButton  *bd=NULL;
   CArrowLeftButton  *bl=NULL;
   CArrowRightButton *br=NULL;
//--- Depending on the type
   switch(this.TypeGraphElement())
     {
      //--- For the vertical scrollbar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  :
        //--- Get the pointer to the up arrow button and set its arrow size equal to 'size'
        bu=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,0);
        if(bu!=NULL)
          {
           bu.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size);
           bu.Redraw(false);
          }
        //--- Get the pointer to the down arrow button and set its arrow size equal to 'size'
        bd=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0);
        if(bd!=NULL)
          {
           bd.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size);
           bd.Redraw(false);
          }
        break;
      //--- For the horizontal scroll bar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL:
        //--- Get the pointer to the left arrow button and set its arrow size equal to 'size'
        bl=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,0);
        if(bl!=NULL)
          {
           bl.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size);
           bl.Redraw(false);
          }
        //--- Get the pointer to the right arrow button and set its arrow size equal to 'size'
        br=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0);
        if(br!=NULL)
          {
           br.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size);
           br.Redraw(false);
          }
        break;
      default:
        break;
     }
  }
//+------------------------------------------------------------------+

スクロールバーの種類に応じて、対応するボタンへのポインタを取得し、それらに対応する描画された矢印のサイズを設定し、オブジェクトを再描画して変更を表示します。

スクロールバースライダーは、コンテナの可視範囲内でコンテナの内容をスクロールさせるために使用されます。マウスでスライダーを動かす場合、スクロールバーからはみ出さないように、移動範囲をスクロールにも使われる矢印ボタンに限定する必要があります。垂直スクロールバーオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ScrollBarVertical.mqhキャプチャ領域オブジェクトクラスファイルを追加します。publicセクションで、矢印ボタンへのポインタを返すメソッドを実装し、イベントハンドラを宣言します。

//+------------------------------------------------------------------+
//|                                            ScrollBarVertical.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+--------------------------------------------+
//| Include files                              |
//+--------------------------------------------+
#include "ScrollBarThumb.mqh"
#include "ArrowDownButton.mqh"
#include "ArrowUpButton.mqh"
#include "ScrollBar.mqh"
//+------------------------------------------------------------------+
//| CScrollBarVertical object class of WForms controls               |
//+------------------------------------------------------------------+
class CScrollBarVertical : public CScrollBar
  {
private:
//--- Create the ArrowButton objects
   virtual void      CreateArrowButtons(const int width,const int height);
//--- Calculate the capture area size
   virtual int       CalculateThumbAreaSize(void);

protected:
//--- Protected constructor with object type, chart ID and subwindow
                     CScrollBarVertical(const ENUM_GRAPH_ELEMENT_TYPE type,
                                        CGCnvElement *main_obj,CGCnvElement *base_obj,
                                        const long chart_id,
                                        const int subwindow,
                                        const string descript,
                                        const int x,
                                        const int y,
                                        const int w,
                                        const int h);
public:
//--- Supported object properties (1) integer, (2) real and (3) string ones
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_INTEGER property) { return true; }
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_DOUBLE property)  { return true; }
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_STRING property)  { return true; }
   
//--- Return the button with the (1) up, (2) down arrow
   CArrowUpButton   *GetArrowButtonUp(void)     { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,0);      }
   CArrowDownButton *GetArrowButtonDown(void)   { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0);    }
   
//--- Constructor
                     CScrollBarVertical(CGCnvElement *main_obj,CGCnvElement *base_obj,
                                        const long chart_id,
                                        const int subwindow,
                                        const string descript,
                                        const int x,
                                        const int y,
                                        const int w,
                                        const int h);
//--- Timer
   virtual void      OnTimer(void);
//--- Event handler
   virtual void      OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam);
  };
//+------------------------------------------------------------------+

ArrowButtonオブジェクトを作成するメソッドでは、すべてのボタンとスライダーを作成し、それらへのポインタを取得し、異なるマウス操作の状態に応じた色を設定しています。

//+--------------------------------------------+
//| Create the ArrowButton objects             |
//+--------------------------------------------+
void CScrollBarVertical::CreateArrowButtons(const int width,const int height)
  {
//--- Set the size of the buttons equal to the width of the scrollbar without the size of its frame
   int size=this.Thickness()-this.BorderSizeLeft()-this.BorderSizeRight();
//--- Create the buttons with up and down arrows and the area capture object. The arrow size is set to 2
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,  0,0,size,size,this.BackgroundColor(),255,true,false);
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0,this.BottomEdge()-this.BorderSizeBottom()-2*size,size,size,this.BackgroundColor(),255,true,false);
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,0,this.Height()/2-height,size,30,CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,255,true,false);
   this.SetArrowSize(2);
//--- Get the pointer to the up arrow button and set the colors of its various states for it
   CArrowUpButton *bu=this.GetArrowButtonUp();
   if(bu!=NULL)
     {
      bu.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR,true);
      bu.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN);
      bu.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER);
      bu.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR,true);
      bu.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN);
      bu.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER);
     }
//--- Get the pointer to the down arrow button and set the colors of its various states for it
   CArrowDownButton *bd=this.GetArrowButtonDown();
   if(bd!=NULL)
     {
      bd.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR,true);
      bd.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN);
      bd.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER);
      bd.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR,true);
      bd.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN);
      bd.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER);
     }
//--- Get the pointer to the capture area object and set the colors of its various states for it
   CScrollBarThumb *th=this.GetThumb();
   if(th!=NULL)
     {
      th.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true);
      th.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_BORDER_COLOR,true);
      th.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN);
      th.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER);
      th.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true);
      th.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN);
      th.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER);
     }
  }
//+------------------------------------------------------------------+

イベントハンドラで、プログレスバースライダーオブジェクトを移動させるとき、スクロールバーの端にあるボタンで制限されるべき座標を計算します。

//+--------------------------------------------+
//| Event handler                              |
//+--------------------------------------------+
void CScrollBarVertical::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 an object movement
   if(id==WF_CONTROL_EVENT_MOVING)
     {
      //--- Get the pointer to the capture area object
      CScrollBarThumb *thumb=this.GetThumb();
      if(thumb==NULL)
         return;
      //--- Get the pointer to the button object with the up arrow
      CArrowUpButton *buttu=this.GetArrowButtonUp();
      if(buttu==NULL)
         return;
      //--- Get the pointer to the button object with the down arrow
      CArrowDownButton *buttd=this.GetArrowButtonDown();
      if(buttd==NULL)
         return;
      //--- Declare the variables for the coordinates of the capture area
      int x=(int)lparam;
      int y=(int)dparam;
      //--- Set the X coordinate equal to the X coordinate of the control element
      x=this.CoordX()+this.BorderSizeLeft();
      //--- Adjust the Y coordinate so that the capture area does not go beyond the control, taking into account the arrow buttons
      if(y<buttu.BottomEdge())
        y=buttu.BottomEdge();
      if(y>buttd.CoordY()-thumb.Height())
        y=buttd.CoordY()-thumb.Height();
      //--- If the capture area object is shifted by the calculated coordinates
      if(thumb.Move(x,y,true))
        {
         //--- set the object relative coordinates
         thumb.SetCoordXRelative(thumb.CoordX()-this.CoordX());
         thumb.SetCoordYRelative(thumb.CoordY()-this.CoordY());
         ::ChartRedraw(this.ChartID());
        }
     }
  }
//+------------------------------------------------------------------+

ScrollBarHorisontal.mqhファイルの水平スクロールバーオブジェクトのクラスにも同様の改良が施されています。

ボタンとスライダーのオブジェクトを作成する方法とイベントハンドラが上記の方法と異なるのは、他の種類のボタンへのポインタとスライダー移動の他の軸の制限だけです。

//+--------------------------------------------+
//| Create the ArrowButton objects             |
//+--------------------------------------------+
void CScrollBarHorisontal::CreateArrowButtons(const int width,const int height)
  {
   int size=this.Thickness()-this.BorderSizeTop()-this.BorderSizeBottom();
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,  0,0,size,size,this.BackgroundColor(),255,true,false);
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,this.RightEdge()-this.BorderSizeRight()-2*size,0,size,size,this.BackgroundColor(),255,true,false);
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,this.Width()/2-width,0,30,size,CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,255,true,false);
   this.SetArrowSize(2);
   CArrowLeftButton *bl=this.GetArrowButtonLeft();
   if(bl!=NULL)
     {
      bl.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR,true);
      bl.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN);
      bl.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER);
      bl.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR,true);
      bl.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN);
      bl.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER);
     }
   CArrowRightButton *br=this.GetArrowButtonRight();
   if(br!=NULL)
     {
      br.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_COLOR,true);
      br.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_DOWN);
      br.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_MOUSE_OVER);
      br.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_COLOR,true);
      br.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_DOWN);
      br.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_BUTT_FORE_MOUSE_OVER);
     }
   CScrollBarThumb *th=this.GetThumb();
   if(th!=NULL)
     {
      th.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true);
      th.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_BORDER_COLOR,true);
      th.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_DOWN);
      th.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER);
      th.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true);
      th.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_DOWN);
      th.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_MOUSE_OVER);
     }
  }
//+------------------------------------------------------------------+

//+--------------------------------------------+
//| Event handler                              |
//+--------------------------------------------+
void CScrollBarHorisontal::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 an object movement
   if(id==WF_CONTROL_EVENT_MOVING)
     {
      //--- Get the pointer to the capture area object
      CScrollBarThumb *thumb=this.GetThumb();
      if(thumb==NULL)
         return;
      //---  Get the pointer to the button object with the left arrow
      CArrowLeftButton *buttl=this.GetArrowButtonLeft();
      if(buttl==NULL)
         return;
      //--- Get the pointer to the button object with the right arrow
      CArrowRightButton *buttr=this.GetArrowButtonRight();
      if(buttr==NULL)
         return;
      //--- Declare the variables for the coordinates of the capture area
      int x=(int)lparam;
      int y=(int)dparam;
      //--- Set the Y coordinate equal to the Y coordinate of the control element
      y=this.CoordY()+this.BorderSizeTop();
      //--- Adjust the X coordinate so that the capture area does not go beyond the control, taking into account the arrow buttons
      if(x<buttl.RightEdge())
        x=buttl.RightEdge();
      if(x>buttr.CoordX()-thumb.Width())
        x=buttr.CoordX()-thumb.Width();
      //--- If the capture area object is shifted by the calculated coordinates
      if(thumb.Move(x,y,true))
        {
         //--- set the object relative coordinates
         thumb.SetCoordXRelative(thumb.CoordX()-this.CoordX());
         thumb.SetCoordYRelative(thumb.CoordY()-this.CoordY());
         ::ChartRedraw(this.ChartID());
        }
     }
  }
//+------------------------------------------------------------------+

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

publicセクションで、オブジェクトのサイズを変更するための仮想メソッドを宣言します

//--- Set the (1) X, (2) Y coordinates, (3) element width and (4) height
   virtual bool      SetCoordX(const int coord_x)              { return CGCnvElement::SetCoordX(coord_x);   }
   virtual bool      SetCoordY(const int coord_y)              { return CGCnvElement::SetCoordY(coord_y);   }
   virtual bool      SetWidth(const int width)                 { return CGCnvElement::SetWidth(width);      }
   virtual bool      SetHeight(const int height)               { return CGCnvElement::SetHeight(height);    }
   
//--- Set the new size for the (1) current object and (2) the object specified by index
   virtual bool      Resize(const int w,const int h,const bool redraw);
   
//--- Create a new attached element

このメソッドは、ベースとなるWinFormsオブジェクトクラスから削除されたコードブロックを受け取ります。

クラスのコンストラクタで、ライブラリ用にデフォルトで実装されている作成済みスクロールバーのサイズを設定し、下部スクロールバーの領域を設定します。右スクロールバーの領域は、まず下のバーの機能を洗練させる必要があるので、設定しないことにしています。すると、結果は右のスクロールバーオブジェクトに移動します。

//+--------------------------------------------+
//| Protected constructor with an object type, |
//| chart ID and subwindow                     |
//+--------------------------------------------+
CContainer::CContainer(const ENUM_GRAPH_ELEMENT_TYPE type,
                       CGCnvElement *main_obj,CGCnvElement *base_obj,
                       const long chart_id,
                       const int subwindow,
                       const string descript,
                       const int x,
                       const int y,
                       const int w,
                       const int h) : CWinFormBase(type,main_obj,base_obj,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_CONTAINER;
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
   this.SetFontBoldType(FW_TYPE_NORMAL);
   this.SetMarginAll(3);
   this.SetPaddingAll(0);
   this.SetDockMode(CANV_ELEMENT_DOCK_MODE_NONE,false);
   this.SetBorderStyle(FRAME_STYLE_NONE);
   this.SetAutoScroll(false,false);
   this.SetAutoScrollMarginAll(0);
   this.SetAutoSize(false,false);
   this.SetAutoSizeMode(CANV_ELEMENT_AUTO_SIZE_MODE_GROW,false);
   this.Initialize();
   this.SetCoordXInit(x);
   this.SetCoordYInit(y);
   this.SetWidthInit(w);
   this.SetHeightInit(h);
   this.CreateScrollBars(DEF_CONTROL_SCROLL_BAR_WIDTH);
   this.SetScrollAreaBottomX(this.CoordX());
   this.SetScrollAreaBottomY(this.BottomEdge()-DEF_CONTROL_SCROLL_BAR_WIDTH);
   this.SetScrollAreaBottomHeight(DEF_CONTROL_SCROLL_BAR_WIDTH);
  }
//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CContainer::CContainer(CGCnvElement *main_obj,CGCnvElement *base_obj,
                       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_CONTAINER,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_CONTAINER);
   this.m_type=OBJECT_DE_TYPE_GWF_CONTAINER;
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
   this.SetFontBoldType(FW_TYPE_NORMAL);
   this.SetMarginAll(3);
   this.SetPaddingAll(0);
   this.SetDockMode(CANV_ELEMENT_DOCK_MODE_NONE,false);
   this.SetBorderStyle(FRAME_STYLE_NONE);
   this.SetAutoScroll(false,false);
   this.SetAutoScrollMarginAll(0);
   this.SetAutoSize(false,false);
   this.SetAutoSizeMode(CANV_ELEMENT_AUTO_SIZE_MODE_GROW,false);
   this.Initialize();
   this.SetCoordXInit(x);
   this.SetCoordYInit(y);
   this.SetWidthInit(w);
   this.SetHeightInit(h);
   this.CreateScrollBars(DEF_CONTROL_SCROLL_BAR_WIDTH);
   this.SetScrollAreaBottomX(this.CoordX());
   this.SetScrollAreaBottomY(this.BottomEdge()-DEF_CONTROL_SCROLL_BAR_WIDTH);
   this.SetScrollAreaBottomHeight(DEF_CONTROL_SCROLL_BAR_WIDTH);
  }
//+------------------------------------------------------------------+

添付されたオブジェクトにパラメータを設定するメソッドで、新しく作成されたキャプチャ領域オブジェクトのデフォルトパラメータを設定するコードブロックを記述します。

//+--------------------------------------------+
//| Set parameters for the attached object     |
//+--------------------------------------------+
void CContainer::SetObjParams(CWinFormBase *obj,const color colour)
  {
//--- Set the text color of the object to be the same as that of the base container
   obj.SetForeColor(this.ForeColor(),true);
//--- If the created object is not a container, set the same group for it as the one for its base object
   if(obj.TypeGraphElement()<GRAPH_ELEMENT_TYPE_WF_CONTAINER || obj.TypeGraphElement()>GRAPH_ELEMENT_TYPE_WF_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;
      //--- For "Hint" WinForms object
      case GRAPH_ELEMENT_TYPE_WF_HINT_BASE            :
        obj.SetBackgroundColor(CLR_CANV_NULL,true);
        obj.SetBorderColor(CLR_CANV_NULL,true);
        obj.SetForeColor(CLR_CANV_NULL,true);
        obj.SetOpacity(0,false);
        obj.SetBorderStyle(FRAME_STYLE_NONE);
        break;
      //--- For "HintMoveLeft", "HintMoveRight", "HintMoveUp" and "HintMoveDown" WinForms object 
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT       :
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT      :
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP         :
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN       :
        obj.SetBackgroundColor(CLR_CANV_NULL,true);
        obj.SetBorderColor(CLR_CANV_NULL,true);
        obj.SetForeColor(CLR_DEF_CONTROL_HINT_FORE_COLOR,true);
        obj.SetOpacity(0,false);
        obj.SetBorderStyle(FRAME_STYLE_NONE);
        break;
      //--- For ToolTip WinForms object
      case GRAPH_ELEMENT_TYPE_WF_TOOLTIP              :
        obj.SetBackgroundColor(CLR_DEF_CONTROL_HINT_BACK_COLOR,true);
        obj.SetBorderColor(CLR_DEF_CONTROL_HINT_BORDER_COLOR,true);
        obj.SetForeColor(CLR_DEF_CONTROL_HINT_FORE_COLOR,true);
        obj.SetBorderStyle(FRAME_STYLE_SIMPLE);
        obj.SetOpacity(0,false);
        obj.SetDisplayed(false);
        obj.Hide();
        break;
      //--- For BarProgressBar WinForms object
      case GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR     :
        obj.SetBackgroundColor(CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR,true);
        obj.SetBorderColor(CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR,true);
        obj.SetForeColor(CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR,true);
        obj.SetBorderStyle(FRAME_STYLE_NONE);
        break;
      //--- For ProgressBar WinForms object
      case GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR         :
        obj.SetBackgroundColor(CLR_DEF_CONTROL_PROGRESS_BAR_BACK_COLOR,true);
        obj.SetBorderColor(CLR_DEF_CONTROL_PROGRESS_BAR_BORDER_COLOR,true);
        obj.SetForeColor(CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR,true);
        obj.SetBorderStyle(FRAME_STYLE_SIMPLE);
        break;
      //--- For ScrollBar WinForms object
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR           :
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL:
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  :
        obj.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR,true);
        obj.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR,true);
        obj.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR,true);
        obj.SetBorderSizeAll(1);
        obj.SetBorderStyle(FRAME_STYLE_SIMPLE);
        break;
      //--- For the ScrollBarThumb WinForms object
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB     :
        obj.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,true);
        obj.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_BORDER_COLOR,true);
        obj.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_THUMB_FORE_COLOR,true);
        obj.SetBorderSizeAll(0);
        obj.SetBorderStyle(FRAME_STYLE_NONE);
        break;
      //--- For GlareObj WinForms object
      case GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ            :
        obj.SetBackgroundColor(CLR_CANV_NULL,true);
        obj.SetBorderColor(CLR_CANV_NULL,true);
        obj.SetForeColor(CLR_CANV_NULL,true);
        obj.SetBorderStyle(FRAME_STYLE_NONE);
        break;
      default:
        break;
     }
   obj.Crop();
  }
//+------------------------------------------------------------------+

コンテナに付属する作成された各オブジェクトについて、そのオブジェクトを表示するために必要な最低限のパラメータを設定するコードブロックがここにあります。

コンテナオブジェクト内のオブジェクトは、自動的に所定の順序で並べられたり、コンテナのサイズに合わせて大きさが調整されたりするため、このように扱われるオブジェクトは、コンテナオブジェクトと一体であり、その中身ではないため、スクロールバーを削除する必要があります。

要素のサイズを内側の内容に合わせて調整するメソッドでは、スクロールバーオブジェクトを処理対象から除外します

//+--------------------------------------------+
//| Adjust the element size to fit its content |
//+--------------------------------------------+
bool CContainer::AutoSizeProcess(const bool redraw)
  {
//--- Get the list of bound objects with WinForms type basic and higher
   CArrayObj *list=this.GetListWinFormsObj();
   int maxcX=0;
   int maxcY=0;
//--- Calculate the maximum coordinate of the right and bottom edge from all bound objects
   for(int i=0;i<list.Total();i++)
     {
      CWinFormBase *obj=list.At(i);
      if(obj==NULL || 
         obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR             || 
         obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL  || 
         obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL
        ) continue;
      if(obj.RightEdge()>maxcX)
         maxcX=obj.RightEdge();
      if(obj.BottomEdge()>maxcY)
         maxcY=obj.BottomEdge();
     }
//--- Calculate the required width and height of the panel after adjusting its size to the content
   int w=maxcX-this.CoordX();
   int h=maxcY-this.CoordY();
//--- Calculate the number of pixels, by which we need to resize the container in width and height
   int excess_x=w-this.WidthWorkspace()-this.BorderSizeRight()-1;
   int excess_y=h-this.HeightWorkspace()-this.BorderSizeBottom()-1;
//--- If failed to change the container size, return 'true'
   if(excess_x==0 && excess_y==0)
      return true;
//--- Return the result of resizing the container
   return
     (
      //--- In case of size increase only
      this.AutoSizeMode()==CANV_ELEMENT_AUTO_SIZE_MODE_GROW ? 
      this.Resize(this.Width()+(excess_x>0  ? excess_x : 0),this.Height()+(excess_y>0  ? excess_y : 0),redraw) :
      //--- if both increase and decrease
      this.Resize(this.Width()+(excess_x!=0 ? excess_x : 0),this.Height()+(excess_y!=0 ? excess_y : 0),redraw)
     );
  }
//+------------------------------------------------------------------+

以下は、現在のオブジェクトの新しいサイズを設定するメソッドです。

//+--------------------------------------------+
//| Set the new size for the current object    |
//+--------------------------------------------+
bool CContainer::Resize(const int w,const int h,const bool redraw)
  {
//--- If it was not possible to change the size of the container, return 'false'
   if(!CWinFormBase::Resize(w,h,redraw))
      return false;

//--- Get the vertical scrollbar and
   CWinFormBase *scroll_v=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0);
   if(scroll_v!=NULL)
     {
      //--- change the vertical size to the size of the container workspace
      scroll_v.Resize(scroll_v.Width(),this.HeightWorkspace(),false);
      //--- Move the vertical scrollbar to new coordinates
      if(scroll_v.Move(this.RightEdgeWorkspace()-scroll_v.Width(),this.CoordYWorkspace()))
        {
         scroll_v.SetCoordXRelative(scroll_v.CoordX()-this.CoordX());
         scroll_v.SetCoordYRelative(scroll_v.CoordY()-this.CoordY());
        }
      //--- Get a button object with the down arrow from the vertical scrollbar object
      CWinFormBase *arr_d=scroll_v.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0);
      //--- If the button has been received
      if(arr_d!=NULL)
        {
         //--- Move it to the bottom edge of the vertical scrollbar
         if(arr_d.Move(arr_d.CoordX(),scroll_v.BottomEdge()-scroll_v.BorderSizeBottom()-2*arr_d.Height()))
           {
            arr_d.SetCoordXRelative(arr_d.CoordX()-scroll_v.CoordX());
            arr_d.SetCoordYRelative(arr_d.CoordY()-scroll_v.CoordY());
           }
        }
     }
//--- Get the horizontal scrollbar and
   CWinFormBase *scroll_h=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0);
   if(scroll_h!=NULL)
     {
      //--- change the horizontal size to the size of the container workspace
      scroll_h.Resize(this.WidthWorkspace(),scroll_h.Height(),false);
      //--- Move the horizontal scrollbar to new coordinates
      if(scroll_h.Move(this.CoordXWorkspace(),this.BottomEdgeWorkspace()-scroll_h.Height()))
        {
         scroll_h.SetCoordXRelative(scroll_h.CoordX()-this.CoordX());
         scroll_h.SetCoordYRelative(scroll_h.CoordY()-this.CoordY());
        }
      //--- Get a button object with the right arrow from the horizontal scrollbar object
      CWinFormBase *arr_r=scroll_h.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0);
      //--- If the button has been received
      if(arr_r!=NULL)
        {
         //--- Move it to the right edge of the horizontal scrollbar
         if(arr_r.Move(scroll_h.RightEdge()-BorderSizeRight()-2*arr_r.Width(),arr_r.CoordY()))
           {
            arr_r.SetCoordXRelative(arr_r.CoordX()-scroll_h.CoordX());
            arr_r.SetCoordYRelative(arr_r.CoordY()-scroll_h.CoordY());
           }
        }
     }
   return true;
  }
//+------------------------------------------------------------------+

この仮想メソッドは、コンテナオブジェクトのサイズを変更します。WinFormsオブジェクトの基本クラスから削除されたコードのブロックをその中に移動させました。まず、WinFormsオブジェクトのリサイズメソッドを呼び出します。その後、成功すれば、両方のスクロールバーのサイズと座標をコンテナの新しいサイズと座標に調整します

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

キャプチャ領域オブジェクト(スクロールバースライダー)を動かしたときに、そのイベントハンドラを呼び出すために、ライブラリにその動きをメッセージで伝える必要があります。SplitContainerオブジェクトでセパレータを移動させることができるのです。つまり、セパレータの移動が処理されるコードメソッドに、移動とスライダーの処理を追加する必要があるのです。

セパレータ処理ブロックのイベントハンドラでスライダー処理を追加します。

      //--- In case of the mouse movement event
      if(id==CHARTEVENT_MOUSE_MOVE)
        {
         //--- If the cursor is above the form
         if(::CheckPointer(form)!=POINTER_INVALID)
           {
            //--- 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 || form.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB)
                    {
                     //--- get its base object
                     CWinFormBase *base=form.GetBase();
                     if(base==NULL)
                        return;
                     //--- and send the "Object movement" event to the event handler of the base object
                     const long lp=x;
                     const double dp=y;
                     base.OnChartEvent(WF_CONTROL_EVENT_MOVING,lp,dp,sparam);
                    }

マウスイベント名が変更されたすべてのイベントハンドラを変更し、追加します

            //+---------------------------------------------------------------------------------------------+
            //| 'The cursor is inside the active area, the left mouse button is clicked' event handler      |
            //+---------------------------------------------------------------------------------------------+
            if(mouse_state==MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED)
              {
               form.OnMouseEvent(MOUSE_EVENT_INSIDE_ACTIVE_AREA_RELEASED,lparam,dparam,sparam);
              }

            //+------------------------------------------------------------------------------------------------------------+
            //| 'The cursor is inside the window scrolling area to the right, no mouse buttons are clicked' event handler  |
            //+------------------------------------------------------------------------------------------------------------+
            if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED)
              {
               form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED,lparam,dparam,sparam);
              }
            //+------------------------------------------------------------------------------------------------------------+
            //|'The cursor is inside the window scrolling area to the right, a mouse button is clicked (any)' event handler|
            //+------------------------------------------------------------------------------------------------------------+
            if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED)
              {
               form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_PRESSED,lparam,dparam,sparam);
              }
            //+--------------------------------------------------------------------------------------------------------------+
            //|'The cursor is inside the window scrolling area to the right, the mouse wheel is being scrolled' event handler|
            //+--------------------------------------------------------------------------------------------------------------+
            if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL)
              {
               form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_RIGHT_WHEEL,lparam,dparam,sparam);
              }
            //+-------------------------------------------------------------------------------------------------------------+
            //| 'The cursor is inside the window scrolling area at the bottom, no mouse buttons are clicked' event handler  |
            //+-------------------------------------------------------------------------------------------------------------+
            if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED)
              {
               form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED,lparam,dparam,sparam);
              }
            //+-------------------------------------------------------------------------------------------------------------+
            //|'The cursor is inside the window scrolling area at the bottom, a mouse button is clicked (any)' event handler|
            //+-------------------------------------------------------------------------------------------------------------+
            if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED)
              {
               form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_PRESSED,lparam,dparam,sparam);
              }
            //+---------------------------------------------------------------------------------------------------------------+
            //|'The cursor is inside the window scrolling area at the bottom, the mouse wheel is being scrolled' event handler|
            //+---------------------------------------------------------------------------------------------------------------+
            if(mouse_state==MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL)
              {
               form.OnMouseEvent(MOUSE_EVENT_INSIDE_SCROLL_AREA_BOTTOM_WHEEL,lparam,dparam,sparam);
              }
            //+---------------------------------------------------------------------------------------------+
            //| 'The cursor is inside the control area, no mouse buttons are clicked' event handler         |
            //+---------------------------------------------------------------------------------------------+
            if(mouse_state==MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED)
              {
               form.OnMouseEvent(MOUSE_EVENT_INSIDE_CONTROL_AREA_NOT_PRESSED,lparam,dparam,sparam);
              }
            //+---------------------------------------------------------------------------------------------+


検証

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

パネル上のすべてのオブジェクトの作成と、パネル上のスクロールバーの機能をテストするための大きなボタンを1つだけコメントアウトします。

//+--------------------------------------------+
//| Expert initialization function             |
//+--------------------------------------------+
int OnInit()
  {
//--- Set EA global variables
   ArrayResize(array_clr,2);        // Array of gradient filling colors
   array_clr[0]=C'26,100,128';      // Original ≈Dark-azure color
   array_clr[1]=C'35,133,169';      // Lightened original color
//--- Create the array with the current symbol and set it to be used in the library
   string array[1]={Symbol()};
   engine.SetUsedSymbols(array);
   //--- Create the timeseries object for the current symbol and period, and show its description in the journal
   engine.SeriesCreate(Symbol(),Period());
   engine.GetTimeSeriesCollection().PrintShort(false); // Short descriptions

//--- Create the required number of WinForms Panel objects
   CPanel *pnl=NULL;
   for(int i=0;i<FORMS_TOTAL;i++)
     {
      pnl=engine.CreateWFPanel("WinForms Panel"+(string)i,(i==0 ? 50 : 70),(i==0 ? 50 : 70),410,200,array_clr,200,true,true,false,-1,FRAME_STYLE_BEVEL,true,false);
      if(pnl!=NULL)
        {
         pnl.Hide();
         //--- Set Padding to 4
         pnl.SetPaddingAll(3);
         //--- Set the flags of relocation, auto resizing and auto changing mode from the inputs
         pnl.SetMovable(InpMovable);
         pnl.SetAutoSize(InpAutoSize,false);
         pnl.SetAutoSizeMode((ENUM_CANV_ELEMENT_AUTO_SIZE_MODE)InpAutoSizeMode,false);

         //---
         pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_BUTTON,10,10,pnl.WidthWorkspace()-20,pnl.HeightWorkspace()-20,clrNONE,255,true,false);
         /*
         //--- Create TabControl
         pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,InpTabControlX,InpTabControlY,pnl.Width()-30,pnl.Height()-40,clrNONE,255,true,false);
         CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0);
         if(tc!=NULL)
           {
            tc.SetTabSizeMode((ENUM_CANV_ELEMENT_TAB_SIZE_MODE)InpTabPageSizeMode);
            tc.SetAlignment((ENUM_CANV_ELEMENT_ALIGNMENT)InpHeaderAlignment);
            tc.SetMultiline(InpTabCtrlMultiline);
            tc.SetHeaderPadding(6,0);
            tc.CreateTabPages(15,0,56,20,TextByLanguage("Вкладка","TabPage"));
            
            //--- Create Tooltip for the Left button
            tc.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0,0,10,10,clrNONE,0,false,false);
            CToolTip *tooltip=tc.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0);
            if(tooltip!=NULL)
              {
               tooltip.SetDescription("Left Button Tooltip");
               tooltip.SetIcon(InpTooltipIcon);
               tooltip.SetTitle(InpTooltipTitle);
               tooltip.SetTooltipText(TextByLanguage("Нажмите для прокрутки заголовков вправо","Click to scroll headings to the right"));
               tc.AddTooltipToArrowLeftButton(tooltip);
              }
            //--- Create Tooltip for the Right button
            tc.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0,0,10,10,clrNONE,0,false,false);
            tooltip=tc.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,1);
            if(tooltip!=NULL)
              {
               tooltip.SetDescription("Right Button Tooltip");
               tooltip.SetIcon(ENUM_CANV_ELEMENT_TOOLTIP_ICON(InpTooltipIcon+1));
               tooltip.SetTitle(InpTooltipTitle);
               tooltip.SetTooltipText(TextByLanguage("Нажмите для прокрутки заголовков влево","Click to scroll headings to the left"));
               tc.AddTooltipToArrowRightButton(tooltip);
              }
              
            //--- Create a text label with a tab description on each tab
            for(int j=0;j<tc.TabPages();j++)
              {
               tc.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_LABEL,322,120,80,20,clrDodgerBlue,255,true,false);
               CLabel *label=tc.GetTabElementByType(j,GRAPH_ELEMENT_TYPE_WF_LABEL,0);
               if(label==NULL)
                  continue;
               //--- If this is the very first tab, then there will be no text
               label.SetText(j<5 ? "" : "TabPage"+string(j+1));
              }
            for(int n=0;n<5;n++)
              {
               //--- Create a SplitContainer control on each tab
               tc.CreateNewElement(n,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,10,10,tc.Width()-22,tc.GetTabField(0).Height()-22,clrNONE,255,true,false);
               //--- Get the SplitContainer control from each tab
               CSplitContainer *split_container=tc.GetTabElementByType(n,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,0);
               if(split_container!=NULL)
                 {
                  //--- The separator will be vertical for each even tab and horizontal for each odd one
                  split_container.SetSplitterOrientation(n%2==0 ? CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL : CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL,true);
                  //--- The separator distance on each tab will be 50 pixels
                  split_container.SetSplitterDistance(50,true);
                  //--- The width of the separator on each subsequent tab will increase by 2 pixels
                  split_container.SetSplitterWidth(6+2*n,false);
                  //--- Make a fixed separator for the tab with index 2, and a movable one for the rest
                  split_container.SetSplitterFixed(n==2 ? true : false);
                  //--- For a tab with index 3, the second panel will be in a collapsed state (only the first one is visible)
                  if(n==3)
                     split_container.SetPanel2Collapsed(true);
                  //--- For a tab with index 4, the first panel will be in a collapsed state (only the second one is visible)
                  if(n==4)
                     split_container.SetPanel1Collapsed(true);
                  
                  //--- On each of the control panels...
                  for(int j=0;j<2;j++)
                    {
                     //--- Get the panel by loop index
                     CSplitContainerPanel *panel=split_container.GetPanel(j);
                     if(panel==NULL)
                        continue;
                     //--- set its description for the panel
                     panel.SetDescription(TextByLanguage("Панель","Panel")+string(j+1));
                     
                     //--- If this is the first tab and the second panel
                     if(n==0 && j==1)
                       {
                        //--- Create the ProgressBar control on it
                        if(split_container.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,4,4,100,12,clrNONE,255,false,false))
                          {
                           CProgressBar *progress_bar=split_container.GetPanelElementByType(j,GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0);
                           if(progress_bar!=NULL)
                             {
                              //--- Set the style of the progress bar specified in the EA settings
                              progress_bar.SetStyle((ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE)InpProgressBarStyle);
                              //--- Set the parameters for describing the progress bar
                              progress_bar.SetBarDescriptionText("Progress Bar ");
                              progress_bar.SetBarDescriptionColor(panel.BackgroundColor());
                              progress_bar.SetBarDescriptionOpacity(255);
                              progress_bar.SetBarDescriptionY(-2);
                             }
                          }
                       }
                     
                     //--- ...create a text label with the panel name
                     if(split_container.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_LABEL,4,4,panel.Width()-8,panel.Height()-8,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(panel.Description());
                       }
                    }
                 }
              }
           }
         */
        }
     }
//--- Display and redraw all created panels
   for(int i=0;i<FORMS_TOTAL;i++)
     {
      //--- Get the panel object
      pnl=engine.GetWFPanel("WinForms Panel"+(string)i);
      if(pnl!=NULL)
        {
         //--- display and redraw the panel
         pnl.Show();
         pnl.Redraw(true);
         //--- Get the pointer to the vertical scrollbar object of the main panel
         CScrollBarVertical *sbv=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0);
         //--- Set the display flag for the object and show the scrollbar
         sbv.SetDisplayed(true);
         sbv.Show();
         sbv.BringToTop();
         sbv.Redraw(true);
         //--- Get the pointer to the horizontal scrollbar object of the main panel
         CScrollBarHorisontal *sbh=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0);
         //--- Set the display flag for the object and show the scrollbar
         sbh.SetDisplayed(true);
         sbh.Show();
         sbh.BringToTop();
         sbh.Redraw(true);
         /*
         //--- Get the TabControl object from the panel
         CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0);
         //--- Get the SplitContainer object from the first tab of the TabControl object
         CSplitContainer *sc=tc.GetTabElementByType(0,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,0);
         //--- Get the second panel from the SplitContainer object
         CSplitContainerPanel *scp=sc.GetPanel(1);
         //--- Get the ProgressBar object from the received panel
         CProgressBar *pb=scp.GetElementByType(GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0);
         //--- Waiting
         Sleep(1);
         //--- Get the width of the ProgressBar object
         int w=pb.Width();
         //--- In the loop, increase the width of the ProgressBar by 180 pixels
         for(int n=0;n<180;n++)
           {
            //Sleep(1);
            pb.Resize(w+n,pb.Height(),true);
           }
         //--- Set the values for PerformStep of the ProgressBar object
         pb.SetValuesForProcessing(0,350,1,0);
         //--- Reset ProgressBar to minimum
         pb.ResetProgressBar();
         //--- If the style of the progress bar is "Continuous line", display the progress bar description
         if(pb.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS)
            pb.ShowBarDescription();
         //--- Waiting
         Sleep(1);
         //--- If the style of the progress bar is not "Continuous scrolling"
         if(pb.Style()!=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE)
           {
            //--- In the loop from the minimum to the maximum value of ProgressBar
            for(int n=0;n<=pb.Maximum();n++)
              {
               //--- call the method for increasing the progress bar by a given step with a wait of 1/5 second
               pb.PerformStep();
               //--- Set the number of completed steps in the description of the progress bar
               pb.SetBarDescriptionText("Progress Bar, pass: "+(InpProgressBarPercent ? pb.ValuePercentDescription() : pb.ValueDescription()));
               Sleep(1);
              }
           }
         //--- Wait, set the description font type to Bold and write a completion message on the progress bar
         Sleep(1);
         pb.SetBarDescriptionFontFlags(FW_BOLD);
         pb.SetBarDescriptionText("Progress Bar: Done");
         //--- Set the glare object type - rectangle, opacity 40, color - white
         pb.SetGlareStyle(CANV_ELEMENT_VISUAL_EFF_STYLE_RECTANGLE);
         pb.SetGlareOpacity(40);
         pb.SetGlareColor(clrWhite);
         */
        }
     }
        
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+

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


見ての通り、スライダーは矢印ボタンによってスクロールバー内で適切に拘束されています。矢印ボタンはクリックに反応し、オブジェクトの色はインタラクション中のオブジェクトとカーソルの状態に応じて変化します。

また、オブジェクトを選択すると、スクロールバーの枠が消えてしまうという欠点もあります。これは、オブジェクトの再描画と、スクロールバーが先に作成され優先順位がないため、他のオブジェクトより下にあることが原因で発生します。また、スクロールバー上の矢印ボタンをクリックして選択することも困難です。同じ理由で、先にオブジェクトが作成され、後から作成された他のオブジェクト(大きなボタン)が重なっています。これは後ですべて修正します。現時点では、欠点を見て、その原因を理解し、それを解消するために何をすべきかを考えることが重要です。


次の段階

次の記事では、フォームオブジェクトクラスの開発を続けます。

目次に戻る

連載のこれまでの記事

 
DoEasy-コントロール(第26部):ToolTipWinFormsオブジェクトの最終確認とProgressBar開発の開始
DoEasy-コントロール(第27部):ProgressBarWinFormsオブジェクトでの作業
DoEasy-コントロール(第28部):ProgressBarコントロールのバースタイル
DoEasy - コントロール(第29部):ScrollBar補助コントロール

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

添付されたファイル |
MQL5.zip (4545.72 KB)
インディケーター情報の測定 インディケーター情報の測定
機械学習は、ストラテジー開発の手法として注目されています。これまで、収益性と予測精度の最大化が重視される一方で、予測モデル構築のためのデータ処理の重要性はあまり注目されてきませんでした。この記事では、Timothy Masters著の書籍「Testing and Tuning Market Trading Systems」に記載されているように、予測モデル構築に使用するインディケーターの適切性を評価するために、エントロピーの概念を使用することについて考察しています。
行列ユーティリティ - 行列とベクトルの標準ライブラリの機能を拡張する 行列ユーティリティ - 行列とベクトルの標準ライブラリの機能を拡張する
行列は大規模な数学的演算を効率的に処理できるため、機械学習アルゴリズムや一般的なコンピュータの基盤となっています。標準ライブラリは必要なものをすべて備えていますが、ユーティリティファイルでライブラリにはまだないいくつかの関数を導入して、拡張する方法を見てみましょう。
母集団最適化アルゴリズム:ホタルアルゴリズム(FA) 母集団最適化アルゴリズム:ホタルアルゴリズム(FA)
今回は、ホタルアルゴリズム(FA)という最適化手法について考えてみます。修正により、このアルゴリズムは部外者から真の評価表リーダーへと変貌を遂げました。
Linux上のMetaTrader 5のC++マルチスレッドサポートを備えた概念実証DLLを開発する Linux上のMetaTrader 5のC++マルチスレッドサポートを備えた概念実証DLLを開発する
最終製品がWindowsとLinuxシステムの両方でシームレスに動作するMetaTrader 5プラットフォームの開発をLinuxシステムのみでおこなう方法のステップとワークフローを探索する旅を始めます。WineとMinGWについて学ぶことができます。これらはどちらも、クロスプラットフォーム開発を機能させるために不可欠なツールです。特に、MinGWのスレッド実装(POSIXおよびWin32)については、どれを使用するかを選択する際に考慮する必要があります。次に、概念実証のDLLを構築し、それをMQL5コードで使用して、最後に両方のスレッド実装のパフォーマンスを比較します。すべては読者の基盤が自力でさらに拡大するようにするためです。この記事を読めば、LinuxでMT関連のツールを快適に構築できるはずです。