Создание графической библиотеки с нуля - страница 9

 
Aliaksandr Hryshyn:

Ещё:

Нажимаем на области окна правой мышкой, появляется меню. Сдвигаем мышку и нажимаем левой. В результате окно смещается.

Возможно. Что б вы понимали, я сам разрабатываю и сам тестирую, в результате, о некоторых багах просто ничего не знаю, пока в процессе работы случайно не столкнусь с ними. Я ж один все делаю...

 

Вот мой пример, в прикрепленном файле, там три окна наложенных друг на друга.

Создание одного окна с подокнами такое, только использование движка без дополнительного кода. Кроме обработки события нажатия на верхние кнопки.

cStrategy_viewer::cStrategy_viewer()
  {
   int width_type=126;
   int height_type=30;
   int width_object=170;
   int height_object=22;

   my_handler.md=GetPointer(this);
   int obj_types_count=(ER_NODE_TYPE_COUNT-1);
//Основное окно
   _main_window=new cV_object_rectangle();
   _main_window.Set_property_info(vop_position_x,10);
   _main_window.Set_property_info(vop_position_y,50);
   _main_window.Set_property_info(vop_size_x,width_type*obj_types_count);
   _main_window.Set_property_info(vop_size_y,700);
   _main_window.Set_property_info(vop_is_zorder_top_on_click,true);
   _main_window.Create(cV_object_base::global_parent_object);
//Заголовок
   cV_object_rectangle *caption=new cV_object_rectangle();
   caption.Set_property_info(vop_position_x,-1);
   caption.Set_property_info(vop_position_y,-1);
   caption.Set_property_info(vop_size_x,_main_window.Get_property(vop_size_x).data_long);
   caption.Set_property_info(vop_size_y,20);
   caption.Create(_main_window);
//Текст заголовка.Будет отображаться полное имя файла стратегии
   _caption_text=new cV_object_label();
   _caption_text.Set_property_info(vop_position_x,-1);
   _caption_text.Set_property_info(vop_position_y,-1);
   _caption_text.Set_property_info(vop_size_x,caption.Get_property(vop_size_x).data_long);
   _caption_text.Set_property_info(vop_text,"Стратегия ....");
   _caption_text.Set_property_info(vop_text_anchor,TA_CENTER);
   _caption_text.Set_property_info(vop_font_size,20);
   _caption_text.Set_property_info(vop_is_movable,true);
   _caption_text.Set_property_info(vop_moving_parent_index,2);
   _caption_text.Set_property_info(vop_is_position_fixing_parent_x,true);
   _caption_text.Set_property_info(vop_is_position_fixing_parent_y,true);
   _caption_text.Set_property_info(vop_position_fixing_parent_index_x,2);
   _caption_text.Set_property_info(vop_position_fixing_parent_index_y,2);
   _caption_text.Create(caption);
//Контейнер для типов объектов
   _object_types=new cV_object_base();
   _object_types.Set_property_info(vop_position_x,0);
   _object_types.Set_property_info(vop_position_y,20);
   _object_types.Set_property_info(vop_size_x,obj_types_count*width_type);
   _object_types.Set_property_info(vop_size_y,height_type);
   _object_types.Create(_main_window);
//Типы объектов
   cV_object_rectangle *obje_type;
   cV_object_label *obje_type_text;
   for(int i1=0; i1<obj_types_count; i1++)
     {
      obje_type=new cV_object_rectangle();
      obje_type.Set_property_info(vop_position_x,i1*width_type);
      obje_type.Set_property_info(vop_position_y,0);
      obje_type.Set_property_info(vop_size_x,width_type);
      obje_type.Set_property_info(vop_size_y,height_type);
      obje_type.Set_property_info(vop_border_line_width,3);
      obje_type.Set_property_info(vop_color_borders_mouse_moving,clrLightBlue);
      obje_type.Set_property_info(vop_color_borders_selected,clrYellow);
      obje_type.Set_property_info(vop_is_change_color_borders_on_mouse_move,true);
      obje_type.Set_property_info(vop_is_change_color_borders_on_select,true);
      obje_type.Set_property_info(vop_is_selected,false);
      obje_type.Set_property_info(vop_is_my_event_MOUSE_DOWN_UP_CLICK_LEFT,true);
      color clr=0;
      switch(eNode_type(i1+1))
        {
         case nt_function:
           {
            clr=clrDimGray;
            break;
           }
         case nt_indicator_data:
           {
            clr=clrNavy;
            break;
           }
         case nt_indicator:
           {
            clr=clrMaroon;
            break;
           }
         case nt_if:
           {
            clr=clrBlack;
            break;
           }
         case nt_const:
           {
            clr=clrGreen;
            break;
           }
         case nt_buffer:
           {
            clr=clrBlue;
            break;
           }
         case nt_node_top:
           {
            clr=clrIndigo;
            break;
           }
        }
      obje_type.Set_property_info(vop_color_borders,clr);
      obje_type.Set_property_info(vop_color_back,clr);
      obje_type.Create(_object_types);
      obje_type.Add_event_handler(GetPointer(my_handler));
      obje_type_text=new cV_object_label();
      obje_type_text.Set_property_info(vop_text,StringSubstr(EnumToString(eNode_type(i1+1)),3));
      obje_type_text.Set_property_info(vop_color_back,clrWhite);
      obje_type_text.Set_property_info(vop_size_x,width_type-1);
      obje_type_text.Set_property_info(vop_position_x,-3);
      obje_type_text.Set_property_info(vop_position_y,5-3);
      obje_type_text.Set_property_info(vop_text_anchor,TA_CENTER);
      obje_type_text.Set_property_info(vop_font_size,18);
      obje_type_text.Create(obje_type);
     }
   _object_types.Get_child(0).Set_property(vop_is_selected,true);
//Окно отображения объектов
   cV_object_rectangle *objects_viever=new cV_object_rectangle();
   objects_viever.Set_property_info(vop_position_x,0);
   objects_viever.Set_property_info(vop_position_y,height_type+_object_types.Get_property(vop_position_y).data_long);
   objects_viever.Set_property_info(vop_size_x,width_object);
   objects_viever.Set_property_info(vop_size_y,30*height_object);
   objects_viever.Create(_main_window);
//Контейнер объектов
   int functions_count=cRules::Get_object_count(nt_function);
   _objects=new cV_object_base();
   _objects.Set_property_info(vop_position_x,0);
   _objects.Set_property_info(vop_position_y,0);
   _objects.Set_property_info(vop_size_x,width_object);
   _objects.Set_property_info(vop_size_y,functions_count*height_object);
   _objects.Set_property_info(vop_color_back,clrOlive);
//_objects.Set_property_info(vop_is_position_fixing_parent_x,true);
//_objects.Set_property_info(vop_is_position_fixing_parent_y,true);
   _objects.Create(objects_viever);
//Объекты
   for(int i1=0; i1<functions_count; i1++)
     {
      cV_object_label *object=new cV_object_label();
      object.Set_property_info(vop_size_x,width_object-2);
      object.Set_property_info(vop_position_x,1);
      object.Set_property_info(vop_position_y,i1*height_object);
      object.Set_property_info(vop_color_back,clrWhite);
      object.Set_property_info(vop_text,cRules::Get_object_name(nt_function,i1));
      object.Set_property_info(vop_text_anchor,TA_LEFT);
      object.Set_property_info(vop_font_size,height_object-2);
      object.Create(_objects);
     }
  }

