English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Contrôles graphiques personnalisés. Partie 3. Formulaires

Contrôles graphiques personnalisés. Partie 3. Formulaires

MetaTrader 5Exemples | 22 décembre 2021, 16:56
225 0
Dmitry Fedoseev
Dmitry Fedoseev

 

Introduction

Le premier article « Création d'un contrôle simple » a traité des principes de création de contrôle graphique et a présenté un exemple étape par étape démontrant la création d'un contrôle simple. L'article qui a suivi « Bibliothèque de contrôles » présente un ensemble de contrôles prêts à l'emploi. Il existe encore un autre composant d'interface graphique très important - le formulaire.

Le formulaire représente une partie rectangulaire spécialement désignée de l'écran contre laquelle les contrôles sont affichés. Par ailleurs, le formulaire est aussi un conteneur qui permet de gérer simultanément tous les champs qu'il contient : les masquer, les afficher et les déplacer tous ensemble.

L'article final exposera la création de formulaires et leur utilisation en combinaison avec les contrôles.

Des classes pour travailler avec les formulaires ont été ajoutées au fichier IncGUI.mqh utilisé dans les articles précédents (le nouveau nom de fichier est IncGUI_v3.mqh). En plus des classes pour travailler avec les formulaires, des classes supplémentaires ont été ajoutées au fichier, les classes CHMenu (Menu horizontal) et CVMenu (Menu vertical) ont été mises à jour et quelques erreurs corrigées.

Classes ajoutées :

  • Classe CFrame - Cadre. La classe est identique au cadre créé par la méthode Frame de la classe CWorkPiece.
  • Classe CButton - Bouton. Un bouton normal (OBJ_BUTTON).
  • Classe CLebel - Étiquette. Outre l'affichage de l’étiquette telle que produite par l'objet graphique « Label » (OBJ_LABEL), cette classe permet d'afficher un texte en quelques lignes, les lignes étant séparées par le symbole "\n".

Suite à l'ajout de nouvelles classes, la classe CColorSchemes a été modifiée, comme suit : les couleurs de nouveaux contrôles ont été ajoutées.

Changements dans les classes CHMenu et CVMenu : les changements appliqués permettent de créer des menus à deux niveaux avec des onglets déroulants. Cela sera examiné plus en détail dans la section « Création du menu principal » ci-dessous.

Erreurs : une correction dans la méthode Frame() de la classe CWorkPiece - un numéro de sous-fenêtre pour une étiquette rectangulaire n'a pas pu être configuré. Classe CListMS - Méthodes Selected() et SetSelected() - la taille du tableau est maintenant vérifiée, sinon il était impossible d'utiliser une liste vide.

 

1. Formulaires

Le formulaire est basé sur les objets graphiques « Etiquette rectangulaire » OBJ_RECTANGLE_LABEL avec utilisation de plusieurs boutons OBJ_BUTTON. Visuellement, le formulaire représente un rectangle (Fig. 1) avec une barre dans la partie supérieure du formulaire où sont affichés le nom du formulaire et les boutons de contrôle.

Un bouton de défilement du formulaire (avec une image en forme de main) est situé à gauche, un bouton de minimisation (avec une image rectangulaire) et un bouton d’arrêt (avec une image en forme de croix) sont situés à droite.

Fig. 1. Formulaire

Fig. 1. Formulaire

Pour déplacer le formulaire, appuyez sur le bouton de défilement (le bouton se mettra en position enfoncée) et cliquez n'importe où dans le graphique pour déplacer le formulaire où que vous souhaitez. En conséquence, le bouton de défilement le bouton de déplacement relâchera et le formulaire se déplacera à l'endroit indiqué (son coin supérieur gauche se retrouvera sur le point cliqué).

Lorsque l'emplacement indiqué se trouve au bord du graphique et que le formulaire doit être placé en dehors du bord du graphique, la position du formulaire sera ajustée de manière à ce qu'il soit entièrement visible dans le graphique.

Il est possible de créer plusieurs types de formulaires :

  • Type 0 (Fig. 1) ;
  • Type 1 - avec des boutons supplémentaires « Annuler » et « Appliquer » (Fig. 2) ;
  • Type 2 - avec un bouton « Fermer » supplémentaire (Fig. 3) ;

Fig. 2. Formulaire de type 1 (avec boutons « Annuler » et « Appliquer »)

Fig. 2. Formulaire de type 1 (avec boutons « Annuler » et « Appliquer »)

Fig. 3. Formulaire de type 2 (avec le bouton « Fermer »)

Fig. 3. Formulaire de type 2 (avec le bouton « Fermer »)

