English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
MQL5 Tarif Defteri Gösterge Alt Pencere Kontrolleri - Düğmeler

MQL5 Tarif Defteri Gösterge Alt Pencere Kontrolleri - Düğmeler

MetaTrader 5Örnekler | 13 Ocak 2022, 16:51
90 0
Anatoli Kazharski
Anatoli Kazharski

Giriş

Bu makalede, düğme kontrolleri ile bir kullanıcı arayüzünü geliştirme örneğini ele alacağız. Kullanıcı ile etkileşim fikrini iletmek için, imleç üzerlerine geldiğinde düğmelerin renkleri değişecektir. İmleç bir düğmenin üzerindeyken, düğme rengi hafifçe koyulaşacak ve düğmeye tıklandığında büyük ölçüde koyulaşacaktır. Ayrıca, her düğmeye araç ipuçları ekleyerek sezgisel bir arayüz oluşturacağız.

Makale aynı zamanda, fare hareketi olayı, sol fare düğmesinin durumu, nesneye sol tıklama ve grafik özelliklerini değiştirme olayı gibi bazı olayları da kapsayacaktır. Gösterge alt penceresinin tüm alanını kaplayacak bir düğme paneli oluşturacağız. Örnekleme amacıyla, düğmeler, her sırada dört düğme olacak şekilde üç sıra halinde düzenlenecektir.

 

Geliştirme

MQL5'te düğmeler, OBJ_BUTTON (Düğme), OBJ_BITMAP (Bitmap), OBJ_BITMAP_LABEL (Bitmap Etiketi) veya OBJ_EDIT (Düzenle) gibi çeşitli grafik nesneleri kullanılarak oluşturulabilir.

Bu makalede, düğmeleri OBJ_EDIT kullanarak oluşturacağız. Bu türde nesneler Salt Okunur hale getirilebilir. Bunlar aynı zamanda, belirttiğiniz metni görüntüleyebilmeleri açısından kullanışlıdır. Ayrıca, nesnenin köşelerini keskinleştirirken kenarlığını koruyabilirsiniz.

Öyleyse, MQL5 Sihirbazını kullanarak bir gösterge oluşturalım. Göstergenin kaynak kodu, biraz değiştirilmiş haliyle, aşağıdaki gibi olacaktır:

//+------------------------------------------------------------------+
//|                                                  TestButtons.mq5 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
//---
#property indicator_separate_window // Indicator is in the subwindow
#property indicator_plots 0         // No plotting series
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---

  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---

  }
//+------------------------------------------------------------------+

Şu anda sıfır çizim serisine sahip boş bir penceremiz var. Bir zamanlayıcı ihtiyacı biraz sonra tartışılacaktır.

Şimdi fonksiyonları oluştururken kullanılacak sabitleri, değişkenleri ve dizileri ekleyelim. Tüm diziler iki boyutludur. İlk boyut, pencere yüksekliği boyunca düğme sayısını belirtir ve ikinci boyut, pencere genişliği boyunca düğme sayısını belirtir:

//---
#define BUTTON_COLUMNS  4           // Number of buttons across the width
#define BUTTON_ROWS 3               // Number of buttons across the height
//+------------------------------------------------------------------+
//| Global parameters                                                |
//+------------------------------------------------------------------+
//--- Font
string            font_name="Calibri";
//--- Indicator subwindow properties
int               subwindow_number           =WRONG_VALUE;             // Subwindow number
int               subwindow_height           =0;                       // Subwindow height
string            subwindow_shortname        ="TestButtons";           // Short name of the indicator
string            prefix                     =subwindow_shortname+"_"; // Prefix for object names
int               chart_width                =0;                       // Chart width
int               chart_height               =0;                       // Chart height
int               chart_y_offset             =0;                       // Distance from the chart top to the subwindow
//--- Colors of button elements
color             background_color           =clrSteelBlue;            // Button color
color             font_color                 =clrWhite;                // Font color
color             hover_background_color     =C'38,118,166';           // Button color when the cursor goes over
color             clicked_background_color   =C'2,72,136';             // Clicked button color
//--- Text displayed on buttons
string button_texts[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"Button 01","Button 02","Button 03","Button 04"},
     {"Button 05","Button 06","Button 07","Button 08"},
     {"Button 09","Button 10","Button 11","Button 12"}
  };
//--- Object names
string button_object_names[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"button_01","button_02","button_03","button_04"},
     {"button_05","button_06","button_07","button_08"},
     {"button_09","button_10","button_11","button_12"}
  };
