Creare una libreria grafica da zero - pagina 9

 
Aliaksandr Hryshyn:

Di più:

Cliccate con il tasto destro del mouse sulle aree della finestra, appare un menu. Spostare il mouse e cliccare con il tasto sinistro. Questo provoca lo spostamento della finestra.

È possibile. Per tua informazione, sto sviluppando e testando io stesso, quindi semplicemente non so di alcuni bug finché non li incontro accidentalmente nel processo. Sto facendo tutto da solo...

 

Ecco il mio esempio, nel file allegato, ci sono tre finestre sovrapposte.

Creare una finestra con sottofinestre è così, basta usare il motore senza codice aggiuntivo. Tranne che per gestire l'evento del clic sui pulsanti in alto.

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

Gestire l'evento del clic sui pulsanti superiori:

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

Ci sono diversi pulsanti e solo una finestra madre

File:
 
Реter Konow:

C'era un tale bug. Riparato. L'evento in sé è fissato bene, ma i bug si verificano con vari cambiamenti che non possono essere evitati nello sviluppo del codice.

Sì, è complicato.

Una foto della demo:


 
È solo che in un affare come questo, la prima cosa da fare è risolvere gli eventi e i controlli delle finestre, e il resto è più facile, anche se c'è molto più lavoro da fare altrove.
 
Chiunque sia interessato a fare una libreria di elementi visivi da zero :) ?
 
Aliaksandr Hryshyn:
È solo che in questo caso, prima di tutto, dobbiamo elaborare gli eventi e i controlli della finestra, il resto è più facile, ma c'è molto più lavoro da fare.

Le basi sono già state poste.

1: le finestre dovrebbero avere pulsanti di chiusura e collasso (almeno).

2: le finestre dovrebbero ridisegnarsi l'una sull'altra quando si clicca.

3: Le finestre dovrebbero muoversi con il mouse.

4: le finestre dovrebbero essere "rilevate" (messe a fuoco) sul grafico quando il cursore si sposta ( evento puntato).

5. Tutti gli elementi delle finestre devono essere su una "mappa" comune della finestra ed essere rilevati quando il mouse viene passato (evento puntato).

 

Gli elementi più semplici:

1. Una finestra statica, dimensionalmente immutabile e indelebile.

2. Pulsante.

3. Casella di controllo.

4. Pulsante radio.

5. Tab.

6. Linea, cornice, divisore, rettangolo.


Elementi di media complessità:

1. Cursori.

2. Barre di progresso.

3. Campi di input.

4. Campi a scorrimento.

5. Voci di liste semplici.


Articoli ad alta complessità.

1. Un elenco a discesa (un elemento molto complesso).

2. Una finestra dinamica (allungabile). Super complesso.


Ci sono circa 50 tipi di controlli. Ognuno dovrebbe avere un insieme comune e unico di proprietà supportate dalla funzionalità del motore corrispondente. Proprietà almeno 100, altrimenti il lavoro degli elementi sarà fortemente limitato.

Forme e linee semplici non hanno bisogno di molte proprietà, ma più l'elemento è complesso, più ce ne sono.
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
  • www.mql5.com
Все объекты, используемые в техническом анализе, имеют привязку на графиках по координатам цены и времени – трендовая линия, каналы, инструменты Фибоначчи и т.д.  Но есть ряд вспомогательных объектов, предназначенных для улучшения интерфейса, которые имеют привязку к видимой всегда части графика (основное окно графика или подокна индикаторов...
 

Merda, mi ero dimenticato dei tavoli! È una giungla là fuori... ))))

E una lista di alberi, e tutti i tipi di collettori...

 
Ogni controllo interattivo ha un parametro controllato da esso con il proprio insieme di proprietà. Per esempio, un pulsante ha un parametro di tipo bool (1 o 0), un campo di input ha un parametro di tipo stringa, un cursore ha un parametro di tipo range... Un campo di input con pulsanti ha un parametro con proprietà current_value, last_value, min, max, step, value_type e altre. Ogni proprietà è supportata dalla funzionalità.

Ogni elemento interattivo dovrebbe avere (idealmente) 8 stati diversi che cambiano in occasione di diversi eventi.

Per esempio: neutro, neutro_puntato, attivato_neutro, attivato_puntato, neutro_illuminato, attivato_illuminato, neutro_bloccato, attivato_bloccato.

Ogni stato è progettato con il proprio insieme di valori di proprietà dell'elemento ed entra in vigore ai propri eventi, che sono fissati da una funzionalità speciale.
 
Реter Konow:

Merda, mi ero dimenticato dei tavoli! È una giungla là fuori... ))))

E una lista ad albero, e tutti i tipi di collettori...

Nel mio caso, la "giungla" non è più complicata della media: una finestra di visualizzazione (l'area visibile della tabella), una finestra a grandezza naturale in cui devono entrare tutte le celle, scorrerà all'interno della finestra principale, finestre per le righe e le celle in esse, più lo scorrimento (un cursore delimitato da una barra). I vincoli sul posizionamento relativo sono determinati dalle proprietà. Solo per il cursore è necessario intercettare gli eventi di movimento dell'oggetto e già correggere la posizione della"finestra full size". Tutto questo è fatto da finestre virtuali, abbiamo bisogno di imbullonare la parte visiva ad essa, senza la parte visiva ci saranno finestre per linee e finestre a grandezza naturale. E per una cella modificabile, fate un campo di input (questo è un campo personalizzato), tutte le altre cose saranno gestite dal motore - riceverà gli eventi giusti per ogni cella (eventi del mouse, ridisegno, spostamento)..... Queste sono le possibilità, ma ci sono anche un paio di idee per aumentare le prestazioni nel caso in cui ci siano troppe finestre (grandi liste, tabelle, diverse migliaia di finestre).