Русский 中文 Español Deutsch 日本語 Português
Graphical Interfaces VI: the Checkbox Control, the Edit Control and their Mixed Types (Chapter 1)

Graphical Interfaces VI: the Checkbox Control, the Edit Control and their Mixed Types (Chapter 1)

MetaTrader 5Examples | 1 June 2016, 17:00
11 603 5
Anatoli Kazharski
Anatoli Kazharski

Contents



Introduction

The first article Graphical Interfaces I: Preparation of the Library Structure (Chapter 1) explains in detail what this library is for. You will find a list of articles with links at the end of each chapter. There, you can also download a complete version of the library at the current stage of development. The files must be placed in the same directories as they are located in the archive.

The sixth part of the series will consist of two chapters. In the first chapter, we will create four controls:

  • Checkbox
  • Edit
  • Edit with checkbox
  • Check combobox

We will discuss only checkbox and edit as edit with checkbox and check combobox will not contain anything that has not been considered before. 

The second article will be dedicated to the following elements:

  • Slider
  • Dual slider

 


The Checkbox Control

The checkbox control is designated to managing parameters that can have only two states. A button with two icons is used to identify the current state of the parameter to which the control is attached. The icon with the check symbol means that the parameter is enabled (on). The icon without the check symbol means the parameter is disabled (off). A brief description of the parameter is located near the button. 

This element will be composed of three graphical objects. They are:

  1. Background
  2. Icon (button)
  3. Text label

Fig. 1. Compound parts of the checkbox control.

Fig. 1. Compound parts of the checkbox control.

Let us take a closer look at the class of this control.

 


Developing a Class for Creating the Checkbox Control

In the third part of this series, we spoke about a similar control - an icon button and its class CIconButton  (see the article Graphical Interfaces III: Simple and Multi-Functional Buttons (Chapter 1)). The checkbox control is similar to an icon button with the two-state mode. The only difference here is that a button in different states (on/off) has different background color and text color (if they are set), and in case of a checkbox, only the icon and the text color change (if they are set). The checkbox background color will be the same as the background color of the window to which it is attached. The background here will be used as the area for identifying the mouse cursor in relation to the boundaries of this area and also for identifying the left mouse button press on the control. The checkbox control is simpler than an icon button as it has less properties the user can set.

Create the CheckBox.mqh file and include it in the file WndContainer.mqh of the library:

//+------------------------------------------------------------------+
//|                                                 WndContainer.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "CheckBox.mqh"

Create the CCheckBox class with the methods standard for all the elements of the library in the CheckBox.mqh file:

//+------------------------------------------------------------------+
//|                                                     CheckBox.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Element.mqh"
#include "Window.mqh"
//+------------------------------------------------------------------+
//| Class for creating a checkbox                                    |
//+------------------------------------------------------------------+
class CCheckBox : public CElement
  {
private:
   //--- Pointer to the form to which the element is attached
   CWindow          *m_wnd;
   //---
public:
                     CCheckBox(void);
                    ~CCheckBox(void);
   //--- Stores the form pointer
   void              WindowPointer(CWindow &object)                 { m_wnd=::GetPointer(object);            }
   //---
public:
   //--- Chart event handler
   virtual void      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   //--- Timer
   virtual void      OnEventTimer(void);
   //--- Moving the element
   virtual void      Moving(const int x,const int y);
   //--- (1) Show, (2) hide, (3) reset, (4) delete
   virtual void      Show(void);
   virtual void      Hide(void);
   virtual void      Reset(void);
   virtual void      Delete(void);
   //--- (1) Setting, (2) resetting of priorities of the left mouse button
   virtual void      SetZorders(void);
   virtual void      ResetZorders(void);
   //--- Reset color
   virtual void      ResetColors(void);
  };

Before the control is created, the user will be able to use methods for installing properties listed below:

  • Control background
  • Icons for the checkbox in the active and blocked states
  • Margins for a text label
  • Colors of the text label in different states

There will be four icons for the checkbox button - two icons for the active state and two for the blocked state. Icons for all states are available at the end of the article but you can use your own. 

class CCheckBox : public CElement
  {
private:
   //--- Color of the checkbox background
   color             m_area_color;
   //--- Checkbox icons in the active and blocked states
   string            m_check_bmp_file_on;
   string            m_check_bmp_file_off;
   string            m_check_bmp_file_on_locked;
   string            m_check_bmp_file_off_locked;
   //--- Text of checkbox
   string            m_label_text;
   //--- Text label margins
   int               m_label_x_gap;
   int               m_label_y_gap;
   //--- Colors of the text label in different states
   color             m_label_color;
   color             m_label_color_off;
   color             m_label_color_hover;
   color             m_label_color_locked;
   color             m_label_color_array[];
   //--- Priorities of the left mouse button press
   int               m_zorder;
   int               m_area_zorder;
   //---
public:
   //--- Setting labels for the button in the active and blocked states
   void              CheckFileOn(const string file_path)            { m_check_bmp_file_on=file_path;         }
   void              CheckFileOff(const string file_path)           { m_check_bmp_file_off=file_path;        }
   void              CheckFileOnLocked(const string file_path)      { m_check_bmp_file_on_locked=file_path;  }
   void              CheckFileOffLocked(const string file_path)     { m_check_bmp_file_off_locked=file_path; }
   //--- (1) Background color, (2) margins for the text label
   void              AreaColor(const color clr)                     { m_area_color=clr;                      }
   void              LabelXGap(const int x_gap)                     { m_label_x_gap=x_gap;                   }
   void              LabelYGap(const int y_gap)                     { m_label_y_gap=y_gap;                   }
   //--- Color of the text in different states
   void              LabelColor(const color clr)                    { m_label_color=clr;                     }
   void              LabelColorOff(const color clr)                 { m_label_color_off=clr;                 }
   void              LabelColorHover(const color clr)               { m_label_color_hover=clr;               }
   void              LabelColorLocked(const color clr)              { m_label_color_locked=clr;              }
   //--- Checkbox description
   string            LabelText(void)                          const { return(m_label.Description());         }
  };

To create the checkbox control, we will need three private methods and one public:

