English Русский Español Deutsch 日本語 Português
preview
DoEasy. 控件(第 二十九 部分):滚动条(ScrollBar)辅助控件

DoEasy. 控件(第 二十九 部分):滚动条(ScrollBar)辅助控件

MetaTrader 5示例 | 25 四月 2023, 17:03
518 0
Artyom Trishkin
Artyom Trishkin

内容


概述

在上一篇文章中,我宣布创建 TrackBar 控件 — 这是一个允许移动滑块即可输入数值的元素:


由于该类对象派生自 ScrollBar 控件,因此在本文中,我将开始创建这个 WinForms 对象。

滚动条用于窗体内容(如果窗体超出容器)的滚动显示。 滚动条通常位于窗体的底部和右侧。 底部的水平滚动条可左右滚动内容,而垂直的则上下滚动内容。

在本文中,我将开发滚动条基准对象及其两个后代 — ScrollBarVertical 和 ScrollBarHorisontal。 这些对象都是静态的,即不会参与管理窗体的内容。 我将在后续文章中应对这个问题。 每个滚动条对象将包含一个底图和位于其上的控件 — 两个按钮(垂直滚动条为上/下按钮,水平滚动条为左/右按钮)。 每个对象都应该有一个捕获区域(ThumbArea)或“滑块”,如此即可抓住它,并用鼠标移动它来滚动窗体的内容。 箭头按钮也是用于此目的。 所有这些控件都已赋予相应的鼠标交互功能。 故此,今天我们将简单地创建这些对象,在下一篇文章中,我们将最终关注指出的缺点,并着手开发滚动条与鼠标的交互,从而控制窗体的内容。

滚动条对于所有对象都应存在,并允许将其它控件附着于它们之上,这意味着它们应是容器对象。 最初,如果内容与容器尺寸相适,则滚动条处于隐藏状态。 如果内容开始超出容器,则应显示滚动条,允许用户通过移动窗体中的附加对象来控制窗体的可见区域。 在本文中,我将创建两个滚动条(垂直和水平),并令其对于主窗体可见,以便评估它们的外观,并决定下一步如何处理它们。


改进库类

将鼠标悬停并捕获滚动条控制区域(按钮和滚动滑块)时,它们应更改其颜色。 悬停和捕获时颜色会发生变化 — 为每个状态设置不同的颜色。
将它们添加到宏替换列表之中 \MQL5\Include\DoEasy\Defines.mqh:

#define CLR_DEF_CONTROL_PROGRESS_BAR_BACK_COLOR       (C'0xF0,0xF0,0xF0')  // ProgressBar control background color
#define CLR_DEF_CONTROL_PROGRESS_BAR_BORDER_COLOR     (C'0xBC,0xBC,0xBC')  // ProgressBar control frame color
#define CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR       (C'0x00,0x78,0xD7')  // ProgressBar control text color
#define CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR        (C'0x06,0xB0,0x25')  // ProgressBar control progress line color

#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_THUMB_COLOR        (C'0xCD,0xCD,0xCD')  // ScrollBar control capture area 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 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


将三个新类型添加到同一文件中的图形元素类型列表之中:

//+---------------------------------------------+
//| 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,                  // Windows Forms ScrollBar
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,       // Windows Forms ScrollBarHorisontal
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,         // Windows Forms ScrollBarVertical
  };
//+------------------------------------------------------------------+

在此,我添加了一个基准滚动条元素,和两个派生自它的控件 — 水平和垂直滚动条。

在 \MQL5\Include\DoEasy\Data.mqh 里,添加新的消息索引:

   MSG_GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR,        // BarProgressBar control
   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_VERTICAL,     // ScrollBarVertical control
   MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,   // ScrollBarHorisontal control
   MSG_GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ,               // Glare object


与新添加的索引相对应的消息文本:

   {"Элемент управления BarProgressBar","Control element \"BarProgressBar\""},
   {"Элемент управления ProgressBar","Control element \"ProgressBar\""},
   {"Элемент управления ScrollBar","Control element \"ScrollBar\""},
   {"Элемент управления ScrollBarVertical","Control element \"ScrollBarVertical\""},
   {"Элемент управления ScrollBarHorisontal","Control element \"ScrollBarHorisontal\""},
   {"Объект блика","Glare object"},

现在我们能够在此处创建的新对象的描述。


