English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
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

MetaTrader 5Exemples | 22 décembre 2021, 16:51
192 0
Dmitry Fedoseev
Dmitry Fedoseev

Introduction

Le langage MQL5 fournit aux développeurs une large gamme d'objets graphiques contrôlés par programmation : un bouton, une étiquette de texte, un champ d'édition, une étiquette bitmap (fig. 1), différents outils graphiques d'analyse (fig. 2).


Fig. 1. Objets graphiques : un bouton, une étiquette de texte, un champ d'édition, une étiquette bitmap


Fig. 2. Quelques objets graphiques à analyser : une ellipse, le Fan de Fibonacci, l'expansion de Fibonacci

Il y a au total plus de quarante objets graphiques dans le terminal client MetaTrader 5. Tous ces objets peuvent être utilisés séparément, mais le plus souvent ils sont utilisés dans une chaîne d'objets interconnectés. Par exemple, lorsqu'un champ d'édition (OBJ_EDIT) est utilisé, une étiquette bitmap (OBJ_LABEL) est utilisée avec lui très souvent pour indiquer la fonction du champ d'édition.

Lorsque vous utilisez un champ d'édition, vous devez souvent vérifier l'exactitude des données saisies par un utilisateur et offrir la possibilité d'utiliser à la fois un point et une virgule comme séparateur décimal.

Lorsque vous utilisez une sortie de données par programmation, vous devez formater les données. Par exemple, vous devez supprimer les zéros inutiles. Ainsi, il serait plus facile d'avoir un seul objet qui inclut le champ d'édition, l'étiquette bitmap et quelques autres fonctionnalités opérationnelles.

Actuellement, il existe un certain ensemble de contrôles graphiques dans le monde de la programmation, qui est utilisé dans presque toutes les applications : un formulaire (la base d'une interface d'application, où se trouvent tous les éléments de contrôle), un cadre (il permet le regroupement et la séparation des ensembles d'éléments qui ont un objectif fonctionnel), un bouton, un champ d'édition, une étiquette, une case à cocher, des boutons radio, des barres de défilement verticales et horizontales, une liste, une liste déroulante, une ligne de menu, un onglet de menu (fig . 3). 

 
Fig. 3. Le formulaire avec les contrôles standard les plus courants

La façon dont les éléments mentionnés ci-dessus sont représentés dans MQL5 est similaire à d'autres langages de programmation (un bouton et un champ d'édition). Il serait pratique d'avoir d'autres contrôles répandus dans votre arsenal.

Plusieurs environnements de développement fournissent aux programmeurs des outils spéciaux pour la création de contrôles personnalisés. MQL5 ne fournit pas une telle fonctionnalité. Cependant, comme MQL5 est un langage orienté-objet, il n'est pas nécessaire de l'avoir. Tout peut se faire sous forme d'objets programmés séparés.

Les principes et la méthodologie de création de contrôles personnalisés seront discutés plus loin dans cet article. Sur leur base, toute personne compétente en programmation peut créer un ensemble de contrôles requis qui peuvent être utilisés à plusieurs reprises dans les applications.


1. Ce que devrait être un contrôle graphique

1.1. Exigences et principes généraux

Pour être utiles, les contrôles graphiques doivent faciliter le développement des applications. Pour ce faire, ils doivent satisfaire aux exigences suivantes :

  1. Il devrait être possible de créer rapidement un contrôle pendant le développement. Ce problème est résolu en utilisant l'approche orientée objet de la programmation. Un contrôle graphique est représenté comme un objet programmé.
     
  2. Un contrôle doit être flexible. Autrement dit, il devrait être possible de modifier ses propriétés : taille, position, couleur, etc.
     
  3. Un contrôle doit être facile à utiliser - il ne doit avoir que les propriétés et les méthodes requises, dont le but est compréhensible à partir du but de l'élément et des noms des méthodes. Divisons maintenant les propriétés des contrôles en catégories :
     
    1. Propriétés non contrôlées. Ces propriétés incluent le schéma de couleurs. Tous les contrôles utilisés dans une application doivent avoir un style général. C'est pourquoi le réglage des couleurs pour chaque contrôle individuellement serait épuisant.
      De plus, rechercher une couleur pour certains contrôles est une tâche assez difficile pour laquelle je ne veux pas perdre de temps. Par exemple, une barre de défilement. Certains développeurs Web ont peut-être été confrontés à cette tâche intéressante.
       
    2. Propriétés définies au stade de la création d'un champ ou propriétés rarement modifiées. Par exemple, la taille d'une commande. La position équilibrée et pratique de toutes les commandes utilisées dans une application est une tâche spéciale et difficile qui est résolue lors de la création de l'interface.
      En relation avec cela, la taille des commandes n'est généralement pas modifiée pendant l'exécution du programme. Cependant, vous devrez parfois modifier ces propriétés. C'est pourquoi vous devez offrir la possibilité de modifier ces propriétés pendant le fonctionnement du programme.
       
    3. Principales propriétés opérationnelles. Propriétés qui changent fréquemment à partir du programme. Les propriétés qui constituent le but d'un contrôle. Ces propriétés peuvent être divisées en deux catégories :
       
      1. Propriétés avec mise à jour automatique de l'affichage d'un champ. Par exemple, une modification. Une fois qu'une valeur est définie par le programme, les modifications doivent être affichées à l'écran. En programmation, cela s’effectue à l'aide d'une seule ligne de code.
         
      2. Propriétés qui nécessitent un rafraîchissement obligatoire de l'affichage. Par exemple, une liste. Les listes impliquent de travailler avec des tableaux de données, c'est pourquoi une liste ne doit pas être actualisée après avoir travaillé avec un seul élément de la liste. Ici, il est préférable d'effectuer une mise à jour obligatoire à la fin en travaillant avec tous les éléments de la liste. Cette approche augmente considérablement les performances de l'application.
         
  4. Une possibilité de masquage et d'affichage rapide et simple de la commande. Rendre un contrôle visible ne devrait pas nécessiter la configuration répétée des propriétés d'affichage ; l'accès aux propriétés de l'objet doit être indépendant de la visibilité des objets graphiques de cette commande. En d'autres termes, un objet programmé doit contenir toutes les propriétés de la commande et ne doit pas utiliser les propriétés des objets graphiques.
      
  5. Afin d'avoir une sortie d'événements qui correspondent à la commande, il doit y avoir un traitement des événements d'objets graphiques individuels qui sont inclus dans la commande.

1.2. La façon d'utiliser une commande et les méthodes requises 

