//+------------------------------------------------------------------+ //| Scrolls.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "..\Element.mqh" #include "Button.mqh" //--- Список классов в файле для быстрого перехода (Alt+G) class CScroll; class CScrollV; class CScrollH; //+------------------------------------------------------------------+ //| Базовый класс для создания полосы прокрутки | //+------------------------------------------------------------------+ class CScroll : public CElement { protected: //--- Объекты для создания полосы прокрутки CButton m_button_inc; CButton m_button_dec; //--- Свойства общей площади полосы прокрутки int m_area_width; int m_area_length; //--- Картинки для кнопок string m_inc_file; string m_inc_file_locked; string m_inc_file_pressed; string m_dec_file; string m_dec_file_locked; string m_dec_file_pressed; //--- (1) Фокус на ползунке и (2) момент его пересечения границ bool m_thumb_focus; bool m_is_crossing_thumb_border; //--- Цвета ползунка в разных состояниях color m_thumb_color; color m_thumb_color_hover; color m_thumb_color_pressed; //--- (1) Общее количество пунктов и (2) видимое int m_items_total; int m_visible_items_total; //--- Координаты ползунка int m_thumb_x; int m_thumb_y; //--- (1) Ширина ползунка, (2) длина ползунка и (3) его минимальная длина int m_thumb_width; int m_thumb_length; int m_thumb_min_length; //--- (1) Размер шага ползунка и (2) кол-во шагов double m_thumb_step_size; double m_thumb_steps_total; //--- Переменные связанные с перемещением ползунка bool m_scroll_state; int m_thumb_size_fixing; int m_thumb_point_fixing; //--- Текущая позиция ползунка int m_current_pos; //--- Для определения области зажатия левой кнопки мыши ENUM_MOUSE_STATE m_clamping_area_mouse; //--- public: CScroll(void); ~CScroll(void); //--- Методы для создания полосы прокрутки bool CreateScroll(const int x_gap,const int y_gap, const int items_total,const int visible_items_total); //--- private: void InitializeProperties(const int x_gap,const int y_gap, const int items_total,const int visible_items_total); bool CreateCanvas(void); bool CreateScrollButton(CButton &button_obj,const int index); //--- public: //--- Возвращает указатели на кнопки полосы прокрутки CButton *GetIncButtonPointer(void) { return(::GetPointer(m_button_inc)); } CButton *GetDecButtonPointer(void) { return(::GetPointer(m_button_dec)); } //--- Ширина полосы прокрутки void ScrollWidth(const int width) { m_area_width=width; } int ScrollWidth(void) const { return(m_area_width); } //--- Установка картинок для кнопок void IncFile(const string file_path) { m_inc_file=file_path; } void IncFileLocked(const string file_path) { m_inc_file_locked=file_path; } void IncFilePressed(const string file_path) { m_inc_file_pressed=file_path; } void DecFile(const string file_path) { m_dec_file=file_path; } void DecFileLocked(const string file_path) { m_dec_file_locked=file_path; } void DecFilePressed(const string file_path) { m_dec_file_pressed=file_path; } //--- (1) Цвета ползунка и (2) рамки ползунка void ThumbColor(const color clr) { m_thumb_color=clr; } void ThumbColorHover(const color clr) { m_thumb_color_hover=clr; } void ThumbColorPressed(const color clr) { m_thumb_color_pressed=clr; } //--- Состояние кнопок bool ScrollIncState(void) const { return(m_button_inc.IsPressed()); } bool ScrollDecState(void) const { return(m_button_dec.IsPressed()); } //--- Состояние полосы прокрутки (свободно/в режиме перемещения ползунка) void State(const bool scroll_state) { m_scroll_state=scroll_state; } bool State(void) const { return(m_scroll_state); } //--- Текущая позиция ползунка void CurrentPos(const int pos) { m_current_pos=pos; } int CurrentPos(void) const { return(m_current_pos); } //--- Инициализация новыми значениями void Reinit(const int items_total,const int visible_items_total); //--- Изменение размера ползунка по новым условиям void ChangeThumbSize(const int items_total,const int visible_items_total); //--- Необходимость показа полосы прокрутки bool IsScroll(void) const { return(m_items_total>m_visible_items_total); } //--- protected: //--- Текущий цвет ползунка uint ThumbColorCurrent(void); //--- Проверка фокуса над ползунком bool CheckThumbFocus(const int x,const int y); //--- Определяет область зажатия левой кнопки мыши void CheckMouseButtonState(void); //--- Обнуление переменных void ZeroThumbVariables(void); //--- Расчёт длины ползунка полосы прокрутки bool CalculateThumbSize(void); //--- Расчёт границ ползунка полосы прокрутки void CalculateThumbBoundaries(int &x1,int &y1,int &x2,int &y2); //--- public: //--- Управление virtual void Show(void); virtual void Hide(void); virtual void Delete(void); //--- Рисует элемент virtual void Draw(void); //--- private: //--- Рисует фон virtual void DrawThumb(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CScroll::CScroll(void) : m_current_pos(0), m_area_width(15), m_area_length(0), m_inc_file(""), m_inc_file_locked(""), m_inc_file_pressed(""), m_dec_file(""), m_dec_file_locked(""), m_dec_file_pressed(""), m_thumb_focus(false), m_is_crossing_thumb_border(false), m_thumb_x(0), m_thumb_y(0), m_thumb_width(0), m_thumb_length(0), m_thumb_min_length(15), m_thumb_size_fixing(0), m_thumb_point_fixing(0), m_thumb_color(C'205,205,205'), m_thumb_color_hover(C'166,166,166'), m_thumb_color_pressed(C'96,96,96') { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CScroll::~CScroll(void) { } //+------------------------------------------------------------------+ //| Создаёт полосу прокрутки | //+------------------------------------------------------------------+ bool CScroll::CreateScroll(const int x_gap,const int y_gap,const int items_total,const int visible_items_total) { //--- Выйти, если нет указателя на главный элемент if(!CElement::CheckMainPointer()) return(false); //--- Выйти, если производится попытка использовать базовый класс полосы прокрутки if(CElementBase::ClassName()=="") { ::Print(__FUNCTION__," > Используйте производные классы полосы прокрутки (CScrollV или CScrollH)."); return(false); } //--- Инициализация свойств InitializeProperties(x_gap,y_gap,items_total,visible_items_total); //--- Создание элемента if(!CreateCanvas()) return(false); if(!CreateScrollButton(m_button_inc,0)) return(false); if(!CreateScrollButton(m_button_dec,1)) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| Инициализация свойств | //+------------------------------------------------------------------+ void CScroll::InitializeProperties(const int x_gap,const int y_gap, const int items_total,const int visible_items_total) { m_x =CElement::CalculateX(x_gap); m_y =CElement::CalculateY(y_gap); m_area_width =(CElementBase::ClassName()=="CScrollV")? CElementBase::XSize() : CElementBase::YSize(); m_area_length =(CElementBase::ClassName()=="CScrollV")? CElementBase::YSize() : CElementBase::XSize(); m_items_total =(items_total<1)? 1 : items_total; m_visible_items_total =(visible_items_total>0)? visible_items_total : 1; m_thumb_width =m_area_width; m_thumb_steps_total =(IsScroll())? m_items_total-m_visible_items_total : 1; m_back_color =(m_back_color!=clrNONE)? m_back_color : C'240,240,240'; //--- Отступы от крайней точки CElementBase::XGap(x_gap); CElementBase::YGap(y_gap); //--- Рассчитаем размер полосы прокрутки CalculateThumbSize(); } //+------------------------------------------------------------------+ //| Создаёт объект для рисования | //+------------------------------------------------------------------+ bool CScroll::CreateCanvas(void) { //--- Формирование имени объекта string name=CElementBase::ElementName((CElementBase::ClassName()=="CScrollV")? "scrollv" : "scrollh"); //--- Создание объекта if(!CElement::CreateCanvas(name,m_x,m_y,m_x_size,m_y_size)) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| Создаёт переключатель скролла вверх или влево | //+------------------------------------------------------------------+ bool CScroll::CreateScrollButton(CButton &button_obj,const int index) { //--- Сохраним указатель на главный элемент button_obj.MainPointer(this); //--- Координаты int x=0,y=0; //--- Файлы string file="",file_locked="",file_pressed=""; //--- Кнопка вверх или влево if(index==0) { //--- Установка свойств с учётом типа скролла if(CElementBase::ClassName()=="CScrollV") { file=(m_inc_file=="")? (string)RESOURCE_SCROLL_UP_BLACK : m_inc_file; file_locked=(m_inc_file_locked=="")? (string)RESOURCE_SCROLL_UP_BLACK : m_inc_file_locked; file_pressed=(m_inc_file_pressed=="")? (string)RESOURCE_SCROLL_UP_WHITE : m_inc_file_pressed; } else { file=(m_inc_file=="")? (string)RESOURCE_SCROLL_LEFT_BLACK : m_inc_file; file_locked=(m_inc_file_locked=="")? (string)RESOURCE_SCROLL_LEFT_BLACK : m_inc_file_locked; file_pressed=(m_inc_file_pressed=="")? (string)RESOURCE_SCROLL_LEFT_WHITE : m_inc_file_pressed; } //--- Индекс элемента button_obj.Index(m_index*2); } //--- Кнопка вниз или вправо else { //--- Установка свойств с учётом типа скролла if(CElementBase::ClassName()=="CScrollV") { x=0; y=m_thumb_width; file=(m_dec_file=="")? (string)RESOURCE_SCROLL_DOWN_BLACK : m_dec_file; file_locked=(m_dec_file_locked=="")? (string)RESOURCE_SCROLL_DOWN_BLACK : m_dec_file_locked; file_pressed=(m_dec_file_pressed=="")? (string)RESOURCE_SCROLL_DOWN_WHITE : m_dec_file_pressed; button_obj.AnchorBottomWindowSide(true); } else { x=m_thumb_width; y=0; file=(m_dec_file=="")? (string)RESOURCE_SCROLL_RIGHT_BLACK : m_dec_file; file_locked=(m_dec_file_locked=="")? (string)RESOURCE_SCROLL_RIGHT_BLACK : m_dec_file_locked; file_pressed=(m_dec_file_pressed=="")? (string)RESOURCE_SCROLL_RIGHT_WHITE : m_dec_file_pressed; button_obj.AnchorRightWindowSide(true); } //--- Индекс элемента button_obj.Index(m_index*2+1); } //--- Свойства button_obj.NamePart("scroll_button"); button_obj.Alpha(m_alpha); button_obj.XSize(15); button_obj.YSize(15); button_obj.IconXGap(0); button_obj.IconYGap(0); button_obj.TwoState(true); button_obj.BackColor(m_back_color); button_obj.BackColorHover(C'218,218,218'); button_obj.BackColorLocked(clrLightGray); button_obj.BackColorPressed(m_thumb_color_pressed); button_obj.BorderColor(m_back_color); button_obj.BorderColorHover(C'218,218,218'); button_obj.BorderColorLocked(clrLightGray); button_obj.BorderColorPressed(m_thumb_color_pressed); button_obj.IconFile((uint)file); button_obj.IconFileLocked((uint)file_locked); button_obj.CElement::IconFilePressed((uint)file_pressed); button_obj.CElement::IconFilePressedLocked((uint)file_locked); button_obj.IsDropdown(CElementBase::IsDropdown()); //--- Создадим элемент управления if(!button_obj.CreateButton("",x,y)) return(false); //--- Добавить элемент в массив CElement::AddToArray(button_obj); return(true); } //+------------------------------------------------------------------+ //| Текущий цвет ползунка | //+------------------------------------------------------------------+ uint CScroll::ThumbColorCurrent(void) { //--- Определим цвет ползунка color clr=(m_scroll_state)? m_thumb_color_pressed : m_thumb_color; //--- Если курсор мыши в зоне ползунка полосы прокрутки if(m_thumb_focus) { //--- Если левая кнопка мыши отжата if(m_clamping_area_mouse==NOT_PRESSED) clr=m_thumb_color_hover; //--- Левая кнопка мыши нажата на ползунке else if(m_clamping_area_mouse==PRESSED_INSIDE) clr=m_thumb_color_pressed; } //--- Если курсор вне зоны полосы прокрутки else { //--- Левая кнопка мыши отжата if(m_clamping_area_mouse==NOT_PRESSED) clr=m_thumb_color; } //--- return(::ColorToARGB(clr,m_alpha)); } //+------------------------------------------------------------------+ //| Проверка фокуса над ползунком | //+------------------------------------------------------------------+ bool CScroll::CheckThumbFocus(const int x,const int y) { //--- Проверка фокуса над ползунком if(CElementBase::ClassName()=="CScrollV") { m_thumb_focus=(x>m_thumb_x && xm_thumb_y && ym_thumb_x && xm_thumb_y && y0) ? m_thumb_y : m_thumb_width; x2 =x1+m_thumb_width; y2 =y1+m_thumb_length; } else { x1 =(m_thumb_x>0) ? m_thumb_x : m_thumb_width; y1 =0; x2 =x1+m_thumb_length; y2 =y1+m_thumb_width; } } //+------------------------------------------------------------------+ //| Инициализация новыми значениями | //+------------------------------------------------------------------+ void CScroll::Reinit(const int items_total,const int visible_items_total) { m_items_total =(items_total>0)? items_total : 1; m_visible_items_total =(visible_items_total>items_total)? items_total : visible_items_total; m_thumb_steps_total =m_items_total-m_visible_items_total+1; } //+------------------------------------------------------------------+ //| Показывает элемент | //+------------------------------------------------------------------+ void CScroll::Show(void) { //--- Выйти, если (1) элемент уже видим или (2) его не нужно показывать if(CElementBase::IsVisible() || !IsScroll()) return; //--- Состояние видимости CElementBase::IsVisible(true); //--- Обновить положение объектов Moving(); //--- Показать объекты ::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS); m_button_inc.Show(); m_button_dec.Show(); } //+------------------------------------------------------------------+ //| Скрывает элемент | //+------------------------------------------------------------------+ void CScroll::Hide(void) { ::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS); m_button_inc.Hide(); m_button_dec.Hide(); //--- Состояние видимости CElementBase::IsVisible(false); } //+------------------------------------------------------------------+ //| Удаление | //+------------------------------------------------------------------+ void CScroll::Delete(void) { //--- Удаление объектов m_canvas.Destroy(); //--- Инициализация переменных значениями по умолчанию m_thumb_x=0; m_thumb_y=0; CurrentPos(0); CElementBase::IsVisible(true); } //+------------------------------------------------------------------+ //| Рисует элемент | //+------------------------------------------------------------------+ void CScroll::Draw(void) { //--- Нарисовать фон CElement::DrawBackground(); //--- Нарисовать ползунок DrawThumb(); } //+------------------------------------------------------------------+ //| Рисует ползунок полосы прокрутки | //+------------------------------------------------------------------+ void CScroll::DrawThumb(void) { //--- Координаты int x1=0,y1=0,x2=0,y2=0; //--- Расчёт границ ползунка CalculateThumbBoundaries(x1,y1,x2,y2); //--- Сохраним координаты ползунка (левый верхний угол) m_thumb_x=x1; m_thumb_y=y1; //--- Нарисовать прямоугольник с заливкой m_canvas.FillRectangle(x1,y1,x2-1,y2-1,ThumbColorCurrent()); } //+------------------------------------------------------------------+ //| Класс для управления вертикальной полосой прокрутки | //+------------------------------------------------------------------+ class CScrollV : public CScroll { public: CScrollV(void); ~CScrollV(void); //--- Управление ползунком bool ScrollBarControl(void); //--- Перемещает ползунок на указанную позицию void MovingThumb(const int pos=WRONG_VALUE); //--- Установить новую координату для полосы прокрутки void XDistance(const int x); //--- Изменить длину полосы прокрутки void ChangeYSize(const int height); //--- Обработка нажатия на кнопках полосы прокрутки bool OnClickScrollInc(const int id=WRONG_VALUE,const int index=WRONG_VALUE); bool OnClickScrollDec(const int id=WRONG_VALUE,const int index=WRONG_VALUE); //--- private: //--- Процесс перемещения ползунка bool OnDragThumb(const int y); //--- Обновление положения ползунка void UpdateThumb(const int new_y_point); //--- Расчёт координаты Y ползунка void CalculateThumbY(void); //--- Корректирует номер позиции ползунка void CalculateThumbPos(void); //--- Быстрая перерисовка ползунка полосы прокрутки void RedrawThumb(const int y); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CScrollV::CScrollV(void) { //--- Сохраним имя класса элемента в базовом классе CElementBase::ClassName(CLASS_NAME); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CScrollV::~CScrollV(void) { } //+------------------------------------------------------------------+ //| Управление ползунком | //+------------------------------------------------------------------+ bool CScrollV::ScrollBarControl(void) { //--- Выйти, если (1) нет указателя на главный элемент или (2) элемент скрыт if(!CElement::CheckMainPointer() || !CElementBase::IsVisible()) return(false); //--- Выйти, если родитель отключен другим элементом if(!m_main.CElementBase::IsAvailable()) return(false); //--- Проверка фокуса над ползунком int x =m_mouse.RelativeX(m_canvas); int y =m_mouse.RelativeY(m_canvas); CheckThumbFocus(x,y); //--- Проверим и запомним состояние кнопки мыши CScroll::CheckMouseButtonState(); //--- Если управление передано полосе прокрутки, определим положение ползунка if(CScroll::State()) { //--- Если ползунок переместили if(OnDragThumb(y)) { //--- Изменяет номер позиции ползунка CalculateThumbPos(); return(true); } } //--- return(false); } //+------------------------------------------------------------------+ //| Перемещает ползунок на указанную позицию | //+------------------------------------------------------------------+ void CScrollV::MovingThumb(const int pos=WRONG_VALUE) { //--- Выйти, если полоса прокрутки не нужна if(!IsScroll()) return; //--- Для проверки позиции ползунка uint check_pos=0; //--- Скорректируем позицию в случае выхода из диапазона if(pos<0 || pos>m_items_total-m_visible_items_total) check_pos=m_items_total-m_visible_items_total; else check_pos=pos; //--- Запомним позицию ползунка CScroll::CurrentPos(check_pos); //--- Расчёт и установка координаты Y ползунка полосы прокрутки CalculateThumbY(); } //+------------------------------------------------------------------+ //| Расчёт и установка координаты Y ползунка полосы прокрутки | //+------------------------------------------------------------------+ void CScrollV::CalculateThumbY(void) { //--- Выйти, если нет указателя на главный элемент if(!CElement::CheckMainPointer()) return; //--- Определим текущую координату Y ползунка int scroll_thumb_y=int(m_thumb_width+(CurrentPos()*m_thumb_step_size)); //--- Если выходим за пределы рабочей области вверх if(scroll_thumb_y<=m_thumb_width) scroll_thumb_y=m_thumb_width; //--- Если выходим за пределы рабочей области вниз if(scroll_thumb_y+m_thumb_length>=m_y_size-m_thumb_width || CScroll::CurrentPos()>=m_thumb_steps_total-1) { scroll_thumb_y=int(m_y_size-m_thumb_width-m_thumb_length); } //--- Обновим координату и отступ по оси Y m_thumb_y=scroll_thumb_y; } //+------------------------------------------------------------------+ //| Изменение координаты X элемента | //+------------------------------------------------------------------+ void CScrollV::XDistance(const int x) { //--- Выйти, если нет указателя на главный элемент if(!CElement::CheckMainPointer()) return; //--- Обновим координату X элемента... CElementBase::X(CElement::CalculateX(x)); CElementBase::XGap(x); m_canvas.X(x); //--- Установим координату и отступ ::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_XDISTANCE,x); m_canvas.XGap(x); //--- Переместить объекты Moving(); } //+------------------------------------------------------------------+ //| Изменить длину полосы прокрутки | //+------------------------------------------------------------------+ void CScrollV::ChangeYSize(const int height) { //--- Координаты и размеры int y=0,y_size=0; //--- Изменить ширину элемента и фона CElementBase::YSize(height); m_canvas.YSize(height); m_canvas.Resize(m_x_size,height); //--- Скорректировать положение кнопки декремента m_button_dec.Moving(); //--- Рассчитаем и установим размеры объектов полосы прокрутки CalculateThumbSize(); //--- Корректировка положения ползунка if(m_thumb_y+m_thumb_length>=m_y_size-m_thumb_length || m_thumb_y0) CScroll::m_current_pos--; //--- Расчёт координты Y полосы прокрутки CalculateThumbY(); //--- Отожмём кнопку m_button_inc.IsPressed(false); return(true); } //+------------------------------------------------------------------+ //| Обработка нажатия на кнопке вниз/вправо | //+------------------------------------------------------------------+ bool CScrollV::OnClickScrollDec(const int id=WRONG_VALUE,const int index=WRONG_VALUE) { //--- Проверить идентификатор и индекс элемента, если был внешний вызов uint check_id =(id!=WRONG_VALUE)? id : CElementBase::Id(); uint check_index =(index!=WRONG_VALUE)? index : CElementBase::Index(); //--- Выйти, если значения не совпадают if(check_id!=m_button_dec.Id() || check_index!=m_button_dec.Index()) return(false); //--- Выйдем, если (1) сейчас активен или (2) кол-во шагов неопределено if(CScroll::State() || m_thumb_steps_total<1) return(false); //--- Увеличим номер позиции полосы прокрутки if(CScroll::CurrentPos()0) { //--- Рассчитаем координату Y new_y_point=y+m_thumb_size_fixing; //--- Обновим положение ползунка UpdateThumb(new_y_point); return(true); } //--- Если в нажатом состоянии прошли порог вверх if(y-m_thumb_point_fixing<0) { //--- Рассчитаем координату Y new_y_point=y-::fabs(m_thumb_size_fixing); //--- Обновим положение ползунка UpdateThumb(new_y_point); return(true); } //--- return(false); } //+------------------------------------------------------------------+ //| Обновление положения ползунка | //+------------------------------------------------------------------+ void CScrollV::UpdateThumb(const int new_y_point) { int y=new_y_point; //--- Обнуление точки фиксации m_thumb_point_fixing=0; //--- Проверка на выход из рабочей области вниз и корректировка значений if(new_y_point>m_y_size-m_thumb_width-m_thumb_length) { y=m_y_size-m_thumb_width-m_thumb_length; CScroll::CurrentPos(int(m_thumb_steps_total-1)); } //--- Проверка на выход из рабочей области вверх и корректировка значений if(new_y_point<=m_thumb_width) { y=m_thumb_width; CScroll::CurrentPos(0); } //--- Текущие координаты RedrawThumb(y); } //+------------------------------------------------------------------+ //| Корректирует номер позиции ползунка | //+------------------------------------------------------------------+ void CScrollV::CalculateThumbPos(void) { //--- Выйти, если шаг равен нулю if(m_thumb_step_size==0) return; //--- Корректирует номер позиции полосы прокрутки CScroll::CurrentPos(int((m_thumb_y-m_thumb_width+1)/m_thumb_step_size)); //--- Проверка на выход из рабочей области вниз/вверх if(m_thumb_y+m_thumb_length>=m_y_size-m_thumb_width) CScroll::CurrentPos(int(m_thumb_steps_total-1)); if(m_thumb_y<=m_thumb_width) CScroll::CurrentPos(0); } //+------------------------------------------------------------------+ //| Быстрая перерисовка ползунка полосы прокрутки | //+------------------------------------------------------------------+ void CScrollV::RedrawThumb(const int y) { //--- Текущие координаты int x1=0,y1=0,x2=0,y2=0; CalculateThumbBoundaries(x1,y1,x2,y2); //--- Стереть текущее положение ползунка m_canvas.FillRectangle(x1,y1,x2-1,y2-1,m_back_color); //--- Обновим координаты m_thumb_y=y; y2=y+m_thumb_length; //--- Нарисовать новое положение ползунка m_canvas.FillRectangle(x1,y1,x2-1,y2-1,m_thumb_color_pressed); } //+------------------------------------------------------------------+ //| Класс для управления горизонтальной полосой прокрутки | //+------------------------------------------------------------------+ class CScrollH : public CScroll { public: CScrollH(void); ~CScrollH(void); //--- Управление ползунком bool ScrollBarControl(void); //--- Перемещает ползунок на указанную позицию void MovingThumb(const int pos=WRONG_VALUE); //--- Установить новую координату для полосы прокрутки void YDistance(const int y); //--- Изменить длину полосы прокрутки void ChangeXSize(const int width); //--- Обработка нажатия на кнопках полосы прокрутки bool OnClickScrollInc(const int id=WRONG_VALUE,const int index=WRONG_VALUE); bool OnClickScrollDec(const int id=WRONG_VALUE,const int index=WRONG_VALUE); //--- private: //--- Перемещение ползунка bool OnDragThumb(const int x); //--- Обновление положения ползунка void UpdateThumb(const int new_x_point); //--- Расчёт координаты X ползунка void CalculateThumbX(void); //--- Корректирует номер позиции ползунка void CalculateThumbPos(void); //--- Быстрая перерисовка ползунка полосы прокрутки void RedrawThumb(const int x); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CScrollH::CScrollH(void) { //--- Сохраним имя класса элемента в базовом классе CElementBase::ClassName(CLASS_NAME); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CScrollH::~CScrollH(void) { } //+------------------------------------------------------------------+ //| Управление скроллом | //+------------------------------------------------------------------+ bool CScrollH::ScrollBarControl(void) { //--- Выйти, если (1) нет указателя на главный элемент или (2) элемент скрыт if(!CElement::CheckMainPointer() || !CElementBase::IsVisible()) return(false); //--- Выйти, если родитель отключен другим элементом if(!m_main.CElementBase::IsAvailable()) return(false); //--- Проверка фокуса над ползунком int x=m_mouse.RelativeX(m_canvas); int y=m_mouse.RelativeY(m_canvas); CheckThumbFocus(x,y); //--- Проверим и запомним состояние кнопки мыши CScroll::CheckMouseButtonState(); //--- Если управление передано полосе прокрутки, определим положение ползунка if(CScroll::State()) { //--- Если ползунок переместили if(OnDragThumb(x)) { //--- Изменяет номер позиции ползунка CalculateThumbPos(); return(true); } } return(false); } //+------------------------------------------------------------------+ //| Перемещает ползунок на указанную позицию | //+------------------------------------------------------------------+ void CScrollH::MovingThumb(const int pos=WRONG_VALUE) { //--- Выйти, если полоса прокрутки не нужна if(!IsScroll()) return; //--- Для проверки позиции ползунка uint check_pos=0; //--- Скорректируем позицию в случае выхода из диапазона if(pos<0 || pos>m_items_total-m_visible_items_total) check_pos=m_items_total-m_visible_items_total; else check_pos=pos; //--- Запомним позицию ползунка CScroll::CurrentPos(check_pos); //--- Расчёт и установка координаты Y ползунка полосы прокрутки CalculateThumbX(); } //+------------------------------------------------------------------+ //| Расчёт координаты X ползунка | //+------------------------------------------------------------------+ void CScrollH::CalculateThumbX(void) { //--- Определим текущую координату X ползунка double scroll_thumb_x=m_thumb_width+(CurrentPos()*m_thumb_step_size); //--- Если выходим за пределы рабочей области влево if(scroll_thumb_x<=m_thumb_width) { scroll_thumb_x=m_thumb_width; } //--- Если выходим за пределы рабочей области вправо if(scroll_thumb_x+m_thumb_length>=m_x_size-m_thumb_width || CScroll::CurrentPos()>=m_thumb_steps_total-1) { scroll_thumb_x=int(m_x_size-m_thumb_width-m_thumb_length); } //--- Обновим координату и отступ по оси X m_thumb_x=(int)scroll_thumb_x; } //+------------------------------------------------------------------+ //| Изменение координаты Y элемента | //+------------------------------------------------------------------+ void CScrollH::YDistance(const int y) { //--- Выйти, если нет указателя на главный элемент if(!CElement::CheckMainPointer()) return; //--- Обновим координату Y элемента... CElementBase::Y(CElement::CalculateY(y)); CElementBase::YGap(y); //--- ...и всех объектов полосы прокрутки m_canvas.Y(y); m_thumb_y=y; //--- Установим координату объектам ::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_YDISTANCE,y); //--- Обновим отступы у всех объектов элемента int y_gap=CElement::CalculateYGap(y); m_canvas.YGap(CElement::CalculateYGap(y)); } //+------------------------------------------------------------------+ //| Изменить длину полосы прокрутки | //+------------------------------------------------------------------+ void CScrollH::ChangeXSize(const int width) { //--- Координаты и размеры int x=0,x_size=width-1; //--- Изменить ширину элемента и фона CElementBase::XSize(x_size); m_canvas.XSize(x_size); m_canvas.Resize(x_size,m_y_size); //--- Скорректировать положение кнопки декремента m_button_dec.Moving(); //--- Рассчитаем и установим размеры объектов полосы прокрутки CalculateThumbSize(); //--- Корректировка положения ползунка if(m_thumb_x+m_thumb_length>=m_x_size-m_thumb_length || m_thumb_x0) CScroll::m_current_pos--; //--- Расчёт координты X полосы прокрутки CalculateThumbX(); //--- Отожмём кнопку m_button_inc.IsPressed(false); return(true); } //+------------------------------------------------------------------+ //| Нажатие на переключателе вправо | //+------------------------------------------------------------------+ bool CScrollH::OnClickScrollDec(const int id=WRONG_VALUE,const int index=WRONG_VALUE) { //--- Проверить идентификатор и индекс элемента, если был внешний вызов uint check_id =(id!=WRONG_VALUE)? id : CElementBase::Id(); uint check_index =(index!=WRONG_VALUE)? index : CElementBase::Index(); //--- Выйти, если значения не совпадают if(check_id!=m_button_inc.Id() || check_index!=m_button_dec.Index()) return(false); //--- Выйдем, если (1) сейчас активен или (2) кол-во шагов неопределено if(CScroll::State() || m_thumb_steps_total<1) return(false); //--- Увеличим номер позиции полосы прокрутки if(CScroll::CurrentPos()0) { //--- Рассчитаем координату X new_x_point=x+CScroll::m_thumb_size_fixing; //--- Обновление положения полосы прокрутки UpdateThumb(new_x_point); return(true); } //--- Если в нажатом состоянии прошли порог влево if(x-CScroll::m_thumb_point_fixing<0) { //--- Рассчитаем координату X new_x_point=x-::fabs(CScroll::m_thumb_size_fixing); //--- Обновление положения полосы прокрутки UpdateThumb(new_x_point); return(true); } //--- return(false); } //+------------------------------------------------------------------+ //| Обновление положения полосы прокрутки | //+------------------------------------------------------------------+ void CScrollH::UpdateThumb(const int new_x_point) { int x=new_x_point; //--- Обнуление точки фиксации CScroll::m_thumb_point_fixing=0; //--- Проверка на выход из рабочей области вправо и корректировка значений if(new_x_point>m_x_size-m_thumb_width-m_thumb_length) { x=m_x_size-m_thumb_width-m_thumb_length; CScroll::CurrentPos(0); } //--- Проверка на выход из рабочей области влево и корректировка значений if(new_x_point<=m_thumb_width) { x=m_thumb_width; CScroll::CurrentPos(int(m_thumb_steps_total)); } //--- Текущие координаты RedrawThumb(x); } //+------------------------------------------------------------------+ //| Корректирует номер позиции ползунка | //+------------------------------------------------------------------+ void CScrollH::CalculateThumbPos(void) { //--- Выйти, если шаг равен нулю if(CScroll::m_thumb_step_size==0) return; //--- Корректирует номер позиции полосы прокрутки double pos=(m_thumb_x-m_thumb_width)/m_thumb_step_size; CScroll::CurrentPos((int)::MathCeil(pos)); //--- Проверка на выход из рабочей области влево/вправо if(m_thumb_x+m_thumb_length>=m_x_size-m_thumb_width-1) CScroll::CurrentPos(int(m_thumb_steps_total-1)); if(m_thumb_x