Créer une bibliothèque graphique à partir de zéro - page 5

 
Comment la bibliothèque progresse-t-elle ?
 
Реter Konow:
Comment la bibliothèque progresse-t-elle ?

tout est plus que bien.

 

J'ai également pris l'habitude de créer une bibliothèque de graphiques, juste avec les éléments dont j'ai besoin.

Le principal atout de la bibliothèque est son moteur de fenêtrage :

  • cela ne dépend pas des graphiques, vous pouvez dire que les fenêtres virtuelles sans une seule fonction pour travailler avec les graphiques, même les fenêtres absolues fonctionneront correctement (événements, propriétés).
  • ensembles de propriétés pour une fenêtre qui affectent son comportement, propriétés dépendantes de cette fenêtre et autres

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


  • en ce qui concerne les graphiques, vous pouvez utiliser à la fois des objets standard et des canevas, ainsi que DirectX, ce que vous voulez.
  • les fenêtres du moteur sont les éléments de base pour construire des éléments graphiques.
  • utilisation de différentes optimisations pour la performance (exclusion des appels inutiles aux fonctions du système graphique, ainsi que l'exclusion du dessin des boîtes invisibles)
  • Simplicité de la création d'un nouvel élément graphique, tant au niveau de la mise en œuvre de la conception graphique que de la création d'éléments graphiques enfants/de la structure des fenêtres. Tous les événements et le calcul des propriétés dépendantes seront effectués au niveau du moteur, il ne distingue pas les éléments graphiques personnalisés, il fonctionne uniquement au niveau des fenêtres de base.

Création et suppression de l'objet 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;
  }

Ceci implémente une méthode pour modifier les propriétés de l'objet standard OBJ_RECTANGLE_LABEL, en parcourant l'aide et en utilisant les propriétés d'intérêt
.

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

  • gestion facile des événements
Il s'agit d'un gestionnaire d'événement externe, le nom de l'objet d'intérêt (fenêtre/élément graphique) peut être spécifié lors de sa création
.
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'étiquette de texte est implémentée via un kanvas car la largeur et la hauteur ne peuvent pas être modifiées dans l'objet OBJ_LABEL. Pour cette raison, le rendu est effectué lorsqu'un événement CHARTEVENT_ON_PAINT se produit (ce qui nécessite un redessin).

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

Ce qu'il faut rendre et mettre à jour est déterminé automatiquement. Les propriétés sont enregistrées avant d'appeler ChartRedraw() . Les événements qui n'ont pas entraîné le redécoupage du graphique sont ignorés.

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

La démo est dans le fichier joint, les sources ci-dessus sont utilisées dans cette démo.

Dossiers :
Test_forms.ex5  221 kb
 

La démo n'affiche pas toutes les propriétés possibles, seulement certaines d'entre elles :

C'est toujours un travail en cours, jusqu'à présent.

 
Aliaksandr Hryshyn:

La démo n'affiche pas toutes les propriétés possibles, seulement certaines d'entre elles :

C'est toujours un travail en cours, pour l'instant.

Bonne chance pour le développement ! :)

 
Реter Konow:

Bonne chance pour le développement ! :)

Merci :)

 

Nous avons testé la fonctionnalité et le potentiel des graphiques 3D dans MT5 sur un ordinateur faible avec 4 Go de RAM et 2 cœurs de processeur.



Il fonctionne bien, même après une longue pause dans la programmation. Mais la chose est lourde et il faut beaucoup de travail pour créer quelque chose de sérieux.

 
Cela permet-il de gagner de l'argent ?
 
Реter Konow:

Nous avons testé la fonctionnalité et le potentiel des graphiques 3D dans MT5 sur un ordinateur faible avec 4 Go de RAM et 2 cœurs de processeur.

Il fonctionne bien, même après une longue pause dans la programmation. Mais, la chose est lourde et il faut beaucoup de travail pour développer quelque chose de sérieux.

Pour le HFT, je pense que la 3D sera utile pour l'analyse graphique du volume et du flux d'ordres de la coupe.
Mais je ne sais pas comment interpréter de telles informations.

dom

flux

 

Mon Dieu ! À quoi ça sert tout ça ?