Compte tenu des exigences mentionnées ci-dessus, nous avons le schéma suivant de création d'une interface graphique ainsi que l'ensemble des propriétés et méthodes requises d'un objet programmé :

  1. Initialisation d'une commande et mise en parallèle de propriétés rarement modifiées. Cette méthode sera appelée Init() ; elle a plusieurs paramètres. Le 1er obligatoire - le nom d'une commande. Ce paramètre sera utilisé comme préfixe pour les noms de tous les objets graphiques inclus dans le champ. De plus, les paramètres qui définissent la taille de la commande et d'autres paramètres peuvent être inclus (en fonction de l'objectif de la commande).
     
  2. Les commandes peuvent avoir un emplacement fixe sur une carte et peuvent nécessiter une possibilité de déplacement. Ainsi, nous allons utiliser des méthodes distinctes pour déterminer les coordonnées : SetPosLeft() - définition de la coordonnée X, SetPosTop() - définition de la coordonnée Y. Chacune de ces méthodes doit avoir un paramètre. Très souvent, il est nécessaire de changer les deux coordonnées, il est donc bon d'avoir la méthode SetPos() avec deux paramètres, qui modifie simultanément les coordonnées X et Y.
    Pour calculer l'emplacement d'une commande, vous devrez peut-être obtenir des informations sur la taille et l'emplacement d'une autre commande. Pour cela, nous allons utiliser les méthodes suivantes : Width() - largeur, Height() - hauteur, Left() - la coordonnée X, Top() - la coordonnée Y. À ce stade de l'opération, les coordonnées de la commande sont calculées et les méthodes de réglage sont appelées.
     
  3. Juste après la création ou à une autre étape de fonctionnement de l'application, nous devons rendre le champ visible. Pour ce faire, la méthode Show() est d’usage. Pour masquer la commande, la méthode Hide() est utilisée.
     
  4. Comme il a été mentionné précédemment, pendant le fonctionnement du programme, nous pourrions avoir besoin de modifier la taille de la commande. C'est pourquoi l'objet programmé doit avoir des méthodes distinctes pour définir la taille - SetWidth() et/ou SetHeght(). Étant donné que ce sont des propriétés rarement modifiées, pour que les modifications prennent effet, nous devons appeler la méthode Refresh(), qui met à jour l'affichage.

  5. Les événements des objets graphiques individuels seront traités dans la méthode Event(), qui renverra une valeur qui correspond à un événement spécifique de la commande. La méthode Event() doit être appelée à partir de la fonction OnChartEvent() ; elle aura le même ensemble de paramètres que la fonction OnChartEvent().

On obtient ainsi l'ensemble des méthodes requises d'un objet programmé :

  • void Init(string aName...) - initialisation de la commande ;
  • void SetPosLeft(int aLeft) - réglage de la coordonnée X ;
  • void SetPosTop(int aTop) - réglage de la coordonnée Y ;
  • void SetPos(int aLeft, int aTop) - réglage simultané des coordonnées X et Y ;
  • void SetWidth(int aWidth) - réglage de la largeur ;
  • void SetHeght(int aHeight) - réglage de la hauteur ;
  • int Width() - acquisition de largeur ;
  • int Height() - acquisition de hauteur ;
  • int Left() - acquisition de la coordonnée X ;
  • int Top() - acquisition de la coordonnée Y ;
  • void Refresh() - rafraîchissement complet de l'affichage ;
  • void Show() - affichage ;
  • void Hide() - masquage ;
  • int Event(const int id, const long & lparam, const double & dparam, const string & sparam) - traitement d’événements de graphique ;

La présence des autres méthodes (ou l'absence de certaines des méthodes répertoriées) dépend de la commande elle-même et de sa finalité.

Plus loin dans cet article, nous allons essayer de mettre en œuvre les principes décrits ci-dessus - nous allons créer une commande permettant à un utilisateur de saisir un texte ou un nombre.

Avant cela, nous devons nous doter d'outils pour un travail rapide et pratique avec des objets graphiques.


2. Comment travailler avec des objets graphiques rapidement et facilement

Pour travailler avec des objets graphiques, MQL5 fournit les fonctions de base suivantes : ObjectCreate(), ObjectDelete(), ObjectSetDouble(), ObjectSetInteger(), ObjectSetString(), ObjectGetDouble(), ObjectGetInteger(), ObjectGetString(). Nous pouvons utiliser ces fonctions directement, mais le processus de programmation sera très laborieux et long. Les fonctions ont des noms longs ; beaucoup d'identifiants qui ont des noms longs doivent être transmis aux fonctions.

Pour rendre le travail avec des objets graphiques plus pratique, nous pouvons utiliser une classe prête à l'emploi qui est incluse dans le paquet du terminal client MetaTrader 5 (la classe CChartObject du fichier MQL5/Include/ChartObjects/ChartObject.mqh), ou nous pouvons écrire notre propre classe et lui doter toutes les méthodes nécessaires.

Pour le dire plaisamment, cette approche de la programmation consiste à appuyer sur une touche suivie d'un point. Après avoir spécifié le nom d'un objet, il suffit de mettre un point et la liste de ses propriétés et méthodes s'ouvre, pour vous permettre alors de choisir un élément nécessaire dans la liste (fig. 4).


Fig. 4. La liste des propriétés et méthodes de l'objet

Il existe deux variantes de gestion d'un objet graphique à l'aide de la classe auxiliaire :

  1. Une instance de classe individuelle est créée pour chaque objet graphique. Méthode assez pratique mais pas économique du point de vue de la quantité de mémoire consommée. Pour cette variante, il est préférable d'écrire des classes spéciales pour chaque type d'objet graphique. Mais cette approche n'est pas optimale car très laborieuse. Contrairement à la programmation des Expert Advisors, il n'y a pas d'exigence stricte sur les performances maximales lors de la création d'une interface utilisateur.
  2. Utilisez une instance de classe. S'il est nécessaire de gérer un objet graphique, l'objet est ajouté à la classe. Nous allons utiliser la deuxième variante.

Créons une classe universelle qui convient le mieux au deuxième type de gestion des objets graphiques.


3. La classe universelle de gestion des objets graphiques

Lors de la programmation, le travail avec chaque objet graphique se compose de trois étapes : création, lecture/réglage des propriétés, suppression en fin d'exploitation de l'application.

Donc tout d'abord, la classe de gestion des objets graphiques doit contenir les méthodes qui les créent. Un paramètre obligatoire pour la création d'un objet graphique est son nom ; ainsi les méthodes de création d'objets auront un paramètre obligatoire pour spécifier un nom d'un objet créé.

Habituellement, des objets graphiques sont créés sur le graphique, où le programme (Expert Advisor, Indicateur ou Script) est exécuté. Un cas plus rare est une sous-fenêtre, et un cas encore plus rare est une autre fenêtre graphique du terminal. Ainsi le deuxième paramètre optionnel sera celui qui précise le numéro d'une sous-fenêtre ; et le troisième est l'identifiant d'un graphique.

Par défaut, les deux paramètres optionnels seront égaux à 0 (le graphique des prix est sur son « propre » graphique). Recherchez la liste de types d’objets graphiques dans la documentation. Ajoutez la méthode Create pour chaque type.

Avant cela, nous devons créer un fichier. Pour ce faire, ouvrez MetaEditor, créez un nouveau fichier d'inclusion et appelez-le IncGUI.mqh. Dans le fichier ouvert, créez la classe CGraphicObjectShell avec les sections protected et public. Dans la section protected, déclarez des variables pour le nom d'un objet et l'identifiant d'un graphique.

Dans les méthodes de création d'objets, ces variables se verront affecter les valeurs passées par les méthodes en paramètres, afin d'avoir la possibilité de les gérer après création d'objet sans spécifier de nom et d'identifiant de graphique. Ainsi on peut aussi utiliser la classe pour la première variante de gestion des objets graphiques.

Pour avoir la possibilité d'utiliser la classe pour la deuxième variante (en vue de gérer n'importe quel objet graphique), donnez-lui une méthode d'attachement d'un objet graphique (la méthode Attach()). Cette méthode aura un paramètre obligatoire - le nom d'un objet graphique, et un paramètre facultatif - un identifiant de graphique. Peut-être aurez-vous besoin de connaître le nom et l'identifiant d'un objet graphique attaché. Pour ce faire, ajoutez les méthodes suivantes à l'objet : Name() et ChartID().

En conséquence, nous obtenons le « produit » suivant de la classe : 

class CGraphicObjectShell
  {
protected:
   string            m_name;
   long              m_id;
public:
   void Attach(string aName,long aChartID=0)
     {
      m_name=aName;
      m_id=aChartID;
     }
   string Name()
     {
      return(m_name);
     }    
   long ChartID()
     {
      return(m_id);
     }
  };

Ajoutez les méthodes de création d'objets graphiques mentionnées ci-dessus. Les noms de ces méthodes commenceront par « Créer ».

Les lecteurs peuvent l'ignorer, le fichier IncGUI.mqh joint à l'article contient la classe CGraphicObjectShell prête à l'emploi.

À titre d'exemple, voici une méthode de création de l'objet graphique de ligne verticale (OBJ_VLINE) :

void CreateVLine(string aName,int aSubWindow=0,long aChartID=0)
  {
   ObjectCreate(m_id,m_name,OBJ_VLINE,aSubWindow,0,0);
   Attach(aName,aChartID);
  }

Ouvrez maintenant la liste des propriétés des objets graphiques dans le guide de l'utilisateur ; et écrivez des méthodes de définition d'une valeur pour chaque propriété à l'aide des fonctions ObjectSetDouble(), ObjectSetInteger() et ObjectSetString(). Le nom des méthodes commencera par « Set ». Ensuite, écrivez des méthodes pour lire les propriétés à l'aide des fonctions ObjectGetDouble() et ObjectGetInteger(). ObjectGetString().

À titre d'exemple, voici des méthodes pour définir et obtenir la couleur :

void SetColor(color aColor)
  {
   ObjectSetInteger(m_id,m_name,OBJPROP_COLOR,aColor);
  }
color Color()
  {
   return(ObjectGetInteger(m_id,m_name,OBJPROP_COLOR));
  }

Eh bien, nous semblons maintenant avoir le minimum d'outils requis pour travailler avec des objets graphiques, mais pas tous.

Parfois, lorsque vous travaillez avec un objet graphique, vous devrez peut-être effectuer une seule action avec un objet. Dans ce cas, il ne sera pas pratique d'exécuter la méthode Attach() pour l'objet, puis de revenir à l'objet principal et d'exécuter à nouveau Attach() pour lui.

Ajoutons deux variantes supplémentaires de toutes les méthodes de définition/acquisition de propriétés à la classe.

La première - par son nom sur son « propre » graphique :

void SetColor(string aName,color aColor)
  {
   ObjectSetInteger(0,aName,OBJPROP_COLOR,aColor);
  }
color Color(string aName)
  {
   return(ObjectGetInteger(0,aName,OBJPROP_COLOR));
  }

La deuxième - par nom et identifiant d'un graphique :

void SetColor(long aChartID,string aName,color aColor)
  {
   ObjectSetInteger(aChartID,aName,OBJPROP_COLOR,aColor);
  }
color Color(long aChartID,string aName)
  {
   return(ObjectGetInteger(aChartID,aName,OBJPROP_COLOR));
  }

En plus des fonctions ObjectGet... et ObjectSet..., il existe d'autres fonctions pour travailler avec des objets graphiques : ObjectDelete(), ObjectMove(), ObjectFind(), ObjectGetTimeByValue(), ObjectGetValueByTime(), ObjectsTotal(). Elles peuvent également être ajoutées à la classe avec trois variantes d'appel de chacun.

Enfin, déclarez la classe CGraphicObjectShell avec un nom simple et court « g » dans ce fichier. 

CGraphicObjectShell g;

Maintenant, pour commencer à travailler avec des objets graphiques, il suffit de connecter le fichier IncGUI.mqh ; nous aurons donc la classe « g » avec laquelle travailler. En l'utilisant, il est facile de gérer tous les objets graphiques disponibles.


4. Produits relatifs aux commandes

Bien que nous ayons la classe pour travailler rapidement avec des objets graphiques, nous pouvons créer des commandes plus facilement. Tous les champs peuvent être créés à partir de quatre objets graphiques :

  1. Label rectangle (OBJ_RECTANGLE_LABEL),
  2. Label de texte (OBJ_LABEL),
  3. Champ d'édition (OBJ_EDIT),
  4. Bouton (OBJ_BUTTON).

Après la création d'objets graphiques, de nombreuses propriétés doivent être définies pour eux : coordonnées, taille, couleur, taille de police, etc. Pour accélérer le processus, créons une autre classe et nommons-la CWorkPiece (produits) et fournissons-lui des méthodes de création d'objets graphiques avec des propriétés passées en paramètres. 

Pour que les commandes fonctionnent, vous devez gérer les événements graphiques. Les événements des autres graphiques ne sont pas disponibles, nous allons donc travailler uniquement avec son propre graphique - il n'y aura pas d'identifiant de graphique dans les paramètres des méthodes de la classe CWorkPiece. 0 (son propre graphique) sera utilisé partout.