class CCheckBox : public CElement
  {
private:
   //--- Objects for creating a checkbox
   CRectLabel        m_area;
   CBmpLabel         m_check;
   CLabel            m_label;
   //---
public:
   //--- Methods for creating a checkbox
   bool              CreateCheckBox(const long chart_id,const int subwin,const string text,const int x,const int y);
   //---
private:
   bool              CreateArea(void);
   bool              CreateCheck(void);
   bool              CreateLabel(void);
  };

Let us create the CCheckBox::CheckButtonState() and CCheckBox::CheckBoxState() methods for managing the state of the checkbox:

class CCheckBox : public CElement
  {
private:
   //--- State of the checkbox button
   bool              m_check_button_state;
   //--- Checkbox state (available/blocked)
   bool              m_checkbox_state;
   //---
public:
   //--- Return/set the checkbox state
   bool              CheckBoxState(void)                      const { return(m_checkbox_state);              }
   void              CheckBoxState(const bool state);
   //--- Return/set the state of the checkbox button
   bool              CheckButtonState(void)                   const { return(m_check.State());               }
   void              CheckButtonState(const bool state);
  };

To block/unblock the control, use the CCheckBox::CheckBoxState() method:

//+------------------------------------------------------------------+
//| Setting the state of the control                                 |
//+------------------------------------------------------------------+
void CCheckBox::CheckBoxState(const bool state)
  {
//--- Control state
   m_checkbox_state=state;
//--- Icon
   m_check.BmpFileOn((state)? "::"+m_check_bmp_file_on : "::"+m_check_bmp_file_on_locked);
   m_check.BmpFileOff((state)? "::"+m_check_bmp_file_off : "::"+m_check_bmp_file_off_locked);
//--- Color of the text label
   m_label.Color((state)? m_label_color : m_label_color_locked);
  }

To set the state of the checkbox button, use the CCheckBox::CheckButtonState() method: 

//+------------------------------------------------------------------+
//| Setting the state of the checkbox button                         |
//+------------------------------------------------------------------+
void CCheckBox::CheckButtonState(const bool state)
  {
//--- Leave, if the control is blocked
   if(!m_checkbox_state)
      return;
//--- Set the button state
   m_check.State(state);
   m_check_button_state=state;
//--- Change colors according to the current state
   m_label.Color((state)? m_label_color : m_label_color_off);
   CElement::InitColorArray((state)? m_label_color : m_label_color_off,m_label_color_hover,m_label_color_array);
  }

We only have to create a method for handling the press on the checkbox control. This method will be called in the main handler of the control CCheckBox::OnEvent() by the event with the CHARTEVENT_OBJECT_CLICK identifier. Let us call it CCheckBox::OnClickLabel(). At the beginning of this method, there is a check if the press was over the area of the control (its background). To avoid confusion over what object of the control exactly the press took place, the background has the priority value of the left mouse button click of 1 and other objects have the value of 0. Therefore, even if the press was when the cursor was over a checkbox button or a text label, it will be treated as a click on the control background, that is the object with the highest priority in this area. Then, we will use the CCheckBox::CheckButtonState() method to set the state opposite the checkbox button. At the end of the method, a custom event with (1) the ON_CLICK_LABEL event identifier, (2) the element identifier and (3) the element description are sent.

class CCheckBox : public CElement
  {
private:
   //--- Handling of the press on the element
   bool              OnClickLabel(const string clicked_object);
  };
//+------------------------------------------------------------------+
//| Event handling                                                   |
//+------------------------------------------------------------------+
void CCheckBox::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Handling the left mouse button click on the object
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Click on the checkbox
      if(OnClickLabel(sparam))
         return;
     }
  }
//+------------------------------------------------------------------+
//| Clicking on the element label                                    |
//+------------------------------------------------------------------+
bool CCheckBox::OnClickLabel(const string clicked_object)
  {
//--- Leave, if the name is different
   if(m_area.Name()!=clicked_object)
      return(false);
//--- Leave, if the control is blocked
   if(!m_checkbox_state)
      return(false);
//--- Switch to the opposite state
   CheckButtonState(!m_check.State());
//--- The mouse cursor is currently over the element
   m_label.Color(m_label_color_hover);
//--- Send a message about it
   ::EventChartCustom(m_chart_id,ON_CLICK_LABEL,CElement::Id(),0,m_label.Description());
   return(true);
  }

 

 


Testing the Checkbox Control

All the method of the CCheckBox class are ready so we can test how this control works. The file with the class of this control must be already included in the library. The EA for tests can be copied from the previous article. Delete all controls from it except the main menu and the status bar. Create two checkboxes for the test. Ensure that the second checkbox is blocked by default at the moment of loading the program on to the chart. The first checkbox will be available for the interaction with the user but in the disabled state. Enabling the first checkbox will be a signal for unblocking the second checkbox. The same will work for the opposite situation - disabling of the first checkbox will be a signal for blocking the second checkbox.

In the CProgram custom class create two instances of the CCheckBox class and declare two methods for creating checkboxes and specify margins from the edge of the form to which they are going to be attached: 

//+------------------------------------------------------------------+
//| Class for creating the application                               |
//+------------------------------------------------------------------+
class CProgram : public CWndEvents
  {
private:
   //--- Checkboxes
   CCheckBox         m_checkbox1;
   CCheckBox         m_checkbox2;
   //---
private:
   //--- Checkboxes
#define CHECKBOX1_GAP_X       (7)
#define CHECKBOX1_GAP_Y       (50)
   bool              CreateCheckBox1(const string text);
#define CHECKBOX2_GAP_X       (30)
#define CHECKBOX2_GAP_Y       (75)
   bool              CreateCheckBox2(const string text);
  };

The only difference in the method implementation will be that the availability of the second checkbox will depend on the state of the first checkbox:

