2026-03-27 16:51:47 +07:00
//+------------------------------------------------------------------+
//| Base.mqh |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
2026-03-28 03:10:10 +07:00
# property copyright " Copyright 2025, MetaQuotes Ltd. "
# property link " https://www.mql5.com "
2026-03-27 16:51:47 +07:00
//+------------------------------------------------------------------+
//| Включаемые библиотеки |
//+------------------------------------------------------------------+
# include <Canvas\Canvas.mqh> // Класс СБ CCanvas
# include <Arrays\List.mqh> // Класс СБ CList
2026-03-28 03:10:10 +07:00
//--- Форвард-декларация классов элементов управления
class CImagePainter ; // Класс рисования изображений
class CLabel ; // Класс текстовой метки
class CButton ; // Класс простой кнопки
class CButtonTriggered ; // Класс двухпозиционной кнопки
class CButtonArrowUp ; // Класс кнопки со стрелкой вверх
class CButtonArrowDown ; // Класс кнопки со стрелкой вниз
class CButtonArrowLeft ; // Класс кнопки со стрелкой влево
class CButtonArrowRight ; // Класс кнопки со стрелкой вправо
class CCheckBox ; // Класс элемента управления CheckBox
class CRadioButton ; // Класс элемента управления RadioButton
2026-03-27 16:51:47 +07:00
//+------------------------------------------------------------------+
//| Макроподстановки |
//+------------------------------------------------------------------+
# define clrNULL 0x00FFFFFF / / Прозрачный цвет для CCanvas
# define MARKER_START_DATA -1 / / Маркер начала данных в файле
2026-03-28 03:10:10 +07:00
# define DEF_FONTNAME " Calibri " / / Шрифт по умолчанию
# define DEF_FONTSIZE 10 / / Размер шрифта по умолчанию
2026-03-27 16:51:47 +07:00
//+------------------------------------------------------------------+
//| Перечисления |
//+------------------------------------------------------------------+
enum ENUM_ELEMENT_TYPE // Перечисление типов графических элементов
{
ELEMENT_TYPE_BASE = 0x10000 , // Базовый объект графических элементов
ELEMENT_TYPE_COLOR , // Объект цвета
ELEMENT_TYPE_COLORS_ELEMENT , // Объект цветов элемента графического объекта
ELEMENT_TYPE_RECTANGLE_AREA , // Прямоугольная область элемента
2026-03-28 03:10:10 +07:00
ELEMENT_TYPE_IMAGE_PAINTER , // Объект для рисования изображений
2026-03-27 16:51:47 +07:00
ELEMENT_TYPE_CANVAS_BASE , // Базовый объект холста графических элементов
2026-03-28 03:10:10 +07:00
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
} ;
enum ENUM_ELEMENT_STATE // Состояние элемента
{
ELEMENT_STATE_DEF , // По умолчанию (напр. кнопка отжата, и т.п.)
ELEMENT_STATE_ACT , // Активирован (напр. кнопка нажата, и т.п.)
2026-03-27 16:51:47 +07:00
} ;
enum ENUM_COLOR_STATE // Перечисление цветов состояний элемента
{
COLOR_STATE_DEFAULT , // Цвет обычного состояния
COLOR_STATE_FOCUSED , // Цвет при наведении курсора на элемент
COLOR_STATE_PRESSED , // Цвет при нажатии на элемент
COLOR_STATE_BLOCKED , // Цвет заблокированного элемента
} ;
//+------------------------------------------------------------------+
//| Функции |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Возвращает тип элемента как строку |
//+------------------------------------------------------------------+
string ElementDescription ( const ENUM_ELEMENT_TYPE type )
{
string array [ ] ;
int total = StringSplit ( EnumToString ( type ) , StringGetCharacter ( " _ " , 0 ) , array ) ;
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 ;
}
//+------------------------------------------------------------------+
//| Классы |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Базовый класс графических элементов |
//+------------------------------------------------------------------+
class CBaseObj : public CObject
{
protected :
int m_id ; // Идентифткатор
ushort m_name [ ] ; // Наименование
public :
//--- Устанавливает (1) наименование, (2) идентификатор
void SetName ( const string name ) { : : StringToShortArray ( name , this . m_name ) ; }
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 ; }
2026-03-28 03:10:10 +07:00
//--- Виртуальные методы (1) сравнения, (2) сохранения в файл, (3) загрузки из файла, (4) тип объекта
2026-03-27 16:51:47 +07:00
virtual int Compare ( const CObject * node , const int mode = 0 ) const ;
2026-03-28 03:10:10 +07:00
virtual bool Save ( const int file_handle ) ;
virtual bool Load ( const int file_handle ) ;
2026-03-27 16:51:47 +07:00
virtual int Type ( void ) const { return ( ELEMENT_TYPE_BASE ) ; }
2026-03-28 03:10:10 +07:00
//--- (1) Возвращает, (2) выводит в журнал описание объекта
virtual string Description ( void ) ;
virtual void Print ( void ) ;
//--- Конструктор/деструктор
CBaseObj ( void ) : m_id ( -1 ) { this . SetName ( " " ) ; }
2026-03-27 16:51:47 +07:00
~ CBaseObj ( void ) { }
} ;
//+------------------------------------------------------------------+
//| CBaseObj::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CBaseObj : : Compare ( const CObject * node , const int mode = 0 ) const
{
const CBaseObj * obj = node ;
switch ( mode )
{
2026-03-28 03:10:10 +07:00
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 ) ;
2026-03-27 16:51:47 +07:00
}
}
//+------------------------------------------------------------------+
2026-03-28 03:10:10 +07:00
//| 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 ;
}
//+------------------------------------------------------------------+
2026-03-27 16:51:47 +07:00
//+------------------------------------------------------------------+
//| Класс цвета |
//+------------------------------------------------------------------+
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 ; }
2026-03-28 03:10:10 +07:00
//--- Возвращает описание объекта
2026-03-27 16:51:47 +07:00
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_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 )
{
2026-03-28 03:10:10 +07:00
//--- Сохраняем данные родительского объекта
if ( ! CBaseObj : : Save ( file_handle ) )
2026-03-27 16:51:47 +07:00
return false ;
2026-03-28 03:10:10 +07:00
2026-03-27 16:51:47 +07:00
//--- Сохраняем цвет
if ( : : FileWriteInteger ( file_handle , this . m_color , INT_VALUE ) ! = INT_VALUE )
return false ;
//--- Всё успешно
return true ;
}
//+------------------------------------------------------------------+
//| CColor::Загрузка из файла |
//+------------------------------------------------------------------+
bool CColor : : Load ( const int file_handle )
{
2026-03-28 03:10:10 +07:00
//--- Загружаем данные родительского объекта
if ( ! CBaseObj : : Load ( file_handle ) )
2026-03-27 16:51:47 +07:00
return false ;
2026-03-28 03:10:10 +07:00
2026-03-27 16:51:47 +07:00
//--- Загружаем цвет
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 ) ;
2026-03-28 03:10:10 +07:00
//--- Инициализация класса
void Init ( void ) ;
2026-03-27 16:51:47 +07:00
//--- Инициализация цветов различных состояний
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 ) ;
2026-03-28 03:10:10 +07:00
//--- Возвращает описание объекта
2026-03-27 16:51:47 +07:00
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_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 ) { }
} ;
//+------------------------------------------------------------------+
//| CColorControl::Конструктор с установкой прозрачных цветов объекта|
//+------------------------------------------------------------------+
CColorElement : : CColorElement ( void )
{
this . InitColors ( clrNULL , clrNULL , clrNULL , clrNULL ) ;
2026-03-28 03:10:10 +07:00
this .Init ( ) ;
2026-03-27 16:51:47 +07:00
}
//+------------------------------------------------------------------+
//| CColorControl::Конструктор с указанием цветов объекта |
//+------------------------------------------------------------------+
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 ) ;
2026-03-28 03:10:10 +07:00
this .Init ( ) ;
2026-03-27 16:51:47 +07:00
}
//+------------------------------------------------------------------+
//| CColorControl::Конструктор с указанием цвета объекта |
//+------------------------------------------------------------------+
CColorElement : : CColorElement ( const color clr )
{
this . InitColors ( clr ) ;
2026-03-28 03:10:10 +07:00
this .Init ( ) ;
}
//+------------------------------------------------------------------+
//| CColorControl::Инициализация класса |
//+------------------------------------------------------------------+
void CColorElement ::Init ( void )
{
2026-03-27 16:51:47 +07:00
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 ) ;
}
//+------------------------------------------------------------------+
//| CColorControl::Устанавливает цвета для всех состояний |
//+------------------------------------------------------------------+
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 ) ;
}
//+------------------------------------------------------------------+
//| CColorControl::Устанавливает цвета для всех состояний по текущему|
//+------------------------------------------------------------------+
void CColorElement : : InitColors ( const color clr )
{
this . InitDefault ( clr ) ;
2026-03-28 03:10:10 +07:00
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 ) ;
2026-03-27 16:51:47 +07:00
}
//+-------------------------------------------------------------------+
//|CColorControl::Устанавливает один цвет из списка цветов как текущий|
//+-------------------------------------------------------------------+
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 ;
}
}
//+------------------------------------------------------------------+
//| CColorControl::Преобразует 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 ;
}
//+------------------------------------------------------------------+
//| CColorControl::Получение значений компонентов 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 ) ;
}
//+------------------------------------------------------------------+
//| CColorControl::Возвращает цвет с новой цветовой составляющей |
//+------------------------------------------------------------------+
color CColorElement : : NewColor ( color base_color , int shift_red , int shift_green , int shift_blue )
{
double clrR = 0 , clrG = 0 , clrB = 0 ;
this . ColorToRGB ( base_color , clrR , clrG , clrB ) ;
double clrRx = ( clrR + shift_red < 0 ? 0 : clrR + shift_red > 255 ? 255 : clrR + shift_red ) ;
double clrGx = ( clrG + shift_green < 0 ? 0 : clrG + shift_green > 255 ? 255 : clrG + shift_green ) ;
double clrBx = ( clrB + shift_blue < 0 ? 0 : clrB + shift_blue > 255 ? 255 : clrB + shift_blue ) ;
return this . RGBToColor ( clrRx , clrGx , clrBx ) ;
}
//+------------------------------------------------------------------+
//| CColorElement::Возвращает описание объекта |
//+------------------------------------------------------------------+
string CColorElement : : Description ( void )
{
string res = : : StringFormat ( " %s Colors. %s " , this . Name ( ) , this . m_current . Description ( ) ) ;
res + = " \n 1: " + this . m_default . Description ( ) ;
res + = " \n 2: " + this . m_focused . Description ( ) ;
res + = " \n 3: " + this . m_pressed . Description ( ) ;
res + = " \n 4: " + this . m_blocked . Description ( ) ;
return res ;
}
//+------------------------------------------------------------------+
//| CColorElement::Сохранение в файл |
//+------------------------------------------------------------------+
bool CColorElement : : Save ( const int file_handle )
{
2026-03-28 03:10:10 +07:00
//--- Сохраняем данные родительского объекта
if ( ! CBaseObj : : Save ( file_handle ) )
2026-03-27 16:51:47 +07:00
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 )
{
2026-03-28 03:10:10 +07:00
//--- Загружаем данные родительского объекта
if ( ! CBaseObj : : Load ( file_handle ) )
2026-03-27 16:51:47 +07:00
return false ;
2026-03-28 03:10:10 +07:00
2026-03-27 16:51:47 +07:00
//--- Загружаем текущий цвет
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 :
CRect m_bound ; // Структура прямоугольной области
public :
//--- Изменяет (1) ширину, (2) высоту, (3) размер ограничивающего прямоугольника
2026-03-28 03:10:10 +07:00
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 ) ; }
2026-03-27 16:51:47 +07:00
//--- Устанавливает координату (1) X, (2) Y, (3) обе координаты ограничивающего прямоугольника
2026-03-28 03:10:10 +07:00
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 ) ; }
2026-03-27 16:51:47 +07:00
//--- (1) Устанавливает, (2) смещает ограничивающий прямоугольник на указанные координаты/размер смещения
2026-03-28 03:10:10 +07:00
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 ) ; }
2026-03-27 16:51:47 +07:00
//--- Возвращает координаты, размеры и границы объекта
2026-03-28 03:10:10 +07:00
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 ) ; }
2026-03-27 16:51:47 +07:00
2026-03-28 03:10:10 +07:00
//--- Возвращает описание объекта
2026-03-27 16:51:47 +07:00
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 ) ;
2026-03-28 03:10:10 +07:00
virtual int Type ( void ) const { return ( ELEMENT_TYPE_RECTANGLE_AREA ) ; }
2026-03-27 16:51:47 +07:00
//--- Конструкторы/деструктор
CBound ( void ) { : : ZeroMemory ( this . m_bound ) ; }
2026-03-28 03:10:10 +07:00
CBound ( const int x , const int y , const int w , const int h ) { this . SetXY ( x , y ) ; this .Resize ( w , h ) ; }
2026-03-27 16:51:47 +07:00
~ 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: x %d, y %d, w %d, h %d " ,
ElementDescription ( ( ENUM_ELEMENT_TYPE ) this . Type ( ) ) , name ,
this . X ( ) , this . Y ( ) , this . Width ( ) , this . Height ( ) ) ;
}
//+------------------------------------------------------------------+
//| CBound::Сохранение в файл |
//+------------------------------------------------------------------+
bool CBound : : Save ( const int file_handle )
{
2026-03-28 03:10:10 +07:00
//--- Сохраняем данные родительского объекта
if ( ! CBaseObj : : Save ( file_handle ) )
2026-03-27 16:51:47 +07:00
return false ;
2026-03-28 03:10:10 +07:00
2026-03-27 16:51:47 +07:00
//--- Сохраняем структуру области
if ( : : FileWriteStruct ( file_handle , this . m_bound ) ! = sizeof ( this . m_bound ) )
return ( false ) ;
//--- Всё успешно
return true ;
}
//+------------------------------------------------------------------+
//| CBound::Загрузка из файла |
//+------------------------------------------------------------------+
bool CBound : : Load ( const int file_handle )
{
2026-03-28 03:10:10 +07:00
//--- Загружаем данные родительского объекта
if ( ! CBaseObj : : Load ( file_handle ) )
2026-03-27 16:51:47 +07:00
return false ;
2026-03-28 03:10:10 +07:00
2026-03-27 16:51:47 +07:00
//--- Загружаем структуру области
if ( : : FileReadStruct ( file_handle , this . m_bound ) ! = sizeof ( this . m_bound ) )
return ( false ) ;
//--- Всё успешно
return true ;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Базовый класс холста графических элементов |
//+------------------------------------------------------------------+
class CCanvasBase : public CBaseObj
{
2026-03-28 03:10:10 +07:00
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 ) ;
2026-03-27 16:51:47 +07:00
protected :
CCanvas m_background ; // Канвас для рисования фона
CCanvas m_foreground ; // Канвас для рисования переднего плана
CBound m_bound ; // Границы объекта
CCanvasBase * m_container ; // Родительский объект-контейнер
CColorElement m_color_background ; // Объект управления цветом фона
CColorElement m_color_foreground ; // Объект управления цветом переднего плана
CColorElement m_color_border ; // Объект управления цветом рамки
2026-03-28 03:10:10 +07:00
CColorElement m_color_background_act ; // Объект управления цветом фона активированного элемента
CColorElement m_color_foreground_act ; // Объект управления цветом переднего плана активированного элемента
CColorElement m_color_border_act ; // Объект управления цветом рамки активированного элемента
ENUM_ELEMENT_STATE m_state ; // Состояние элемента (напр., кнопки (вкл/выкл))
2026-03-27 16:51:47 +07:00
long m_chart_id ; // Идентификатор графика
int m_wnd ; // Номер подокна графика
int m_wnd_y ; // Смещение координаты Y курсора в подокне
int m_obj_x ; // Координата X графического объекта
int m_obj_y ; // Координата Y графического объекта
2026-03-28 03:10:10 +07:00
uchar m_alpha_bg ; // Прозрачность фона
uchar m_alpha_fg ; // Прозрачность переднего плана
2026-03-27 16:51:47 +07:00
uint m_border_width ; // Ширина рамки
string m_program_name ; // Имя программы
bool m_hidden ; // Флаг скрытого объекта
bool m_blocked ; // Флаг заблокированного элемента
bool m_focused ; // Флаг элемента в фокусе
//--- Возврат смещения начальных координат рисования на холсте относительно канваса и координат объекта
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 ( ) ) ; }
//--- Получение границ родительского объекта-контейнера
int ContainerLimitLeft ( void ) const { return ( this . m_container = = NULL ? this . X ( ) : this . m_container . LimitLeft ( ) ) ; }
int ContainerLimitRight ( void ) const { return ( this . m_container = = NULL ? this . Right ( ) : this . m_container . LimitRight ( ) ) ; }
int ContainerLimitTop ( void ) const { return ( this . m_container = = NULL ? this . Y ( ) : this . m_container . LimitTop ( ) ) ; }
int ContainerLimitBottom ( void ) const { return ( this . m_container = = NULL ? this . Bottom ( ) : this . m_container . LimitBottom ( ) ) ; }
//--- Возврат координат, границ и размеров графического объекта
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) размер ограничивающего прямоугольника
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) размер графического объекта
bool ObjectResizeW ( const int size ) ;
bool ObjectResizeH ( const int size ) ;
bool ObjectResize ( const int w , const int h ) ;
//--- Устанавливает координату (1) X, (2) Y, (3) обе координаты графического объекта
bool ObjectSetX ( const int x ) ;
bool ObjectSetY ( const int y ) ;
bool ObjectSetXY ( const int x , const int y ) { return ( this . ObjectSetX ( x ) & & this . ObjectSetY ( y ) ) ; }
//--- (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 ) ; }
//--- Ограничивает графический объект по размерам контейнера
virtual void ObjectTrim ( void ) ;
2026-03-28 03:10:10 +07:00
//--- Возвращает флаг нахождения курсора внутри объекта
bool Contains ( 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 ) ;
virtual void InitColors ( void ) ;
//--- Обработчики событий (1) наведения курсора (Focus), (2) нажатий кнопок мышки (Press), (3) прокрутки колёсика (Wheel),
//--- (4) ухода из фокуса (Release), (5) создания графического объекта (Create). Должны определяться в наследниках
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 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 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 ; } // обработчик здесь отключен
2026-03-27 16:51:47 +07:00
public :
//--- Возвращает указатель на канвас (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 ; }
2026-03-28 03:10:10 +07:00
//--- Возвращает указатель на объект управления цветом (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 ( ) ; }
2026-03-27 16:51:47 +07:00
//--- Установка цветов фона для всех состояний
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 ) ; }
2026-03-28 03:10:10 +07:00
//--- Установка цветов фона для всех состояний
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 ) ; }
2026-03-27 16:51:47 +07:00
//--- Установка текущего цвета фона в различные состояния
2026-03-28 03:10:10 +07:00
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 ) ; }
2026-03-27 16:51:47 +07:00
//--- Установка текущего цвета переднего плана в различные состояния
2026-03-28 03:10:10 +07:00
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 ) ; }
2026-03-27 16:51:47 +07:00
//--- Установка текущего цвета рамки в различные состояния
2026-03-28 03:10:10 +07:00
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 ) ; }
2026-03-27 16:51:47 +07:00
//--- Установка текущих цветов элемента в различные состояния
bool ColorsToDefault ( void ) ;
bool ColorsToFocused ( void ) ;
bool ColorsToPressed ( void ) ;
bool ColorsToBlocked ( void ) ;
//--- Устанавливает указатель на родительский объект-контейнер
void SetContainerObj ( CCanvasBase * obj ) ;
//--- Создаёт OBJ_BITMAP_LABEL
2026-03-28 03:10:10 +07:00
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 ) ;
//--- (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) скрытого, (3) заблокированного элемента (4) в фокусе, (5) имя графического объекта (фон, текст)
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 IsFocused ( void ) const { return this . m_focused ; }
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 ; }
2026-03-27 16:51:47 +07:00
2026-03-28 03:10:10 +07:00
//--- Устанавливает прозрачность для фона и переднего плана
void SetAlpha ( const uchar value ) { this . m_alpha_fg = this . m_alpha_bg = value ; }
2026-03-27 16:51:47 +07:00
//--- (1) Возвращает, (2) устанавливает ширину рамки
uint BorderWidth ( void ) const { return this . m_border_width ; }
void SetBorderWidth ( const uint width ) { this . m_border_width = width ; }
//--- Возвращает координаты, размеры и границы объекта
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) X, (2) Y, (3) XY
bool MoveX ( const int x ) ;
bool MoveY ( const int y ) ;
bool Move ( const int x , const int y ) ;
//--- Смещает объект по оси (1) X, (2) Y, (3) XY на указанное смещение
bool ShiftX ( const int dx ) ;
bool ShiftY ( const int dy ) ;
bool Shift ( const int dx , const int dy ) ;
//--- Возврат границ объекта с учётом рамки
int LimitLeft ( void ) const { return this . X ( ) + ( int ) this . m_border_width ; }
int LimitRight ( void ) const { return this . Right ( ) - ( int ) this . m_border_width ; }
int LimitTop ( void ) const { return this . Y ( ) + ( int ) this . m_border_width ; }
int LimitBottom ( void ) const { return this . Bottom ( ) - ( int ) this . m_border_width ; }
//--- (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 ) ;
2026-03-28 03:10:10 +07:00
//--- Возвращает описание объекта
2026-03-27 16:51:47 +07:00
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 ) ; }
2026-03-28 03:10:10 +07:00
//--- Обработчик событий |
void OnChartEvent ( const int id , const long & lparam , const double & dparam , const string & sparam ) ;
2026-03-27 16:51:47 +07:00
//--- Конструкторы/деструктор
CCanvasBase ( void ) :
m_program_name ( : : MQLInfoString ( MQL_PROGRAM_NAME ) ) , m_chart_id ( : : ChartID ( ) ) , m_wnd ( 0 ) ,
2026-03-28 03:10:10 +07:00
m_alpha_bg ( 0 ) , m_alpha_fg ( 255 ) , m_hidden ( false ) , m_blocked ( false ) , m_focused ( false ) , m_border_width ( 0 ) , m_wnd_y ( 0 ) , m_state ( 0 ) { 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 ) ;
2026-03-27 16:51:47 +07:00
~ CCanvasBase ( void ) ;
} ;
//+------------------------------------------------------------------+
//| CCanvasBase::Конструктор |
//+------------------------------------------------------------------+
2026-03-28 03:10:10 +07:00
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_border_width ( 0 ) , m_state ( 0 )
2026-03-27 16:51:47 +07:00
{
//--- Получаем скорректированный идентификатор графика и дистанцию в пикселях по вертикальной оси Y
//--- между верхней рамкой подокна индикатора и верхней рамкой главного окна графика
this . m_chart_id = this . CorrectChartID ( chart_id ) ;
this . m_wnd_y = ( int ) : : ChartGetInteger ( this . m_chart_id , CHART_WINDOW_YDISTANCE , this . m_wnd ) ;
//--- Если графический ресурс и графический объект созданы
2026-03-28 03:10:10 +07:00
if ( this . Create ( this . m_chart_id , this . m_wnd , object_name , x , y , w , h ) )
2026-03-27 16:51:47 +07:00
{
//--- Очищаем канвасы фона и переднего плана и устанавливаем начальные значения координат,
//--- наименования графических объектов и свойства текста, рисуемого на переднем плане
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 " ) ;
2026-03-28 03:10:10 +07:00
this . m_foreground . FontSet ( DEF_FONTNAME , - DEF_FONTSIZE * 10 , FW_MEDIUM ) ;
2026-03-27 16:51:47 +07:00
this . m_bound . SetName ( " Perimeter " ) ;
2026-03-28 03:10:10 +07:00
//--- Запоминаем разрешения для мышки и инструментов графика
this .Init ( ) ;
2026-03-27 16:51:47 +07:00
}
}
//+------------------------------------------------------------------+
//| CCanvasBase::Деструктор |
//+------------------------------------------------------------------+
CCanvasBase : : ~ CCanvasBase ( void )
{
2026-03-28 03:10:10 +07:00
//--- Уничтожаем объект
2026-03-27 16:51:47 +07:00
this . Destroy ( ) ;
2026-03-28 03:10:10 +07:00
//--- Возвращаем разрешения для мышки и инструментов графика
: : 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 ) ;
2026-03-27 16:51:47 +07:00
}
//+------------------------------------------------------------------+
//| CCanvasBase::Создаёт графические объекты фона и переднего плана |
//+------------------------------------------------------------------+
2026-03-28 03:10:10 +07:00
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 )
2026-03-27 16:51:47 +07:00
{
//--- Получаем скорректированный идентификатор графика
long id = this . CorrectChartID ( chart_id ) ;
2026-03-28 03:10:10 +07:00
//--- Корректируем переданное имя для объекта
string nm = object_name ;
: : StringReplace ( nm , " " , " _ " ) ;
2026-03-27 16:51:47 +07:00
//--- Создаём имя графического объекта для фона и создаём канвас
2026-03-28 03:10:10 +07:00
string obj_name = nm + " _BG " ;
2026-03-27 16:51:47 +07:00
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 ;
}
//--- Создаём имя графического объекта для переднего плана и создаём канвас
2026-03-28 03:10:10 +07:00
obj_name = nm + " _FG " ;
2026-03-27 16:51:47 +07:00
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 ) ;
2026-03-28 03:10:10 +07:00
: : ObjectSetString ( id , this . NameBG ( ) , OBJPROP_TOOLTIP , " \n " ) ;
: : ObjectSetString ( id , this . NameFG ( ) , OBJPROP_TOOLTIP , " \n " ) ;
2026-03-27 16:51:47 +07:00
//--- Устанавливаем размеры прямоугольной области и возвращаем 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::Подрезает графический объект по контуру контейнера |
//+------------------------------------------------------------------+
void CCanvasBase : : ObjectTrim ( )
{
//--- Получаем границы контейнера
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 ( object_right < = container_left | | object_left > = container_right | |
object_bottom < = container_top | | object_top > = container_bottom )
{
this . Hide ( true ) ;
this . ObjectResize ( this . Width ( ) , this . Height ( ) ) ;
return ;
}
//--- Проверяем выход объекта по горизонтали и вертикали за пределы контейнера
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 ) ;
}
}
//+------------------------------------------------------------------+
2026-03-28 03:10:10 +07:00
//| CCanvasBase::Возвращает флаг нахождения курсора внутри объекта |
//+------------------------------------------------------------------+
bool CCanvasBase : : Contains ( const int x , const int y )
{
//--- check and return the result
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 ) ;
}
//+------------------------------------------------------------------+
2026-03-27 16:51:47 +07:00
//| 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::Устанавливает объекту новые координаты 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 . ObjectY ( ) ) ;
}
//+------------------------------------------------------------------+
//| CCanvasBase::Устанавливает объекту новую координату Y |
//+------------------------------------------------------------------+
bool CCanvasBase : : MoveY ( const int y )
{
return this . Move ( 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::Скрывает объект на всех периодах графика |
//+------------------------------------------------------------------+
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 )
{
this . Hide ( false ) ;
this . Show ( chart_redraw ) ;
}
//+------------------------------------------------------------------+
//| 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::Блокирует элемент |
//+------------------------------------------------------------------+
void CCanvasBase : : Block ( const bool chart_redraw )
{
//--- Если элемент уже заблокирован - уходим
if ( this . m_blocked )
return ;
//--- Устанавливаем текущие цвета как цвета заблокированного элемента,
2026-03-28 03:10:10 +07:00
//--- устанавливаем флаг блокировки и перерисовываем объект
2026-03-27 16:51:47 +07:00
this . ColorsToBlocked ( ) ;
this . m_blocked = true ;
2026-03-28 03:10:10 +07:00
this . Draw ( chart_redraw ) ;
2026-03-27 16:51:47 +07:00
}
//+------------------------------------------------------------------+
//| CCanvasBase::Разблокирует элемент |
//+------------------------------------------------------------------+
void CCanvasBase : : Unblock ( const bool chart_redraw )
{
//--- Если элемент уже разблокирован - уходим
if ( ! this . m_blocked )
return ;
//--- Устанавливаем текущие цвета как цвета элемента в обычном состоянии,
//--- перерисовываем объект и сбрасываем флаг блокировки
this . ColorsToDefault ( ) ;
this . Draw ( chart_redraw ) ;
this . m_blocked = false ;
}
//+------------------------------------------------------------------+
//| CCanvasBase::Заливает объект указанным цветом |
//| с установленной в m_alpha прозрачностью |
//+------------------------------------------------------------------+
void CCanvasBase : : Fill ( const color clr , const bool chart_redraw )
{
2026-03-28 03:10:10 +07:00
this . m_background . Erase ( : : ColorToARGB ( clr , this . m_alpha_bg ) ) ;
2026-03-27 16:51:47 +07:00
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 )
{
this . m_background . Destroy ( ) ;
this . m_foreground . Destroy ( ) ;
}
//+------------------------------------------------------------------+
//| 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 ;
2026-03-28 03:10:10 +07:00
//--- Сохраняем данные родительского объекта
if ( ! CBaseObj : : Save ( file_handle ) )
2026-03-27 16:51:47 +07:00
return false ;
/*
//--- Сохранение свойств
* /
//--- Всё успешно
return true ;
}
//+------------------------------------------------------------------+
2026-03-28 03:10:10 +07:00
//| CCanvasBase::Загрузка из файла |
2026-03-27 16:51:47 +07:00
//+------------------------------------------------------------------+
bool CCanvasBase : : Load ( const int file_handle )
{
//--- Метод временно отключен
return false ;
2026-03-28 03:10:10 +07:00
//--- Загружаем данные родительского объекта
if ( ! CBaseObj : : Load ( file_handle ) )
2026-03-27 16:51:47 +07:00
return false ;
/*
//--- Загрузка свойств
* /
//--- Всё успешно
return true ;
}
//+------------------------------------------------------------------+
2026-03-28 03:10:10 +07:00
//| 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 ( ) ;
}
//+------------------------------------------------------------------+
//| CCanvasBase::Инициализация цветов объекта по умолчанию |
//+------------------------------------------------------------------+
void CCanvasBase : : InitColors ( void )
{
//--- Инициализируем цвета заднего плана для обычного и активированного состояний и делаем его текущим цветом фона
this . InitBackColors ( clrWhiteSmoke ) ;
this . InitBackColorsAct ( clrWhiteSmoke ) ;
this . BackColorToDefault ( ) ;
//--- Инициализируем цвета переднего плана для обычного и активированного состояний и делаем его текущим цветом текста
this . InitForeColors ( clrBlack ) ;
this . InitForeColorsAct ( clrBlack ) ;
this . ForeColorToDefault ( ) ;
//--- Инициализируем цвета рамки для обычного и активированного состояний и делаем его текущим цветом рамки
this . InitBorderColors ( clrDarkGray ) ;
this . InitBorderColorsAct ( clrDarkGray ) ;
this . BorderColorToDefault ( ) ;
//--- Инициализируем цвет рамки и цвет переднего плана для заблокированного элемента
this . InitBorderColorBlocked ( clrLightGray ) ;
this . InitForeColorBlocked ( clrSilver ) ;
}
//+------------------------------------------------------------------+
//| CCanvasBase::Проверяет установленный цвет на равенство указанному|
//+------------------------------------------------------------------+
bool CCanvasBase : : CheckColor ( const ENUM_COLOR_STATE state ) const
{
bool res = true ;
//--- В зависимости от проверяемого события
switch ( state )
{
//--- проверяем равенство всех STANDARD цветов фона, текста и рамки предустановленным значениям
case COLOR_STATE_DEFAULT :
res & = this . BackColor ( ) = = this . BackColorDefault ( ) ;
res & = this . ForeColor ( ) = = this . ForeColorDefault ( ) ;
res & = this . BorderColor ( ) = = this . BorderColorDefault ( ) ;
break ;
//--- проверяем равенство всех FOCUSED цветов фона, текста и рамки предустановленным значениям
case COLOR_STATE_FOCUSED :
res & = this . BackColor ( ) = = this . BackColorFocused ( ) ;
res & = this . ForeColor ( ) = = this . ForeColorFocused ( ) ;
res & = this . BorderColor ( ) = = this . BorderColorFocused ( ) ;
break ;
//--- проверяем равенство всех PRESSED цветов фона, текста и рамки предустановленным значениям
case COLOR_STATE_PRESSED :
res & = this . BackColor ( ) = = this . BackColorPressed ( ) ;
res & = this . ForeColor ( ) = = this . ForeColorPressed ( ) ;
res & = this . BorderColor ( ) = = this . BorderColorPressed ( ) ;
break ;
//--- проверяем равенство всех BLOCKED цветов фона, текста и рамки предустановленным значениям
case COLOR_STATE_BLOCKED :
res & = this . BackColor ( ) = = this . BackColorBlocked ( ) ;
res & = this . ForeColor ( ) = = this . ForeColorBlocked ( ) ;
res & = this . BorderColor ( ) = = this . BorderColorBlocked ( ) ;
break ;
default : res = false ;
break ;
}
return res ;
}
//+------------------------------------------------------------------+
//| CCanvasBase::Смена цвета элементов объекта по событию |
//+------------------------------------------------------------------+
void CCanvasBase : : ColorChange ( const ENUM_COLOR_STATE state )
{
//--- В зависимости от события устанавливаем цвета события как основные
switch ( state )
{
case COLOR_STATE_DEFAULT : this . ColorsToDefault ( ) ; break ;
case COLOR_STATE_FOCUSED : this . ColorsToFocused ( ) ; break ;
case COLOR_STATE_PRESSED : this . ColorsToPressed ( ) ; break ;
case COLOR_STATE_BLOCKED : this . ColorsToBlocked ( ) ; break ;
default : break ;
}
}
//+------------------------------------------------------------------+
//| CCanvasBase::Обработчик событий |
//+------------------------------------------------------------------+
void CCanvasBase : : OnChartEvent ( const int id , const long & lparam , const double & dparam , const string & sparam )
{
//--- Если изменение графика
if ( id = = CHARTEVENT_CHART_CHANGE )
{
//--- скорректируем дистанцию между верхней рамкой подокна индикатора и верхней рамкой главного окна графика
this . m_wnd_y = ( int ) : : ChartGetInteger ( this . m_chart_id , CHART_WINDOW_YDISTANCE , this . m_wnd ) ;
}
//--- Если элемент заблокирован или скрыт - уходим
if ( this . IsBlocked ( ) | | this . IsHidden ( ) )
return ;
//--- Координаты курсора мышки
int x = ( int ) lparam ;
int y = ( int ) dparam - this . m_wnd_y ; // Корректируем Y по высоте окна индикатора
//--- Событие перемещения курсора, либо щелчка кнопкой мышки
if ( id = = CHARTEVENT_MOUSE_MOVE | | id = = CHARTEVENT_OBJECT_CLICK )
{
//--- Если курсор в пределах объекта
if ( this . Contains ( x , y ) )
{
//--- Если объект не в составе контейнера - запрещаем прокрутку графика, контекстное меню и инструмент "Перекрестие"
if ( this . m_container = = NULL )
this . SetFlags ( false ) ;
//--- Получаем состояние кнопок мышки, если нажаты - вызываем обработчик нажатий
if ( sparam = = " 1 " | | sparam = = " 2 " | | sparam = = " 16 " )
this . OnPressEvent ( id , lparam , dparam , sparam ) ;
//--- кнопки не нажаты - обрабатываем перемещение курсора
else
this . OnFocusEvent ( id , lparam , dparam , sparam ) ;
}
//--- Курсор за пределами объекта
else
{
//--- Обрабатываем увод курсора за границы объекта
this . OnReleaseEvent ( id , lparam , dparam , sparam ) ;
//--- Если объект не в составе контейнера - разрешаем прокрутку графика, контекстное меню и инструмент "Перекрестие"
if ( this . m_container = = NULL )
this . SetFlags ( true ) ;
}
}
//--- Событие прокрутки колёсика мышки
if ( id = = CHARTEVENT_MOUSE_WHEEL )
{
this . OnWheelEvent ( id , lparam , dparam , sparam ) ;
}
//--- Событие создания графического объекта
if ( id = = CHARTEVENT_OBJECT_CREATE )
{
this . OnCreateEvent ( id , lparam , dparam , sparam ) ;
}
//--- Если пришло пользовательское событие графика
if ( id > CHARTEVENT_CUSTOM )
{
//--- собственные события не обрабатываем
if ( sparam = = this . NameBG ( ) )
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 ) ;
}
}
}
//+------------------------------------------------------------------+
//| CCanvasBase::Обработчик ухода из фокуса |
//+------------------------------------------------------------------+
void CCanvasBase : : OnReleaseEvent ( const int id , const long lparam , const double dparam , const string sparam )
{
//--- Элемент не в фокусе при уводе курсора
this . m_focused = false ;
//--- восстанавливаем исходные цвета, сбрасываем флаг Focused и перерисовываем объект
if ( ! this . CheckColor ( COLOR_STATE_DEFAULT ) )
{
this . ColorChange ( COLOR_STATE_DEFAULT ) ;
this . Draw ( true ) ;
}
}
//+------------------------------------------------------------------+
//| 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 ) ;
}
}
//+------------------------------------------------------------------+
//| 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 ) ;
}
//--- отправляем пользовательское событие на график с передаенными значениями в lparam, dparam, и именем объекта в sparam
: : EventChartCustom ( this . m_chart_id , ( ushort ) CHARTEVENT_OBJECT_CLICK , lparam , dparam , this . NameBG ( ) ) ;
}
//+------------------------------------------------------------------+
//| CCanvasBase::Обработчик события создания графического объекта |
//+------------------------------------------------------------------+
void CCanvasBase : : OnCreateEvent ( const int id , const long lparam , const double dparam , const string sparam )
{
//--- если это объект, принадлежащий этой программе - уходим
if ( this . IsBelongsToThis ( sparam ) )
return ;
//--- переносим объект на передний план
this . BringToTop ( true ) ;
}
//+------------------------------------------------------------------+