Le paramètre qui spécifie un numéro de sous-fenêtre sera utilisé pour offrir la possibilité de créer des champs à la fois dans le tableau des prix et dans ses sous-fenêtres. Les objets graphiques seront liés uniquement au coin supérieur gauche ; s'il est nécessaire de déplacer une commande relativement à n'importe quel autre coin, il est beaucoup plus facile de recalculer les coordonnées de l'ensemble de la commande, compte tenu de la taille du graphique. Pour commander les changements de taille du graphique, vous pouvez gérer l'événement CHARTEVENT_CHART_CHANGE.

Comme base pour de nombreuses commandes, nous allons utiliser l'objet « Label rectangle » ; ajoutez la méthode de création de cet objet à la classe CWorkPiece ; la méthode s'appelle Canvas() :

void Canvas(string aName="Canvas",
             int aSubWindow=0,
             int aLeft=100,
             int aTop=100,
             int aWidth=300,
             int aHeight=150,
             color aColorBg=clrIvory,
             int aColorBorder=clrDimGray)
  {
   g.CreateRectangleLabel(aName,aSubWindow); // Creation of rectangle label
   g.SetXDistance(aLeft);                    // Setting of the X coordinate
   g.SetYDistanse(aTop);                        // Setting of the Y coordinate
   g.SetXSize(aWidth);                          // Setting of width
   g.SetYSize(aHeight);                         // Setting of height
   g.SetBgColor(aColorBg);                   // Setting of background color
   g.SetColor(aColorBorder);                 // Setting of border color
   g.SetCorner(CORNER_LEFT_UPPER);             // Setting of a anchor point
   g.SetBorderType(BORDER_FLAT);             // Setting of border type
   g.SetTimeFrames(OBJ_ALL_PERIODS);            // Setting visibility at all timeframes
   g.SetSelected(false);                        // Disabling selection
   g.SetSelectable(false);                   // Disabling of selection possibility
   g.SetWidth(1);                               // Setting of border width
   g.SetStyle(STYLE_SOLID);                  // Setting of border style
  }

Attention : la méthode se compose de 14 lignes de code ; il serait très frustrant de les écrire tous à chaque fois que vous créez cet objet. Maintenant il suffit d'écrire une seule ligne, tous les paramètres de la méthode sont optionnels et sont listés par ordre de fréquence d'utilisation : position, taille, couleur, etc.

De la même manière que la méthode Canvas(), écrivez les méthodes de création d'un label de texte, d'un bouton et d'un champ d'édition : Label(), Button() et Edit(). La classe prête à l'emploi CWorkPiece est jointe à l'article dans le fichier IncGUI.mqh. En plus des méthodes mentionnées ci-dessus, la classe contient plusieurs autres méthodes : Frame() et DeleteFrame() - les méthodes de création et de suppression d'un cadre (fig. 5). Un cadre est un label rectangulaire avec une légende dans le coin supérieur gauche.

Les cadres sont prévus pour être utilisés lors du regroupement de champs dans un formulaire.


Fig. 5. Le cadre avec légende.

La liste de toutes les méthodes de la classe CWorkPiece est jointe à l'article.

De la même manière que pour la classe CGraphicObjectShell, déclarez la classe CWorkPiece avec le nom court « w » pour pouvoir l'utiliser juste après avoir connecté le fichier IncGUI.mqh.

CWorkPiece w;

Tous les outils auxiliaires sont prêts, nous pouvons donc continuer avec le sujet de l'article - la création d'une commande personnalisée.


5. Création d'un champ « Modifier »

Tout d'abord, pour ne pas confondre la terminologie, appelons l'objet graphique OBJ_EDIT comme champ de texte, l'objet OBJ_LABEL - comme label, et les commandes créées - en tant que champ d'édition. Le champ créé est constitué de deux objets graphiques : un champ d'édition (OBJ_EDIT) et un label de texte (OBJ_LABEL).

La commande prendra en charge deux modes de fonctionnement : la saisie de données textuelles et la saisie de données numériques. Dans le mode d'entrée de données numériques, il y aura une limitation sur la plage de valeurs d'entrée et une virgule et un point seront acceptables comme séparateurs décimaux. Lors d'une sortie programmée d'une valeur dans le champ d'édition, elle est formatée selon un nombre spécifié de décimales.

Ainsi, lors de l'initialisation d'un champ, il convient de préciser son mode de fonctionnement : texte ou numérique ; le mode est spécifié à l'aide du paramètre aDigits. Une valeur supérieure à zéro définit le mode numérique avec le nombre spécifié de décimales, une valeur négative définit le mode texte.

Par défaut, la plage de valeurs acceptables va de -DBL_MAX à DBL_MAX (toute la plage de valeurs d'une variable double). Si nécessaire, vous pouvez définir une autre plage en appelant les méthodes SetMin() et SetMax(). Parmi les paramètres de taille, seule la largeur sera définie pour le champ. Pour que le champ d'édition soit équilibré, une hauteur et une largeur correspondantes doivent être configurées pour cela.

Un changement de taille de police nécessite le changement correspondant de hauteur de l'objet graphique. Et cela nécessite de changer l'emplacement de toutes les autres commandes ; personne ne ferait ça. Nous supposons l'utilisation d'une taille de police constante pour toutes les commandes et les champs d'édition correspondants. Cependant, la classe de la commande aura une méthode qui renvoie sa hauteur pour faciliter le calcul des coordonnées des autres éléments.

Il y aura quatre paramètres de couleur : couleur de fond, couleur de texte, couleur de légende et couleur d'avertissement (il sera possible de changer la couleur de fond du champ de texte pour attirer l'attention d'un utilisateur, par exemple, en cas de saisie d'une valeur incorrecte).

Comme mentionné précédemment, les commandes dans une sous-fenêtre sont prises en charge. En plus des principaux paramètres nécessaires au fonctionnement d'une commande, nous allons utiliser l'autre paramètre Tag ; c'est une simple valeur de texte qui est stockée dans une instance de la classe. Une étiquette est un outil auxiliaire pratique.

La classe s'appellera CInputBox. Nous avons donc l'ensemble de variables de la classe suivant (situé dans la section privée) :

string m_NameEdit;    // Name of the Edit object
string m_NameLabel;   // Name of the Label object
int m_Left;           // X coordinate
int m_Top;            // Y coordinate
int m_Width;           // Width
int m_Height;          // Height
bool m_Visible;        // Visibility flag of the control
int m_Digits;          // Number of decimal places for the double number; -1 set the text mode
string m_Caption;      // Caption
string m_Value;        // Value
double m_ValueMin;     // Minimum value
double m_ValueMax;     // Maximum value
color m_BgColor;       // Background color
color m_TxtColor;     // Text color
color m_LblColor;      // Caption color
color m_WarningColor; // Warning font color
bool m_Warning;        // Flag of warning
int m_SubWindow;       // Subwindow
string m_Tag;           // Tag

