
DoEasy. Элементы управления (Часть 29): Вспомогательный элемент управления "ScrollBar"
Содержание
- Концепция
- Доработка классов библиотеки
- Базовый класс вспомогательного элемента управления ScrollBar
- Производные от базового объекты ScrollBarVertical и ScrollBarHorisontal
- Тестирование
- Что дальше
Концепция
В прошлой статье было анонсировано создание элемента управления TrackBar — элемента, который с помощью перемещения ползунка позволяет вводить числовые значения:
Так как такой объект является наследником элемента управления ScrollBar (полоса прокрутки), то сегодня начнём создание этого WinForms-объекта.
ScrollBar (полоса прокрутки) используется для прокручивания содержимого формы, если оно выходит за пределы контейнера. Полосы прокрутки обычно расположены снизу и справа формы. Горизонтальная, расположенная снизу, служит для прокрутки содержимого влево-вправо, а вертикальная — для прокрутки вверх-вниз.
Сегодня создадим базовый объект ScrollBar и два его наследника — ScrollBarVertical и ScrollBarHorisontal. Объекты будут статичными, т.е. не будут управлять содержимым формы — этим займёмся в последующих статьях. Каждый объект-полоса прокрутки будет состоять из подложки и элементов управления, расположенных на ней — двух кнопок (вверх-вниз для вертикальной полосы прокрутки и влево-вправо — для горизонтальной). У каждого объекта должна быть область захвата (ThumbArea), или "ползунок", ухватив за который и двигая его мышкой, можно смещать содержимое формы. Для этого также служат и кнопки со стрелками, имеющимися у объекта. Все эти элементы управления уже наделены функционалом для взаимодействия с мышкой. Поэтому сегодня мы просто создадим эти объекты, а в следующей статье доработаем замеченные недостатки и начнём разработку взаимодействия полос прокрутки с мышкой для управления содержимым формы.
Полосы прокрутки должны присутствовать у всех объектов, позволяющих прикреплять к себе другие элементы управления, а значит — это должны быть объекты-контейнеры. Изначально полоса прокрутки скрыта в случае, если содержимое контейнера умещается в его пределах. Если же содержимое стало выходить за пределы контейнера, то полоса прокрутки должна появиться, позволяя управлять видимой областью формы, смещая прикреплённые объекты в её пределах. Сегодня создадим две полосы прокрутки — вертикальную и горизонтальную и сделаем их видимыми для основной формы — чтобы поглядеть как они выглядят и что необходимо будет сделать с ними далее.
Доработка классов библиотеки
При наведении курсора мышки и захвате области управления ScrollBar (кнопки и ползунок прокрутки) они должны менять свой цвет. Цвет меняется при наведении курсора и захвате — для каждого состояния установлен свой цвет.
Внесём их в список макроподстановок в файле \MQL5\Include\DoEasy\Defines.mqh:
#define CLR_DEF_CONTROL_PROGRESS_BAR_BACK_COLOR (C'0xF0,0xF0,0xF0') // Цвет фона элемента управления ProgressBar #define CLR_DEF_CONTROL_PROGRESS_BAR_BORDER_COLOR (C'0xBC,0xBC,0xBC') // Цвет рамки элемента управления ProgressBar #define CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR (C'0x00,0x78,0xD7') // Цвет текста элемента управления ProgressBar #define CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR (C'0x06,0xB0,0x25') // Цвет линии прогресса элемента управления ProgressBar #define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR (C'0xF0,0xF0,0xF0') // Цвет фона элемента управления ScrollBar #define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR (C'0xFF,0xFF,0xFF') // Цвет рамки элемента управления ScrollBar #define CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR (C'0x60,0x60,0x60') // Цвет текста элемента управления ScrollBar #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_COLOR (C'0xCD,0xCD,0xCD') // Цвет области захвата элемента управления ScrollBar #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB__MOUSE_DOWN (C'0x60,0x60,0x60') // Цвет области захвата элемента управления ScrollBar при нажатии мышки на элемент управления #define CLR_DEF_CONTROL_SCROLL_BAR_THUMB_MOUSE_OVER (C'0xA6,0xA6,0xA6') // Цвет области захвата элемента управления ScrollBar при наведении мышки на элемент управления #define DEF_CONTROL_LIST_MARGIN_X (1) // Зазор между столбцами в элементах управления ListBox #define DEF_CONTROL_LIST_MARGIN_Y (0) // Зазор между строками в элементах управления ListBox
В этом же файле в список типов графических элементов добавим три новых типа:
//+------------------------------------------------------------------+ //| Список типов графических элементов | //+------------------------------------------------------------------+ enum ENUM_GRAPH_ELEMENT_TYPE { GRAPH_ELEMENT_TYPE_STANDARD, // Стандартный графический объект GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED, // Расширенный стандартный графический объект GRAPH_ELEMENT_TYPE_SHADOW_OBJ, // Объект тени GRAPH_ELEMENT_TYPE_ELEMENT, // Элемент GRAPH_ELEMENT_TYPE_FORM, // Форма GRAPH_ELEMENT_TYPE_WINDOW, // Окно //--- WinForms GRAPH_ELEMENT_TYPE_WF_UNDERLAY, // Подложка объекта-панели GRAPH_ELEMENT_TYPE_WF_BASE, // Windows Forms Base //--- Ниже нужно вписывать типы объектов "контейнер" GRAPH_ELEMENT_TYPE_WF_CONTAINER, // Windows Forms базовый объект-контейнер 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 //--- Ниже нужно вписывать типы объектов "стандартный элемент управления" GRAPH_ELEMENT_TYPE_WF_COMMON_BASE, // Windows Forms базовый стандартный элемент управления 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, // Базовый объект-список Windows Forms элементов 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 //--- Вспомогательные элементы WinForms-объектов 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, // Объект блика 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 MSG_GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR, // Элемент управления ProgressBar MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR, // Элемент управления ScrollBar MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL, // Элемент управления ScrollBarVertical MSG_GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL, // Элемент управления ScrollBarHorisontal MSG_GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ, // Объект блика
и тексты сообщений, соответствующие вновь добавленным индексам:
{"Элемент управления 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.
Внесём в него вывод описания новых объектов:
//+------------------------------------------------------------------+ //| Возвращает описание типа графического элемента | //+------------------------------------------------------------------+ 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) : //--- Контейнеры 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) : //--- Стандартные элементы управления 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) : //--- Вспомогательные объекты элементов управления 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, рассмотренным нами в статьях первой серии описания библиотеки.
Базовый класс вспомогательного элемента управления ScrollBar
Базовый объект-полоса прокрутки будет унаследован от базового класса всех WinForms-объектов библиотеки. Это будет некий абстрактный объект-полоса прокрутки, а в его наследниках уже будут уточняться необходимые параметры для конкретного объекта.
В папке вспомогательных объектов библиотеки \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ создадим новый класс CScrollBar в файле ScrollBar.mqh. Класс должен быть унаследован от класса CWinFormBase, а файлы этого и других классов должны быть подключены к файлу создаваемого объекта:
//+------------------------------------------------------------------+ //| ScrollBar.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/ru/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/ru/users/artmedia70" #property version "1.00" #property strict // Нужно для mql4 //+------------------------------------------------------------------+ //| Включаемые файлы | //+------------------------------------------------------------------+ #include "..\WinFormBase.mqh" #include "ArrowDownButton.mqh" #include "ArrowUpButton.mqh" #include "ArrowLeftButton.mqh" #include "ArrowRightButton.mqh" //+------------------------------------------------------------------+ //| Класс объекта CScrollBar элементов управления WForms | //+------------------------------------------------------------------+ class CScrollBar : public CWinFormBase {
В приватной секции класса объявим методы для создания кнопок со стрелками, стандартный для графических элементов библиотеки метод создания нового графического объекта, метод для рассчёта размера области захвата (ползунка) и метод инициализации параметров объекта:
//+------------------------------------------------------------------+ //| Класс объекта CScrollBar элементов управления WForms | //+------------------------------------------------------------------+ class CScrollBar : public CWinFormBase { private: //--- Создаёт объекты ArrowButton virtual void CreateArrowButtons(const int width,const int height) { return; } //--- Создаёт новый графический объект 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); //--- Рассчитывает размер области захвата virtual int CalculateThumbAreaSize(void); //--- Инициализирует свойства элемента void Initialize(void); protected:
Метод, рассчитывающий размеры ползунка в разных объектах-наследниках, будет выдавать разные размеры области захвата, так как её расположение зависит от ориентации полосы прокрутки — вертикальная или горизонтальная. Метод для создания объектов-кнопок тоже будет в разных унаследованных объектах создавать разные кнопки — для вертикальной полосы прокрутки нужны кнопки со стрелками вверх-вниз, а для горизонтальной — со стрелками влево-вправо. Все эти методы сделаны виртуальными для их переопределения в производных классах.
В защищённой секции класса объявим виртуальный метод для создания области захвата (в методе будут создаваться кнопки и ползунок), защищённый конструктор (стандартный для графических элементов библиотеки). В публичной секции напишем методы, возвращающие флаги поддержания свойств объекта, параметрический конструктор и виртуальный обработчик событий таймера объекта:
protected: //--- Создаёт объект-область захвата virtual void CreateThumbArea(void); //--- Защищённый конструктор с указанием типа объекта, идентификатора чарта и подокна 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: //--- Поддерживаемые свойства объекта (1) целочисленные, (2) вещественные, (3) строковые 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; } //--- Конструктор 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); //--- Таймер virtual void OnTimer(void); }; //+------------------------------------------------------------------+
Аналогичные методы мы рассматриваем каждый раз при создании каждого нового графического элемента — все они идентичны и имеют одно и то же назначение для каждого графического объекта библиотеки.
Рассмотрим реализацию объявленных методов.
Защищённый конструктор:
//+------------------------------------------------------------------+ //| Защищённый конструктор с указанием типа объекта, | //| идентификатора чарта и подокна | //+------------------------------------------------------------------+ 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) { //--- Установим объекту указанный тип графического элемента, а тип объекта библиотеки - как тип этого объекта this.SetTypeElement(type); this.m_type=OBJECT_DE_TYPE_GWF_HELPER; this.Initialize(); } //+------------------------------------------------------------------+
В конструктор передаётся тип создаваемого объекта и другие стандартные для создания графических элементов параметры. В строке инициализации в конструктор родительского класса передаётся тип создаваемого объекта. В теле конструктора устанавливаем тип графического элемента и тип графического объекта библиотеки и вызываем метод инициализации параметров.
Параметрический конструктор:
//+------------------------------------------------------------------+ //| Конструктор с указанием главного и базового объектов, | //| идентификатора чарта и подокна | //+------------------------------------------------------------------+ 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.
Метод инициализации свойства элемента:
//+------------------------------------------------------------------+ //| Инициализирует свойства элемента | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+
Здесь: устанавливаем размер рамки объекта в один пиксель с каждой стороны, устанавлиаем тип рамки "простая" и задаём цвета фона, рамки и текста элемента.
Метод, создающий объект-область захвата:
//+------------------------------------------------------------------+ //| Создаёт объект-область захвата | //+------------------------------------------------------------------+ void CScrollBar::CreateThumbArea(void) { this.CreateArrowButtons(DEF_ARROW_BUTTON_SIZE,DEF_ARROW_BUTTON_SIZE); } //+------------------------------------------------------------------+
В методе вызывается виртуальный метод CreateArrowButtons() для создания объектов-кнопок со стрелками и ползунка, который должен быть переопределён в объектах-наследниках.
Метод, рассчитывающий размер области захвата:
//+------------------------------------------------------------------+ //| Рассчитывает размер области захвата | //+------------------------------------------------------------------+ int CScrollBar::CalculateThumbAreaSize(void) { return 0; } //+------------------------------------------------------------------+
Здесь метод возвращает ноль, и должен быть переопределён в производных классах, так как для каждого из наследуемых объектов размеры и расположение ползунка — свои.
Метод, создающий новый графический объект:
//+------------------------------------------------------------------+ //| Создаёт новый графический объект | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+
Метод стандартный для графических объектов библиотеки. Позволяет создать пять элементов управления: кнопки со стрелками вверх-вниз, вправо-влево и объект-кнопку, на базе которой будет сделан ползунок.
Обработчик событий таймера:
//+------------------------------------------------------------------+ //| Таймер | //+------------------------------------------------------------------+ void CScrollBar::OnTimer(void) { } //+------------------------------------------------------------------+
На данный момент метод пустой и ничего не делает — им будем заниматься в последующих статьях.
Этот объект является абстрактой полосой прокрутки, ничего не делает, и служит для создания на его основе двух других объектов — вертикальной и горизонтальной полос прокрутки.
Производные от базового объекты ScrollBarVertical и ScrollBarHorisontal
Создадим объекты-наследники от базового абстрактного объекта-полосы прокрутки — вертикальную и горизонтальную.
В папке библиотеки \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ создадим новый файл ScrollBarVertical.mqh класса CScrollBarVertical.
Класс должен быть унаследован от базового объекта-полосы прокрутки, а его файл, и другие необходимые, подключены к файлу создаваемого класса:
//+------------------------------------------------------------------+ //| ScrollBarVertical.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/ru/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/ru/users/artmedia70" #property version "1.00" #property strict // Нужно для mql4 //+------------------------------------------------------------------+ //| Включаемые файлы | //+------------------------------------------------------------------+ #include "..\Containers\Container.mqh" #include "..\Common Controls\Button.mqh" #include "ArrowDownButton.mqh" #include "ArrowUpButton.mqh" #include "ScrollBar.mqh" //+------------------------------------------------------------------+ //| Класс объекта CScrollBarVertical элементов управления WForms | //+------------------------------------------------------------------+ class CScrollBarVertical : public CScrollBar { }
В приватной секции класса объявим виртуальный метод для создания кнопок со стрелками и метод для расчёта размера области захвата.
В защищённой секции объявим защищённый конструктор класса, а в публичной секции напишем методы, возвращающие флаги поддержания объектом его свойств, параметрический конструктор и обработчик событий таймера:
//+------------------------------------------------------------------+ //| Класс объекта CScrollBarVertical элементов управления WForms | //+------------------------------------------------------------------+ class CScrollBarVertical : public CScrollBar { private: //--- Создаёт объекты ArrowButton virtual void CreateArrowButtons(const int width,const int height); //--- Рассчитывает размер области захвата virtual int CalculateThumbAreaSize(void); protected: //--- Защищённый конструктор с указанием типа объекта, идентификатора чарта и подокна 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: //--- Поддерживаемые свойства объекта (1) целочисленные, (2) вещественные, (3) строковые 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; } //--- Конструктор 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); //--- Таймер virtual void OnTimer(void); }; //+------------------------------------------------------------------+
Рассмотрим объявленные методы подробнее.
Защищённый конструктор:
//+------------------------------------------------------------------+ //| Защищённый конструктор с указанием типа объекта, | //| идентификатора чарта и подокна | //+------------------------------------------------------------------+ 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) { //--- Установим объекту указанный тип графического элемента, а тип объекта библиотеки - как тип этого объекта this.SetTypeElement(type); this.CreateThumbArea(); } //+------------------------------------------------------------------+
В конструктор передаётся тип создаваемого объекта и другие параметры для его создания. В строке инициализации тип объекта передаётся в конструктор родительского класса. В теле конструктора устанавливаем тип графического объекта и вызываем метод создания области захвата (кнопок и ползунка).
Параметрический конструктор:
//+------------------------------------------------------------------+ //| Конструктор с указанием главного и базового объектов, | //| идентификатора чарта и подокна | //+------------------------------------------------------------------+ 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:
//+------------------------------------------------------------------+ //| Создаёт объекты ArrowButton | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+
Здесь: создаём объект-кнопку со стрелкой вверх, объект-кнопку со стрелкой вниз и объект-кнопку, который будет выполнять функции ползунка.
Во всех этих объектах уже создан и работает функционал взаимодействия с курсором мышки. Поэтому в следующей статье мы просто напишем обработчики событий этих объектов для управления содержимым контейнера, к которому прикреплена эта полоса прокрутки.
Метод, рассчитывающий размер области захвата:
//+------------------------------------------------------------------+ //| Рассчитывает размер области захвата | //+------------------------------------------------------------------+ int CScrollBarVertical::CalculateThumbAreaSize(void) { return 0; } //+------------------------------------------------------------------+
В данной версии объекта этот метод просто возвращает ноль. Объект-ползунок будет создан с жёстко-заданным размером, а все изменения его размеров будем делать в последующих статьях. Размер ползунка зависит от количества содержимого, выходящего за пределы контейнера — чем больше данных не умещается в видимой области формы, тем меньший размер имеет ползунок. Всеми этими рассчётами будем заниматься уже при создании функционала интерактивного взаимодействия мышки с полосой прокрутки.
Обработчик событий таймера:
//+------------------------------------------------------------------+ //| Таймер | //+------------------------------------------------------------------+ void CScrollBarVertical::OnTimer(void) { } //+------------------------------------------------------------------+
Созданием функционала обработчика будем заниматься в последующих статьях.
Элемент управления "Горизонтальная полоса прокрутки" идентичен только что созданному элементу управления "Вертикальная полоса прокрутки". Рассмотрим класс целиком без каких-либо пояснений, так как всё вышесказанное в равной степени относится и к классу этого объекта.
Класс должен быть создан в файле ScrollBarHorisontal.mqh в папке \MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ScrollBarHorisontal.mqh:
//+------------------------------------------------------------------+ //| ScrollBarVertical.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/ru/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/ru/users/artmedia70" #property version "1.00" #property strict // Нужно для mql4 //+------------------------------------------------------------------+ //| Включаемые файлы | //+------------------------------------------------------------------+ #include "..\Containers\Container.mqh" #include "..\Common Controls\Button.mqh" #include "ArrowLeftButton.mqh" #include "ArrowRightButton.mqh" //+------------------------------------------------------------------+ //| Класс объекта CScrollBarHorisontal элементов управления WForms | //+------------------------------------------------------------------+ class CScrollBarHorisontal : public CScrollBar { private: //--- Создаёт объекты ArrowButton virtual void CreateArrowButtons(const int width,const int height); //--- Рассчитывает размер области захвата virtual int CalculateThumbAreaSize(void); protected: //--- Защищённый конструктор с указанием типа объекта, идентификатора чарта и подокна 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: //--- Поддерживаемые свойства объекта (1) целочисленные, (2) вещественные, (3) строковые 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; } //--- Конструктор 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); //--- Таймер virtual void OnTimer(void); }; //+------------------------------------------------------------------+ //| Защищённый конструктор с указанием типа объекта, | //| идентификатора чарта и подокна | //+------------------------------------------------------------------+ 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) { //--- Установим объекту указанный тип графического элемента, а тип объекта библиотеки - как тип этого объекта this.SetTypeElement(type); this.CreateThumbArea(); } //+------------------------------------------------------------------+ //| Конструктор с указанием главного и базового объектов, | //| идентификатора чарта и подокна | //+------------------------------------------------------------------+ 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(); } //+------------------------------------------------------------------+ //| Создаёт объекты ArrowButton | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Рассчитывает размер области захвата | //+------------------------------------------------------------------+ int CScrollBarHorisontal::CalculateThumbAreaSize(void) { return 0; } //+------------------------------------------------------------------+ //| Таймер | //+------------------------------------------------------------------+ void CScrollBarHorisontal::OnTimer(void) { } //+------------------------------------------------------------------+
Написанные выше классы объектов-полос прокруток всегда создаются в каждом объекте-контейнере. Независимо от пользователя. По умолчанию. И они сразу же после создания скрываются. Появляться объекты будут только если содержимое контейнера выходит за его пределы, либо при предусмотренных программистом ситуациях. К слову — для теста мы их откроем для отображения в тестовой программе.
Соответственно, раз объекты должны присутствовать по умолчанию в объектах-контейнерах, то их создание необходимо организовать в классе объекта-контейнера в файле \MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Container.mqh.
Подключим файлы вновь созданных объектов к файлу объекта-контейнера. В приватной секции просто написанный виртуальный метод создания графических объектов сделаем объявлением этого метода (реализацию его напишем ниже — ранее его реализация делалась в наследуемых классах) и объявим методы для создания вертикальной и горизонтальной полос прокруток. В защищённой секции объявим метод для создания обеих полос прокрутки:
//+------------------------------------------------------------------+ //| Container.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/ru/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/ru/users/artmedia70" #property version "1.00" #property strict // Нужно для mql4 //+------------------------------------------------------------------+ //| Включаемые файлы | //+------------------------------------------------------------------+ #include "..\WinFormBase.mqh" #include "..\Common Controls\RadioButton.mqh" #include "..\Common Controls\Button.mqh" #include "..\Helpers\ScrollBarVertical.mqh" #include "..\Helpers\ScrollBarHorisontal.mqh" //+------------------------------------------------------------------+ //| Класс базового объекта-контейнера элементов управления WForms | //+------------------------------------------------------------------+ class CContainer : public CWinFormBase { private: //--- Создаёт новый графический объект 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; } //--- Рассчитывает координаты привязки Dock-объектов void CalculateCoords(CArrayObj *list); //--- Создаёт (1) вертикальный, (2) горизонтальный ScrollBar CWinFormBase *CreateScrollBarVertical(const int width); CWinFormBase *CreateScrollBarHorisontal(const int width); protected: //--- Подстраивает размеры элемента под его внутреннее содержимое bool AutoSizeProcess(const bool redraw); //--- Устанавливает параметры присоединённому объекту void SetObjParams(CWinFormBase *obj,const color colour); //--- Создаёт объекты ScrollBar вертикальный и горизонтальный void CreateScrollBars(const int width); public:
В обоих конструкторах класса в самом конце создания объекта вызовем метод создания обеих полос прокрутки:
//+------------------------------------------------------------------+ //| Защищённый конструктор с указанием типа объекта, | //| идентификатора чарта и подокна | //+------------------------------------------------------------------+ 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) { //--- Установим объекту указанный тип графического элемента, а тип объекта библиотеки - как тип этого объекта 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); } //+------------------------------------------------------------------+ //| Конструктор с указанием главного и базового объектов, | //| идентификатора чарта и подокна | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+
После создания объекта-контейнера будут созданы прикреплённые к нему две полосы прокрутки. После создания полосы будут скрыты.
В методе, устанавливающем параметры присоединённому объекту, напишем блок кода, где будут устанавливаться свойства вновь созданным объектам-полосам прокрутки:
//+------------------------------------------------------------------+ //| Устанавливает параметры присоединённому объекту | //+------------------------------------------------------------------+ void CContainer::SetObjParams(CWinFormBase *obj,const color colour) { //--- Устанавливаем объекту цвет текста как у базового контейнера obj.SetForeColor(this.ForeColor(),true); //--- Если созданный объект не является контейнером - устанавливаем для него такую же группу, как у его базового объекта if(obj.TypeGraphElement()<GRAPH_ELEMENT_TYPE_WF_CONTAINER || obj.TypeGraphElement()>GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER) obj.SetGroup(this.Group()); //--- В зависимости от типа объекта switch(obj.TypeGraphElement()) { //--- Для WinForms-объектов "Контейнер", "Панель", "GroupBox" case GRAPH_ELEMENT_TYPE_WF_CONTAINER : case GRAPH_ELEMENT_TYPE_WF_PANEL : case GRAPH_ELEMENT_TYPE_WF_GROUPBOX : obj.SetBorderColor(obj.BackgroundColor(),true); break; //--- Для WinForms-объектов "Label", "CheckBox", "RadioButton" 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; //--- Для WinForms-объекта "Button", "TabHeader", TabField, "ListBoxItem" 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; //--- Для WinForms-объекта "ListBox", "CheckedListBox", "ButtonListBox" 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; //--- Для WinForms-объекта "TabControl" 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; //--- Для WinForms-объекта "SplitContainer" 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; //--- Для WinForms-объекта "SplitContainerPanel" 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; //--- Для WinForms-объекта "Splitter" 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; //--- Для WinForms-объекта"ArrowButton" 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; //--- Для WinForms-объекта "Hint" 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; //--- Для WinForms-объекта "HintMoveLeft", "HintMoveRight", "HintMoveUp", "HintMoveDown", 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; //--- Для WinForms-объекта "ToolTip" 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; //--- Для WinForms-объекта "BarProgressBar" 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; //--- Для WinForms-объекта "ProgressBar" 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; //--- Для WinForms-объекта "ScrollBar" 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; //--- Для WinForms-объекта "GlareObj" 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(); } //+------------------------------------------------------------------+
Всегда, после создания прикреплённого к контейнеру объекта, вызывается этот метод, в котором созданному объекту устанавливаются параметры по умолчанию. Потом их можно будет поменять на другие. Но, после создания, они всегда устанавливаются автоматически в этом методе.
Метод, создающий объекты ScrollBar вертикальный и горизонтальный:
//+------------------------------------------------------------------+ //| Создаёт объекты ScrollBar вертикальный и горизонтальный | //+------------------------------------------------------------------+ void CContainer::CreateScrollBars(const int width) { //--- Создаём объект-вертикальную полосу прокрутки CScrollBarVertical *sbv=this.CreateScrollBarVertical(DEF_ARROW_BUTTON_SIZE); //--- Если объект создан if(sbv!=NULL) { //--- устанавливаем флаг неотображения объекта и скрываем его sbv.SetDisplayed(false); sbv.Hide(); } //--- Создаём объект-горизонтальную полосу прокрутки CScrollBarHorisontal *sbh=this.CreateScrollBarHorisontal(DEF_ARROW_BUTTON_SIZE); //--- Если объект создан if(sbh!=NULL) { //--- устанавливаем флаг неотображения объекта и скрываем его sbh.SetDisplayed(false); sbh.Hide(); } } //+------------------------------------------------------------------+
Логика метода прокомментирована в коде. Здесь просто создаём две полосы прокрутки и скрываем их, устанавливая им флаги неотображения при обновлении, отображении и перерисовке базового объекта, к которому они прикреплены. Т.е. полосы прокрутки возможно будет отобразить только явно сняв запрет их отображения в коде программы или библиотеки в дальнейшем.
Метод, создающий вертикальный ScrollBar:
//+------------------------------------------------------------------+ //| Создаёт вертикальный ScrollBar | //+------------------------------------------------------------------+ CWinFormBase *CContainer::CreateScrollBarVertical(const int width) { //--- Если не удалось создать объект-вертикальную полосу прокрутки - возвращаем 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 this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0); } //+------------------------------------------------------------------+
Создаём объект и возвращаем указатель на него из списка прикреплённых объектов.
Метод, создающий горизонтальный ScrollBar:
//+------------------------------------------------------------------+ //| Создаёт горизонтальный ScrollBar | //+------------------------------------------------------------------+ CWinFormBase *CContainer::CreateScrollBarHorisontal(const int width) { //--- Если не удалось создать объект-горизонтальную полосу прокрутки - возвращаем 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 this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0); } //+------------------------------------------------------------------+
Создаём объект и возвращаем указатель на него из списка прикреплённых объектов.
Метод, создающий новый графический объект:
//+------------------------------------------------------------------+ //| Создаёт новый графический объект | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+
Ранее метод ничего не делал и переопределялся в производных классах. Теперь этот метод здесь позволяет создать объекты-полосы прокрутки.
Так как полосы прокрутки прикреплены к объектам-контейнерам по их сторонам — снизу и справа, то изменение размеров формы должно вызывать и изменение объектов-полос прокрутки. Сделаем это в файле \MQL5\Include\DoEasy\Objects\Graph\WForms\WinFormBase.mqh базового WinForms-объекта.
В методе, устанавливающем новые размеры текущему объекту, впишем такой блок кода:
//+------------------------------------------------------------------+ //| Устанавливает новые размеры текущему объекту | //+------------------------------------------------------------------+ bool CWinFormBase::Resize(const int w,const int h,const bool redraw) { //--- Если ширина и высота объекта равны переданным - возвращаем true if(this.Width()==w && this.Height()==h) return true; //--- Объявляем переменную с результатом изменения свойства bool res=true; //--- Запоминаем изначальные размеры панели int prev_w=this.Width(); int prev_h=this.Height(); //--- В переменную res записываем результат изменения свойств //--- (если величина свойства не равна переданной величине) if(this.Width()!=w) res &=this.SetWidth(w); if(this.Height()!=h) res &=this.SetHeight(h); if(!res) return false; //--- Полчаем вертикальную полосу прокрутки и, если есть CWinFormBase *scroll_v=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0); if(scroll_v!=NULL) { //--- изменяем вертикальный размер под размер рабочей области контейнера scroll_v.Resize(scroll_v.Width(),this.Height()-this.BorderSizeTop()-this.BorderSizeBottom(),false); //--- Получаем из объекта-вертикальной полосы прокрутки объект-кнопку со стрелкой вниз CWinFormBase *arr_d=scroll_v.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0); //--- Если кнопка получена if(arr_d!=NULL) { //--- Перемещаем её к нижнему краю вертикальной полосы прокрутки 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()); } } } //--- Полчаем горизонтальную полосу прокрутки и, если есть CWinFormBase *scroll_h=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0); if(scroll_h!=NULL) { //--- изменяем горизонтальный размер под размер рабочей области контейнера scroll_h.Resize(this.Width()-this.BorderSizeLeft()-this.BorderSizeRight(),scroll_h.Height(),false); //--- Получаем из объекта-горизонтальной полосы прокрутки объект-кнопку со стрелкой вправо CWinFormBase *arr_r=scroll_h.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0); //--- Если кнопка получена if(arr_r!=NULL) { //--- Перемещаем её к правому краю горизонтальной полосы прокрутки 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()); } } } //--- Рассчитываем величину, на которую нужно изменить размеры int excess_w=this.Width()-prev_w; int excess_h=this.Height()-prev_h; //--- Получим объект "Тень" CShadowObj *shadow=this.GetShadowObj(); //--- Если у объекта есть тень, и объект "Тень" получен if(this.IsShadow() && shadow!=NULL) { //--- запомним смещения тени по X и Y, int x=shadow.CoordXRelative(); int y=shadow.CoordYRelative(); //--- установим новые ширину и высоту тени res &=shadow.SetWidth(shadow.Width()+excess_w); res &=shadow.SetHeight(shadow.Height()+excess_h); //--- Если в переменной res записано значение false - //--- значит была ошибка изменения размеров - возвращаем false if(!res) return false; //--- Если не нужно перерисовывать - сотрём тень if(!redraw) shadow.Erase(); //--- Запишем ранее сохранённые значения смещения тени относительно панели shadow.SetCoordXRelative(x); shadow.SetCoordYRelative(y); } //--- Перерисуем весь элемент с новыми размерами if(redraw) this.Redraw(true); //--- Всё успешно - возвращаем true return true; } //+------------------------------------------------------------------+
Теперь при изменении размеров объекта будут изменяться соответствующим образом и полосы прокрутки. Логика добавленного блока кода полностью расписана в комментариях.
Все файлы всех создаваемых графических элементов мы подключаем к библиотеке в файле класса объекта-панели.
В файле \MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Panel.mqh подключим файлы новых элементов управления:
//+------------------------------------------------------------------+ //| Включаемые файлы | //+------------------------------------------------------------------+ #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 элементов управления WForms | //+------------------------------------------------------------------+ class CPanel : public CContainer
В методе, создающем новый графический объект, добавим строки создания новых объектов-полос прокрутки:
//+------------------------------------------------------------------+ //| Создаёт новый графический объект | //+------------------------------------------------------------------+ 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.
Посмотрим что у нас получилось.
Тестирование
Для теста возьмём советник из прошлой статьи и сохраним его в новой папке\MQL5\Experts\TestDoEasy\Part129\ под новым именем TestDoEasy129.mq5.
В обработчике OnInit() в блоке кода для перерисовки всех созданных объектов добавим получение указателей на обе полосы прокрутки основного объекта-панели и принудительное их отображение — чтобы посмотреть в каком виде они создаются:
//--- Отобразим и перерисуем все созданные панели for(int i=0;i<FORMS_TOTAL;i++) { //--- Получаем объект-панель pnl=engine.GetWFPanel("WinForms Panel"+(string)i); if(pnl!=NULL) { //--- отображаем и перерисовываем панель pnl.Show(); pnl.Redraw(true); //--- Получаем указатель на объект-вертикальную полосу прокрутки основной панели CScrollBarVertical *sbv=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,0); //--- Устанавливаем для объекта флаг его отображения и показываем полосу прокрутки sbv.SetDisplayed(true); sbv.Show(); sbv.Redraw(true); //--- Получаем указатель на объект-горизонтальную полосу прокрутки основной панели CScrollBarHorisontal *sbh=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,0); //--- Устанавливаем для объекта флаг его отображения и показываем полосу прокрутки sbh.SetDisplayed(true); sbh.Show(); sbh.Redraw(true); //--- Получаем с панели объект TabControl CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0); //--- С первой вкладки объекта TabControl получаем объект SplitContainer CSplitContainer *sc=tc.GetTabElementByType(0,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,0); //--- С объекта SplitContainer получаем его вторую панель CSplitContainerPanel *scp=sc.GetPanel(1); //--- С полученной панели получаем объект ProgressBar CProgressBar *pb=scp.GetElementByType(GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0); //--- Ожидаем 1/10 секунды Sleep(100); //--- Получаем ширину объекта ProgressBar int w=pb.Width(); //--- В цикле с задержкой 1/50 увеличиваем ширину ProgressBar на 180 пикселей for(int n=0;n<180;n++) { Sleep(20); pb.Resize(w+n,pb.Height(),true); } //--- Устанавливаем значения для PerformStep объекта ProgressBar pb.SetValuesForProcessing(0,350,1,0); //--- Сбрасываем полосу прогресса объекта ProgressBar в минимальное положение pb.ResetProgressBar(); //--- Если стиль полосы прогресса "Непрерывная линия" - отображаем описание полосы прогресса if(pb.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS) pb.ShowBarDescription(); //--- Ожидаем 1/5 секунды Sleep(200); //--- Если стиль полосы прогресса не "Непрерывная прокрутка" if(pb.Style()!=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE) { //--- В цикле от минимального до максимального значения ProgressBar for(int n=0;n<=pb.Maximum();n++) { //--- вызываем метод увеличения полосы прогресса на заданный шаг с ожиданием в 1/5 секунды pb.PerformStep(); //--- Записываем в описание полосы прогресса количество пройденных шагов pb.SetBarDescriptionText("Progress Bar, pass: "+(InpProgressBarPercent ? pb.ValuePercentDescription() : pb.ValueDescription())); Sleep(20); } } //--- Ожидаем 1/2 секунды, устанавливаем для описания тип шрифта Bold и пишем на полосе прогресса сообщение о выполнении Sleep(500); pb.SetBarDescriptionFontFlags(FW_BOLD); pb.SetBarDescriptionText("Progress Bar: Done"); //--- Устанавливаем для объекта-блика тип - прямоугольник, непрозрачность 40, цвет - белый pb.SetGlareStyle(CANV_ELEMENT_VISUAL_EFF_STYLE_RECTANGLE); pb.SetGlareOpacity(40); pb.SetGlareColor(clrWhite); } }
Скомпилируем советник и запустим его на графике:
Видим, что полосы прокрутки созданы в правильных местах, имеют нормальные элементы управления, которые реагируют на взаимодействие с мышкой. Объекты элементов управления на полосах прокрутки при наведении на них указателя мышки окрашиваются в неправильные цвета. Это происходит потому, что для этих элементов управления мы ещё не создавали обработчики событий. В последующих статьях всё будет скорректировано, дополнено и исправлено.
Что дальше
В следующей статье продолжим развитие объекта ScrollBar.
*Статьи этой серии:
DoEasy. Элементы управления (Часть 26): Дорабатываем WinForms-объект "ToolTip" и начинаем разработку индикатора выполнения "ProgressBar"
DoEasy. Элементы управления (Часть 27): Продолжаем работу над WinForms-объектом "ProgressBar"
DoEasy. Элементы управления (Часть 28): Стили полосы в элементе управления "ProgressBar"





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования