Creare una libreria grafica da zero - pagina 5

 
Come procede la biblioteca?
 
Реter Konow:
Come procede la biblioteca?

tutto va più che bene.

 

Ho anche imparato a fare una libreria grafica, solo con gli elementi di cui ho bisogno.

Il trucco principale della libreria è il suo motore a finestre:

  • non dipende dalla grafica, si può dire finestre virtuali senza una sola funzione per lavorare con la grafica, anche le finestre in assoluto funzioneranno correttamente (eventi, proprietà)
  • insiemi di proprietà per una finestra che influenzano il suo comportamento, proprietà dipendenti di quella finestra e altre

   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);


  • come grafica potete usare sia oggetti standard che canvas, e DirectX, quello che volete
  • le finestre del motore sono i mattoni per costruire elementi grafici
  • uso di diverse ottimizzazioni per le prestazioni (esclusione di chiamate inutili di funzioni del sistema grafico, così come l'esclusione del disegno di caselle invisibili)
  • Semplicità nella creazione di un nuovo elemento grafico, sia l'implementazione del disegno grafico che la creazione di elementi grafici figli/struttura delle finestre. Tutti gli eventi e il calcolo delle proprietà dipendenti saranno eseguiti a livello di motore, non distingue gli elementi grafici personalizzati, funziona solo a livello di finestre di base

Creare e cancellare l'oggetto standard 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;
  }

Questo implementa un metodo per cambiare le proprietà dell'oggetto standard OBJ_RECTANGLE_LABEL, scorrendo la guida e utilizzando le proprietà di interesse

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;
  }

  • facile gestione degli eventi
Questo è un gestore di eventi esterno, il nome dell'oggetto di interesse (finestra/oggetto grafico) può essere specificato quando lo si crea
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," мс");
                    }
                 }
        }
     }
  };

L'etichetta di testo è implementata tramite kanvas perché la larghezza e l'altezza non possono essere cambiate nell'oggetto OBJ_LABEL, e per questo motivo il rendering viene eseguito quando si verifica un evento CHARTEVENT_ON_PAINT (che richiede un ridisegno)

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;
  }

Cosa rendere e aggiornare viene determinato automaticamente. Le proprietà sono registrate prima di chiamare ChartRedraw() . Gli eventi che non hanno causato il ridisegno del grafico vengono saltati.

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," мс");
     }
  }

Il demo è nel file allegato, le fonti di cui sopra sono utilizzate in esso.

File:
Test_forms.ex5  221 kb
 

Il demo non mostra tutte le proprietà possibili, solo alcune:

È ancora un lavoro in corso, per ora.

 
Aliaksandr Hryshyn:

Il demo non mostra tutte le proprietà possibili, solo alcune:

È ancora un lavoro in corso, per ora.

Buona fortuna per lo sviluppo! :)

 
Реter Konow:

Buona fortuna per lo sviluppo! :)

Grazie :)

 

Testato la funzionalità e il potenziale della grafica 3D in MT5 su un computer debole con 4 GB di RAM e 2 core del processore.



Funziona bene anche dopo una lunga pausa nella programmazione. Ma la cosa è pesante e ci vuole molto lavoro per creare qualcosa di serio.

 
Aiuta a fare soldi?
 
Реter Konow:

Testato la funzionalità e il potenziale della grafica 3D in MT5 su un computer debole con 4 GB di RAM e 2 core del processore.

Funziona bene anche dopo una lunga pausa nella programmazione. Ma la cosa è pesante e ci vuole molto lavoro per sviluppare qualcosa di serio.

Per l'HFT, penso che il 3D sarà utile per l'analisi grafica del volume della tazza e del flusso degli ordini.
Ma non so come interpretare tali informazioni.

dom

stream

 

Mio Dio, a cosa serve tutto questo?