Lors de l'utilisation d'une commande, la première méthode appelée est Init().

Dans cette méthode, nous préparons les valeurs de tous les paramètres déterminés auparavant :

// The initialization method
void Init(string aName="CInputBox",
           int aWidth=50,
           int aDigits=-1,
           string aCaption="CInputBox")
 { 
   m_NameEdit=aName+"_E";  // Preparing the name of the text field
   m_NameLabel=aName+"_L"; // Preparing the caption name
   m_Left=0;                 // X coordinate
   m_Top=0;                  // Y coordinate
   m_Width=aWidth;          // Width
   m_Height=15;             // Height
   m_Visible=false;         // Visibility
   m_Digits=aDigits;       // The mode of operation and the number of decimal places
   m_Caption=aCaption;     // Caption text
   m_Value="";              // Value in the text mode
   if(aDigits>=0)m_Value=DoubleToString(0,m_Digits); // Value in the numeric mode
   m_ValueMin=-DBL_MAX;                   // Minimal value
   m_ValueMax=DBL_MAX;                  // Maximal value
   m_BgColor=ClrScheme.Color(0);       // Background color of the text field
   m_TxtColor=ClrScheme.Color(1);      // Color of text and frame of the text field
   m_LblColor=ClrScheme.Color(2);      // Caption color
   m_WarningColor=ClrScheme.Color(3); // Warning color
   m_Warning=false;                      // Mode: warning, normal
   m_SubWindow=0; // Number of subwindow
   m_Tag=""; // Tag
 }

Si une commande fonctionne en mode texte, la variable m_Value reçoit la valeur "", s'il fonctionne en mode numérique - un zéro avec le nombre spécifié de décimales. Les paramètres de couleur sont définis sur leurs valeurs par défaut ; nous traiterons des schémas de couleurs à la dernière étape.

Les variables qui déterminent les coordonnées de la commande sont mises à zéro, car la commande n'est pas encore visible. Après avoir appelé la méthode Init() (s'il est prévu que la commande aura une position fixe sur le graphique), nous pouvons configurer les coordonnées à l'aide de la méthode SetPos() :

// Setting the X and Y coordinates
void SetPos(int aLeft,int aTop)
{ 
   m_Left=aLeft;
   m_Top=aTop;
}

Après cela, nous pouvons rendre la commande visible (la méthode Show()) :

// Enable visibility on the previously specified position
void Show()
{ 
   m_Visible=true; // Registration of visibility
   Create();       // Creation of graphical objects
   ChartRedraw();   // Refreshing of the chart
}

La fonction Create() est appelée à partir de la méthode Show() ; elle crée des objets graphiques (situés dans la section privée), puis le graphique est rafraîchi (ChartRedraw()). Le code de la fonction Create() est donné ci-dessous :

// The function of creation of graphical objects
void Create(){ 
   color m_ctmp=m_BgColor;  // Normal background color
      if(m_Warning){ // The warning method is set
         m_ctmp=m_WarningColor; // The text field will be color in the warning color
      }
    // Creation of the text field
   w.Edit(m_NameEdit,m_SubWindow,m_Left,m_Top,m_Width,m_Height,m_Value,m_ctmp,m_TxtColor,7,"Arial"); 
      if(m_Caption!=""){ // There is a caption
          // Creation of caption
         w.Label(m_NameLabel,m_SubWindow,m_Left+m_Width+1,m_Top+2,m_Caption,m_LblColor,7,"Arial"); 
      } 
}   

Lors de la création d'objets graphiques dans la fonction Create() en fonction de la valeur de m_Warning, le champ de texte se voit attribuer la couleur d'arrière-plan correspondante. Si la variable m_Caption a une valeur, la légende est créée (vous pouvez créer un champ sans légende).

Si vous envisagez de créer une commande mobile, utilisez la deuxième variante de la méthode Show() - avec la spécification des coordonnées. Dans cette méthode, les coordonnées sont configurées et la première variante de la méthode Show() est appelée :

// Setting the X and Y coordinates
void SetPos(int aLeft,int aTop){ 
   m_Left=aLeft;
   m_Top=aTop;
}

Une fois la commande affichée, vous devrez la masquer pendant un certain temps.

La méthode Hide() est utilisée à cette fin :

// Hiding (deletion of graphical objects)
void Hide()
{ 
   m_Visible=false; // Registration of the invisible state
   Delete();        // Deletion of graphical objects
   ChartRedraw();    // Refreshing of the chart
}  

La méthode Hide() appelle la fonction Delete() qui supprime les objets graphiques, puis elle appelle la fonction ChartRedraw() pour actualiser le graphique. La fonction Delete() se trouve dans la section privée :

// The function of deletion of graphical objects
void Delete()
{ 
   ObjectDelete(0,m_NameEdit);  // Deletion of the text field
   ObjectDelete(0,m_NameLabel); // Deletion of caption
}   

Puisque nous avons déjà rencontré une méthode qui ne configure que les valeurs des propriétés sans modifier l'affichage d'une commande (la méthode SetPos()), il est logique de créer une méthode pour un rafraîchissement forcé d'une commande - la méthode Refresh() : 

// Refreshing of displaying (deletion and creation)
void Refresh()
{ 
   if(m_Visible)
   {   // Visibility enabled
      Delete();     // Deletion of graphical object
      Create();     // Creation of graphical objects
      ChartRedraw(); // Redrawing of the chart 
   }            
}   

La commande est assez simple, c'est pourquoi nous utilisons la simple méthode de rafraîchissement - suppression et création. S'il s'agissait d'une commande plus complexe comme une liste composée de nombreux champs d'édition, nous choisirions une approche plus intelligente.

Donc, nous avons terminé avec le placement de la commande. Passons maintenant à la configuration d'une valeur - la méthode SetValue(). Puisque la commande peut fonctionner dans deux modes, il y aura deux variantes de la méthode SetValue() : avec la chaîne et le type double. En mode texte, la valeur est utilisée telle quelle :

// Setting a text value
void SetValue(string aValue)
{ 
   m_Value=aValue; // Assigning a value to variable to store it
      if(m_Visible)
      { // The visibility of the control is enabled
          // Assigning the text field to the object for managing graphical objects
         g.Attach(m_NameEdit); 
         g.SetText(m_Value); // Setting the value for the text field
         ChartRedraw();        // Redrawing the chart
      }
} 

L'argument obtenu est affecté à la variable m_Value, et si la commande est visible, il est affiché dans le champ de texte.

