EasyAndFastMod/Controls/ContextMenu.mqh

831 lines
73 KiB
MQL5
Raw Permalink Normal View History

2026-01-15 07:23:17 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| ContextMenu.mqh |
//| Copyright 2015, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
#include "MenuItem.mqh"
#include "SeparateLine.mqh"
//+------------------------------------------------------------------+
//| ;0AA 4;O A>740=8O :>=B5:AB=>3> <5=N |
//+------------------------------------------------------------------+
class CContextMenu : public CElement
{
private:
//--- 1J5:BK 4;O A>740=8O ?C=:B0 <5=N
CMenuItem m_items[];
CSeparateLine m_sep_line[];
//--- #:070B5;L =0 ?@54K4CI89 C75;
CMenuItem *m_prev_node;
//--- !2>9AB20 ?C=:B0 <5=N
int m_item_y_size;
//--- !2>9AB20 @0745;8B5;L=>9 ;8=88
color m_sepline_dark_color;
color m_sepline_light_color;
//--- 0AA82K A2>9AB2 ?C=:B>2 <5=N:
// (1) "5:AB, (2) O@;K: 4>ABC?=>3> ?C=:B0, (3) O@;K: 701;>:8@>20==>3> ?C=:B0
string m_text[];
string m_path_bmp_on[];
string m_path_bmp_off[];
//--- 0AA82 =><5@>2 8=45:A>2 ?C=:B>2 <5=N, ?>A;5 :>B>@KE =C6=> CAB0=>28BL @0745;8B5;L=CN ;8=8N
int m_sep_line_index[];
//--- !B>@>=0 D8:A0F88 :>=B5:AB=>3> <5=N
ENUM_FIX_CONTEXT_MENU m_fix_side;
//--- 568< A2>1>4=>3> :>=B5:AB=>3> <5=N. "> 5ABL, 157 ?@82O7:8 : ?@54K4CI5<C C7;C.
bool m_free_context_menu;
//---
public:
CContextMenu(void);
~CContextMenu(void);
//--- 5B>4K 4;O A>740=8O :>=B5:AB=>3> <5=N
bool CreateContextMenu(const int x_gap=0,const int y_gap=0);
//---
private:
void InitializeProperties(const int x_gap,const int y_gap);
bool CreateCanvas(void);
bool CreateItems(void);
bool CreateSeparateLine(const int item_index,const int line_index);
//---
public:
//--- >72@0I05B C:070B5;L ?C=:B0 87 :>=B5:AB=>3> <5=N
CMenuItem *GetItemPointer(const uint index);
CSeparateLine *GetSeparateLinePointer(const uint index);
//--- (1) !>E@0=5=85 8 (2) ?>;CG5=85 C:070B5;O ?@54K4CI53> C7;0, (3) CAB0=>2:0 @568<0 A2>1>4=>3> :>=B5:AB=>3> <5=N
void PrevNodePointer(CMenuItem &object);
CMenuItem *PrevNodePointer(void) const { return(m_prev_node); }
void FreeContextMenu(const bool flag) { m_free_context_menu=flag; }
//--- (1) >;8G5AB2> ?C=:B>2 <5=N, (2) 2KA>B0
int ItemsTotal(void) const { return(::ArraySize(m_items)); }
int SeparateLinesTotal(void) const { return(::ArraySize(m_sep_line)); }
void ItemYSize(const int y_size) { m_item_y_size=y_size; }
//--- (1) "Q<=K9 8 (2) A25B;K9 F25B @0745;8B5;L=>9 ;8=88
void SeparateLineDarkColor(const color clr) { m_sepline_dark_color=clr; }
void SeparateLineLightColor(const color clr) { m_sepline_light_color=clr; }
//--- #AB0=>2:0 @568<0 D8:A0F88 :>=B5:AB=>3> <5=N
void FixSide(const ENUM_FIX_CONTEXT_MENU side) { m_fix_side=side; }
//--- >102;O5B ?C=:B <5=N A C:070==K<8 A2>9AB20<8 4> A>740=8O :>=B5:AB=>3> <5=N
void AddItem(const string text,const string path_bmp_on,const string path_bmp_off,const ENUM_TYPE_MENU_ITEM type);
//--- >102;O5B @0745;8B5;L=CN ;8=8N ?>A;5 C:070==>3> ?C=:B0 4> A>740=8O :>=B5:AB=>3> <5=N
void AddSeparateLine(const int item_index);
//--- >72@0I05B >?8A0=85 (>B>1@0605<K9 B5:AB)
string DescriptionByIndex(const uint index);
//--- >72@0I05B B8? ?C=:B0 <5=N
ENUM_TYPE_MENU_ITEM TypeMenuItemByIndex(const uint index);
//--- (1) >;CG5=85 8 (2) CAB0=>2:0 A>AB>O=8O G5:1>:A0
bool CheckBoxStateByIndex(const uint index);
void CheckBoxStateByIndex(const uint index,const bool state);
//--- (1) >72@0I05B 8 (2) CAB0=02;8205B id @048>-?C=:B0 ?> 8=45:AC
int RadioItemIdByIndex(const uint index);
void RadioItemIdByIndex(const uint item_index,const int radio_id);
//--- (1) >72@0I05B 2K45;5==K9 @048>-?C=:B, (2) ?5@5:;NG05B @048>-?C=:B
int SelectedRadioItem(const int radio_id);
void SelectedRadioItem(const int radio_index,const int radio_id);
//---
public:
//--- 1@01>BG8: A>1KB89 3@0D8:0
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
//--- #?@02;5=85
virtual void Show(void);
virtual void Hide(void);
virtual void Delete(void);
//--- 8AC5B M;5<5=B
virtual void Draw(void);
//---
private:
//--- @>25@:0 CA;>289 =0 70:@KB85 2A5E :>=B5:AB=KE <5=N
void CheckHideContextMenus(void);
//--- @>25@:0 CA;>289 =0 70:@KB85 2A5E :>=B5:AB=KE <5=N, :>B>@K5 1K;8 >B:@KBK ?>A;5 MB>3>
void CheckHideBackContextMenus(void);
//--- 1@01>B:0 =060B8O =0 ?C=:B5, : :>B>@><C MB> :>=B5:AB=>5 <5=N ?@82O70=>
bool OnClickMenuItem(const string pressed_object,const int id,const int index);
//--- @8Q< A>>1I5=8O >B ?C=:B0 <5=N 4;O >1@01>B:8
void ReceiveMessageFromMenuItem(const int id,const int index_item,const string message_item);
//--- >;CG5=85 (1) 845=B8D8:0B>@0 8 (2) 8=45:A0 87 A>>1I5=8O @048>-?C=:B0
int RadioIdFromMessage(const string message);
int RadioIndexByItemIndex(const int index);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CContextMenu::CContextMenu(void) : m_free_context_menu(false),
m_fix_side(FIX_RIGHT),
m_item_y_size(24),
m_sepline_dark_color(C'160,160,160'),
m_sepline_light_color(clrWhite)
{
//--- !>E@0=8< 8<O :;0AA0 M;5<5=B0 2 107>2>< :;0AA5
CElementBase::ClassName(CLASS_NAME);
//--- >=B5:AB=>5 <5=N O2;O5BAO 2K?040NI8< M;5<5=B><
CElementBase::IsDropdown(true);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CContextMenu::~CContextMenu(void)
{
}
//+------------------------------------------------------------------+
//| 1@01>BG8: A>1KB89 |
//+------------------------------------------------------------------+
void CContextMenu::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
//--- 1@01>B:0 ?5@<5I5=8O :C@A>@0 <KH8
if(id==CHARTEVENT_MOUSE_MOVE)
{
//--- K9B8, 5A;8 MB> A2>1>4=>5 :>=B5:AB=>5 <5=N
if(m_free_context_menu)
return;
//--- A;8 :>=B5:AB=>5 <5=N 2:;NG5=> 8 ;520O :=>?:0 <KH8 =060B0
if(m_mouse.LeftButtonState())
{
//--- @>25@8< CA;>289 =0 70:@KB85 2A5E :>=B5:AB=KE <5=N
CheckHideContextMenus();
return;
}
//--- @>25@8< CA;>28O =0 70:@KB85 2A5E :>=B5:AB=KE <5=N, :>B>@K5 1K;8 >B:@KBK ?>A;5 MB>3>
CheckHideBackContextMenus();
return;
}
//--- 1@01>B:0 A>1KB8O =060B8O ;52>9 :=>?:8 <KH8 =0 >1J5:B5
if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
{
if(OnClickMenuItem(sparam,(int)lparam,(int)dparam))
return;
}
//--- 1@01>B:0 A>1KB8O =060B8O =0 ?C=:B5 <5=N
if(id==CHARTEVENT_CUSTOM+ON_CLICK_MENU_ITEM)
{
//--- K9B8, 5A;8 MB> A2>1>4=>5 :>=B5:AB=>5 <5=N
if(m_free_context_menu)
return;
//---
int item_id =int(lparam);
int item_index =int(dparam);
string item_message =sparam;
//--- @8Q< A>>1I5=8O >B ?C=:B0 <5=N 4;O >1@01>B:8
ReceiveMessageFromMenuItem(item_id,item_index,item_message);
return;
}
}
//+------------------------------------------------------------------+
//| !>740QB :>=B5:AB=>5 <5=N |
//+------------------------------------------------------------------+
bool CContextMenu::CreateContextMenu(const int x_gap=0,const int y_gap=0)
{
//--- K9B8, 5A;8 =5B C:070B5;O =0 3;02=K9 M;5<5=B
if(!CElement::CheckMainPointer())
return(false);
//--- A;8 MB> ?@82O70==>5 :>=B5:AB=>5 <5=N
if(!m_free_context_menu)
{
//--- K9B8, 5A;8 =5B C:070B5;O =0 ?@54K4CI89 C75;
if(::CheckPointer(m_prev_node)==POINTER_INVALID)
{
::Print(__FUNCTION__," > 5@54 A>740=85< :>=B5:AB=>3> <5=N 5<C =C6=> ?5@540BL "
"C:070B5;L =0 ?@54K4CI89 C75; A ?><>ILN <5B>40 CContextMenu::PrevNodePointer(CMenuItem &object).");
return(false);
}
}
//--- =8F80;870F8O A2>9AB2
InitializeProperties(x_gap,y_gap);
//--- !>740=85 :>=B5:AB=>3> <5=N
if(!CreateCanvas())
return(false);
if(!CreateItems())
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| =8F80;870F8O A2>9AB2 |
//+------------------------------------------------------------------+
void CContextMenu::InitializeProperties(const int x_gap,const int y_gap)
{
//--- 0AGQB 2KA>BK :>=B5:AB=>3> <5=N 7028A8B >B :>;8G5AB20 ?C=:B>2 <5=N 8 @0745;8B5;L=KE ;8=89
int items_total =ItemsTotal();
int sep_y_size =::ArraySize(m_sep_line)*9;
m_y_size =(m_item_y_size*items_total+2)+sep_y_size;
//--- A;8 :>>@48=0BK =5 C:070=K
if(!m_free_context_menu && (x_gap==0 || y_gap==0))
{
if(m_fix_side==FIX_RIGHT)
{
m_x =(m_anchor_right_window_side)? m_prev_node.X()-m_prev_node.XSize()+3 : m_prev_node.X2()-3;
m_y =(m_anchor_bottom_window_side)? m_prev_node.Y()+1 : m_prev_node.Y()-1;
}
else
{
m_x =(m_anchor_right_window_side)? m_prev_node.X()-1 : m_prev_node.X()+1;
m_y =(m_anchor_bottom_window_side)? m_prev_node.Y()-m_prev_node.YSize()+1 : m_prev_node.Y2()-1;
}
}
//--- A;8 :>>@48=0BK C:070=K
else
{
m_x =CElement::CalculateX(x_gap);
m_y =CElement::CalculateY(y_gap);
}
//--- &25B D>=0 ?> C<>;G0=8N
m_back_color =(m_back_color!=clrNONE)? m_back_color : C'240,240,240';
m_back_color_hover =(m_back_color_hover!=clrNONE)? m_back_color_hover : C'51,153,255';
m_back_color_locked =(m_back_color_locked!=clrNONE)? m_back_color_locked : clrLightGray;
m_back_color_pressed =(m_back_color_pressed!=clrNONE)? m_back_color_pressed : C'51,153,255';
m_border_color =(m_border_color!=clrNONE)? m_border_color : C'150,170,180';
//--- BABC?K 8 F25B B5:AB>2>9 <5B:8
m_icon_x_gap =(m_icon_x_gap!=WRONG_VALUE)? m_icon_x_gap : 3;
m_icon_y_gap =(m_icon_y_gap!=WRONG_VALUE)? m_icon_y_gap : 3;
m_label_x_gap =(m_label_x_gap!=WRONG_VALUE)? m_label_x_gap : 24;
m_label_y_gap =(m_label_y_gap!=WRONG_VALUE)? m_label_y_gap : 5;
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;
//--- BABC?K >B :@09=59 B>G:8
CElementBase::XGap(CElement::CalculateXGap(m_x));
CElementBase::YGap(CElement::CalculateYGap(m_y));
}
//+------------------------------------------------------------------+
//| !>740QB >1J5:B 4;O @8A>20=8O |
//+------------------------------------------------------------------+
bool CContextMenu::CreateCanvas(void)
{
//--- $>@<8@>20=85 8<5=8 >1J5:B0
string name=CElementBase::ElementName("context_menu");
//--- !>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 CContextMenu::CreateItems(void)
{
//--- ;O >?@545;5=8O ?>;>65=8O @0745;8B5;L=KE ;8=89
int s=0;
//--- >>@48=0BK
int x=1,y=0;
//--- >;8G5AB2> @0745;8B5;L=KE ;8=89
int sep_lines_total=::ArraySize(m_sep_line_index);
//---
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
//--- 0AGQB :>>@48=0BK Y
y=(i>0) ? y+m_item_y_size : 1;
//--- !>E@0=8< C:070B5;L D>@<K
m_items[i].MainPointer(this);
//--- A;8 :>=B5:AB=>5 <5=N A ?@82O7:>9, B> 4>1028< C:070B5;L =0 ?@54K4CI89 C75;
if(!m_free_context_menu)
m_items[i].GetPrevNodePointer(m_prev_node);
//--- #AB0=>28< A2>9AB20
m_items[i].Index(i);
m_items[i].TwoState(m_items[i].TypeMenuItem()==MI_HAS_CONTEXT_MENU? true : false);
m_items[i].XSize(m_x_size-2);
m_items[i].YSize(m_item_y_size);
m_items[i].IconXGap(m_icon_x_gap);
m_items[i].IconYGap(m_icon_y_gap);
m_items[i].IconFile(m_path_bmp_on[i]);
m_items[i].IconFileLocked(m_path_bmp_off[i]);
m_items[i].IconFilePressed(m_path_bmp_on[i]);
m_items[i].IconFilePressedLocked(m_path_bmp_off[i]);
m_items[i].BackColor(m_back_color);
m_items[i].BackColorHover(m_back_color_hover);
m_items[i].BackColorPressed(m_back_color_hover);
m_items[i].BorderColor(m_back_color);
m_items[i].BorderColorHover(m_back_color);
m_items[i].BorderColorLocked(m_back_color);
m_items[i].BorderColorPressed(m_back_color);
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_hover);
m_items[i].IsDropdown(m_is_dropdown);
m_items[i].AnchorRightWindowSide(m_anchor_right_window_side);
m_items[i].AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- !>740=85 ?C=:B0 <5=N
if(!m_items[i].CreateMenuItem(m_text[i],x,y))
return(false);
//--- >1028BL M;5<5=B 2 <0AA82
CElement::AddToArray(m_items[i]);
//--- 1=C;8BL D>:CA
CElementBase::MouseFocus(false);
//--- 5@59B8 : A;54CNI5<C, 5A;8 2A5 @0745;8B5;L=K5 ;8=88 CAB0=>2;5=K
if(s>=sep_lines_total)
continue;
//--- A;8 8=45:AK A>2?0;8, 7=0G8B ?>A;5 MB>3> ?C=:B0 =C6=> CAB0=>28BL @0745;8B5;L=CN ;8=8N
if(i==m_sep_line_index[s])
{
if(!CreateSeparateLine(i,s))
return(false);
//--- >@@5:B8@>2:0 :>>@48=0BK Y 4;O A;54CNI53> ?C=:B0
y=y+9;
//--- #25;8G5=85 AGQBG8:0 @0745;8B5;L=KE ;8=89
s++;
}
}
return(true);
}
//+------------------------------------------------------------------+
//| !>740QB @0745;8B5;L=CN ;8=8N |
//+------------------------------------------------------------------+
bool CContextMenu::CreateSeparateLine(const int item_index,const int line_index)
{
int x=CElement::CalculateXGap(m_items[item_index].X()+5);
int y=CElement::CalculateYGap(m_items[item_index].Y2()+2);
//--- !>E@0=8< C:070B5;L D>@<K
m_sep_line[line_index].MainPointer(m_main);
//--- #AB0=>28< A2>9AB20
m_sep_line[line_index].Index(line_index);
m_sep_line[line_index].IsDropdown(m_is_dropdown);
m_sep_line[line_index].TypeSepLine(H_SEP_LINE);
m_sep_line[line_index].DarkColor(m_sepline_dark_color);
m_sep_line[line_index].LightColor(m_sepline_light_color);
m_sep_line[line_index].AnchorRightWindowSide(m_anchor_right_window_side);
m_sep_line[line_index].AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- !>740=85 @0745;8B5;L=>9 ;8=88
if(!m_sep_line[line_index].CreateSeparateLine(x,y,m_x_size-10,2))
return(false);
//--- >1028BL M;5<5=B 2 <0AA82
CElement::AddToArray(m_sep_line[line_index]);
return(true);
}
//+------------------------------------------------------------------+
//| >72@0I05B C:070B5;L ?C=:B0 <5=N ?> 8=45:AC |
//+------------------------------------------------------------------+
CMenuItem *CContextMenu::GetItemPointer(const uint index)
{
uint array_size=::ArraySize(m_items);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 :>=B5:AB=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
::Print(__FUNCTION__," > K7>2 MB>3> <5B>40 =C6=> >ACI5AB2;OBL, :>340 2 :>=B5:AB=>< <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 @0745;8B5;L=CN ;8=8N ?> 8=45:AC |
//+------------------------------------------------------------------+
CSeparateLine *CContextMenu::GetSeparateLinePointer(const uint index)
{
uint array_size=::ArraySize(m_sep_line);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 :>=B5:AB=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
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_sep_line[i]));
}
//+------------------------------------------------------------------+
//| 1<5= C:070B5;O<8 ?C=:B0 <5=N 8 :>=B5:AB=>3> <5=N |
//+------------------------------------------------------------------+
void CContextMenu::PrevNodePointer(CMenuItem &object)
{
//--- !>E@0=8BL C:070B5;L =0 ?C=:B <5=N, : :>B>@><C ?@82O70=> MB> :>=B5:AB=>5 <5=N
m_prev_node=::GetPointer(object);
//--- !>E@0=8BL C:070B5;L =0 MB> :>=B5:AB=>5 <5=N
m_prev_node.GetContextMenuPointer(this);
}
//+------------------------------------------------------------------+
//| >102;O5B ?C=:B <5=N |
//+------------------------------------------------------------------+
void CContextMenu::AddItem(const string text,const string path_bmp_on,const string path_bmp_off,const ENUM_TYPE_MENU_ITEM type)
{
//--- #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_text,array_size+1);
::ArrayResize(m_path_bmp_on,array_size+1);
::ArrayResize(m_path_bmp_off,array_size+1);
//--- !>E@0=8< 7=0G5=8O ?5@540==KE ?0@0<5B@>2
m_text[array_size]=text;
m_path_bmp_on[array_size] =path_bmp_on;
m_path_bmp_off[array_size] =path_bmp_off;
//--- #AB0=>2:0 B8?0 ?C=:B0 <5=N
m_items[array_size].TypeMenuItem(type);
}
//+------------------------------------------------------------------+
//| >102;O5B @0745;8B5;L=CN ;8=8N |
//+------------------------------------------------------------------+
void CContextMenu::AddSeparateLine(const int item_index)
{
//--- #25;8G8< @07<5@ <0AA82>2 =0 >48= M;5<5=B
int array_size=::ArraySize(m_sep_line);
::ArrayResize(m_sep_line,array_size+1);
::ArrayResize(m_sep_line_index,array_size+1);
//--- !>E@0=8< =><5@ 8=45:A0
m_sep_line_index[array_size]=item_index;
}
//+------------------------------------------------------------------+
//| >72@0I05B =0720=85 ?C=:B0 ?> 8=45:AC |
//+------------------------------------------------------------------+
string CContextMenu::DescriptionByIndex(const uint index)
{
uint array_size=::ArraySize(m_items);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 :>=B5:AB=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
::Print(__FUNCTION__," > K7>2 MB>3> <5B>40 =C6=> >ACI5AB2;OBL, :>340 2 :>=B5:AB=>< <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 >?8A0=85 ?C=:B0
return(m_items[i].LabelText());
}
//+------------------------------------------------------------------+
//| >72@0I05B B8? ?C=:B0 ?> 8=45:AC |
//+------------------------------------------------------------------+
ENUM_TYPE_MENU_ITEM CContextMenu::TypeMenuItemByIndex(const uint index)
{
uint array_size=::ArraySize(m_items);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 :>=B5:AB=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
::Print(__FUNCTION__," > K7>2 MB>3> <5B>40 =C6=> >ACI5AB2;OBL, :>340 2 :>=B5:AB=>< <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 B8? ?C=:B0
return(m_items[i].TypeMenuItem());
}
//+------------------------------------------------------------------+
//| >72@0I05B A>AB>O=85 G5:1>:A0 ?> 8=45:AC |
//+------------------------------------------------------------------+
bool CContextMenu::CheckBoxStateByIndex(const uint index)
{
uint array_size=::ArraySize(m_items);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 :>=B5:AB=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
::Print(__FUNCTION__," > K7>2 MB>3> <5B>40 =C6=> >ACI5AB2;OBL, :>340 2 :>=B5:AB=>< <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 A>AB>O=85 ?C=:B0
return(m_items[i].CheckBoxState());
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B A>AB>O=85 G5:1>:A0 ?> 8=45:AC |
//+------------------------------------------------------------------+
void CContextMenu::CheckBoxStateByIndex(const uint index,const bool state)
{
//--- @>25@:0 =0 2KE>4 87 480?07>=0
uint array_size=::ArraySize(m_items);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 :>=B5:AB=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
return;
//--- >@@5:B8@>2:0 2 A;CG05 2KE>40 87 480?07>=0
uint i=(index>=array_size)? array_size-1 : index;
//--- #AB0=>28BL A>AB>O=85
m_items[i].CheckBoxState(state);
}
//+------------------------------------------------------------------+
//| >72@0I05B id @048>-?C=:B0 ?> 8=45:AC |
//+------------------------------------------------------------------+
int CContextMenu::RadioItemIdByIndex(const uint index)
{
uint array_size=::ArraySize(m_items);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 :>=B5:AB=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
::Print(__FUNCTION__," > K7>2 MB>3> <5B>40 =C6=> >ACI5AB2;OBL, :>340 2 :>=B5:AB=>< <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 845=B8D8:0B>@
return(m_items[i].RadioButtonID());
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B id 4;O @048>-?C=:B0 ?> 8=45:AC |
//+------------------------------------------------------------------+
void CContextMenu::RadioItemIdByIndex(const uint index,const int id)
{
//--- @>25@:0 =0 2KE>4 87 480?07>=0
uint array_size=::ArraySize(m_items);
//--- A;8 =5B =8 >4=>3> ?C=:B0 2 :>=B5:AB=>< <5=N, A>>1I8BL >1 MB><
if(array_size<1)
return;
//--- >@@5:B8@>2:0 2 A;CG05 2KE>40 87 480?07>=0
uint i=(index>=array_size)? array_size-1 : index;
//--- #AB0=>28BL 845=B8D8:0B>@
m_items[i].RadioButtonID(id);
}
//+------------------------------------------------------------------+
//| >72@0I05B 8=45:A @048>-?C=:B0 ?> id |
//+------------------------------------------------------------------+
int CContextMenu::SelectedRadioItem(const int radio_id)
{
//--- !GQBG8: @048>-?C=:B>2
int count_radio_id=0;
//--- @>94Q<AO 2 F8:;5 ?> A?8A:C ?C=:B>2 :>=B5:AB=>3> <5=N
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
//--- 5@59B8 : A;54CNI5<C, 5A;8 =5 @048>-?C=:B
if(m_items[i].TypeMenuItem()!=MI_RADIOBUTTON)
continue;
//--- A;8 845=B8D8:0B>@K A>2?040NB
if(m_items[i].RadioButtonID()==radio_id)
{
//--- A;8 MB> 0:B82=K9 @048>-?C=:B, 2KE>48< 87 F8:;0
if(m_items[i].RadioButtonState())
break;
//--- #25;8G8BL AGQBG8: @048>-?C=:B>2
count_radio_id++;
}
}
//--- 5@=CBL 8=45:A
return(count_radio_id);
}
//+------------------------------------------------------------------+
//| 5@5:;NG05B @048>-?C=:B ?> 8=45:AC 8 id |
//+------------------------------------------------------------------+
void CContextMenu::SelectedRadioItem(const int radio_index,const int radio_id)
{
//--- !GQBG8: @048>-?C=:B>2
int count_radio_id=0;
//--- @>94Q<AO 2 F8:;5 ?> A?8A:C ?C=:B>2 :>=B5:AB=>3> <5=N
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
//--- 5@59B8 : A;54CNI5<C, 5A;8 =5 @048>-?C=:B
if(m_items[i].TypeMenuItem()!=MI_RADIOBUTTON)
continue;
//--- A;8 845=B8D8:0B>@K A>2?040NB
if(m_items[i].RadioButtonID()==radio_id)
{
//--- 5@5:;NG8BL @048>-?C=:B
if(count_radio_id==radio_index)
m_items[i].RadioButtonState(true);
else
m_items[i].RadioButtonState(false);
//--- #25;8G8BL AGQBG8: @048>-?C=:B>2
count_radio_id++;
}
}
}
//+------------------------------------------------------------------+
//| >:07K205B :>=B5:AB=>5 <5=N |
//+------------------------------------------------------------------+
void CContextMenu::Show(void)
{
//--- K9B8, 5A;8 M;5<5=B C65 2848<
if(CElementBase::IsVisible())
return;
//--- @8A2>8BL AB0BCA 2848<>3> M;5<5=B0
CElementBase::IsVisible(true);
//--- 1=>28BL ?>;>65=85 >1J5:B>2
Moving();
//--- >:070BL >1J5:B
::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);
//--- >:070BL ?C=:BK <5=N
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
m_items[i].Show();
//--- >:070BL @0745;8B5;L=K5 ;8=88
int sep_total=::ArraySize(m_sep_line);
for(int i=0; i<sep_total; i++)
m_sep_line[i].Show();
//--- B<5B8BL A>AB>O=85 2 ?@54K4CI5< C7;5
if(!m_free_context_menu)
m_prev_node.IsPressed(true);
}
//+------------------------------------------------------------------+
//| !:@K205B :>=B5:AB=>5 <5=N |
//+------------------------------------------------------------------+
void CContextMenu::Hide(void)
{
//--- K9B8, 5A;8 M;5<5=B A:@KB
if(!CElementBase::IsVisible())
return;
//--- !:@KBL >1J5:B
::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
//--- !:@KBL ?C=:BK <5=N
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
m_items[i].Hide();
//--- !:@KBL @0745;8B5;L=K5 ;8=88
int sep_total=::ArraySize(m_sep_line);
for(int i=0; i<sep_total; i++)
m_sep_line[i].Hide();
//--- 1=C;8BL D>:CA
CElementBase::MouseFocus(false);
//--- @8A2>8BL AB0BCA A:@KB>3> M;5<5=B0
CElementBase::IsVisible(false);
//--- B<5B8BL A>AB>O=85 2 ?@54K4CI5< C7;5
if(!m_free_context_menu)
m_prev_node.IsPressed(false);
}
//+------------------------------------------------------------------+
//| #40;5=85 |
//+------------------------------------------------------------------+
void CContextMenu::Delete(void)
{
//--- #40;5=85 >1J5:B>2
m_canvas.Destroy();
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
m_items[i].Delete();
//--- #40;5=85 @0745;8B5;L=KE ;8=89
int sep_total=::ArraySize(m_sep_line);
for(int i=0; i<sep_total; i++)
m_sep_line[i].Delete();
//--- A2>1>645=85 <0AA82>2 M;5<5=B0
::ArrayFree(m_items);
::ArrayFree(m_sep_line);
::ArrayFree(m_sep_line_index);
::ArrayFree(m_text);
::ArrayFree(m_path_bmp_on);
::ArrayFree(m_path_bmp_off);
//--- A2>1>645=85 <0AA82>2 M;5<5=B>2 8 >1J5:B>2
CElement::FreeElementsArray();
//--- =8F80;870F8O ?5@5<5==KE 7=0G5=8O<8 ?> C<>;G0=8N
CElementBase::MouseFocus(false);
CElementBase::IsVisible(true);
}
//+------------------------------------------------------------------+
//| @>25@:0 CA;>289 =0 70:@KB85 2A5E :>=B5:AB=KE <5=N |
//+------------------------------------------------------------------+
void CContextMenu::CheckHideContextMenus(void)
{
//--- K9B8, 5A;8 (1) :C@A>@ 2 >1;0AB8 :>=B5:AB=>3> <5=N 8;8 (2) 2 >1;0AB8 ?@54K4CI53> C7;0
if(CElementBase::MouseFocus() || m_prev_node.MouseFocus())
return;
//--- A;8 65 :C@A>@ 2=5 >1;0AB8 MB8E M;5<5=B>2, B> ...
// ... =C6=> ?@>25@8BL, 5ABL ;8 >B:@KBK5 :>=B5:AB=K5 <5=N, :>B>@K5 1K;8 0:B828@>20=K 87 MB>3>
//--- ;O MB>3> ?@>94Q<AO 2 F8:;5 ?> A?8A:C MB>3> :>=B5:AB=>3> <5=N ...
// ... 4;O >?@545;5=8O =0;8G8O ?C=:B0, :>B>@K9 A>45@68B 2 A515 :>=B5:AB=>5 <5=N
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
//--- A;8 B0:>9 ?C=:B =0HQ;AO, B> =C6=> ?@>25@8BL, >B:@KB> ;8 53> :>=B5:AB=>5 <5=N.
// A;8 >=> >B:@KB>, B> =5 =C6=> >BAK;0BL A83=0; =0 70:@KB85 2A5E :>=B5:AB=KE <5=N 87 MB>3> M;5<5=B0, B0: :0:...
// ... 2>7<>6=>, GB> :C@A>@ =0E>48BAO 2 >1;0AB8 A;54CNI53> 8 =C6=> ?@>25@8BL B0<.
if(m_items[i].TypeMenuItem()==MI_HAS_CONTEXT_MENU)
if(m_items[i].GetContextMenuPointer().IsVisible())
return;
}
//--- B60BL :=>?:C ?@54K4CI53> C740
m_prev_node.IsPressed(false);
m_prev_node.Update(true);
//--- >A;0BL A83=0; =0 A:@KB85 2A5E :>=B5:AB=KE <5=N
::EventChartCustom(m_chart_id,ON_HIDE_CONTEXTMENUS,0,0,"");
//--- !>>1I5=85 =0 2>AAB0=>2;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.0,"");
}
//+------------------------------------------------------------------+
//| @>25@:0 CA;>289 =0 70:@KB85 2A5E :>=B5:AB=KE <5=N, |
//| :>B>@K5 1K;8 >B:@KBK ?>A;5 MB>3> |
//+------------------------------------------------------------------+
void CContextMenu::CheckHideBackContextMenus(void)
{
//--- @>9B8AL ?> 2A5< ?C=:B0< <5=N
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
//--- A;8 (1) ?C=:B A>45@68B :>=B5:AB=>5 <5=N 8 (2) >=> 2:;NG5=>
if(m_items[i].TypeMenuItem()==MI_HAS_CONTEXT_MENU && m_items[i].IsPressed())
{
//--- A;8 D>:CA 2 :>=B5:AB=>< <5=N, => =5 2 MB>< ?C=:B5
if(CElementBase::MouseFocus() && !m_items[i].MouseFocus())
{
//--- B?@028BL A83=0; =0 A:@KB85 2A5E :>=B5:AB=KE <5=N, :>B>@K5 1K;8 >B:@KBK ?>A;5 MB>3>
::EventChartCustom(m_chart_id,ON_HIDE_BACK_CONTEXTMENUS,CElementBase::Id(),0,"");
//--- !>>1I5=85 =0 2>AAB0=>2;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,"");
break;
}
}
}
}
//+------------------------------------------------------------------+
//| 1@01>B:0 =060B8O =0 ?C=:B <5=N |
//+------------------------------------------------------------------+
bool CContextMenu::OnClickMenuItem(const string pressed_object,const int id,const int index)
{
//--- K945<, 5A;8 =060B85 1K;> =5 =0 :=>?:5
if(::StringFind(pressed_object,"menu_item")<0)
return(false);
//--- K945<, 5A;8 (1) MB> :>=B5:AB=>5 <5=N 8<55B ?@54K4CI89 C75; 8 (2) C65 >B:@KB>
if(!m_free_context_menu && CElementBase::IsVisible())
return(true);
//--- A;8 MB> A2>1>4=>5 :>=B5:AB=>5 <5=N
if(m_free_context_menu)
{
//--- 094Q< 2 F8:;5 ?C=:B <5=N, =0 :>B>@K9 =060;8
int total=ItemsTotal();
for(int i=0; i<total; i++)
{
if(i!=index)
continue;
//--- B?@028< A>>1I5=85 >1 MB><
::EventChartCustom(m_chart_id,ON_CLICK_FREEMENU_ITEM,CElementBase::Id(),i,DescriptionByIndex(i));
break;
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| @8Q< A>>1I5=8O >B ?C=:B0 <5=N 4;O >1@01>B:8 |
//+------------------------------------------------------------------+
void CContextMenu::ReceiveMessageFromMenuItem(const int id,const int index_item,const string message_item)
{
//--- A;8 (1) =5B ?@87=0:0 MB>9 ?@>3@0<<K 8;8 (2) 845=B8D8:0B>@K =5 A>2?040NB
if(::StringFind(message_item,CElementBase::ProgramName(),0)<0 || id!=CElementBase::Id())
return;
//--- A;8 =060B85 1K;> =0 @048>-?C=:B5
if(::StringFind(message_item,"radioitem",0)>-1)
{
//--- >;CG8< id @048>-?C=:B0 87 ?5@540==>3> A>>1I5=8O
int radio_id=RadioIdFromMessage(message_item);
//--- >;CG8< 8=45:A @048>-?C=:B0 ?> >1I5<C 8=45:AC
int radio_index=RadioIndexByItemIndex(index_item);
//--- 5@5:;NG8BL @048>-?C=:B
SelectedRadioItem(radio_index,radio_id);
}
//--- !:@KB85 :>=B5:AB=>3> <5=N
Hide();
//--- B?@028< A>>1I5=85 >1 MB><
::EventChartCustom(m_chart_id,ON_CLICK_CONTEXTMENU_ITEM,id,index_item,DescriptionByIndex(index_item));
//--- >A;0BL A83=0; =0 A:@KB85 2A5E :>=B5:AB=KE <5=N
::EventChartCustom(m_chart_id,ON_HIDE_CONTEXTMENUS,0,0,"");
//--- !>>1I5=85 =0 2>AAB0=>2;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.0,"");
}
//+------------------------------------------------------------------+
//| 72;5:05B 845=B8D8:0B>@ 87 A>>1I5=8O 4;O @048>-?C=:B0 |
//+------------------------------------------------------------------+
int CContextMenu::RadioIdFromMessage(const string message)
{
ushort u_sep=0;
string result[];
int array_size=0;
//--- >;CG8< :>4 @0745;8B5;O
u_sep=::StringGetCharacter("_",0);
//--- 07>1LQ< AB@>:C
::StringSplit(message,u_sep,result);
array_size=::ArraySize(result);
//--- A;8 AB@C:BC@0 A>>1I5=8O >B;8G05BAO >B >68405<>9
if(array_size!=3)
{
::Print(__FUNCTION__," > 5?@028;L=0O AB@C:BC@0 2 A>>1I5=88 4;O @048>-?C=:B0! message: ",message);
return(WRONG_VALUE);
}
//--- @54>B2@0I5=85 2KE>40 70 ?@545;K <0AA820
if(array_size<3)
{
::Print(PREVENTING_OUT_OF_RANGE);
return(WRONG_VALUE);
}
//--- 5@=CBL id @048>-?C=:B0
return((int)result[2]);
}
//+------------------------------------------------------------------+
//| >72@0I05B 8=45:A @048>-?C=:B0 ?> >1I5<C 8=45:AC |
//+------------------------------------------------------------------+
int CContextMenu::RadioIndexByItemIndex(const int index)
{
int radio_index=0;
//--- >;CG05< ID @048>-?C=:B0 ?> >1I5<C 8=45:AC
int radio_id=RadioItemIdByIndex(index);
//--- !GQBG8: ?C=:B>2 87 =C6=>9 3@C??K
int count_radio_id=0;
//--- @>94Q<AO 2 F8:;5 ?> A?8A:C
int items_total=ItemsTotal();
for(int i=0; i<items_total; i++)
{
//--- A;8 MB> =5 @048>-?C=:B, ?5@59B8 : A;54CNI5<C
if(m_items[i].TypeMenuItem()!=MI_RADIOBUTTON)
continue;
//--- A;8 845=B8D8:0B>@K A>2?040NB
if(m_items[i].RadioButtonID()==radio_id)
{
//--- A;8 8=45:AK A>2?0;8, B>
// 70?><=8< B5:CI55 7=0G5=85 AGQBG8:0 8 70:>=G8< F8:;
if(m_items[i].Index()==index)
{
radio_index=count_radio_id;
break;
}
//--- #25;8G5=85 AGQBG8:0
count_radio_id++;
}
}
//--- 5@=CBL 8=45:A
return(radio_index);
}
//+------------------------------------------------------------------+
//| 8AC5B M;5<5=B |
//+------------------------------------------------------------------+
void CContextMenu::Draw(void)
{
//--- 0@8A>20BL D>=
CElement::DrawBackground();
//--- 0@8A>20BL @0<:C
CElement::DrawBorder();
}
//+------------------------------------------------------------------+