Les moyens programmatiques pour travailler avec les formulaires sont représentés par deux classes : CFormBase et CFormTemplate.

La classe CFormBase est une classe de base tandis que CFormTemplate est une sous-classe de la classe CFormBase. En effet et en principe (notamment le principe applicatif), la classe CFormBase est exactement le même contrôle que les autres contrôles décrits précédemment.

La classe CFormBase possède la méthode Init() pour la préparation des contrôles, les méthodes SetPos() et Show() pour l'affichage d'un formulaire (création d'objets graphiques représentant un formulaire), la méthode Hide() pour le masquage, la méthode Refresh() pour le rafraîchissement de l'affichage, méthode Event() pour la gestion des événements et d'autres méthodes comme dans tous les autres contrôles.

L'application d'un formulaire ainsi que l'utilisation des champs commencent par l'appel de la méthode Init(), suivi de la mise en position avec l'utilisation de la méthode SetPos() et de l'activation de l'affichage par la méthode Show() ou bien l'affichage peut être activé en utilisant uniquement la méthode Show() avec des paramètres, et un formulaire peut être masqué en utilisant la méthode Hide().

Un appel de méthode Event() est ajouté à la fonction OnChartEvent() pour garantir la capacité de contrôle du formulaire (déplacement, minimisation, fermeture, etc.). Lorsqu'il est nécessaire d'assurer le fonctionnement du formulaire dans une sous-fenêtre, on utilise la méthode SetSubWindow() qui est appelée juste après l'appel de la méthode Init() ainsi que dans la fonction OnChartEvent() lors de l'événement CHARTEVENT_CHART_CHANGE. Tout est pareil aux autres contrôles.

Alors que les champs standards sont indépendants (ils n'ont pas à être associés à d'autres champs), le formulaire implique l'existence d'une association obligatoire avec d'autres champs, afin d'assurer simultanément l'affichage/masquage des champs situés dans le formulaire ainsi que le masquage/ affichage du formulaire. Ainsi, un fonctionnement synchronisé des méthodes Init(), Show() et Hide() du formulaire et des contrôles associés doit être assuré.

On peut certainement juste appeler (par exemple lors de l'appel de la méthode Show() du formulaire) les méthodes Show() de tous les contrôles relatifs au formulaire, mais lorsque plusieurs formulaires sont utilisés dans le programme, une telle approche aboutira à un code non structuré et gênant pour la compréhension, le débogage et la mise à jour.

On peut faire une copie de la classe de formulaire pour chaque formulaire et y ajouter du code fonctionnel avec des contrôles ; cependant cela entraînera à nouveau le code non structuré (où le code du formulaire ne sera pas séparé du code lié à l'opération de contrôle), une duplication excessive du code où seule la partie de code en charge de la conception et de la fonctionnalité du formulaire pourra être dupliquée ; tout cela compliquera l'application de modifications à toutes les fonctions de formulaire car cela nécessitera des modifications à chaque copie de classe.

La division en classe de base et sous-classe permet de résoudre le problème de la création de plusieurs formulaires, de la synchronisation de l'affichage du formulaire et des contrôles associés et de la séparation claire du code relatif aux différents formulaires. En plus de résoudre les problèmes de base, l'utilisation de la classe et de la sous-classe permettra la future mise à niveau de la classe de base sans avoir à apporter de modifications au travail déjà terminé.

Afin de synchroniser l'appel des méthodes Init(), Show() et Hide() des contrôles et du formulaire, la classe CFormBase présente quelques différences par rapport à la classe de contrôle standard : quelques méthodes virtuelles dans une section protégée :

virtual void MainProperties() {}
virtual void OnInitEvent() {}
virtual void OnShowEvent() {}
virtual void OnHideEvent() {}
virtual void EventsHandler(const int id, const long& lparam, const double& dparam, const string& sparam){}
virtual void OnWindowChangeEvent(int aSubWindow) {}
virtual bool OnCancelEvent() {return(true);}
virtual bool OnApplyEvent()  {return(true);} 

Ces méthodes sont virtuelles, ce qui signifie que la redirection vers les méthodes réelles correspondantes de la sous-classe CFormTemplate s'effectue par elles.

La sous-classe CFormTemplate n'est pas utilisée seule, elle représente un modèle. Afin de créer un nouveau formulaire, faites une copie de la classe CFormTemplate avec un nom unique (copiez simplement le code de la classe CFormTemplate, renommez-le et répétez la même chose pour chaque formulaire). La copie des sous-classes permet de séparer le code relatif aux différentes formes.

Les méthodes Virtuelles sont situées dans la section protégée et seront donc inaccessibles pour un appel qui n'est même pas nécessaire puisque les méthodes sont déjà appelées depuis la classe de base lors de différents événements de formulaire - vous ne devez ajouter qu'un code pour le fonctionnement des contrôles correspondant à ces événements.

Le graphique ci-dessous montre l'interaction entre les fonctions de l'Expert Advisor et les méthodes de classe de contrôle standard. (Fig. 4) et à titre de comparaison l'interaction avec les méthodes de classe de formulaire (Fig. 5).

Fig. 4. Interaction entre les fonctions de l'Expert Advisor et les méthodes de contrôle
Fig. 4. Interaction entre les fonctions de l'Expert Advisor et les méthodes de contrôle

Fig. 5. Interaction entre les fonctions Expert Advisor et les méthodes de classe de formulaire
Fig. 5. Interaction entre les fonctions Expert Advisor et les méthodes de classe de formulaire

Passons en revue le but de chaque méthode en détail :

  • Les méthodes MainProperties() et OnInitEvent() sont appelées à partir de la méthode Init() du formulaire. La méthode MainProperties() définit l'apparence du formulaire (type de formulaire, présence des boutons déplacer, minimiser et fermer). La méthode OnInitEvent() appelle les méthodes Init() de tous les contrôles et définit les valeurs par défaut des contrôles.

  • La méthode OnShowEvent() est appelée à partir de la méthode Show() ; le code d'appel des méthodes Show() de tous les champs y est ajouté.

  • La méthode OnHideEvent() est appelée à partir de la méthode Hide() ; le code d'appel des méthodes Hide() de tous les champs y est ajouté.

  • La méthode EventsHandler() est équivalente à la fonction OnChartEvent() de l'Expert Advisor. La méthode Event() du formulaire est appelée à partir de la fonction OnChartEvent() de l'Expert Advisor et tous les événements de graphique sont simplement redirigés vers cette méthode. Le code d'appel des méthodes Event() de tous les contrôles et la gestion des événements correspondants sont ajoutés à EventsHandler().

  • La méthode OnWindowChangeEvent() est appelée à partir de la méthode SetSubWindow() lors de la modification d'une sous-fenêtre. Le code d'appel des méthodes SetSubWindow() de tous les contrôles y est ajouté. La méthode a un paramètre qui transmet un nouveau numéro de sous-fenêtre à configurer dans tous les contrôles.

  • La méthode OnCancelEvent() est exécutée à la fermeture du formulaire (lors du clic sur le bouton avec une image en forme de croix, les boutons « Annuler » ou « Fermer »). On peut y ajouter un code de contrôle à la fermeture du formulaire, par exemple un appel d'une fenêtre de confirmation pour s'assurer que le formulaire a besoin d’être bien fermé. Si la méthode réagît en retour avec true, le code fermant le formulaire sera complété et le formulaire se fermera ; si la méthode retourne false, l'exécution du code qui ferme le formulaire sera interrompue et le formulaire restera ouvert.

  • La méthode OnApplyEvent() est exécutée en cliquant sur le bouton « Appliquer » du formulaire. Ici (comme dans la méthode OnCancelEvent()), on peut exécuter une vérification et voir si la méthode réagit avec true ou false, pour permettre ainsi ou non au formulaire de se fermer. Cette méthode peut également contenir un code pour enregistrer les valeurs de contrôle afin que les valeurs de contrôle au prochain démarrage de l'Expert Advisor soient les mêmes qu'avant la fermeture du programme. Et à cette fin, les valeurs enregistrées doivent être chargées dans la méthode OnInitEvent() et configurées dans les contrôles.

 

2. Une procédure étape par étape pour créer un nouveau formulaire

Ainsi, une procédure étape par étape pour créer un nouveau formulaire est la suivante :

1. Incluez le fichier IncGUI_v3.mqh.

#include <IncGUI_v3.mqh>
2. Copiez le code de la classe CFormTemplate du fichier IncGUI_v3.mqh dans un fichier de votre Expert Advisor (la sous-classe est à la fin du fichier) et renommez-le (dans l'exemple de l'utilisation de la bibliothèque la sous-classe se nomme CForm). 

 

class CFormTemplate: public CFormBase{
   public:
   protected      void MainProperties()
     {
        m_Name        = "Form";       // Form name. The names of all the controls of this form should start with it.
        m_Width       = 200;           // Form width
        m_Height      = 150;           // Form height
        m_Type        = 1;             // Form type: 0 - without buttons, 1 - with "Apply" and "Cancel" buttons, 2 - with the "Close" button
        m_Caption     = "FormCaption"; // Form caption
        m_Movable     = true;          // Movable form (the button with a hand image is displayed in the top left corner)
        m_Resizable   =  true;         // Form minimizing/maximizing allowed (the button with a rectangle image 
                                           // is displayed in the top right corner)
        m_CloseButton = true;          // Form closing allowed (the button with a cross image is displayed in the top right corner)
     }
      void OnInitEvent() {} 
      void OnShowEvent(int aLeft, int aTop) {}
      void OnHideEvent() {}
      void OnWindowChangeEvent(int aSubWindow) {}
      void EventsHandler(const int id,const long& lparam,const double& dparam,const string& sparam){}
      bool OnApplyEvent()  {return(true);}
      bool OnCancelEvent() {return(true);}
};

On peut créer un fichier d'inclusion séparé pour le code du formulaire, l'inclure dans l'Expert Advisor, y copier le code de la sous-classe CFormTemplate et effectuer le codage restant relatif à l'opération du formulaire dans ce fichier.

En faisant une analogie avec l'utilisation d'un éditeur visuel, cette étape serait assez similaire à celle consistant à cliquer sur le bouton pour créer un nouveau formulaire à la suite duquel un nouveau fichier de formulaire avec des fonctions de divers événements de formulaire apparaîtrait dans le projet.

3. Définissez les propriétés principales du formulaire. Cette étape est exécutée dans la méthode MainProperties() en affectant des valeurs aux variables déclarées dans la classe de base. Des commentaires détaillés sur les objectifs de toutes les variables sont fournis dans le modèle. Vous pouvez noter la similitude de cette étape avec l'utilisation de la fenêtre des propriétés du formulaire dans un éditeur visuel (par exemple VBA dans Excel).

void MainProperties()
{
   m_Name         =  "Form";        // Form name. The names of all the controls of this form should start with this one.
   m_Width        =  200;           // Form width
   m_Height       =  150;           // Form height
   m_Type         =  1;             // Form type: 0 - without buttons, 1 - with "Apply" and "Cancel" buttons, 2 - with the "Close" button
   m_Caption      =  "FormCaption";   // Form caption
   m_Movable      =  true;          // Movable form (the button with a hand image is displayed in the top left corner)
   m_Resizable    =  true;          // Form minimizing/maximizing allowed (the button with a rectangle image 
                                    // is displayed in the top right corner)
   m_CloseButton = true;            // Form closing allowed (the button with a cross image is displayed in the top right corner)
}

On peut remarquer une autre différence entre le formulaire et les autres contrôles - le nom du formulaire est défini dans la méthode MainProperties() au lieu d'être transmis en tant que paramètre de méthode Init().

Le travail principal sur la forme est effectué dans une sous-classe ; chaque sous-classe du formulaire n'est déclarée qu'une seule fois, il n'est donc pas nécessaire de spécifier des noms différents lors de l'appel de la méthode Init() d'une sous-classe du formulaire.

Le seul paramètre pouvant être transmis à la méthode Init() est le paramètre State, encore faut-il préciser que même ce dernier n'est pas obligatoire. La valeur du paramètre State détermine l'état initial du formulaire lorsqu'il est affiché : maximisé ou minimisé. Si la valeur est 1, le formulaire est maximisé (Fig. 1, 2, 3), si la valeur est 2, le formulaire est minimisé (Fig. 6).

Fig. 6. Formulaire minimisé

Fig. 6. Formulaire minimisé

4. Déclaration d’une classe.

CForm frm;

5. Effectuez les étapes standard d'utilisation du contrôle : appeler la méthode Init() du formulaire depuis la fonction OnInit() de l'Expert Advisor, appeler la méthode Deinit() depuis la fonction OnDeinit(), appeler la méthode Event() depuis le OnChartEvent() et, si nécessaire, appeler la méthode SetSubWindow() lors de l'événement CHARTEVENT_CHART_CHANGE.

Le formulaire doit ensuite être visible dans le graphique et répondre aux clics sur les boutons déplacer, minimiser, fermer, etc.

Nous procédons ensuite à l'ajout des contrôles au formulaire.

 

3. Une procédure étape par étape pour ajouter les contrôles au formulaire

  1. Déclaration des contrôles. Si vous devez garantir l'accès aux méthodes de contrôle en dehors du formulaire, les classes de contrôle doivent être déclarées dans la section publique ; si tout le travail peut être effectué dans la classe de formulaire, les classes de contrôle doivent être déclarées dans la section protégée.

  2. Déclaration des variables pour restitution des valeurs de contrôle. Une étape facultative. Si vous allez utiliser le formulaire avec les boutons « Annuler » et « Appliquer », une variable doit être ajoutée à chaque contrôle pour stocker la valeur que le contrôle avait à l'ouverture du formulaire afin de restaurer la valeur si un utilisateur change la valeur de contrôle mais appuie sur le bouton « Annuler ».

  3. Appel des méthodes Int() de tous les contrôles. Il est exécuté dans la méthode OnInitEvent().

  4. Chargement des données enregistrées. Une étape facultative. Il est exécuté dans la méthode OnInitEvent(). L'étape est utilisée lorsqu'il est nécessaire que les champs conservent leurs valeurs après redémarrage de l'Expert Advisor, du Terminal ou de l'ordinateur. La sauvegarde des données est effectuée à l'étape 12.

  5. Configuration des valeurs par défaut. Dans cette étape, tous les contrôles sont définis à des valeurs qui seront vues dans les contrôles lors de la première ouverture du formulaire après le démarrage de l'Expert Advisor (jusqu'à ce que leurs valeurs soient modifiées par un utilisateur). Si les données ont été chargées à l'étape 4, les données chargées sont utilisées. Une préparation supplémentaire des contrôles est également effectuée au cours de cette étape, par exemple des éléments de liste et de menu sont également ajoutés ici.

  6. Les méthodes Calling the Show() (version avec paramètres) pour tous les champs est exécuté dans la méthode OnShowEvent(). La méthode OnShowEvent() a deux paramètres (int aLeft, int aTop) qui transmettent les coordonnées du coin supérieur gauche de l'espace de travail du formulaire. Les positions de contrôle sont définies en fonction des valeurs de ces variables (les valeurs doivent être ajoutées).

  7. La méthode A call of the Hide() pour tous les champs du formulaire est exécuté dans la méthode OnHideEvent().

  8. Appel de la méthode SetSubWindow(). Une étape facultative. S'il est nécessaire d'afficher le formulaire dans une sous-fenêtre, la méthode SetSubWindow() est appelée pour tous les champs. Il est exécuté dans la méthode OnWindowChangeEvent() qui a un paramètre (int aSubWindow) qui transmet un nouveau numéro de sous-fenêtre.

  9. Les méthodes Calling the Event() de tous les contrôles. Cela est exécuté dans la méthode EventsHandler().

  10. Gestion des événements de contrôle. Une étape facultative. S'il est nécessaire d'assurer l'interaction entre les contrôles sur leurs événements, c'est à cette étape que les événements sont traités et que les actions appropriées sont exécutées. Cela est exécuté dans la méthode EventsHandler().

  11. Application de nouvelles valeurs. Une étape facultative qui est exécutée à l'aide du bouton « Appliquer ». Elle est exécutée dans la méthode OnApplyEvent(). Dans cette étape, les valeurs de contrôle sont vérifiées pour exactitude ; si des valeurs incorrectes sont trouvées, l'utilisateur doit en être informé, la méthode retournera une valeur false et le formulaire restera ouvert. Si les valeurs sont correctes, true doit être renvoyé pour que le formulaire se ferme.

  12. Enregistrement des données. Une étape facultative. Elle est exécutée dans la méthode OnApplyEvent() en utilisant le bouton « Appliquer ». Les données peuvent être enregistrées (selon objectifs et finalités) dans un fichier, des variables globales, des objets invisibles dans le graphique, etc.

  13. Vérification par la méthode OnCancelEvent(). Une étape facultative. Si false est renvoyé par la méthode OnCancelEvent(), le formulaire restera ouvert, c'est-à-dire que le bouton de fermeture ne répondra pas. Pour que le formulaire se ferme, la méthode doit renvoyer true.

Un exemple de travail avec des formulaires peut être trouvé dans le fichier eIncGUI_v3_Test_Form.mq5 en annexe. Le formulaire principal avec différents contrôles s'ouvre au démarrage (Fig. 7).

Notez que le formulaire n'a pas de bouton de fermeture ; c'est le formulaire principal et il ne faut pas le faire disparaître du graphique sinon l'Expert Advisor devra être redémarré pour que le formulaire réapparaisse.

Fig. 7. Formulaire principal de l'exemple eIncGUI_v3_Test_Form.mq5 avec un onglet de menu principal ouvert

Fig. 7. Formulaire principal de l'exemple eIncGUI_v3_Test_Form.mq5 avec un onglet de menu principal ouvert

À l'aide des commandes du menu principal, vous pouvez ouvrir les deux autres variantes du formulaire.

Menu principal - Types de formulaires - Le type 1 ouvre un formulaire de type 1 (avec les boutons « Annuler » et « Appliquer »).
Menu principal - Types de formulaires - Le type 2 ouvre un formulaire de type 2 (avec le bouton « Fermer »).

Les deux formulaires nécessitent une confirmation lors de leur fermeture (effectuée à l'aide de la fonction MessageBox()). Le formulaire de type 1 a une zone de saisie ; une valeur d'entrée est vérifiée en cliquant sur le bouton « Appliquer ». Le formulaire de type 2 a un nouveau contrôle « Label » (classe CLabel) et quelques boutons (classe CButton) pour le tester.

Maintenant, comme mentionné dans l'introduction, passons en revue les changements dans les classes CHMenu et CVMenu comme illustré par la création du menu principal.

 

Tout d'abord, je voudrais dire que seuls des menus à deux niveaux peuvent être créés : une barre horizontale (basée sur la classe CHMenu) et des onglets (basés sur la classe CVMenu). En principe, il est possible de créer encore plus de niveaux mais le processus sera très compliqué et laborieux c'est pourquoi il n'est pas recommandé et ne sera plus envisagé.

En fait, la création du menu principal du formulaire n'était même pas prévue, et les classes CHMenu et CVMenu étaient censées être utilisées individuellement et indépendamment les unes des autres pour activer/désactiver diverses fonctions et instruments. Cependant une légère amélioration des classes CHMenu et CVMenu a permis d'obtenir le menu principal qui est assez approprié pour la majorité des cas.

Afin de créer un menu à plusieurs niveaux à part entière, une approche quelque peu différente doit être appliquée (création d'une structure de données en forme d'arbre) qui peut servir de sujet pour un article séparé, nous allons donc dès lors nous en tenir aux modes existants.

Passons d'abord en revue tous les changements et corrections appliqués aux classes CHMenu et CVMenu.

Dans la classe CVMenu, une réponse au clic sur l'objet graphique « Label » a été corrigée et est utilisée pour afficher le symbole du trait. En conséquence, il y a eu des changements dans le fonctionnement des méthodes LastClickedX(), LastClickedY() et LastClickedQuarter(). Lorsque vous cliquez sur les valeurs des étiquettes, elles sont maintenant renvoyées comme dans le cas des zones de texte. Des corrections similaires ont été appliquées à la classe CHMenu et aux méthodes LastClickedX(), LastClickedY(), LastClickedQuarter() et LastClickedW().

Les deux classes ont été mises à jour en ajoutant les méthodes SolvePosX() et SolvePosY() qui sont destinées à calculer les coordonnées d'un objet graphique affiché dans la commande de menu. La largeur de l'objet affiché est transmise à la méthode SolvePosX() et la hauteur de l'objet affiché est transmise à la méthode SolvePosY() qui renvoie respectivement la coordonnée X ou Y de l'objet affiché. Désormais, il n'est plus nécessaire d'utiliser les méthodes LastClickedX(), LastClickedY(), LastClickedQuarter() et LastClickedW().

Les deux classes ont été mises à jour en ajoutant les méthodes LastClickedName1() et LastClickedName2(). Ces méthodes renvoient les noms des objets graphiques formant le dernier élément de menu cliqué. LastClickedName1() renvoie le nom de la zone de texte, LastClickedName2() renvoie le nom de l'étiquette du symbole de trait.

Les méthodes ToggleNameAdd() et ToggleNamesClear() ont été ajoutées à CVMenu. La méthode ToggleNameAdd() est utilisée pour créer une liste de noms « toggle », la méthode ToggleNamesClear() est utilisée pour effacer cette liste. Lors de l'utilisation de la méthode ToggleNameAdd() (ajout d'un nom à la liste), le menu se fermera automatiquement à tout événement du graphique à l'exception des événements des objets graphiques formant le menu et des objets graphiques dont les noms ont été ajoutés par la méthode ToggleNameAdd() . Le menu revient au mode de fonctionnement normal lorsque la liste est effacée par la méthode ToggleNamesClear().

Le fonctionnement du menu à deux niveaux est le suivant : lorsque l'événement de clic sur l'élément de menu horizontal est défini par les méthodes LastClickedName1() et LastClickedName2(), nous obtenons les noms des objets de cet élément qui sont ensuite transmis à ToggleNameAdd() du menu vertical.

Ensuite, le menu vertical sera masqué sur n'importe quel graphique, même à l'exception des événements du menu vertical et d'un élément de menu horizontal (au moyen duquel le menu vertical a été ouvert).

Si un utilisateur sélectionne un élément du menu vertical, le menu vertical doit être fermé et les actions correspondant à cet élément doivent être exécutées. Si un utilisateur a cliqué à plusieurs reprises sur le même élément de menu horizontal (au moyen duquel le menu vertical a été ouvert), le menu vertical doit être masqué.

Passons en revue un exemple de création de menu t/phe.

Le menu principal a trois éléments, nous avons donc besoin de trois menus verticaux. Déclarez une classe de menu horizontal et trois classes de menu vertical dans la section publique de la sous-classe de formulaire (l'exemple ci-dessous le montre exactement de la même manière que dans l'exemple eIncGUI_v3_Test_Form.mq5) :

class CForm: public CFormBase{
public:
   CHMenu m_hm;
   CVMenu m_vm1;
   CVMenu m_vm2;
   CVMenu m_vm3; 

Initialisez les classes de menu dans la méthode OnInitEvent() et ajoutez des éléments de menu :

// Horizontal menu
m_hm.Init(m_Name+"_HM",m_Width,2);
// Adding horizontal menu items
m_hm.AddItem("Form types");
m_hm.AddItem("Item-2");
m_hm.AddItem("Item-3");
// Vertical menu 1
m_vm1.Init(m_Name+"_VM1",70,10); 
// Adding items to vertical menu 1
m_vm1.AddItem("Type-1");
m_vm1.AddItem("Type-2");
// Vertical menu 2
m_vm2.Init(m_Name+"_VM2",70,3);
// Adding items to vertical menu 2
m_vm2.AddItem("Item-2-1");
m_vm2.AddItem("Item-2-2");
m_vm2.AddItem("Item-2-3"); 
m_vm2.AddItem("Item-2-4");
m_vm2.AddItem("Item-2-5"); 
// Vertical menu 3
m_vm3.Init(m_Name+"_VM3",70,3);
// Adding items to vertical menu 3
m_vm3.AddItem("Item-3-1");
m_vm3.AddItem("Item-3-2");
m_vm3.AddItem("Item-3-3"); 
m_vm3.AddItem("Item-3-4");
m_vm3.AddItem("Item-3-5"); 

Masquez le menu dans la méthode OnHideEvent() :

void OnHideEvent()
{
   m_hm.Hide(); 
   m_vm1.Hide(); 
   m_vm2.Hide(); 
   m_vm3.Hide(); 
}

Affichez le menu horizontal dans la méthode OnShowEvent() :

void OnShowEvent(int aLeft,int aTop)
{
    m_hm.Show(aLeft,aTop); 
}

Enfin, le travail principal dans la méthode EventsHandler().

Appel des méthodes Event() de tous les menus :

void EventsHandler(const int id,const long& lparam,const double& dparam,const string& sparam)
{
    int m_event0=m_hm.Event(id,lparam,dparam,sparam);
    int m_event1=m_vm1.Event(id,lparam,dparam,sparam);
    int m_event2=m_vm2.Event(id,lparam,dparam,sparam);
    int m_event3=m_vm3.Event(id,lparam,dparam,sparam); 

En fonction de la valeur m_event0 (indice d'élément de menu horizontal), travaillez avec le menu vertical approprié (par exemple avec l'élément 0 et le menu vertical 1) :

if(m_event0==0)
{ // Clicking item 0
   if(m_vm1.Visible())
   { 
      m_vm1.Hide(); // If the vertical menu is open, close it
   }
   else{ // If the vertical menu is closed
      m_vm1.ToggleNamesClear(); // Clear the list of "toggle" names
      // Add to the list the names of the graphical objects forming the item 
      // of the horizontal menu which led to the last event 
      // of the horizontal menu 
      m_vm1.ToggleNameAdd(m_hm.LastClickedName1()); 
      m_vm1.ToggleNameAdd(m_hm.LastClickedName2());
      // Display the vertical menu
      m_vm1.Show(m_hm.SolvePosLeft(m_vm1.Width()),m_hm.SolvePosTop(m_vm1.Height())); 
   }
}

De telles actions doivent être effectuées pour tous les éléments de menu horizontaux qui ouvrent le menu vertical. Si l'événement de menu vertical s'est produit, fermez le menu.

En fonction de l'index de l'élément cliqué, procédez comme suit :

if(m_event1>=0)
{ // Vertical menu event 1
   m_vm1.Hide(); // Hide the menu
      if(m_event1==0)
      { // Clicking item 0
        //...
      }
      if(m_event1==1)
      { // Clicking item 1
        //...
      }
}

De telles actions doivent être effectuées pour tous les menus verticaux et tous leurs éléments.

La création du menu principal est maintenant terminée.

 

Conclusion

Cet article finalise la série d'articles consacrée à la création d'une interface graphique.

Grâce à notre travail, nous disposons d'un arsenal de moyens assez considérable pour une création rapide d'une interface graphique multifonctionnelle et facile à utiliser. Ceci est tout à fait cohérent avec les exigences existantes pour une interface graphique :

  • Utiliser le cadre dans le formulaire d'une légende et un formulaire minimisé/maximisé, déplacé ;
  • Zones de code clairement désignées liées à un formulaire ou un autre ;
  • L'affichage/masquage des champs est synchronisé avec l'affichage/masquage du formulaire.

Tous les contrôles et le formulaire ont une conception et un schéma de couleurs communs qui peuvent être rapidement modifiés.

Répétons la procédure de création d'un formulaire.

Une brève procédure pour créer un formulaire :

  1. Inclure le fichier IncGUI_v3.mqh.

  2. Faire une copie de la classe CFormTemplate avec un nom unique et déclarez cette classe.

  3. Configurer les propriétés du formulaire dans la méthode MainProperties() de la copie de la sous-classe.

  4. Appeler les méthodes Init(), Hide() et Event() du formulaire respectivement à partir des fonctions OnInit(), OnDeinit() et OnChartEvent() de l'Expert Advisor. Appeler la méthode Show() à partir de la fonction OnInit() de l'Expert Advisor ou en cas de besoin.

  5. Travailler avec les contrôles. Déclarer les classes de contrôle dans la copie de la sous-classe. Appeler les méthodes Init(), Show(), Hide() et Event() des contrôles à partir des méthodes OnInitEvent(), OnShowEvent(), OnHideEvent() et EventHandler() de la copie de sous-classe.

 

Annexe

Liste des fichiers ajoutés :

  • IncGUI_v3.mqh - un fichier d'inclusion contenant toutes les classes pour créer une interface graphique. Le fichier doit être placé dans le répertoire MQL5/Include du Répertoire de données du terminal.
  • eIncGUI_v3_Test_Form.mq5 - un exemple de travail avec des formulaires. Le fichier doit être placé dans le répertoire MQL5/Experts du Répertoire de données du terminal.
  • IncGUIv3mqh.chm - documentation du fichier IncGUI_v3.mqh.

Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/322

Accélération des calculs avec le réseau cloud MQL5 Accélération des calculs avec le réseau cloud MQL5
Combien de cœurs avez-vous sur votre ordinateur personnel ? Combien d'ordinateurs pouvez-vous utiliser pour optimiser une stratégie de trading ? Nous montrons ici comment utiliser le réseau cloud MQL5 pour accélérer les calculs en recevant la puissance de calcul à travers le monde d'un simple clic de souris. L'expression « Le temps, c'est de l'argent » devient de plus en plus d'actualité d'année en année, et nous ne pouvons pas nous permettre d'attendre des calculs importants pendant des dizaines d'heures, voire des jours.
Contrôles graphiques personnalisés. Partie 2. Bibliothèque de contrôle Contrôles graphiques personnalisés. Partie 2. Bibliothèque de contrôle
Le deuxième article de la série « Contrôles graphiques personnalisés » présente une bibliothèque de contrôles permettant de traiter les principaux problèmes d'interaction entre un programme (Expert Advisor, script, indicateur) et un utilisateur. La bibliothèque contient un grand nombre de classes (CInputBox, CSpinInputBox, CCheckBox, CRadioGroup, CVSсrollBar, CHSсrollBar, CList, CListMS, CComBox, CHMenu, CVMenu, CHProgress, CDialer, CDialerInputBox, CTable) et des exemples de leur utilisation.
Créez vos propres panneaux graphiques en MQL5 Créez vos propres panneaux graphiques en MQL5
La convivialité du programme MQL5 est déterminée à la fois par sa riche fonctionnalité et par une interface utilisateur graphique élaborée. La perception visuelle est parfois plus importante qu'un fonctionnement rapide et stable. Voici un guide étape par étape pour créer vous-même des panneaux d'affichage sur la base des classes de la bibliothèque standard.
Contrôles graphiques personnalisés. Partie 1 : Création d'un contrôle simple Contrôles graphiques personnalisés. Partie 1 : Création d'un contrôle simple
Cet article couvre les principes généraux de développement des contrôles graphiques. Nous allons préparer des outils pour un travail rapide et pratique avec des objets graphiques, analyser un exemple de création d'un champ simple de saisie de texte ou de données numériques ainsi que les manières de l'utiliser.