En mode numérique, l'argument obtenu est normalisé selon la valeur m_Digits, puis il est corrigé selon la valeur maximale et minimale (m_MaxValue, m_MinValue), transformé en chaîne, puis la première méthode SetValue() est appelée.

// Setting a number value
void SetValue(double aValue)
{ 
   if(m_Digits>=0)
   {  // In the numeric mode
       // Normalization of the number according to the specified accuracy
      aValue=NormalizeDouble(aValue,m_Digits);
      // "Alignment" of the value according to the minimal acceptable value
      aValue=MathMax(aValue,m_ValueMin); 
       // "Alignment" of the value according to the maximal acceptable value
      aValue=MathMin(aValue,m_ValueMax); 
       // Setting the obtained value as a string
      SetValue(DoubleToString(aValue,m_Digits)); 
   }
   else
   { // In the text mode
      SetValue((string)aValue); // Assigning the value to the variable to store it as is
   }            
}

Écrivons deux méthodes pour obtenir des valeurs : l'une pour obtenir une valeur de chaîne, l'autre pour obtenir une valeur double :

// Getting a text value
string ValueStrind()
{ 
   return(m_Value);
}

// Getting a numeric value
double ValueDouble()
{ 
   return(StringToDouble(m_Value));
}

La valeur qui est fixée pour la commande est corrigée en fonction des valeurs maximales et minimales acceptables ; ajoutons des méthodes pour les obtenir et les configurer :

// Setting the maximal acceptable value
void SetMaxValue(double aValue)
{ 
   m_ValueMax=aValue; // Registration of the new maximal accepted value
      if(m_Digits>=0)
     { // The control works in the numeric mode
         if(StringToDouble(m_Value)>m_ValueMax)
         { /* The current value of the control is greater than the new maximal acceptable value*/
            SetValue(m_ValueMax); // Setting the new value that is equal to the maximal accepted value
         }
      }         
}

// Setting the minimal acceptable value
void SetMinValue(double aValue)
{ 
   m_ValueMin=aValue; // Registration of the new minimal acceptable value     
      if(m_Digits>=0)
      { // The control works in the numeric mode
         if(StringToDouble(m_Value)<m_ValueMin)
         { /* The current value of the control is less than the new minimal acceptable value*/
            SetValue(m_ValueMin); // Setting the new value that is equal to the minimum acceptable value
         }
      }
}

// Getting the maximal accepted value
double MaxValue()
{ 
   return(m_ValueMax); 
}

// Getting the minimal accepted value
double MinValue()
{ 
   return(m_ValueMin);
}

Si la commande fonctionne en mode numérique, la commande et la correction (si nécessaire) de la valeur actuelle sont effectuées lors de la définition de nouvelles valeurs maximales et minimales acceptables.

Intéressons-nous maintenant à la saisie d'une valeur par un utilisateur, la méthode Event(). La vérification des données saisies par un utilisateur sera effectuée à l'aide de l'événement CHARTEVENT_OBJECT_ENDEDIT. Lorsque vous travaillez en mode texte, si une valeur spécifiée par un utilisateur n'est pas égale à m_Value, alors la nouvelle valeur est affectée à m_Value ainsi que la valeur 1 est affectée à la variable m_event renvoyée par la méthode Event().

Lorsque vous travaillez en mode numérique, mémorisez la valeur précédente de m_Value dans la variable m_OldValue, remplacez la virgule par un point, convertissez la chaîne en nombre et passez-la à la fonction SetValue(). Ensuite, si m_Value et m_OldValue ne sont pas égaux, « générez » l'événement (convertissez la valeur 1 sur la variable m_event).

// Handling of events
int Event(const int id,
           const long & lparam,
           const double & dparam,
           const string & sparam)
{ 
   bool m_event=0; // Variable for an event of this control
      if(id==CHARTEVENT_OBJECT_ENDEDIT)
      { // There has been an event of end of editing the text field
         if(sparam==m_NameEdit)
         { // The text field with the name m_NameEdit has been modified
            if(m_Digits<0)
            { // In the text mode
               g.Attach(m_NameEdit); // Assigning the text field for controlling it
                  if(g.Text()!=m_Value)
                  { // New value in the text field
                     m_Value=g.Text(); // Assigning the value to the variable to store it
                     m_event=1;         // There has been an event
                  }
            }
            else
            { // In the numeric mode
               string m_OldValue=m_Value; // The variable with the previous value of the control
               g.Attach(m_NameEdit);      // Attaching the text field for controlling it
               string m_stmp=g.Text();     // Getting text specified by a user in the text field
               StringReplace(m_stmp,",",".");       // Replacing comma with a dot
               double m_dtmp=StringToDouble(m_stmp); // Conversion to a number
               SetValue(m_dtmp);                     // Setting the new numeric value
                     // Comparing the new value with the previous one
                  if(StringToDouble(m_Value)!=StringToDouble(m_OldValue))
                  { 
                     m_event=1; // There has been an event 
                  }
            }
         }
      }               
   return(m_event); // Return the event. 0 - there is no event, 1 - there is an event
}

Prise en charge du fonctionnement du champ dans des sous-fenêtres. Pour la fournir, ajoutez la méthode SetSubWindow() qui doit être appelée à partir de la fonction OnChartEvent() en cas d'événement CHARTEVENT_CHART_CHANGE. Si vous prévoyez d'utiliser la commande uniquement sur un graphique de prix, il n'est pas nécessaire d'appeler cette méthode. 

La variable m_SubWindow est déjà déclarée, elle est égale à 0 par défaut et elle est transmise aux méthodes Edit() et Label() de la classe « w » lors de la création des objets graphiques d'un champ. Le numéro d'une sous-fenêtre sera transmis à la méthode SetSubWindowName() ; si le nombre est modifié, modifiez la valeur de la variable m_SubWindow et exécutez la méthode Refresh().

// Setting a subwindow by number
void SetSubWindow(int aNumber)
{ 
   int m_itmp=(int)MathMax(aNumber,0); /* If the number is negative, 0 will be used - the price chart*/
      if(m_itmp!=m_SubWindow)
      { /* The specified number doesn't correspond the number where the control is located*/
         m_SubWindow=m_itmp; // Registration of the new number of subwindow
         Refresh(); // Recreation of the graphical objects
      }
} 

Probablement, il sera plus pratique de transmettre le nom d'une sous-fenêtre au lieu de son numéro à la fonction. Ajoutez une autre variante de la méthode SetSubWindow() :

// Setting a subwindow by name
void SetSubWindow(string aName)
{ 
   SetSubWindow(ChartWindowFind(0,aName)); // Determination of the number of the subwindow by its name and setting the subwindow by number
}

