Galleria di interfacce utente scritte in MQL - pagina 77

 

Stadio attuale di sviluppo di VE:

  • Quasi 400 proprietà di finestre, elementi e parametri del nucleo sono integrati e inseriti in schede nelle finestre dell'editor. Tutti questi elementi diventeranno impostazioni controllabili degli elementi GUI creati in VE.
  • Sono stati integrati 52 modelli di vari elementi di controllo necessari per il lavoro degli utenti.
  • È stato fatto molto lavoro sul design e sullo stile. Continuo a valutare una serie di soluzioni per ottenere praticità e usabilità della GUI di VE.
  • Una volta completata l'integrazione dei modelli e delle proprietà, nonché il loro ordinamento e la loro distribuzione, inizierà il lavoro sulla funzionalità.
  • Al momento la GUI è scritta nel linguaggio di markup KIB, che è piuttosto noioso. Il passaggio all'editing visivo non è ancora avvenuto. Tuttavia, ciò avverrà nel prossimo futuro.
  • Ci sono dei difetti grafici. Sono temporanei.
  • L'altezza della barra delle applicazioni è stata ridotta per risparmiare spazio.
  • La cornice della finestra dell'editor è stata spostata fuori dal campo visivo per ottenere più spazio.


 
Sembra fantastico Peter, penso che una volta che avrai usato il VE per costruirsi da solo, ti darà sicuramente delle indicazioni preziose su come funziona il tuo design dell'interfaccia utente.
Aspetto con ansia il prossimo aggiornamento dello sviluppo.
 
Douglas Prager #:
Sembra fantastico, Peter. Penso che quando si usa VE per costruire se stessi, si ottengono preziose informazioni su come funziona il design dell'interfaccia utente.
Attendo con ansia il prossimo aggiornamento dello sviluppo.
Grazie, Douglas. Hai ragione, è esattamente così. C'è un minimo di "ostacolo" tecnico da superare.

Seguirò con interesse anche il vostro sviluppo fondamentale.
 
Doerk Hilger #:
L'interfaccia utente è ancora al 100% puro MQL.
Tutto basato su vettori, completamente scalabile e adattabile a qualsiasi display.
Tutti i display visivi funzionano in modo asincrono all'interno di una classe centrale che gestisce e distribuisce tutti gli eventi MQL agli oggetti, a seconda delle loro impostazioni di sottoscrizione e in base alle priorità degli eventi.

Spero di non rubare l'interessantissimo thread e perdonami Peter se lo faccio, non sarà una discussione, spero solo in una risposta breve per l'interesse teorico - intendi dire che hai una sorta di classe statica che conosce (tiene traccia di tutti i puntatori agli oggetti) tutti gli oggetti di classe istanziati nel sistema e ogni oggetto ha accesso a sottoscrivere se stesso agli eventi richiesti da quella classe statica di controllo e quella classe statica singleton di controllo consegna semplicemente gli eventi a tutti gli oggetti? Se è così, lo considera corretto in termini di OOP o forse è accettabile come programmazione guidata dagli eventi? Dato che ne avete scritto, immagino che vogliate accettare domande in merito e, in tal caso, cerchiamo di essere il più brevi possibile per non dirottare questo thread, anche se è correlato.

 
Amir Yacoby #:

Spero di non rubare il thread molto interessante e perdonami Peter se lo faccio, non sarà una discussione, spero solo in una risposta breve per l'interesse teorico - intendi dire che hai una sorta di classe statica che conosce (tiene traccia di tutti i puntatori agli oggetti) tutti gli oggetti di classe istanziati nel sistema e ogni oggetto ha accesso a sottoscrivere se stesso agli eventi richiesti su quella classe statica di controllo e quella classe statica di controllo singleton consegna semplicemente gli eventi a tutti gli oggetti? Se è così, lo considera corretto in termini di OOP o forse è accettabile come programmazione guidata dagli eventi? Dato che ne avete scritto, immagino che vogliate accettare domande in merito e, in tal caso, cerchiamo di essere il più brevi possibile per non dirottare questo thread, anche se è correlato.

Sì, è esattamente questo.
Breve descrizione:

Il core riceve tutti gli eventi di MetaTrader e qualsiasi oggetto può sottoscrivere il core. Per questo motivo è stato necessario riprogettare/modificare anche la classe CObject, in modo che ogni oggetto abbia una funzione chiamata "public: virtual void OnEACycle(CCycleParams * cpm)". Tale ciclo può essere un evento grafico, un init, un deinit, ecc. Ogni oggetto può anche avere un "public: virtual void OnEATick()". L'effetto collaterale è che in questo modo si ottiene una funzione in più, perché si può sottoscrivere anche la fine di qualsiasi ciclo, indipendentemente da quale sia. Piuttosto utile per chiudere un file o finire qualsiasi altra cosa, semplicemente alla fine di qualsiasi ciclo.

Inoltre, ogni oggetto CObject può avere figli e anche sottoscrittori. Ciò significa che un oggetto può innescare i propri eventi, come quando qualcosa viene cliccato o simili. Allora si esegue semplicemente un object.SubEvent(STH_CLICKED, params). In questo modo l'oggetto stesso non si preoccupa di chi ha bisogno di queste informazioni, ma solo di distribuirle ai sottoscrittori, che ricevono un OnSubEvent(int msg, CSubEventParams * sep) e possono farci quello che vogliono.

