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

 
Как продвигается библиотека?
 
Реter Konow:
Как продвигается библиотека?

все более чем хорошо.

 

Тоже заморочился делать графическую библиотеку, только с необходимыми мне элементами.

Главная фишка библиотеки в его оконном движке:

  • не зависит от графической части, можно сказать, виртуальные окна без единой функции для работы с графикой, даже абсолютно окна будут корректно работать(события,свойства)
  • задаются множества свойств для окна, которые влияют на его поведение, зависимые свойства этого окна и других

   cV_object_base::Init(my_handler);
   cV_object_rectangle *app_00=new cV_object_rectangle();
   cV_object_rectangle *app_0=new cV_object_rectangle();
   cV_object_rectangle *app_1=new cV_object_rectangle();

   cV_object_label *lb1=new cV_object_label();
   app_00.Create(cV_object_base::global_parent_object);
   app_00.Set_property(vop_size_x,800);
   app_00.Set_property(vop_size_y,500);
   app_00.Set_property(vop_color_back,clrDarkGreen);

   app_0.Create(app_00,"AAA");

   app_00.Set_property(vop_is_position_fixing_parent_x,true);
   app_00.Set_property(vop_is_position_fixing_parent_y,true);

   app_1.Create(app_00);
   app_0.Set_property(vop_is_zorder_top_on_click,true);
   app_0.Set_property(vop_is_position_fixing_parent_x,true);
   app_0.Set_property(vop_is_position_fixing_parent_y,true);
   app_1.Set_property(vop_is_zorder_top_on_click,true);

   app_0.Set_property(vop_size_x,1000);
   app_0.Set_property(vop_size_y,300);
   app_0.Set_property(vop_position_x,100);
   app_0.Set_property(vop_position_y,100);
   app_0.Set_property(vop_color_back,clrDarkBlue);
   app_0.Set_property(vop_is_movable,true);
   app_0.Set_property(vop_is_selected_multi,false);

   lb1.Create(app_0,"E_hallo_world_E");
   lb1.Set_property(vop_is_movable,true);
   lb1.Set_property(vop_color_back_selected,clrDarkTurquoise);
   lb1.Set_property(vop_is_change_color_back_on_select,true);
   lb1.Set_property(vop_is_zorder_top_on_click,true);

   app_1.Set_property(vop_size_x,300);
   app_1.Set_property(vop_size_y,500);
   app_1.Set_property(vop_position_x,200);
   app_1.Set_property(vop_position_y,200);
   app_1.Set_property(vop_is_movable,true);

   cV_object_rectangle *app_2;
   cV_object_rectangle *app_3;
   for(int i1=0; i1<4; i1++)
     {
      app_2=new cV_object_rectangle();
      app_3=new cV_object_rectangle();
      app_2.Create(app_0,ShortToString(ushort('A'+i1)));
      app_3.Create(app_1);

      app_2.Set_property(vop_size_x,100);
      app_2.Set_property(vop_size_y,75);
      app_3.Set_property(vop_size_x,75);
      app_3.Set_property(vop_size_y,100);

      app_2.Set_property(vop_position_x,i1*20);
      app_2.Set_property(vop_position_y,i1*40);
      app_3.Set_property(vop_position_x,i1*20);
      app_3.Set_property(vop_position_y,i1*40);

      app_2.Set_property(vop_color_back,clrDarkGray);
      app_3.Set_property(vop_color_back,clrLightGoldenrod);

      app_2.Set_property(vop_is_movable,true);
      app_2.Set_property(vop_is_zorder_top_on_click,true);
      app_3.Set_property(vop_is_movable,true);

      app_3.Set_property(vop_is_change_color_back_on_select,true);
      app_3.Set_property(vop_color_back_selected,clrRed);

      app_2.Set_property(vop_color_back_selected,clrDarkTurquoise);
      app_2.Set_property(vop_is_change_color_back_on_select,true);
     }
   app_3.Set_property(vop_moving_parent_index,1);
   app_3.Set_property(vop_position_x,150);
   app_3.Set_property(vop_size_y,150);

   app_2.Set_property(vop_moving_parent_index,2);
   app_2.Set_property(vop_position_x,150);
   app_2.Set_property(vop_size_y,150);

   app_2.Set_property(vop_color_borders,clrDarkTurquoise);
   app_3.Set_property(vop_color_borders,clrDarkTurquoise);

   app_2.Set_property(vop_is_change_color_back_on_mouse_move,true);
   app_3.Set_property(vop_is_change_color_back_on_mouse_move,true);
   app_2.Set_property(vop_is_change_color_borders_on_mouse_move,true);
   app_3.Set_property(vop_is_change_color_borders_on_mouse_move,true);
   app_3.Set_property(vop_is_selected,true);


  • в качестве графики можно использовать как стандартные объекты, так и канвас, и  DirectX, тут как душе угодно
  • окна движка являются кирпичиками для построения графических элементов
  • использование разных оптимизаций для быстродействия(исключение лишних вызовов графических системных функций, также и исключение из прорисовки невидимых окошек)
  • простота в создании нового графического элемента, как реализации графического оформления, так и создание структуры дочерних элементов/окон. Все события и просчёт зависимых свойств будут происходит на уровне движка, он не различает пользовательские графические элементы, работает только на уровне базовых окон

