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

707 lines
56 KiB
MQL5

//+------------------------------------------------------------------+
//| StandardChart.mqh |
//| Copyright 2015, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
#include "Pointer.mqh"
//+------------------------------------------------------------------+
//| Класс для создания стандартного графика |
//+------------------------------------------------------------------+
class CStandardChart : public CElement
{
private:
//--- Объекты для создания элемента
CSubChart m_sub_chart[];
CPointer m_x_scroll;
//--- Свойства графиков:
long m_sub_chart_id[];
string m_sub_chart_symbol[];
ENUM_TIMEFRAMES m_sub_chart_tf[];
//--- Режим горизонтальной прокрутки
bool m_x_scroll_mode;
//--- Переменные связанные с горизонтальной прокруткой графика
int m_prev_x;
int m_new_x_point;
int m_prev_new_x_point;
//--- Режим изменения высоты подокна
bool m_drag_border_window_mode;
//---
public:
CStandardChart(void);
~CStandardChart(void);
//--- Методы для создания стандартного графика
bool CreateStandardChart(const int x_gap,const int y_gap);
//---
private:
bool CreateSubCharts(void);
bool CreateXScrollPointer(void);
//---
public:
//--- (1) Возвращает указатель на указатель курсора мыши, (2) возвращает размер массива графиков
CPointer *GetMousePointer(void) { return(::GetPointer(m_x_scroll)); }
int SubChartsTotal(void) const { return(::ArraySize(m_sub_chart)); }
//--- Возвращает указатель на объект-график по указанному индексу
CSubChart *GetSubChartPointer(const uint index);
//--- Режим горизонтальной прокрутки
void XScrollMode(const bool mode) { m_x_scroll_mode=mode; }
//--- Добавляет график с указанными свойствами до создания
void AddSubChart(const string symbol,const ENUM_TIMEFRAMES tf);
//--- Переход к указанной дате
void SubChartNavigate(const datetime date);
//--- Сброс графиков
void ResetCharts(void);
//---
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 Delete(void);
//--- (1) Установка, (2) сброс приоритетов на нажатие левой кнопки мыши
virtual void SetZorders(void);
virtual void ResetZorders(void);
//---
private:
//--- Обработка нажатия на графике
bool OnClickSubChart(const string clicked_object);
//--- Проверка символа
bool CheckSymbol(const string symbol);
//--- Горизонтальная прокрутка
void HorizontalScroll(void);
//--- Обнуление переменных горизонтальной прокрутки
void ZeroHorizontalScrollVariables(void);
//--- Проверка режима изменения размеров подокна графика
bool CheckDragBorderWindowMode(void);
//--- Изменить ширину по правому краю окна
virtual void ChangeWidthByRightWindowSide(void);
//--- Изменить высоту по нижнему краю окна
virtual void ChangeHeightByBottomWindowSide(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CStandardChart::CStandardChart(void) : m_prev_x(0),
m_new_x_point(0),
m_prev_new_x_point(0),
m_x_scroll_mode(false),
m_drag_border_window_mode(false)
{
//--- Сохраним имя класса элемента в базовом классе
CElementBase::ClassName(CLASS_NAME);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CStandardChart::~CStandardChart(void)
{
}
//+------------------------------------------------------------------+
//| Обработка событий |
//+------------------------------------------------------------------+
void CStandardChart::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
//--- Обработка события перемещения курсора
if(id==CHARTEVENT_MOUSE_MOVE)
{
//--- Выйти, если в режиме изменения размера подокна
if(CheckDragBorderWindowMode())
return;
//--- Если есть фокус, проверим горизонтальную прокрутку графика
if(CElementBase::MouseFocus())
HorizontalScroll();
//--- Если фокуса нет и левая кнопка мыши отжата
else if(!m_mouse.LeftButtonState())
{
if(!m_x_scroll.IsVisible())
return;
//---
m_prev_x=0;
//--- Скрыть указатель горизонтальной прокрутки
m_x_scroll.Hide();
::ChartRedraw();
//--- Отправим сообщение на определение доступных элементов
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),1,"");
//--- Отправим сообщение об изменении в графическом интерфейсе
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
}
//---
return;
}
//--- Обработка события нажатия левой кнопки мыши на объекте
if(id==CHARTEVENT_OBJECT_CLICK)
{
if(OnClickSubChart(sparam))
return;
}
}
//+------------------------------------------------------------------+
//| Создаёт элемент "Стандартный график" |
//+------------------------------------------------------------------+
bool CStandardChart::CreateStandardChart(const int x_gap,const int y_gap)
{
//--- Выйти, если нет указателя на главный элемент
if(!CElement::CheckMainPointer())
return(false);
//--- Инициализация свойств
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;
//--- Отступы от крайней точки
CElementBase::XGap(x_gap);
CElementBase::YGap(y_gap);
//--- Приоритет, как у главного элемента, так как элемент не имеет своей области для нажатия
CElement::Z_Order(m_main.Z_Order());
//--- Создание графика
if(!CreateSubCharts())
return(false);
if(!CreateXScrollPointer())
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Создаёт графики |
//+------------------------------------------------------------------+
bool CStandardChart::CreateSubCharts(void)
{
//--- Получим количество графиков
int sub_charts_total=SubChartsTotal();
//--- Если нет ни одного графика в группе, сообщить об этом
if(sub_charts_total<1)
{
::Print(__FUNCTION__," > This method must be called when there is at least one graph in the group! "
"Use the method CStandardChart::AddSubChart()");
return(false);
}
//--- Рассчитаем координаты и размер
int x=m_x;
int x_size=(sub_charts_total>1)? m_x_size/sub_charts_total : m_x_size;
//--- Создадим указанное количество графиков
for(int i=0; i<sub_charts_total; i++)
{
//--- Формирование имени объекта
string name=CElementBase::ProgramName()+"_sub_chart_"+(string)i+"__"+(string)CElementBase::Id();
//--- Расчёт координаты X
x=(i>0)? x+x_size-1 : x;
//--- Корректировка ширины последнего графика
if(i+1>=sub_charts_total)
x_size=m_x_size-(x_size*(sub_charts_total-1)-(sub_charts_total-1));
//--- Установим кнопку
if(!m_sub_chart[i].Create(m_chart_id,name,m_subwin,x,m_y,x_size,m_y_size))
return(false);
//--- Скрыть
m_sub_chart[i].Timeframes(OBJ_NO_PERIODS);
//--- Получим и сохраним идентификатор созданного графика
m_sub_chart_id[i]=m_sub_chart[i].GetInteger(OBJPROP_CHART_ID);
//--- Установим свойства
m_sub_chart[i].Symbol(m_sub_chart_symbol[i]);
m_sub_chart[i].Period(m_sub_chart_tf[i]);
m_sub_chart[i].Z_Order(m_zorder+1);
m_sub_chart[i].Tooltip("\n");
//--- Режим фиксированного масштаба
//::ChartSetInteger(m_sub_chart_id[i],CHART_SCALEFIX,true);
//--- Максимум и минимум
//::ChartSetDouble(m_sub_chart_id[i],CHART_FIXED_MAX,2.0);
//::ChartSetDouble(m_sub_chart_id[i],CHART_FIXED_MIN,1.0);
//--- Сохраним размеры
m_sub_chart[i].XSize(x_size);
m_sub_chart[i].YSize(m_y_size);
//--- Отступы от крайней точки
m_sub_chart[i].XGap(CElement::CalculateXGap(x));
m_sub_chart[i].YGap(CElement::CalculateYGap(m_y));
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Создаёт указатель курсора горизонтальной прокрутки |
//+------------------------------------------------------------------+
bool CStandardChart::CreateXScrollPointer(void)
{
//--- Выйти, если горизонтальная прокрутка не нужна
if(!m_x_scroll_mode)
return(true);
//--- Установка свойств
m_x_scroll.XGap(0);
m_x_scroll.YGap(-20);
m_x_scroll.Id(CElementBase::Id());
m_x_scroll.Type(MP_X_SCROLL);
//--- Создание элемента
if(!m_x_scroll.CreatePointer(m_chart_id,m_subwin))
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Возвращает указатель на график по указанному индексу |
//+------------------------------------------------------------------+
CSubChart *CStandardChart::GetSubChartPointer(const uint index)
{
uint array_size=::ArraySize(m_sub_chart);
//--- Если нет ни одного графика, сообщить об этом
if(array_size<1)
{
::Print(__FUNCTION__," > This method must be called when there is at least one graph in the group!");
return(NULL);
}
//--- Корректировка в случае выхода из диапазона
uint i=(index>=array_size)? array_size-1 : index;
//--- Вернуть указатель
return(::GetPointer(m_sub_chart[i]));
}
//+------------------------------------------------------------------+
//| Добавляет график |
//+------------------------------------------------------------------+
void CStandardChart::AddSubChart(const string symbol,const ENUM_TIMEFRAMES tf)
{
//--- Проверим, есть ли такой символ на сервере
if(!CheckSymbol(symbol))
{
::Print(__FUNCTION__," > The symbol "+symbol+" is not on the server!");
return;
}
//---
int reserve=10;
//--- Увеличим размер массивов на один элемент
int array_size=::ArraySize(m_sub_chart);
int new_size=array_size+1;
::ArrayResize(m_sub_chart,new_size,reserve);
::ArrayResize(m_sub_chart_id,new_size,reserve);
::ArrayResize(m_sub_chart_symbol,new_size,reserve);
::ArrayResize(m_sub_chart_tf,new_size,reserve);
//--- Сохраним значения переданных параметров
m_sub_chart_symbol[array_size] =symbol;
m_sub_chart_tf[array_size] =tf;
}
//+------------------------------------------------------------------+
//| Переход к указанной дате |
//+------------------------------------------------------------------+
void CStandardChart::SubChartNavigate(const datetime date)
{
//--- (1) Текущая дата на графике и (2) только что выбранная в календаре
datetime current_date =::StringToTime(::TimeToString(::TimeCurrent(),TIME_DATE));
datetime selected_date =date;
//--- Отключим автопрокрутку и сдвиг от правого края
::ChartSetInteger(m_chart_id,CHART_AUTOSCROLL,false);
::ChartSetInteger(m_chart_id,CHART_SHIFT,false);
//--- Если выбранная в календаре дата больше, чем текущая
if(selected_date>=current_date)
{
//--- Перейти к текущей дате на всех графиках
::ChartNavigate(m_chart_id,CHART_END);
ResetCharts();
return;
}
//--- Получим количество баров от указанной даты
int bars_total =::Bars(::Symbol(),::Period(),selected_date,current_date);
int visible_bars =(int)::ChartGetInteger(m_chart_id,CHART_VISIBLE_BARS);
long seconds_today =::TimeCurrent()-current_date;
int bars_today =int(seconds_today/::PeriodSeconds())+2;
//--- Установим отступ от правого края всех графиков
m_prev_new_x_point=m_new_x_point=-((bars_total-visible_bars)+bars_today);
::ChartNavigate(m_chart_id,CHART_END,m_new_x_point);
//---
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
{
//--- Отключим автопрокрутку и сдвиг от правого края
::ChartSetInteger(m_sub_chart_id[i],CHART_AUTOSCROLL,false);
::ChartSetInteger(m_sub_chart_id[i],CHART_SHIFT,false);
//--- Получим количество баров от указанной даты
bars_total =::Bars(m_sub_chart[i].Symbol(),(ENUM_TIMEFRAMES)m_sub_chart[i].Period(),selected_date,current_date);
visible_bars =(int)::ChartGetInteger(m_sub_chart_id[i],CHART_VISIBLE_BARS);
bars_today =int(seconds_today/::PeriodSeconds((ENUM_TIMEFRAMES)m_sub_chart[i].Period()))+2;
//--- Отступ от правого края графика
m_prev_new_x_point=m_new_x_point=-((bars_total-visible_bars)+bars_today);
::ChartNavigate(m_sub_chart_id[i],CHART_END,m_new_x_point);
}
}
//+------------------------------------------------------------------+
//| Сброс графиков |
//+------------------------------------------------------------------+
void CStandardChart::ResetCharts(void)
{
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
::ChartNavigate(m_sub_chart_id[i],CHART_END);
//--- Обнулить вспомогательные переменные для горизонтальной прокрутки графиков
ZeroHorizontalScrollVariables();
}
//+------------------------------------------------------------------+
//| Перемещение элементов |
//+------------------------------------------------------------------+
void CStandardChart::Moving(const bool only_visible=true)
{
//--- Выйти, если элемент скрыт
if(only_visible)
if(!CElementBase::IsVisible())
return;
//--- Обновить положение
CElement::Moving();
//---
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
{
//--- Если привязка справа
if(m_anchor_right_window_side)
{
//--- Сохранение координат в полях элемента
CElementBase::X(m_main.X2()-XGap());
//--- Сохранение координат в полях объектов
m_sub_chart[i].X(m_main.X2()-m_sub_chart[i].XGap());
}
//--- Если привязка слева
else
{
CElementBase::X(m_main.X()+XGap());
m_sub_chart[i].X(m_main.X()+m_sub_chart[i].XGap());
}
//--- Если привязка снизу
if(m_anchor_bottom_window_side)
{
CElementBase::Y(m_main.Y2()-YGap());
m_sub_chart[i].Y(m_main.Y2()-m_sub_chart[i].YGap());
}
//--- Если привязка сверху
else
{
CElementBase::Y(m_main.Y()+YGap());
m_sub_chart[i].Y(m_main.Y()+m_sub_chart[i].YGap());
}
//--- Обновление координат графических объектов
m_sub_chart[i].X_Distance(m_sub_chart[i].X());
m_sub_chart[i].Y_Distance(m_sub_chart[i].Y());
}
//--- Обнулить вспомогательные переменные для горизонтальной прокрутки графиков
ZeroHorizontalScrollVariables();
}
//+------------------------------------------------------------------+
//| Показывает кнопку |
//+------------------------------------------------------------------+
void CStandardChart::Show(void)
{
//--- Выйти, если элемент уже видим
if(CElementBase::IsVisible())
return;
//--- Состояние видимости
CElementBase::IsVisible(true);
//--- Обновить положение объектов
Moving();
//--- Сделать видимыми все объекты
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
m_sub_chart[i].Timeframes(OBJ_ALL_PERIODS);
}
//+------------------------------------------------------------------+
//| Скрывает кнопку |
//+------------------------------------------------------------------+
void CStandardChart::Hide(void)
{
//--- Выйти, если элемент скрыт
if(!CElementBase::IsVisible())
return;
//--- Скрыть указатель горизонтальной прокрутки
m_x_scroll.Hide();
//--- Скрыть все объекты
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
m_sub_chart[i].Timeframes(OBJ_NO_PERIODS);
//--- Состояние видимости
CElementBase::IsVisible(false);
}
//+------------------------------------------------------------------+
//| Удаление |
//+------------------------------------------------------------------+
void CStandardChart::Delete(void)
{
m_x_scroll.Delete();
//--- Удаление объектов
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
m_sub_chart[i].Delete();
//--- Освобождение массивов элемента
::ArrayFree(m_sub_chart);
//--- Инициализация переменных значениями по умолчанию
CElementBase::MouseFocus(false);
CElementBase::IsVisible(true);
}
//+------------------------------------------------------------------+
//| Установка приоритетов |
//+------------------------------------------------------------------+
void CStandardChart::SetZorders(void)
{
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
m_sub_chart[i].Z_Order(m_zorder);
}
//+------------------------------------------------------------------+
//| Сброс приоритетов |
//+------------------------------------------------------------------+
void CStandardChart::ResetZorders(void)
{
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
m_sub_chart[i].Z_Order(WRONG_VALUE);
}
//+------------------------------------------------------------------+
//| Обработка нажатия на кнопку |
//+------------------------------------------------------------------+
bool CStandardChart::OnClickSubChart(const string clicked_object)
{
//--- Выйдем, если нажатие было не на пункте меню
if(::StringFind(clicked_object,CElementBase::ProgramName()+"_sub_chart_",0)<0)
return(false);
//--- Получим идентификатор и индекс из имени объекта
int id=CElementBase::IdFromObjectName(clicked_object);
//--- Выйти, если идентификатор не совпадает
if(id!=CElementBase::Id())
return(false);
//--- Получим индекс
int group_index=CElementBase::IndexFromObjectName(clicked_object);
//--- Отправить сигнал об этом
::EventChartCustom(m_chart_id,ON_CLICK_SUB_CHART,CElementBase::Id(),group_index,m_sub_chart_symbol[group_index]);
return(true);
}
//+------------------------------------------------------------------+
//| Проверка наличия символа |
//+------------------------------------------------------------------+
bool CStandardChart::CheckSymbol(const string symbol)
{
bool flag=false;
//--- Проверим символ в окне "Обзор рынка"
int symbols_total=::SymbolsTotal(true);
for(int i=0; i<symbols_total; i++)
{
//--- Если такой символ есть, остановим цикл
if(::SymbolName(i,true)==symbol)
{
flag=true;
break;
}
}
//--- Если символа нет в окне "Обзор рынка", то ...
if(!flag)
{
//--- ... попробуем найти его в общем списке
symbols_total=::SymbolsTotal(false);
for(int i=0; i<symbols_total; i++)
{
//--- Если такой символ есть, то...
if(::SymbolName(i,false)==symbol)
{
//--- ... поместим его в окно "Обзор рынка" и остановим цикл
::SymbolSelect(symbol,true);
flag=true;
break;
}
}
}
//--- Вернуть результат поиска
return(flag);
}
//+------------------------------------------------------------------+
//| Горизонтальная прокрутка графика |
//+------------------------------------------------------------------+
void CStandardChart::HorizontalScroll(void)
{
//--- Выйти, если отключена горизонтальная прокрутка графиков
if(!m_x_scroll_mode)
return;
//--- Если кнопка мыши нажата
if(m_mouse.LeftButtonState())
{
//--- Запомним текущие координаты X курсора
if(m_prev_x==0)
{
m_prev_x =m_mouse.X()+m_prev_new_x_point;
m_new_x_point =m_prev_new_x_point;
//--- Обновить координаты указателя и сделать его видимым
m_x_scroll.Moving(m_mouse.X(),m_mouse.Y());
m_x_scroll.Reset();
//--- Отправим сообщение на определение доступных элементов
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),0,"");
//--- Отправим сообщение об изменении в графическом интерфейсе
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
}
else
m_new_x_point=m_prev_x-m_mouse.X();
//--- Обновить координаты указателя
m_x_scroll.Moving(m_mouse.X(),m_mouse.Y());
}
else
{
if(m_prev_x==0)
return;
//---
m_prev_x=0;
//--- Скрыть указатель
m_x_scroll.Hide();
m_chart.Redraw();
//--- Отправим сообщение на определение доступных элементов
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),1,"");
//--- Отправим сообщение об изменении в графическом интерфейсе
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
return;
}
//--- Выйти, если положительное значение
if(m_new_x_point>0)
return;
//--- Запомнить текущее положение
m_prev_new_x_point=m_new_x_point;
//--- Применить ко всем графикам
int symbols_total=SubChartsTotal();
//--- Отключим автопрокрутку и сдвиг от правого края
for(int i=0; i<symbols_total; i++)
{
if(::ChartGetInteger(m_sub_chart_id[i],CHART_AUTOSCROLL))
::ChartSetInteger(m_sub_chart_id[i],CHART_AUTOSCROLL,false);
if(::ChartGetInteger(m_sub_chart_id[i],CHART_SHIFT))
::ChartSetInteger(m_sub_chart_id[i],CHART_SHIFT,false);
}
//--- Сброс последней ошибки
ResetLastError();
//--- Сместим графики
for(int i=0; i<symbols_total; i++)
if(!::ChartNavigate(m_sub_chart_id[i],CHART_END,m_new_x_point))
::Print(__FUNCTION__," > error: ",::GetLastError());
//--- Обновить график
::ChartRedraw();
}
//+------------------------------------------------------------------+
//| Обнуление переменных горизонтальной прокрутки |
//+------------------------------------------------------------------+
void CStandardChart::ZeroHorizontalScrollVariables(void)
{
m_prev_x =0;
m_new_x_point =0;
m_prev_new_x_point =0;
}
//+------------------------------------------------------------------+
//| Проверка режима изменения размеров подокна графика |
//+------------------------------------------------------------------+
bool CStandardChart::CheckDragBorderWindowMode(void)
{
//--- Получим высоту главного графика
int chart_y_size=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
//--- Если левая кнопка мыши нажата
if(m_mouse.LeftButtonState())
{
//--- Если режим отключен
if(!m_drag_border_window_mode)
{
//--- Запомним состояние, если курсор мыши в зоне захвата границы для изменения высоты подокна
if((m_mouse.SubWindowNumber()==m_subwin && m_mouse.Y()<2) ||
(m_mouse.SubWindowNumber()==m_subwin && m_mouse.Y()==chart_y_size+1) ||
(m_mouse.SubWindowNumber()==m_subwin-1 && m_mouse.Y()>=chart_y_size-2))
{
m_drag_border_window_mode=true;
return(false);
}
}
}
//--- Сбросим состояние отключенного режима
else
m_drag_border_window_mode=false;
//--- Вернём результат включенного режима
if(m_drag_border_window_mode)
return(true);
//---
return(false);
}
//+------------------------------------------------------------------+
//| Изменить ширину по правому краю формы |
//+------------------------------------------------------------------+
void CStandardChart::ChangeWidthByRightWindowSide(void)
{
//--- Координаты
int x=0;
//--- Размеры
int x_size=0;
//--- Рассчитать новый размер
x_size=m_main.X2()-m_sub_chart[0].X()-m_auto_xresize_right_offset;
//--- Не изменять размер, если меньше установленного ограничения
if(x_size<80)
return;
//--- Установить новый общий размер
CElementBase::XSize(x_size);
//--- Получим количество графиков в группе
int sub_charts_total=SubChartsTotal();
//--- Расчёт координат и размера
x=m_x;
x_size=(sub_charts_total>1)? x_size/sub_charts_total : x_size;
//--- Если более одного графика
if(sub_charts_total>1)
{
for(int i=0; i<sub_charts_total; i++)
{
//--- Расчёт координаты X
x=(i>0)? x+x_size-1 : x;
//--- Корректировка ширины последнего графика
if(i+1>=sub_charts_total)
x_size=m_x_size-(x_size*(sub_charts_total-1)-(sub_charts_total-1));
//---
m_sub_chart[i].X(x);
m_sub_chart[i].X_Distance(x);
//---
m_sub_chart[i].XSize(x_size);
m_sub_chart[i].X_Size(x_size);
//--- Отступы от крайней точки
m_sub_chart[i].XGap(CElement::CalculateXGap(x));
}
}
else
{
//--- Установить новый размер
CElementBase::XSize(x_size);
m_sub_chart[0].XSize(x_size);
m_sub_chart[0].X_Size(x_size);
}
//--- Обновить положение объектов
Moving();
}
//+------------------------------------------------------------------+
//| Изменить высоту по нижнему краю окна |
//+------------------------------------------------------------------+
void CStandardChart::ChangeHeightByBottomWindowSide(void)
{
//--- Координаты
int y=0;
//--- Размеры
int y_size=0;
//--- Рассчитать новый размер
y_size=m_main.Y2()-m_y-m_auto_yresize_bottom_offset;
//--- Не изменять размер, если меньше установленного ограничения
if(y_size<50)
return;
//--- Получим количество графиков в группе
int sub_charts_total=SubChartsTotal();
//--- Если более одного графика
if(sub_charts_total>1)
{
//--- Установить новый размер
CElementBase::YSize(y_size);
for(int i=0; i<sub_charts_total; i++)
{
m_sub_chart[i].YSize(y_size);
m_sub_chart[i].Y_Size(y_size);
}
}
else
{
//--- Установить новый размер
CElementBase::YSize(y_size);
m_sub_chart[0].YSize(y_size);
m_sub_chart[0].Y_Size(y_size);
}
//--- Обновить положение объектов
Moving();
}
//+------------------------------------------------------------------+