//+------------------------------------------------------------------+ //| Base.mqh | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Включаемые библиотеки | //+------------------------------------------------------------------+ #include // Класс СБ CCanvas #include // Класс СБ CList #include "..\Tables.mqh" //--- Форвард-декларация классов элементов управления class CBoundedObj; // Базовый класс, хранящий размеры объекта class CCanvasBase; // Базовый класс холста графических элементов class CCounter; // Класс счётчика задержки class CAutoRepeat; // Класс автоповтора событий class CImagePainter; // Класс рисования изображений class CVisualHint; // Класс подсказки class CLabel; // Класс текстовой метки class CButton; // Класс простой кнопки class CButtonTriggered; // Класс двухпозиционной кнопки class CButtonArrowUp; // Класс кнопки со стрелкой вверх class CButtonArrowDown; // Класс кнопки со стрелкой вниз class CButtonArrowLeft; // Класс кнопки со стрелкой влево class CButtonArrowRight; // Класс кнопки со стрелкой вправо class CCheckBox; // Класс элемента управления CheckBox class CRadioButton; // Класс элемента управления RadioButton class CScrollBarThumbH; // Класс ползунка горизонтальной полосы прокрутки class CScrollBarThumbV; // Класс ползунка вертикальной полосы прокрутки class CScrollBarH; // Класс горизонтальной полосы прокрутки class CScrollBarV; // Класс вертикальной полосы прокрутки class CTableCellView; // Класс визуального представления ячейки таблицы class CTableRowView; // Класс визуального представления строки таблицы class CColumnCaptionView; // Класс визуального представления заголовка столбца таблицы class CTableHeaderView; // Класс визуального представления заголовка таблицы class CTableView; // Класс визуального представления таблицы class CTableControl; // Класс управления таблицами class CPanel; // Класс элемента управления Panel class CGroupBox; // Класс элемента управления GroupBox class CContainer; // Класс элемента управления Container //+------------------------------------------------------------------+ //| Макроподстановки | //+------------------------------------------------------------------+ #define clrNULL 0x00FFFFFF // Прозрачный цвет для CCanvas #ifndef __TABLES__ #define MARKER_START_DATA -1 // Маркер начала данных в файле #endif #define DEF_FONTNAME "Calibri" // Шрифт по умолчанию #define DEF_FONTSIZE 10 // Размер шрифта по умолчанию #define DEF_EDGE_THICKNESS 3 // Толщина зоны для захвата границы/угла //+------------------------------------------------------------------+ //| Перечисления | //+------------------------------------------------------------------+ enum ENUM_ELEMENT_TYPE // Перечисление типов графических элементов { ELEMENT_TYPE_BASE = 0x10000, // Базовый объект графических элементов ELEMENT_TYPE_COLOR, // Объект цвета ELEMENT_TYPE_COLORS_ELEMENT, // Объект цветов элемента графического объекта ELEMENT_TYPE_RECTANGLE_AREA, // Прямоугольная область элемента ELEMENT_TYPE_IMAGE_PAINTER, // Объект для рисования изображений ELEMENT_TYPE_COUNTER, // Объект счётчика ELEMENT_TYPE_AUTOREPEAT_CONTROL, // Объект автоповтора событий ELEMENT_TYPE_BOUNDED_BASE, // Базовый объект размеров графических элементов ELEMENT_TYPE_CANVAS_BASE, // Базовый объект холста графических элементов ELEMENT_TYPE_ELEMENT_BASE, // Базовый объект графических элементов ELEMENT_TYPE_HINT, // Подсказка ELEMENT_TYPE_LABEL, // Текстовая метка ELEMENT_TYPE_BUTTON, // Простая кнопка ELEMENT_TYPE_BUTTON_TRIGGERED, // Двухпозиционная кнопка ELEMENT_TYPE_BUTTON_ARROW_UP, // Кнопка со стрелкой вверх ELEMENT_TYPE_BUTTON_ARROW_DOWN, // Кнопка со стрелкой вниз ELEMENT_TYPE_BUTTON_ARROW_LEFT, // Кнопка со стрелкой влево ELEMENT_TYPE_BUTTON_ARROW_RIGHT, // Кнопка со стрелкой вправо ELEMENT_TYPE_CHECKBOX, // Элемент управления CheckBox ELEMENT_TYPE_RADIOBUTTON, // Элемент управления RadioButton ELEMENT_TYPE_SCROLLBAR_THUMB_H, // Ползунок горизонтальной полосы прокрутки ELEMENT_TYPE_SCROLLBAR_THUMB_V, // Ползунок вертикальной полосы прокрутки ELEMENT_TYPE_SCROLLBAR_H, // Элемент управления ScrollBarHorisontal ELEMENT_TYPE_SCROLLBAR_V, // Элемент управления ScrollBarVertical ELEMENT_TYPE_TABLE_CELL_VIEW, // Ячейка таблицы (View) ELEMENT_TYPE_TABLE_ROW_VIEW, // Строка таблицы (View) ELEMENT_TYPE_TABLE_COLUMN_CAPTION_VIEW,// Заголовок столбца таблицы (View) ELEMENT_TYPE_TABLE_HEADER_VIEW, // Заголовок таблицы (View) ELEMENT_TYPE_TABLE_VIEW, // Таблица (View) ELEMENT_TYPE_TABLE_CONTROL_VIEW, // Элемент управления таблицами (View) ELEMENT_TYPE_PANEL, // Элемент управления Panel ELEMENT_TYPE_GROUPBOX, // Элемент управления GroupBox ELEMENT_TYPE_CONTAINER, // Элемент управления Container }; #define ACTIVE_ELEMENT_MIN ELEMENT_TYPE_LABEL // Минимальное значение списка активных элементов #define ACTIVE_ELEMENT_MAX ELEMENT_TYPE_TABLE_HEADER_VIEW // Максимальное значение списка активных элементов enum ENUM_ELEMENT_STATE // Состояние элемента { ELEMENT_STATE_DEF, // По умолчанию (напр. кнопка отжата, и т.п.) ELEMENT_STATE_ACT, // Активирован (напр. кнопка нажата, и т.п.) }; enum ENUM_COLOR_STATE // Перечисление цветов состояний элемента { COLOR_STATE_DEFAULT, // Цвет обычного состояния COLOR_STATE_FOCUSED, // Цвет при наведении курсора на элемент COLOR_STATE_PRESSED, // Цвет при нажатии на элемент COLOR_STATE_BLOCKED, // Цвет заблокированного элемента }; enum ENUM_BASE_COMPARE_BY // Сравниваемые свойства базовых объектов { BASE_SORT_BY_ID = 0, // Сравнение базовых объектов по идентификатору BASE_SORT_BY_NAME, // Сравнение базовых объектов по имени BASE_SORT_BY_X, // Сравнение базовых объектов по координате X BASE_SORT_BY_Y, // Сравнение базовых объектов по координате Y BASE_SORT_BY_WIDTH, // Сравнение базовых объектов по ширине BASE_SORT_BY_HEIGHT, // Сравнение базовых объектов по высоте BASE_SORT_BY_ZORDER, // Сравнение по Z-order объектов }; enum ENUM_CURSOR_REGION // Перечисление расположения курсора на границах элемента { CURSOR_REGION_NONE, // Нет CURSOR_REGION_TOP, // На верхней грани CURSOR_REGION_BOTTOM, // На нижней грани CURSOR_REGION_LEFT, // На левой грани CURSOR_REGION_RIGHT, // На правой грани CURSOR_REGION_LEFT_TOP, // В левом верхнем углу CURSOR_REGION_LEFT_BOTTOM, // В левом нижнем углу CURSOR_REGION_RIGHT_TOP, // В правом верхнем углу CURSOR_REGION_RIGHT_BOTTOM, // В правом нижнем углу }; enum ENUM_RESIZE_ZONE_ACTION // Перечисление взаимодействий с зоной перетаскивания элемента { RESIZE_ZONE_ACTION_NONE, // Нет RESIZE_ZONE_ACTION_HOVER, // Наведение курсора на зону RESIZE_ZONE_ACTION_BEGIN, // Начало перетаскивания RESIZE_ZONE_ACTION_DRAG, // Процесс перетаскивания RESIZE_ZONE_ACTION_END // Завершение перетаскивания }; //+------------------------------------------------------------------+ //| Функции | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Возвращает тип элемента как строку | //+------------------------------------------------------------------+ string ElementDescription(const ENUM_ELEMENT_TYPE type) { string array[]; int total=StringSplit(EnumToString(type),StringGetCharacter("_",0),array); if(array[array.Size()-1]=="V") array[array.Size()-1]="Vertical"; if(array[array.Size()-1]=="H") array[array.Size()-1]="Horisontal"; string result=""; for(int i=2;iobj.ID() ? 1 : this.ID() obj.Name() ? 1 : this.Name()>8)&0xFF; } double GetB(const color clr) { return(clr>>16)&0xFF; } public: //--- Возвращает новый цвет color NewColor(color base_color, int shift_red, int shift_green, int shift_blue); //--- Инициализация класса void Init(void); //--- Инициализация цветов различных состояний bool InitDefault(const color clr) { return this.m_default.SetColor(clr); } bool InitFocused(const color clr) { return this.m_focused.SetColor(clr); } bool InitPressed(const color clr) { return this.m_pressed.SetColor(clr); } bool InitBlocked(const color clr) { return this.m_blocked.SetColor(clr); } //--- Установка цветов для всех состояний void InitColors(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked); void InitColors(const color clr); //--- Возврат цветов различных состояний color GetCurrent(void) const { return this.m_current.Get(); } color GetDefault(void) const { return this.m_default.Get(); } color GetFocused(void) const { return this.m_focused.Get(); } color GetPressed(void) const { return this.m_pressed.Get(); } color GetBlocked(void) const { return this.m_blocked.Get(); } //--- Устанавливает один из списка цветов как текущий bool SetCurrentAs(const ENUM_COLOR_STATE color_state); //--- Возвращает описание объекта virtual string Description(void); //--- Виртуальные методы (1) сохранения в файл, (2) загрузки из файла, (3) тип объекта virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); virtual int Type(void) const { return(ELEMENT_TYPE_COLORS_ELEMENT); } //--- Конструкторы/деструктор CColorElement(void); CColorElement(const color clr); CColorElement(const color clr_default,const color clr_focused,const color clr_pressed,const color clr_blocked); ~CColorElement(void) {} }; //+------------------------------------------------------------------+ //| CColorElement::Конструктор с установкой прозрачных цветов объекта| //+------------------------------------------------------------------+ CColorElement::CColorElement(void) { this.InitColors(clrNULL,clrNULL,clrNULL,clrNULL); this.Init(); } //+------------------------------------------------------------------+ //| CColorElement::Конструктор с указанием цветов объекта | //+------------------------------------------------------------------+ CColorElement::CColorElement(const color clr_default,const color clr_focused,const color clr_pressed,const color clr_blocked) { this.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); this.Init(); } //+------------------------------------------------------------------+ //| CColorElement::Конструктор с указанием цвета объекта | //+------------------------------------------------------------------+ CColorElement::CColorElement(const color clr) { this.InitColors(clr); this.Init(); } //+------------------------------------------------------------------+ //| CColorElement::Инициализация класса | //+------------------------------------------------------------------+ void CColorElement::Init(void) { this.m_default.SetName("Default"); this.m_default.SetID(1); this.m_focused.SetName("Focused"); this.m_focused.SetID(2); this.m_pressed.SetName("Pressed"); this.m_pressed.SetID(3); this.m_blocked.SetName("Blocked"); this.m_blocked.SetID(4); this.SetCurrentAs(COLOR_STATE_DEFAULT); this.m_current.SetName("Current"); this.m_current.SetID(0); } //+------------------------------------------------------------------+ //| CColorElement::Устанавливает цвета для всех состояний | //+------------------------------------------------------------------+ void CColorElement::InitColors(const color clr_default,const color clr_focused,const color clr_pressed,const color clr_blocked) { this.InitDefault(clr_default); this.InitFocused(clr_focused); this.InitPressed(clr_pressed); this.InitBlocked(clr_blocked); } //+------------------------------------------------------------------+ //| CColorElement::Устанавливает цвета для всех состояний по текущему| //+------------------------------------------------------------------+ void CColorElement::InitColors(const color clr) { this.InitDefault(clr); this.InitFocused(clr!=clrNULL ? this.NewColor(clr,-20,-20,-20) : clrNULL); this.InitPressed(clr!=clrNULL ? this.NewColor(clr,-40,-40,-40) : clrNULL); this.InitBlocked(clrWhiteSmoke); } //+-------------------------------------------------------------------+ //|CColorElement::Устанавливает один цвет из списка цветов как текущий| //+-------------------------------------------------------------------+ bool CColorElement::SetCurrentAs(const ENUM_COLOR_STATE color_state) { switch(color_state) { case COLOR_STATE_DEFAULT : return this.m_current.SetColor(this.m_default.Get()); case COLOR_STATE_FOCUSED : return this.m_current.SetColor(this.m_focused.Get()); case COLOR_STATE_PRESSED : return this.m_current.SetColor(this.m_pressed.Get()); case COLOR_STATE_BLOCKED : return this.m_current.SetColor(this.m_blocked.Get()); default : return false; } } //+------------------------------------------------------------------+ //| CColorElement::Преобразует RGB в color | //+------------------------------------------------------------------+ color CColorElement::RGBToColor(const double r,const double g,const double b) const { int int_r=(int)::round(r); int int_g=(int)::round(g); int int_b=(int)::round(b); int clr=0; clr=int_b; clr<<=8; clr|=int_g; clr<<=8; clr|=int_r; return (color)clr; } //+------------------------------------------------------------------+ //| CColorElement::Получение значений компонентов RGB | //+------------------------------------------------------------------+ void CColorElement::ColorToRGB(const color clr,double &r,double &g,double &b) { r=this.GetR(clr); g=this.GetG(clr); b=this.GetB(clr); } //+------------------------------------------------------------------+ //| CColorElement::Возвращает цвет с новой цветовой составляющей | //+------------------------------------------------------------------+ color CColorElement::NewColor(color base_color, int shift_red, int shift_green, int shift_blue) { double clrR=0, clrG=0, clrB=0; this.ColorToRGB(base_color,clrR,clrG,clrB); double clrRx=(clrR+shift_red < 0 ? 0 : clrR+shift_red > 255 ? 255 : clrR+shift_red); double clrGx=(clrG+shift_green< 0 ? 0 : clrG+shift_green> 255 ? 255 : clrG+shift_green); double clrBx=(clrB+shift_blue < 0 ? 0 : clrB+shift_blue > 255 ? 255 : clrB+shift_blue); return this.RGBToColor(clrRx,clrGx,clrBx); } //+------------------------------------------------------------------+ //| CColorElement::Возвращает описание объекта | //+------------------------------------------------------------------+ string CColorElement::Description(void) { string res=::StringFormat("%s Colors. %s",this.Name(),this.m_current.Description()); res+="\n 1: "+this.m_default.Description(); res+="\n 2: "+this.m_focused.Description(); res+="\n 3: "+this.m_pressed.Description(); res+="\n 4: "+this.m_blocked.Description(); return res; } //+------------------------------------------------------------------+ //| CColorElement::Сохранение в файл | //+------------------------------------------------------------------+ bool CColorElement::Save(const int file_handle) { //--- Сохраняем данные родительского объекта if(!CBaseObj::Save(file_handle)) return false; //--- Сохраняем текущий цвет if(!this.m_current.Save(file_handle)) return false; //--- Сохраняем цвет обычного состояния if(!this.m_default.Save(file_handle)) return false; //--- Сохраняем цвет при наведении курсора if(!this.m_focused.Save(file_handle)) return false; //--- Сохраняем цвет при нажатии if(!this.m_pressed.Save(file_handle)) return false; //--- Сохраняем цвет заблокированного элемента if(!this.m_blocked.Save(file_handle)) return false; //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| CColorElement::Загрузка из файла | //+------------------------------------------------------------------+ bool CColorElement::Load(const int file_handle) { //--- Загружаем данные родительского объекта if(!CBaseObj::Load(file_handle)) return false; //--- Загружаем текущий цвет if(!this.m_current.Load(file_handle)) return false; //--- Загружаем цвет обычного состояния if(!this.m_default.Load(file_handle)) return false; //--- Загружаем цвет при наведении курсора if(!this.m_focused.Load(file_handle)) return false; //--- Загружаем цвет при нажатии if(!this.m_pressed.Load(file_handle)) return false; //--- Загружаем цвет заблокированного элемента if(!this.m_blocked.Load(file_handle)) return false; //--- Всё успешно return true; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Класс прямоугольной области | //+------------------------------------------------------------------+ class CBound : public CBaseObj { protected: CBaseObj *m_assigned_obj; // Назначенный на область объект CRect m_bound; // Структура прямоугольной области public: //--- Изменяет (1) ширину, (2) высоту, (3) размер ограничивающего прямоугольника void ResizeW(const int size) { this.m_bound.Width(size); } void ResizeH(const int size) { this.m_bound.Height(size); } void Resize(const int w,const int h) { this.m_bound.Width(w); this.m_bound.Height(h); } //--- Устанавливает координату (1) X, (2) Y, (3) обе координаты ограничивающего прямоугольника void SetX(const int x) { this.m_bound.left=x; } void SetY(const int y) { this.m_bound.top=y; } void SetXY(const int x,const int y) { this.m_bound.LeftTop(x,y); } //--- (1) Устанавливает, (2) смещает ограничивающий прямоугольник на указанные координаты/размер смещения void Move(const int x,const int y) { this.m_bound.Move(x,y); } void Shift(const int dx,const int dy) { this.m_bound.Shift(dx,dy); } //--- Возвращает координаты, размеры и границы объекта int X(void) const { return this.m_bound.left; } int Y(void) const { return this.m_bound.top; } int Width(void) const { return this.m_bound.Width(); } int Height(void) const { return this.m_bound.Height(); } int Right(void) const { return this.m_bound.right-(this.m_bound.Width() >0 ? 1 : 0);} int Bottom(void) const { return this.m_bound.bottom-(this.m_bound.Height()>0 ? 1 : 0);} //--- Возвращает флаг нахождения курсора внутри области bool Contains(const int x,const int y) const { return this.m_bound.Contains(x,y); } //--- (1) Назначает, (2) снимает назначение, (3) возвращает указатель на назначенный элемент void AssignObject(CBaseObj *obj) { this.m_assigned_obj=obj; } void UnassignObject(void) { this.m_assigned_obj=NULL; } CBaseObj *GetAssignedObj(void) { return this.m_assigned_obj; } //--- Возвращает описание объекта virtual string Description(void); //--- Виртуальные методы (1) сравнения, (2) сохранения в файл, (3) загрузки из файла, (4) тип объекта virtual int Compare(const CObject *node,const int mode=0) const; virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); virtual int Type(void) const { return(ELEMENT_TYPE_RECTANGLE_AREA); } //--- Конструкторы/деструктор CBound(void) { ::ZeroMemory(this.m_bound); } CBound(const int x,const int y,const int w,const int h) { this.SetXY(x,y); this.Resize(w,h); } ~CBound(void) { ::ZeroMemory(this.m_bound); } }; //+------------------------------------------------------------------+ //| CBound::Возвращает описание объекта | //+------------------------------------------------------------------+ string CBound::Description(void) { string nm=this.Name(); string name=(nm!="" ? ::StringFormat(" \"%s\"",nm) : nm); return ::StringFormat("%s%s: id %d, x %d, y %d, w %d, h %d, right %d, bottom %d", ElementDescription((ENUM_ELEMENT_TYPE)this.Type()),name,this.ID(), this.X(),this.Y(),this.Width(),this.Height(),this.Right(),this.Bottom()); } //+------------------------------------------------------------------+ //| CBound::Сравнение двух объектов | //+------------------------------------------------------------------+ int CBound::Compare(const CObject *node,const int mode=0) const { if(node==NULL) return -1; const CBound *obj=node; switch(mode) { case BASE_SORT_BY_NAME : return(this.Name() >obj.Name() ? 1 : this.Name() obj.X() ? 1 : this.X() obj.Y() ? 1 : this.Y() obj.Width() ? 1 : this.Width() obj.Height() ? 1 : this.Height() obj.ID() ? 1 : this.ID() this.m_delay) { //--- сбрасываем флаг запущенного отсчёта и возвращаем true this.m_launched=false; return true; } //--- Заданное время ещё не прошло return false; } //--- Виртуальные методы (1) сохранения в файл, (2) загрузки из файла, (3) тип объекта virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); virtual int Type(void) const { return(ELEMENT_TYPE_COUNTER); } //--- Конструктор/деструктор CCounter(void) : m_start(0), m_delay(0), m_launched(false) {} ~CCounter(void) {} }; //+------------------------------------------------------------------+ //| CCounter::Сохранение в файл | //+------------------------------------------------------------------+ bool CCounter::Save(const int file_handle) { //--- Сохраняем данные родительского объекта if(!CBaseObj::Save(file_handle)) return false; //--- Сохраняем значение задержки if(::FileWriteInteger(file_handle,this.m_delay,INT_VALUE)!=INT_VALUE) return false; //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| CCounter::Загрузка из файла | //+------------------------------------------------------------------+ bool CCounter::Load(const int file_handle) { //--- Загружаем данные родительского объекта if(!CBaseObj::Load(file_handle)) return false; //--- Загружаем значение задержки this.m_delay=::FileReadInteger(file_handle,INT_VALUE); //--- Всё успешно return true; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Класс автоповтора событий | //+------------------------------------------------------------------+ class CAutoRepeat : public CBaseObj { private: CCounter m_delay_counter; // Счетчик для задержки перед автоповтором CCounter m_repeat_counter; // Счетчик для периодической отправки событий long m_chart_id; // График для отправки пользовательского события bool m_button_pressed; // Флаг, указывающий нажата ли кнопка bool m_auto_repeat_started; // Флаг, указывающий начался ли автоповтор uint m_delay_before_repeat; // Задержка перед началом автоповтора (мс) uint m_repeat_interval; // Периодичность отправки событий (мс) ushort m_event_id; // Идентификатор пользовательского события long m_event_lparam; // long-параметр пользовательского события double m_event_dparam; // double-параметр пользовательского события string m_event_sparam; // string-параметр пользовательского события //--- Отправка пользовательского события void SendEvent() { ::EventChartCustom((this.m_chart_id<=0 ? ::ChartID() : this.m_chart_id), this.m_event_id, this.m_event_lparam, this.m_event_dparam, this.m_event_sparam); } public: //--- Тип объекта virtual int Type(void) const { return(ELEMENT_TYPE_AUTOREPEAT_CONTROL); } //--- Конструкторы CAutoRepeat(void) : m_button_pressed(false), m_auto_repeat_started(false), m_delay_before_repeat(350), m_repeat_interval(100), m_event_id(0), m_event_lparam(0), m_event_dparam(0), m_event_sparam(""), m_chart_id(::ChartID()) {} CAutoRepeat(long chart_id, int delay_before_repeat=350, int repeat_interval=100, ushort event_id=0, long event_lparam=0, double event_dparam=0, string event_sparam="") : m_button_pressed(false), m_auto_repeat_started(false), m_delay_before_repeat(delay_before_repeat), m_repeat_interval(repeat_interval), m_event_id(event_id), m_event_lparam(event_lparam), m_event_dparam(event_dparam), m_event_sparam(event_sparam), m_chart_id(chart_id) {} //--- Установка идентификатора графика void SetChartID(const long chart_id) { this.m_chart_id=chart_id; } void SetDelay(const uint delay) { this.m_delay_before_repeat=delay; } void SetInterval(const uint interval) { this.m_repeat_interval=interval; } //--- Установка идентификатора и параметров пользовательского события void SetEvent(ushort event_id, long event_lparam, double event_dparam, string event_sparam) { this.m_event_id=event_id; this.m_event_lparam=event_lparam; this.m_event_dparam=event_dparam; this.m_event_sparam=event_sparam; } //--- Возврат флагов bool ButtonPressedFlag(void) const { return this.m_button_pressed; } bool AutorepeatStartedFlag(void) const { return this.m_auto_repeat_started;} uint Delay(void) const { return this.m_delay_before_repeat;} uint Interval(void) const { return this.m_repeat_interval; } //--- Обработка нажатия кнопки (запуск автоповтора) void OnButtonPress(void) { if(this.m_button_pressed) return; this.m_button_pressed=true; this.m_auto_repeat_started=false; this.m_delay_counter.Start(this.m_delay_before_repeat); // Запускаем счётчик ожидания } //--- Обработка отпускания кнопки (остановка автоповтора) void OnButtonRelease(void) { this.m_button_pressed=false; this.m_auto_repeat_started=false; } //--- Метод выполнения автоповтора (запускается в таймере) void Process(void) { //--- Если кнопка удерживается if(this.m_button_pressed) { //--- Проверяем, истекла ли задержка перед началом автоповтора if(!this.m_auto_repeat_started && this.m_delay_counter.IsDone()) { this.m_auto_repeat_started=true; this.m_repeat_counter.Start(this.m_repeat_interval); // Запускаем счетчик автоповтора } //--- Если автоповтор начался, проверяем периодичность отправки событий if(this.m_auto_repeat_started && this.m_repeat_counter.IsDone()) { //--- Отправляем событие и перезапускаем счетчик this.SendEvent(); this.m_repeat_counter.Start(this.m_repeat_interval); } } } }; //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Базовый класс, хранящий размеры объекта | //+------------------------------------------------------------------+ class CBoundedObj : public CBaseObj { protected: CBound m_bound; // Границы объекта bool m_canvas_owner; // Флаг владения канвасами public: //--- Возвращает координаты, размеры и границы объекта int X(void) const { return this.m_bound.X(); } int Y(void) const { return this.m_bound.Y(); } int Width(void) const { return this.m_bound.Width(); } int Height(void) const { return this.m_bound.Height(); } int Right(void) const { return this.m_bound.Right(); } int Bottom(void) const { return this.m_bound.Bottom(); } //--- Изменяет (1) ширину, (2) высоту, (3) размер ограничивающего прямоугольника void BoundResizeW(const int size) { this.m_bound.ResizeW(size); } void BoundResizeH(const int size) { this.m_bound.ResizeH(size); } void BoundResize(const int w,const int h) { this.m_bound.Resize(w,h); } //--- Устанавливает координату (1) X, (2) Y, (3) обе координаты ограничивающего прямоугольника void BoundSetX(const int x) { this.m_bound.SetX(x); } void BoundSetY(const int y) { this.m_bound.SetY(y); } void BoundSetXY(const int x,const int y) { this.m_bound.SetXY(x,y); } //--- (1) Устанавливает, (2) смещает ограничивающий прямоугольник на указанные координаты/размер смещения void BoundMove(const int x,const int y) { this.m_bound.Move(x,y); } void BoundShift(const int dx,const int dy) { this.m_bound.Shift(dx,dy); } //--- Виртуальные методы (1) сравнения, (2) сохранения в файл, (3) загрузки из файла, (4) тип объекта //virtual int Compare(const CObject *node,const int mode=0) const; virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); virtual int Type(void) const { return(ELEMENT_TYPE_BOUNDED_BASE); } CBoundedObj (void) : m_canvas_owner(true) {} CBoundedObj (const string user_name,const int id,const int x,const int y,const int w,const int h); ~CBoundedObj (void){} }; //+------------------------------------------------------------------+ //| CBoundedObj::Конструктор | //+------------------------------------------------------------------+ CBoundedObj::CBoundedObj(const string user_name,const int id,const int x,const int y,const int w,const int h) : m_canvas_owner(true) { //--- Получаем скорректированный идентификатор графика и дистанцию в пикселях по вертикальной оси Y this.m_bound.SetName(user_name); this.m_bound.SetID(id); this.m_bound.SetXY(x,y); this.m_bound.Resize(w,h); } //+------------------------------------------------------------------+ //| CBoundedObj::Сохранение в файл | //+------------------------------------------------------------------+ bool CBoundedObj::Save(const int file_handle) { //--- Сохраняем данные родительского объекта if(!CBaseObj::Save(file_handle)) return false; //--- Сохраняем флаг владения канвасами if(::FileWriteInteger(file_handle,this.m_canvas_owner,INT_VALUE)!=INT_VALUE) return false; //--- Сохраняем размеры return this.m_bound.Save(file_handle); } //+------------------------------------------------------------------+ //| CBoundedObj::Загрузка из файла | //+------------------------------------------------------------------+ bool CBoundedObj::Load(const int file_handle) { //--- Загружаем данные родительского объекта if(!CBaseObj::Load(file_handle)) return false; //--- Загружаем флаг владения канвасами this.m_canvas_owner=::FileReadInteger(file_handle,INT_VALUE); //--- Загружаем размеры return this.m_bound.Load(file_handle); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Базовый класс холста графических элементов | //+------------------------------------------------------------------+ class CCanvasBase : public CBoundedObj { private: bool m_chart_mouse_wheel_flag; // Флаг отправки сообщений о прокрутке колёсика мышки bool m_chart_mouse_move_flag; // Флаг отправки сообщений о перемещениях курсора мышки bool m_chart_object_create_flag; // Флаг отправки сообщений о событии создания графического объекта bool m_chart_mouse_scroll_flag; // Флаг прокрутки графика левой кнопкой и колёсиком мышки bool m_chart_context_menu_flag; // Флаг доступа к контекстному меню по нажатию правой клавиши мышки bool m_chart_crosshair_tool_flag; // Флаг доступа к инструменту "Перекрестие" по нажатию средней клавиши мышки bool m_flags_state; // Состояние флагов прокрутки графика колёсиком, контекстного меню и перекрестия //--- Установка запретов для графика (прокрутка колёсиком, контекстное меню и перекрестие) void SetFlags(const bool flag); protected: CCanvas *m_background; // Канвас для рисования фона CCanvas *m_foreground; // Канвас для рисования переднего плана CCanvasBase *m_container; // Родительский объект-контейнер CColorElement m_color_background; // Объект управления цветом фона CColorElement m_color_foreground; // Объект управления цветом переднего плана CColorElement m_color_border; // Объект управления цветом рамки CColorElement m_color_background_act; // Объект управления цветом фона активированного элемента CColorElement m_color_foreground_act; // Объект управления цветом переднего плана активированного элемента CColorElement m_color_border_act; // Объект управления цветом рамки активированного элемента CAutoRepeat m_autorepeat; // Объект управления автоповторами событий ENUM_ELEMENT_STATE m_state; // Состояние элемента (напр., кнопки (вкл/выкл)) long m_chart_id; // Идентификатор графика int m_wnd; // Номер подокна графика int m_wnd_y; // Смещение координаты Y курсора в подокне int m_obj_x; // Координата X графического объекта int m_obj_y; // Координата Y графического объекта uchar m_alpha_bg; // Прозрачность фона uchar m_alpha_fg; // Прозрачность переднего плана uint m_border_width_lt; // Ширина рамки слева uint m_border_width_rt; // Ширина рамки справа uint m_border_width_up; // Ширина рамки сверху uint m_border_width_dn; // Ширина рамки снизу string m_program_name; // Имя программы bool m_hidden; // Флаг скрытого объекта bool m_blocked; // Флаг заблокированного элемента bool m_movable; // Флаг перемещаемого элемента bool m_resizable; // Флаг разрешения изменения размеров bool m_focused; // Флаг элемента в фокусе bool m_main; // Флаг главного объекта bool m_autorepeat_flag; // Флаг автоповтора отправки событий bool m_scroll_flag; // Флаг прокрутки содержимого при помощи скроллбаров bool m_trim_flag; // Флаг обрезки элемента по границам контейнера bool m_cropped; // Флаг того, что объект скрыт за границами контейнера int m_cursor_delta_x; // Дистанция от курсора до левого края элемента int m_cursor_delta_y; // Дистанция от курсора до верхнего края элемента int m_z_order; // Z-ордер графического объекта //--- (1) Устанавливает имя, возвращает (2) имя, (3) флаг активного элемента void SetActiveElementName(const string name) { CCommonManager::GetInstance().SetElementName(name); } string ActiveElementName(void) const { return CCommonManager::GetInstance().ElementName(); } bool IsCurrentActiveElement(void) const { return this.ActiveElementName()==this.NameFG(); } //--- (1) Устанавливает, (2) возвращает флаг режима изменения размеров void SetResizeMode(const bool flag) { CCommonManager::GetInstance().SetResizeMode(flag); } bool ResizeMode(void) const { return CCommonManager::GetInstance().ResizeMode(); } //--- (1) Устанавливает, (2) возвращает грань элемента, за которую изменяется размер void SetResizeRegion(const ENUM_CURSOR_REGION edge){ CCommonManager::GetInstance().SetResizeRegion(edge); } ENUM_CURSOR_REGION ResizeRegion(void) const { return CCommonManager::GetInstance().ResizeRegion(); } //--- Возвращает смещения начальных координат рисования на холсте относительно канваса и координат объекта int CanvasOffsetX(void) const { return(this.ObjectX()-this.X()); } int CanvasOffsetY(void) const { return(this.ObjectY()-this.Y()); } //--- Возвращает скорректированную координату точки на холсте с учётом смещения холста относительно объекта int AdjX(const int x) const { return(x-this.CanvasOffsetX()); } int AdjY(const int y) const { return(y-this.CanvasOffsetY()); } //--- Возвращает скорректированный идентификатор графика long CorrectChartID(const long chart_id) const { return(chart_id!=0 ? chart_id : ::ChartID()); } public: //--- Получение границ родительского объекта-контейнера int ContainerLimitLeft(void) const { return(this.m_container==NULL ? this.ObjectX() : this.m_container.LimitLeft()); } int ContainerLimitRight(void) const { return(this.m_container==NULL ? this.ObjectRight() : this.m_container.LimitRight()); } int ContainerLimitTop(void) const { return(this.m_container==NULL ? this.ObjectY() : this.m_container.LimitTop()); } int ContainerLimitBottom(void) const { return(this.m_container==NULL ? this.ObjectBottom(): this.m_container.LimitBottom());} string ContainerDescription(void) const { return(this.m_container==NULL ? "Not specified" : this.m_container.Description());} //--- Возврат координат, границ и размеров графического объекта int ObjectX(void) const { return this.m_obj_x; } int ObjectY(void) const { return this.m_obj_y; } int ObjectWidth(void) const { return this.m_background.Width(); } int ObjectHeight(void) const { return this.m_background.Height(); } int ObjectRight(void) const { return this.ObjectX()+this.ObjectWidth()-1; } int ObjectBottom(void) const { return this.ObjectY()+this.ObjectHeight()-1; } //--- Изменяет (1) ширину, (2) высоту, (3) размер графического объекта protected: virtual bool ObjectResizeW(const int size); virtual bool ObjectResizeH(const int size); bool ObjectResize(const int w,const int h); //--- Устанавливает координату (1) X, (2) Y, (3) обе координаты графического объекта virtual bool ObjectSetX(const int x); virtual bool ObjectSetY(const int y); bool ObjectSetXY(const int x,const int y) { return(this.ObjectSetX(x) && this.ObjectSetY(y)); } //--- Устанавливает одновременно координаты и размеры графического объекта virtual bool ObjectSetXYWidthResize(const int x,const int y,const int w,const int h); //--- (1) Устанавливает, (2) смещает графический объект на указанные координаты/размер смещения bool ObjectMove(const int x,const int y) { return this.ObjectSetXY(x,y); } bool ObjectShift(const int dx,const int dy) { return this.ObjectSetXY(this.ObjectX()+dx,this.ObjectY()+dy); } //--- Возвращает флаг нахождения курсора внутри объекта bool Contains(const int x,const int y); //--- Возвращает место нахождения курсора на границах объекта ENUM_CURSOR_REGION CheckResizeZone(const int x,const int y); //--- Проверяет установленный цвет на равенство указанному bool CheckColor(const ENUM_COLOR_STATE state) const; //--- Изменяет цвета фона, текста и рамки в зависимости от условия void ColorChange(const ENUM_COLOR_STATE state); //--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию void Init(void); void InitColors(void); //--- Обработчики событий (1) наведения курсора (Focus), (2) нажатий кнопок мышки (Press), //--- (3) перемещения курсора (Move), (4) ухода из фокуса (Release), (5) создания графического объекта (Create), //--- (6) прокрутки колёсика (Wheel), (7) изменение размеров (Resize). Переопределяются в наследниках. virtual void OnFocusEvent(const int id, const long lparam, const double dparam, const string sparam); virtual void OnPressEvent(const int id, const long lparam, const double dparam, const string sparam); virtual void OnMoveEvent(const int id, const long lparam, const double dparam, const string sparam); virtual void OnReleaseEvent(const int id, const long lparam, const double dparam, const string sparam); virtual void OnCreateEvent(const int id, const long lparam, const double dparam, const string sparam); virtual void OnWheelEvent(const int id, const long lparam, const double dparam, const string sparam) { return; } // обработчик здесь отключен virtual void OnResizeZoneEvent(const int id, const long lparam, const double dparam, const string sparam) { return; } // обработчик здесь отключен //--- Обработчики изменения размеров элемента по сторонам и углам virtual bool OnResizeZoneLeft(const int x, const int y) { return false; } // обработчик здесь отключен virtual bool OnResizeZoneRight(const int x, const int y) { return false; } // обработчик здесь отключен virtual bool OnResizeZoneTop(const int x, const int y) { return false; } // обработчик здесь отключен virtual bool OnResizeZoneBottom(const int x, const int y) { return false; } // обработчик здесь отключен virtual bool OnResizeZoneLeftTop(const int x, const int y) { return false; } // обработчик здесь отключен virtual bool OnResizeZoneRightTop(const int x, const int y) { return false; } // обработчик здесь отключен virtual bool OnResizeZoneLeftBottom(const int x, const int y) { return false; } // обработчик здесь отключен virtual bool OnResizeZoneRightBottom(const int x, const int y) { return false; } // обработчик здесь отключен //--- Обработчики пользовательских событий элемента при наведении курсора, щелчке, прокрутке колёсика в области объекта и его изменения virtual void MouseMoveHandler(const int id, const long lparam, const double dparam, const string sparam) { return; } // обработчик здесь отключен virtual void MousePressHandler(const int id, const long lparam, const double dparam, const string sparam) { return; } // обработчик здесь отключен virtual void MouseWheelHandler(const int id, const long lparam, const double dparam, const string sparam) { return; } // обработчик здесь отключен virtual void ObjectChangeHandler(const int id, const long lparam, const double dparam, const string sparam) { return; } // обработчик здесь отключен public: //--- Возвращает указатель на (1) контейнер, (2) объект класса автоповтора событий CCanvasBase *GetContainer(void) const { return this.m_container; } CAutoRepeat *GetAutorepeatObj(void) { return &this.m_autorepeat; } //--- Возвращает указатель на канвас (1) фона, (2) переднего плана CCanvas *GetBackground(void) { return this.m_background; } CCanvas *GetForeground(void) { return this.m_foreground; } //--- Возвращает указатель на объект управления цветом (1) фона, (2) переднего плана, (3) рамки CColorElement *GetBackColorControl(void) { return &this.m_color_background; } CColorElement *GetForeColorControl(void) { return &this.m_color_foreground; } CColorElement *GetBorderColorControl(void) { return &this.m_color_border; } //--- Возвращает указатель на объект управления цветом (1) фона, (2) переднего плана, (3) рамки активированного элемента CColorElement *GetBackColorActControl(void) { return &this.m_color_background_act; } CColorElement *GetForeColorActControl(void) { return &this.m_color_foreground_act; } CColorElement *GetBorderColorActControl(void) { return &this.m_color_border_act; } //--- Возврат текущего цвета (1) фона, (2) переднего плана, (3) рамки color BackColor(void) const { return(!this.State() ? this.m_color_background.GetCurrent() : this.m_color_background_act.GetCurrent()); } color ForeColor(void) const { return(!this.State() ? this.m_color_foreground.GetCurrent() : this.m_color_foreground_act.GetCurrent()); } color BorderColor(void) const { return(!this.State() ? this.m_color_border.GetCurrent() : this.m_color_border_act.GetCurrent()); } //--- Возврат предустановленного цвета DEFAULT (1) фона, (2) переднего плана, (3) рамки color BackColorDefault(void) const { return(!this.State() ? this.m_color_background.GetDefault() : this.m_color_background_act.GetDefault()); } color ForeColorDefault(void) const { return(!this.State() ? this.m_color_foreground.GetDefault() : this.m_color_foreground_act.GetDefault()); } color BorderColorDefault(void)const { return(!this.State() ? this.m_color_border.GetDefault() : this.m_color_border_act.GetDefault()); } //--- Возврат предустановленного цвета FOCUSED (1) фона, (2) переднего плана, (3) рамки color BackColorFocused(void) const { return(!this.State() ? this.m_color_background.GetFocused() : this.m_color_background_act.GetFocused()); } color ForeColorFocused(void) const { return(!this.State() ? this.m_color_foreground.GetFocused() : this.m_color_foreground_act.GetFocused()); } color BorderColorFocused(void)const { return(!this.State() ? this.m_color_border.GetFocused() : this.m_color_border_act.GetFocused()); } //--- Возврат предустановленного цвета PRESSED (1) фона, (2) переднего плана, (3) рамки color BackColorPressed(void) const { return(!this.State() ? this.m_color_background.GetPressed() : this.m_color_background_act.GetPressed()); } color ForeColorPressed(void) const { return(!this.State() ? this.m_color_foreground.GetPressed() : this.m_color_foreground_act.GetPressed()); } color BorderColorPressed(void)const { return(!this.State() ? this.m_color_border.GetPressed() : this.m_color_border_act.GetPressed()); } //--- Возврат предустановленного цвета BLOCKED (1) фона, (2) переднего плана, (3) рамки color BackColorBlocked(void) const { return this.m_color_background.GetBlocked(); } color ForeColorBlocked(void) const { return this.m_color_foreground.GetBlocked(); } color BorderColorBlocked(void) const { return this.m_color_border.GetBlocked(); } //--- Установка цветов фона для всех состояний void InitBackColors(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_background.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitBackColors(const color clr) { this.m_color_background.InitColors(clr); } //--- Установка цветов переднего плана для всех состояний void InitForeColors(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_foreground.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitForeColors(const color clr) { this.m_color_foreground.InitColors(clr); } //--- Установка цветов рамки для всех состояний void InitBorderColors(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_border.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitBorderColors(const color clr) { this.m_color_border.InitColors(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки начальными значениями void InitBackColorDefault(const color clr) { this.m_color_background.InitDefault(clr); } void InitForeColorDefault(const color clr) { this.m_color_foreground.InitDefault(clr); } void InitBorderColorDefault(const color clr) { this.m_color_border.InitDefault(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки при наведении курсора начальными значениями void InitBackColorFocused(const color clr) { this.m_color_background.InitFocused(clr); } void InitForeColorFocused(const color clr) { this.m_color_foreground.InitFocused(clr); } void InitBorderColorFocused(const color clr) { this.m_color_border.InitFocused(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки при щелчке по объекту начальными значениями void InitBackColorPressed(const color clr) { this.m_color_background.InitPressed(clr); } void InitForeColorPressed(const color clr) { this.m_color_foreground.InitPressed(clr); } void InitBorderColorPressed(const color clr) { this.m_color_border.InitPressed(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки для заблокированного объекта начальными значениями void InitBackColorBlocked(const color clr) { this.m_color_background.InitBlocked(clr); } void InitForeColorBlocked(const color clr) { this.m_color_foreground.InitBlocked(clr); } void InitBorderColorBlocked(const color clr) { this.m_color_border.InitBlocked(clr); } //--- Установка цветов фона для всех состояний void InitBackColorsAct(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_background_act.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitBackColorsAct(const color clr) { this.m_color_background_act.InitColors(clr); } //--- Установка цветов переднего плана для всех состояний void InitForeColorsAct(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_foreground_act.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitForeColorsAct(const color clr) { this.m_color_foreground_act.InitColors(clr); } //--- Установка цветов рамки для всех состояний void InitBorderColorsAct(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_border_act.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitBorderColorsAct(const color clr) { this.m_color_border_act.InitColors(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки начальными значениями void InitBackColorActDefault(const color clr) { this.m_color_background_act.InitDefault(clr); } void InitForeColorActDefault(const color clr) { this.m_color_foreground_act.InitDefault(clr); } void InitBorderColorActDefault(const color clr){ this.m_color_border_act.InitDefault(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки при наведении курсора начальными значениями void InitBackColorActFocused(const color clr) { this.m_color_background_act.InitFocused(clr); } void InitForeColorActFocused(const color clr) { this.m_color_foreground_act.InitFocused(clr); } void InitBorderColorActFocused(const color clr){ this.m_color_border_act.InitFocused(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки при щелчке по объекту начальными значениями void InitBackColorActPressed(const color clr) { this.m_color_background_act.InitPressed(clr); } void InitForeColorActPressed(const color clr) { this.m_color_foreground_act.InitPressed(clr); } void InitBorderColorActPressed(const color clr){ this.m_color_border_act.InitPressed(clr); } //--- Установка текущего цвета фона в различные состояния bool BackColorToDefault(void) { return(!this.State() ? this.m_color_background.SetCurrentAs(COLOR_STATE_DEFAULT) : this.m_color_background_act.SetCurrentAs(COLOR_STATE_DEFAULT)); } bool BackColorToFocused(void) { return(!this.State() ? this.m_color_background.SetCurrentAs(COLOR_STATE_FOCUSED) : this.m_color_background_act.SetCurrentAs(COLOR_STATE_FOCUSED)); } bool BackColorToPressed(void) { return(!this.State() ? this.m_color_background.SetCurrentAs(COLOR_STATE_PRESSED) : this.m_color_background_act.SetCurrentAs(COLOR_STATE_PRESSED)); } bool BackColorToBlocked(void) { return this.m_color_background.SetCurrentAs(COLOR_STATE_BLOCKED); } //--- Установка текущего цвета переднего плана в различные состояния bool ForeColorToDefault(void) { return(!this.State() ? this.m_color_foreground.SetCurrentAs(COLOR_STATE_DEFAULT) : this.m_color_foreground_act.SetCurrentAs(COLOR_STATE_DEFAULT)); } bool ForeColorToFocused(void) { return(!this.State() ? this.m_color_foreground.SetCurrentAs(COLOR_STATE_FOCUSED) : this.m_color_foreground_act.SetCurrentAs(COLOR_STATE_FOCUSED)); } bool ForeColorToPressed(void) { return(!this.State() ? this.m_color_foreground.SetCurrentAs(COLOR_STATE_PRESSED) : this.m_color_foreground_act.SetCurrentAs(COLOR_STATE_PRESSED)); } bool ForeColorToBlocked(void) { return this.m_color_foreground.SetCurrentAs(COLOR_STATE_BLOCKED); } //--- Установка текущего цвета рамки в различные состояния bool BorderColorToDefault(void) { return(!this.State() ? this.m_color_border.SetCurrentAs(COLOR_STATE_DEFAULT) : this.m_color_border_act.SetCurrentAs(COLOR_STATE_DEFAULT)); } bool BorderColorToFocused(void) { return(!this.State() ? this.m_color_border.SetCurrentAs(COLOR_STATE_FOCUSED) : this.m_color_border_act.SetCurrentAs(COLOR_STATE_FOCUSED)); } bool BorderColorToPressed(void) { return(!this.State() ? this.m_color_border.SetCurrentAs(COLOR_STATE_PRESSED) : this.m_color_border_act.SetCurrentAs(COLOR_STATE_PRESSED)); } bool BorderColorToBlocked(void) { return this.m_color_border.SetCurrentAs(COLOR_STATE_BLOCKED); } //--- Установка текущих цветов элемента в различные состояния bool ColorsToDefault(void); bool ColorsToFocused(void); bool ColorsToPressed(void); bool ColorsToBlocked(void); //--- Устанавливает указатель на родительский объект-контейнер void SetContainerObj(CCanvasBase *obj); protected: //--- Создаёт канвасы фона и переднего плана bool CreateCanvasObjects(void); //--- Создаёт OBJ_BITMAP_LABEL bool Create(const long chart_id,const int wnd,const string object_name,const int x,const int y,const int w,const int h); public: //--- (1) Устанавливает, (2) возвращает состояние void SetState(ENUM_ELEMENT_STATE state) { this.m_state=state; this.ColorsToDefault(); } ENUM_ELEMENT_STATE State(void) const { return this.m_state; } //--- (1) Устанавливает, (2) возвращает z-ордер bool ObjectSetZOrder(const int value); int ObjectZOrder(void) const { return this.m_z_order; } //--- Возвращает (1) принадлежность объекта программе, флаг (2) скрытого, (3) заблокированного, //--- (4) перемещаемого, (5) изменяемого в размерах, (6) главного элемента, (7) в фокусе, (8, 9) имя графического объекта (фон, текст) bool IsBelongsToThis(const string name) const { return(::ObjectGetString(this.m_chart_id,name,OBJPROP_TEXT)==this.m_program_name);} bool IsHidden(void) const { return this.m_hidden; } bool IsBlocked(void) const { return this.m_blocked; } bool IsMovable(void) const { return this.m_movable; } bool IsResizable(void) const { return this.m_resizable; } bool IsMain(void) const { return this.m_main; } bool IsFocused(void) const { return this.m_focused; } bool IsAutorepeat(void) const { return this.m_autorepeat_flag; } bool IsScrollable(void) const { return this.m_scroll_flag; } bool IsTrimmed(void) const { return this.m_trim_flag; } bool IsCropped(void) const { return this.m_cropped; } string NameBG(void) const { return this.m_background.ChartObjectName(); } string NameFG(void) const { return this.m_foreground.ChartObjectName(); } //--- (1) Возвращает, (2) устанавливает прозрачность фона uchar AlphaBG(void) const { return this.m_alpha_bg; } void SetAlphaBG(const uchar value) { this.m_alpha_bg=value; } //--- (1) Возвращает, (2) устанавливает прозрачность переднего плана uchar AlphaFG(void) const { return this.m_alpha_fg; } void SetAlphaFG(const uchar value) { this.m_alpha_fg=value; } //--- Устанавливает прозрачность для фона и переднего плана void SetAlpha(const uchar value) { this.m_alpha_fg=this.m_alpha_bg=value; } //--- (1) Возвращает, (2) устанавливает ширину рамки слева uint BorderWidthLeft(void) const { return this.m_border_width_lt; } void SetBorderWidthLeft(const uint width) { this.m_border_width_lt=width; } //--- (1) Возвращает, (2) устанавливает ширину рамки справа uint BorderWidthRight(void) const { return this.m_border_width_rt; } void SetBorderWidthRight(const uint width) { this.m_border_width_rt=width; } //--- (1) Возвращает, (2) устанавливает ширину рамки сверху uint BorderWidthTop(void) const { return this.m_border_width_up; } void SetBorderWidthTop(const uint width) { this.m_border_width_up=width; } //--- (1) Возвращает, (2) устанавливает ширину рамки снизу uint BorderWidthBottom(void) const { return this.m_border_width_dn; } void SetBorderWidthBottom(const uint width) { this.m_border_width_dn=width; } //--- Устанавливает одинаковую ширину рамки со всех сторон void SetBorderWidth(const uint width) { this.m_border_width_lt=this.m_border_width_rt=this.m_border_width_up=this.m_border_width_dn=width; } //--- Устанавливает ширину рамки void SetBorderWidth(const uint left,const uint right,const uint top,const uint bottom) { this.m_border_width_lt=left; this.m_border_width_rt=right; this.m_border_width_up=top; this.m_border_width_dn=bottom; } //--- Возврат границ объекта с учётом рамки int LimitLeft(void) const { return this.ObjectX()+(int)this.m_border_width_lt; } int LimitRight(void) const { return this.ObjectRight()-(int)this.m_border_width_rt; } int LimitTop(void) const { return this.ObjectY()+(int)this.m_border_width_up; } int LimitBottom(void) const { return this.ObjectBottom()-(int)this.m_border_width_dn; } //--- Устанавливает объекту флаг (1) перемещаемости, (2) главного объекта, (3) возможности изменения размеров, //--- (4) автоповтора событий, (5) прокрутки внутри контейнера, (6) обрезки по границам контейнера void SetMovable(const bool flag) { this.m_movable=flag; } void SetAsMain(void) { this.m_main=true; } virtual void SetResizable(const bool flag) { this.m_resizable=flag; } void SetAutorepeat(const bool flag) { this.m_autorepeat_flag=flag; } void SetScrollable(const bool flag) { this.m_scroll_flag=flag; } virtual void SetTrimmered(const bool flag) { this.m_trim_flag=flag; } void SetCropped(const bool flag) { this.m_cropped=flag; } //--- Возвращает флаг того, что объект расположен за пределами своего контейнера virtual bool IsOutOfContainer(void); //--- Ограничивает графический объект по размерам контейнера virtual bool ObjectTrim(void); //--- Изменяет размеры объекта virtual bool ResizeW(const int w); virtual bool ResizeH(const int h); virtual bool Resize(const int w,const int h); //--- Устанавливает объекту новую координату (1) X, (2) Y, (3) XY virtual bool MoveX(const int x); virtual bool MoveY(const int y); virtual bool Move(const int x,const int y); //--- Устанавливает одновременно координаты и размеры элемента virtual bool MoveXYWidthResize(const int x,const int y,const int w,const int h); //--- Смещает объект по оси (1) X, (2) Y, (3) XY на указанное смещение virtual bool ShiftX(const int dx); virtual bool ShiftY(const int dy); virtual bool Shift(const int dx,const int dy); //--- (1) Скрывает (2) отображает объект на всех периодах графика, //--- (3) помещает объект на передний план, (4) блокирует, (5) разблокирует элемент, //--- (6) заливает объект указанным цветом с установленной прозрачностью virtual void Hide(const bool chart_redraw); virtual void Show(const bool chart_redraw); virtual void BringToTop(const bool chart_redraw); virtual void Block(const bool chart_redraw); virtual void Unblock(const bool chart_redraw); void Fill(const color clr,const bool chart_redraw); //--- (1) Заливает объект прозрачным цветом, (2) обновляет объект для отображения изменений, //--- (3) рисует внешний вид, (4) уничтожает объект virtual void Clear(const bool chart_redraw); virtual void Update(const bool chart_redraw); virtual void Draw(const bool chart_redraw); virtual void Destroy(void); //--- Возвращает описание объекта virtual string Description(void); //--- Виртуальные методы (1) сравнения, (2) сохранения в файл, (3) загрузки из файла, (4) тип объекта virtual int Compare(const CObject *node,const int mode=0) const; virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); virtual int Type(void) const { return(ELEMENT_TYPE_CANVAS_BASE); } //--- Обработчик событий virtual void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam); //--- (1) Таймер, (2) обработчик события таймера virtual void OnTimer() { this.TimerEventHandler(); } virtual void TimerEventHandler(void) { return; } //--- Конструкторы/деструктор CCanvasBase(void) : m_program_name(::MQLInfoString(MQL_PROGRAM_NAME)), m_chart_id(::ChartID()), m_wnd(0), m_alpha_bg(0), m_alpha_fg(255), m_hidden(false), m_blocked(false), m_focused(false), m_movable(false), m_resizable(false), m_main(false), m_autorepeat_flag(false), m_trim_flag(true), m_cropped(false), m_scroll_flag(false), m_border_width_lt(0), m_border_width_rt(0), m_border_width_up(0), m_border_width_dn(0), m_z_order(0), m_state(0), m_wnd_y(0), m_cursor_delta_x(0), m_cursor_delta_y(0) { this.CreateCanvasObjects(); this.Init(); } CCanvasBase(const string object_name,const long chart_id,const int wnd,const int x,const int y,const int w,const int h); ~CCanvasBase(void); }; //+------------------------------------------------------------------+ //| CCanvasBase::Конструктор | //+------------------------------------------------------------------+ CCanvasBase::CCanvasBase(const string object_name,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) : m_program_name(::MQLInfoString(MQL_PROGRAM_NAME)), m_wnd(wnd<0 ? 0 : wnd), m_alpha_bg(0), m_alpha_fg(255), m_hidden(false), m_blocked(false), m_focused(false), m_movable(false), m_resizable(false), m_main(false), m_autorepeat_flag(false), m_trim_flag(true), m_cropped(false), m_scroll_flag(false), m_border_width_lt(0), m_border_width_rt(0), m_border_width_up(0), m_border_width_dn(0), m_z_order(0), m_state(0), m_cursor_delta_x(0), m_cursor_delta_y(0) { //--- Получаем скорректированный идентификатор графика и дистанцию в пикселях по вертикальной оси Y //--- между верхней рамкой подокна индикатора и верхней рамкой главного окна графика this.m_chart_id=this.CorrectChartID(chart_id); //--- Если не удалось создать канвасы - уходим if(!this.CreateCanvasObjects()) return; //--- Если графический ресурс и графический объект созданы if(this.Create(this.m_chart_id,this.m_wnd,object_name,x,y,w,h)) { //--- Очищаем канвасы фона и переднего плана и устанавливаем начальные значения координат, //--- наименования графических объектов и свойства текста, рисуемого на переднем плане this.Clear(false); this.m_obj_x=x; this.m_obj_y=y; this.m_color_background.SetName("Background"); this.m_color_foreground.SetName("Foreground"); this.m_color_border.SetName("Border"); this.m_foreground.FontSet(DEF_FONTNAME,-DEF_FONTSIZE*10,FW_MEDIUM); this.m_bound.SetName("Perimeter"); //--- Запоминаем разрешения для мышки и инструментов графика this.Init(); } } //+------------------------------------------------------------------+ //| CCanvasBase::Деструктор | //+------------------------------------------------------------------+ CCanvasBase::~CCanvasBase(void) { //--- Уничтожаем объект this.Destroy(); //--- Возвращаем разрешения для мышки и инструментов графика ::ChartSetInteger(this.m_chart_id, CHART_EVENT_MOUSE_WHEEL, this.m_chart_mouse_wheel_flag); ::ChartSetInteger(this.m_chart_id, CHART_EVENT_MOUSE_MOVE, this.m_chart_mouse_move_flag); ::ChartSetInteger(this.m_chart_id, CHART_EVENT_OBJECT_CREATE, this.m_chart_object_create_flag); ::ChartSetInteger(this.m_chart_id, CHART_MOUSE_SCROLL, this.m_chart_mouse_scroll_flag); ::ChartSetInteger(this.m_chart_id, CHART_CONTEXT_MENU, this.m_chart_context_menu_flag); ::ChartSetInteger(this.m_chart_id, CHART_CROSSHAIR_TOOL, this.m_chart_crosshair_tool_flag); } //+------------------------------------------------------------------+ //| CCanvasBase::Сравнение двух объектов | //+------------------------------------------------------------------+ int CCanvasBase::Compare(const CObject *node,const int mode=0) const { if(node==NULL) return -1; const CCanvasBase *obj=node; switch(mode) { case BASE_SORT_BY_NAME : return(this.Name() >obj.Name() ? 1 : this.Name() obj.X() ? 1 : this.X() obj.Y() ? 1 : this.Y() obj.Width() ? 1 : this.Width() obj.Height() ? 1 : this.Height() obj.ObjectZOrder() ? 1 : this.ObjectZOrder() obj.ID() ? 1 : this.ID() 0 ? w : 1),(h>0 ? h : 1),COLOR_FORMAT_ARGB_NORMALIZE)) { ::PrintFormat("%s: The CreateBitmapLabel() method of the CCanvas class returned an error creating a \"%s\" graphic object",__FUNCTION__,obj_name); return false; } //--- Создаём имя графического объекта для переднего плана и создаём канвас obj_name=nm+"FG"; if(!this.m_foreground.CreateBitmapLabel(id,(wnd<0 ? 0 : wnd),obj_name,x,y,(w>0 ? w : 1),(h>0 ? h : 1),COLOR_FORMAT_ARGB_NORMALIZE)) { ::PrintFormat("%s: The CreateBitmapLabel() method of the CCanvas class returned an error creating a \"%s\" graphic object",__FUNCTION__,obj_name); return false; } //--- При успешном создании в свойство графического объекта OBJPROP_TEXT вписываем наименование программы ::ObjectSetString(id,this.NameBG(),OBJPROP_TEXT,this.m_program_name); ::ObjectSetString(id,this.NameFG(),OBJPROP_TEXT,this.m_program_name); ::ObjectSetString(id,this.NameBG(),OBJPROP_TOOLTIP,"\n"); ::ObjectSetString(id,this.NameFG(),OBJPROP_TOOLTIP,"\n"); ::ObjectSetInteger(id,this.NameBG(),OBJPROP_ZORDER,0); ::ObjectSetInteger(id,this.NameFG(),OBJPROP_ZORDER,0); //--- Устанавливаем размеры прямоугольной области и возвращаем true this.m_bound.SetXY(x,y); this.m_bound.Resize(w,h); return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает указатель | //| на родительский объект-контейнер | //+------------------------------------------------------------------+ void CCanvasBase::SetContainerObj(CCanvasBase *obj) { //--- Устанавливаем переданный указатель объекту this.m_container=obj; //--- Если указатель пустой - уходим if(this.m_container==NULL) return; //--- Если передан невалидный указатель - обнуляем его в объекте и уходим if(::CheckPointer(this.m_container)==POINTER_INVALID) { this.m_container=NULL; return; } //--- Обрезаем объект по границам назначенного ему контейнера this.ObjectTrim(); } //+------------------------------------------------------------------+ //| CCanvasBase::Возвращает флаг того, что объект | //| расположен за пределами своего контейнера | //+------------------------------------------------------------------+ bool CCanvasBase::IsOutOfContainer(void) { //--- Возвращаем результат проверки, что объект полностью выходит за пределы контейнера return(this.Right() <= this.ContainerLimitLeft() || this.X() >= this.ContainerLimitRight() || this.Bottom()<= this.ContainerLimitTop() || this.Y() >= this.ContainerLimitBottom()); } //+------------------------------------------------------------------+ //| CCanvasBase::Подрезает графический объект по контуру контейнера | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectTrim() { //--- Проверяем флаг разрешения обрезки элемента и, //--- если элемент не должен обрезаться по границам контейнера - возвращаем false if(!this.m_trim_flag) return false; //--- Получаем границы контейнера int container_left = this.ContainerLimitLeft(); int container_right = this.ContainerLimitRight(); int container_top = this.ContainerLimitTop(); int container_bottom = this.ContainerLimitBottom(); //--- Получаем текущие границы объекта int object_left = this.X(); int object_right = this.Right(); int object_top = this.Y(); int object_bottom = this.Bottom(); //--- Проверяем, полностью ли объект выходит за пределы контейнера и, если да - скрываем его if(this.IsOutOfContainer()) { //--- Устанавливаем флаг, что объект за пределами контейнера this.m_cropped=true; //--- Скрываем объект и восстанавливаем его размеры this.Hide(false); if(this.ObjectResize(this.Width(),this.Height())) this.BoundResize(this.Width(),this.Height()); return true; } //--- Объект полностью или частично находится внутри видимой области контейнера else { //--- Снимаем флаг расположения объекта за пределами контейнера this.m_cropped=false; //--- Если элемент полностью внутри контейнера if(object_right<=container_right && object_left>=container_left && object_bottom<=container_bottom && object_top>=container_top) { //--- Если ширина или высота графического объекта не совпадает с шириной или высотой элемента, //--- модифицируем графический объект по размерам элемента и возвращаем true if(this.ObjectWidth()!=this.Width() || this.ObjectHeight()!=this.Height()) { if(this.ObjectResize(this.Width(),this.Height())) return true; } } //--- Если элемент частично находится в видимой области контейнера else { //--- Если элемент по вертикали полностью находится в видимой области контейнера if(object_bottom<=container_bottom && object_top>=container_top) { //--- Если высота графического объекта не совпадает с высотой элемента, //--- модифицируем графический объект по высоте элемента if(this.ObjectHeight()!=this.Height()) this.ObjectResizeH(this.Height()); } else { //--- Если элемент по горизонтали полностью находится в видимой области контейнера if(object_right<=container_right && object_left>=container_left) { //--- Если ширина графического объекта не совпадает с шириной элемента, //--- модифицируем графический объект по ширине элемента if(this.ObjectWidth()!=this.Width()) this.ObjectResizeW(this.Width()); } } } } //--- Проверяем выход объекта по горизонтали и вертикали за пределы контейнера bool modified_horizontal=false; // Флаг изменений по горизонтали bool modified_vertical =false; // Флаг изменений по вертикали //--- Обрезка по горизонтали int new_left = object_left; int new_width = this.Width(); //--- Если объект выходит за левую границу контейнера if(object_left<=container_left) { int crop_left=container_left-object_left; new_left=container_left; new_width-=crop_left; modified_horizontal=true; } //--- Если объект выходит за правую границу контейнера if(object_right>=container_right) { int crop_right=object_right-container_right; new_width-=crop_right; modified_horizontal=true; } //--- Если были изменения по горизонтали if(modified_horizontal) { this.ObjectSetX(new_left); this.ObjectResizeW(new_width); } //--- Обрезка по вертикали int new_top=object_top; int new_height=this.Height(); //--- Если объект выходит за верхнюю границу контейнера if(object_top<=container_top) { int crop_top=container_top-object_top; new_top=container_top; new_height-=crop_top; modified_vertical=true; } //--- Если объект выходит за нижнюю границу контейнера if(object_bottom>=container_bottom) { int crop_bottom=object_bottom-container_bottom; new_height-=crop_bottom; modified_vertical=true; } //--- Если были изменения по вертикали if(modified_vertical) { this.ObjectSetY(new_top); this.ObjectResizeH(new_height); } //--- После рассчётов, объект может быть скрыт, но теперь находится в области контейнера - отображаем его this.Show(false); //--- Если объект был изменен, перерисовываем его if(modified_horizontal || modified_vertical) { this.Update(false); this.Draw(false); return true; } return false; } //+------------------------------------------------------------------+ //| CCanvasBase::Возвращает флаг нахождения курсора внутри объекта | //+------------------------------------------------------------------+ bool CCanvasBase::Contains(const int x,const int y) { int left=::fmax(this.X(),this.ObjectX()); int right=::fmin(this.Right(),this.ObjectRight()); int top=::fmax(this.Y(),this.ObjectY()); int bottom=::fmin(this.Bottom(),this.ObjectBottom()); return(x>=left && x<=right && y>=top && y<=bottom); } //+--------------------------------------------------------------------+ //|CCanvasBase::Возвращает место нахождения курсора на границах объекта| //+--------------------------------------------------------------------+ ENUM_CURSOR_REGION CCanvasBase::CheckResizeZone(const int x,const int y) { //--- Координаты границ элемента int top=this.Y(); int bottom=this.Bottom(); int left=this.X(); int right=this.Right(); //--- Если за пределами объекта - возвращаем CURSOR_REGION_NONE if(xright || ybottom) return CURSOR_REGION_NONE; //--- Левая грань и углы if(x>=left && x<=left+DEF_EDGE_THICKNESS) { //--- Левый верхний угол if(y>=top && y<=top+DEF_EDGE_THICKNESS) return CURSOR_REGION_LEFT_TOP; //--- Левый нижний угол if(y>=bottom-DEF_EDGE_THICKNESS && y<=bottom) return CURSOR_REGION_LEFT_BOTTOM; //--- Левая грань return CURSOR_REGION_LEFT; } //--- Правая грань и углы if(x>=right-DEF_EDGE_THICKNESS && x<=right) { //--- Правый верхний угол if(y>=top && y<=top+DEF_EDGE_THICKNESS) return CURSOR_REGION_RIGHT_TOP; //--- Правый нижний угол if(y>=bottom-DEF_EDGE_THICKNESS && y<=bottom) return CURSOR_REGION_RIGHT_BOTTOM; //--- Правая грань return CURSOR_REGION_RIGHT; } //--- Верхняя грань if(y>=top && y<=top+DEF_EDGE_THICKNESS) return CURSOR_REGION_TOP; //--- Нижняя грань if(y>=bottom-DEF_EDGE_THICKNESS && y<=bottom) return CURSOR_REGION_BOTTOM; //--- Курсор не на гранях элемента return CURSOR_REGION_NONE; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает z-ордер графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectSetZOrder(const int value) { //--- Если передано уже установленное значение - возвращаем true if(this.ObjectZOrder()==value) return true; //--- Если не удалось установить новое значение в графические объекты фона и переднего плана - возвращаем false if(!::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_ZORDER,value) || !::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_ZORDER,value)) return false; //--- Записываем новое значение z-ордер в переменную и возвращаем true this.m_z_order=value; return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает координату X графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectSetX(const int x) { //--- Если передана существующая координата - возвращаем true if(this.ObjectX()==x) return true; //--- Если не удалось установить новую координату в графические объекты фона и переднего плана - возвращаем false if(!::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_XDISTANCE,x) || !::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_XDISTANCE,x)) return false; //--- Записываем новую координату в переменную и возвращаем true this.m_obj_x=x; return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает координату Y графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectSetY(const int y) { //--- Если передана существующая координата - возвращаем true if(this.ObjectY()==y) return true; //--- Если не удалось установить новую координату в графические объекты фона и переднего плана - возвращаем false if(!::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_YDISTANCE,y) || !::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_YDISTANCE,y)) return false; //--- Записываем новую координату в переменную и возвращаем true this.m_obj_y=y; return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет ширину графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectResizeW(const int size) { //--- Если передана существующая ширина - возвращаем true if(this.ObjectWidth()==size) return true; //--- Если передан размер больше 0, возвращаем результат изменения ширины фона и переднего плана, иначе - false return(size>0 ? (this.m_background.Resize(size,this.ObjectHeight()) && this.m_foreground.Resize(size,this.ObjectHeight())) : false); } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет высоту графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectResizeH(const int size) { //--- Если передана существующая высота - возвращаем true if(this.ObjectHeight()==size) return true; //--- Если передан размер больше 0, возвращаем результат изменения высоты фона и переднего плана, иначе - false return(size>0 ? (this.m_background.Resize(this.ObjectWidth(),size) && this.m_foreground.Resize(this.ObjectWidth(),size)) : false); } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет размер графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectResize(const int w,const int h) { if(!this.ObjectResizeW(w)) return false; return this.ObjectResizeH(h); } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает одновременно | //| координаты и размеры графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectSetXYWidthResize(const int x,const int y,const int w,const int h) { //--- Если новые координаты установлены - возвращаем результат изменения размеров if(this.ObjectSetXY(x,y)) return this.ObjectResize(w,h); //--- Не удалось установить новые координаты - возвращаем false return false; } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет ширину объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ResizeW(const int w) { if(!this.ObjectResizeW(w)) return false; this.BoundResizeW(w); if(!this.ObjectTrim()) { this.Update(false); this.Draw(false); } return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет высоту объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ResizeH(const int h) { if(!this.ObjectResizeH(h)) return false; this.BoundResizeH(h); if(!this.ObjectTrim()) { this.Update(false); this.Draw(false); } return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет размеры объекта | //+------------------------------------------------------------------+ bool CCanvasBase::Resize(const int w,const int h) { if(!this.ObjectResize(w,h)) return false; this.BoundResize(w,h); if(!this.ObjectTrim()) { this.Update(false); this.Draw(false); } return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает объекту новые координаты X и Y | //+------------------------------------------------------------------+ bool CCanvasBase::Move(const int x,const int y) { if(!this.ObjectMove(x,y)) return false; this.BoundMove(x,y); this.ObjectTrim(); return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает объекту новую координату X | //+------------------------------------------------------------------+ bool CCanvasBase::MoveX(const int x) { return this.Move(x,this.AdjY(this.ObjectY())); } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает объекту новую координату Y | //+------------------------------------------------------------------+ bool CCanvasBase::MoveY(const int y) { return this.Move(this.AdjX(this.ObjectX()),y); } //+------------------------------------------------------------------+ //| CCanvasBase::Смещает объект по осям X и Y на указанное смещение | //+------------------------------------------------------------------+ bool CCanvasBase::Shift(const int dx,const int dy) { if(!this.ObjectShift(dx,dy)) return false; this.BoundShift(dx,dy); this.ObjectTrim(); return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Смещает объект по оси X на указанное смещение | //+------------------------------------------------------------------+ bool CCanvasBase::ShiftX(const int dx) { return this.Shift(dx,0); } //+------------------------------------------------------------------+ //| CCanvasBase::Смещает объект по оси Y на указанное смещение | //+------------------------------------------------------------------+ bool CCanvasBase::ShiftY(const int dy) { return this.Shift(0,dy); } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает и координаты, и размеры элемента | //+------------------------------------------------------------------+ bool CCanvasBase::MoveXYWidthResize(const int x,const int y,const int w,const int h) { if(!this.ObjectSetXYWidthResize(x,y,w,h)) return false; this.BoundMove(x,y); this.BoundResize(w,h); if(!this.ObjectTrim()) { this.Update(false); this.Draw(false); } return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Скрывает объект на всех периодах графика | //+------------------------------------------------------------------+ void CCanvasBase::Hide(const bool chart_redraw) { //--- Если объект уже скрыт - уходим if(this.m_hidden) return; //--- Если изменение видимости для фона и переднего плана успешно поставлено //--- в очередь команд графика - устанавливаем флаг скрытого объекта if(::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS) && ::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS) ) this.m_hidden=true; //--- Если указано - перерисовываем график if(chart_redraw) ::ChartRedraw(this.m_chart_id); } //+------------------------------------------------------------------+ //| CCanvasBase::Отображает объект на всех периодах графика | //+------------------------------------------------------------------+ void CCanvasBase::Show(const bool chart_redraw) { //--- Если объект уже видимый - уходим if(!this.m_hidden) return; //--- Если изменение видимости для фона и переднего плана успешно поставлено //--- в очередь команд графика - сбрасываем флаг скрытого объекта if(::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS) && ::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS) ) this.m_hidden=false; //--- Если указано - перерисовываем график if(chart_redraw) ::ChartRedraw(this.m_chart_id); } //+------------------------------------------------------------------+ //| CCanvasBase::Помещает объект на передний план | //+------------------------------------------------------------------+ void CCanvasBase::BringToTop(const bool chart_redraw) { if(this.m_cropped) return; this.Hide(false); this.Show(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Блокирует элемент | //+------------------------------------------------------------------+ void CCanvasBase::Block(const bool chart_redraw) { //--- Если элемент уже заблокирован - уходим if(this.m_blocked) return; //--- Устанавливаем текущие цвета как цвета заблокированного элемента, //--- устанавливаем флаг блокировки и перерисовываем объект this.ColorsToBlocked(); this.m_blocked=true; this.Draw(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Разблокирует элемент | //+------------------------------------------------------------------+ void CCanvasBase::Unblock(const bool chart_redraw) { //--- Если элемент уже разблокирован - уходим if(!this.m_blocked) return; //--- Устанавливаем текущие цвета как цвета элемента в обычном состоянии, //--- перерисовываем объект и сбрасываем флаг блокировки this.ColorsToDefault(); this.Draw(chart_redraw); this.m_blocked=false; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает текущие цвета | //| элемента в состояние по умолчанию | //+------------------------------------------------------------------+ bool CCanvasBase::ColorsToDefault(void) { bool res=true; res &=this.BackColorToDefault(); res &=this.ForeColorToDefault(); res &=this.BorderColorToDefault(); return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает текущие цвета | //| элемента в состояние при наведении курсора | //+------------------------------------------------------------------+ bool CCanvasBase::ColorsToFocused(void) { bool res=true; res &=this.BackColorToFocused(); res &=this.ForeColorToFocused(); res &=this.BorderColorToFocused(); return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает текущие цвета | //| элемента в состояние при нажатии курсора | //+------------------------------------------------------------------+ bool CCanvasBase::ColorsToPressed(void) { bool res=true; res &=this.BackColorToPressed(); res &=this.ForeColorToPressed(); res &=this.BorderColorToPressed(); return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает текущие цвета | //| элемента в заблокированное состояние | //+------------------------------------------------------------------+ bool CCanvasBase::ColorsToBlocked(void) { bool res=true; res &=this.BackColorToBlocked(); res &=this.ForeColorToBlocked(); res &=this.BorderColorToBlocked(); return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Заливает объект указанным цветом | //| с установленной в m_alpha прозрачностью | //+------------------------------------------------------------------+ void CCanvasBase::Fill(const color clr,const bool chart_redraw) { this.m_background.Erase(::ColorToARGB(clr,this.m_alpha_bg)); this.m_background.Update(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Заливает объект прозрачным цветом | //+------------------------------------------------------------------+ void CCanvasBase::Clear(const bool chart_redraw) { this.m_background.Erase(clrNULL); this.m_foreground.Erase(clrNULL); this.Update(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Обновляет объект для отображения изменений | //+------------------------------------------------------------------+ void CCanvasBase::Update(const bool chart_redraw) { this.m_background.Update(false); this.m_foreground.Update(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Рисует внешний вид | //+------------------------------------------------------------------+ void CCanvasBase::Draw(const bool chart_redraw) { return; } //+------------------------------------------------------------------+ //| CCanvasBase::Уничтожает объект | //+------------------------------------------------------------------+ void CCanvasBase::Destroy(void) { if(this.m_canvas_owner) { this.m_background.Destroy(); this.m_foreground.Destroy(); delete this.m_background; delete this.m_foreground; this.m_background=NULL; this.m_foreground=NULL; } } //+------------------------------------------------------------------+ //| CCanvasBase::Возвращает описание объекта | //+------------------------------------------------------------------+ string CCanvasBase::Description(void) { string nm=this.Name(); string name=(nm!="" ? ::StringFormat(" \"%s\"",nm) : nm); string area=::StringFormat("x %d, y %d, w %d, h %d",this.X(),this.Y(),this.Width(),this.Height()); return ::StringFormat("%s%s (%s, %s): ID %d, %s",ElementDescription((ENUM_ELEMENT_TYPE)this.Type()),name,this.NameBG(),this.NameFG(),this.ID(),area); } //+------------------------------------------------------------------+ //| CCanvasBase::Сохранение в файл | //+------------------------------------------------------------------+ bool CCanvasBase::Save(const int file_handle) { //--- Метод временно отключен return false; //--- Сохраняем данные родительского объекта if(!CBaseObj::Save(file_handle)) return false; /* //--- Сохранение свойств */ //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Загрузка из файла | //+------------------------------------------------------------------+ bool CCanvasBase::Load(const int file_handle) { //--- Метод временно отключен return false; //--- Загружаем данные родительского объекта if(!CBaseObj::Load(file_handle)) return false; /* //--- Загрузка свойств */ //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Установка запретов для графика | //| (прокрутка колёсиком, контекстное меню и перекрестие) | //+------------------------------------------------------------------+ void CCanvasBase::SetFlags(const bool flag) { //--- Если нужно установить флаги, и они уже были установлены ранее - уходим if(flag && this.m_flags_state) return; //--- Если нужно сбросить флаги, и они уже были сброшены ранее - уходим if(!flag && !this.m_flags_state) return; //--- Устанавливаем требуемый флаг для контекстного меню, //--- инструмента "перекрестие" и прокрутки графика колёсиком мышки. //--- После установки запоминаем значение установленного флага ::ChartSetInteger(this.m_chart_id, CHART_CONTEXT_MENU, flag); ::ChartSetInteger(this.m_chart_id, CHART_CROSSHAIR_TOOL,flag); ::ChartSetInteger(this.m_chart_id, CHART_MOUSE_SCROLL, flag); this.m_flags_state=flag; //--- Делаем обновление графика для немедленного применения установленных флагов ::ChartRedraw(this.m_chart_id); } //+------------------------------------------------------------------+ //| CCanvasBase::Инициализация класса | //+------------------------------------------------------------------+ void CCanvasBase::Init(void) { //--- Запоминаем разрешения для мышки и инструментов графика this.m_chart_mouse_wheel_flag = ::ChartGetInteger(this.m_chart_id, CHART_EVENT_MOUSE_WHEEL); this.m_chart_mouse_move_flag = ::ChartGetInteger(this.m_chart_id, CHART_EVENT_MOUSE_MOVE); this.m_chart_object_create_flag = ::ChartGetInteger(this.m_chart_id, CHART_EVENT_OBJECT_CREATE); this.m_chart_mouse_scroll_flag = ::ChartGetInteger(this.m_chart_id, CHART_MOUSE_SCROLL); this.m_chart_context_menu_flag = ::ChartGetInteger(this.m_chart_id, CHART_CONTEXT_MENU); this.m_chart_crosshair_tool_flag= ::ChartGetInteger(this.m_chart_id, CHART_CROSSHAIR_TOOL); //--- Устанавливаем разрешения для мышки и графика ::ChartSetInteger(this.m_chart_id, CHART_EVENT_MOUSE_WHEEL, true); ::ChartSetInteger(this.m_chart_id, CHART_EVENT_MOUSE_MOVE, true); ::ChartSetInteger(this.m_chart_id, CHART_EVENT_OBJECT_CREATE, true); //--- Инициализируем цвета объекта по умолчанию this.InitColors(); //--- Инициализируем миллисекундный таймер ::EventSetMillisecondTimer(16); //--- Флаг владения канвасами this.m_canvas_owner=true; } //+------------------------------------------------------------------+ //| CCanvasBase::Инициализация цветов объекта по умолчанию | //+------------------------------------------------------------------+ void CCanvasBase::InitColors(void) { //--- Инициализируем цвета заднего плана для обычного и активированного состояний и делаем его текущим цветом фона this.InitBackColors(clrWhiteSmoke); this.InitBackColorsAct(clrWhiteSmoke); this.BackColorToDefault(); //--- Инициализируем цвета переднего плана для обычного и активированного состояний и делаем его текущим цветом текста this.InitForeColors(clrBlack); this.InitForeColorsAct(clrBlack); this.ForeColorToDefault(); //--- Инициализируем цвета рамки для обычного и активированного состояний и делаем его текущим цветом рамки this.InitBorderColors(clrDarkGray); this.InitBorderColorsAct(clrDarkGray); this.BorderColorToDefault(); //--- Инициализируем цвет рамки и цвет переднего плана для заблокированного элемента this.InitBorderColorBlocked(clrLightGray); this.InitForeColorBlocked(clrSilver); } //+------------------------------------------------------------------+ //| CCanvasBase::Проверяет установленный цвет на равенство указанному| //+------------------------------------------------------------------+ bool CCanvasBase::CheckColor(const ENUM_COLOR_STATE state) const { bool res=true; //--- В зависимости от проверяемого события switch(state) { //--- проверяем равенство всех STANDARD цветов фона, текста и рамки предустановленным значениям case COLOR_STATE_DEFAULT : res &=this.BackColor()==this.BackColorDefault(); res &=this.ForeColor()==this.ForeColorDefault(); res &=this.BorderColor()==this.BorderColorDefault(); break; //--- проверяем равенство всех FOCUSED цветов фона, текста и рамки предустановленным значениям case COLOR_STATE_FOCUSED : res &=this.BackColor()==this.BackColorFocused(); res &=this.ForeColor()==this.ForeColorFocused(); res &=this.BorderColor()==this.BorderColorFocused(); break; //--- проверяем равенство всех PRESSED цветов фона, текста и рамки предустановленным значениям case COLOR_STATE_PRESSED : res &=this.BackColor()==this.BackColorPressed(); res &=this.ForeColor()==this.ForeColorPressed(); res &=this.BorderColor()==this.BorderColorPressed(); break; //--- проверяем равенство всех BLOCKED цветов фона, текста и рамки предустановленным значениям case COLOR_STATE_BLOCKED : res &=this.BackColor()==this.BackColorBlocked(); res &=this.ForeColor()==this.ForeColorBlocked(); res &=this.BorderColor()==this.BorderColorBlocked(); break; default: res=false; break; } return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Смена цвета элементов объекта по событию | //+------------------------------------------------------------------+ void CCanvasBase::ColorChange(const ENUM_COLOR_STATE state) { //--- В зависимости от события устанавливаем цвета события как основные switch(state) { case COLOR_STATE_DEFAULT : this.ColorsToDefault(); break; case COLOR_STATE_FOCUSED : this.ColorsToFocused(); break; case COLOR_STATE_PRESSED : this.ColorsToPressed(); break; case COLOR_STATE_BLOCKED : this.ColorsToBlocked(); break; default : break; } } //+------------------------------------------------------------------+ //| CCanvasBase::Обработчик событий | //+------------------------------------------------------------------+ void CCanvasBase::OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam) { //--- Событие изменения графика if(id==CHARTEVENT_CHART_CHANGE) { //--- скорректируем дистанцию между верхней рамкой подокна индикатора и верхней рамкой главного окна графика this.m_wnd_y=(int)::ChartGetInteger(this.m_chart_id,CHART_WINDOW_YDISTANCE,this.m_wnd); } //--- Событие создания графического объекта if(id==CHARTEVENT_OBJECT_CREATE) { //--- Если это не элемент-контейнер - уходим if(this.Type()ACTIVE_ELEMENT_MAX)) return; //--- Кнопка мышки удерживается if(sparam=="1") { //--- Курсор в пределах объекта if(this.Contains(x, y)) { //--- Если это главный объект - запрещаем инструменты графика if(this.IsMain()) this.SetFlags(false); //--- Если кнопка мышки была зажата на графике - обрабатывать нечего, уходим if(this.ActiveElementName()=="Chart") return; //--- Фиксируем имя активного элемента, над которым был курсор при нажатии кнопки мышки this.SetActiveElementName(this.ActiveElementName()); //--- Если это текущий активный элемент - обрабатываем его перемещение if(this.IsCurrentActiveElement()) { this.OnMoveEvent(id,lparam,dparam,sparam); //--- Если у элемента активен автоповтор событий - указываем, что кнопка нажата if(this.m_autorepeat_flag) this.m_autorepeat.OnButtonPress(); //--- Для изменяемых в размерах элементов if(this.m_resizable) { //--- Если не активирован режим изменения размеров, //--- вызываем обработчик начала изменения размеров if(!this.ResizeMode()) this.OnResizeZoneEvent(RESIZE_ZONE_ACTION_BEGIN,x,y,this.NameFG()); //--- иначе, при активном режиме изменения размеров //--- вызываем обработчик перетаскивания грани для изменения размеров else this.OnResizeZoneEvent(RESIZE_ZONE_ACTION_DRAG,x,y,this.NameFG()); } } } //--- Курсор за пределами объекта else { //--- Если это активный главный объект, либо кнопка мышки зажата на графике, и это не режим изменения размеров - разрешаем инструменты графика if(this.IsMain() && (this.ActiveElementName()==this.NameFG() || this.ActiveElementName()=="Chart")) if(!this.ResizeMode()) this.SetFlags(true); //--- Если это текущий активный элемент if(this.IsCurrentActiveElement()) { //--- Если элемент неперемещаемый if(!this.IsMovable()) { //--- вызываем обработчик наведения курсора мышки this.OnFocusEvent(id,lparam,dparam,sparam); //--- Если у элемента активен автоповтор событий - указываем, что кнопка отжата if(this.m_autorepeat_flag) this.m_autorepeat.OnButtonRelease(); } //--- Если элемент перемещаемый - вызываем обработчик перемещения else this.OnMoveEvent(id,lparam,dparam,sparam); //--- Для изменяемых в размерах элементов //--- вызываем обработчик перетаскивания грани для изменения размеров if(this.m_resizable) this.OnResizeZoneEvent(RESIZE_ZONE_ACTION_DRAG,x,y,this.NameFG()); } } } //--- Кнопка мышки не нажата else { //--- Курсор в пределах объекта if(this.Contains(x, y)) { //--- Если это главный элемент - отключаем инструменты графика if(this.IsMain()) this.SetFlags(false); //--- Вызываем обработчик наведения курсора и //--- устанавливаем элемент как текущий активный this.OnFocusEvent(id,lparam,dparam,sparam); this.SetActiveElementName(this.NameFG()); //--- Для изменяемых в размерах элементов //--- вызываем обработчик наведения курсора на облась изменения размеров if(this.m_resizable) this.OnResizeZoneEvent(RESIZE_ZONE_ACTION_HOVER,x,y,this.NameFG()); } //--- Курсор за пределами объекта else { //--- Если это главный объект if(this.IsMain()) { //--- Разрешаем инструменты графика и //--- устанавливаем график как текущий активный элемент this.SetFlags(true); this.SetActiveElementName("Chart"); } //--- Вызываем обработчик увода курсора из фокуса this.OnReleaseEvent(id,lparam,dparam,sparam); //--- Для изменяемых в размерах элементов //--- вызываем обработчик режима не изменения размеров if(this.m_resizable) this.OnResizeZoneEvent(RESIZE_ZONE_ACTION_NONE,x,y,this.NameFG()); } } } //--- Событие щелчка кнопкой мышки на объекте (отпускание кнопки) if(id==CHARTEVENT_OBJECT_CLICK) { //--- Если щелчок (отпускание кнопки мышки) был по этому объекту if(sparam==this.NameFG()) { //--- Вызываем обработчик щелчка мышки и освобождаем текущий активный объект this.OnPressEvent(id, lparam, dparam, sparam); this.SetActiveElementName(""); //--- Если у элемента активен автоповтор событий - указываем, что кнопка отжата if(this.m_autorepeat_flag) this.m_autorepeat.OnButtonRelease(); //--- Для изменяемых в размерах элементов if(this.m_resizable) { //--- Отключаем режим изменения размеров, сбрасываем область взаимодействия, //--- вызываем обработчик завершения изменения размеров перетаскиванием граней this.SetResizeMode(false); this.SetResizeRegion(CURSOR_REGION_NONE); this.OnResizeZoneEvent(RESIZE_ZONE_ACTION_END,x,y,this.NameFG()); } } } //--- Событие прокрутки колёсика мышки if(id==CHARTEVENT_MOUSE_WHEEL) { //--- Если это активный элемент - вызываем его обработчик события прокрутки колёсика if(this.IsCurrentActiveElement()) this.OnWheelEvent(id,lparam,dparam,this.ActiveElementName()); // в sparam передаём имя активного элемента } //--- Если пришло пользовательское событие графика if(id>CHARTEVENT_CUSTOM) { //--- собственные события не обрабатываем if(sparam==this.NameFG()) return; //--- приводим пользовательское событие в соответствие со стандартными ENUM_CHART_EVENT chart_event=ENUM_CHART_EVENT(id-CHARTEVENT_CUSTOM); //--- Если щелчок мышки по объекту - вызываем обработчик пользовательского события if(chart_event==CHARTEVENT_OBJECT_CLICK) { this.MousePressHandler(chart_event, lparam, dparam, sparam); } //--- Если перемещение курсора мышки - вызываем обработчик пользовательского события if(chart_event==CHARTEVENT_MOUSE_MOVE) { this.MouseMoveHandler(chart_event, lparam, dparam, sparam); } //--- Если прокрутка колёсика мышки - вызываем обработчик пользовательского события if(chart_event==CHARTEVENT_MOUSE_WHEEL) { this.MouseWheelHandler(chart_event, lparam, dparam, sparam); } //--- Если изменение графического элемента - вызываем обработчик пользовательского события if(chart_event==CHARTEVENT_OBJECT_CHANGE) { this.ObjectChangeHandler(chart_event, lparam, dparam, sparam); } } } //+------------------------------------------------------------------+ //| CCanvasBase::Обработчик ухода из фокуса | //+------------------------------------------------------------------+ void CCanvasBase::OnReleaseEvent(const int id,const long lparam,const double dparam,const string sparam) { //--- Элемент не в фокусе при уводе курсора this.m_focused=false; //--- восстанавливаем исходные цвета и перерисовываем объект if(!this.CheckColor(COLOR_STATE_DEFAULT)) { this.ColorChange(COLOR_STATE_DEFAULT); this.Draw(true); } //--- Инициализируем отступ курсора от верхнего левого угла элемента по осям X и Y this.m_cursor_delta_x=0; this.m_cursor_delta_y=0; } //+------------------------------------------------------------------+ //| CCanvasBase::Обработчик наведения курсора | //+------------------------------------------------------------------+ void CCanvasBase::OnFocusEvent(const int id,const long lparam,const double dparam,const string sparam) { //--- Элемент в фокусе this.m_focused=true; //--- Если цвета объекта не для режима Focused if(!this.CheckColor(COLOR_STATE_FOCUSED)) { //--- устанавливаем цвета и флаг Focused и перерисовываем объект this.ColorChange(COLOR_STATE_FOCUSED); this.Draw(true); } //--- Инициализируем отступ курсора от верхнего левого угла элемента по осям X и Y this.m_cursor_delta_x=0; this.m_cursor_delta_y=0; } //+------------------------------------------------------------------+ //| CCanvasBase::Обработчик нажатия на объект | //+------------------------------------------------------------------+ void CCanvasBase::OnPressEvent(const int id,const long lparam,const double dparam,const string sparam) { //--- Элемент в фокусе при щелчке по нему this.m_focused=true; //--- Если цвета объекта не для режима Pressed if(!this.CheckColor(COLOR_STATE_PRESSED)) { //--- устанавливаем цвета Pressed и перерисовываем объект this.ColorChange(COLOR_STATE_PRESSED); this.Draw(true); } //--- Инициализируем отступ курсора от верхнего левого угла элемента по осям X и Y this.m_cursor_delta_x=0; this.m_cursor_delta_y=0; //--- отправляем пользовательское событие на график с переданными значениями в lparam, dparam, и именем объекта в sparam ::EventChartCustom(this.m_chart_id, (ushort)CHARTEVENT_OBJECT_CLICK, lparam, dparam, this.NameFG()); } //+------------------------------------------------------------------+ //| CCanvasBase::Обработчик перемещения курсора | //+------------------------------------------------------------------+ void CCanvasBase::OnMoveEvent(const int id,const long lparam,const double dparam,const string sparam) { //--- Элемент в фокусе при щелчке по нему this.m_focused=true; //--- Если цвета объекта не для режима Pressed if(!this.CheckColor(COLOR_STATE_PRESSED)) { //--- устанавливаем цвета Pressed и перерисовываем объект this.ColorChange(COLOR_STATE_PRESSED); this.Draw(true); } //--- Рассчитываем отступ курсора от верхнего левого угла элемента по осям X и Y if(this.m_cursor_delta_x==0) this.m_cursor_delta_x=(int)lparam-this.X(); if(this.m_cursor_delta_y==0) this.m_cursor_delta_y=(int)::round(dparam-this.Y()); } //+------------------------------------------------------------------+ //| CCanvasBase::Обработчик события создания графического объекта | //+------------------------------------------------------------------+ void CCanvasBase::OnCreateEvent(const int id,const long lparam,const double dparam,const string sparam) { //--- если созданный объект принадлежит этой программе - уходим if(this.IsBelongsToThis(sparam)) return; //--- переносим объект на передний план this.BringToTop(true); } //+------------------------------------------------------------------+