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

 
Aliaksandr Hryshyn:

Plus :

Cliquez sur les zones de la fenêtre avec le bouton droit de la souris, un menu apparaît. Déplacez la souris et cliquez avec le bouton gauche de la souris. Cela fait bouger la fenêtre.

C'est possible. Pour votre information, je développe et teste moi-même, et je ne suis donc pas au courant de certains bogues avant de les rencontrer accidentellement au cours du processus. Je fais tout par moi-même...

 

Voici mon exemple, dans le fichier joint, il y a trois fenêtres qui se chevauchent.

Pour créer une fenêtre avec des sous-fenêtres, il suffit d'utiliser le moteur sans code supplémentaire. Sauf pour gérer l'événement du clic sur les boutons du haut.

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

Gérer l'événement de cliquer sur les boutons du haut :

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

Il y a plusieurs boutons et une seule fenêtre parent

Dossiers :
 
Реter Konow:

Il y avait un tel bug. Je l'ai corrigé. L'événement lui-même est bien fixé, mais des bogues surviennent lors de diverses modifications qui ne peuvent être évitées lors du développement du code.

Oui, c'est compliqué.

Une photo de la démo :


 
C'est juste que, dans une entreprise comme celle-ci, la première chose à faire est d'élaborer les événements et les contrôles de fenêtre, et le reste est plus facile, bien qu'il y ait beaucoup plus de travail à faire ailleurs.
 
Toute personne intéressée par la création d'une bibliothèque d'éléments visuels à partir de zéro :) ?
 
Aliaksandr Hryshyn:
C'est juste que dans ce cas, nous devons tout d'abord élaborer les événements et les contrôles de la fenêtre, le reste est plus facile, mais il y a beaucoup plus de travail à faire.

Le travail de fond est déjà en place.

1 : les fenêtres devraient avoir des boutons de fermeture et de réduction (au moins).

2 : les fenêtres devraient se redessiner l'une sur l'autre quand on clique dessus.

3 : Les fenêtres doivent se déplacer avec la souris.

4 : les fenêtres doivent être "détectées" (mises au point) sur le graphique lorsque le curseur se déplace ( événement pointé).

5. Tous les éléments des fenêtres doivent se trouver sur une "carte" commune de la fenêtre et être détectés lors du survol de la souris (événement pointé).

 

Les éléments les plus simples :

1. Une fenêtre statique, dimensionnellement immuable et indélébile.

2. Bouton.

3. case à cocher.

4. Bouton radio.

5. Onglet.

6. Ligne, cadre, séparateur, rectangle.


Éléments de complexité moyenne :

1. Sliders.

2. Barres de progression.

3. Champs de saisie.

4. Champs défilants.

5. Des éléments de liste simples.


Éléments de haute complexité.

1. Une liste déroulante (un élément très complexe).

2. Une fenêtre dynamique (extensible). Super-complexe.


Il existe environ 50 types de contrôles. Chacune d'entre elles doit avoir un ensemble commun et unique de propriétés prises en charge par la fonctionnalité correspondante du moteur. Propriétés au moins 100, sinon le travail des éléments sera sévèrement limité.

Les formes et les lignes simples n'ont pas besoin de beaucoup de propriétés, mais plus l'élément est complexe, plus elles sont nombreuses.
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
  • www.mql5.com
Все объекты, используемые в техническом анализе, имеют привязку на графиках по координатам цены и времени – трендовая линия, каналы, инструменты Фибоначчи и т.д.  Но есть ряд вспомогательных объектов, предназначенных для улучшения интерфейса, которые имеют привязку к видимой всегда части графика (основное окно графика или подокна индикаторов...
 

Merde ! J'ai oublié les tables ! C'est la jungle dehors... ))))

Et une liste d'arbres, et toutes sortes d'effondrements...

 
Chaque contrôle interactif possède un paramètre qu'il contrôle avec son propre ensemble de propriétés. Par exemple, un bouton a un paramètre de type bool (1 ou 0), un champ de saisie a un paramètre de type string, un curseur a un paramètre de type range... Un champ de saisie avec des boutons a un paramètre avec les propriétés current_value, last_value, min, max, step, value_type et autres. Chaque propriété est prise en charge par la fonctionnalité.

Chaque élément interactif devrait (idéalement) avoir 8 états différents qui changent selon les événements.

Par exemple : neutre, neutre_pointé, activé_neutre, activé_pointé, neutre_lumineux, activé_lumineux, neutre_verrouillé, activé_verrouillé.

Chaque état est conçu avec son propre ensemble de valeurs de propriétés d'éléments et entre en vigueur lors de ses propres événements, qui sont fixés par une fonctionnalité spéciale.
 
Реter Konow:

Merde ! J'ai oublié les tables ! C'est la jungle dehors... ))))

Et une liste en forme d'arbre, et toutes sortes de réducteurs...

Dans mon cas, la "jungle" n'est pas plus compliquée que la moyenne : une fenêtre d'affichage (la zone visible du tableau), une fenêtre pleine grandeur dans laquelle toutes les cellules doivent tenir, elle se glissera à l'intérieur de la fenêtre principale, des fenêtres pour les lignes et les cellules qui s'y trouvent, plus le défilement (un curseur délimité par une barre). Les contraintes sur le positionnement relatif sont déterminées par les propriétés. Seulement pour le curseur, il est nécessaire d'intercepter les événements de mouvement de l'objet et de corriger déjà la position de la"fenêtre pleine grandeur". Tout ceci est fait par des fenêtres virtuelles, nous devons y attacher une partie visuelle, sans cette partie visuelle il y aura des fenêtres pour les lignes et des fenêtres de taille normale. Et pour une cellule modifiable, faites un champ de saisie (c'est un champ personnalisé), toutes les autres choses seront gérées par le moteur - il recevra les événements appropriés pour chaque cellule (événements de souris, redessin, déplacement)...... Ce sont les possibilités, mais il y a aussi quelques idées pour augmenter les performances au cas où il y aurait trop de fenêtres (grandes listes, tableaux, plusieurs milliers de fenêtres).