Galerie d'interfaces utilisateur écrites en MQL - page 77

 

Stade actuel du développement de VE :

  • Près de 400 propriétés de fenêtres, éléments et paramètres du noyau sont intégrés et tabulés dans les fenêtres de l'éditeur. Ils deviendront tous des paramètres contrôlables des éléments de l'interface graphique créés dans VE.
  • 52 modèles de divers éléments de contrôle nécessaires au travail des utilisateurs ont été intégrés.
  • Beaucoup de travail a été fait sur la conception et le style. Je continue à évaluer diverses solutions pour rendre l'interface graphique de VE pratique et facile à utiliser.
  • Une fois que l'intégration des modèles et des propriétés, ainsi que leur tri et leur distribution, sera terminée, le travail sur les fonctionnalités commencera.
  • Pour l'instant, l'interface graphique est écrite dans le langage de balisage KIB, ce qui est assez fastidieux. La transition vers l'édition visuelle n'a pas encore eu lieu. Cependant, cela se fera dans un avenir proche.
  • Il y a des défauts graphiques. Ils sont temporaires.
  • La hauteur de la barre des tâches a été réduite pour gagner de la place.
  • Le cadre de la fenêtre de l'éditeur a été déplacé hors du champ de vision pour gagner de la place.


 
Ça a l'air génial Peter, je pense qu'une fois que vous utiliserez le VE pour se construire lui-même, cela vous donnera certainement des indications précieuses sur la façon dont votre conception de l'interface utilisateur fonctionne.
J'attends avec impatience la prochaine mise à jour du développement.
 
Douglas Prager #:
Cela a l'air génial, Peter. Je pense que lorsque vous utilisez VE pour vous construire vous-même, cela vous donnera des indications précieuses sur la façon dont fonctionne votre conception de l'interface utilisateur.
J'attends avec impatience la prochaine mise à jour.
Merci, Douglas. Vous avez raison, c'est tout à fait exact. Il y a un minimum d'obstacles techniques à surmonter.

Je suivrai également avec intérêt votre développement fondamental.
 
Doerk Hilger #:
L 'interface utilisateur est toujours 100 % purement MQL.
Tout est basé sur des vecteurs, entièrement modulable et adaptable à n'importe quel affichage.
Tous les affichages visuels fonctionnent de manière asychrone au sein d'une classe centrale qui gère et distribue tous les événements MQL aux objets, en fonction de leurs paramètres d'abonnement et de leurs priorités d'événement.

J'espère que je ne vole pas le fil très intéressant et pardonnez-moi Peter si je le fais, ce ne sera pas une discussion, j'espère juste une réponse courte pour l'intérêt théorique - voulez-vous dire que vous avez une sorte de classe statique qui connaît (garde la trace de tous les pointeurs d'objets) tous les objets de classe instanciés dans le système et chaque objet a accès à s'abonner aux événements requis sur cette classe statique de contrôle et cette classe singleton statique de contrôle délivre simplement les événements à tous les objets ? Si c'est le cas, considérez-vous que c'est correct en termes de POO ou peut-être est-ce une programmation événementielle acceptable ? Puisque vous avez écrit sur le sujet, je suppose que vous voudriez accepter des questions à ce sujet et si oui, s'il vous plaît, soyez aussi bref que possible pour ne pas détourner ce fil, bien qu'il soit lié.

 
Amir Yacoby #:

J'espère que je ne vole pas le fil très intéressant et pardonnez-moi Peter si je le fais, ce ne sera pas une discussion, j'espère juste une réponse courte pour l'intérêt théorique - voulez-vous dire que vous avez une sorte de classe statique qui connaît (garde la trace de tous les pointeurs d'objets) tous les objets de classe instanciés dans le système et chaque objet a accès à s'abonner aux événements requis sur cette classe statique de contrôle et cette classe singleton de contrôle statique délivre simplement les événements à tous les objets ? Si c'est le cas, considérez-vous que c'est correct en termes de POO ou peut-être est-ce une programmation événementielle acceptable ? Puisque vous avez écrit à ce sujet, je suppose que vous voudriez accepter des questions à ce sujet et si oui, s'il vous plaît, soyez aussi bref que possible pour ne pas détourner ce fil, bien qu'il soit lié.

Oui, c'est exactement de cela qu'il s'agit.
Brève description :

Le noyau reçoit tous les événements MetaTrader et n'importe quel objet peut s'abonner au noyau. Par conséquent, la classe CObject a également dû être redessinée/modifiée, de sorte que tout objet dispose d'une fonction nommée "public : virtual void OnEACycle(CCycleParams * cpm)". Un tel cycle pourrait alors être un événement graphique, init, deinit, etc. Chaque objet peut également avoir une fonction "public : virtual void OnEATick()". L'effet secondaire est que vous obtenez une fonctionnalité supplémentaire, car vous pouvez vous abonner à la fin de n'importe quel cycle, quel qu'il soit. C'est très utile pour fermer un fichier ou terminer toute autre chose, simplement à la fin d'un cycle.

De plus, chaque objet CObject peut avoir des enfants et aussi des abonnés. Cela signifie qu'un objet peut déclencher ses propres événements, par exemple lorsque qqch. a été cliqué ou autre. Il suffit alors d'exécuter un object.SubEvent(STH_CLICKED, params). De cette façon, l'objet lui-même ne se soucie pas de savoir qui a besoin de cette information, elle est juste distribuée aux abonnés, ils reçoivent un OnSubEvent(int msg, CSubEventParams * sep) et peuvent en faire ce qu'ils veulent.

Dans l'ensemble, cette façon est plus proche de la façon de coder que nous connaissons en C#, où l'on utilise simplement .Invoke() pour déclencher des événements et ne pas se soucier de qui les reçoit.

En fait, ce n'est pas si compliqué à mettre en œuvre, mais bien sûr les détails sont le défi à la fin, puisque c'est un noyau/base pour chaque EA ou indicateur pour l'avenir qui doit fonctionner dans tous les scénarios.

 
Pour mieux comprendre, il s'agit de la classe de base pour tout EA ou indicateur après implémentation.

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)         {}
         
   };
Et un EA final ressemble alors à ceci :

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;
 
Bien sûr, Load/Unload/Activate etc. sont personnalisés, mais puisque vous avez cet event-core, vous avez beaucoup plus de flexibilité que sans et beaucoup plus de contrôle sur absolument tout.
Si j'avais eu le temps, j'aurais écrit un article et fourni les sources. Ce n'est pas un secret, il n'y a pas de magie du tout.
 
Doerk Hilger contrôle sur absolument tout.
J'ai regardé l'interface graphique que vous avez créée. Je l'aime beaucoup. Dites-moi, l'avez-vous écrite vous-même ou avez-vous utilisé des bibliothèques MQL ?
 
Реter Konow #:
J'ai regardé l'interface graphique que vous avez créée. Je l'aime beaucoup. Dites-moi, l'avez-vous écrite vous-même ou avez-vous utilisé des bibliothèques MQL ?

Je vous remercie.
Non, pas de bibliothèques. Je l'ai conçue moi-même à partir de zéro. En fait, seul CCanvas des originaux a été adapté, rien d'autre.

 
Doerk Hilger #:

Merci.
Non, pas de bibliothèques. Je l'ai développé moi-même à partir de zéro. En fait, seul CCanvas est adapté des originaux, rien d'autre.

Ce n'est pas facile de faire quelque chose comme ça. )

Pour autant que je sache, dans la classe standard Ccanvas il n'y a pas de fonctionnalité pour dessiner un gradient de couleur, comment avez-vous résolu le problème avec un gradient dans votre GUI ?