//+------------------------------------------------------------------+
//| Creates checkbox 2                                               |
//+------------------------------------------------------------------+
bool CProgram::CreateCheckBox2(string text)
  {
//--- Pass the panel object
   m_checkbox2.WindowPointer(m_window1);
//--- Coordinates
   int x=m_window1.X()+CHECKBOX2_GAP_X;
   int y=m_window1.Y()+CHECKBOX2_GAP_Y;
//--- Set properties before creation
   m_checkbox2.XSize(90);
   m_checkbox2.YSize(18);
   m_checkbox2.AreaColor(clrWhiteSmoke);
   m_checkbox2.LabelColor(clrBlack);
   m_checkbox2.LabelColorOff(clrBlack);
   m_checkbox2.LabelColorLocked(clrSilver);
//--- Create control
   if(!m_checkbox2.CreateCheckBox(m_chart_id,m_subwin,text,x,y))
      return(false);
//--- The availability will depend on the current state of the first checkbox
   m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState()); 
//--- Add the object to the common array of the object groups
   CWndContainer::AddToElementsArray(0,m_checkbox2);
   return(true);
  }

Put the method calls for creating checkboxes in the main method for creating the graphical interface. A shortened version of this code is presented below:

//+------------------------------------------------------------------+
//| Creates the training panel                                       |
//+------------------------------------------------------------------+
bool CProgram::CreateTradePanel(void)
  {
//--- Creating form 1 for controls
//--- Creating controls:
//    Main menu
//--- Context menus
//--- Creating the status bar

//--- Checkboxes
   if(!CreateCheckBox1("Checkbox 1"))
      return(false);
   if(!CreateCheckBox2("Checkbox 2"))
      return(false);
//--- Redrawing the chart
   m_chart.Redraw();
   return(true);
  }

We will receive and handle a message with the ON_CLICK_LABEL identifier in the event handler of the CProgram class. The availability of the second checkbox will be defined by the state of the first checkbox as shown in the code below: 

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- The checkbox press event
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
      //--- If the press was on the first checkbox
      if(lparam==m_checkbox1.Id())
        {
         //--- Set the state of the second checkbox
         m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState());
        }
     }
  }

Now, compile the files and load the EA on the chart. The result should be as in the screenshot below:

Fig. 2. Testing the checkbox control.

Fig. 2. Testing the checkbox control.


The screenshot shows that the second checkbox is blocked. The indication here is the color of the text and the button icon corresponding to this state (faded colors). Everything works well and we are moving on to developing a class for creating the edit control. 

 


The Edit Control

The edit control is used for setting a numeric value in the text field. The value can be entered manually or with the help of buttons for scrolling. The maximum and minimum values (limits) as well as the step for scrolling can be defined by the user. If the button with the up/down arrow is pressed once, then the value will be increased/decreased by the step specified in settings. If the up-down arrow is pressed and held down, the value in the edit will be changing fast. The scrolling will stop having reached the allowed maximum or minimum.

This control will be composed of five graphical objects. They are:

  1. Background
  2. Text label
  3. Edit
  4. Two buttons for scrolling values in the edit control

Fig. 3. Compound parts of the edit control.

Fig. 3. Compound parts of the edit control.


In the next part of the article, we will write a class for creating this interface element.

 


Developing a Class for Creating the Edit Control

Similar to the checkbox control, the edit control is simple, not compound. In other words, it is made up of simple objects and does not contain any other controls. This is why no additions are required in the WndContainer.mqh file. We just need to include the file with the class of the edit control.

Now, create the SpinEdit.mqh file and include it in the WndContainer.mqh file:

//+------------------------------------------------------------------+
//|                                                 WndContainer.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "SpinEdit.mqh"

In the SpinEdit.mqh file, create the CSpinEdit class with the methods standard for all the elements of the library like in the description of the CCheckBox class earlier in this article. That is why we will go straight to the description of the edit control properties. 

Below is the list of all properties of the edit control which will be available to the user for setting.

  • Background color
  • Text of the description of the edit
  • Margins of the text label
  • Colors of the text in different state
  • Size of the edit
  • Margin of the edit from the right side of the element
  • Colors of the edit in different states
  • Colors of the edit text in different states
  • Colors of the edit frame in different states
  • Labels of the switches in the active and blocked state
  • Button margins (from the right side)
  • Mode of resetting the value to the minimum
  • Minimum and maximum value
  • Step for changing the value in the edit using the buttons
  • Mode of text alignment
  • Number of decimal places

The code below presents the fields and methods of the class for setting the control properties listed above: 