//--- Button widths
int button_widths[BUTTON_ROWS][BUTTON_COLUMNS];
//--- Button heights
int button_heights[BUTTON_ROWS][BUTTON_COLUMNS];
//--- X-coordinates
int button_x_distances[BUTTON_ROWS][BUTTON_COLUMNS];
//--- Y-coordinates
int button_y_distances[BUTTON_ROWS][BUTTON_COLUMNS];
//--- Button states
bool button_states[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {true,false,false,false},
     {false,false,false,false},
     {false,false,false,false}
  };
//--- Button colors
color button_colors[BUTTON_ROWS][BUTTON_COLUMNS];

Göstergeyi grafiğe eklerken, diziler, koordinatların ve boyutlarının hesaplanmasının ardından OnInit() fonksiyonu içindeki nesne özelliklerine başlatılacaktır. İmleç izlemeyi de etkinleştirmemiz gerekiyor. Son olarak, gösterge alt penceresine düğmeler eklememiz gerekiyor. Bu eylemler, kolaylık sağlamak adına, aşağıda tek tek inceleyeceğimiz ayrı fonksiyonlarda gerçekleştirilecektir. Bunun sonucunda, OnInit() fonksiyonu kodu aşağıdaki şekilde görünecektir:

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Set the timer at 1-second intervals
   EventSetTimer(1);
//--- Add prefix to object names
   AddPrefix();
//--- Enable tracking of mouse events
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
//--- Set the short name
   IndicatorSetString(INDICATOR_SHORTNAME,subwindow_shortname);
//--- Set subwindow properties
   SetSubwindowProperties();
//--- Set button properties
   SetButtonColors();      // Colors
   SetButtonCoordinates(); // Coordinates
   SetButtonSizes();       // Sizes
//--- Add the button panel
   AddButtonsPanel();
//--- Refresh the chart
   ChartRedraw();
//--- Everything completed successfully
   return(INIT_SUCCEEDED);
  }

AddPrefix() fonksiyonundaki ön ek, yani göstergenin kısa adı, her bir grafik nesnesinin adına eklenir. Bu, çizelgede birden fazla programın çalıştığında nesne adlarının eşleşmesi durumunda nesnelerin değiştirilmesini/silinmesini/kaydurulmasını hariç tutmak için gereklidir.

//+------------------------------------------------------------------+
//| Adding prefix to all object names                                |
//+------------------------------------------------------------------+
void AddPrefix()
  {
//--- Add prefix to object names
   for(int i=0; i<BUTTON_COLUMNS; i++)
      for(int j=0; j<BUTTON_ROWS; j++)
         button_object_names[j][i]=prefix+button_object_names[j][i];
  }

Hesaplamalar için gereken grafik özellikleri SetSubwindowProperties() fonksiyonunda başlatılacaktır:

//+------------------------------------------------------------------+
//| Setting subwindow properties                                     |
//+------------------------------------------------------------------+
void SetSubwindowProperties()
  {
//--- Indicator subwindow number
   subwindow_number=ChartWindowFind(0,subwindow_shortname);
//--- Subwindow width and height
   chart_width=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
   subwindow_height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,subwindow_number);
  }

Grafik özelliklerini elde etmenin ardından, düğme renklerini, koordinat değerlerini ve boyutlarını belirlemek için hesaplamalar yapabiliriz. Tüm bu eylemler aşağıda sağlanan üç ayrı fonksiyonda gerçekleştirilir:

//+------------------------------------------------------------------+
//| Setting button color                                             |
//+------------------------------------------------------------------+
void SetButtonColors()
  {
   for(int i=0; i<BUTTON_COLUMNS; i++)
     {
      for(int j=0; j<BUTTON_ROWS; j++)
        {
         //--- If the button is clicked
         if(button_states[j][i])
            button_colors[j][i]=clicked_background_color;
         //--- If the button is unclicked
         else
            button_colors[j][i]=background_color;
        }
     }
  }
//+------------------------------------------------------------------+
//| Setting X and Y coordinates for buttons                          |
//+------------------------------------------------------------------+
void SetButtonCoordinates()
  {
   int button_width=chart_width/BUTTON_COLUMNS;
   int button_height=subwindow_height/BUTTON_ROWS;
//---
   for(int i=0; i<BUTTON_COLUMNS; i++)
     {
      for(int j=0; j<BUTTON_ROWS; j++)
        {
         if(i==0)
            button_x_distances[j][i]=0;
         else
            button_x_distances[j][i]=(button_width*i)-i;
         //---
         if(j==0)
            button_y_distances[j][i]=0;
         else
            button_y_distances[j][i]=(button_height*j)-j;
        }
     }
  }