为了显示函数库图形对象的描述,请在函数库所有图形对象的基准对象类中调用 TypeElementDescription()方法,该类位于 \MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqh 当中。

我们将新对象描述的输出添加到其中:

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

该方法接收对象类型。 根据所传递类型,该方法返回我在函数库系列文章第一篇中研究的 CMessage 库中的文本消息类的对象文本。


滚动条辅助控件的基类

基准滚动条对象将从所有 WinForms 库对象的基类继承。 它将是某种抽象的滚动条对象,而特定对象的必要参数需在其后代中指定。

在函数库辅助对象 \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ 的文件夹中,在 ScrollBar.mqh 中创建新的类 CScrollBar。 该类应派生自 CWinFormBase 类,而这个类和其它类的文件都应包含在所创建对象的文件中

//+------------------------------------------------------------------+
//|                                                    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 "ArrowDownButton.mqh"
#include "ArrowUpButton.mqh"
#include "ArrowLeftButton.mqh"
#include "ArrowRightButton.mqh"
//+---------------------------------------------+
//| CScrollBar object class of WForms controls  |
//+---------------------------------------------+
class CScrollBar : public CWinFormBase
  {


在类的私密部分中,声明创建箭头按钮的方法、创建新图形对象的标准方法、计算捕获区域(滑块)大小的方法、以及初始化对象参数的方法:

//+------------------------------------------------------------------+
//| CScrollBar object class of WForms controls                       |
//+------------------------------------------------------------------+
class CScrollBar : public CWinFormBase
  {
private:
//--- 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:

计算不同子对象中滑块大小的方法将生成不同大小的捕获区域,因为它的位置取决于滚动条的方向 — 垂直或水平。 创建按钮对象的方法还将在不同的继承对象中创建不同的按钮:对于垂直滚动条,我们需要向上/向下箭头的按钮;对于水平滚动条,我们需要向左/向右箭头的按钮。 所有这些方法都是虚拟的,以便可以在派生类中重写它们。

在类的受保护部分中,声明创建捕获区域的虚拟方法(将在方法中创建按钮和滑块),和受保护的构造函数(函数库图形元素的标准)。 在公开部分中,编写返回对象属性维护标志、参数构造函数、和虚拟对象计时器事件处理程序的方法:

protected:
//--- 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; }
   
//--- 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);
  };
//+------------------------------------------------------------------+

每次创建新的图形元素时,我们都会考虑类似的方法 — 它们都是雷同的,并且对于函数库中的每个图形对象具有相同的用意。

我们来研究一下所声明方法的实现。

受保护的构造函数:

//+---------------------------------------------+
//| Protected constructor with an object type,  |
//| chart ID and subwindow                      |
//+---------------------------------------------+
CScrollBar::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) : 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_HELPER;
   this.Initialize();
  }
//+------------------------------------------------------------------+

构造函数接收所创建对象的类型和其它标准参数在初始化清单中,把欲创建对象的类型传递给父类构造函数。 在构造函数主体中,设置图形元素的类型,以及函数库图形对象的类型,并调用参数初始化方法


参数型构造函数:

//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CScrollBar::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) : CWinFormBase(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR);
   this.m_type=OBJECT_DE_TYPE_GWF_HELPER;
   this.Initialize();
  }
//+------------------------------------------------------------------+

此处的所有内容都与受保护的构造函数雷同,但对象类型在初始化清单中硬编码为 ScrollBar


元素属性初始化方法:

//+---------------------------------------------+
//| 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.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR,true);
   this.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR,true);
  }
//+------------------------------------------------------------------+

在此,将对象的每一侧边框大小设置为一个像素,将边框类型设置为“简单”,并添加元素背景、边框和文本颜色。

创建捕获区域对象的方法:

//+---------------------------------------------+
//| Create the capture area object              |
//+---------------------------------------------+
void CScrollBar::CreateThumbArea(void)
  {
   this.CreateArrowButtons(DEF_ARROW_BUTTON_SIZE,DEF_ARROW_BUTTON_SIZE);
  }
//+------------------------------------------------------------------+

在创建箭头按钮对象和滑块的方法中,调用虚拟方法 CreateArrowButtons(),其应在后代对象中重新定义。

计算捕获区域大小的方法:

//+---------------------------------------------+
//| Calculate the capture area size             |
//+---------------------------------------------+
int CScrollBar::CalculateThumbAreaSize(void)
  {
   return 0;
  }
