EasyAndFastMod/Controls/MenuBar.mqh

418 lines
35 KiB
MQL5
Raw Permalink Normal View History

2026-01-15 07:23:17 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| MenuBar.mqh |
//| Copyright 2015, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
#include "MenuItem.mqh"
#include "ContextMenu.mqh"
//+------------------------------------------------------------------+
//| ;0AA 4;O A>740=8O 3;02=>3> <5=N |
//+------------------------------------------------------------------+
class CMenuBar : public CElement
{
private:
//--- 1J5:BK 4;O A>740=8O ?C=:B0 <5=N
CMenuItem m_items[];
//--- 0AA82 C:070B5;59 =0 :>=B5:AB=K5 <5=N
CContextMenu *m_contextmenus[];
//--- !>AB>O=85 3;02=>3> <5=N
bool m_menubar_state;
//--- =45:A ?@54K4CI53> 0:B828@>20==>3> ?C=:B0
int m_prev_active_item_index;
//---
public:
CMenuBar(void);
~CMenuBar(void);
//--- 5B>4K 4;O A>740=8O M;5<5=B0
bool CreateMenuBar(const int x_gap,const int y_gap);
//---
private:
void InitializeProperties(const int x_gap,const int y_gap);
bool CreateCanvas(void);
bool CreateItems(void);
//---
public:
//--- (1) >;CG5=85 C:070B5;O C:070==>3> ?C=:B0 <5=N, (2) ?>;CG5=85 C:070B5;O C:070==>3> :>=B5:AB=>3> <5=N
CMenuItem *GetItemPointer(const uint index);
CContextMenu *GetContextMenuPointer(const uint index);
//--- >;8G5AB2> (1) ?C=:B>2 8 (2) :>=B5:AB=KE <5=N, (3) A>AB>O=85 3;02=>3> <5=N
int ItemsTotal(void) const { return(::ArraySize(m_items)); }
int ContextMenusTotal(void) const { return(::ArraySize(m_contextmenus)); }
bool State(void) const { return(m_menubar_state); }
void State(const bool state);
//--- >102;O5B ?C=:B <5=N A C:070==K<8 A2>9AB20<8 4> A>740=8O 3;02=>3> <5=N
void AddItem(const int width,const string text);
//--- @8A>548=O5B ?5@540==>5 :>=B5:AB=>5 <5=N : C:070==><C ?C=:BC 3;02=>3> <5=N
void AddContextMenuPointer(const uint index,CContextMenu &object);
//---
public:
//--- 1@01>BG8: A>1KB89 3@0D8:0
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
//--- #40;5=85
virtual void Delete(void);
//--- 8AC5B M;5<5=B
virtual void Draw(void);
//---
private:
//--- 1@01>B:0 =060B8O =0 ?C=:B5 <5=N
bool OnClickMenuItem(const int id,const int index);
//--- >72@0I05B 0:B82=K9 ?C=:B 3;02=>3> <5=N
int ActiveItemIndex(void);
//--- 5@5:;NG05B :>=B5:AB=K5 <5=N 3;02=>3> <5=N, =02545=85< :C@A>@0
void SwitchContextMenuByFocus(void);
//--- 7<5=8BL H8@8=C ?> ?@02><C :@0N >:=0
virtual void ChangeWidthByRightWindowSide(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CMenuBar::CMenuBar(void) : m_menubar_state(false),
m_prev_active_item_index(WRONG_VALUE)
{
//--- !>E@0=8< 8<O :;0AA0 M;5<5=B0 2 107>2>< :;0AA5
CElementBase::ClassName(CLASS_NAME);
//--- &5=B@8@>20BL B5:AB 2 ?C=:B0E <5=N
CElement::IsCenterText(true);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CMenuBar::~CMenuBar(void)
{
}
//+------------------------------------------------------------------+
//| 1@01>BG8: A>1KB89 |
//+------------------------------------------------------------------+
void CMenuBar::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
//--- 1@01>B:0 A>1KB8O A<5=K D>:CA0 =0 :=>?:0E <5=N
if(id==CHARTEVENT_CUSTOM+ON_MOUSE_FOCUS)
{
//--- K9B8, 5A;8 (2) 3;02=>5 <5=N =5 0:B828@>20=> 8;8 (2) 845=B8D8:0B>@K =5 A>2?040NB
if(!m_menubar_state || lparam!=CElementBase::Id())
return;
//--- 5@5:;NG8BL :>=B5:AB=>5 <5=N ?> 0:B828@>20==><C ?C=:BC 3;02=>3> <5=N
SwitchContextMenuByFocus();
return;
}
//--- 1@01>B:0 A>1KB8O =060B8O ;52>9 :=>?:8 <KH8 =0 ?C=:B5 3;02=>3> <5=N
if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
{
if(OnClickMenuItem((uint)lparam,(uint)dparam))
return;
//---
return;
}
}
//+------------------------------------------------------------------+
//| !>740QB 3;02=>5 <5=N |
//+------------------------------------------------------------------+
bool CMenuBar::CreateMenuBar(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
InitializeProperties(x_gap,y_gap);
//--- !>740=85 M;5<5=B0
if(!CreateCanvas())
return(false);
if(!CreateItems())
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| =8F80;870F8O A2>9AB2 |
//+------------------------------------------------------------------+
void CMenuBar::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)? 22 : m_y_size;
//--- !2>9AB20 ?> C<>;G0=8N
m_back_color =(m_back_color!=clrNONE)? m_back_color : C'225,225,225';
m_back_color_hover =(m_back_color_hover!=clrNONE)? m_back_color_hover : C'51,153,255';
m_back_color_pressed =(m_back_color_pressed!=clrNONE)? m_back_color_pressed : m_back_color_hover;
m_border_color =(m_border_color!=clrNONE)? m_border_color : m_back_color;
m_border_color_hover =(m_border_color_hover!=clrNONE)? m_border_color_hover : m_back_color;
m_border_color_pressed =(m_border_color_pressed!=clrNONE)? m_border_color_pressed : m_back_color;
m_label_y_gap =(m_label_y_gap!=WRONG_VALUE)? m_label_y_gap : 3;
m_label_color =(m_label_color!=clrNONE)? m_label_color : clrBlack;
m_label_color_hover =(m_label_color_hover!=clrNONE)? m_label_color_hover : clrWhite;
m_label_color_pressed =(m_label_color_pressed!=clrNONE)? m_label_color_pressed : clrWhite;
//--- BABC?K >B :@09=59 B>G:8
CElementBase::XGap(x_gap);
CElementBase::YGap(y_gap);
}
//+------------------------------------------------------------------+
//| !>740QB >1J5:B 4;O @8A>20=8O |
//+------------------------------------------------------------------+
bool CMenuBar::CreateCanvas(void)
{
//--- $>@<8@>20=85 8<5=8 >1J5:B0
string name=CElementBase::ElementName("menubar");
//--- !>740=85 >1J5:B0
if(!CElement::CreateCanvas(name,m_x,m_y,m_x_size,m_y_size))
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| !>740QB A?8A>: ?C=:B>2 <5=N |
//+------------------------------------------------------------------+
bool CMenuBar::CreateItems(void)
{
//--- >>@48=0BK
int x=0,y=0;
//---
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
//--- 0AGQB :>>@48=0BK X
x=(i>0)? x+m_items[i-1].XSize() : x;
//--- !>E@0=8< C:070B5;L =0 3;02=K9 M;5<5=B
m_items[i].MainPointer(this);
//--- #AB0=>28< A2>9AB20 ?5@54 A>740=85<
m_items[i].Index(i);
m_items[i].NamePart("menu_item");
m_items[i].TwoState(true);
m_items[i].TypeMenuItem(MI_HAS_CONTEXT_MENU);
m_items[i].ShowRightArrow(false);
m_items[i].XSize(m_items[i].XSize());
m_items[i].YSize(m_y_size);
m_items[i].BackColor(m_back_color);
m_items[i].BackColorHover(m_back_color_hover);
m_items[i].BackColorPressed(m_back_color_pressed);
m_items[i].BorderColor(m_border_color);
m_items[i].BorderColorHover(m_border_color_hover);
m_items[i].BorderColorPressed(m_border_color_pressed);
m_items[i].IconXGap(3);
m_items[i].IconYGap(4);
m_items[i].LabelXGap(m_label_x_gap);
m_items[i].LabelYGap(m_label_y_gap);
m_items[i].LabelColor(m_label_color);
m_items[i].LabelColorHover(m_label_color_hover);
m_items[i].LabelColorPressed(m_label_color_pressed);
m_items[i].IsCenterText(CElement::IsCenterText());
//--- !>740=85 ?C=:B0 <5=N
if(!m_items[i].CreateMenuItem(m_items[i].LabelText(),x,y))
return(false);
//--- >1028BL M;5<5=B 2 <0AA82
CElement::AddToArray(m_items[i]);
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| #AB0=>2:0 A>AB>O=8O 3;02=>3> <5=N |
//+------------------------------------------------------------------+
void CMenuBar::State(const bool state)
{
if(state)
m_menubar_state=true;
else
{
m_menubar_state=false;
//--- @>9B8AL ?> 2A5< ?C=:B0< 3;02=>3> <5=N 4;O CAB0=>2:8 AB0BCA0 >B:;NG5==KE :>=B5:AB=KE <5=N
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
m_items[i].IsPressed(false);
m_items[i].Update(true);
}
}
}
//+------------------------------------------------------------------+
//| >72@0I05B C:070B5;L ?C=:B0 <5=N ?> 8=45:AC |
//+------------------------------------------------------------------+
CMenuItem *CMenuBar::GetItemPointer(const uint index)
{
uint array_size=::ArraySize(m_items);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 3;02=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
{
::Print(__FUNCTION__," > K7>2 MB>3> <5B>40 =C6=> >ACI5AB2;OBL, "
":>340 2 3;02=>< <5=N 5ABL E>BO 1K >48= ?C=:B!");
}
//--- >@@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_items[i]));
}
//+------------------------------------------------------------------+
//| >72@0I05B C:070B5;L :>=B5:AB=>3> <5=N ?> 8=45:AC |
//+------------------------------------------------------------------+
CContextMenu *CMenuBar::GetContextMenuPointer(const uint index)
{
uint array_size=::ArraySize(m_contextmenus);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 3;02=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
{
::Print(__FUNCTION__," > K7>2 MB>3> <5B>40 =C6=> >ACI5AB2;OBL, "
":>340 2 3;02=>< <5=N 5ABL E>BO 1K >48= ?C=:B!");
}
//--- >@@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_contextmenus[i]));
}
//+------------------------------------------------------------------+
//| >102;O5B ?C=:B <5=N |
//+------------------------------------------------------------------+
void CMenuBar::AddItem(const int width,const string text)
{
//--- #25;8G8< @07<5@ <0AA82>2 =0 >48= M;5<5=B
int array_size=::ArraySize(m_items);
::ArrayResize(m_items,array_size+1);
::ArrayResize(m_contextmenus,array_size+1);
//--- !>E@0=8< 7=0G5=8O ?5@540==KE ?0@0<5B@>2
m_items[array_size].XSize(width);
m_items[array_size].LabelText(text);
}
//+------------------------------------------------------------------+
//| >102;O5B C:070B5;L :>=B5:AB=>3> <5=N |
//+------------------------------------------------------------------+
void CMenuBar::AddContextMenuPointer(const uint index,CContextMenu &object)
{
//--- @>25@:0 =0 2KE>4 87 480?07>=0
uint size=::ArraySize(m_contextmenus);
if(size<1 || index>=size)
return;
//--- !>E@0=8BL C:070B5;L
m_contextmenus[index]=::GetPointer(object);
}
//+------------------------------------------------------------------+
//| #40;5=85 |
//+------------------------------------------------------------------+
void CMenuBar::Delete(void)
{
//--- #40;5=85 >1J5:B>2
CElement::Delete();
//--- A2>1>645=85 <0AA82>2 M;5<5=B0
::ArrayFree(m_items);
::ArrayFree(m_contextmenus);
}
//+------------------------------------------------------------------+
//| 060B85 =0 ?C=:B5 3;02=>3> <5=N |
//+------------------------------------------------------------------+
bool CMenuBar::OnClickMenuItem(const int id,const int index)
{
//--- K9B8, 5A;8 (1) 845=B8D8:0B>@K =5 A>2?040NB 8;8 (2) M;5<5=B 701;>:8@>20=
if(id!=CElementBase::Id() || CElementBase::IsLocked())
return(false);
//--- A;8 5ABL C:070B5;L =0 :>=B5:AB=>5 <5=N
if(::CheckPointer(m_contextmenus[index])!=POINTER_INVALID)
{
//--- !>AB>O=85 3;02=>3> <5=N 7028A8B >B 2848<>AB8 :>=B5:AB=>3> <5=N
m_menubar_state=(m_contextmenus[index].IsVisible())? false : true;
//--- ?@545;8< 2K45;5==K9 ?C=:B
m_prev_active_item_index=(m_menubar_state)? index : WRONG_VALUE;
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| >72@0I05B 8=45:A 0:B828@>20==>3> ?C=:B0 <5=N |
//+------------------------------------------------------------------+
int CMenuBar::ActiveItemIndex(void)
{
int active_item_index=WRONG_VALUE;
//---
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
//--- A;8 ?C=:B 2 D>:CA5
if(m_items[i].MouseFocus())
{
//--- 0?><=8< 8=45:A 8 >AB0=>28< F8:;
active_item_index=i;
break;
}
}
//---
return(active_item_index);
}
//+------------------------------------------------------------------+
//| 5@5:;NG05B :>=B5:AB=K5 <5=N 3;02=>3> <5=N, =02545=85< :C@A>@0 |
//+------------------------------------------------------------------+
void CMenuBar::SwitchContextMenuByFocus(void)
{
//--- >;CG8< 8=45:A 0:B828@>==>3> ?C=:B0 3;02=>3> <5=N
int active_item_index=ActiveItemIndex();
//--- K9B8, 5A;8 (1) <5=N =5 0:B828@>20=> 8;8 (2) MB> B>B 65 ?C=:B <5=N
if(active_item_index==WRONG_VALUE || active_item_index==m_prev_active_item_index)
return;
//--- 5@59B8 : A;54CNI5<C, 5A;8 2 MB>< ?C=:B5 =5B :>=B5:AB=>3> <5=N
if(::CheckPointer(m_contextmenus[active_item_index])!=POINTER_INVALID)
{
//--- !45;0BL :>=B5:AB=>5 <5=N 2848<K<
m_contextmenus[active_item_index].Show();
m_items[active_item_index].IsPressed(true);
}
//--- >;CG8< C:070B5;L =0 ?@54K4CI89 2K45;5==K9 ?C=:B
CContextMenu *cm=m_contextmenus[m_prev_active_item_index];
//--- !:@KBL :>=B5:AB=K5 <5=N, :>B>@K5 >B:@KBK 87 4@C38E :>=B5:AB=KE <5=N.
// @>94Q<AO 2 F8:;5 ?> ?C=:B0< B5:CI53> :>=B5:AB=>3> <5=N, GB>1K 2KOA=8BL, 5ABL ;8 B0:85.
int cm_items_total=cm.ItemsTotal();
for(int c=0; c<cm_items_total; c++)
{
CMenuItem *mi=cm.GetItemPointer(c);
//--- 5@59B8 : A;54CNI5<C, 5A;8 C:070B5;L =0 ?C=:B =5:>@@5:B=K9
if(::CheckPointer(mi)==POINTER_INVALID)
continue;
//--- 5@59B8 : A;54CNI5<C, 5A;8 MB>B ?C=:B =5 A>45@68B 2 A515 :>=B5:AB=>5 <5=N
if(mi.TypeMenuItem()!=MI_HAS_CONTEXT_MENU)
continue;
//--- A;8 :>=B5:AB=>5 <5=N 0:B828@>20=>
if(mi.IsPressed())
{
//--- B?@028BL A83=0; =0 70:@KB85 2A5E :>=B5:AB=KE <5=N, :>B>@K5 >B:@KBK 87 MB>3>
::EventChartCustom(m_chart_id,ON_HIDE_BACK_CONTEXTMENUS,CElementBase::Id(),0,"");
break;
}
}
//--- !:@KBL :>=B5:AB=>5 <5=N 3;02=>3> <5=N
m_contextmenus[m_prev_active_item_index].Hide();
m_items[m_prev_active_item_index].IsPressed(false);
m_items[m_prev_active_item_index].Update(true);
//--- 0?><=8< 8=45:A B5:CI53> 0:B828@>20==>3> <5=N
m_prev_active_item_index=active_item_index;
//--- 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.0,"");
}
//+------------------------------------------------------------------+
//| 7<5=8BL H8@8=C ?> ?@02><C :@0N D>@<K |
//+------------------------------------------------------------------+
void CMenuBar::ChangeWidthByRightWindowSide(void)
{
//--- K9B8, 5A;8 2:;NG5= @568< D8:A0F88 : ?@02><C :@0N D>@<K
if(m_anchor_right_window_side)
return;
//--- 07<5@K
int x_size=0;
//--- 0AAG8B0BL 8 CAB0=>28BL =>2K9 @07<5@ D>=C M;5<5=B0
x_size=m_main.X2()-m_canvas.X()-m_auto_xresize_right_offset;
CElementBase::XSize(x_size);
m_canvas.XSize(x_size);
m_canvas.Resize(x_size,m_y_size);
//--- 5@5@8A>20BL M;5<5=B
Draw();
//--- 1=>28BL ?>;>65=85 >1J5:B>2
Moving();
}
//+------------------------------------------------------------------+
//| 8AC5B M;5<5=B |
//+------------------------------------------------------------------+
void CMenuBar::Draw(void)
{
//--- 0@8A>20BL D>=
CElement::DrawBackground();
}
//+------------------------------------------------------------------+