//+------------------------------------------------------------------+
//| Class for creating the edit                                      |
//+------------------------------------------------------------------+
class CSpinEdit : public CElement
  {
private:
   //--- Color of the control background
   color             m_area_color;
   //--- Text of the description of the edit
   string            m_label_text;
   //--- Text label margins
   int               m_label_x_gap;
   int               m_label_y_gap;
   //--- Color of the text in different states
   color             m_label_color;
   color             m_label_color_hover;
   color             m_label_color_locked;
   color             m_label_color_array[];
   //--- Size of the edit
   int               m_edit_x_size;
   int               m_edit_y_size;
   //--- Margin of edit from the right side
   int               m_edit_x_gap;
   //--- Colors of the edit and text of the edit in different states
   color             m_edit_color;
   color             m_edit_color_locked;
   color             m_edit_text_color;
   color             m_edit_text_color_locked;
   color             m_edit_text_color_highlight;
   //--- Colors of the edit frame in different states
   color             m_edit_border_color;
   color             m_edit_border_color_hover;
   color             m_edit_border_color_locked;
   color             m_edit_border_color_array[];
   //--- Labels of switches in the active and blocked states
   string            m_inc_bmp_file_on;
   string            m_inc_bmp_file_off;
   string            m_inc_bmp_file_locked;
   string            m_dec_bmp_file_on;
   string            m_dec_bmp_file_off;
   string            m_dec_bmp_file_locked;
   //--- Button margins (from the right side)
   int               m_inc_x_gap;
   int               m_inc_y_gap;
   int               m_dec_x_gap;
   int               m_dec_y_gap;
   //--- The mode of resetting the value to the minimum
   bool              m_reset_mode;
   //--- Minimum/maximum value
   double            m_min_value;
   double            m_max_value;
   //--- Step for changing the value in edit
   double            m_step_value;
   //--- Mode of text alignment
   ENUM_ALIGN_MODE   m_align_mode;
   //--- Number of decimal places
   int               m_digits;
   //---
public:
   //--- (1) Background color, (2) text of edit description, (3) margins of the text label
   void              AreaColor(const color clr)                     { m_area_color=clr;                   }
   string            LabelText(void)                          const { return(m_label.Description());      }
   void              LabelXGap(const int x_gap)                     { m_label_x_gap=x_gap;                }
   void              LabelYGap(const int y_gap)                     { m_label_y_gap=y_gap;                }
   //--- Colors of the text label in different states
   void              LabelColor(const color clr)                    { m_label_color=clr;                  }
   void              LabelColorHover(const color clr)               { m_label_color_hover=clr;            }
   void              LabelColorLocked(const color clr)              { m_label_color_locked=clr;           }
   //--- (1) Edit size, (2) margin for edit from the right side
   void              EditXSize(const int x_size)                    { m_edit_x_size=x_size;               }
   void              EditYSize(const int y_size)                    { m_edit_y_size=y_size;               }
   void              EditXGap(const int x_gap)                      { m_edit_x_gap=x_gap;                 }
   //--- Colors of edit in different states
   void              EditColor(const color clr)                     { m_edit_color=clr;                   }
   void              EditColorLocked(const color clr)               { m_edit_color_locked=clr;            }
   //--- Colors of the edit text in different states
   void              EditTextColor(const color clr)                 { m_edit_text_color=clr;              }
   void              EditTextColorLocked(const color clr)           { m_edit_text_color_locked=clr;       }
   void              EditTextColorHighlight(const color clr)        { m_edit_text_color_highlight=clr;    }
   //--- Colors of the edit frame in different states
   void              EditBorderColor(const color clr)               { m_edit_border_color=clr;            }
   void              EditBorderColorHover(const color clr)          { m_edit_border_color_hover=clr;      }
   void              EditBorderColorLocked(const color clr)         { m_edit_border_color_locked=clr;     }
   //--- Setting labels for the button in the active and blocked states
   void              IncFileOn(const string file_path)              { m_inc_bmp_file_on=file_path;        }
   void              IncFileOff(const string file_path)             { m_inc_bmp_file_off=file_path;       }
   void              IncFileLocked(const string file_path)          { m_inc_bmp_file_locked=file_path;    }
   void              DecFileOn(const string file_path)              { m_dec_bmp_file_on=file_path;        }
   void              DecFileOff(const string file_path)             { m_dec_bmp_file_off=file_path;       }
   void              DecFileLocked(const string file_path)          { m_dec_bmp_file_locked=file_path;    }
   //--- Margins for edit buttons
   void              IncXGap(const int x_gap)                       { m_inc_x_gap=x_gap;                  }
   void              IncYGap(const int y_gap)                       { m_inc_y_gap=y_gap;                  }
   void              DecXGap(const int x_gap)                       { m_dec_x_gap=x_gap;                  }
   void              DecYGap(const int y_gap)                       { m_dec_y_gap=y_gap;                  }
   //--- Reset mode when press on the text label takes place
   bool              ResetMode(void)                                { return(m_reset_mode);               }
   void              ResetMode(const bool mode)                     { m_reset_mode=mode;                  }
   //--- Minimum value
   double            MinValue(void)                           const { return(m_min_value);                }
   void              MinValue(const double value)                   { m_min_value=value;                  }
   //--- Maximum value
   double            MaxValue(void)                           const { return(m_max_value);                }
   void              MaxValue(const double value)                   { m_max_value=value;                  }
   //--- The step of the value
   double            StepValue(void)                          const { return(m_step_value);               }
   void              StepValue(const double value)                  { m_step_value=(value<=0)? 1 : value; }
   //--- (1) Number of decimal places, (2) mode of text alignment
   void              SetDigits(const int digits)                    { m_digits=::fabs(digits);            }
   void              AlignMode(ENUM_ALIGN_MODE mode)                { m_align_mode=mode;                  }
  };

To create the edit control, we will need five private methods for creating graphical primitive objects and one public method, which will be called in the custom class when the graphical interface is created. Icons for scrolling buttons can be downloaded at the end of the article. They are used by default but you can use your own.

class CSpinEdit : public CElement
  {
private:
   //--- Objects for creating the edit
   CRectLabel        m_area;
   CLabel            m_label;
   CEdit             m_edit;
   CBmpLabel         m_spin_inc;
   CBmpLabel         m_spin_dec;
   //---
public:
   //--- Methods for creating the edit
   bool              CreateSpinEdit(const long chart_id,const int subwin,const string label_text,const int x,const int y);
   //---
private:
   bool              CreateArea(void);
   bool              CreateLabel(void);
   bool              CreateEdit(void);
   bool              CreateSpinInc(void);
   bool              CreateSpinDec(void);
  };

Now, we are going to discuss modes and methods for managing the states and properties of the control after its creation. Let us start with the CSpinEdit::SetValue() method for adjusting and storing the value for the edit control and also the CSpinEdit::HighlightLimit() auxiliary method for highlighting (flashing) of the text in edit when the minimum and maximum limits are exceeded.

At the beginning of the CSpinEdit::SetValue() method, there is an adjustment considering the step for changing the value. Then, follow checks for exceeding set limits (maximum/minimum). If the limits are exceeded, then a value corresponding to the check is set and the CSpinEdit::HighlightLimit() method is called for highlighting the text. If after all the checks and adjustments the value changed in relation to what was stored before, the new value overwrites the old one.

The CSpinEdit::HighlightLimit() method is rather simple. There, the color of flashing is set first. It is red by default and can be redefined by the user. After that, there is a pause of 100 milliseconds. This is sufficient for a temporary change of color to be noticed. The initial text color is set at the end.

Below is the code of the described methods: 

class CSpinEdit : public CElement
  {
private:
   //--- Current value of the edit
   double            m_edit_value;
   //---
public:
   //--- Returning and setting the edit value
   double            GetValue(void)                           const { return(m_edit_value);               }
   bool              SetValue(const double value);
   //--- Flashing when the limit is reached
   void              HighlightLimit(void);
  };