//+------------------------------------------------------------------+

此处,该方法返回零,而其应在派生类中重写,因为对于每个派生对象,滑块的大小和位置都不同。

该方法创建新的图形对象:

//+---------------------------------------------+
//| 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_BUTTON               :
         element=new CButton(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;
  }
//+------------------------------------------------------------------+

该方法是函数库图形对象的标准方法。 它允许您创建五个控件:向上/向下箭头的按钮、向右/向左箭头,和滑块所基于的按钮对象。


计时器事件处理程序:

//+---------------------------------------------+
//| Timer                                       |
//+---------------------------------------------+
void CScrollBar::OnTimer(void)
  {

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

目前,该方法为空,不执行任何操作。 我将在后续文章中应对它。

该对象是一个抽象滚动条。 它不执行任何操作,并只是作为创建另外两个对象的基础 — 垂直和水平滚动条。


ScrollBarVertical 和 ScrollBarHorisontal 控件派生自基准控件

我们来创建从基准抽象滚动条对象派生的对象 — 垂直和水平对象。

在 \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\,创建一个 CScrollBarVertical 类的新文件 ScrollBarVertical.mqh
该类应派生自基准滚动条对象而其文件以及其它一些必要的文件应包含在创建的类文件中

//+------------------------------------------------------------------+
//|                                            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 "..\Containers\Container.mqh"
#include "..\Common Controls\Button.mqh"
#include "ArrowDownButton.mqh"
#include "ArrowUpButton.mqh"
#include "ScrollBar.mqh"
//+------------------------------------------------------------------+
//| CScrollBarVertical object class of WForms controls               |
//+------------------------------------------------------------------+
class CScrollBarVertical : public CScrollBar
  {
  }


在类的私密部分中,声明创建箭头按钮的虚拟方法、和计算捕获区域大小的方法。
在受保护部分中,声明受保护的类构造函数,而在公开部分中,实现维护对象属性、参数型构造函数、和计时器事件处理程序的方法,并返回结果标志:

//+------------------------------------------------------------------+
//| 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; }
   
//--- 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);
  };
//+------------------------------------------------------------------+


我们来仔细查看所声明的方法。

受保护的构造函数:

//+---------------------------------------------+
//| Protected constructor with an object type,  |
//| chart ID and subwindow                      |
//+---------------------------------------------+
CScrollBarVertical::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) : CScrollBar(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.CreateThumbArea();
  }
//+------------------------------------------------------------------+

构造函数接收所创建对象的类型,及创建所需的其它参数对象类型在初始化清单中传递给父类构造函数。 在构造函数主体中,设置图形对象类型,并调用创建捕获区域的方法(按钮和滑块)


参数型构造函数:

//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CScrollBarVertical::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) : CScrollBar(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL);
   this.CreateThumbArea();
  }
//+------------------------------------------------------------------+

此处的所有内容都与上面讨论的受保护构造函数雷同,但对象类型被硬编码为“垂直滚动条”


创建 ArrowButton 对象的方法:

//+---------------------------------------------+
//| Create the ArrowButton objects              |
//+---------------------------------------------+
void CScrollBarVertical::CreateArrowButtons(const int width,const int height)
  {
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,  -1,0,                   width,height,this.BackgroundColor(),255,true,false);
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,-1,this.Height()-2*height,width,height,this.BackgroundColor(),255,true,false);
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_BUTTON,0,this.Height()/2-height,width,height,CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,255,true,false);
  }
//+------------------------------------------------------------------+

在此,创建一个向上箭头的按钮对象一个向下箭头的按钮对象,和一个按钮对象,该对象将充当滑块。

在所有这些对象中,已经创建了与鼠标光标交互的功能。 故此,在下一篇文章中,我将简单地实现这些对象的事件处理程序,以便管理滚动条所附着容器的内容。


计算捕获区域大小的方法:

//+---------------------------------------------+
//| Calculate the capture area size             |
//+---------------------------------------------+
int CScrollBarVertical::CalculateThumbAreaSize(void)
  {
   return 0;
  }
//+------------------------------------------------------------------+

在此版本的对象中,该方法仅返回 null。 滑块对象创建时采用固定尺寸,在后续文章中会完成对其尺寸的所有更改。 滑块的尺寸取决于超出容器的内容含量 — 窗体的可见区域中无法容纳的数据越多,滑块的尺寸就越小。 在创建鼠标与滚动条交互的功能时,我才会应对所有这些计算。