Fournissez à la classe du champ les autres méthodes manquantes, selon le concept énoncé au début de l'article.

Dès que nous avons la méthode SetPos() qui permet de définir les deux coordonnées de la commande simultanément, ajoutez les méthodes pour un réglage séparé des coordonnées :

// Setting the X coordinate
void SetPosLeft(int aLeft)
{ 
   m_Left=aLeft;
}      

// Setting the Y coordinate
void SetPosTop(int aTop)
{ 
   m_Top=aTop;
}  

Méthode de définition d'une largeur :

// Setting the width
void SetWidth(int aWidth)
{ 
   m_Width=aWidth;
}

Méthode pour obtenir les coordonnées et la taille :

// Getting the X coordinate
int Left()
{ 
   return(m_Left);
}

// Getting the Y coordinate
int Top()
{ 
   return(m_Top);
}

// Getting the width
int Width()
{ 
   return(m_Width);
}

// Getting the height
int Height()
{
   return(m_Height); 
}

Les méthodes pour travailler avec la balise :

// Setting the tag
void SetTag(string aValue)
{ 
   m_Tag=aValue;
}

// Getting the tag
string Tag()
{ 
   return(m_Tag);
}  

Les méthodes d'avertissement :

// Setting the warning mode
void SetWarning(bool aValue)
{ 
      if(m_Visible)
      { // Visibility is enabled
         if(aValue)
         { // We need to turn on the warning mode
            if(!m_Warning)
            { // The warning mode has not been enabled
               g.Attach(m_NameEdit);         // Attaching the text field for controlling
               g.SetBgColor(m_WarningColor); // Setting the warning color of text in the text field
            }
         }
         else
         { // We need to disable the warning mode
            if(m_Warning)
            { // The warning mode is enabled
               g.Attach(m_NameEdit);    // Attach the text field for controlling 
               g.SetBgColor(m_BgColor); // Setting the normal font color                
            }
         }
      }
   m_Warning=aValue; // Registration of the current mode
}

// Getting the warning mode
bool Warning()
{ 
   return(m_Warning);
}

Si le champ est visible lors de la configuration du mode d'avertissement, la valeur du paramètre transmis à la méthode SetWarning est vérifiée ; si sa valeur ne correspond pas à l'état courant du champ, la couleur de fond du champ texte est modifiée.

Quoi qu'il en soit, le mode de réglage est enregistré, pour ne pas configurer la couleur correspondante au champ de texte au cas où la commande serait invisible.

Il reste une propriété - m_Digits. Ajoutons des méthodes pour obtenir et configurer sa valeur : 

// Setting the number of decimal places
void SetDigits(int aValue)
{ 
   m_Digits=aValue; // Registration of the new value
      if(m_Digits>=0)
      { // The numeric mode
         SetValue(ValueDouble()); // Resetting of the current value
      }
}  

// Getting the m_Digits value
int Digits()
{ 
   return(m_Digits);
}  

Eh bien, nous avons terminé avec la partie la plus intéressante. Nous en arrivons maintenant au paroxysme de tout.


6. Schéma de couleur

Les schémas de couleurs seront stockés dans les variables de la classe CСolorSchemes.

La classe sera préalablement déclarée dans le fichier IncGUI.mqh avec le nom ClrScheme. Pour configurer un schéma de couleurs, nous appellerons la méthode SetScheme() avec le numéro d'un schéma de couleurs spécifié comme paramètre. Si la méthode SetScheme() n'est pas appelée, le schéma de couleurs avec le numéro 0 sera utilisé.

Pour obtenir une couleur, nous utiliserons la méthode Color() avec un nombre spécifié de couleurs du jeu de couleurs. Écrivons la classe CСolor Schemes avec les sections privées et publiques. Dans la section privée, déclarez la variable m_ShemeIndex pour stocker l'indice d'un jeu de couleurs. Dans la section publique, écrivez la méthode SetScheme() :

// Setting the color scheme number
void SetScheme(int aShemeIndex)
{ 
   m_ShemeIndex=aShemeIndex;
}

La méthode Color(). Un tableau bidimensionnel est déclaré dans la méthode : la première dimension est le numéro du schéma de couleurs ; la deuxième est le numéro de couleur dans le schéma. Selon le nombre spécifié d'un schéma de couleurs, elle renvoie la couleur par nombre spécifié dans les paramètres de la méthode.

color Color(int aColorIndex)
{
   color m_Color[3][4];  // The first dimension - the color scheme number, the second one - the number of the color in the color scheme
   // default
   m_Color[0][0]=clrSnow;
   m_Color[0][1]=clrDimGray;
   m_Color[0][2]=clrDimGray;
   m_Color[0][3]=clrPink;
   // yellow-black
   m_Color[1][0]=clrLightYellow;
   m_Color[1][1]=clrBrown;
   m_Color[1][2]=clrBrown;
   m_Color[1][3]=clrPink;
   // blue
   m_Color[2][0]=clrAliceBlue;
   m_Color[2][1]=clrNavy;
   m_Color[2][2]=clrNavy;
   m_Color[2][3]=clrPink;
   return(m_Color[m_ShemeIndex][aColorIndex]); // Returning a value according to the scheme number and the number of color in the scheme
}

Pour l'instant, les schémas de couleurs comprennent quatre couleurs chacun ; à cela deux d'entre eux ont les mêmes valeurs. De plus, lors de la création d'autres commandes, nous pouvons avoir besoin de plus de couleurs.

Pour trouver facilement une couleur appropriée dans le schéma ou décider d'ajouter une nouvelle couleur, la classe comprend une méthode qui permet de visualiser les couleurs - la méthode Show() (fig. 6). Et il existe également la méthode inverse Hide() pour supprimer les exemples de couleurs du graphique.


Fig. 6. Affichage des schémas de couleurs à l'aide de la méthode Show()

L'article a le ColorSchemesView.mq5 attaché. Il s'agit d'un Expert Advisor pour la visualisation des schémas de couleurs (ColorSchemesView.mq5).

Modifions légèrement la méthode Init() dans la classe CInputBox. Remplacez ses couleurs par les couleurs de la classe ClrScheme :

m_BgColor=ClrScheme.Color(0);       // Background color of the text field
m_TxtColor=ClrScheme.Color(1);      // Font color and frame color of the text field
m_LblColor=ClrScheme.Color(2);     // Caption color
m_WarningColor=ClrScheme.Color(3); // Warning color

C'est la fin de la création d'une commande ; et maintenant nous avons la base pour développer d'autres commandes.


7. Utilisation de la commande

Créons un Expert Advisor et nommons-le GUITest ; connectez le fichier IncGUI.mqh :  

