EasyAndFastMod/Controls/ComboBox.mqh

482 lines
39 KiB
MQL5
Raw Permalink Normal View History

2026-01-15 07:23:17 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| ComboBox.mqh |
//| Copyright 2015, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
#include "ListView.mqh"
//+------------------------------------------------------------------+
//| ;0AA 4;O A>740=8O :><18=8@>20==>3> A?8A:0 |
//+------------------------------------------------------------------+
class CComboBox : public CElement
{
private:
//--- -:75<?;O@K 4;O A>740=8O M;5<5=B0
CButton m_button;
CListView m_listview;
//--- 568< M;5<5=B0 A G5:-1>:A><
bool m_checkbox_mode;
//---
public:
CComboBox(void);
~CComboBox(void);
//--- 5B>4K 4;O A>740=8O :><1>-1>:A0
bool CreateComboBox(const string text,const int x_gap,const int y_gap);
//---
private:
void InitializeProperties(const string text,const int x_gap,const int y_gap);
bool CreateCanvas(void);
bool CreateButton(void);
bool CreateList(void);
//---
public:
//--- >72@0I05B C:070B5;8 =0 (1) :=>?:C, (2) A?8A>: 8 (3) ?>;>AC ?@>:@CB:8
CButton *GetButtonPointer(void) { return(::GetPointer(m_button)); }
CListView *GetListViewPointer(void) { return(::GetPointer(m_listview)); }
CScrollV *GetScrollVPointer(void) { return(m_listview.GetScrollVPointer()); }
//--- (1) 07<5@ A?8A:0 (:>;8G5AB2> ?C=:B>2) (2) CAB0=>2:0 @568<0 M;5<5=B0 A G5:-1>:A><
void ItemsTotal(const int items_total) { m_listview.ListSize(items_total); }
void CheckBoxMode(const bool state) { m_checkbox_mode=state; }
//--- !>AB>O=85 M;5<5=B0 (=060B/>B60B)
bool IsPressed(void) const { return(m_is_pressed); }
void IsPressed(const bool state);
//--- !>E@0=O5B ?5@540==>5 7=0G5=85 2 A?8A:5 ?> C:070==><C 8=45:AC
void SetValue(const int item_index,const string item_text);
//--- >72@0I05B 2K1@0==>5 7=0G5=85 2 A?8A:5
string GetValue(void);
//--- K45;5=85 ?C=:B0 ?> C:070==><C 8=45:AC
void SelectItem(const int item_index);
//--- 7<5=O5B B5:CI55 A>AB>O=85 :><1>-1>:A0 =0 ?@>B82>?>;>6=>5
void ChangeComboBoxListState(void);
//---
public:
//--- 1@01>BG8: A>1KB89 3@0D8:0
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
//--- ;>:8@>2:0
virtual void IsLocked(const bool state);
//--- #?@02;5=85 2848<>ABLN
virtual void Hide(void);
//--- 8AC5B M;5<5=B
virtual void Draw(void);
//---
private:
//--- 1@01>B:0 =060B8O =0 M;5<5=B5
bool OnClickElement(const string pressed_object);
//--- 1@01>B:0 =060B8O =0 :=>?:C
bool OnClickButton(const string pressed_object,const int id,const int index);
//--- 1@01>B:0 =060B8O =0 ?C=:B5 A?8A:0
bool OnClickListItem(const int id);
//--- @>25@:0 =060B>9 ;52>9 :=>?:8 <KH8 =04 :=>?:>9 :><1>-1>:A0
void CheckPressedOverButton(void);
//--- 8AC5B :0@B8=:C
virtual void DrawImage(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CComboBox::CComboBox(void) : m_checkbox_mode(false)
{
//--- !>E@0=8< 8<O :;0AA0 M;5<5=B0 2 107>2>< :;0AA5
CElementBase::ClassName(CLASS_NAME);
//--- 568< 2K?040NI53> A?8A:0
m_listview.IsDropdown(true);
m_listview.GetScrollVPointer().IsDropdown(true);
m_listview.GetScrollVPointer().GetIncButtonPointer().IsDropdown(true);
m_listview.GetScrollVPointer().GetDecButtonPointer().IsDropdown(true);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CComboBox::~CComboBox(void)
{
}
//+------------------------------------------------------------------+
//| 1@01>BG8: A>1KB89 |
//+------------------------------------------------------------------+
void CComboBox::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)
{
//--- @>25@:0 =060B>9 ;52>9 :=>?:8 <KH8 =04 :=>?:>9
CheckPressedOverButton();
//--- 5@5@8A>20BL M;5<5=B
if(CheckCrossingBorder())
Update(true);
//---
return;
}
//--- 1@01>B:0 A>1KB8O =060B8O =0 ?C=:B5 A?8A:0
if(id==CHARTEVENT_CUSTOM+ON_CLICK_LIST_ITEM)
{
if(!OnClickListItem((int)lparam))
return;
//---
return;
}
//--- 1@01>B:0 =060B8O =0 M;5<5=B5
if(id==CHARTEVENT_OBJECT_CLICK)
{
if(OnClickElement(sparam))
return;
//---
return;
}
//--- 1@01>B:0 A>1KB8O =060B8O =0 :=>?:5
if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
{
if(OnClickButton(sparam,(uint)lparam,(uint)dparam))
return;
//---
return;
}
//--- 1@01>B:0 A>1KB8O 87<5=5=8O A2>9AB2 3@0D8:0
if(id==CHARTEVENT_CHART_CHANGE)
{
//--- K9B8, 5A;8 (1) M;5<5=B 701;>:8@>20= 8;8 (2) :=>?:0 >B60B0
if(CElementBase::IsLocked() || !m_button.IsPressed())
return;
//--- B60BL :=>?:C
m_button.IsPressed(false);
//--- 7<5=8BL A>AB>O=85 A?8A:0
ChangeComboBoxListState();
return;
}
}
//+------------------------------------------------------------------+
//| !>740QB 3@C??C >1J5:B>2 B8?0 :><1>-1>:A |
//+------------------------------------------------------------------+
bool CComboBox::CreateComboBox(const string text,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(text,x_gap,y_gap);
//--- !>740=85 M;5<5=B0
if(!CreateCanvas())
return(false);
if(!CreateButton())
return(false);
if(!CreateList())
return(false);
//--- #AB0=>28BL B5:AB 2 :=>?:C
m_button.LabelText(m_listview.SelectedItemText());
return(true);
}
//+------------------------------------------------------------------+
//| =8F80;870F8O A2>9AB2 |
//+------------------------------------------------------------------+
void CComboBox::InitializeProperties(const string text,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)? 50 : m_x_size;
m_y_size =(m_y_size<1)? 20 : m_y_size;
m_label_text =text;
//--- &25B D>=0 8 >BABC?K 4;O :0@B8=:8/G5:-1>:A0
m_back_color=(m_back_color!=clrNONE)? m_back_color : m_main.BackColor();
//--- BABC?K 8 F25B B5:AB>2>9 <5B:8
m_icon_y_gap =(m_icon_y_gap!=WRONG_VALUE)? m_icon_y_gap : 4;
m_label_x_gap =(m_label_x_gap!=WRONG_VALUE)? m_label_x_gap : (m_checkbox_mode)? 20 : 0;
m_label_y_gap =(m_label_y_gap!=WRONG_VALUE)? m_label_y_gap : 4;
m_label_color =(m_label_color!=clrNONE)? m_label_color : clrBlack;
m_label_color_hover =(m_label_color_hover!=clrNONE)? m_label_color_hover : C'0,120,215';
m_label_color_locked =(m_label_color_locked!=clrNONE)? m_label_color_locked : clrSilver;
m_label_color_pressed =(m_label_color_pressed!=clrNONE)? m_label_color_pressed : clrBlack;
//--- 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 CComboBox::CreateCanvas(void)
{
//--- $>@<8@>20=85 8<5=8 >1J5:B0
string name=CElementBase::ElementName("combobox");
//--- A;8 =C65= M;5<5=B A G5:-1>:A><
if(m_checkbox_mode)
{
IconFile(RESOURCE_CHECKBOX_OFF);
IconFileLocked(RESOURCE_CHECKBOX_OFF_LOCKED);
IconFilePressed(RESOURCE_CHECKBOX_ON);
IconFilePressedLocked(RESOURCE_CHECKBOX_ON_LOCKED);
}
//--- !>740=85 >1J5:B0
if(!CElement::CreateCanvas(name,m_x,m_y,m_x_size,m_y_size))
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| !>740QB :=>?:C |
//+------------------------------------------------------------------+
bool CComboBox::CreateButton(void)
{
//--- !>E@0=8< C:070B5;L =0 @>48B5;LA:89 M;5<5=B
m_button.MainPointer(this);
//--- 07<5@K
int x_size=(m_button.XSize()<1)? 80 : m_button.XSize();
//--- >>@48=0BK
int x =(m_button.XGap()<1)? x_size : m_button.XGap();
int y =0;
//--- BABC?K 4;O :0@B8=:8
int icon_x_gap =(m_button.IconXGap()<1)? x_size-18 : m_button.IconXGap();
int icon_y_gap =(m_button.IconYGap()<1)? 2 : m_button.IconYGap();
//--- BABC?K 4;O B5:AB0
int label_x_gap =(m_button.LabelXGap()<1)? 7 : m_button.LabelXGap();
int label_y_gap =(m_button.LabelYGap()<1)? 4 : m_button.LabelYGap();
//--- !2>9AB20
m_button.NamePart("combobox_button");
m_button.Index(0);
m_button.TwoState(true);
m_button.XSize(x_size);
m_button.YSize(m_y_size);
m_button.IconXGap(icon_x_gap);
m_button.IconYGap(icon_y_gap);
m_button.LabelXGap(label_x_gap);
m_button.LabelYGap(label_y_gap);
m_button.IsDropdown(CElementBase::IsDropdown());
m_button.IconFile(RESOURCE_DOWN_THIN_BLACK);
m_button.IconFileLocked(RESOURCE_DOWN_THIN_BLACK);
m_button.CElement::IconFilePressed(RESOURCE_UP_THIN_BLACK);
m_button.CElement::IconFilePressedLocked(RESOURCE_UP_THIN_BLACK);
//--- !>74048< M;5<5=B C?@02;5=8O
if(!m_button.CreateButton("",x,y))
return(false);
//--- >1028BL M;5<5=B 2 <0AA82
CElement::AddToArray(m_button);
return(true);
}
//+------------------------------------------------------------------+
//| !>740QB A?8A>: |
//+------------------------------------------------------------------+
bool CComboBox::CreateList(void)
{
//--- !>E@0=8< C:070B5;L =0 3;02=K9 M;5<5=B
m_listview.MainPointer(this);
//--- >>@48=0BK
int x =m_button.XGap();
int y =m_button.YSize();
//--- 07<5@K
int x_size =(m_listview.XSize()<1)? m_button.XSize() : m_listview.XSize();
int y_size =(m_listview.YSize()<1)? 93 : m_listview.YSize();
//--- !2>9AB20
m_listview.XSize(x_size);
m_listview.YSize(y_size);
m_listview.AnchorRightWindowSide(m_button.AnchorRightWindowSide());
//--- !>74048< M;5<5=B C?@02;5=8O
if(!m_listview.CreateListView(x,y))
return(false);
//--- !:@KBL A?8A>:
m_listview.Hide();
//--- >1028BL M;5<5=B 2 <0AA82
CElement::AddToArray(m_listview);
return(true);
}
//+------------------------------------------------------------------+
//| #AB0=>2:0 A>AB>O=8O M;5<5=B0 (=060B/>B60B) |
//+------------------------------------------------------------------+
void CComboBox::IsPressed(const bool state)
{
//--- K9B8, 5A;8 (1) M;5<5=B 701;>:8@>20= 8;8 (2) M;5<5=B C65 2 B0:>< A>AB>O=88
if(CElementBase::IsLocked() || m_is_pressed==state)
return;
//--- #AB0=>2:0 A>AB>O=8O
m_is_pressed=state;
//--- #AB0=>28BL A>>B25BAB2CNICN :0@B8=:C
CElement::ChangeImage(0,!m_is_pressed? 0 : 2);
}
//+------------------------------------------------------------------+
//| !>E@0=O5B ?5@540==>5 7=0G5=85 2 A?8A:5 ?> C:070==><C 8=45:AC |
//+------------------------------------------------------------------+
void CComboBox::SetValue(const int item_index,const string item_text)
{
m_listview.SetValue(item_index,item_text);
}
//+------------------------------------------------------------------+
//| >72@0I05B 2K1@0==>5 2 A?8A:5 7=0G5=85 |
//+------------------------------------------------------------------+
string CComboBox::GetValue(void)
{
return(m_listview.SelectedItemText());
}
//+------------------------------------------------------------------+
//| K45;5=85 ?C=:B0 ?> C:070==><C 8=45:AC |
//+------------------------------------------------------------------+
void CComboBox::SelectItem(const int item_index)
{
//--- K1@0BL ?C=:B 2 A?8A:5
m_listview.SelectItem(item_index);
//--- #AB0=>28BL B5:AB 2 :=>?:C
m_button.LabelText(m_listview.SelectedItemText());
}
//+------------------------------------------------------------------+
//| ;>:8@>2:0 |
//+------------------------------------------------------------------+
void CComboBox::IsLocked(const bool state)
{
CElement::IsLocked(state);
//--- #AB0=>28BL A>>B25BAB2CNICN :0@B8=:C
CElement::ChangeImage(0,(m_is_locked)? !m_is_pressed? 1 : 3 : !m_is_pressed? 0 : 2);
}
//+------------------------------------------------------------------+
//| !:@KB85 |
//+------------------------------------------------------------------+
void CComboBox::Hide(void)
{
CElement::Hide();
//--- B60BL :=>?:C
m_button.IsPressed(false);
}
//+------------------------------------------------------------------+
//| 7<5=O5B B5:CI55 A>AB>O=85 :><1>-1>:A0 =0 ?@>B82>?>;>6=>5 |
//+------------------------------------------------------------------+
void CComboBox::ChangeComboBoxListState(void)
{
//--- A;8 :=>?:0 =060B0
if(m_button.IsPressed())
{
//--- >:070BL A?8A>:
m_listview.Show();
//--- 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
{
//--- !:@KBL A?8A>:
m_listview.Hide();
//--- B?@028< A>>1I5=85 =0 2>AAB0=>2;5=85 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,"");
}
}
//+------------------------------------------------------------------+
//| 060B85 =0 G5:-1>:A5 |
//+------------------------------------------------------------------+
bool CComboBox::OnClickElement(const string pressed_object)
{
//--- K945<, 5A;8 (1) M;5<5=B 701;>:8@>20= 8;8 (2) GC6>5 8<O >1J5:B0
if(CElementBase::IsLocked() || m_canvas.ChartObjectName()!=pressed_object)
return(false);
//--- A;8 G5:-1>:A 2:;NG5=
if(m_checkbox_mode)
{
//--- 5@5:;NG8BL =0 ?@>B82>?>;>6=K9 @568<
IsPressed(!(IsPressed()));
//--- B?@028< A>>1I5=85 >1 MB><
::EventChartCustom(m_chart_id,ON_CLICK_CHECKBOX,CElementBase::Id(),CElementBase::Index(),"");
}
//--- 0@8A>20BL M;5<5=B
CElement::Update(true);
return(true);
}
//+------------------------------------------------------------------+
//| 060B85 =0 :=>?:C :><1>-1>:A0 |
//+------------------------------------------------------------------+
bool CComboBox::OnClickButton(const string pressed_object,const int id,const int index)
{
//--- K9B8, 5A;8 =060B85 1K;> =0 4@C3>< M;5<5=B5
if(!m_button.CheckElementName(pressed_object))
return(false);
//--- K9B8, 5A;8 7=0G5=8O =5 A>2?040NB
if(id!=m_button.Id() || index!=m_button.Index())
return(false);
//--- 7<5=8BL A>AB>O=85 A?8A:0
ChangeComboBoxListState();
//--- B?@028< A>>1I5=85 >1 MB><
::EventChartCustom(m_chart_id,ON_CLICK_COMBOBOX_BUTTON,CElementBase::Id(),0,"");
return(true);
}
//+------------------------------------------------------------------+
//| 1@01>B:0 =060B8O =0 ?C=:B5 A?8A:0 |
//+------------------------------------------------------------------+
bool CComboBox::OnClickListItem(const int id)
{
//--- K9B8, 5A;8 7=0G5=8O =5 A>2?040NB
if(id!=CElementBase::Id())
return(false);
//--- B60BL :=>?:C
m_button.IsPressed(false);
//--- #AB0=>28BL B5:AB 2 :=>?:C
m_button.LabelText(m_listview.SelectedItemText());
m_button.Update(true);
//--- 7<5=8BL A>AB>O=85 A?8A:0
ChangeComboBoxListState();
//--- B?@028< A>>1I5=85 >1 MB><
::EventChartCustom(m_chart_id,ON_CLICK_COMBOBOX_ITEM,CElementBase::Id(),0,m_label_text);
return(true);
}
//+------------------------------------------------------------------+
//| @>25@:0 =060B>9 ;52>9 :=>?:8 <KH8 =04 :=>?:>9 |
//+------------------------------------------------------------------+
void CComboBox::CheckPressedOverButton(void)
{
//--- K9B8, 5A;8 :=>?:0 C65 >B60B0
if(!m_button.IsPressed())
return;
//--- K9B8, 5A;8 (1) M;5<5=B 701;>:8@>20= 8;8 (2) ;520O :=>?:0 <KH8 >B60B0
if(CElementBase::IsLocked() || !m_mouse.LeftButtonState())
return;
//--- A;8 D>:CA0 =5B
if(!CElementBase::MouseFocus() && !m_button.MouseFocus())
{
//--- K9B8, 5A;8 D>:CA =0 A?8A:5 8;8 ?>;>A0 ?@>:@CB:8 A?8A:0 2 459AB288
if(m_listview.MouseFocus() || m_listview.ScrollState())
return;
//--- !:@KBL A?8A>:
m_listview.Hide();
m_button.IsPressed(false);
m_button.Update(true);
//--- 0@8A>20BL M;5<5=B
Update(true);
//--- B?@028< A>>1I5=85 =0 2>AAB0=>2;5=85 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,"");
}
}
//+------------------------------------------------------------------+
//| 8AC5B M;5<5=B |
//+------------------------------------------------------------------+
void CComboBox::Draw(void)
{
//--- 0@8A>20BL D>=
CElement::DrawBackground();
//--- 0@8A>20BL :0@B8=:C
CElement::DrawImage();
//--- 0@8A>20BL B5:AB
CElement::DrawText();
}
//+------------------------------------------------------------------+
//| 8AC5B :0@B8=:C |
//+------------------------------------------------------------------+
void CComboBox::DrawImage(void)
{
//--- K9B8, 5A;8 (1) G5:-1>:A =5 =C65= 8;8 (2) :0@B8=:0 =5 >?@545;5=0
if(!m_checkbox_mode || CElement::IconFile()=="")
return;
//--- ?@545;8< 8=45:A
uint image_index=(m_is_pressed)? 2 : 0;
//--- A;8 M;5<5=B =5 701;>:8@>20=
if(!CElementBase::IsLocked())
{
if(CElementBase::MouseFocus())
image_index=(m_is_pressed)? 2 : 0;
}
else
image_index=(m_is_pressed)? 3 : 1;
//--- #AB0=>28BL A>>B25BAB2CNICN :0@B8=:C
CElement::ChangeImage(0,image_index);
//--- 8AC5< :0@B8=:C
CElement::DrawImage();
}
//+------------------------------------------------------------------+