计时器事件处理程序:

//+---------------------------------------------+
//| Timer                                       |
//+---------------------------------------------+
void CScrollBarVertical::OnTimer(void)
  {

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

我们将在后续文章中创建处理程序功能。


水平滚动条控件与新创建的垂直滚动条雷同。 我们将其视为一个整体的类,无需任何解释,因为上述所有内容也适用于该对象的类。

该类应该在 ScrollBarHorisontal.mqh 的 \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ScrollBarHorisontal.mqh 中创建:

//+------------------------------------------------------------------+
//|                                            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 "..\Containers\Container.mqh"
#include "..\Common Controls\Button.mqh"
#include "ArrowLeftButton.mqh"
#include "ArrowRightButton.mqh"
//+------------------------------------------------------------------+
//| CScrollBarHorisontal object class of WForms controls             |
//+------------------------------------------------------------------+
class CScrollBarHorisontal : 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
                     CScrollBarHorisontal(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; }
   
//--- Constructor
                     CScrollBarHorisontal(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);
  };
//+---------------------------------------------+
//| Protected constructor with an object type,  |
//| chart ID and subwindow                      |
//+---------------------------------------------+
CScrollBarHorisontal::CScrollBarHorisontal(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) : CScrollBar(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.CreateThumbArea();
  }
//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CScrollBarHorisontal::CScrollBarHorisontal(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) : CScrollBar(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL);
   this.CreateThumbArea();
  }
//+---------------------------------------------+
//| Create the ArrowButton objects              |
//+---------------------------------------------+
void CScrollBarHorisontal::CreateArrowButtons(const int width,const int height)
  {
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,  -1,-1,                   width,height,this.BackgroundColor(),255,true,false);
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,this.Width()-2*width,-1,width,height,this.BackgroundColor(),255,true,false);
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_BUTTON,this.Width()/2-width,0,width,height,CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR,255,true,false);
  }
//+---------------------------------------------+
//| Calculate the capture area size             |
//+---------------------------------------------+
int CScrollBarHorisontal::CalculateThumbAreaSize(void)
  {
   return 0;
  }
//+---------------------------------------------+
//| Timer                                       |
//+---------------------------------------------+
void CScrollBarHorisontal::OnTimer(void)
  {

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


上面编写的滚动条对象类,始终默认在每个容器对象内创建,且与用户无关,并在创建后立即隐藏。 仅当容器的内容超出其限制,或在开发人员指定的情况下,才会显示对象。 在测试期间,我会在程序中显示它们。

由于对象默认应存在于容器对象内,因此它们应在 \MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Container.mqh 容器对象类之中创建。

将新创建的对象文件包含在容器对象文件之中。 在私密部分,一个简单编写的创建图形对象的虚拟方法被转换为方法声明(我将在下面编写它的实现 — 以前,其实现是在继承的类中完成的)。 此外,声明创建垂直和水平滚动条的方法。 在受保护的部分中,声明创建两个滚动条的方法

//+------------------------------------------------------------------+
//|                                                    Container.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 "..\Common Controls\RadioButton.mqh"
#include "..\Common Controls\Button.mqh"
#include "..\Helpers\ScrollBarVertical.mqh"
#include "..\Helpers\ScrollBarHorisontal.mqh"
//+------------------------------------------------------------------+
//| Class of the base container object of WForms controls            |
//+------------------------------------------------------------------+
class CContainer : public CWinFormBase
  {
private:
//--- Create a new graphical object
   virtual CGCnvElement *CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                          const int element_num,
                                          const string descript,
                                          const int x,
                                          const int y,
                                          const int w,
                                          const int h,
                                          const color colour,
                                          const uchar opacity,
                                          const bool movable,
                                          const bool activity);// { return NULL; }

//--- Calculate Dock objects' binding coordinates
   void              CalculateCoords(CArrayObj *list);
   
//--- Create the (1) vertical and (2) horizontal ScrollBar
   CWinFormBase     *CreateScrollBarVertical(const int width);
   CWinFormBase     *CreateScrollBarHorisontal(const int width);

protected:
//--- Adjust the element size to fit its content
   bool              AutoSizeProcess(const bool redraw);
//--- Set parameters for the attached object
   void              SetObjParams(CWinFormBase *obj,const color colour);
//--- Create vertical and horizontal ScrollBar objects
   void              CreateScrollBars(const int width);

public:


在两个类构造函数中,于对象创建结束时,调用创建两个滚动条的方法

//+---------------------------------------------+
//| 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(10);
  }