Создание и удаление  стандартного объекта OBJ_RECTANGLE_LABEL , проще некуда

bool cV_object_rectangle::_Create_resource()
  {
   if(!ObjectCreate(0,visual_object_name,OBJ_RECTANGLE_LABEL,0,0,0))
     {
      cLng_add_user(lng_id,8,EnumToString(OBJ_RECTANGLE_LABEL),"");
      return false;
     }
   return true;
  }

bool cV_object_rectangle::_Delete_resource()
  {
   ObjectDelete(0,visual_object_name);
   return true;
  }

Тут реализуем метод для изменения свойств стандартного объекта OBJ_RECTANGLE_LABEL, шуршание по справке и использование интересующих свойств

bool cV_object_rectangle::_Set_property(eV_object_property property,sV_property_value &property_value)
  {
   _is_redraw_object=true;
   switch(property)
     {
      case vop_s_is_hidden:
        {
         if(property_value.data_long)
           {
            ObjectSetInteger(0,visual_object_name,OBJPROP_XSIZE,0);
            ObjectSetInteger(0,visual_object_name,OBJPROP_YSIZE,0);
            ObjectSetInteger(0,visual_object_name,OBJPROP_XDISTANCE,-20);
            ObjectSetInteger(0,visual_object_name,OBJPROP_YDISTANCE,-20);
           }
         else
           {
            ObjectSetInteger(0,visual_object_name,OBJPROP_XSIZE,_property_values[vop_s_size_real_x].data_long);
            ObjectSetInteger(0,visual_object_name,OBJPROP_YSIZE,_property_values[vop_s_size_real_y].data_long);
            ObjectSetInteger(0,visual_object_name,OBJPROP_XDISTANCE,_property_values[vop_s_position_real_x].data_long);
            ObjectSetInteger(0,visual_object_name,OBJPROP_YDISTANCE,_property_values[vop_s_position_real_y].data_long);
           }
         break;
        }
      case vop_s_color_back:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_BGCOLOR,property_value.data_long);
         break;
        }
      case vop_border_type:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_BORDER_TYPE,property_value.data_long);
         break;
        }
      case vop_s_color_borders:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_COLOR,property_value.data_long);
         break;
        }
      case vop_s_position_real_x:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_XDISTANCE,property_value.data_long);
         break;
        }
      case vop_s_position_real_y:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_YDISTANCE,property_value.data_long);
         break;
        }
      case vop_s_size_real_x:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_XSIZE,property_value.data_long);
         break;
        }
      case vop_s_size_real_y:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_YSIZE,property_value.data_long);
         break;
        }
      case vop_font_size:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_FONTSIZE,property_value.data_long);
         break;
        }
      case vop_line_width:
        {
         ObjectSetInteger(0,visual_object_name,OBJPROP_WIDTH,property_value.data_long);
         break;
        }
      default:
        {
         _is_redraw_object=false;
        }
     }
   return true;
  }

  • лёгкость в обработке событий