Tutto sommato, questo modo è più simile al modo di codificare che conosciamo da C#, dove si usa anche solo .Invoke() per lanciare eventi e non ci si preoccupa di chi li riceve.

In realtà non è così complicato da implementare, ma ovviamente i dettagli sono la sfida finale, dato che si tratta di un nucleo/base per ogni singolo EA o indicatore del futuro che deve funzionare in ogni scenario.

 
Per capire meglio, questa è la classe base per qualsiasi EA o indicatore dopo l'implementazione.

class CEAMain : public CObject
   {
   public: CEAMain()
      {
      m_classname="CEAMain";
      SubscribeToCycle(EA_CYCLE_LOAD);
      SubscribeToCycle(EA_CYCLE_PARAMS);   
      SubscribeToCycle(EA_CYCLE_INIT);   
      SubscribeToCycle(EA_CYCLE_ACTIVATE);
      SubscribeToCycle(EA_CYCLE_TICK);
      SubscribeToCycle(EA_CYCLE_DEINIT);
      SubscribeToCycle(EA_CYCLE_UNLOAD);
      }
      //+------------------------------------------------------------------+
      //| Cycles handler                                                   |
      //+------------------------------------------------------------------+
      public: virtual void OnEACycle(CEACycleParams * cpm)
         {
         switch (cpm.Cycle)
            {
            case EA_CYCLE_LOAD:        cpm.CycleResult(OnEALoad(PTR(cpm.Init))); break;
            case EA_CYCLE_PARAMS:      cpm.CycleResult(OnEAParams()); break;
            case EA_CYCLE_INIT:        cpm.CycleResult(OnEAInit(PTR(cpm.Init))); break;
            case EA_CYCLE_ACTIVATE:    OnEAActivate(); break;
            case EA_CYCLE_DEINIT:      OnEADeinit(PTR(cpm.Deinit)); break;
            case EA_CYCLE_UNLOAD:      OnEAUnload(PTR(cpm.Deinit)); break;
            case EA_CYCLE_BOOKEVENT:   OnEABookEvent(PTR(cpm.BookEvent)); break;
            }
         }
      //+------------------------------------------------------------------+
      //| Cycles override                                                  |
      //+------------------------------------------------------------------+
      protected: virtual bool OnEALoad(CEAInitParams * ipm)                   { return true; }
      protected: virtual bool OnEAParams(void)                                { return true; }
      protected: virtual bool OnEAInit(CEAInitParams * ipm)                   { return true; } 
      protected: virtual void OnEAActivate(void)                              {}
      protected: virtual void OnEADeinit(CEADeinitParams * dpm)               {}
      protected: virtual void OnEAUnload(CEADeinitParams * dpm)               {}
      protected: virtual void OnEAChartEvent(CEAChartEventParams * cep)       {}
      protected: virtual void OnEABookEvent(CEABookEventParams * cpm)         {}
         
   };
Un EA finale ha quindi questo aspetto:

class CMain : public CEAMain
   {
      public: CMain()
         {
         m_classname="MainEA";
         }
      public: ~CMain()
         {
         }         

      //+------------------------------------------------------------------+
      //| Load                                                             |
      //+------------------------------------------------------------------+
      protected: virtual bool OnEALoad(CEAInitParams * ipm)
         {
         Print("Welcome :)");
         return true;
         }
      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      protected: virtual bool OnEAInit(CEAInitParams * ipm)
         { 
         if (ipm.IsFirstInit) return true;
         //--- Account changed init
         if (ipm.IsAccountChanged)
            {
            }
         //--- Symbol change init
         else if (ipm.IsSymbolChanged)    
            {
            }
         return true;
        }
        
      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      protected: virtual void OnEADeinit(CEADeinitParams * dpm)
        {
        }
      protected: virtual void OnEAUnload(CEADeinitParams * dpm)
         {
         DeInit();
         Print("Bye.");
         }  
      ...
      ...
};

// Create the main EA object on a global scope. 
CMain __MainEA;
 
Naturalmente, Load/Unload/Activate ecc. sono personalizzati, ma dal momento che si dispone di questo event-core, si ha molta più flessibilità che senza e molto più controllo su tutto.
Se avessi il tempo, scriverei un articolo e fornirei le fonti. Non è un segreto, non c'è nessuna magia.
 
Doerk Hilger controllo su tutto.
Ho visto l'interfaccia grafica che avete creato. Mi piace molto. Dimmi, l'hai scritta tu o hai usato qualche libreria MQL?
 
Реter Konow #:
Ho guardato l'interfaccia grafica che hai creato. Mi piace molto. Dimmi, l'hai scritta tu o hai usato qualche libreria MQL?

Grazie.
No, nessuna libreria. L'ho progettata da zero. In realtà solo CCanvas di quelli originali è stato adattato, nient'altro.

 
Doerk Hilger #:

Grazie.
No, nessuna libreria. L'ho sviluppato da zero da solo. In realtà, solo CCanvas è adattato da quelli originali, nient'altro.

Non è facile creare qualcosa di simile. )

Per quanto ne so, nella classe Ccanvas standard non c'è alcuna funzionalità per disegnare un gradiente di colore, come hai risolto il problema del gradiente nella tua GUI?