//+------------------------------------------------------------------+
//| 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(10);
  }
//+------------------------------------------------------------------+

创建容器对象后,将往其内附加两个滚动条。 一旦创建,滚动条先被隐藏。


在为附着对象设置参数的方法中,编写一个代码模块,在其中为新创建的滚动条对象设置属性:

//+---------------------------------------------+
//| 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 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();
  }
//+------------------------------------------------------------------+

该方法始终在创建附着于容器的对象后调用。 该方法为新创建的对象指定默认参数。 稍后,可以把它们替换成其它数值。 但是,一旦创建,它们始终在此方法中自动设置。


创建垂直和水平滚动条对象的方法:

//+------------------------------------------------------------------+
//| Create vertical and horizontal ScrollBar objects                 |
//+------------------------------------------------------------------+
void CContainer::CreateScrollBars(const int width)
  {
//--- Create the vertical scrollbar object
   CScrollBarVertical *sbv=this.CreateScrollBarVertical(DEF_ARROW_BUTTON_SIZE);
//--- If the object has been created
   if(sbv!=NULL)
     {
      //--- set the object non-display flag and hide it
      sbv.SetDisplayed(false);
      sbv.Hide();
     }
//--- Create the horizontal scrollbar object
   CScrollBarHorisontal *sbh=this.CreateScrollBarHorisontal(DEF_ARROW_BUTTON_SIZE);
//--- If the object has been created
   if(sbh!=NULL)
     {
      //--- set the object non-display flag and hide it
      sbh.SetDisplayed(false);
      sbh.Hide();
     }
  }
//+------------------------------------------------------------------+

该方法的逻辑在代码中已有注释。 在此,我们只需创建两个滚动条,并在更新、显示和重绘它们所附于的基准对象时,设置不显示标志来隐藏它们。 换言之,滚动条将来只能在程序或函数库代码中明确允许,才能显示它们。


创建垂直滚动条的方法:

//+---------------------------------------------+
//| Create the vertical ScrollBar               |
//+---------------------------------------------+
CWinFormBase *CContainer::CreateScrollBarVertical(const int width)
  {
//--- If failed to create the vertical scroll bar object, return NULL
   if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,this.RightEdge()-width,0,width,this.HeightWorkspace(),this.BackgroundColor(),255,true,false))
      .return NULL;
//--- Return the pointer to the vertical scrollbar object
   return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0);
  }
//+------------------------------------------------------------------+

创建一个对象,并从附着对象列表中返回指向该对象的指针。


创建水平滚动条的方法:

//+---------------------------------------------+
//| Create the horizontal ScrollBar             |
//+---------------------------------------------+
CWinFormBase *CContainer::CreateScrollBarHorisontal(const int width)
  {
//--- If failed to create the horizontal scroll bar object, return NULL
   if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0,this.BottomEdge()-width,this.WidthWorkspace(),width,this.BackgroundColor(),255,true,false))
      .return NULL;
//--- Return the pointer to the horizontal scrollbar object
   return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0);
  }
//+------------------------------------------------------------------+

创建一个对象,并从附着对象列表中返回指向该对象的指针。


该方法创建新的图形对象:

//+---------------------------------------------+
//| Create a new graphical object               |
//+---------------------------------------------+
CGCnvElement *CContainer::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           : element=new CScrollBar(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);          break;
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  : element=new CScrollBarVertical(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);  break;
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL: element=new CScrollBarHorisontal(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;
  }
//+------------------------------------------------------------------+

以前,该方法不执行任何操作,并在派生类中被重写。 现在它也能够创建滚动条对象了。


由于滚动条附于其底部和右侧的容器对象,因此调整窗体大小也应更改滚动条对象。 我们在基准 WinForms 对象的 \MQL5\Include\DoEasy\Objects\Graph\WForms\WinFormBase.mqh 中执行此操作。

在为当前对象设置新维度的方法中,添加以下代码模块

//+---------------------------------------------+
//| 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;
  }
//+------------------------------------------------------------------+

现在,当调整对象大小时,滚动条也会相应更改。 所添加代码模块的逻辑在注释中进行了完整讲述。