//+------------------------------------------------------------------+
//| Check of the current value                                       |
//+------------------------------------------------------------------+
bool CSpinEdit::SetValue(double value)
  {
//--- For adjustment
   double corrected_value =0.0;
//--- Adjust considering the step
   corrected_value=::MathRound(value/m_step_value)*m_step_value;
//--- Check for the minimum/maximum
   if(corrected_value<m_min_value)
     {
      //--- Set the minimum value
      corrected_value=m_min_value;
      //--- Set the state to On
      m_spin_dec.State(true);
      //--- Flash to indicate that the limit has been reached
      HighlightLimit();
     }
   if(corrected_value>m_max_value)
     {
      //--- Set the maximum value
      corrected_value=m_max_value;
      //--- Set the state to On
      m_spin_inc.State(true);
      //--- Flash to indicate that the limit has been reached
      HighlightLimit();
     }
//--- If the value has been changed
   if(m_edit_value!=corrected_value)
     {
      m_edit_value=corrected_value;
      m_edit.Color(m_edit_text_color);
      return(true);
     }
//--- Value unchanged
   return(false);
  }
//+------------------------------------------------------------------+
//| Highlighting the limit                                           |
//+------------------------------------------------------------------+
void CSpinEdit::HighlightLimit(void)
  {
//--- Change the text color temporarily
   m_edit.Color(m_edit_text_color_highlight);
//--- Update
   ::ChartRedraw();
//--- Delay before returning to the initial color
   ::Sleep(100);
//--- Change the text color for the initial one
   m_edit.Color(m_edit_text_color);
  }

The CSpinEdit::SetValue() method is designated only for adjusting the value in case the set limit is exceeded. The CSpinEdit:: ChangeValue() method is used for changing the value in the edit:

class CSpinEdit : public CElement
  {
private:
   //--- Changing the value in the edit
   void              ChangeValue(const double value);
  };
//+------------------------------------------------------------------+
//| Changing the value in the edit                                   |
//+------------------------------------------------------------------+
void CSpinEdit::ChangeValue(const double value)
  {
//--- Check, adjust and store the new value
   SetValue(value);
//--- Set the new value in the edit
   m_edit.Description(::DoubleToString(GetValue(),m_digits));
  }

Similar to other elements, we will need a method for managing the availability of the edit control as shown in the code below:

class CSpinEdit : public CElement
  {
private:
   //--- Checkbox state (available/blocked)
   bool              m_spin_edit_state;
   //---
public:
   //--- Returning/ setting the state of availability of the edit
   bool              SpinEditState(void)                      const { return(m_spin_edit_state);          }
   void              SpinEditState(const bool state);
  };
//+------------------------------------------------------------------+
//| Setting the state of the control                                 |
//+------------------------------------------------------------------+
void CSpinEdit::SpinEditState(const bool state)
  {
   m_spin_edit_state=state;
//--- Color of the text label
   m_label.Color((state)? m_label_color : m_label_color_locked);
//--- Color of the edit
   m_edit.Color((state)? m_edit_text_color : m_edit_text_color_locked);
   m_edit.BackColor((state)? m_edit_color : m_edit_color_locked);
   m_edit.BorderColor((state)? m_edit_border_color : m_edit_border_color_locked);
//--- Icons of switches
   m_spin_inc.BmpFileOn((state)? "::"+m_inc_bmp_file_on : "::"+m_inc_bmp_file_locked);
   m_spin_dec.BmpFileOn((state)? "::"+m_dec_bmp_file_on : "::"+m_dec_bmp_file_locked);
//--- Setting in relation of the current state
   if(!m_spin_edit_state)
     {
      //--- Priorities
      m_edit.Z_Order(-1);
      m_spin_inc.Z_Order(-1);
      m_spin_dec.Z_Order(-1);
      //--- Edit in the read only mode
      m_edit.ReadOnly(true);
     }
   else
     {
      //--- Priorities
      m_edit.Z_Order(m_edit_zorder);
      m_spin_inc.Z_Order(m_spin_zorder);
      m_spin_dec.Z_Order(m_spin_zorder);
      //--- The edit control in the edit mode
      m_edit.ReadOnly(false);
     }
  }

Now, we are going to consider methods for handling the edit control events. Pressing on the text label will generate a custom event with (1) the ON_CLICK_LABEL event identifier, (2) the control identifier, (3) the control index and (4) the description of the text label. The mode of resetting the value in edit to the minimum has been mentioned earlier. This mode is disabled by default (false). It can be enabled with the CSpinEdit::ResetMode() method. For that, you just need to set true in its only argument. If the mode for resetting the value is enabled, then pressing on the text label will call the method for setting a minimum value in the edit.

The code of the CSpinEdit::OnClickLabel() method for handling the press on the text label will be as shown below:

class CSpinEdit : public CElement
  {
private:
   //--- Handling the press on the text label
   bool              OnClickLabel(const string clicked_object);
  };
//+------------------------------------------------------------------+
//| Clicking on the element label                                    |
//+------------------------------------------------------------------+
bool CSpinEdit::OnClickLabel(const string clicked_object)
  {
//--- Leave, if the name is different
   if(m_area.Name()!=clicked_object)
      return(false);
//--- If the mode of resetting the value is enabled
   if(m_reset_mode)
     {
      //--- Set the minimum value
      ChangeValue(MinValue());
     }
//--- Send a message about it
   ::EventChartCustom(m_chart_id,ON_CLICK_LABEL,CElement::Id(),CElement::Index(),m_label.Description());
   return(true);
  }

The user can change the value in the edit control by entering the new value either manually or using the buttons of increment and decrement. We will need new identifiers of custom events. Add them in the Defines.mqh file:

//+------------------------------------------------------------------+
//|                                                      Defines.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#define ON_END_EDIT               (18) // Final editing of the value in the edit
#define ON_CLICK_INC              (19) // Change the counter up
#define ON_CLICK_DEC              (20) // Change the counter down

To handle the manual entry of the new value, let us write the CSpinEdit::OnEndEdit() method. It will be called in the CSpinEdit::OnEvent() common handler by receiving an event with the CHARTEVENT_OBJECT_ENDEDIT identifier. The new value can be adjusted if the necessity arises. At the end of the method, a custom event will be generated with (1) the ON_END_EDIT event identifier, (2) the element identifier, (3) the element index and (4) the description from the text label as shown in the code below. 

