//+------------------------------------------------------------------+ //| Element.mqh | //| Copyright 2016, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "ElementBase.mqh" class CWindow; //+------------------------------------------------------------------+ //| Производный класс элемента управления | //+------------------------------------------------------------------+ class CElement : public CElementBase { protected: //--- Указатель на форму CWindow *m_wnd; //--- Указатель на главный элемент CElement *m_main; //--- Холст для рисования элемента CRectCanvas m_canvas; //--- Указатели на подключенные элементы CElement *m_elements[]; //--- Группы изображений struct EImagesGroup { //--- Массив изображений CImage m_image[]; //--- Отступы ярлыка int m_x_gap; int m_y_gap; //--- Выбранное для показа изображение в группе int m_selected_image; }; EImagesGroup m_images_group[]; //--- Отступы ярлыка int m_icon_x_gap; int m_icon_y_gap; //--- Цвет фона в разных состояниях color m_back_color; color m_back_color_hover; color m_back_color_locked; color m_back_color_pressed; //--- Цвет рамки в разных состояниях color m_border_color; color m_border_color_hover; color m_border_color_locked; color m_border_color_pressed; //--- Цвета текста в разных состояниях color m_label_color; color m_label_color_hover; color m_label_color_locked; color m_label_color_pressed; //--- Текст описания string m_label_text; //--- Отступы текстовой метки int m_label_x_gap; int m_label_y_gap; //--- Шрифт string m_font; int m_font_size; //--- Значение альфа-канала (прозрачность элемента) uchar m_alpha; //--- Текст всплывающей подсказки string m_tooltip_text; //--- Режим выравнивания текста bool m_is_center_text; //--- Приоритет на нажатие левой кнопки мыши long m_zorder; //--- public: CElement(void); ~CElement(void); //--- protected: //--- Создание холста для рисования bool CreateCanvas(const string name,const int x,const int y, const int x_size,const int y_size,ENUM_COLOR_FORMAT clr_format=COLOR_FORMAT_ARGB_NORMALIZE); //--- public: //--- Сохраняет и возвращает указатель на форму CWindow *WindowPointer(void) { return(::GetPointer(m_wnd)); } void WindowPointer(CWindow &object) { m_wnd=::GetPointer(object); } //--- Сохраняет и возвращает указатель на (1) главный элемент, // (2) возвращает указатель на холст элемента, (3) возвращает указатель на группу изображений CElement *MainPointer(void) { return(::GetPointer(m_main)); } void MainPointer(CElement &object) { m_main=::GetPointer(object); } CRectCanvas *CanvasPointer(void) { return(::GetPointer(m_canvas)); } //--- (1) Получение количества подключенных элементов, (2) освобождение массива подключенных элементов int ElementsTotal(void) const { return(::ArraySize(m_elements)); } void FreeElementsArray(void) { ::ArrayFree(m_elements); } //--- Возвращает указатель подключенного элемента по указанному индексу CElement *Element(const uint index); //--- Значение альфа-канала (прозрачность элемента) void Alpha(const uchar value) { m_alpha=value; } uchar Alpha(void) const { return(m_alpha); } //--- (1) Всплыващая подсказка, (2) режим показа всплывающей подсказки void Tooltip(const string text) { m_tooltip_text=text; } string Tooltip(void) const { return(m_tooltip_text); } void ShowTooltip(const bool state); //--- Цвет фона в разных состояниях void BackColor(const color clr) { m_back_color=clr; } color BackColor(void) const { return(m_back_color); } void BackColorHover(const color clr) { m_back_color_hover=clr; } color BackColorHover(void) const { return(m_back_color_hover); } void BackColorLocked(const color clr) { m_back_color_locked=clr; } color BackColorLocked(void) const { return(m_back_color_locked); } void BackColorPressed(const color clr) { m_back_color_pressed=clr; } color BackColorPressed(void) const { return(m_back_color_pressed); } //--- Цвет рамки в разных состояниях void BorderColor(const color clr) { m_border_color=clr; } color BorderColor(void) const { return(m_border_color); } void BorderColorHover(const color clr) { m_border_color_hover=clr; } color BorderColorHover(void) const { return(m_border_color_hover); } void BorderColorLocked(const color clr) { m_border_color_locked=clr; } color BorderColorLocked(void) const { return(m_border_color_locked); } void BorderColorPressed(const color clr) { m_border_color_pressed=clr; } color BorderColorPressed(void) const { return(m_border_color_pressed); } //--- Цвета текстовой метки в разных состояниях void LabelColor(const color clr) { m_label_color=clr; } color LabelColor(void) const { return(m_label_color); } void LabelColorHover(const color clr) { m_label_color_hover=clr; } color LabelColorHover(void) const { return(m_label_color_hover); } void LabelColorLocked(const color clr) { m_label_color_locked=clr; } color LabelColorLocked(void) const { return(m_label_color_locked); } void LabelColorPressed(const color clr) { m_label_color_pressed=clr; } color LabelColorPressed(void) const { return(m_label_color_pressed); } //--- Отступы ярлыка void IconXGap(const int x_gap) { m_icon_x_gap=x_gap; } int IconXGap(void) const { return(m_icon_x_gap); } void IconYGap(const int y_gap) { m_icon_y_gap=y_gap; } int IconYGap(void) const { return(m_icon_y_gap); } //--- (1) Текст описания поля ввода, (2) отступы текстовой метки void LabelText(const string text) { m_label_text=text; } string LabelText(void) const { return(m_label_text); } void LabelXGap(const int x_gap) { m_label_x_gap=x_gap; } int LabelXGap(void) const { return(m_label_x_gap); } void LabelYGap(const int y_gap) { m_label_y_gap=y_gap; } int LabelYGap(void) const { return(m_label_y_gap); } //--- (1) Шрифт и (2) размер шрифта void Font(const string font) { m_font=font; } string Font(void) const { return(m_font); } void FontSize(const int font_size) { m_font_size=font_size; } int FontSize(void) const { return(m_font_size); } //--- (1) Выравнивать текст по центру, (2) приоритет на нажатие левой кнопкой мыши void IsCenterText(const bool state) { m_is_center_text=state; } bool IsCenterText(void) const { return(m_is_center_text); } long Z_Order(void) const { return(m_zorder); } void Z_Order(const long z_order); //--- Блокировка элемента virtual void IsLocked(const bool state); //--- Доступность элемента virtual void IsAvailable(const bool state); //--- Отступ для картинок указанной группы int ImageGroupXGap(const uint index); void ImageGroupXGap(const uint index,const int x_gap); //--- Установка ярлыков для активного и заблокированного состояния void IconFile(const string file_path); void IconFile(const uint resource_index); string IconFile(bool resource_index_mode = false); void IconFileLocked(const string file_path); void IconFileLocked(const uint resource_index); string IconFileLocked(bool resource_index_mode = false); //--- Установка ярлыков для элемента в нажатом состоянии (доступен/заблокирован) void IconFilePressed(const string file_path); void IconFilePressed(const uint resource_index); string IconFilePressed(bool resource_index_mode = false); void IconFilePressedLocked(const string file_path); void IconFilePressedLocked(const uint resource_index); string IconFilePressedLocked(bool resource_index_mode = false); //--- Возвращает количество групп изображений uint ImagesGroupTotal(void) const { return(::ArraySize(m_images_group)); } //--- Возвращает количество изображений в указанной группе int ImagesTotal(const uint group_index); //--- Добавление группы изображений с массивом изображений void AddImagesGroup(const int x_gap,const int y_gap,const string &file_pathways[]); //--- Добавление группы изображений void AddImagesGroup(const int x_gap,const int y_gap); //--- Добавление изображения (путь к ресурсу) в указанную группу void AddImage(const uint group_index,const string file_path); //--- Добавление изображения (индекс к ресурсу) в указанную группу void AddImage(const uint group_index,const uint resource_index); //--- Установка/замена изображения (путь к ресурсу) void SetImage(const uint group_index,const uint image_index,const string file_path); //--- Установка/замена изображения (индекс к ресурсу) void SetImage(const uint group_index,const uint image_index,const uint resource_index); //--- Переключение изображения void ChangeImage(const uint group_index,const uint image_index); //--- Возвращает выбранное для показа изображение в указанной группе int SelectedImage(const uint group_index=0); //--- public: //--- Обработчик событий графика virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) {} //--- Таймер virtual void OnEventTimer(void) {} //--- Перемещение элемента virtual void Moving(const bool only_visible=true); //--- (1) Показ, (2) скрытие, (3) перемещение на верхний слой, (4) удаление virtual void Show(void); virtual void Hide(void); virtual void Reset(void); virtual void Delete(void); //--- (1) Установка, (2) сброс приоритетов на нажатие левой кнопки мыши virtual void SetZorders(void); virtual void ResetZorders(void); //--- Обновляет элемент для отображения последних изменений virtual void Update(const bool redraw=false); //--- Рисует элемент virtual void Draw(void) {} //--- protected: //--- Метод для добавления указателей на элементы-потомки в общий массив void AddToArray(CElement &object); //--- Проверить выход из диапазона групп картинок virtual bool CheckOutOfRange(const uint group_index,const uint image_index); //--- Проверка наличия указателя на главный элемент bool CheckMainPointer(void); //--- Расчёт абсолютных координат int CalculateX(const int x_gap); int CalculateY(const int y_gap); //--- Расчёт относительных координат от крайней точки формы int CalculateXGap(const int x); int CalculateYGap(const int y); //--- Рисует фон virtual void DrawBackground(void); //--- Рисует рамку virtual void DrawBorder(void); //--- Рисует картинку virtual void DrawImage(void); //--- Рисует текст virtual void DrawText(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CElement::CElement(void) : m_alpha(255), m_tooltip_text("\n"), m_back_color(clrNONE), m_back_color_hover(clrNONE), m_back_color_locked(clrNONE), m_back_color_pressed(clrNONE), m_border_color(clrNONE), m_border_color_hover(clrNONE), m_border_color_locked(clrNONE), m_border_color_pressed(clrNONE), m_icon_x_gap(WRONG_VALUE), m_icon_y_gap(WRONG_VALUE), m_label_text(""), m_label_x_gap(WRONG_VALUE), m_label_y_gap(WRONG_VALUE), m_label_color(clrNONE), m_label_color_hover(clrNONE), m_label_color_locked(clrNONE), m_label_color_pressed(clrNONE), m_font("Calibri"), m_font_size(8), m_is_center_text(false), m_zorder(WRONG_VALUE) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CElement::~CElement(void) { } //+------------------------------------------------------------------+ //| Создание холста для рисования элемента | //+------------------------------------------------------------------+ bool CElement::CreateCanvas(const string name,const int x,const int y, const int x_size,const int y_size,ENUM_COLOR_FORMAT clr_format=COLOR_FORMAT_ARGB_NORMALIZE) { //--- Корректировка размеров int xsize =(x_size<1)? 50 : x_size; int ysize =(y_size<1)? 20 : y_size; //--- Сбросить последнюю ошибку ::ResetLastError(); //--- Создание объекта if(!m_canvas.CreateBitmapLabel(m_chart_id,m_subwin,name,x,y,xsize,ysize,clr_format)) { ::Print(__FUNCTION__," > name: ",name); ::Print(__FUNCTION__," > Не удалось создать холст для рисования элемента ("+m_class_name+"): ",::GetLastError()); return(false); } //--- Сбросить последнюю ошибку ::ResetLastError(); //--- Получим указатель на базовый класс if(!m_canvas.Attach(m_chart_id,name,clr_format)) { ::Print(__FUNCTION__," > Не удалось присоединить холст для рисования к графику: ",::GetLastError()); return(false); } //--- Свойства ::ObjectSetString(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TOOLTIP,"\n"); ::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_CORNER,m_corner); ::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_SELECTABLE,false); //--- У всех элементов, кроме формы, приоритет больше, чем у главного элемента Z_Order((dynamic_cast(&this)!=NULL)? 0 : m_main.Z_Order()+1); //--- Координаты m_canvas.X(x); m_canvas.Y(y); //--- Размеры m_canvas.XSize(x_size); m_canvas.YSize(y_size); //--- Отступы от крайней точки m_canvas.XGap(CalculateXGap(x)); m_canvas.YGap(CalculateYGap(y)); return(true); } //+------------------------------------------------------------------+ //| Возвращает отступ для картинок из указанной группы | //+------------------------------------------------------------------+ int CElement::ImageGroupXGap(const uint index) { //--- Вернуть указатель объекта return(m_images_group[index].m_x_gap); } //+------------------------------------------------------------------+ //| Установка отступа для картинок из указанной группы | //+------------------------------------------------------------------+ void CElement::ImageGroupXGap(const uint index,const int x_gap) { m_images_group[index].m_x_gap=x_gap; } //+------------------------------------------------------------------+ //| Возвращает указатель подключенного элемента | //+------------------------------------------------------------------+ CElement *CElement::Element(const uint index) { uint array_size=::ArraySize(m_elements); //--- Проверка размера массива объектов if(array_size<1) { ::Print(__FUNCTION__," > В этом элементе ("+m_class_name+") нет элементов-потомков!"); return(NULL); } //--- Корректировка в случае выхода из диапазона uint i=(index>=array_size)? array_size-1 : index; //--- Вернуть указатель объекта return(::GetPointer(m_elements[i])); } //+------------------------------------------------------------------+ //| Установка показа всплывающей подсказки | //+------------------------------------------------------------------+ void CElement::ShowTooltip(const bool state) { if(state) ::ObjectSetString(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TOOLTIP,m_tooltip_text); else ::ObjectSetString(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TOOLTIP,"\n"); } //+------------------------------------------------------------------+ //| Приоритет на нажатие левой кнопкой мыши | //+------------------------------------------------------------------+ void CElement::Z_Order(const long z_order) { m_zorder=z_order; SetZorders(); } //+------------------------------------------------------------------+ //| Блокировка/снятие блокировки элемента | //+------------------------------------------------------------------+ void CElement::IsLocked(const bool state) { //--- Выйти, если уже установлено if(state==CElementBase::IsLocked()) return; //--- Сохранить состояние CElementBase::IsLocked(state); //--- Остальные элементы int elements_total=ElementsTotal(); for(int i=0; i=images_group_total) return(false); //--- Проверка индекса изображения uint images_total=::ArraySize(m_images_group[group_index].m_image); if(images_total<1 || image_index>=images_total) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| Возвращает количество изображений в указанной группе | //+------------------------------------------------------------------+ int CElement::ImagesTotal(const uint group_index) { //--- Проверка индекса группы uint images_group_total=::ArraySize(m_images_group); if(images_group_total<1 || group_index>=images_group_total) return(WRONG_VALUE); //--- Количество изображений return(::ArraySize(m_images_group[group_index].m_image)); } //+------------------------------------------------------------------+ //| Добавление группы изображений с массивом изображений | //+------------------------------------------------------------------+ void CElement::AddImagesGroup(const int x_gap,const int y_gap,const string &file_pathways[]) { //--- Получим размер массива групп изображений uint images_group_total=::ArraySize(m_images_group); //--- Добавим одну группу ::ArrayResize(m_images_group,images_group_total+1); //--- Установить отступы для изображений m_images_group[images_group_total].m_x_gap =x_gap; m_images_group[images_group_total].m_y_gap =y_gap; //--- Изображение по умолчанию m_images_group[images_group_total].m_selected_image=0; //--- Получим размер массива добавляемых изображений uint images_total=::ArraySize(file_pathways); //--- Добавим изображения в новую группу, если был передан не пустой массив for(uint i=0; i Добавить группу изображений можно с помощью методов CElement::AddImagesGroup()"); return; } //--- Предотвращение выхода из диапазона uint check_group_index=(group_index Добавить группу изображений можно с помощью методов CElement::AddImagesGroup()"); return; } //--- Предотвращение выхода из диапазона uint check_group_index=(group_index=images_group_total) return(WRONG_VALUE); //--- Выйти, если не одного изображения в указанной группе uint images_total=::ArraySize(m_images_group[group_index].m_image); if(images_total<1) return(WRONG_VALUE); //--- Вернуть выбранное для показа изображение return(m_images_group[group_index].m_selected_image); } //+------------------------------------------------------------------+ //| Проверка наличия указателя на главный элемент | //+------------------------------------------------------------------+ bool CElement::CheckMainPointer(void) { //--- Если нет указателя if(::CheckPointer(m_main)==POINTER_INVALID) { //--- Вывести сообщение в журнал терминала ::Print(__FUNCTION__, " > Перед созданием элемента... \n...нужно передать указатель на главный элемент: "+ ClassName()+"::MainPointer(CElementBase &object)"); //--- Прервать построение графического интерфейса приложения return(false); } //--- Сохранение указателя на форму m_wnd =m_main.WindowPointer(); //--- Если нет указателя на форму if(::CheckPointer(m_wnd)==POINTER_INVALID) { //--- Вывести сообщение в журнал терминала ::Print(__FUNCTION__, " > У элемента "+ClassName()+" нет указателя на форму!...\n"+ "...Элементы должны создаваться в порядке своей вложенности!"); //--- Прервать построение графического интерфейса приложения return(false); } //--- Сохранение указателя на курсор мыши m_mouse =m_main.MousePointer(); //--- Сохранение свойств //Print(__FUNCTION__, // " > dynamic_cast(&this) != NULL: ", dynamic_cast(&this) != NULL, // "; m_main.ClassName(): ", m_main.ClassName(), // "; m_wnd: ",m_wnd, // "; m_wnd.LastId(): ",m_wnd.LastId(), // "; m_main.LastId(): ",m_main.LastId()); m_id =m_wnd.LastId()+1; m_chart_id =m_wnd.ChartId(); m_subwin =m_wnd.SubwindowNumber(); m_corner =(ENUM_BASE_CORNER)m_wnd.Corner(); m_anchor =(ENUM_ANCHOR_POINT)m_wnd.Anchor(); //--- Отправить признак наличия указателя return(true); } //+------------------------------------------------------------------+ //| Расчёт абсолютной X-координаты | //+------------------------------------------------------------------+ int CElement::CalculateX(const int x_gap) { return((AnchorRightWindowSide())? m_main.X2()-x_gap : m_main.X()+x_gap); } //+------------------------------------------------------------------+ //| Расчёт абсолютной Y-координаты | //+------------------------------------------------------------------+ int CElement::CalculateY(const int y_gap) { return((AnchorBottomWindowSide())? m_main.Y2()-y_gap : m_main.Y()+y_gap); } //+------------------------------------------------------------------+ //| Расчёт относительной X-координаты от крайней точки формы | //+------------------------------------------------------------------+ int CElement::CalculateXGap(const int x) { return((AnchorRightWindowSide())? m_main.X2()-x : x-m_main.X()); } //+------------------------------------------------------------------+ //| Расчёт относительной Y-координаты от крайней точки формы | //+------------------------------------------------------------------+ int CElement::CalculateYGap(const int y) { return((AnchorBottomWindowSide())? m_main.Y2()-y : y-m_main.Y()); } //+------------------------------------------------------------------+ //| Рисует фон | //+------------------------------------------------------------------+ void CElement::DrawBackground(void) { m_canvas.Erase(::ColorToARGB(m_back_color,m_alpha)); } //+------------------------------------------------------------------+ //| Рисует рамку | //+------------------------------------------------------------------+ void CElement::DrawBorder(void) { //--- Координаты int x1=0,y1=0; int x2=(int)::ObjectGetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_XSIZE)-1; int y2=(int)::ObjectGetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_YSIZE)-1; //--- Рисуем прямоугольник без заливки m_canvas.Rectangle(x1,y1,x2,y2,::ColorToARGB(m_border_color,m_alpha)); } //+------------------------------------------------------------------+ //| Рисует картинку | //+------------------------------------------------------------------+ void CElement::DrawImage(void) { //--- Количество групп uint group_total=ImagesGroupTotal(); //--- Рисуем изображения for(uint g=0; g>1; y =m_y_size>>1; m_canvas.TextOut(x,y,m_label_text,::ColorToARGB(clr),TA_CENTER|TA_VCENTER); } else m_canvas.TextOut(x,y,m_label_text,::ColorToARGB(clr),TA_LEFT); } //+------------------------------------------------------------------+