我们将所有创建的图形元素的所有文件包含在面板对象的类文件之中。

在 \MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Panel.mqh 中,包含新控件的文件:

//+---------------------------------------------+
//| Include files                               |
//+---------------------------------------------+
#include "Container.mqh"
#include "..\Helpers\TabField.mqh"
#include "..\Helpers\ArrowUpButton.mqh"
#include "..\Helpers\ArrowDownButton.mqh"
#include "..\Helpers\ArrowLeftButton.mqh"
#include "..\Helpers\ArrowRightButton.mqh"
#include "..\Helpers\ArrowUpDownBox.mqh"
#include "..\Helpers\ArrowLeftRightBox.mqh"
#include "..\Helpers\HintMoveLeft.mqh"
#include "..\Helpers\HintMoveRight.mqh"
#include "..\Helpers\HintMoveUp.mqh"
#include "..\Helpers\HintMoveDown.mqh"
#include "..\Helpers\ScrollBarVertical.mqh"
#include "..\Helpers\ScrollBarHorisontal.mqh"
#include "GroupBox.mqh"
#include "TabControl.mqh"
#include "SplitContainer.mqh"
#include "..\..\WForms\Common Controls\ListBox.mqh"
#include "..\..\WForms\Common Controls\CheckedListBox.mqh"
#include "..\..\WForms\Common Controls\ButtonListBox.mqh"
#include "..\..\WForms\Common Controls\ToolTip.mqh"
#include "..\..\WForms\Common Controls\ProgressBar.mqh"
#include "..\..\WForms\GlareObj.mqh"
//+---------------------------------------------+
//| Panel object class of WForms controls       |
//+---------------------------------------------+
class CPanel : public CContainer


在创建新图形对象的方法中,添加创建新滚动条对象的代码

//+---------------------------------------------+
//| Create a new graphical object               |
//+---------------------------------------------+
CGCnvElement *CPanel::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                       const int obj_num,
                                       const string descript,
                                       const int x,
                                       const int y,
                                       const int w,
                                       const int h,
                                       const color colour,
                                       const uchar opacity,
                                       const bool movable,
                                       const bool activity)
  {
   CGCnvElement *element=NULL;
   switch(type)
     {
      case GRAPH_ELEMENT_TYPE_ELEMENT                 : element=new CGCnvElement(type,this.GetMain(),this.GetObject(),this.ID(),obj_num,this.ChartID(),this.SubWindow(),descript,x,y,w,h,colour,opacity,movable,activity); break;
      case GRAPH_ELEMENT_TYPE_FORM                    : element=new CForm(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);               break;
      case GRAPH_ELEMENT_TYPE_WF_CONTAINER            : element=new CContainer(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);          break;
      case GRAPH_ELEMENT_TYPE_WF_GROUPBOX             : element=new CGroupBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);           break;
      case GRAPH_ELEMENT_TYPE_WF_PANEL                : element=new CPanel(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);              break;
      case GRAPH_ELEMENT_TYPE_WF_LABEL                : element=new CLabel(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);              break;
      case GRAPH_ELEMENT_TYPE_WF_CHECKBOX             : element=new CCheckBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);           break;
      case GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON          : element=new CRadioButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);        break;
      case GRAPH_ELEMENT_TYPE_WF_BUTTON               : element=new CButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);             break;
      case GRAPH_ELEMENT_TYPE_WF_LIST_BOX             : element=new CListBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);            break;
      case GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM        : element=new CListBoxItem(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);        break;
      case GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX     : element=new CCheckedListBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);     break;
      case GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX      : element=new CButtonListBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);      break;
      case GRAPH_ELEMENT_TYPE_WF_TAB_HEADER           : element=new CTabHeader(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);          break;
      case GRAPH_ELEMENT_TYPE_WF_TAB_FIELD            : element=new CTabField(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);           break;
      case GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL          : element=new CTabControl(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);         break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON         : element=new CArrowButton(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_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_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;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX : element=new CArrowUpDownBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);     break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX : element=new CArrowLeftRightBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);  break;
      case GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER      : element=new CSplitContainer(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);     break;
      case GRAPH_ELEMENT_TYPE_WF_SPLITTER             : element=new CSplitter(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);           break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_BASE            : element=new CHintBase(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);           break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT       : element=new CHintMoveLeft(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);       break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT      : element=new CHintMoveRight(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);      break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP         : element=new CHintMoveUp(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);         break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN       : element=new CHintMoveDown(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);       break;
      case GRAPH_ELEMENT_TYPE_WF_TOOLTIP              : element=new CToolTip(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);            break;
      case GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR         : element=new CProgressBar(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);        break;
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR           : element=new CScrollBar(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);          break;
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  : element=new CScrollBarVertical(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);  break;
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL: element=new CScrollBarHorisontal(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;
  }
