EasyAndFastMod/Controls/Graph.mqh
2026-01-15 07:23:17 -05:00

379 строки
29 КиБ
MQL5

//+------------------------------------------------------------------+
//| Graph.mqh |
//| Copyright 2017, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
//+------------------------------------------------------------------+
//| Класс для создания графика |
//+------------------------------------------------------------------+
class CGraph : public CElement
{
private:
//--- Объекты для создания элемента
CGraphic m_graph;
//--- Полноэкранный режим
bool m_is_fullscreen_mode;
//--- Предадущие размеры и положение для режима "Полноэкранный режим"
int m_prev_x;
int m_prev_y;
int m_prev_width;
int m_prev_height;
//---
public:
CGraph(void);
~CGraph(void);
//--- Методы для создания элемента
bool CreateGraph(const int x_gap,const int y_gap);
//---
private:
void InitializeProperties(const int x_gap,const int y_gap);
bool CreateGraphic(void);
//---
public:
//--- Возвращает указатель на график
CGraphic *GetGraphicPointer(void) { return(::GetPointer(m_graph)); }
//--- Изменение размеров
void Resize(const int width,const int height);
//--- Полноэкранный режим
void IsFullScreenMode(const bool mode) { m_is_fullscreen_mode=mode; };
void FullScreenMode(const bool mode=true);
//---
public:
//--- Обработчик событий графика
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
//--- Перемещение элемента
virtual void Moving(const bool only_visible=true);
//--- Управление
virtual void Show(void);
virtual void Hide(void);
virtual void Reset(void);
virtual void Delete(void);
//--- Применение последних изменений
virtual void Update(const bool redraw=false);
//--- (1) Установка, (2) сброс приоритетов на нажитие левой кнопки мыши
virtual void SetZorders(void);
virtual void ResetZorders(void);
//---
private:
//--- Обработка нажатия на графике
bool OnClickGraph(const string pressed_object);
//--- Изменить ширину по правому краю окна
virtual void ChangeWidthByRightWindowSide(void);
//--- Изменить высоту по нижнему краю окна
virtual void ChangeHeightByBottomWindowSide(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CGraph::CGraph(void) : m_prev_x(0),
m_prev_y(0),
m_prev_width(0),
m_prev_height(0),
m_is_fullscreen_mode(true)
{
//--- Сохраним имя класса элемента в базовом классе
CElementBase::ClassName(CLASS_NAME);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CGraph::~CGraph(void)
{
}
//+------------------------------------------------------------------+
//| Обработчик событий |
//+------------------------------------------------------------------+
void CGraph::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
//--- Обработка события перемещения курсора
if(id==CHARTEVENT_MOUSE_MOVE)
{
return;
}
//--- Обработка события нажатия левой кнопки мыши на объекте
if(id==CHARTEVENT_OBJECT_CLICK)
{
if(OnClickGraph(sparam))
return;
//---
return;
}
}
//+------------------------------------------------------------------+
//| Создаёт график |
//+------------------------------------------------------------------+
bool CGraph::CreateGraph(const int x_gap,const int y_gap)
{
//--- Выйти, если нет указателя на главный элемент
if(!CElement::CheckMainPointer())
return(false);
//--- Инициализация свойств
InitializeProperties(x_gap,y_gap);
//--- Создание элемента
if(!CreateGraphic())
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Инициализация свойств |
//+------------------------------------------------------------------+
void CGraph::InitializeProperties(const int x_gap,const int y_gap)
{
m_x =CElement::CalculateX(x_gap);
m_y =CElement::CalculateY(y_gap);
//--- Рассчитаем размеры
m_x_size =(m_x_size<1 || m_auto_xresize_mode)? m_main.X2()-m_x-m_auto_xresize_right_offset : m_x_size;
m_y_size =(m_y_size<1 || m_auto_yresize_mode)? m_main.Y2()-m_y-m_auto_yresize_bottom_offset : m_y_size;
m_prev_width =m_x_size;
m_prev_height =m_y_size;
//--- Сохраним размеры
CElementBase::XSize(m_x_size);
CElementBase::YSize(m_y_size);
//--- Отступы от крайней точки
CElementBase::XGap(x_gap);
CElementBase::YGap(y_gap);
}
//+------------------------------------------------------------------+
//| Создаёт объект |
//+------------------------------------------------------------------+
bool CGraph::CreateGraphic(void)
{
//--- Корректировка размеров
m_x_size =(m_x_size<1)? 50 : m_x_size;
m_y_size =(m_y_size<1)? 20 : m_y_size;
//--- Формирование имени объекта
string name=CElementBase::ElementName("graph");
//--- Координаты
int x2=m_x+m_x_size;
int y2=m_y+m_y_size;
//--- Удалим объект, если он есть
if(::ObjectFind(m_chart_id,name)>=0)
{
::ObjectDelete(m_chart_id,name);
}
//--- Создание объекта
if(!m_graph.Create(m_chart_id,name,m_subwin,m_x,m_y,x2,y2))
return(false);
//--- Свойства
::ObjectSetString(m_chart_id,m_graph.ChartObjectName(),OBJPROP_TOOLTIP,"\n");
//--- У всех элементов, кроме формы, приоритет больше, чем у главного элемента
Z_Order(m_main.Z_Order()+1);
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_ZORDER,m_zorder);
return(true);
}
//+------------------------------------------------------------------+
//| Перемещение |
//+------------------------------------------------------------------+
void CGraph::Moving(const bool only_visible=true)
{
//--- Выйти, если элемент скрыт
if(only_visible)
if(!CElementBase::IsVisible())
return;
//--- Если привязка справа
if(m_anchor_right_window_side)
{
//--- Сохранение координат в полях элемента
CElementBase::X(m_main.X2()-XGap());
}
else
{
CElementBase::X(m_main.X()+XGap());
}
//--- Если привязка снизу
if(m_anchor_bottom_window_side)
{
CElementBase::Y(m_main.Y2()-YGap());
}
else
{
CElementBase::Y(m_main.Y()+YGap());
}
//--- Обновление координат графических объектов
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_XDISTANCE,X());
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_YDISTANCE,Y());
}
//+------------------------------------------------------------------+
//| Показывает пункт меню |
//+------------------------------------------------------------------+
void CGraph::Show(void)
{
//--- Выйти, если элемент уже видим
if(CElementBase::IsVisible())
return;
//--- Сделать видимыми все объекты
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);
//--- Состояние видимости
CElementBase::IsVisible(true);
//--- Обновить положение объектов
Moving();
}
//+------------------------------------------------------------------+
//| Скрывает пункт меню |
//+------------------------------------------------------------------+
void CGraph::Hide(void)
{
//--- Выйти, если элемент скрыт
if(!CElementBase::IsVisible())
return;
//--- Скрыть все объекты
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
//--- Состояние видимости
CElementBase::IsVisible(false);
}
//+------------------------------------------------------------------+
//| Перерисовка |
//+------------------------------------------------------------------+
void CGraph::Reset(void)
{
//--- Выйдем, если элемент выпадающий
if(CElementBase::IsDropdown())
return;
//--- Скрыть и показать
Hide();
Show();
}
//+------------------------------------------------------------------+
//| Удаление |
//+------------------------------------------------------------------+
void CGraph::Delete(void)
{
//--- Удалить объекты серий
int total=m_graph.CurvesTotal();
for(int i=total-1; i>=0; i--)
m_graph.CurveRemoveByIndex(i);
//--- Удалить объект графика
m_graph.Destroy();
//--- Инициализация переменных значениями по умолчанию
CElementBase::IsVisible(true);
}
//+------------------------------------------------------------------+
//| Обновление элемента |
//+------------------------------------------------------------------+
void CGraph::Update(const bool redraw=false)
{
//--- Применить
m_graph.Update();
}
//+------------------------------------------------------------------+
//| Установка приоритетов |
//+------------------------------------------------------------------+
void CGraph::SetZorders(void)
{
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_ZORDER,m_zorder);
}
//+------------------------------------------------------------------+
//| Сброс приоритетов |
//+------------------------------------------------------------------+
void CGraph::ResetZorders(void)
{
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_ZORDER,WRONG_VALUE);
}
//+------------------------------------------------------------------+
//| Изменение размеров |
//+------------------------------------------------------------------+
void CGraph::Resize(const int width,const int height)
{
m_x_size=width;
m_y_size=height;
//--- Удалить объект
::ObjectDelete(m_chart_id,m_graph.ChartObjectName());
//--- Создать график
CreateGraphic();
//--- Скрыть все объекты
if(!CElementBase::IsVisible())
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
}
//+------------------------------------------------------------------+
//| Управление полноэкранным режимом графика |
//+------------------------------------------------------------------+
void CGraph::FullScreenMode(const bool mode)
{
//--- Изменить размеры
int chart_width =m_chart.WidthInPixels();
int chart_height =m_chart.HeightInPixels(0);
//---
if(chart_width-1==m_x_size && chart_height-1==m_y_size)
{
Resize(m_prev_width,m_prev_height);
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_XDISTANCE,m_prev_x);
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_YDISTANCE,m_prev_y);
}
else
{
m_prev_x =m_x;
m_prev_y =m_y;
m_prev_width =m_x_size;
m_prev_height =m_y_size;
Resize(chart_width-1,chart_height-1);
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_XDISTANCE,1);
::ObjectSetInteger(m_chart_id,m_graph.ChartObjectName(),OBJPROP_YDISTANCE,1);
}
//---
m_graph.Redraw(true);
m_graph.Update();
m_chart.Redraw();
}
//+------------------------------------------------------------------+
//| Нажатие на график |
//+------------------------------------------------------------------+
bool CGraph::OnClickGraph(const string pressed_object)
{
//--- Выйдем, если (1) чужое имя объекта или (2) выключен полноэкранный режим
if(m_graph.ChartObjectName()!=pressed_object || !m_is_fullscreen_mode)
return(false);
//--- Изменить размеры
FullScreenMode();
return(true);
}
//+------------------------------------------------------------------+
//| Изменить ширину по правому краю формы |
//+------------------------------------------------------------------+
void CGraph::ChangeWidthByRightWindowSide(void)
{
//--- Выйти, если включен режим фиксации к правому краю формы
if(m_anchor_right_window_side)
return;
//--- Размеры
int x_size=0;
//--- Рассчитать размер
x_size=m_main.X2()-X()-m_auto_xresize_right_offset;
//--- Не изменять размер, если меньше установленного ограничения
if(x_size<200 || x_size==m_x_size)
return;
//---
m_prev_width=x_size;
//--- Установить новый размер
CElementBase::XSize(x_size);
Resize(x_size,m_graph.Height());
//--- Обновить данные на графике
m_graph.Redraw(true);
}
//+------------------------------------------------------------------+
//| Изменить высоту по нижнему краю окна |
//+------------------------------------------------------------------+
void CGraph::ChangeHeightByBottomWindowSide(void)
{
//--- Выйти, если включен режим фиксации к нижнему краю формы
if(m_anchor_bottom_window_side)
return;
//--- Размеры
int y_size=0;
//--- Рассчитать размер
y_size=m_main.Y2()-Y()-m_auto_yresize_bottom_offset;
//--- Не изменять размер, если меньше установленного ограничения
if(y_size<200 || y_size==m_y_size)
return;
//---
m_prev_height=y_size;
//--- Установить новый размер
CElementBase::YSize(y_size);
Resize(m_graph.Width(),y_size);
//--- Обновить данные на графике
m_graph.Redraw(true);
}
//+------------------------------------------------------------------+