Это внешний обработчик событий, имя интересующего объекта(окна/графического элемента) можно указать при его создании
class My_handler:public iE_event_handler
  {
   void              On_event(sEvent &event)
     {
      if(event.id==CHARTEVENT_CLICK_)
        {
         if(
            (event.sparam=="A")||
            (event.sparam=="B")||
            (event.sparam=="C")||
            (event.sparam=="D")||
            (event.sparam=="E_hallo_world_E")
         )
           {
            sV_property_value v;
            cV_object_base *obj;
            obj=cV_object_base::Get_object_from_name(event.sparam);
            obj.Get_property(vop_is_selected,v);
            v.data_long=!v.data_long;
            obj.Set_property(vop_is_selected,v.data_long);
           }
         else
            if(event.sparam=="AAA")
              {
               sV_property_value v;
               cV_object_base *obj;
               obj=cV_object_base::Get_object_from_name("AAA");
               obj.Get_property(vop_is_selected_multi,v);
               v.data_long=!v.data_long;
               obj.Set_property(vop_is_selected_multi,v.data_long);
              }
            else
               if(event.sparam=="vt_rectangle_4")
                 {
                  sV_property_value v;
                  cV_object_base *obj;
                  obj=cV_object_base::Get_object_from_name("AAA");
                  obj.Get_property(vop_position_x,v);
                  v.data_long=v.data_long+5;
                  obj.Set_property(vop_position_x,v.data_long);
                  ulong ms=cV_object_base::Get_timer_msc();
                  if(ms!=ULONG_MAX)
                    {
                     Print(ms/1000.0," мс");
                    }
                 }
        }
     }
  };

Текстовая метка реализована через канвас по причине того, что объекту OBJ_LABEL нельзя изменить ширину и высоту, и по этой причине прорисовка происходит при поступлении событии CHARTEVENT_ON_PAINT (необходимость перерисовки)

bool cV_object_label::_On_event(const sEvent &event)
  {
   if(event.id==CHARTEVENT_ON_PAINT)
     {
      color color_back=clrBlack;
      if(CheckPointer(_object_parent))
        {
         color_back=color(_object_parent._property_values[vop_color_back].data_long);
        }
      int width=int(_property_values[vop_s_size_real_x].data_long);
      int height=int(_property_values[vop_s_size_real_y].data_long);
      int x=int(_property_values[vop_s_position_global_x].data_long-_property_values[vop_s_position_real_x].data_long);
      int y=int(_property_values[vop_s_position_global_y].data_long-_property_values[vop_s_position_real_y].data_long);
      _canvas.Resize(width,height);
      width=int(_property_values[vop_size_x].data_long);
      height=int(_property_values[vop_size_y].data_long);
      _canvas.Erase(ColorToARGB(color_back));
      switch(int(_property_values[vop_text_anchor].data_long))
        {
         case TA_CENTER:
           {
            x=x+(width-_canvas.TextWidth(_property_values[vop_text].data_string))/2;
            break;
           }
         case TA_RIGHT:
           {
            x=x+(width-_canvas.TextWidth(_property_values[vop_text].data_string));
            break;
           }
        }
      _canvas.TextOut(x,y,_property_values[vop_text].data_string,ColorToARGB(color(_property_values[vop_s_color_back].data_long)));//);
      _canvas.Update(false);
     }
   return true;
  }

Что просчитывать и обновлять определяется автоматически. Логируется время просчёта свойств и до вызова ChartRedraw() . События, что не привели к перерисовке графика пропускаются

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   cV_object_base::On_chart_event(id,lparam,long(dparam),sparam);
   ulong ms=cV_object_base::Get_timer_msc();
   if(ms!=ULONG_MAX)
     {
      Print(ms/1000.0," мс");
     }
  }

Демка в прикрепленном файле, выше исходники используются в ней.

Файлы:
Test_forms.ex5  221 kb
 

Демка не отображает все возможные свойства, только некоторые из них:

Ещё всё процессе разработки, пока так.

 
Aliaksandr Hryshyn:

Демка не отображает все возможные свойства, только некоторые из них:

Ещё всё процессе разработки, пока так.

Удачи в разработке! :)

 
Реter Konow:

Удачи в разработке! :)

Спасибо :)

 

Проверил работоспособность и потенциал функционала 3D графики в МТ5 на слабом компе с 4 гигами оперативки и 2-умя ядрами процессора.



Осваивается нормально, даже после затяжной паузы в программировании. Но, вещь тяжелая и чтобы создать что то серьезное - нужно немало потрудиться.

 
Зарабатывать помогает? 
 
Реter Konow:

Проверил работоспособность и потенциал функционала 3D графики в МТ5 на слабом компе с 4 гигами оперативки и 2-умя ядрами процессора.

Осваивается нормально, даже после затяжной паузы в программировании. Но, вещь тяжелая и чтобы создать что то серьезное - нужно немало потрудиться.

Для HFT,  3D думаю будет полезно при создании графического анализа объемов стакана и потока ордеров.
Но как интерпретировать такую информацию, не вникал.

dom

stream 

 

бог ты мой ! зачем все это ?