//+------------------------------------------------------------------+

现在,在这个对象中,我们就能够创建附于它的滚动条对象。

在其它容器对象类中也应在相同方法中添加相同的代码。

已进行修改的函数库文件如下:

SplitContainerPanel.mqh, Containers\TabControl.mqh, TabField.mqh, SplitContainer.mqh

我们检查一下结果。


测试

为了执行测试,我沿用来自前一篇文章中的 EA,并将其保存在 \MQL5\Experts\TestDoEasy\Part129\ 中,命名为 TestDoEasy129.mq5

OnInit() 处理程序中,即在重绘所有已创建对象的代码模块中,添加获取指向主面板对象的两个滚动条的指针,并强制显示它们,从而查看它们以何种形式创建:

//--- 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.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.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);
         //--- Wait for 1/10 of a second
         Sleep(100);
         //--- Get the width of the ProgressBar object
         int w=pb.Width();
         //--- In the loop, increase the width of the ProgressBar by 180 pixels with a delay of 1/50
         for(int n=0;n<180;n++)
           {
            Sleep(20);
            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();
         //--- Wait for 1/5 second
         Sleep(200);
         //--- 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(20);
              }
           }
         //--- Wait for 1/2 second, set the description font type to Bold and write a completion message on the progress bar
         Sleep(500);
         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);
        }
     }


编译 EA,并在图表上启动它:


我们看到滚动条在正确的位置上创建,且控件能正常响应鼠标交互。 当鼠标光标悬停在滚动条上的控件对象上时,它们的涂色是错误的,因为我尚未为这些控件创建事件处理程序。 我将在后续文章中修复此问题。


下一步是什么?

在下一篇文章中,我将继续开发 ScrollBar 对象。

返回内容目录

*该系列的前几篇文章:

 
DoEasy. 控件 (第 26 部分): 完成 ToolTip(工具提示)WinForms 对象,并转移至 ProgressBar(进度条)开发
DoEasy. 控件 (第 27 部分): 继续致力 ProgressBar(进度条)WinForms 对象
DoEasy. 控件 (第 28 部分): 进度条控件中的柱线样式

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/11847

附加的文件 |
MQL5.zip (4534.94 KB)
种群优化算法:鱼群搜索(FSS) 种群优化算法:鱼群搜索(FSS)
鱼群搜索(FSS)是一种新的优化算法,其灵感来自鱼群中鱼的行为,其中大多数(高达 80%)游弋在有组织的亲属群落中。 经证明,鱼类的聚集在觅食效率和保护捕食者方面起着重要作用。
神经网络变得轻松(第三十五部分):内在好奇心模块 神经网络变得轻松(第三十五部分):内在好奇心模块
我们继续研究强化学习算法。 到目前为止,我们所研究的所有算法都需要创建一个奖励政策,从而令代理者能够每次从一个系统状态过渡到另一个系统状态的转换中估算其每个动作。 然而,这种方式人为因素相当大。 在实践中,动作和奖励之间存在一些时间滞后。 在本文中,我们将领略一种模型训练算法,该算法可以操控从动作到奖励的各种时间延迟。
MQL5 中的范畴论 (第 1 部分) MQL5 中的范畴论 (第 1 部分)
范畴论是数学的一个多样化和不断扩展的分支,到目前为止,在 MQL 社区中还相对难以发现。 这些系列文章旨在介绍和研究其一些概念,其总体目标是建立一个开放的函数库,吸引评论和研讨,同时希望在交易者的策略开发中进一步在运用这一非凡的领域。
MQL5 酷宝书 — 服务 MQL5 酷宝书 — 服务
本文讲述了服务的多功能性 — 不需要绑定图的 MQL5 程序。 我还会重点介绍服务与其它 MQL5 程序的区别,并强调开发人员使用服务的细微差别。 作为示例,为读者提供了各种任务,涵盖了可以作为服务实现的各种功能。