class CSpinEdit : public CElement
  {
private:
   //--- Handling the value entering in the edit
   bool              OnEndEdit(const string edited_object);
  };
//+------------------------------------------------------------------+
//| Handling the value entering in the edit                          |
//+------------------------------------------------------------------+
bool CSpinEdit::OnEndEdit(const string edited_object)
  {
//--- Leave, if the name is different
   if(m_edit.Name()!=edited_object)
      return(false);
//--- Get the entered value
   double entered_value=::StringToDouble(m_edit.Description());
//--- Check, adjust and store the new value
   ChangeValue(entered_value);
//--- Send a message about it
   ::EventChartCustom(m_chart_id,ON_END_EDIT,CElement::Id(),CElement::Index(),m_label.Description());
   return(true);
  }

To handle the press on the increment and decrement buttons, we need to create two separate methods CSpinEdit::OnClickSpinInc() and CSpinEdit::OnClickSpinDec(). They are rather simple. After a graphical object has been pressed on, there is a check by its name of if it is a button of our control. Then, we get the current value in the edit and increase/decrease its step set in the properties of the control. At the end of the methods, a custom event is generated with (1) the ON_CLICK_INC/ON_CLICK_DEC event identifier, (2) the element identifier, (3) the element index and (4) the description from the text label as shown in the code below.

class CSpinEdit : public CElement
  {
private:
   //--- Handling the edit button press
   bool              OnClickSpinInc(const string clicked_object);
   bool              OnClickSpinDec(const string clicked_object);
  };
//+------------------------------------------------------------------+
//| Pressing on the increment switch                                 |
//+------------------------------------------------------------------+
bool CSpinEdit::OnClickSpinInc(const string clicked_object)
  {
//--- Leave, if the name is different
   if(m_spin_inc.Name()!=clicked_object)
      return(false);
//--- Get the current value
   double value=GetValue();
//--- Increase by one step and check for exceeding the limit
   ChangeValue(value+m_step_value);
//--- Set the state to On
   m_spin_inc.State(true);
//--- Send a message about it
   ::EventChartCustom(m_chart_id,ON_CLICK_INC,CElement::Id(),CElement::Index(),m_label.Description());
   return(true);
  }
//+------------------------------------------------------------------+
//| Pressing on the decrement switch                                 |
//+------------------------------------------------------------------+
bool CSpinEdit::OnClickSpinDec(const string clicked_object)
  {
//--- Leave, if the name is different
   if(m_spin_dec.Name()!=clicked_object)
      return(false);
//--- Get the current value
   double value=GetValue();
//--- Decrease by one step and check for exceeding the limit
   ChangeValue(value-m_step_value);
//--- Set the state to On
   m_spin_dec.State(true);
//--- Send a message about it
   ::EventChartCustom(m_chart_id,ON_CLICK_DEC,CElement::Id(),CElement::Index(),m_label.Description());
   return(true);
  }

All these handling methods must be called in the main method for event handling as shown in the code below. Access to the body of handling methods is controlled by the current availability of the control.

//+------------------------------------------------------------------+
//| Event handling                                                   |
//+------------------------------------------------------------------+
void CSpinEdit::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Handling the left mouse button click on the object
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Leave, if the control is blocked
      if(!m_spin_edit_state)
         return;
      //--- Handling the press on the text label
      if(OnClickLabel(sparam))
         return;
      //--- Handling the edit button press
      if(OnClickSpinInc(sparam))
         return;
      if(OnClickSpinDec(sparam))
         return;
      //---
      return;
     }
//--- Handling the value change in edit event
   if(id==CHARTEVENT_OBJECT_ENDEDIT)
     {
      //--- Leave, if the control is blocked
      if(!m_spin_edit_state)
         return;
      //--- Handling the value entry
      if(OnEndEdit(sparam))
         return;
     }
  }

For fast scrolling of values when the left mouse button is pressed down over switch buttons of the control, create the CSpinEdit::FastSwitching() method that will be called in the timer of the control. We discussed this method when spoke about the CListView class for creating list views with a scrollbar. Whereas this method was required there for scrolling a list, here it will have a function of increasing or decreasing values in edit. More detailed code of the CSpinEdit::FastSwitching() method is presented below. 

class CSpinEdit : public CElement
  {
private:
   //--- Fast scrolling of values in the edit
   void              FastSwitching(void);
  };
//+------------------------------------------------------------------+
//| Timer                                                            |
//+------------------------------------------------------------------+
void CSpinEdit::OnEventTimer(void)
  {
//--- If the element is a drop-down
   if(CElement::IsDropdown())
     {
      ChangeObjectsColor();
      FastSwitching();
     }
   else
     {
      //--- Track the change of color and the fast scrolling of values 
      //    if the form is not blocked
      if(!m_wnd.IsLocked())
        {
         ChangeObjectsColor();
         FastSwitching();
        }
     }
  }
//+------------------------------------------------------------------+
//| Fast scrolling of values in the edit                             |
//+------------------------------------------------------------------+
void CSpinEdit::FastSwitching(void)
  {
//--- Leave, if the focus is not on the control
   if(!CElement::MouseFocus())
      return;
//--- Return the counter to the initial value if the mouse button is released
   if(!m_mouse_state)
      m_timer_counter=SPIN_DELAY_MSC;
//--- If the mouse button is pressed down
   else
     {
      //--- Increase the counter by the set step
      m_timer_counter+=TIMER_STEP_MSC;
      //--- Leave, if less than zero
      if(m_timer_counter<0)
         return;
      //--- Get the current value in the edit
      double current_value=::StringToDouble(m_edit.Description());
      //--- If increase 
      if(m_spin_inc.State())
         SetValue(current_value+m_step_value);
      //--- If decrease
      else if(m_spin_dec.State())
         SetValue(current_value-m_step_value);
      //--- Change the value if the switching button is still pressed down
      if(m_spin_inc.State() || m_spin_dec.State())
         m_edit.Description(::DoubleToString(GetValue(),m_digits));
     }
  }

 

 