//+------------------------------------------------------------------+
//| Setting button width and height                                  |
//+------------------------------------------------------------------+
void SetButtonSizes()
  {
   int button_width=chart_width/BUTTON_COLUMNS;
   int button_height=subwindow_height/BUTTON_ROWS;
//---
   for(int i=0; i<BUTTON_COLUMNS; i++)
     {
      for(int j=0; j<BUTTON_ROWS; j++)
        {
         if(i==BUTTON_COLUMNS-1)
            button_widths[j][i]=chart_width-(button_width*(BUTTON_COLUMNS-1)-i);
         else
            button_widths[j][i]=button_width;
         //---
         if(j==BUTTON_ROWS-1)
            button_heights[j][i]=subwindow_height-(button_height*(BUTTON_ROWS-1)-j)-1;
         else
            button_heights[j][i]=button_height;
        }
     }
  }

Son olarak, AddButtonsPanel() fonksiyonu, düğmeleri gösterge alt penceresine ekler:

//+------------------------------------------------------------------+
//| Adding buttons to the indicator subwindow                        |
//+------------------------------------------------------------------+
void AddButtonsPanel()
  {
//--- Create buttons
   for(int i=0; i<BUTTON_COLUMNS; i++)
     {
      for(int j=0; j<BUTTON_ROWS; j++)
        {
         CreateButton(0,subwindow_number,button_object_names[j][i],button_texts[j][i],
                      CORNER_LEFT_UPPER,font_name,8,font_color,button_colors[j][i],clrNONE,
                      button_widths[j][i],button_heights[j][i],
                      button_x_distances[j][i],button_y_distances[j][i],2,true,button_texts[j][i]);
        }
     }
  }

CreateButton() yardımcı fonksiyonunun kaynak kodu aşağıdaki gibidir:

//+------------------------------------------------------------------+
//| Creating a button (graphical object of the Edit type)            |
//+------------------------------------------------------------------+
void CreateButton(long   chart_id,     // chart id
                  int    sub_window,   // (sub)window number
                  string object_name,  // object name
                  string text,         // displayed text
                  long   corner,       // chart corner
                  string font,         // font
                  int    font_size,    // font size
                  color  c_font,       // font color
                  color  c_background, // background color
                  color  c_border,     // border color
                  int    x_size,       // width
                  int    y_size,       // height
                  int    x_dist,       // X-coordinate
                  int    y_dist,       // Y-coordinate
                  long   zorder,       // Z-order
                  bool   read_only,    // Read Only flag
                  string tooltip)      // tooltip
  {
//--- If the object has been created successfully, set the remaining properties
   if(ObjectCreate(chart_id,object_name,OBJ_EDIT,subwindow_number,0,0))
     {
      ObjectSetString(chart_id,object_name,OBJPROP_TEXT,text);              // name
      ObjectSetInteger(chart_id,object_name,OBJPROP_CORNER,corner);         // chart corner
      ObjectSetString(chart_id,object_name,OBJPROP_FONT,font);              // font
      ObjectSetInteger(chart_id,object_name,OBJPROP_FONTSIZE,font_size);    // font size
      ObjectSetInteger(chart_id,object_name,OBJPROP_COLOR,c_font);          // font color
      ObjectSetInteger(chart_id,object_name,OBJPROP_BGCOLOR,c_background);  // background color
      ObjectSetInteger(chart_id,object_name,OBJPROP_BORDER_COLOR,c_border); // border color
      ObjectSetInteger(chart_id,object_name,OBJPROP_XSIZE,x_size);          // width
      ObjectSetInteger(chart_id,object_name,OBJPROP_YSIZE,y_size);          // height
      ObjectSetInteger(chart_id,object_name,OBJPROP_XDISTANCE,x_dist);      // X-coordinate
      ObjectSetInteger(chart_id,object_name,OBJPROP_YDISTANCE,y_dist);      // Y-coordinate
      ObjectSetInteger(chart_id,object_name,OBJPROP_SELECTABLE,false);      // object is not available for selection
      ObjectSetInteger(chart_id,object_name,OBJPROP_ZORDER,zorder);         // Z-order
      ObjectSetInteger(chart_id,object_name,OBJPROP_READONLY,read_only);    // Read Only text
      ObjectSetInteger(chart_id,object_name,OBJPROP_ALIGN,ALIGN_CENTER);    // align center
      ObjectSetString(chart_id,object_name,OBJPROP_TOOLTIP,tooltip);        // no tooltip if "\n"
     }
  }

