707 lines
56 KiB
MQL5
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();
|
|
}
|
|
//+------------------------------------------------------------------+
|