Обработка события нажатия на кнопки вверху:

void cStrategy_viewer::cMy_handler::On_event(sEvent &event)
  {
   cV_object_base *obj=GetPointer(event.object);
   switch(event.id)
     {
      case CHARTEVENT_CLICK_:
        {
         if(obj.Get_parent()==GetPointer(md._object_types))
           {
            obj.Set_property(vop_is_selected,true);
           }
         break;
        }
     }
  }

Кнопок несколько, а родителькое окно только одно

Файлы:
 
Реter Konow:

Был такой баг. Исправил. Само событие фиксируется в порядке, но баги возникают при разных изменениях, которые нельзя избежать при развитии кода. 

Да, всё непросто

Картинка с демки:


 
Просто в таком деле в перкую очередь надо хорошо прорабатывать события и управления окнами, остальное уже проще, хотя по остальному значительно больше работы.
 
Есть желающие сделать библиотеку визуальных элементов с нуля :) ?
 
Aliaksandr Hryshyn:
Просто в таком деле в перкую очередь надо хорошо прорабатывать события и управления окнами, остальное уже проще, хотя по остальному значительно больше работы.

Задел уже есть.

1: окна должны иметь кнопки закрытия и сворачивания (как минимум). 

2: окна должны перерисовываться поверх друг друга при нажатии.