CreateButton() fonksiyonunun son parametresine dikkat edin: bu, fare imleci bir grafik nesnesinin üzerinden geçtiğinde araç ipucundan sorumludur. Örneğin, bu parametre AddButtonsPanel() fonksiyonunda button_texts dizisinden (düğmeler üzerinde görüntülenen metin) aktarılan değerler ile temsil edilir. İsterseniz daha detaylı açıklamalara sahip ayrı bir dizi oluşturabilirsiniz.

Şimdi, göstergeyi grafiğe eklerseniz, sonuç aşağıdaki gibi olacaktır:

Şekil 1. Gösterge alt penceresine eklenen düğmeler

Şekil 1. Gösterge alt penceresine eklenen düğmeler

Şu anda, bunlar yalnızca gösterge alt penceresinde düzenlenmiş nesnelerdir. Kullanıcı ile etkileşim henüz uygulanmamıştır. Şimdi bu nesnelere "hayat verelim".

İlk olarak, alt pencere yeniden boyutlandırıldığında, düğme boyutlarını bunun boyutuna göre ayarlama imkanını uygulayacağız. Bunun için iki fonksiyon daha yazacağız: UpdateButtonCoordinates() ve ResizeButtons(). Bunlar, düğme koordinatlarını ve boyutlarını ayarlayacaktır:

//+------------------------------------------------------------------+
//| Updating button coordinates                                      |
//+------------------------------------------------------------------+
void UpdateButtonCoordinates()
  {
//--- Set coordinates
   for(int i=0; i<BUTTON_COLUMNS; i++)
     {
      for(int j=0; j<BUTTON_ROWS; j++)
        {
         ObjectSetInteger(0,button_object_names[j][i],OBJPROP_XDISTANCE,button_x_distances[j][i]);
         ObjectSetInteger(0,button_object_names[j][i],OBJPROP_YDISTANCE,button_y_distances[j][i]);
        }
     }
  }
//+------------------------------------------------------------------+
//| Updating button sizes                                            |
//+------------------------------------------------------------------+
void ResizeButtons()
  {
//--- Set sizes
   for(int i=0; i<BUTTON_COLUMNS; i++)
     {
      for(int j=0; j<BUTTON_ROWS; j++)
        {
         ObjectSetInteger(0,button_object_names[j][i],OBJPROP_XSIZE,button_widths[j][i]);
         ObjectSetInteger(0,button_object_names[j][i],OBJPROP_YSIZE,button_heights[j][i]);
        }
     }
  }

Grafik özelliklerinin değiştirilmesi ve grafiğin yeniden boyutlandırılması olayını ele almak için, CHARTEVENT_CHART_CHANGE tanımlayıcısını kullanmamız gerekiyor.. Aşağıda, OnChartEvent() fonksiyonu gövdesine eklemeniz gereken kodu göreceksiniz:

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,           // event identifier
                  const long &lparam,     // parameter of the event of type long
                  const double &dparam,   // parameter of the event of type double
                  const string &sparam)   // parameter of the event of type string
  {
//--- Tracking the event of modifying the chart properties and resizing the chart
   if(id==CHARTEVENT_CHART_CHANGE)
     {
      //--- Set subwindow properties
      SetSubwindowProperties();
      //--- Set button coordinates
      SetButtonCoordinates();
      //--- Set button sizes
      SetButtonSizes();
      //--- Set new button coordinates
      UpdateButtonCoordinates();
      //--- Set new button sizes
      ResizeButtons();
      //--- Refresh the chart
      ChartRedraw(); return;
     }

  }

Göstergeyi grafiğe şimdi eklersek (veya gösterge halihazırda grafik üzerindeyse kodu yeniden derlersek), grafik penceresi veya gösterge alt penceresi yeniden boyutlandırılır boyutlandırılmaz, düğmeler otomatik olarak yeniden boyutlandırılacak ve yeniden konumlandırılacaktır.

Ayrıca, imleç bir düğmenin üzerine geldiğinde düğme renginin değişimini uyguluyoruz. Fakat fonksiyon kodunu yazmadan önce, CHARTEVENT_MOUSE_MOVE tanımlayıcısı ile olayın ele alınma sürecine bir göz atalım.

OnInit() fonksiyonu içinde, halihazırda, programa fare imleci hareketini ve sol fare düğmesinin durumunu izlemesi talimatı veren bir dizemiz var:

//--- Enable tracking of mouse events
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);

Bu dize olmadan (veya aktarılan son parametre değeri false ise), CHARTEVENT_MOUSE_MOVE tanımlayıcı ile olaylar, OnChartEvent() fonksiyonu içinde izlenmeyecektir. Bu tür olayları her programda izlemeye gerek olmayabileceğinden, bu oldukça faydalı gibi görünüyor.

Fare olayı izlemenin nasıl çalıştığını anlamak için, OnChartEvent() fonksiyon koduna, geçici olarak ilgili yorumu grafikte görüntüleme imkanını ekleyebiliriz:

//--- Mouse movement and left-click tracking
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      Comment("id: ",CHARTEVENT_MOUSE_MOVE,"\n",
              "lparam (x): ",lparam,"\n",
              "dparam (y): ",dparam,"\n",
              "sparam (state of the mouse buttons): ",sparam
              );

Şimdi fare imlecini grafikte hareket ettirmeye başlarsanız, sol üst köşedeki imlecin mevcut koordinatlarını görebileceksiniz. Sol tıklandığında, değişiklikler yorum satırı sparam (fare düğmelerinin durumu) içinde görüntülenecektir, burada bir (1) fare düğmesine tıklandığı anlamına gelir ve sıfır (0) düğmenin bırakıldığı anlamına gelir.

Fare imlecinin mevcut olarak bulunduğu alt pencereyi bilmek isterseniz, ChartXYToTimePrice() fonksiyonunu kullanabilirsiniz. Koordinatları alır ve pencere/alt pencere sayısını, zamanı ve fiyatı (referans olarak kendisine aktarılan değişkenlere) döndürür. Bunu, aşağıdaki kodu test ederek çalışma halinde görebilirsiniz:

//--- Mouse movement and left-click tracking
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      int      x      =(int)lparam; // X-coordinate
      int      y      =(int)dparam; // Y-coordinate
      int      window =WRONG_VALUE; // Number of the window where the cursor is located
      datetime time   =NULL;        // Time corresponding to the X-coordinate
      double   price  =0.0;         // Price corresponding to the Y-coordinate
      //--- Get the position of the cursor
      if(ChartXYToTimePrice(0,x,y,window,time,price))
        {
         Comment("id: ",CHARTEVENT_MOUSE_MOVE,"\n",
                 "x: ",x,"\n",
                 "y: ",y,"\n",
                 "sparam (state of the mouse buttons): ",sparam,"\n",
                 "window: ",window,"\n",
                 "time: ",time,"\n",
                 "price: ",DoubleToString(price,_Digits)
                 );
        }
      //---
      return;
     }

Gösterge alt penceresindeki hesaplamalar, göreceli koordinatların kullanılması durumunda daha kolaydır. Bu durumda, Y koordinatı (fiyat ölçeği) ile ilgilidir. Göreceli değeri elde etmek için, yalnızca grafiğin tepesinden gösterge alt penceresine olan mesafeyi mevcut değerden çıkarmanız gerekiyor. Bu işlem şu şekilde yapılabilir:

      //--- Get the position of the cursor
      if(ChartXYToTimePrice(0,x,y,window,time,price))
        {
         //--- Get the distance from the chart top to the indicator subwindow
         chart_y_offset=(int)ChartGetInteger(0,CHART_WINDOW_YDISTANCE,subwindow_number);
         //--- Convert the Y-coordinate to the relative value
         y-=chart_y_offset;
         Comment("id: ",CHARTEVENT_MOUSE_MOVE,"\n",
                 "x: ",x,"\n",
                 "y: ",y,"\n",
                 "sparam (state of the mouse buttons): ",sparam,"\n",
                 "window: ",window,"\n",
                 "time: ",time,"\n",
                 "price: ",DoubleToString(price,_Digits)
                 );
        }

Şimdi, y değişkenindeki değer, fare imleci gösterge alt penceresinin üzerindeyse negatif ve imleç alt pencere alanının üzerine geldiğinde pozitif olacaktır.

Varsayılan olarak, grafiği imlecin grafik üzerindeki konumundan bağımsız olarak zaman ölçeği boyunca kaydırma imkanı vardır. Ancak, gerekirse ve gerektiğinde grafik kaydırma devre dışı bırakılabilir. Bu çoğunlukla, imleç panelin veya özel kontrollerin üzerinde bulunduğunda gerekli olacaktır. İmleç gösterge alt penceresindeyken grafik kaydırmayı devre dışı bırakma ve imleç alt pencereden dışarı hareket ettirildiğinde bunu etkinleştirme kodu, örneğin, aşağıdaki gibi olabilir:

         //--- If the cursor is in the subwindow area, disable chart scrolling
         if(window==subwindow_number)
            ChartSetInteger(0,CHART_MOUSE_SCROLL,false);
         //--- Enable chart scrolling if the cursor moves out of the indicator subwindow area
         else
            ChartSetInteger(0,CHART_MOUSE_SCROLL,true);

Ayrıca, imleç ilgili düğme üzerine geldiğinde düğme rengini değiştiren bir fonksiyon yazalım: ChangeButtonColorOnHover():

//+------------------------------------------------------------------+
//| Changing the button color when the cursor hovers over the button |
//+------------------------------------------------------------------+
void ChangeButtonColorOnHover(int x,int y)
  {
   int x1,y1,x2,y2;
//--- Initialize the array of XY coordinates for buttons
   SetButtonCoordinates();
//--- Determine if the cursor is over any of the buttons
   for(int i=0; i<BUTTON_COLUMNS; i++)
     {
      for(int j=0; j<BUTTON_ROWS; j++)
        {
         //--- If this button is clicked, go to the next one
         if(button_states[j][i])
            continue;
         //--- Get the button boundaries
         x1=button_x_distances[j][i];
         y1=button_y_distances[j][i];
         x2=button_x_distances[j][i]+button_widths[j][i];
         y2=button_y_distances[j][i]+button_heights[j][i];
         //--- If the cursor is within the button area, set the new button color
         if(x>x1 && x<x2 && y>y1 && y<y2)
            ObjectSetInteger(0,button_object_names[j][i],OBJPROP_BGCOLOR,hover_background_color);
         //--- Otherwise set the standard color
         else
            ObjectSetInteger(0,button_object_names[j][i],OBJPROP_BGCOLOR,background_color);
        }
     }
  }

Bunun sonucunda, CHARTEVENT_MOUSE_MOVE tanımlayıcı dalında aşağıdaki kaynak kodumuz olur:

//--- Mouse movement and left-click tracking
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      int      x      =(int)lparam; // X-coordinate
      int      y      =(int)dparam; // Y-coordinate
      int      window =WRONG_VALUE; // Number of the window where the cursor is located
      datetime time   =NULL;        // Time corresponding to the X-coordinate
      double   price  =0.0;         // Price corresponding to the Y-coordinate
      //--- Get the position of the cursor
      if(ChartXYToTimePrice(0,x,y,window,time,price))
        {
         //--- Get the distance from the chart top to the indicator subwindow
         chart_y_offset=(int)ChartGetInteger(0,CHART_WINDOW_YDISTANCE,subwindow_number);
         //--- Convert the Y-coordinate to the relative value
         y-=chart_y_offset;
         //--- If the cursor is in the subwindow area, disable chart scrolling
         if(window==subwindow_number)
            ChartSetInteger(0,CHART_MOUSE_SCROLL,false);
         //--- Enable chart scrolling if the cursor moves out of the indicator subwindow area
         else
            ChartSetInteger(0,CHART_MOUSE_SCROLL,true);
         //--- Change the button color when the cursor is hovered over
         ChangeButtonColorOnHover(x,y);
        }
      //--- Refresh the chart
      ChartRedraw(); 
      return;
     }

Şimdi, imleci düğmelerin üzerinde hareket ettirirseniz, düğme renginin değiştiğini/normale döndüğünü görebileceksiniz.

Şu anda yalnızca Düğme 01, tıklanan düğme rengindedir. Diğer düğmelere tıklamaya çalışırsanız, yanıt ve dolayısıyla renk değişikliği olmayacaktır. Bu durumda renk değişikliğini uygulamak için, CHARTEVENT_OBJECT_CLICK tanımlayıcısına sahip bir olayı kullanmamız gerekir.

İki fonksiyon yazalım: InitializeButtonStates() ve ChangeButtonColorOnClick(). InitializeButtonStates() fonksiyonu, adındaki ön ek dikkate alındığında, belirli bir düğmeye tıklanıp tıklanmadığını kontrol eder. Tıklama olayı tanımlanmışsa, bu durumda düğme durumları (button_states) dizisi bir döngüde başlatılır ve fonksiyon true değerini döndürür.

//+------------------------------------------------------------------+
//| Initializing button states in case of click                      |
//+------------------------------------------------------------------+
bool InitializeButtonStates(string clicked_object)
  {
//--- Get the indicator subwindow number
   subwindow_number=ChartWindowFind(0,subwindow_shortname);
//--- If a button in the indicator subwindow has been clicked
   if(ObjectFind(0,clicked_object)==subwindow_number && StringFind(clicked_object,prefix+"button_",0)>=0)
     {
      //--- Determine the clicked button
      for(int i=0; i<BUTTON_COLUMNS; i++)
        {
         for(int j=0; j<BUTTON_ROWS; j++)
           {
            //--- Determine the state of all buttons
            if(clicked_object==button_object_names[j][i])
               button_states[j][i]=true;
            else
               button_states[j][i]=false;
           }
        }
      //---
      return(true);
     }
//---
   return(false);
  }

Bunun ardından, ChangeButtonColorOnClick() fonksiyonu, düğme renklerini button_states dizisinin değerlerine göre ayarlar.

//+------------------------------------------------------------------+
//| Changing the button color in case of click                       |
//+------------------------------------------------------------------+
void ChangeButtonColorOnClick()
  {
   for(int i=0; i<BUTTON_COLUMNS; i++)
     {
      for(int j=0; j<BUTTON_ROWS; j++)
        {
         //--- If the button has been clicked, it is set a distinctive color
         if(button_states[j][i])
            ObjectSetInteger(0,button_object_names[j][i],OBJPROP_BGCOLOR,clicked_background_color);
         //--- Set the standard color to the unclicked button
         else
            ObjectSetInteger(0,button_object_names[j][i],OBJPROP_BGCOLOR,background_color);
        }
     }
  }

Bunların hepsinin çalışması için, düğme tıklamalarının işlenmesini OnChartEvent() olay izleme fonksiyonuna eklediğinizden emin olmalısınız:

//--- Tracking left mouse button clicks on a graphical object
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- If the button has been clicked
      if(InitializeButtonStates(sparam))
        {
         //--- Set button colors
         ChangeButtonColorOnClick();
        }
      //--- Refresh the chart
      ChartRedraw();
      return;
     }

Şimdi tıklandığında, düğmenin rengini değişecektir.

Hala dikkat etmemiz gereken birkaç nokta var. OnDeinit() fonksiyonu içinde, alt pencere alanında grafik kaymasını etkinleştirmemiz ve göstergeyi grafikten silerken fare olaylarının izlenmesini devre dışı bırakmamız gerekir. Bu, olay izlemeyi kullanan birkaç program grafik üzerinde aynı anda çalışıyorsa önemli olabilir.

//+------------------------------------------------------------------+
//| Deinitialization                                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(reason==REASON_REMOVE ||  // If the indicator has been deleted from the chart or
      reason==REASON_RECOMPILE) // the program has been recompiled
     {
      //--- Deactivate the timer
      EventKillTimer();
      //--- Delete the objects
      DeleteButtons();
      //--- Enable chart scrolling
      ChartSetInteger(0,CHART_MOUSE_SCROLL,true);
      //--- Disable tracking of mouse events
      ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,false);
      //--- Refresh the chart
      ChartRedraw();
     }
  }

Programın grafik nesnelerini silme fonksiyonları:

//+------------------------------------------------------------------+
//| Deleting all buttons                                             |
//+------------------------------------------------------------------+
void DeleteButtons()
  {
   for(int i=0; i<BUTTON_COLUMNS; i++)
      for(int j=0; j<BUTTON_ROWS; j++)
         DeleteObjectByName(button_object_names[j][i]);
  }
//+------------------------------------------------------------------+
//| Deleting the object by name                                      |
//+------------------------------------------------------------------+
void DeleteObjectByName(string object_name)
  {
//--- If such object exists
   if(ObjectFind(0,object_name)>=0)
     {
      //--- If an error occurred when deleting, print the relevant message
      if(!ObjectDelete(0,object_name))
         Print("Error ("+IntegerToString(GetLastError())+") when deleting the object!");
     }
  }

Ve son olarak, bu programda bir zamanlayıcıya ihtiyacımız olmasının nedeni şudur. Örneğin, grafik üzerinde birkaç program çalışıyorsa ve programların her birinin fare olaylarını izlemesi gerekiyorsa, bunlardan biri grafikten silindiğinde, izleme tüm programlar için OnDeinit() fonksiyonunda devre dışı bırakılacaktır. Bu yüzden, alternatif olarak, fare olaylarının izlenmesinin etkinleştirilip etkinleştirilmediğini görmek için her saniye kontrol gerçekleştirebilirsiniz:

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//--- Check whether tracking of mouse events is enabled
   CheckChartEventMouseMove();

  }

CheckChartEventMouseMove() fonksiyon kodu aşağıda verilmiştir.

