Galeria de UIs escritas em MQL - página 77

 

Estágio atual do desenvolvimento do VE:

  • Quase 400 propriedades de janelas, elementos e parâmetros do núcleo estão integrados e com guias nas janelas do editor. Todos eles se tornarão configurações controláveis dos elementos da GUI criados no VE.
  • Foram integrados 52 modelos de vários elementos de controle necessários ao trabalho dos usuários.
  • Muito trabalho foi feito em termos de design e estilo. Continuo avaliando uma variedade de soluções para obter praticidade e usabilidade da GUI do VE.
  • Quando a integração de modelos e propriedades, bem como sua classificação e distribuição, estiver concluída, o trabalho na funcionalidade começará.
  • No momento, a GUI está escrita na linguagem de marcação KIB, o que é bastante tedioso. A transição para a edição visual ainda não ocorreu. No entanto, isso ocorrerá em um futuro próximo.
  • Há defeitos gráficos. Eles são temporários.
  • A altura da barra de tarefas foi reduzida para economizar espaço.
  • A moldura da janela do editor foi movida para fora do campo de visão para obter mais espaço.


 
Parece ótimo, Peter, acho que, quando você estiver usando o VE para construir a si mesmo, ele definitivamente lhe dará algumas informações valiosas sobre como o design da interface do usuário está funcionando.
Aguardamos ansiosamente a próxima atualização de desenvolvimento.
 
Douglas Prager #:
Isso parece fantástico, Peter. Acho que quando você usa o VE para construir você mesmo, isso lhe dará informações valiosas sobre como o design da interface do usuário funciona.
Aguardamos ansiosamente a próxima atualização de desenvolvimento.
Obrigado, Douglas. Você está certo, é exatamente isso. Há uma "barreira" técnica mínima a ser superada.

Também acompanharei seu desenvolvimento fundamental com interesse.
 
Doerk Hilger #:
A interface do usuário ainda é 100% MQL pura.
Tudo baseado em vetores, totalmente escalonável e ajustável a qualquer tela.
Todas as telas visuais funcionam de forma anacrônica em uma classe principal que manipula e distribui todos os eventos MQL para objetos, dependendo das configurações de assinatura e com base nas prioridades de eventos.

Espero não estar roubando o fio da meada muito interessante e me perdoe, Peter, se o fizer, não será uma discussão, apenas espero uma resposta curta para o interesse teórico - você quer dizer que tem um tipo de classe estática que conhece (mantém o controle de todos os ponteiros de objeto) todos os objetos de classe instanciados no sistema e cada objeto tem acesso para se inscrever nos eventos necessários nessa classe estática de controle e essa classe singleton de controle estático apenas entrega os eventos a todos os objetos? Em caso afirmativo, você considera isso correto em termos de OOP ou talvez seja uma programação orientada a eventos aceitável? Como você escreveu sobre isso, acho que gostaria de aceitar perguntas sobre o assunto e, se for o caso, por favor, seja o mais breve possível para não atrapalhar este tópico, embora ele esteja relacionado.

 
Amir Yacoby #:

Espero não estar roubando o fio da meada muito interessante e me perdoe, Peter, se o fizer, não será uma discussão, apenas espero uma resposta curta para o interesse teórico. Quer dizer que você tem um tipo de classe estática que conhece (mantém o controle de todos os ponteiros de objeto) todos os objetos de classe instanciados no sistema e cada objeto tem acesso para se inscrever nos eventos necessários nessa classe estática de controle e essa classe singleton de controle estático apenas entrega os eventos a todos os objetos? Em caso afirmativo, você considera isso correto em termos de OOP ou talvez seja uma programação orientada a eventos aceitável? Como você escreveu sobre isso, acho que gostaria de aceitar perguntas sobre o assunto e, se for o caso, por favor, seja o mais breve possível para não atrapalhar este tópico, embora ele esteja relacionado.

Sim, é exatamente isso.
Breve descrição:

O núcleo recebe todos os eventos da MetaTrader e qualquer objeto pode se inscrever no núcleo. Portanto, a classe CObject também teve de ser redesenhada/modificada, de modo que qualquer objeto tenha uma função chamada "public: virtual void OnEACycle(CCycleParams * cpm)". Esse ciclo poderia então ser um evento de gráfico, init, deinit etc. Todo objeto também pode ter uma função "public: virtual void OnEATick()". Um efeito colateral interessante é que você obtém um recurso extra dessa forma, pois também pode assinar o fim de qualquer ciclo, não importa qual seja. Muito útil para fechar um arquivo ou terminar qualquer outra coisa, simplesmente no final de qualquer ciclo.

Além disso, todo objeto CObject pode ter filhos e também assinantes. Isso significa que um objeto pode acionar seus próprios eventos, como quando algo é clicado ou algo semelhante. Então, basta executar um object.SubEvent(STH_CLICKED, params). Dessa forma, o objeto em si não se importa com quem precisa dessas informações, elas são apenas distribuídas para os assinantes, que recebem um OnSubEvent(int msg, CSubEventParams * sep) e podem fazer o que quiserem com elas.

Em suma, dessa forma, ele está mais relacionado à forma de codificação que conhecemos do C#, em que você também usa apenas .Invoke() para disparar eventos e não se importar com quem os recebe.

Na verdade, não é tão complicado de implementar, mas é claro que os detalhes são o desafio no final, já que se trata de um núcleo/base para cada EA ou indicador do futuro que precisa funcionar em todos os cenários.

 
Para entender um pouco melhor, essa é a classe base para qualquer EA ou indicador após a implementação.

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)         {}
         
   };
E um EA final tem a seguinte aparência:

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;
 
É claro que Load/Unload/Activate etc. são personalizados, mas como você tem esse núcleo de evento, você tem muito mais flexibilidade do que sem ele e muito mais controle sobre absolutamente tudo.
Se eu tivesse tempo, escreveria um artigo e forneceria as fontes. Não é segredo, não há mágica alguma.
 
Doerk Hilger controle sobre absolutamente tudo.
Observei a GUI que você criou. Gosto muito dela. Diga-me, você mesmo a escreveu ou usou algumas bibliotecas MQL?
 
Реter Konow #:
Observei a GUI que você criou. Gostei muito dela. Diga-me, você mesmo a escreveu ou usou algumas bibliotecas MQL?

Obrigado.
Não, nenhuma biblioteca. Foi projetada por mim mesmo do zero. Na verdade, apenas o CCanvas dos originais foi adaptado, nada mais.

 
Doerk Hilger #:

Obrigado.
Não, não há bibliotecas. Eu mesmo o desenvolvi do zero. Na verdade, apenas o CCanvas foi adaptado dos originais, nada mais.

Não é fácil criar algo assim. )

Até onde eu sei, na classe Ccanvas padrão não há funcionalidade para desenhar um gradiente de cor. Como você resolveu o problema com um gradiente em sua GUI?