Testing the Edit Control

All the methods of the edit control have been implemented. Let us test it in the program that we have prepared earlier. In the CProgram custom class of the application, create one instance of the CSpinEdit class and declare a method for creating the edit control.

//+------------------------------------------------------------------+
//| Class for creating the application                               |
//+------------------------------------------------------------------+
class CProgram : public CWndEvents
  {
private:
   //--- Edits
   CSpinEdit         m_spin_edit1;
   //---
private:
   //--- Edits
#define SPINEDIT1_GAP_X       (150)
#define SPINEDIT1_GAP_Y       (75)
   bool              CreateSpinEdit1(const string text);
  };

Let us make the first checkbox to manage the availability of this control in the same way as it was done in relation to the second checkbox. Therefore, after this control has been created, its availability will depend on the state of the first checkbox as shown in the code below.

//+------------------------------------------------------------------+
//| Creates edit 1                                                   |
//+------------------------------------------------------------------+
bool CProgram::CreateSpinEdit1(string text)
  {
//--- Store the window pointer
   m_spin_edit1.WindowPointer(m_window1);
//--- Coordinates
   int x=m_window1.X()+SPINEDIT1_GAP_X;
   int y=m_window1.Y()+SPINEDIT1_GAP_Y;
//--- Value
   double v=(m_spin_edit1.GetValue()==WRONG_VALUE) ? 4 : m_spin_edit1.GetValue();
//--- Set properties before creation
   m_spin_edit1.XSize(150);
   m_spin_edit1.YSize(18);
   m_spin_edit1.EditXSize(76);
   m_spin_edit1.MaxValue(1000);
   m_spin_edit1.MinValue(-1000);
   m_spin_edit1.StepValue(1);
   m_spin_edit1.SetDigits(0);
   m_spin_edit1.SetValue(v);
   m_spin_edit1.ResetMode(true);
   m_spin_edit1.AreaColor(clrWhiteSmoke);
   m_spin_edit1.LabelColor(clrBlack);
   m_spin_edit1.LabelColorLocked(clrSilver);
   m_spin_edit1.EditColorLocked(clrWhiteSmoke);
   m_spin_edit1.EditTextColor(clrBlack);
   m_spin_edit1.EditTextColorLocked(clrSilver);
   m_spin_edit1.EditBorderColor(clrSilver);
   m_spin_edit1.EditBorderColorLocked(clrSilver);
//--- Create control
   if(!m_spin_edit1.CreateSpinEdit(m_chart_id,m_subwin,text,x,y))
      return(false);
//--- The availability will depend on the current state of the first checkbox
   m_spin_edit1.SpinEditState(m_checkbox1.CheckButtonState());
//--- Add the object to the common array of the object groups
   CWndContainer::AddToElementsArray(0,m_spin_edit1);
   return(true);
  }

Similar to other controls, the CProgram::CreateSpinEdit1() method must be called in the main method for creating the graphical interface of the program. Below is a shortened version of the method:

//+------------------------------------------------------------------+
//| Creates the training panel                                       |
//+------------------------------------------------------------------+
bool CProgram::CreateTradePanel(void)
  {
//--- Creating form 1 for controls
//--- Creating controls:
//    Main menu
//--- Context menus
//--- Creating the status bar
//--- Checkboxes
//--- Edits
   if(!CreateSpinEdit1("Spin Edit 1:"))
      return(false);
//--- Redrawing the chart
   m_chart.Redraw();
   return(true);
  }

In the CProgram::OnEvent() event handler, add code for the test of listening events from the edit controls and also specify that the first edit depends on the state of the first checkbox

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- The text label press event
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
      //--- If the press was on the first checkbox
      if(lparam==m_checkbox1.Id())
        {
         //--- Set the state for the second checkbox and the first edit
         m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState());
         m_spin_edit1.SpinEditState(m_checkbox1.CheckButtonState());
        }
     }
//--- The end of value entry in edit event
   if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
     }
//--- Switching buttons of the edit press event
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_INC || id==CHARTEVENT_CUSTOM+ON_CLICK_DEC)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
     }
  }

Compile the program and load it on to the chart. You can see what the graphical interface of the application currently looks like in the screenshot below:

Fig. 4. Testing the edit control.

Fig. 4. Testing the edit control.

 


Other Controls with Checkboxes

It was mentioned at the beginning of the article that besides the checkbox and edit controls we would consider edit with checkbox and check combobox. Edit with checkbox is an extended version of the CSpinEdit class enriched with fields and methods of the CCheckBox class which have been considered in this article. 

 Fig. 5. Compound parts of the edit with checkbox control.

Fig. 5. Compound parts of the edit with checkbox control.


Check combobox is a similar combination of the CComboBox and CCheckBox classes:

 Fig. 6. Compound parts of the check combobox control.

Fig. 6. Compound parts of the check combobox control.


You can find the implementation of the CCheckBoxEdit (edit with checkbox) and CCheckComboBox (check combobox) in the files attached to this article for independent study. As the control of the CCheckComboBox type contains a drop-down list view, relevant additions need to be introduced in the WndContainer.mqh file similar to other elements that have drop-down parts. In this case, the drop-down list view pointer must get into the m_drop_lists[] private array of pointers. A detailed description of the way to do it can be found in the article Graphical Interfaces V: The Combobox Control (Chapter 3).

For the sake of example, we will add the test application with these controls so you can see how it works. Let us add two checkboxes of the CCheckBox type and one of CCheckBoxEdit and CCheckComboBox. The availability of the control of the CCheckBoxEdit type will depend on the state of the third checkbox and the availability of the control of the CCheckComboBox control will be defined by the state of the fourth combobox.

 Fig. 7. Testing controls of mixed types.

Fig. 7. Testing controls of mixed types.

 


Conclusion

In this article, we have developed controls widely used in many graphical interfaces in different environments: checkbox, edit, edit with checkbox and check combobox. In the second chapter, we will develop the slider and dual slider controls. 

You can download the material of Part VI and test how it works. If you have questions on using material from those files, you can refer to the detailed description of the library development in one of the articles from the list below or ask your question in the comments of this article.