3: окна должны перемещаться мышкой.

4. Окна должны "обнаруживаться" (попадать в фокус) на графике при движении курсора (событие pointed). 

5. Все элементы окон должны быть на общей "карте" окна и обнаруживатся при наведении мышки (событие pointed).

 

Самые простые элементы: 

1. Статичное, неизменное в размерах и несворачиваемое Окно.

2. Кнопка.

3. Чекбокс.

4. Радио-кнопка.

5. Вкладка.

6. Линия, рамка, разделитель, прямоугольник.


Элементы средней сложности:

1. Слайдеры.

2. Прогресс бары.

3. Поля ввода.

4. Поля с прокруткой.

5. Пункты простого списка.


Элементы высокой степени сложности.

1. Выпадающий список (очень сложный элемент).

2. Динамичное (растягиваемое) окно. Супер-сложно.


Всего имеется около 50-ти типов элементов управления. Каждый должен обладать общим и уникальным набором свойств поддерживаемым соответствующим функционалом движка. Свойств не менее 100, иначе,  работа элементов будет сильно ограничена. 

Простым формам и линиям много свойств не нужно, но чем сложнее элемент, тем их больше.
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
  • www.mql5.com
Все объекты, используемые в техническом анализе, имеют привязку на графиках по координатам цены и времени – трендовая линия, каналы, инструменты Фибоначчи и т.д.  Но есть ряд вспомогательных объектов, предназначенных для улучшения интерфейса, которые имеют привязку к видимой всегда части графика (основное окно графика или подокна индикаторов...
 

Блин! Забыл про таблицы! Там вообще джунгли...))))

И древовидный список, и всякие сворачиватели разных мастей...

 
Каждый интерактивный элемент управления имеет управляемый им параметр с набором из своих свойств. Например, кнопка - параметр типа bool (1 или 0), поле ввода имеет параметр типа string (строка), слайдер - range (диапазон)... поле ввода с кнопками имеет параметр со свойствами current_value, last_value, min, max, step, value_type и другие. Каждое свойство поддерживается функционалом.

Каждый интерактивный элемент (по хорошему) должен иметь 8 различный состояний, которые меняет на различных событиях. 

Например: neutral, neutral_pointed, activated_neutral, activated_pointed, neutral_highlighted, activated_highlighted, neutral_locked, activated_locked.

Каждое состояние продумано со своим набором значений свойств элемента и вступает в силу на своих событиях, которые фиксирует спец.функционал.
 
Реter Konow:

Блин! Забыл про таблицы! Там вообще джунгли...))))

И древовидный список, и всякие сворачиватели разных мастей...

В моём случае "джунгли" делаются не сложнее чем средне: окно отображения(видимая область таблицы), полноразмерное окно, в которое должны помещаться все ячейки, оно будет сдвигаться внутри основного окна, окна для строк и в них ячейки, плюс прокрутки(ползунок,ограниченный полосой). Ограничения по относительному расположению определяется свойствами. Только для ползунка надо перехватывать события перемещения объекта и уже корректировать позицию  "полноразмерного окна". Это всё делается виртуальными окнами, к нему надо прикрутить визуальную часть, без визуальной части будут окна для строк и полноразмерное окно. Ну и для редактируемой ячейки сделать поле ввода(это уже самому), всё остальное взаимодействие реализуется движком: будут поступать правильные события для каждой ячейки(события мыши, перерисовка, перемещения).... Такие возможности, есть ещё пару идей для увеличения быстродействия в случае когда окон очень много(большие списки,таблицы, несколько тысяч окон).

Причина обращения: