481 líneas
39 KiB
MQL5
481 líneas
39 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ComboBox.mqh |
|
|
//| Copyright 2015, MetaQuotes Software Corp. |
|
|
//| http://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#include "..\Element.mqh"
|
|
#include "ListView.mqh"
|
|
//+------------------------------------------------------------------+
|
|
//| Класс для создания комбинированного списка |
|
|
//+------------------------------------------------------------------+
|
|
class CComboBox : public CElement
|
|
{
|
|
private:
|
|
//--- Экземпляры для создания элемента
|
|
CButton m_button;
|
|
CListView m_listview;
|
|
//--- Режим элемента с чек-боксом
|
|
bool m_checkbox_mode;
|
|
//---
|
|
public:
|
|
CComboBox(void);
|
|
~CComboBox(void);
|
|
//--- Методы для создания комбо-бокса
|
|
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:
|
|
//--- Возвращает указатели на (1) кнопку, (2) список и (3) полосу прокрутки
|
|
CButton *GetButtonPointer(void) { return(::GetPointer(m_button)); }
|
|
CListView *GetListViewPointer(void) { return(::GetPointer(m_listview)); }
|
|
CScrollV *GetScrollVPointer(void) { return(m_listview.GetScrollVPointer()); }
|
|
//--- (1) Размер списка (количество пунктов) (2) установка режима элемента с чек-боксом
|
|
void ItemsTotal(const int items_total) { m_listview.ListSize(items_total); }
|
|
void CheckBoxMode(const bool state) { m_checkbox_mode=state; }
|
|
//--- Состояние элемента (нажат/отжат)
|
|
bool IsPressed(void) const { return(m_is_pressed); }
|
|
void IsPressed(const bool state);
|
|
//--- Сохраняет переданное значение в списке по указанному индексу
|
|
void SetValue(const int item_index,const string item_text);
|
|
//--- Возвращает выбранное значение в списке
|
|
string GetValue(void);
|
|
//--- Выделение пункта по указанному индексу
|
|
void SelectItem(const int item_index);
|
|
//--- Изменяет текущее состояние комбо-бокса на противоположное
|
|
void ChangeComboBoxListState(void);
|
|
//---
|
|
public:
|
|
//--- Обработчик событий графика
|
|
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
|
//--- Блокировка
|
|
virtual void IsLocked(const bool state);
|
|
//--- Управление видимостью
|
|
virtual void Hide(void);
|
|
//--- Рисует элемент
|
|
virtual void Draw(void);
|
|
//---
|
|
private:
|
|
//--- Обработка нажатия на элементе
|
|
bool OnClickElement(const string pressed_object);
|
|
//--- Обработка нажатия на кнопку
|
|
bool OnClickButton(const string pressed_object,const int id,const int index);
|
|
//--- Обработка нажатия на пункте списка
|
|
bool OnClickListItem(const int id);
|
|
|
|
//--- Проверка нажатой левой кнопки мыши над кнопкой комбо-бокса
|
|
void CheckPressedOverButton(void);
|
|
//--- Рисует картинку
|
|
virtual void DrawImage(void);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
CComboBox::CComboBox(void) : m_checkbox_mode(false)
|
|
{
|
|
//--- Сохраним имя класса элемента в базовом классе
|
|
CElementBase::ClassName(CLASS_NAME);
|
|
//--- Режим выпадающего списка
|
|
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)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработчик событий |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
|
{
|
|
//--- Обработка события перемещения курсора
|
|
if(id==CHARTEVENT_MOUSE_MOVE)
|
|
{
|
|
//--- Проверка нажатой левой кнопки мыши над кнопкой
|
|
CheckPressedOverButton();
|
|
//--- Перерисовать элемент
|
|
if(CheckCrossingBorder())
|
|
Update(true);
|
|
//---
|
|
return;
|
|
}
|
|
//--- Обработка события нажатия на пункте списка
|
|
if(id==CHARTEVENT_CUSTOM+ON_CLICK_LIST_ITEM)
|
|
{
|
|
if(!OnClickListItem((int)lparam))
|
|
return;
|
|
//---
|
|
return;
|
|
}
|
|
//--- Обработка нажатия на элементе
|
|
if(id==CHARTEVENT_OBJECT_CLICK)
|
|
{
|
|
if(OnClickElement(sparam))
|
|
return;
|
|
//---
|
|
return;
|
|
}
|
|
//--- Обработка события нажатия на кнопке
|
|
if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
|
|
{
|
|
if(OnClickButton(sparam,(uint)lparam,(uint)dparam))
|
|
return;
|
|
//---
|
|
return;
|
|
}
|
|
//--- Обработка события изменения свойств графика
|
|
if(id==CHARTEVENT_CHART_CHANGE)
|
|
{
|
|
//--- Выйти, если (1) элемент заблокирован или (2) кнопка отжата
|
|
if(CElementBase::IsLocked() || !m_button.IsPressed())
|
|
return;
|
|
//--- Отжать кнопку
|
|
m_button.IsPressed(false);
|
|
//--- Изменить состояние списка
|
|
ChangeComboBoxListState();
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт группу объектов типа комбо-бокс |
|
|
//+------------------------------------------------------------------+
|
|
bool CComboBox::CreateComboBox(const string text,const int x_gap,const int y_gap)
|
|
{
|
|
//--- Выйти, если нет указателя на главный элемент
|
|
if(!CElement::CheckMainPointer())
|
|
return(false);
|
|
//--- Инициализация свойств
|
|
InitializeProperties(text,x_gap,y_gap);
|
|
//--- Создание элемента
|
|
if(!CreateCanvas())
|
|
return(false);
|
|
if(!CreateButton())
|
|
return(false);
|
|
if(!CreateList())
|
|
return(false);
|
|
//--- Установить текст в кнопку
|
|
m_button.LabelText(m_listview.SelectedItemText());
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Инициализация свойств |
|
|
//+------------------------------------------------------------------+
|
|
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;
|
|
//--- Цвет фона и отступы для картинки/чек-бокса
|
|
m_back_color=(m_back_color!=clrNONE)? m_back_color : m_main.BackColor();
|
|
//--- Отступы и цвет текстовой метки
|
|
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;
|
|
//--- Отступы от крайней точки
|
|
CElementBase::XGap(x_gap);
|
|
CElementBase::YGap(y_gap);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт объект для рисования |
|
|
//+------------------------------------------------------------------+
|
|
bool CComboBox::CreateCanvas(void)
|
|
{
|
|
//--- Формирование имени объекта
|
|
string name=CElementBase::ElementName("combobox");
|
|
//--- Если нужен элемент с чек-боксом
|
|
if(m_checkbox_mode)
|
|
{
|
|
IconFile(RESOURCE_CHECKBOX_OFF);
|
|
IconFileLocked(RESOURCE_CHECKBOX_OFF_LOCKED);
|
|
IconFilePressed(RESOURCE_CHECKBOX_ON);
|
|
IconFilePressedLocked(RESOURCE_CHECKBOX_ON_LOCKED);
|
|
}
|
|
//--- Создание объекта
|
|
if(!CElement::CreateCanvas(name,m_x,m_y,m_x_size,m_y_size))
|
|
return(false);
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт кнопку |
|
|
//+------------------------------------------------------------------+
|
|
bool CComboBox::CreateButton(void)
|
|
{
|
|
//--- Сохраним указатель на родительский элемент
|
|
m_button.MainPointer(this);
|
|
//--- Размеры
|
|
int x_size=(m_button.XSize()<1)? 80 : m_button.XSize();
|
|
//--- Координаты
|
|
int x =(m_button.XGap()<1)? x_size : m_button.XGap();
|
|
int y =0;
|
|
//--- Отступы для картинки
|
|
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();
|
|
//--- Отступы для текста
|
|
int label_x_gap =(m_button.LabelXGap()<1)? 7 : m_button.LabelXGap();
|
|
int label_y_gap =(m_button.LabelYGap()<1)? 4 : m_button.LabelYGap();
|
|
//--- Свойства
|
|
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);
|
|
|
|
//--- Создадим элемент управления
|
|
if(!m_button.CreateButton("",x,y))
|
|
return(false);
|
|
|
|
//--- Добавить элемент в массив
|
|
CElement::AddToArray(m_button);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт список |
|
|
//+------------------------------------------------------------------+
|
|
bool CComboBox::CreateList(void)
|
|
{
|
|
//--- Сохраним указатель на главный элемент
|
|
m_listview.MainPointer(this);
|
|
//--- Координаты
|
|
int x =m_button.XGap();
|
|
int y =m_button.YSize();
|
|
//--- Размеры
|
|
int x_size =(m_listview.XSize()<1)? m_button.XSize() : m_listview.XSize();
|
|
int y_size =(m_listview.YSize()<1)? 93 : m_listview.YSize();
|
|
//--- Свойства
|
|
m_listview.XSize(x_size);
|
|
m_listview.YSize(y_size);
|
|
m_listview.AnchorRightWindowSide(m_button.AnchorRightWindowSide());
|
|
//--- Создадим элемент управления
|
|
if(!m_listview.CreateListView(x,y))
|
|
return(false);
|
|
//--- Скрыть список
|
|
m_listview.Hide();
|
|
//--- Добавить элемент в массив
|
|
CElement::AddToArray(m_listview);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Установка состояния элемента (нажат/отжат) |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::IsPressed(const bool state)
|
|
{
|
|
//--- Выйти, если (1) элемент заблокирован или (2) элемент уже в таком состоянии
|
|
if(CElementBase::IsLocked() || m_is_pressed==state)
|
|
return;
|
|
//--- Установка состояния
|
|
m_is_pressed=state;
|
|
//--- Установить соответствующую картинку
|
|
CElement::ChangeImage(0,!m_is_pressed? 0 : 2);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Сохраняет переданное значение в списке по указанному индексу |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::SetValue(const int item_index,const string item_text)
|
|
{
|
|
m_listview.SetValue(item_index,item_text);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает выбранное в списке значение |
|
|
//+------------------------------------------------------------------+
|
|
string CComboBox::GetValue(void)
|
|
{
|
|
return(m_listview.SelectedItemText());
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Выделение пункта по указанному индексу |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::SelectItem(const int item_index)
|
|
{
|
|
//--- Выбрать пункт в списке
|
|
m_listview.SelectItem(item_index);
|
|
//--- Установить текст в кнопку
|
|
m_button.LabelText(m_listview.SelectedItemText());
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Блокировка |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::IsLocked(const bool state)
|
|
{
|
|
CElement::IsLocked(state);
|
|
//--- Установить соответствующую картинку
|
|
CElement::ChangeImage(0,(m_is_locked)? !m_is_pressed? 1 : 3 : !m_is_pressed? 0 : 2);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Скрытие |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::Hide(void)
|
|
{
|
|
CElement::Hide();
|
|
//--- Отжать кнопку
|
|
m_button.IsPressed(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Изменяет текущее состояние комбо-бокса на противоположное |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::ChangeComboBoxListState(void)
|
|
{
|
|
//--- Если кнопка нажата
|
|
if(m_button.IsPressed())
|
|
{
|
|
//--- Показать список
|
|
m_listview.Show();
|
|
//--- Отправим сообщение на определение доступных элементов
|
|
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),0,"");
|
|
//--- Отправим сообщение об изменении в графическом интерфейсе
|
|
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
|
|
}
|
|
else
|
|
{
|
|
//--- Скрыть список
|
|
m_listview.Hide();
|
|
//--- Отправим сообщение на восстановление элементов
|
|
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),1,"");
|
|
//--- Отправим сообщение об изменении в графическом интерфейсе
|
|
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Нажатие на чек-боксе |
|
|
//+------------------------------------------------------------------+
|
|
bool CComboBox::OnClickElement(const string pressed_object)
|
|
{
|
|
//--- Выйдем, если (1) элемент заблокирован или (2) чужое имя объекта
|
|
if(CElementBase::IsLocked() || m_canvas.ChartObjectName()!=pressed_object)
|
|
return(false);
|
|
//--- Если чек-бокс включен
|
|
if(m_checkbox_mode)
|
|
{
|
|
//--- Переключить на противоположный режим
|
|
IsPressed(!(IsPressed()));
|
|
//--- Отправим сообщение об этом
|
|
::EventChartCustom(m_chart_id,ON_CLICK_CHECKBOX,CElementBase::Id(),CElementBase::Index(),"");
|
|
}
|
|
//--- Нарисовать элемент
|
|
CElement::Update(true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Нажатие на кнопку комбо-бокса |
|
|
//+------------------------------------------------------------------+
|
|
bool CComboBox::OnClickButton(const string pressed_object,const int id,const int index)
|
|
{
|
|
//--- Выйти, если нажатие было на другом элементе
|
|
if(!m_button.CheckElementName(pressed_object))
|
|
return(false);
|
|
//--- Выйти, если значения не совпадают
|
|
if(id!=m_button.Id() || index!=m_button.Index())
|
|
return(false);
|
|
//--- Изменить состояние списка
|
|
ChangeComboBoxListState();
|
|
//--- Отправим сообщение об этом
|
|
::EventChartCustom(m_chart_id,ON_CLICK_COMBOBOX_BUTTON,CElementBase::Id(),0,"");
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на пункте списка |
|
|
//+------------------------------------------------------------------+
|
|
bool CComboBox::OnClickListItem(const int id)
|
|
{
|
|
//--- Выйти, если значения не совпадают
|
|
if(id!=CElementBase::Id())
|
|
return(false);
|
|
//--- Отжать кнопку
|
|
m_button.IsPressed(false);
|
|
//--- Установить текст в кнопку
|
|
m_button.LabelText(m_listview.SelectedItemText());
|
|
m_button.Update(true);
|
|
//--- Изменить состояние списка
|
|
ChangeComboBoxListState();
|
|
//--- Отправим сообщение об этом
|
|
::EventChartCustom(m_chart_id,ON_CLICK_COMBOBOX_ITEM,CElementBase::Id(),0,m_label_text);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Проверка нажатой левой кнопки мыши над кнопкой |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::CheckPressedOverButton(void)
|
|
{
|
|
//--- Выйти, если кнопка уже отжата
|
|
if(!m_button.IsPressed())
|
|
return;
|
|
//--- Выйти, если (1) элемент заблокирован или (2) левая кнопка мыши отжата
|
|
if(CElementBase::IsLocked() || !m_mouse.LeftButtonState())
|
|
return;
|
|
//--- Если фокуса нет
|
|
if(!CElementBase::MouseFocus() && !m_button.MouseFocus())
|
|
{
|
|
//--- Выйти, если фокус на списке или полоса прокрутки списка в действии
|
|
if(m_listview.MouseFocus() || m_listview.ScrollState())
|
|
return;
|
|
//--- Скрыть список
|
|
m_listview.Hide();
|
|
m_button.IsPressed(false);
|
|
m_button.Update(true);
|
|
//--- Нарисовать элемент
|
|
Update(true);
|
|
//--- Отправим сообщение на восстановление элементов
|
|
::EventChartCustom(m_chart_id,ON_SET_AVAILABLE,CElementBase::Id(),1,"");
|
|
//--- Отправим сообщение об изменении в графическом интерфейсе
|
|
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0.0,"");
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рисует элемент |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::Draw(void)
|
|
{
|
|
//--- Нарисовать фон
|
|
CElement::DrawBackground();
|
|
//--- Нарисовать картинку
|
|
CElement::DrawImage();
|
|
//--- Нарисовать текст
|
|
CElement::DrawText();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рисует картинку |
|
|
//+------------------------------------------------------------------+
|
|
void CComboBox::DrawImage(void)
|
|
{
|
|
//--- Выйти, если (1) чек-бокс не нужен или (2) картинка не определена
|
|
if(!m_checkbox_mode || CElement::IconFile()=="")
|
|
return;
|
|
//--- Определим индекс
|
|
uint image_index=(m_is_pressed)? 2 : 0;
|
|
//--- Если элемент не заблокирован
|
|
if(!CElementBase::IsLocked())
|
|
{
|
|
if(CElementBase::MouseFocus())
|
|
image_index=(m_is_pressed)? 2 : 0;
|
|
}
|
|
else
|
|
image_index=(m_is_pressed)? 3 : 1;
|
|
//--- Установить соответствующую картинку
|
|
CElement::ChangeImage(0,image_index);
|
|
//--- Рисуем картинку
|
|
CElement::DrawImage();
|
|
}
|
|
//+------------------------------------------------------------------+
|