List of articles (chapters) of the sixth part:

Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/2466

Attached files |
Last comments | Go to discussion (5)
[Deleted] | 20 Jun 2016 at 04:46

Hello sir i am interesting on your Article but i stil newbie about GUI and mql,
can you please  tell me how to get  value of Spin edit so it can be read to the EA.

 

Regards 

Anatoli Kazharski
Anatoli Kazharski | 20 Jun 2016 at 10:18
Hidayat Nur Wahit:

Hello sir i am interesting on your Article but i stil newbie about GUI and mql,
can you please  tell me how to get  value of Spin edit so it can be read to the EA.

Regards 

For example, from an article in CProgram::OnEvent() event handler:

void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Событие нажатия на текстовой метке
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
      //--- Если нажали на первом чекбоксе
      if(lparam==m_checkbox1.Id())
        {
         m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState());
         m_spin_edit1.SpinEditState(m_checkbox1.CheckButtonState());
         
         Print("m_spin_edit1.GetValue(): ",m_spin_edit1.GetValue());
        }

      if(lparam==m_checkbox3.Id())
        {
         m_checkboxedit1.CheckBoxEditState(m_checkbox3.CheckButtonState());
         
         Print("m_checkboxedit1.GetValue(): ",m_checkboxedit1.GetValue());
        }

      if(lparam==m_checkbox4.Id())
        {
         m_checkcombobox1.CheckComboBoxState(m_checkbox4.CheckButtonState());
        }

      if(lparam==m_checkbox5.Id())
        {
         m_slider1.SliderState(m_checkbox5.CheckButtonState());
         m_dual_slider1.SliderState(m_checkbox5.CheckButtonState());
         
         Print("m_slider1.GetValue(): ",m_slider1.GetValue());
         Print("m_dual_slider1.GetLeftValue(): ",m_dual_slider1.GetLeftValue());
         Print("m_dual_slider1.GetRightValue(): ",m_dual_slider1.GetRightValue());
        }
     }

   if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
      
      if(lparam==m_spin_edit1.Id())
        {
         Print("m_spin_edit1.GetValue(): ",m_spin_edit1.GetValue());
        }
        
      if(lparam==m_checkboxedit1.Id())
        {
         Print("m_checkboxedit1.GetValue(): ",m_checkboxedit1.GetValue());
        }
      
      if(lparam==m_slider1.Id())
        {
         Print("m_slider1.GetValue(): ",m_slider1.GetValue());
        }
        
      if(lparam==m_dual_slider1.Id())
        {
         Print("m_dual_slider1.GetLeftValue(): ",m_dual_slider1.GetLeftValue());
         Print("m_dual_slider1.GetRightValue(): ",m_dual_slider1.GetRightValue());
        }
     }

   if(id==CHARTEVENT_CUSTOM+ON_CLICK_INC || id==CHARTEVENT_CUSTOM+ON_CLICK_DEC)
     {
      ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam);
      
      if(lparam==m_spin_edit1.Id())
        {
         Print("m_spin_edit1.GetValue(): ",m_spin_edit1.GetValue());
        }
        
      if(lparam==m_checkboxedit1.Id())
        {
         Print("m_checkboxedit1.GetValue(): ",m_checkboxedit1.GetValue());
        }
     }
  }
[Deleted] | 3 Jul 2016 at 12:52
Anatoli Kazharski:

For example, from an article in CProgram::OnEvent() event handler:

Thank's sir and now it well read the value,and will apply on my EA.

Regard's
Thomas Schwabhaeuser
Thomas Schwabhaeuser | 5 Oct 2016 at 09:53

Dear Anatoli Kazharski, thank you so much for this great library!

I kind of love the look & feel of the resulting interfaces.

When starting to adapt Test Library 10.mq5 to my personal needs I just thought it is worth mentioning that it really helped me to add the method

void CSpinEdit::LabelText(const string new_text)

to the class CSpinEdit doing nothing but deferring any call to CLabel::Description(const string new_text). The reason is that I am using a CSpinEdit for different types of values depending on the state of a CComboBox. After changing label with LabelText(text) and choosing the appropriate edit format the values are displayed as desired after calling

void CSpinEdit::ChangeValue(const double value)

 

Thanks again and Regards 

Anatoli Kazharski
Anatoli Kazharski | 5 Oct 2016 at 12:20
Thomas Schwabhäuser:

...

Thanks for the tip!

I will add this capability. Watch for updates future articles in this series.

Self-optimization of EA: Evolutionary and genetic algorithms Self-optimization of EA: Evolutionary and genetic algorithms
This article covers the main principles set fourth in evolutionary algorithms, their variety and features. We will conduct an experiment with a simple Expert Advisor used as an example to show how our trading system benefits from optimization. We will consider software programs that implement genetic, evolutionary and other types of optimization, and provide examples of application when optimizing a predictor set and parameters of the trading system.
Universal Expert Advisor: Pending Orders and Hedging Support (Part 5) Universal Expert Advisor: Pending Orders and Hedging Support (Part 5)
This article provides further description of the CStrategy trading engine. By popular demand of users, we have added pending order support functions to the trading engine. Also, the latest version of the MetaTrader 5 now supports accounts with the hedging option. The same support has been added to CStrategy. The article provides a detailed description of algorithms for the use of pending orders, as well as of CStrategy operation principles on accounts with the hedging option enabled.
Graphical Interfaces VI: the Slider and the Dual Slider Controls (Chapter 2) Graphical Interfaces VI: the Slider and the Dual Slider Controls (Chapter 2)
In the previous article, we have enriched our library with four controls frequently used in graphical interfaces: checkbox, edit, edit with checkbox and check combobox. The second chapter of the sixth part will be dedicated to the slider and the dual slider controls.
How to create an indicator of non-standard charts for MetaTrader Market How to create an indicator of non-standard charts for MetaTrader Market
Through offline charts, programming in MQL4, and reasonable willingness, you can get a variety of chart types: "Point & Figure", "Renko", "Kagi", "Range bars", equivolume charts, etc. In this article, we will show how this can be achieved without using DLL, and therefore such "two-for-one" indicators can be published and purchased from the Market.