MQL5-MVC-GUI-Framework/Controls/Base.mqh

2845 lignes
176 Kio
MQL5

//+------------------------------------------------------------------+
//| Base.mqh |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Включаемые библиотеки |
//+------------------------------------------------------------------+
#include <Canvas\Canvas.mqh> // Класс СБ CCanvas
#include <Arrays\List.mqh> // Класс СБ 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 CCaptionView; // Класс базового объекта визуального представления заголовка
class CColumnCaptionView; // Класс визуального представления заголовка столбца таблицы
class CRowCaptionView; // Класс визуального представления заголовка строки таблицы
class CTableHeaderView; // Класс визуального представления заголовка таблицы
class CTableRowsHeaderView; // Класс визуального представления заголовка строк таблицы
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_CAPTION_VIEW, // Базовый объект заголовка (View)
ELEMENT_TYPE_TABLE_COLUMN_CAPTION_VIEW,// Заголовок столбца таблицы (View)
ELEMENT_TYPE_TABLE_ROW_CAPTION_VIEW, // Заголовок строки таблицы (View)
ELEMENT_TYPE_TABLE_HEADER_VIEW, // Заголовок таблицы (View)
ELEMENT_TYPE_TABLE_ROWS_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;i<total;i++)
{
array[i]+=" ";
array[i].Lower();
array[i].SetChar(0,ushort(array[i].GetChar(0)-0x20));
result+=array[i];
}
result.TrimLeft();
result.TrimRight();
return result;
}
//+------------------------------------------------------------------+
//| Возвращает короткое имя элемента по типу |
//+------------------------------------------------------------------+
string ElementShortName(const ENUM_ELEMENT_TYPE type)
{
switch(type)
{
case ELEMENT_TYPE_ELEMENT_BASE : return "BASE"; // Базовый объект графических элементов
case ELEMENT_TYPE_HINT : return "HNT"; // Подсказка
case ELEMENT_TYPE_LABEL : return "LBL"; // Текстовая метка
case ELEMENT_TYPE_BUTTON : return "SBTN"; // Простая кнопка
case ELEMENT_TYPE_BUTTON_TRIGGERED : return "TBTN"; // Двухпозиционная кнопка
case ELEMENT_TYPE_BUTTON_ARROW_UP : return "BTARU"; // Кнопка со стрелкой вверх
case ELEMENT_TYPE_BUTTON_ARROW_DOWN : return "BTARD"; // Кнопка со стрелкой вниз
case ELEMENT_TYPE_BUTTON_ARROW_LEFT : return "BTARL"; // Кнопка со стрелкой влево
case ELEMENT_TYPE_BUTTON_ARROW_RIGHT : return "BTARR"; // Кнопка со стрелкой вправо
case ELEMENT_TYPE_CHECKBOX : return "CHKB"; // Элемент управления CheckBox
case ELEMENT_TYPE_RADIOBUTTON : return "RBTN"; // Элемент управления RadioButton
case ELEMENT_TYPE_SCROLLBAR_THUMB_H : return "THMBH"; // Ползунок горизонтальной полосы прокрутки
case ELEMENT_TYPE_SCROLLBAR_THUMB_V : return "THMBV"; // Ползунок вертикальной полосы прокрутки
case ELEMENT_TYPE_SCROLLBAR_H : return "SCBH"; // Элемент управления ScrollBarHorisontal
case ELEMENT_TYPE_SCROLLBAR_V : return "SCBV"; // Элемент управления ScrollBarVertical
case ELEMENT_TYPE_TABLE_CELL_VIEW : return "TCELL"; // Ячейка таблицы (View)
case ELEMENT_TYPE_TABLE_ROW_VIEW : return "TROW"; // Строка таблицы (View)
case ELEMENT_TYPE_TABLE_CAPTION_VIEW : return "TCAPT"; // Базовый объект заголовка (View)
case ELEMENT_TYPE_TABLE_COLUMN_CAPTION_VIEW : return "TCCAPT"; // Заголовок столбца таблицы (View)
case ELEMENT_TYPE_TABLE_ROW_CAPTION_VIEW : return "TRCAPT"; // Заголовок строки таблицы (View)
case ELEMENT_TYPE_TABLE_HEADER_VIEW : return "TCHDR"; // Заголовок таблицы (View)
case ELEMENT_TYPE_TABLE_ROWS_HEADER_VIEW : return "TRHDR"; // Заголовок строк таблицы (View)
case ELEMENT_TYPE_TABLE_VIEW : return "TABLE"; // Таблица (View)
case ELEMENT_TYPE_TABLE_CONTROL_VIEW : return "TBLCTRL"; // Элемент управления таблицами (View)
case ELEMENT_TYPE_PANEL : return "PNL"; // Элемент управления Panel
case ELEMENT_TYPE_GROUPBOX : return "GRBX"; // Элемент управления GroupBox
case ELEMENT_TYPE_CONTAINER : return "CNTR"; // Элемент управления Container
default : return "Unknown"; // Unknown
}
}
//+------------------------------------------------------------------+
//| Возвращает массив имён иерархии элементов |
//+------------------------------------------------------------------+
int GetElementNames(string value, string sep, string &array[])
{
if(value=="" || value==NULL)
{
PrintFormat("%s: Error. Empty string passed");
return 0;
}
ResetLastError();
int res=StringSplit(value, StringGetCharacter(sep,0),array);
if(res==WRONG_VALUE)
{
PrintFormat("%s: StringSplit() failed. Error %d",__FUNCTION__, GetLastError());
return WRONG_VALUE;
}
return res;
}
//+------------------------------------------------------------------+
//| Классы |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс-синглтон для общих флагов и событий графических элементов |
//+------------------------------------------------------------------+
class CCommonManager
{
private:
static CCommonManager *m_instance; // Экземпляр класса
string m_element_name; // Имя активного элемента
int m_cursor_x; // Координата X курсора
int m_cursor_y; // Координата Y курсора
bool m_resize_mode; // Режим изменения размеров
ENUM_CURSOR_REGION m_resize_region; // Грань элемента, за которую изменяется размер
//--- Конструктор/деструктор
CCommonManager(void) : m_element_name("") {}
~CCommonManager() {}
public:
//--- Метод для получения экземпляра Singleton
static CCommonManager *GetInstance(void)
{
if(m_instance==NULL)
m_instance=new CCommonManager();
return m_instance;
}
//--- Метод для уничтожения экземпляра Singleton
static void DestroyInstance(void)
{
if(m_instance!=NULL)
{
delete m_instance;
m_instance=NULL;
}
}
//--- (1) Устанавливает, (2) возвращает имя активного текущего элемента
void SetElementName(const string name) { this.m_element_name=name; }
string ElementName(void) const { return this.m_element_name; }
//--- (1) Устанавливает, (2) возвращает координату X курсора
void SetCursorX(const int x) { this.m_cursor_x=x; }
int CursorX(void) const { return this.m_cursor_x; }
//--- (1) Устанавливает, (2) возвращает координату Y курсора
void SetCursorY(const int y) { this.m_cursor_y=y; }
int CursorY(void) const { return this.m_cursor_y; }
//--- (1) Устанавливает, (2) возвращает режим изменения размеров
void SetResizeMode(const bool flag) { this.m_resize_mode=flag; }
bool ResizeMode(void) const { return this.m_resize_mode; }
//--- (1) Устанавливает, (2) возвращает грань элемента
void SetResizeRegion(const ENUM_CURSOR_REGION edge){ this.m_resize_region=edge; }
ENUM_CURSOR_REGION ResizeRegion(void) const { return this.m_resize_region;}
};
//--- Инициализация статической переменной экземпляра класса
CCommonManager* CCommonManager::m_instance=NULL;
//+------------------------------------------------------------------+
//| Базовый класс графических элементов |
//+------------------------------------------------------------------+
class CBaseObj : public CObject
{
protected:
int m_id; // Идентифткатор
ushort m_name[]; // Наименование
public:
//--- Устанавливает (1) наименование, (2) идентификатор
void SetName(const string name) { ::StringToShortArray(name,this.m_name); }
virtual void SetID(const int id) { this.m_id=id; }
//--- Возвращает (1) наименование, (2) идентификатор
string Name(void) const { return ::ShortArrayToString(this.m_name); }
int ID(void) const { return this.m_id; }
//--- Возвращает координаты курсора
int CursorX(void) const { return CCommonManager::GetInstance().CursorX(); }
int CursorY(void) const { return CCommonManager::GetInstance().CursorY(); }
//--- Виртуальные методы (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_BASE); }
//--- (1) Возвращает, (2) выводит в журнал описание объекта
virtual string Description(void);
virtual void Print(void);
//--- Конструктор/деструктор
CBaseObj (void) : m_id(-1) { this.SetName(""); }
~CBaseObj (void) {}
};
//+------------------------------------------------------------------+
//| CBaseObj::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CBaseObj::Compare(const CObject *node,const int mode=0) const
{
if(node==NULL)
return -1;
const CBaseObj *obj=node;
switch(mode)
{
case 0 : return(this.ID() >obj.ID() ? 1 : this.ID() <obj.ID() ? -1 : 0);
default : return(this.Name()>obj.Name() ? 1 : this.Name()<obj.Name() ? -1 : 0);
}
}
//+------------------------------------------------------------------+
//| CBaseObj::Возвращает описание объекта |
//+------------------------------------------------------------------+
string CBaseObj::Description(void)
{
string nm=this.Name();
string name=(nm!="" ? ::StringFormat(" \"%s\"",nm) : nm);
return ::StringFormat("%s%s ID %d",ElementDescription((ENUM_ELEMENT_TYPE)this.Type()),name,this.ID());
}
//+------------------------------------------------------------------+
//| CBaseObj::Выводит в журнал описание объекта |
//+------------------------------------------------------------------+
void CBaseObj::Print(void)
{
::Print(this.Description());
}
//+------------------------------------------------------------------+
//| CBaseObj::Сохранение в файл |
//+------------------------------------------------------------------+
bool CBaseObj::Save(const int file_handle)
{
//--- Проверяем хэндл
if(file_handle==INVALID_HANDLE)
return false;
//--- Сохраняем маркер начала данных - 0xFFFFFFFFFFFFFFFF
if(::FileWriteLong(file_handle,-1)!=sizeof(long))
return false;
//--- Сохраняем тип объекта
if(::FileWriteInteger(file_handle,this.Type(),INT_VALUE)!=INT_VALUE)
return false;
//--- Сохраняем идентификатор
if(::FileWriteInteger(file_handle,this.m_id,INT_VALUE)!=INT_VALUE)
return false;
//--- Сохраняем наименование
if(::FileWriteArray(file_handle,this.m_name)!=sizeof(this.m_name))
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CBaseObj::Загрузка из файла |
//+------------------------------------------------------------------+
bool CBaseObj::Load(const int file_handle)
{
//--- Проверяем хэндл
if(file_handle==INVALID_HANDLE)
return false;
//--- Загружаем и проверяем маркер начала данных - 0xFFFFFFFFFFFFFFFF
if(::FileReadLong(file_handle)!=-1)
return false;
//--- Загружаем тип объекта
if(::FileReadInteger(file_handle,INT_VALUE)!=this.Type())
return false;
//--- Загружаем идентификатор
this.m_id=::FileReadInteger(file_handle,INT_VALUE);
//--- Загружаем наименование
if(::FileReadArray(file_handle,this.m_name)!=sizeof(this.m_name))
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс цвета |
//+------------------------------------------------------------------+
class CColor : public CBaseObj
{
protected:
color m_color; // Цвет
public:
//--- Устанавливает цвет
bool SetColor(const color clr)
{
if(this.m_color==clr)
return false;
this.m_color=clr;
return true;
}
//--- Возвращает цвет
color Get(void) const { return this.m_color; }
//--- Возвращает описание объекта
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_COLOR); }
//--- Конструкторы/деструктор
CColor(void) : m_color(clrNULL) { this.SetName(""); }
CColor(const color clr) : m_color(clr) { this.SetName(""); }
CColor(const color clr,const string name) : m_color(clr) { this.SetName(name);}
~CColor(void) {}
};
//+------------------------------------------------------------------+
//| CColor::Возвращает описание объекта |
//+------------------------------------------------------------------+
string CColor::Description(void)
{
string color_name=(this.Get()!=clrNULL ? ::ColorToString(this.Get(),true) : "clrNULL (0x00FFFFFF)");
return(this.Name()+(this.Name()!="" ? " " : "")+"Color: "+color_name);
}
//+------------------------------------------------------------------+
//| CColor::Сохранение в файл |
//+------------------------------------------------------------------+
bool CColor::Save(const int file_handle)
{
//--- Сохраняем данные родительского объекта
if(!CBaseObj::Save(file_handle))
return false;
//--- Сохраняем цвет
if(::FileWriteInteger(file_handle,this.m_color,INT_VALUE)!=INT_VALUE)
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CColor::Загрузка из файла |
//+------------------------------------------------------------------+
bool CColor::Load(const int file_handle)
{
//--- Загружаем данные родительского объекта
if(!CBaseObj::Load(file_handle))
return false;
//--- Загружаем цвет
this.m_color=(color)::FileReadInteger(file_handle,INT_VALUE);
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс цветов элемента графического объекта |
//+------------------------------------------------------------------+
class CColorElement : public CBaseObj
{
protected:
CColor m_current; // Текущий цвет. Может быть одним из нижеследующих
CColor m_default; // Цвет обычного состояния
CColor m_focused; // Цвет при наведении курсора
CColor m_pressed; // Цвет при нажатии
CColor m_blocked; // Цвет заблокированного элемента
//--- Преобразует RGB в color
color RGBToColor(const double r,const double g,const double b) const;
//--- Записывает в переменные значения компонентов RGB
void ColorToRGB(const color clr,double &r,double &g,double &b);
//--- Возвращает составляющую цвета (1) Red, (2) Green, (3) Blue
double GetR(const color clr) { return clr&0xFF; }
double GetG(const color clr) { return(clr>>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);
//--- Возвращает интерполированный цвет между тремя цветами в зависимости от значения коэффициента (от -1 до +1)
color InterpolateColorByCoeff(const color color1, const color color2, const color color3, const double coeff);
//--- Инициализация класса
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);
}
//+------------------------------------------------------------------+
//| Возвращает интерполированный цвет между тремя цветами |
//| в зависимости от значения коэффициента (от -1 до +1) |
//+------------------------------------------------------------------+
color CColorElement::InterpolateColorByCoeff(const color color1,const color color2,const color color3,const double coeff)
{
//--- Ограничиваем значение коэффициента
double val=::fmax(-1.0,::fmin(1.0,coeff));
//--- Переменные для получения компонент RGB для каждого цвета
double r1, g1, b1, r2, g2, b2;
double r, g, b, t;
//--- Интерполяция между начальным и средним цветом
if(val<0.0)
{
this.ColorToRGB(color1,r1,g1,b1);
this.ColorToRGB(color2,r2,g2,b2);
t=(val+1.0)/1.0;
r=r1+(r2-r1)*t;
g=g1+(g2-g1)*t;
b=b1+(b2-b1)*t;
}
//--- Интерполяция между средним и конечным цветом
else
{
this.ColorToRGB(color3,r1,g1,b1);
this.ColorToRGB(color2,r2,g2,b2);
t=val/1.0;
r=r2+(r1-r2)*t;
g=g2+(g1-g2)*t;
b=b2+(b1-b2)*t;
}
//--- Возвращаем рассчитанный цвет
return this.RGBToColor(r,g,b);
}
//+------------------------------------------------------------------+
//| 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.Name() ? -1 : 0);
case BASE_SORT_BY_X : return(this.X() >obj.X() ? 1 : this.X() <obj.X() ? -1 : 0);
case BASE_SORT_BY_Y : return(this.Y() >obj.Y() ? 1 : this.Y() <obj.Y() ? -1 : 0);
case BASE_SORT_BY_WIDTH : return(this.Width() >obj.Width() ? 1 : this.Width() <obj.Width() ? -1 : 0);
case BASE_SORT_BY_HEIGHT: return(this.Height() >obj.Height() ? 1 : this.Height() <obj.Height() ? -1 : 0);
default : return(this.ID() >obj.ID() ? 1 : this.ID() <obj.ID() ? -1 : 0);
}
}
//+------------------------------------------------------------------+
//| CBound::Сохранение в файл |
//+------------------------------------------------------------------+
bool CBound::Save(const int file_handle)
{
//--- Сохраняем данные родительского объекта
if(!CBaseObj::Save(file_handle))
return false;
//--- Сохраняем структуру области
if(::FileWriteStruct(file_handle,this.m_bound)!=sizeof(this.m_bound))
return(false);
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CBound::Загрузка из файла |
//+------------------------------------------------------------------+
bool CBound::Load(const int file_handle)
{
//--- Загружаем данные родительского объекта
if(!CBaseObj::Load(file_handle))
return false;
//--- Загружаем структуру области
if(::FileReadStruct(file_handle,this.m_bound)!=sizeof(this.m_bound))
return(false);
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс счётчика миллисекунд |
//+------------------------------------------------------------------+
class CCounter : public CBaseObj
{
private:
bool m_launched; // Флаг запущенного отсчёта
//--- Запускает отсчёт
void Run(const uint delay)
{
//--- Если отсчёт уже запущен - уходим
if(this.m_launched)
return;
//--- Если передано ненулевое значение задержки - устанавливаем новое значение
if(delay!=0)
this.m_delay=delay;
//--- Запоминаем время запуска и устанавливаем флаг, что отсчёт уже запущен
this.m_start=::GetTickCount64();
this.m_launched=true;
}
protected:
ulong m_start; // Время начала отсчёта
uint m_delay; // Задержка
public:
//--- (1) Устанавливает задержку, запускает отсчёт с (2) установленной, (3) указанной задержкой
void SetDelay(const uint delay) { this.m_delay=delay; }
void Start(void) { this.Run(0); }
void Start(const uint delay) { this.Run(delay); }
//--- Возвращает флаг окончания отсчёта
bool IsDone(void)
{
//--- Если отсчёт не запущен - возвращаем false
if(!this.m_launched)
return false;
//--- Если прошло миллисекунд больше, чем время ожидания
if(::GetTickCount64()-this.m_start>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.Name() ? -1 : 0);
case BASE_SORT_BY_X : return(this.X() >obj.X() ? 1 : this.X() <obj.X() ? -1 : 0);
case BASE_SORT_BY_Y : return(this.Y() >obj.Y() ? 1 : this.Y() <obj.Y() ? -1 : 0);
case BASE_SORT_BY_WIDTH : return(this.Width() >obj.Width() ? 1 : this.Width() <obj.Width() ? -1 : 0);
case BASE_SORT_BY_HEIGHT: return(this.Height() >obj.Height() ? 1 : this.Height() <obj.Height() ? -1 : 0);
case BASE_SORT_BY_ZORDER: return(this.ObjectZOrder() >obj.ObjectZOrder() ? 1 : this.ObjectZOrder() <obj.ObjectZOrder() ? -1 : 0);
default : return(this.ID() >obj.ID() ? 1 : this.ID() <obj.ID() ? -1 : 0);
}
}
//+------------------------------------------------------------------+
//| CCanvasBase::Создаёт канвасы фона и переднего плана |
//+------------------------------------------------------------------+
bool CCanvasBase::CreateCanvasObjects(void)
{
//--- Если оба канваса уже созданы, или класс не управляет канвасами - возвращаем true
if((this.m_background!=NULL && this.m_foreground!=NULL) || !this.m_canvas_owner)
return true;
//--- Создаём канвас фона
this.m_background=new CCanvas();
if(this.m_background==NULL)
{
::PrintFormat("%s: Error! Failed to create background canvas",__FUNCTION__);
return false;
}
//--- Создаём канвас переднего плана
this.m_foreground=new CCanvas();
if(this.m_foreground==NULL)
{
::PrintFormat("%s: Error! Failed to create foreground canvas",__FUNCTION__);
return false;
}
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CCanvasBase::Создаёт графические объекты фона и переднего плана |
//+------------------------------------------------------------------+
bool CCanvasBase::Create(const long chart_id,const int wnd,const string object_name,const int x,const int y,const int w,const int h)
{
//--- Получаем скорректированный идентификатор графика
long id=this.CorrectChartID(chart_id);
//--- Корректируем переданное имя для объекта
string nm=object_name;
::StringReplace(nm," ","");
//--- Создаём имя графического объекта для фона и создаём канвас
string obj_name=nm+"BG";
if(!this.m_background.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;
}
//--- Создаём имя графического объекта для переднего плана и создаём канвас
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(x<left || x>right || y<top || y>bottom)
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(this.m_wnd>0 && this.m_wnd_y==0)
this.m_wnd_y=(int)::ChartGetInteger(this.m_chart_id,CHART_WINDOW_YDISTANCE,this.m_wnd);
//--- Событие изменения графика
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()<ELEMENT_TYPE_PANEL)
return;
//--- Вызываем обработчик создания графического объекта
this.OnCreateEvent(id,lparam,dparam,sparam);
}
//--- Если элемент заблокирован или скрыт - уходим
if(this.IsBlocked() || this.IsHidden())
return;
//--- Координаты курсора мышки
int x=(int)lparam;
int y=(int)dparam-this.m_wnd_y; // Корректируем Y по высоте окна индикатора
//--- Событие перемещения курсора
if(id==CHARTEVENT_MOUSE_MOVE)
{
//--- Отправим координаты курсора в менеджер ресурсов
CCommonManager::GetInstance().SetCursorX(x);
CCommonManager::GetInstance().SetCursorY(y);
//--- Неактивные элементы, кроме главного, не обрабатываем
if(!this.IsMain() && (this.Type()<ACTIVE_ELEMENT_MIN || 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);
}
//+------------------------------------------------------------------+