EasyAndFastMod/Controls/StandardChart.mqh

708 lines
56 KiB
MQL5
Raw Permalink Normal View History

2026-01-15 07:23:17 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| StandardChart.mqh |
//| Copyright 2015, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
#include "Pointer.mqh"
//+------------------------------------------------------------------+
//| ;0AA 4;O A>740=8O AB0=40@B=>3> 3@0D8:0 |
//+------------------------------------------------------------------+
class CStandardChart : public CElement
{
private:
//--- 1J5:BK 4;O A>740=8O M;5<5=B0
CSubChart m_sub_chart[];
CPointer m_x_scroll;
//--- !2>9AB20 3@0D8:>2:
long m_sub_chart_id[];
string m_sub_chart_symbol[];
ENUM_TIMEFRAMES m_sub_chart_tf[];
//--- 568< 3>@87>=B0;L=>9 ?@>:@CB:8
bool m_x_scroll_mode;
//--- 5@5<5==K5 A2O70==K5 A 3>@87>=B0;L=>9 ?@>:@CB:>9 3@0D8:0
int m_prev_x;
int m_new_x_point;
int m_prev_new_x_point;
//--- 568< 87<5=5=8O 2KA>BK ?>4>:=0
bool m_drag_border_window_mode;
//---
public:
CStandardChart(void);
~CStandardChart(void);
//--- 5B>4K 4;O A>740=8O AB0=40@B=>3> 3@0D8:0
bool CreateStandardChart(const int x_gap,const int y_gap);
//---
private:
bool CreateSubCharts(void);
bool CreateXScrollPointer(void);
//---
public:
//--- (1) >72@0I05B C:070B5;L =0 C:070B5;L :C@A>@0 <KH8, (2) 2>72@0I05B @07<5@ <0AA820 3@0D8:>2
CPointer *GetMousePointer(void) { return(::GetPointer(m_x_scroll)); }
int SubChartsTotal(void) const { return(::ArraySize(m_sub_chart)); }
//--- >72@0I05B C:070B5;L =0 >1J5:B-3@0D8: ?> C:070==><C 8=45:AC
CSubChart *GetSubChartPointer(const uint index);
//--- 568< 3>@87>=B0;L=>9 ?@>:@CB:8
void XScrollMode(const bool mode) { m_x_scroll_mode=mode; }
//--- >102;O5B 3@0D8: A C:070==K<8 A2>9AB20<8 4> A>740=8O
void AddSubChart(const string symbol,const ENUM_TIMEFRAMES tf);
//--- 5@5E>4 : C:070==>9 40B5
void SubChartNavigate(const datetime date);
//--- !1@>A 3@0D8:>2
void ResetCharts(void);
//---
public:
//--- 1@01>BG8: A>1KB8O 3@0D8:0
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
//--- 5@5<5I5=85 M;5<5=B0
virtual void Moving(const bool only_visible=true);
//--- #?@02;5=85
virtual void Show(void);
virtual void Hide(void);
virtual void Delete(void);
//--- (1) #AB0=>2:0, (2) A1@>A ?@8>@8B5B>2 =0 =060B85 ;52>9 :=>?:8 <KH8
virtual void SetZorders(void);
virtual void ResetZorders(void);
//---
private:
//--- 1@01>B:0 =060B8O =0 3@0D8:5
bool OnClickSubChart(const string clicked_object);
//--- @>25@:0 A8<2>;0
bool CheckSymbol(const string symbol);
//--- >@87>=B0;L=0O ?@>:@CB:0
void HorizontalScroll(void);
//--- 1=C;5=85 ?5@5<5==KE 3>@87>=B0;L=>9 ?@>:@CB:8
void ZeroHorizontalScrollVariables(void);
//--- @>25@:0 @568<0 87<5=5=8O @07<5@>2 ?>4>:=0 3@0D8:0
bool CheckDragBorderWindowMode(void);
//--- 7<5=8BL H8@8=C ?> ?@02><C :@0N >:=0
virtual void ChangeWidthByRightWindowSide(void);
//--- 7<5=8BL 2KA>BC ?> =86=5<C :@0N >:=0
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)
{
//--- !>E@0=8< 8<O :;0AA0 M;5<5=B0 2 107>2>< :;0AA5
CElementBase::ClassName(CLASS_NAME);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CStandardChart::~CStandardChart(void)
{
}
//+------------------------------------------------------------------+
//| 1@01>B:0 A>1KB89 |
//+------------------------------------------------------------------+
void CStandardChart::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
//--- 1@01>B:0 A>1KB8O ?5@5<5I5=8O :C@A>@0
if(id==CHARTEVENT_MOUSE_MOVE)
{
//--- K9B8, 5A;8 2 @568<5 87<5=5=8O @07<5@0 ?>4>:=0
if(CheckDragBorderWindowMode())
return;
//--- A;8 5ABL D>:CA, ?@>25@8< 3>@87>=B0;L=CN ?@>:@CB:C 3@0D8:0
if(CElementBase::MouseFocus())
HorizontalScroll();
//--- A;8 D>:CA0 =5B 8 ;520O :=>?:0 <KH8 >B60B0
else if(!m_mouse.LeftButtonState())
{
if(!m_x_scroll.IsVisible())
return;
//---
m_prev_x=0;
//--- !:@KBL C:070B5;L 3>@87>=B0;L=>9 ?@>:@CB:8
m_x_scroll.Hide();
::ChartRedraw();
//--- B?@028< A>>1I5=85 =0 >?@545;5=85 4>ABC?=KE M;5<5=B>2
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),1,"");
//--- B?@028< A>>1I5=85 >1 87<5=5=88 2 3@0D8G5A:>< 8=B5@D59A5
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
}
//---
return;
}
//--- 1@01>B:0 A>1KB8O =060B8O ;52>9 :=>?:8 <KH8 =0 >1J5:B5
if(id==CHARTEVENT_OBJECT_CLICK)
{
if(OnClickSubChart(sparam))
return;
}
}
//+------------------------------------------------------------------+
//| !>740QB M;5<5=B "!B0=40@B=K9 3@0D8:" |
//+------------------------------------------------------------------+
bool CStandardChart::CreateStandardChart(const int x_gap,const int y_gap)
{
//--- K9B8, 5A;8 =5B C:070B5;O =0 3;02=K9 M;5<5=B
if(!CElement::CheckMainPointer())
return(false);
//--- =8F80;870F8O A2>9AB2
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;
//--- BABC?K >B :@09=59 B>G:8
CElementBase::XGap(x_gap);
CElementBase::YGap(y_gap);
//--- @8>@8B5B, :0: C 3;02=>3> M;5<5=B0, B0: :0: M;5<5=B =5 8<55B A2>59 >1;0AB8 4;O =060B8O
CElement::Z_Order(m_main.Z_Order());
//--- !>740=85 3@0D8:0
if(!CreateSubCharts())
return(false);
if(!CreateXScrollPointer())
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| !>740QB 3@0D8:8 |
//+------------------------------------------------------------------+
bool CStandardChart::CreateSubCharts(void)
{
//--- >;CG8< :>;8G5AB2> 3@0D8:>2
int sub_charts_total=SubChartsTotal();
//--- A;8 =5B =8 >4=>3> 3@0D8:0 2 3@C??5, A>>1I8BL >1 MB><
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);
}
//--- 0AAG8B05< :>>@48=0BK 8 @07<5@
int x=m_x;
int x_size=(sub_charts_total>1)? m_x_size/sub_charts_total : m_x_size;
//--- !>74048< C:070==>5 :>;8G5AB2> 3@0D8:>2
for(int i=0; i<sub_charts_total; i++)
{
//--- $>@<8@>20=85 8<5=8 >1J5:B0
string name=CElementBase::ProgramName()+"_sub_chart_"+(string)i+"__"+(string)CElementBase::Id();
//--- 0AGQB :>>@48=0BK X
x=(i>0)? x+x_size-1 : x;
//--- >@@5:B8@>2:0 H8@8=K ?>A;54=53> 3@0D8:0
if(i+1>=sub_charts_total)
x_size=m_x_size-(x_size*(sub_charts_total-1)-(sub_charts_total-1));
//--- #AB0=>28< :=>?:C
if(!m_sub_chart[i].Create(m_chart_id,name,m_subwin,x,m_y,x_size,m_y_size))
return(false);
//--- !:@KBL
m_sub_chart[i].Timeframes(OBJ_NO_PERIODS);
//--- >;CG8< 8 A>E@0=8< 845=B8D8:0B>@ A>740==>3> 3@0D8:0
m_sub_chart_id[i]=m_sub_chart[i].GetInteger(OBJPROP_CHART_ID);
//--- #AB0=>28< A2>9AB20
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");
//--- 568< D8:A8@>20==>3> <0AHB010
//::ChartSetInteger(m_sub_chart_id[i],CHART_SCALEFIX,true);
//--- 0:A8<C< 8 <8=8<C<
//::ChartSetDouble(m_sub_chart_id[i],CHART_FIXED_MAX,2.0);
//::ChartSetDouble(m_sub_chart_id[i],CHART_FIXED_MIN,1.0);
//--- !>E@0=8< @07<5@K
m_sub_chart[i].XSize(x_size);
m_sub_chart[i].YSize(m_y_size);
//--- BABC?K >B :@09=59 B>G:8
m_sub_chart[i].XGap(CElement::CalculateXGap(x));
m_sub_chart[i].YGap(CElement::CalculateYGap(m_y));
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| !>740QB C:070B5;L :C@A>@0 3>@87>=B0;L=>9 ?@>:@CB:8 |
//+------------------------------------------------------------------+
bool CStandardChart::CreateXScrollPointer(void)
{
//--- K9B8, 5A;8 3>@87>=B0;L=0O ?@>:@CB:0 =5 =C6=0
if(!m_x_scroll_mode)
return(true);
//--- #AB0=>2:0 A2>9AB2
m_x_scroll.XGap(0);
m_x_scroll.YGap(-20);
m_x_scroll.Id(CElementBase::Id());
m_x_scroll.Type(MP_X_SCROLL);
//--- !>740=85 M;5<5=B0
if(!m_x_scroll.CreatePointer(m_chart_id,m_subwin))
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| >72@0I05B C:070B5;L =0 3@0D8: ?> C:070==><C 8=45:AC |
//+------------------------------------------------------------------+
CSubChart *CStandardChart::GetSubChartPointer(const uint index)
{
uint array_size=::ArraySize(m_sub_chart);
//--- A;8 =5B =8 >4=>3> 3@0D8:0, A>>1I8BL >1 MB><
if(array_size<1)
{
::Print(__FUNCTION__," > This method must be called when there is at least one graph in the group!");
return(NULL);
}
//--- >@@5:B8@>2:0 2 A;CG05 2KE>40 87 480?07>=0
uint i=(index>=array_size)? array_size-1 : index;
//--- 5@=CBL C:070B5;L
return(::GetPointer(m_sub_chart[i]));
}
//+------------------------------------------------------------------+
//| >102;O5B 3@0D8: |
//+------------------------------------------------------------------+
void CStandardChart::AddSubChart(const string symbol,const ENUM_TIMEFRAMES tf)
{
//--- @>25@8<, 5ABL ;8 B0:>9 A8<2>; =0 A5@25@5
if(!CheckSymbol(symbol))
{
::Print(__FUNCTION__," > The symbol "+symbol+" is not on the server!");
return;
}
//---
int reserve=10;
//--- #25;8G8< @07<5@ <0AA82>2 =0 >48= M;5<5=B
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);
//--- !>E@0=8< 7=0G5=8O ?5@540==KE ?0@0<5B@>2
m_sub_chart_symbol[array_size] =symbol;
m_sub_chart_tf[array_size] =tf;
}
//+------------------------------------------------------------------+
//| 5@5E>4 : C:070==>9 40B5 |
//+------------------------------------------------------------------+
void CStandardChart::SubChartNavigate(const datetime date)
{
//--- (1) "5:CI0O 40B0 =0 3@0D8:5 8 (2) B>;L:> GB> 2K1@0==0O 2 :0;5=40@5
datetime current_date =::StringToTime(::TimeToString(::TimeCurrent(),TIME_DATE));
datetime selected_date =date;
//--- B:;NG8< 02B>?@>:@CB:C 8 A4283 >B ?@02>3> :@0O
::ChartSetInteger(m_chart_id,CHART_AUTOSCROLL,false);
::ChartSetInteger(m_chart_id,CHART_SHIFT,false);
//--- A;8 2K1@0==0O 2 :0;5=40@5 40B0 1>;LH5, G5< B5:CI0O
if(selected_date>=current_date)
{
//--- 5@59B8 : B5:CI59 40B5 =0 2A5E 3@0D8:0E
::ChartNavigate(m_chart_id,CHART_END);
ResetCharts();
return;
}
//--- >;CG8< :>;8G5AB2> 10@>2 >B C:070==>9 40BK
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;
//--- #AB0=>28< >BABC? >B ?@02>3> :@0O 2A5E 3@0D8:>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++)
{
//--- B:;NG8< 02B>?@>:@CB:C 8 A4283 >B ?@02>3> :@0O
::ChartSetInteger(m_sub_chart_id[i],CHART_AUTOSCROLL,false);
::ChartSetInteger(m_sub_chart_id[i],CHART_SHIFT,false);
//--- >;CG8< :>;8G5AB2> 10@>2 >B C:070==>9 40BK
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;
//--- BABC? >B ?@02>3> :@0O 3@0D8:0
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);
}
}
//+------------------------------------------------------------------+
//| !1@>A 3@0D8:>2 |
//+------------------------------------------------------------------+
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);
//--- 1=C;8BL 2A?><>30B5;L=K5 ?5@5<5==K5 4;O 3>@87>=B0;L=>9 ?@>:@CB:8 3@0D8:>2
ZeroHorizontalScrollVariables();
}
//+------------------------------------------------------------------+
//| 5@5<5I5=85 M;5<5=B>2 |
//+------------------------------------------------------------------+
void CStandardChart::Moving(const bool only_visible=true)
{
//--- K9B8, 5A;8 M;5<5=B A:@KB
if(only_visible)
if(!CElementBase::IsVisible())
return;
//--- 1=>28BL ?>;>65=85
CElement::Moving();
//---
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
{
//--- A;8 ?@82O7:0 A?@020
if(m_anchor_right_window_side)
{
//--- !>E@0=5=85 :>>@48=0B 2 ?>;OE M;5<5=B0
CElementBase::X(m_main.X2()-XGap());
//--- !>E@0=5=85 :>>@48=0B 2 ?>;OE >1J5:B>2
m_sub_chart[i].X(m_main.X2()-m_sub_chart[i].XGap());
}
//--- A;8 ?@82O7:0 A;520
else
{
CElementBase::X(m_main.X()+XGap());
m_sub_chart[i].X(m_main.X()+m_sub_chart[i].XGap());
}
//--- A;8 ?@82O7:0 A=87C
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());
}
//--- A;8 ?@82O7:0 A25@EC
else
{
CElementBase::Y(m_main.Y()+YGap());
m_sub_chart[i].Y(m_main.Y()+m_sub_chart[i].YGap());
}
//--- 1=>2;5=85 :>>@48=0B 3@0D8G5A:8E >1J5:B>2
m_sub_chart[i].X_Distance(m_sub_chart[i].X());
m_sub_chart[i].Y_Distance(m_sub_chart[i].Y());
}
//--- 1=C;8BL 2A?><>30B5;L=K5 ?5@5<5==K5 4;O 3>@87>=B0;L=>9 ?@>:@CB:8 3@0D8:>2
ZeroHorizontalScrollVariables();
}
//+------------------------------------------------------------------+
//| >:07K205B :=>?:C |
//+------------------------------------------------------------------+
void CStandardChart::Show(void)
{
//--- K9B8, 5A;8 M;5<5=B C65 2848<
if(CElementBase::IsVisible())
return;
//--- !>AB>O=85 2848<>AB8
CElementBase::IsVisible(true);
//--- 1=>28BL ?>;>65=85 >1J5:B>2
Moving();
//--- !45;0BL 2848<K<8 2A5 >1J5:BK
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
m_sub_chart[i].Timeframes(OBJ_ALL_PERIODS);
}
//+------------------------------------------------------------------+
//| !:@K205B :=>?:C |
//+------------------------------------------------------------------+
void CStandardChart::Hide(void)
{
//--- K9B8, 5A;8 M;5<5=B A:@KB
if(!CElementBase::IsVisible())
return;
//--- !:@KBL C:070B5;L 3>@87>=B0;L=>9 ?@>:@CB:8
m_x_scroll.Hide();
//--- !:@KBL 2A5 >1J5:BK
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
m_sub_chart[i].Timeframes(OBJ_NO_PERIODS);
//--- !>AB>O=85 2848<>AB8
CElementBase::IsVisible(false);
}
//+------------------------------------------------------------------+
//| #40;5=85 |
//+------------------------------------------------------------------+
void CStandardChart::Delete(void)
{
m_x_scroll.Delete();
//--- #40;5=85 >1J5:B>2
int sub_charts_total=SubChartsTotal();
for(int i=0; i<sub_charts_total; i++)
m_sub_chart[i].Delete();
//--- A2>1>645=85 <0AA82>2 M;5<5=B0
::ArrayFree(m_sub_chart);
//--- =8F80;870F8O ?5@5<5==KE 7=0G5=8O<8 ?> C<>;G0=8N
CElementBase::MouseFocus(false);
CElementBase::IsVisible(true);
}
//+------------------------------------------------------------------+
//| #AB0=>2:0 ?@8>@8B5B>2 |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| !1@>A ?@8>@8B5B>2 |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| 1@01>B:0 =060B8O =0 :=>?:C |
//+------------------------------------------------------------------+
bool CStandardChart::OnClickSubChart(const string clicked_object)
{
//--- K945<, 5A;8 =060B85 1K;> =5 =0 ?C=:B5 <5=N
if(::StringFind(clicked_object,CElementBase::ProgramName()+"_sub_chart_",0)<0)
return(false);
//--- >;CG8< 845=B8D8:0B>@ 8 8=45:A 87 8<5=8 >1J5:B0
int id=CElementBase::IdFromObjectName(clicked_object);
//--- K9B8, 5A;8 845=B8D8:0B>@ =5 A>2?0405B
if(id!=CElementBase::Id())
return(false);
//--- >;CG8< 8=45:A
int group_index=CElementBase::IndexFromObjectName(clicked_object);
//--- B?@028BL A83=0; >1 MB><
::EventChartCustom(m_chart_id,ON_CLICK_SUB_CHART,CElementBase::Id(),group_index,m_sub_chart_symbol[group_index]);
return(true);
}
//+------------------------------------------------------------------+
//| @>25@:0 =0;8G8O A8<2>;0 |
//+------------------------------------------------------------------+
bool CStandardChart::CheckSymbol(const string symbol)
{
bool flag=false;
//--- @>25@8< A8<2>; 2 >:=5 "17>@ @K=:0"
int symbols_total=::SymbolsTotal(true);
for(int i=0; i<symbols_total; i++)
{
//--- A;8 B0:>9 A8<2>; 5ABL, >AB0=>28< F8:;
if(::SymbolName(i,true)==symbol)
{
flag=true;
break;
}
}
//--- A;8 A8<2>;0 =5B 2 >:=5 "17>@ @K=:0", B> ...
if(!flag)
{
//--- ... ?>?@>1C5< =09B8 53> 2 >1I5< A?8A:5
symbols_total=::SymbolsTotal(false);
for(int i=0; i<symbols_total; i++)
{
//--- A;8 B0:>9 A8<2>; 5ABL, B>...
if(::SymbolName(i,false)==symbol)
{
//--- ... ?><5AB8< 53> 2 >:=> "17>@ @K=:0" 8 >AB0=>28< F8:;
::SymbolSelect(symbol,true);
flag=true;
break;
}
}
}
//--- 5@=CBL @57C;LB0B ?>8A:0
return(flag);
}
//+------------------------------------------------------------------+
//| >@87>=B0;L=0O ?@>:@CB:0 3@0D8:0 |
//+------------------------------------------------------------------+
void CStandardChart::HorizontalScroll(void)
{
//--- K9B8, 5A;8 >B:;NG5=0 3>@87>=B0;L=0O ?@>:@CB:0 3@0D8:>2
if(!m_x_scroll_mode)
return;
//--- A;8 :=>?:0 <KH8 =060B0
if(m_mouse.LeftButtonState())
{
//--- 0?><=8< B5:CI85 :>>@48=0BK X :C@A>@0
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;
//--- 1=>28BL :>>@48=0BK C:070B5;O 8 A45;0BL 53> 2848<K<
m_x_scroll.Moving(m_mouse.X(),m_mouse.Y());
m_x_scroll.Reset();
//--- B?@028< A>>1I5=85 =0 >?@545;5=85 4>ABC?=KE M;5<5=B>2
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),0,"");
//--- B?@028< A>>1I5=85 >1 87<5=5=88 2 3@0D8G5A:>< 8=B5@D59A5
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
}
else
m_new_x_point=m_prev_x-m_mouse.X();
//--- 1=>28BL :>>@48=0BK C:070B5;O
m_x_scroll.Moving(m_mouse.X(),m_mouse.Y());
}
else
{
if(m_prev_x==0)
return;
//---
m_prev_x=0;
//--- !:@KBL C:070B5;L
m_x_scroll.Hide();
m_chart.Redraw();
//--- B?@028< A>>1I5=85 =0 >?@545;5=85 4>ABC?=KE M;5<5=B>2
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),1,"");
//--- B?@028< A>>1I5=85 >1 87<5=5=88 2 3@0D8G5A:>< 8=B5@D59A5
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
return;
}
//--- K9B8, 5A;8 ?>;>68B5;L=>5 7=0G5=85
if(m_new_x_point>0)
return;
//--- 0?><=8BL B5:CI55 ?>;>65=85
m_prev_new_x_point=m_new_x_point;
//--- @8<5=8BL :> 2A5< 3@0D8:0<
int symbols_total=SubChartsTotal();
//--- B:;NG8< 02B>?@>:@CB:C 8 A4283 >B ?@02>3> :@0O
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);
}
//--- !1@>A ?>A;54=59 >H81:8
ResetLastError();
//--- !<5AB8< 3@0D8:8
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());
//--- 1=>28BL 3@0D8:
::ChartRedraw();
}
//+------------------------------------------------------------------+
//| 1=C;5=85 ?5@5<5==KE 3>@87>=B0;L=>9 ?@>:@CB:8 |
//+------------------------------------------------------------------+
void CStandardChart::ZeroHorizontalScrollVariables(void)
{
m_prev_x =0;
m_new_x_point =0;
m_prev_new_x_point =0;
}
//+------------------------------------------------------------------+
//| @>25@:0 @568<0 87<5=5=8O @07<5@>2 ?>4>:=0 3@0D8:0 |
//+------------------------------------------------------------------+
bool CStandardChart::CheckDragBorderWindowMode(void)
{
//--- >;CG8< 2KA>BC 3;02=>3> 3@0D8:0
int chart_y_size=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
//--- A;8 ;520O :=>?:0 <KH8 =060B0
if(m_mouse.LeftButtonState())
{
//--- A;8 @568< >B:;NG5=
if(!m_drag_border_window_mode)
{
//--- 0?><=8< A>AB>O=85, 5A;8 :C@A>@ <KH8 2 7>=5 70E20B0 3@0=8FK 4;O 87<5=5=8O 2KA>BK ?>4>:=0
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);
}
}
}
//--- !1@>A8< A>AB>O=85 >B:;NG5==>3> @568<0
else
m_drag_border_window_mode=false;
//--- 5@=Q< @57C;LB0B 2:;NG5==>3> @568<0
if(m_drag_border_window_mode)
return(true);
//---
return(false);
}
//+------------------------------------------------------------------+
//| 7<5=8BL H8@8=C ?> ?@02><C :@0N D>@<K |
//+------------------------------------------------------------------+
void CStandardChart::ChangeWidthByRightWindowSide(void)
{
//--- >>@48=0BK
int x=0;
//--- 07<5@K
int x_size=0;
//--- 0AAG8B0BL =>2K9 @07<5@
x_size=m_main.X2()-m_sub_chart[0].X()-m_auto_xresize_right_offset;
//--- 5 87<5=OBL @07<5@, 5A;8 <5=LH5 CAB0=>2;5==>3> >3@0=8G5=8O
if(x_size<80)
return;
//--- #AB0=>28BL =>2K9 >1I89 @07<5@
CElementBase::XSize(x_size);
//--- >;CG8< :>;8G5AB2> 3@0D8:>2 2 3@C??5
int sub_charts_total=SubChartsTotal();
//--- 0AGQB :>>@48=0B 8 @07<5@0
x=m_x;
x_size=(sub_charts_total>1)? x_size/sub_charts_total : x_size;
//--- A;8 1>;55 >4=>3> 3@0D8:0
if(sub_charts_total>1)
{
for(int i=0; i<sub_charts_total; i++)
{
//--- 0AGQB :>>@48=0BK X
x=(i>0)? x+x_size-1 : x;
//--- >@@5:B8@>2:0 H8@8=K ?>A;54=53> 3@0D8:0
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);
//--- BABC?K >B :@09=59 B>G:8
m_sub_chart[i].XGap(CElement::CalculateXGap(x));
}
}
else
{
//--- #AB0=>28BL =>2K9 @07<5@
CElementBase::XSize(x_size);
m_sub_chart[0].XSize(x_size);
m_sub_chart[0].X_Size(x_size);
}
//--- 1=>28BL ?>;>65=85 >1J5:B>2
Moving();
}
//+------------------------------------------------------------------+
//| 7<5=8BL 2KA>BC ?> =86=5<C :@0N >:=0 |
//+------------------------------------------------------------------+
void CStandardChart::ChangeHeightByBottomWindowSide(void)
{
//--- >>@48=0BK
int y=0;
//--- 07<5@K
int y_size=0;
//--- 0AAG8B0BL =>2K9 @07<5@
y_size=m_main.Y2()-m_y-m_auto_yresize_bottom_offset;
//--- 5 87<5=OBL @07<5@, 5A;8 <5=LH5 CAB0=>2;5==>3> >3@0=8G5=8O
if(y_size<50)
return;
//--- >;CG8< :>;8G5AB2> 3@0D8:>2 2 3@C??5
int sub_charts_total=SubChartsTotal();
//--- A;8 1>;55 >4=>3> 3@0D8:0
if(sub_charts_total>1)
{
//--- #AB0=>28BL =>2K9 @07<5@
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
{
//--- #AB0=>28BL =>2K9 @07<5@
CElementBase::YSize(y_size);
m_sub_chart[0].YSize(y_size);
m_sub_chart[0].Y_Size(y_size);
}
//--- 1=>28BL ?>;>65=85 >1J5:B>2
Moving();
}
//+------------------------------------------------------------------+