Bazen, bu kontrolü CHARTEVENT_CHART_CHANGE tanımlayıcı ile bir olay için yapmak gayet yeterli olabilir.

Aşağıda, elde ettiğimiz sonucu gösteren videoyu görebilirsiniz:

 

Sonuç

Konu genel itibarıyla bu şekilde. TestButtons.mq5 göstergesi makaleye eklenmiştir ve buradan indirilebilir. Daha fazla geliştirme ile bu örnek ilginç bir ana menüye dönüşebilir. Örneğin, kullanıcı belirli bir düğmeye tıklayarak ilgili bilgi parçasına atlayabilir. Düğme sayısı, gerekirse, artırılabilir.

MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/750

Ekli dosyalar |
testbuttons.mq5 (20.47 KB)
MQL5 Tarif Defteri Gösterge Alt Pencere Kontrolleri - Kaydırma Çubuğu MQL5 Tarif Defteri Gösterge Alt Pencere Kontrolleri - Kaydırma Çubuğu
Çeşitli kontrolleri keşfetmeye devam edelim ve bu sefer dikkatimizi kaydırma çubuğuna çevirelim. Tıpkı "MQL5 Tarif Defteri: Gösterge Alt Pencere Kontrolleri - Düğmeler" başlıklı önceki makaledeki gibi, tüm işlemler gösterge alt penceresinde gerçekleştirilecektir. OnChartEvent() fonksiyonundaki olaylar ile çalışmanın ayrıntılı bir açıklamasını sağladığından, yukarıda bahsedilen makaleyi okumak için biraz zaman ayırın, ancak bu noktaya bu makalede yalnızca üstünkörü değinilecektir. Açıklayıcı olması açısından, bu sefer MQL5 kaynakları kullanılarak elde edilebilen tüm finansal enstrüman özelliklerinin geniş bir listesi için dikey bir kaydırma çubuğu oluşturacağız.
MQL5 Tarif Defteri Birkaç Zaman Aralığını Tek bir Pencerede Görüntüleme MQL5 Tarif Defteri Birkaç Zaman Aralığını Tek bir Pencerede Görüntüleme
Analiz için MetaTrader 5'te kullanılabilir 21 zaman aralığı vardır. Mevcut grafiğe yerleştirebileceğiniz özel grafik nesnelerinden yararlanabilir ve sembolü, zaman aralığını ve diğer bazı özellikleri tam buradan ayarlayabilirsiniz. Bu makale, bu grafik nesnelerine dair ayrıntılı bilgi sağlayacaktır: bir alt pencerede aynı anda birçok grafik nesnesi ayarlamamıza olanak sağlayacak kontrollere (düğmelere) sahip bir gösterge oluşturacağız. Ayrıca, grafik nesneleri alt pencereye tam olarak sığar ve ana grafik veya terminal penceresi yeniden boyutlandırıldığında otomatik olarak ayarlanır.
MQL5 Tarif Defteri MQL5'te Çok Sembollü Volatilite Göstergesi Geliştirme MQL5 Tarif Defteri MQL5'te Çok Sembollü Volatilite Göstergesi Geliştirme
Bu makalede, çok sembollü bir volatilite göstergesinin geliştirilmesini ele alacağız. Çok sembollü göstergelerin geliştirilmesi, acemi MQL5 geliştiricileri için bazı zorluklar ortaya çıkabilir, bu makale de bunun açıklığa kavuşturulmasına yardımcı olur. Çok sembollü bir göstergenin geliştirilmesi sırasında ortaya çıkan önemli sorunlar, diğer sembollerin verilerinin mevcut sembole göre senkronize edilmesi, bazı gösterge verilerinin olmaması ve belirli bir zaman aralığının "true" çubuklarının başlangıcının tanımlanması ile ilgilidir. Bu konuların tamamı makalede yakından ele alınacaktır.
MQL5 Tarif Defteri MetaTrader 5 Alım Satım Olayları için Sesli Bildirimler MQL5 Tarif Defteri MetaTrader 5 Alım Satım Olayları için Sesli Bildirimler
Bu makalede, Uzman Danışmanın dosyasına ses dosyaları eklenmesi ve böylece alım satım olaylarına sesli bildirimler eklenmesi gibi konuları ele alacağız. Dosyaların eklenmesi, ses dosyalarının Uzman Danışman içine yerleştirileceği anlamına gelir. Bu nedenle, Uzman Danışmanın derlenmiş sürümünü (*.ex5) başka bir kullanıcıya sağlarken, ses dosyalarını da sağlamanız ve nereye kaydedilmeleri gerektiğini açıklamanız gerekmez.