448 righe
38 KiB
MQL5
448 righe
38 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| PicturesSlider.mqh |
|
|
//| Copyright 2016, MetaQuotes Software Corp. |
|
|
//| http://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#include "..\Element.mqh"
|
|
#include "Picture.mqh"
|
|
#include "Button.mqh"
|
|
#include "ButtonsGroup.mqh"
|
|
//--- Картинка по умолчанию
|
|
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp"
|
|
//+------------------------------------------------------------------+
|
|
//| Класс для создания слайдера картинок |
|
|
//+------------------------------------------------------------------+
|
|
class CPicturesSlider : public CElement
|
|
{
|
|
private:
|
|
//--- Объекты для создания элемента
|
|
CPicture m_pictures[];
|
|
CButtonsGroup m_radio_buttons;
|
|
CButton m_left_arrow;
|
|
CButton m_right_arrow;
|
|
//--- Массив картинок (путь к картинкам)
|
|
string m_file_path[];
|
|
//--- Путь к картинке по умолчанию
|
|
string m_default_path;
|
|
//--- Отступ для картинок по оси Y
|
|
int m_pictures_y_gap;
|
|
//--- Отступы для кнопок
|
|
int m_arrows_x_gap;
|
|
int m_arrows_y_gap;
|
|
//--- Ширина радио-кнопки
|
|
int m_radio_button_width;
|
|
//--- Отступы для радио-кнопок
|
|
int m_radio_buttons_x_gap;
|
|
int m_radio_buttons_y_gap;
|
|
int m_radio_buttons_x_offset;
|
|
//---
|
|
public:
|
|
CPicturesSlider(void);
|
|
~CPicturesSlider(void);
|
|
//--- Методы для создания слайдера картинок
|
|
bool CreatePicturesSlider(const int x_gap,const int y_gap);
|
|
//---
|
|
private:
|
|
void InitializeProperties(const int x_gap,const int y_gap);
|
|
bool CreateCanvas(void);
|
|
bool CreatePictures(void);
|
|
bool CreateRadioButtons(void);
|
|
bool CreateArrow(CButton &button_obj,const int index);
|
|
//---
|
|
public:
|
|
//--- Возвращает указатели на составные элементы
|
|
CButtonsGroup *GetRadioButtonsPointer(void) { return(::GetPointer(m_radio_buttons)); }
|
|
CButton *GetLeftArrowPointer(void) { return(::GetPointer(m_left_arrow)); }
|
|
CButton *GetRightArrowPointer(void) { return(::GetPointer(m_right_arrow)); }
|
|
CPicture *GetPicturePointer(const uint index);
|
|
//--- Отступы для кнопок-стрелок
|
|
void ArrowsXGap(const int x_gap) { m_arrows_x_gap=x_gap; }
|
|
void ArrowsYGap(const int y_gap) { m_arrows_y_gap=y_gap; }
|
|
//--- (1) Возвращает количество картинок, (2) отступ для картинок по оси Y
|
|
int PicturesTotal(void) const { return(::ArraySize(m_pictures)); }
|
|
void PictureYGap(const int y_gap) { m_pictures_y_gap=y_gap; }
|
|
//--- (1) Отступы радио-кнопок, (2) расстояние между радио-кнопками
|
|
void RadioButtonsXGap(const int x_gap) { m_radio_buttons_x_gap=x_gap; }
|
|
void RadioButtonsYGap(const int y_gap) { m_radio_buttons_y_gap=y_gap; }
|
|
void RadioButtonsXOffset(const int x_offset) { m_radio_buttons_x_offset=x_offset; }
|
|
//--- Добавляет картинку
|
|
void AddPicture(const string file_path="");
|
|
//--- Переключает картинку по указанному индексу
|
|
void SelectPicture(const int index);
|
|
//---
|
|
public:
|
|
//--- Обработчик событий графика
|
|
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
|
//--- Показать, удалить
|
|
virtual void Show(void);
|
|
virtual void Delete(void);
|
|
//--- Рисует элемент
|
|
virtual void Draw(void);
|
|
//---
|
|
private:
|
|
//--- Обработка нажатия на радио-кнопку
|
|
bool OnClickRadioButton(const string clicked_object,const int id,const int index);
|
|
//--- Обработка нажатия на левой кнопку
|
|
bool OnClickLeftArrow(const string clicked_object,const int id,const int index);
|
|
//--- Обработка нажатия на правой кнопку
|
|
bool OnClickRightArrow(const string clicked_object,const int id,const int index);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
CPicturesSlider::CPicturesSlider(void) : m_default_path("Images\\EasyAndFastGUI\\Icons\\bmp64\\no_image.bmp"),
|
|
m_arrows_x_gap(2),
|
|
m_arrows_y_gap(2),
|
|
m_radio_button_width(18),
|
|
m_radio_buttons_x_gap(25),
|
|
m_radio_buttons_y_gap(1),
|
|
m_radio_buttons_x_offset(20),
|
|
m_pictures_y_gap(25)
|
|
{
|
|
//--- Сохраним имя класса элемента в базовом классе
|
|
CElementBase::ClassName(CLASS_NAME);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
CPicturesSlider::~CPicturesSlider(void)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработчик событий |
|
|
//+------------------------------------------------------------------+
|
|
void CPicturesSlider::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
|
{
|
|
//--- Обработка события нажатия левой кнопки мыши на объекте
|
|
if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
|
|
{
|
|
//--- Нажатие на радио-кнопке
|
|
if(OnClickRadioButton(sparam,(int)lparam,(int)dparam))
|
|
return;
|
|
//--- Если нажатие на кнопках-стрелках слайдера, переключить картинку
|
|
if(OnClickLeftArrow(sparam,(int)lparam,(int)dparam))
|
|
return;
|
|
if(OnClickRightArrow(sparam,(int)lparam,(int)dparam))
|
|
return;
|
|
//---
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт элемент |
|
|
//+------------------------------------------------------------------+
|
|
bool CPicturesSlider::CreatePicturesSlider(const int x_gap,const int y_gap)
|
|
{
|
|
//--- Выйти, если нет указателя на главный элемент
|
|
if(!CElement::CheckMainPointer())
|
|
return(false);
|
|
//--- Инициализация свойств
|
|
InitializeProperties(x_gap,y_gap);
|
|
//--- Создание элемента
|
|
if(!CreateCanvas())
|
|
return(false);
|
|
if(!CreatePictures())
|
|
return(false);
|
|
if(!CreateRadioButtons())
|
|
return(false);
|
|
if(!CreateArrow(m_left_arrow,0))
|
|
return(false);
|
|
if(!CreateArrow(m_right_arrow,1))
|
|
return(false);
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Инициализация свойств |
|
|
//+------------------------------------------------------------------+
|
|
void CPicturesSlider::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)? 300 : m_x_size;
|
|
m_y_size =(m_y_size<1)? 300 : m_y_size;
|
|
//--- Свойства по умолчанию
|
|
m_back_color =(m_back_color!=clrNONE)? m_back_color : m_main.BackColor();
|
|
m_border_color =(m_border_color!=clrNONE)? m_border_color : m_main.BackColor();
|
|
//--- Отступы от крайней точки
|
|
CElementBase::XGap(x_gap);
|
|
CElementBase::YGap(y_gap);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт объект для рисования |
|
|
//+------------------------------------------------------------------+
|
|
bool CPicturesSlider::CreateCanvas(void)
|
|
{
|
|
//--- Формирование имени объекта
|
|
string name=CElementBase::ElementName("pictures_slider");
|
|
//--- Создание объекта
|
|
if(!CElement::CreateCanvas(name,m_x,m_y,m_x_size,m_y_size))
|
|
return(false);
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт группу картинок |
|
|
//+------------------------------------------------------------------+
|
|
bool CPicturesSlider::CreatePictures(void)
|
|
{
|
|
//--- Получим количество картинок
|
|
int pictures_total=PicturesTotal();
|
|
//--- Если нет ни одной картинки в группе, сообщить об этом
|
|
if(pictures_total<1)
|
|
{
|
|
::Print(__FUNCTION__," > Вызов этого метода нужно осуществлять, "
|
|
"когда в группе есть хотя бы одна картинка! Воспользуйтесь методом CPicturesSlider::AddPicture()");
|
|
return(false);
|
|
}
|
|
//--- Координаты
|
|
uint x=0,y=m_pictures_y_gap;
|
|
//--- Размеры
|
|
uint x_size=0,y_size=0;
|
|
//--- Массив для изображения
|
|
uint image_data[];
|
|
//---
|
|
for(int i=0; i<pictures_total; i++)
|
|
{
|
|
//--- Сохраним указатель на окно
|
|
m_pictures[i].MainPointer(this);
|
|
//--- Прочитать данные изображения
|
|
if(!::ResourceReadImage("::"+m_file_path[i],image_data,x_size,y_size))
|
|
{
|
|
::Print(__FUNCTION__," > Ошибка при чтении изображения ("+m_file_path[i]+"): ",::GetLastError());
|
|
return(false);
|
|
}
|
|
//--- Рассчитать отступ
|
|
x=(m_x_size>>1)-(x_size>>1);
|
|
//--- Свойства
|
|
m_pictures[i].Index(i);
|
|
m_pictures[i].XSize(x_size);
|
|
m_pictures[i].YSize(y_size);
|
|
m_pictures[i].NamePart("picture_slider");
|
|
m_pictures[i].IconFile(m_file_path[i]);
|
|
m_pictures[i].IconFileLocked(m_file_path[i]);
|
|
//--- Создание кнопки
|
|
if(!m_pictures[i].CreatePicture(x,y))
|
|
return(false);
|
|
//--- Добавить элемент в массив
|
|
CElement::AddToArray(m_pictures[i]);
|
|
}
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт группу радио-кнопок |
|
|
//+------------------------------------------------------------------+
|
|
bool CPicturesSlider::CreateRadioButtons(void)
|
|
{
|
|
//--- Сохраним указатель на родительский элемент
|
|
m_radio_buttons.MainPointer(this);
|
|
//--- Координаты
|
|
int x=m_radio_buttons_x_gap,y=m_radio_buttons_y_gap;
|
|
//--- Количество картинок
|
|
int pictures_total=PicturesTotal();
|
|
//--- Свойства
|
|
int buttons_x_offset[];
|
|
//--- Установим размер массивам
|
|
::ArrayResize(buttons_x_offset,pictures_total);
|
|
//--- Отступы между радио-кнопками
|
|
for(int i=0; i<pictures_total; i++)
|
|
buttons_x_offset[i]=(i>0)? buttons_x_offset[i-1]+m_radio_buttons_x_offset : 0;
|
|
//---
|
|
m_radio_buttons.NamePart("radio_button");
|
|
m_radio_buttons.RadioButtonsMode(true);
|
|
m_radio_buttons.RadioButtonsStyle(true);
|
|
//--- Добавим кнопки в группу
|
|
for(int i=0; i<pictures_total; i++)
|
|
m_radio_buttons.AddButton(buttons_x_offset[i],0,"",m_radio_button_width);
|
|
//--- Создать группу кнопок
|
|
if(!m_radio_buttons.CreateButtonsGroup(x,y))
|
|
return(false);
|
|
//--- Покажем картинку по выделенной радио-кнопке
|
|
SelectPicture(1);
|
|
//--- Добавить элемент в массив
|
|
CElement::AddToArray(m_radio_buttons);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт кнопку со стрелкой |
|
|
//+------------------------------------------------------------------+
|
|
//#resource "\\Images\\EasyAndFastGUI\\Controls\\left_thin_black.bmp"
|
|
//#resource "\\Images\\EasyAndFastGUI\\Controls\\right_thin_black.bmp"
|
|
//---
|
|
bool CPicturesSlider::CreateArrow(CButton &button_obj,const int index)
|
|
{
|
|
//--- Сохраним указатель на главный элемент
|
|
button_obj.MainPointer(this);
|
|
//--- Координаты
|
|
int x =(index<1)? m_arrows_x_gap : m_arrows_x_gap+16;
|
|
int y =m_arrows_y_gap;
|
|
//--- Установим свойства перед созданием
|
|
button_obj.Index(index);
|
|
button_obj.XSize(16);
|
|
button_obj.YSize(16);
|
|
//--- Ярлыки для кнопок
|
|
if(index<1)
|
|
{
|
|
button_obj.IconFile(RESOURCE_LEFT_THIN_BLACK);
|
|
button_obj.IconFileLocked(RESOURCE_LEFT_THIN_BLACK);
|
|
}
|
|
else
|
|
{
|
|
button_obj.IconFile(RESOURCE_RIGHT_THIN_BLACK);
|
|
button_obj.IconFileLocked(RESOURCE_RIGHT_THIN_BLACK);
|
|
button_obj.AnchorRightWindowSide(true);
|
|
}
|
|
//--- Создадим элемент управления
|
|
if(!button_obj.CreateButton("",x,y))
|
|
return(false);
|
|
//--- Добавить элемент в массив
|
|
CElement::AddToArray(button_obj);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Добавляет картинку |
|
|
//+------------------------------------------------------------------+
|
|
CPicture *CPicturesSlider::GetPicturePointer(const uint index)
|
|
{
|
|
uint array_size=PicturesTotal();
|
|
//--- Проверка размера массива объектов
|
|
if(array_size<1)
|
|
{
|
|
Print(__FUNCTION__," > В группе нет ни одного элемента!");
|
|
return(NULL);
|
|
}
|
|
//--- Корректировка в случае выхода из диапазона
|
|
uint i=(index>=array_size)? array_size-1 : index;
|
|
//--- Вернуть указатель объекта
|
|
return(::GetPointer(m_pictures[i]));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Добавляет картинку |
|
|
//+------------------------------------------------------------------+
|
|
void CPicturesSlider::AddPicture(const string file_path="")
|
|
{
|
|
//--- Увеличим размер массивов на один элемент
|
|
int array_size=::ArraySize(m_pictures);
|
|
int new_size=array_size+1;
|
|
::ArrayResize(m_pictures,new_size);
|
|
::ArrayResize(m_file_path,new_size);
|
|
//--- Сохраним значения переданных параметров
|
|
m_file_path[array_size]=(file_path=="")? m_default_path : file_path;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Указывает, какая картинка должна быть показана |
|
|
//+------------------------------------------------------------------+
|
|
void CPicturesSlider::SelectPicture(const int index)
|
|
{
|
|
//--- Получим количество картинок
|
|
int pictures_total=PicturesTotal();
|
|
//--- Если нет ни одной картинки в группе, сообщить об этом
|
|
if(pictures_total<1)
|
|
{
|
|
::Print(__FUNCTION__," > Вызов этого метода нужно осуществлять, "
|
|
"когда в группе есть хотя бы одна картинка! Воспользуйтесь методом CPicturesSlider::AddPicture()");
|
|
return;
|
|
}
|
|
//--- Скорректировать значение индекса, если выходит из диапазона
|
|
uint correct_index=(index>=pictures_total)? pictures_total-1 :(index<0)? 0 : index;
|
|
//--- Выделить радио-кнопку по этому индексу
|
|
m_radio_buttons.SelectButton(correct_index);
|
|
//--- Переключить картинку
|
|
for(int i=0; i<pictures_total; i++)
|
|
{
|
|
if(i==correct_index)
|
|
m_pictures[i].Show();
|
|
else
|
|
m_pictures[i].Hide();
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Показать |
|
|
//+------------------------------------------------------------------+
|
|
void CPicturesSlider::Show(void)
|
|
{
|
|
CElement::Show();
|
|
SelectPicture(m_radio_buttons.SelectedButtonIndex());
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Удаление |
|
|
//+------------------------------------------------------------------+
|
|
void CPicturesSlider::Delete(void)
|
|
{
|
|
CElement::Delete();
|
|
//--- Освобождение массивов элемента
|
|
::ArrayFree(m_pictures);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Нажатие на радио-кнопку |
|
|
//+------------------------------------------------------------------+
|
|
bool CPicturesSlider::OnClickRadioButton(const string clicked_object,const int id,const int index)
|
|
{
|
|
//--- Выйдем, если нажатие было не на кнопке
|
|
if(::StringFind(clicked_object,m_radio_buttons.NamePart(),0)<0)
|
|
return(false);
|
|
//--- Выйти, если (1) идентификаторы не совпадают или (2) элемент заблокирован
|
|
if(id!=CElementBase::Id() || CElementBase::IsLocked())
|
|
return(false);
|
|
//--- Выйти, если индекс совпадает
|
|
if(index==m_radio_buttons.SelectedButtonIndex())
|
|
return(true);
|
|
//--- Выбрать картинку
|
|
SelectPicture(index);
|
|
//--- Перерисовать элемент
|
|
m_radio_buttons.Update(true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Нажатие на левую кнопку |
|
|
//+------------------------------------------------------------------+
|
|
bool CPicturesSlider::OnClickLeftArrow(const string clicked_object,const int id,const int index)
|
|
{
|
|
//--- Выйдем, если нажатие было не на кнопке
|
|
if(::StringFind(clicked_object,m_left_arrow.NamePart(),0)<0)
|
|
return(false);
|
|
//--- Выйти, если (1) идентификаторы не совпадают или (2) элемент заблокирован
|
|
if(id!=CElementBase::Id() || index!=m_left_arrow.Index() || CElementBase::IsLocked())
|
|
return(false);
|
|
//--- Получим текущий индекс выделенной радио-кнопки
|
|
int selected_radio_button=m_radio_buttons.SelectedButtonIndex();
|
|
//--- Переключение картинки
|
|
SelectPicture(--selected_radio_button);
|
|
//--- Перерисовать радио-кнопки
|
|
m_radio_buttons.Update(true);
|
|
//--- Отправим сообщение об этом
|
|
::EventChartCustom(m_chart_id,ON_CLICK_BUTTON,CElementBase::Id(),CElementBase::Index(),"");
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Нажатие на правую кнопку |
|
|
//+------------------------------------------------------------------+
|
|
bool CPicturesSlider::OnClickRightArrow(const string clicked_object,const int id,const int index)
|
|
{
|
|
//--- Выйдем, если нажатие было не на кнопке
|
|
if(::StringFind(clicked_object,m_right_arrow.NamePart(),0)<0)
|
|
return(false);
|
|
//--- Выйти, если (1) идентификаторы не совпадают или (2) элемент заблокирован
|
|
if(id!=CElementBase::Id() || index!=m_right_arrow.Index() || CElementBase::IsLocked())
|
|
return(false);
|
|
//--- Получим текущий индекс выделенной радио-кнопки
|
|
int selected_radio_button=m_radio_buttons.SelectedButtonIndex();
|
|
//--- Переключение картинки
|
|
SelectPicture(++selected_radio_button);
|
|
//--- Перерисовать радио-кнопки
|
|
m_radio_buttons.Update(true);
|
|
//--- Отправим сообщение об этом
|
|
::EventChartCustom(m_chart_id,ON_CLICK_BUTTON,CElementBase::Id(),CElementBase::Index(),"");
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рисует элемент |
|
|
//+------------------------------------------------------------------+
|
|
void CPicturesSlider::Draw(void)
|
|
{
|
|
//--- Нарисовать фон
|
|
CElement::DrawBackground();
|
|
//--- Нарисовать рамку
|
|
CElement::DrawBorder();
|
|
}
|
|
//+------------------------------------------------------------------+
|