1780 Zeilen
109 KiB
MQL5
1780 Zeilen
109 KiB
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
|
|
|
|
//--- Форвард-декларация классов элементов управления
|
|
class CImagePainter; // Класс рисования изображений
|
|
class CLabel; // Класс текстовой метки
|
|
class CButton; // Класс простой кнопки
|
|
class CButtonTriggered; // Класс двухпозиционной кнопки
|
|
class CButtonArrowUp; // Класс кнопки со стрелкой вверх
|
|
class CButtonArrowDown; // Класс кнопки со стрелкой вниз
|
|
class CButtonArrowLeft; // Класс кнопки со стрелкой влево
|
|
class CButtonArrowRight; // Класс кнопки со стрелкой вправо
|
|
class CCheckBox; // Класс элемента управления CheckBox
|
|
class CRadioButton; // Класс элемента управления RadioButton
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Макроподстановки |
|
|
//+------------------------------------------------------------------+
|
|
#define clrNULL 0x00FFFFFF // Прозрачный цвет для CCanvas
|
|
#define MARKER_START_DATA -1 // Маркер начала данных в файле
|
|
#define DEF_FONTNAME "Calibri" // Шрифт по умолчанию
|
|
#define DEF_FONTSIZE 10 // Размер шрифта по умолчанию
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Перечисления |
|
|
//+------------------------------------------------------------------+
|
|
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_CANVAS_BASE, // Базовый объект холста графических элементов
|
|
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, // Активирован (напр. кнопка нажата, и т.п.)
|
|
};
|
|
|
|
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; }
|
|
|
|
//--- Виртуальные методы (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
|
|
{
|
|
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) загрузки из файла, (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)
|
|
{
|
|
//--- Сохраняем данные родительского объекта
|
|
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);
|
|
|
|
//--- Инициализация класса
|
|
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) загрузки из файла, (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);
|
|
this.Init();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
this.Init();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| CColorControl::Конструктор с указанием цвета объекта |
|
|
//+------------------------------------------------------------------+
|
|
CColorElement::CColorElement(const color clr)
|
|
{
|
|
this.InitColors(clr);
|
|
this.Init();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| CColorControl::Инициализация класса |
|
|
//+------------------------------------------------------------------+
|
|
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);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
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);
|
|
}
|
|
//+-------------------------------------------------------------------+
|
|
//|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)
|
|
{
|
|
//--- Сохраняем данные родительского объекта
|
|
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:
|
|
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); }
|
|
|
|
//--- Возвращает описание объекта
|
|
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: 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)
|
|
{
|
|
//--- Сохраняем данные родительского объекта
|
|
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 CCanvasBase : public CBaseObj
|
|
{
|
|
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; // Канвас для рисования переднего плана
|
|
CBound m_bound; // Границы объекта
|
|
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; // Объект управления цветом рамки активированного элемента
|
|
|
|
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; // Ширина рамки
|
|
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);
|
|
//--- Возвращает флаг нахождения курсора внутри объекта
|
|
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; } // обработчик здесь отключен
|
|
|
|
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; }
|
|
|
|
//--- Возвращает указатель на объект управления цветом (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);
|
|
|
|
//--- Создаёт 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);
|
|
|
|
//--- (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; }
|
|
|
|
//--- Устанавливает прозрачность для фона и переднего плана
|
|
void SetAlpha(const uchar value) { this.m_alpha_fg=this.m_alpha_bg=value; }
|
|
|
|
//--- (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);
|
|
|
|
//--- Возвращает описание объекта
|
|
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); }
|
|
|
|
//--- Обработчик событий |
|
|
void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam);
|
|
|
|
//--- Конструкторы/деструктор
|
|
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_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);
|
|
~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_border_width(0), m_state(0)
|
|
{
|
|
//--- Получаем скорректированный идентификатор графика и дистанцию в пикселях по вертикальной оси 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);
|
|
//--- Если графический ресурс и графический объект созданы
|
|
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::Создаёт графические объекты фона и переднего плана |
|
|
//+------------------------------------------------------------------+
|
|
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");
|
|
|
|
//--- Устанавливаем размеры прямоугольной области и возвращаем 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);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 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;
|
|
//--- Устанавливаем текущие цвета как цвета заблокированного элемента,
|
|
//--- устанавливаем флаг блокировки и перерисовываем объект
|
|
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::Заливает объект указанным цветом |
|
|
//| с установленной в 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)
|
|
{
|
|
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;
|
|
|
|
//--- Сохраняем данные родительского объекта
|
|
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();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
}
|
|
//+------------------------------------------------------------------+
|