#include <IncGUI.mqh>
Déclarez la classe CInputBox avec le nom ib :
CInputBox ib;

Dans le OnInit() de l'EA, appelez la méthode Init() de l'objet ib :

ib.Init("InpytBox",50,4,"input");

Rendez la commande visible et positionnez-la :

ib.Show(10,20);

Dans la fonction OnDeinit() de l'EA, supprimez le champ :

ib.Hide(); 

Compilez et attachez l'Expert Advisor à un graphique. Vous verrez notre commande (fig. 7).


Fig. 7. La commande InputBox

Ajoutez la possibilité de changer le schéma de couleurs sur l'Expert Advisor.

En ce moment, nous avons trois schémas de couleurs. Faisons une énumération et une variable externe pour choisir un schéma de couleurs : 

enum eColorScheme
  {
   DefaultScheme=0,
   YellowBrownScheme=1,
   BlueScheme=2
  };

input eColorScheme ColorScheme=DefaultScheme;

Au tout début de la fonction OnInit() de l'Expert Advisor, ajoutez la configuration d'un schéma de couleurs :

ClrScheme.SetScheme(ColorScheme);

Maintenant, dans la fenêtre des propriétés de l'EA, nous pouvons choisir l'un des trois schémas de couleurs (fig. 8).




Fig. 8. Différents schémas de couleurs

Pour gérer l'événement de spécification d'une nouvelle valeur, ajoutez le code suivant à la fonction OnChartEvent() de l'EA :

if(ib.Event(id,lparam,dparam,sparam)==1)
  {
   Alert("Entered value "+ib.ValueStrind());
  }

Désormais, lorsqu'une nouvelle valeur est spécifiée dans le champ d'édition, une fenêtre de message informant de la valeur spécifiée s'ouvre.

Fournissez à l'Expert Advisor la possibilité de créer des champs dans une sous-fenêtre.

Tout d'abord, créez un indicateur de test TestSubWindow (attaché dans le fichier TestSubWindow.mq5). Lors de la création de l'indicateur dans l'assistant MQL5, spécifiez qu'il doit fonctionner dans une sous-fenêtre distincte. Ajoutez le code suivant à la fonction OnChartEvent() de l'EA :

if(CHARTEVENT_CHART_CHANGE)
  {
   ip.SetSubWindow("TestSubWindow");
  }

Maintenant, si l'indicateur n'est pas sur le graphique, la commande est créée sur le graphique des prix. Si vous attachez l'indicateur au graphique, la commande passera à la sous-fenêtre (fig. 9). Si vous supprimez l'indicateur, la commande reviendra au tableau des prix.

 
Fig. 9. La commande dans la sous-fenêtre

Conclusion

À la suite du travail effectué, nous avons le fichier d'inclusion IncGUI.mqh qui contient les classes suivantes : CGraphicObjectShell (création et gestion d'objets graphiques), CWorkPiece (création rapide de plusieurs objets graphiques avec configuration de leurs propriétés à l'aide de paramètres), CColorSchemes (configuration d'un schéma de couleurs et obtention de la couleur du schéma de couleurs actuel) et une classe de commande - CInputBox.

Les classes CGraphicObjectShell, CWorkPiece et CColorSchemes sont déjà déclarées dans le fichier avec les noms « g », « w » et « ClrScheme », c'est-à-dire qu'elles sont prêtes à l'emploi juste après avoir connecté le fichier IncGUI.mqh.

Répétons comment utiliser la classe CInputBox :

  1. Connectez le fichier IncGUI.mqh.
  2. Déclarez une classe de type CInputBox.
  3. Appelez la méthode Init().
  4. Configurez les coordonnées à l'aide de la méthode SetPos() ; activez la visibilité en utilisant Show() si nécessaire. La deuxième variante : activez la visibilité à l'aide de Show() avec la spécification des coordonnées.
  5. Si nécessaire ou en fin de travail de l'Expert Advisor, masquez le champ à l'aide de la méthode Hide().
  6. Ajoutez l'appel de la méthode Event() à la fonction OnChartEvent().
  7. Si vous devez créer une commande dans une sous-fenêtre, fournissez à la fonction OnChartEvent() un appel de la méthode SetSubWindow() lorsqu'un événement CHARTEVENT_CHART_CHANGE se produit.
  8. Pour utiliser des schémas de couleurs, appelez la méthode SetScheme() de la classe ClrScheme avant d'appeler la méthode Init(). 


Pièces jointes

  • IncGUI.mqh - fichier d'inclusion principal. Le fichier doit être placé dans le dossier MQL5/Include du dossier de données du terminal client.
  • GUITest.mq5 - l'Expert Advisor avec un exemple de la commande CInputBox. Le fichier doit être placé dans le dossier MQL5/Experts du dossier de données du terminal client.
  • TestSubWindow.mq5 - l'indicateur pour tester la fonction d'affichage d'une commande dans une sous-fenêtre. Le fichier doit être placé dans le dossier MQL5/Indicators du dossier de données du terminal client.
  • ColorSchemesView.mq5 - l’Expert Advisor pour visualiser les schémas de couleurs. Un outil auxiliaire pour la création de commandes. Le fichier doit être placé dans le dossier MQL5/Experts du dossier de données du terminal client.
  • IncGUImqh.chm - documentation pour le fichier IncGUI.mqh.  

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

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.
Assistant MQL5 : Nouvelle version Assistant MQL5 : Nouvelle version
L'article contient des descriptions des nouvelles fonctionnalités disponibles dans l'assistant MQL5 mis à jour. L'architecture modifiée des signaux permet de créer des robots de trading basés sur la combinaison de divers modèles de marché. L'exemple contenu dans l'article explique la procédure de création interactive d'un Expert Advisor.
Contrôles graphiques personnalisés. Partie 3. Formulaires Contrôles graphiques personnalisés. Partie 3. Formulaires
Ceci est le dernier des trois articles consacrés aux contrôles graphiques. Il couvre la création du composant principal de l'interface graphique - le formulaire - et son utilisation en combinaison avec d'autres contrôles. En plus des classes de formulaire, les classes CFrame, CButton, CLabel ont été ajoutées à la bibliothèque de contrôle.
Utilisation des ressources en MQL5 Utilisation des ressources en MQL5
Les programmes MQL5 automatisent non seulement les calculs de routine, mais peuvent également créer un environnement graphique complet. Les fonctions de création de contrôles véritablement interactifs sont désormais pratiquement de la même richesse que celles des langages de programmation classiques. Si vous souhaitez écrire un programme autonome à part entière en MQL5, utilisez les ressources qu'il contient. Les programmes avec des ressources sont plus faciles à maintenir et à distribuer.