English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
CChartObject sınıfına dayalı yeni GUI pencere öğelerinin tasarlanması ve uygulanması

CChartObject sınıfına dayalı yeni GUI pencere öğelerinin tasarlanması ve uygulanması

MetaTrader 5Göstergeler | 16 Aralık 2021, 14:26
54 0
investeo
investeo

Giriş

GUI arayüzlü yarı otomatik Uzman Danışman (EA) üzerine önceki makaleyi yazdıktan sonra arayüzün daha karmaşık göstergeler ve Uzman Danışman (EA) için bazı yeni işlevlerle geliştirilmesinin istendiği ortaya çıktı. MQL5 Standart Kitaplık sınıfları ile tanıştıktan sonra yeni pencere öğelerini uyguladım.

Bu makalede, GUI nesneleri için MQL5 Standart Kitaplık sınıflarını kullanmaya yönelik bir işlemi ve CChartObjectEdit sınıfından türetilen yeni sınıfların nasıl uygulanacağını açıklayacağım: CChartObjectProgressBar, CChartObjectSpinner ve CChartEditTable. CChartEditTable sınıfı, dinamik, iki boyutlu bir nesne dizisi kullanır, bu MQL5’te dinamik 2D bir nesne dizisinin nasıl uygulanacağına dair bir çalışma örneğidir.

 

1. CChartObject ve bunun soyundan gelenler

Standart MQL5 kitaplık sınıfı kullanmıyorsak grafikte herhangi bir nesne oluşturmak ve korumak için Nesne Fonksiyonlarını kullanmalıyız.

Nesneler ObjectCreate() fonksiyonu ile oluşturulur ve nesnenin türü bir ENUM_OBJECT değeri olarak ObjectCreate() fonksiyonuna geçirilir. Grafikteki tüm nesneler kendi özelliklerine sahiptir, bu Tamsayı, Çift veya Dizgi tipi olabilir. Tüm özellikler özel fonksiyonlar yoluyla ayarlanır ve alınır: ObjectGetInteger(), ObjectSetInteger(), ObjectGetDouble(), ObjectSetDouble(), ObjectGetString(), ObjectSetString(). Ayrıca belirli herhangi bir grafikte nesneleri silmek, taşımak ve silmek için fonksiyon vardır. 

MQL5’teki OOP paradigması nedeniyle, çeşitli grafik nesnelerinin işlenmesi CChartObject sınıfı ve bunun soyundan gelenler kullanılarak yapılabilir.

CChartObject sınıfı, bir grafik üzerine koyulabilen herhangi bir grafik nesnesi için temel bir sınıftır. Lütfen aşağıdaki CChartObject nesnesi için temel kalıtım diyagramını gözlemleyin:

 

CChartObject sınıfı için kalıtım diyagramı 

Şekil 1. CChartObject sınıfı için kalıtım diyagramı


Gördüğümüz gibi sağ alt köşede küçük bir üçgenle işaretlenmiş birkaç sınıf vardır.

Bunlar, diğer sınıfların üstleri olan sınıflardır.  Temel olarak, aynı soydan gelen sınıflar nesne üzerinde çalışan yeni değişkenler ve yöntemler ekleyerek bir temel sınıf olanaklarını artırır. Bunlar ayrıca, türetilen bir nesneyi oluşturmak ve türünü geri döndürmek için Create() ve Type() yöntemlerinde farklılık gösterebilir.

Bunu örnekle göstereyim: CChartObjectTrend sınıfı, CChartObjectTrendByAngle, CChartObjectChannel, CChartObjectStdDevChannel, CChartObjectRegression ve CChartObjectPitchfork sınıflarının bir üstüdür.

CChartObjectTrendOBJPROP_RAY_RIGHT ve OBJPROP_RAY_LEFT özelliklerine sahip nesneler için bir temel sınıftır ve aşağıdaki gibi tanımlanır:

class CChartObjectTrend : public CChartObject
  {
public:
   //--- methods of access to properties of the object
   bool              RayLeft() const;
   bool              RayLeft(bool new_sel);
   bool              RayRight() const;
   bool              RayRight(bool new_sel);
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,
                                datetime time1,double price1,datetime time2,double price2);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_TREND); }
   //--- methods for working with files
   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
  };

Bunlar, tanımda farklı yöntem türlerini ayırt etmeyi sağlayan yorumlardır.

Nesnenin özelliklerine erişim yöntemleri RayLeft() ve RayRight()’tır. Bunların uygulamaları, CChartObjectTrend nesnesi üzerinde çalışan ObjectGetInteger() ve ObjectSetInteger() yöntemlerini çağırmaktır.

bool CChartObjectTrend::RayLeft(bool new_ray)
  {
//--- checking
   if(m_chart_id==-1) return(false);
//---
   return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_LEFT,new_ray));
  }

Create() yöntemi, grafik üzerinde nesneyi oluşturma ve eklemeden sorumludur.

Bu, parametrelerden biri olarak OBJ_TREND ile ObjectCreate() yöntemini çağırır:

bool CChartObjectTrend::Create(long chart_id,string name,int window,
                                   datetime time1,double price1,datetime time2,double price2)
  {
   bool result=ObjectCreate(chart_id,name,OBJ_TREND,window,time1,price1,time2,price2);
   if(result) result&=Attach(chart_id,name,window,2);
//---
   return(result);
  }

Save() ve Load() yöntemleri, FileWriteInteger() ve FileLoadInteger() fonksiyonlarını kullanarak nesne verilerini bir sabit sürücüye depolar ve yükler:

bool CChartObjectTrend::Save(int file_handle)
  {
   bool result;
//--- checking
   if(file_handle<=0) return(false);
   if(m_chart_id==-1) return(false);
//--- writing
   result=CChartObject::Save(file_handle);
   if(result)
     {
      //--- writing value of the "Ray left" property
      if(FileWriteInteger(file_handle,(int) ObjectGetInteger(m_chart_id,m_name,
                                                        OBJPROP_RAY_LEFT),CHAR_VALUE)!=sizeof(char))
      return(false);
      //--- writing value of the "Ray right" property
      if(FileWriteInteger(file_handle,(int) ObjectGetInteger(m_chart_id,m_name, 
                                                                OBJPROP_RAY_RIGHT),CHAR_VALUE)!=sizeof(char))
       return(false);
     }
//---
   return(result);
  }

bool CChartObjectTrend::Load(int file_handle)
  {
   bool result;
//--- checking
   if(file_handle<=0) return(false);
   if(m_chart_id==-1) return(false);
//--- reading
   result=CChartObject::Load(file_handle);
   if(result)
     {
      //--- reading value of the "Ray left" property
      if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_LEFT,
                                                 FileReadInteger(file_handle,CHAR_VALUE)))return(false);
      //--- reading value of the "Ray right" property
      if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_RIGHT,
                                                 FileReadInteger(file_handle,CHAR_VALUE))) return(false);
     }
//---
   return(result);
  }

Hızlıca CChartObjectTrend’den gelen aynı soydan sınıfların tanımları üzerinden geçelim.

CChartObjectTrendByAngle sınıfı Angle() özellik değiştiriciyi ekler ve OBJ_TRENDBYANGLE nesne tipini geri döndürür:

class CChartObjectTrendByAngle : public CChartObjectTrend
  {
public:
   //--- methods of access to properties of the object
   double            Angle() const;
   bool              Angle(double angle);
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,datetime time1,double price1,
                               datetime time2,double price2);
   //--- method of identifying the object
   virtual int       Type() { return(OBJ_TRENDBYANGLE); }
  };

CChartObjectChannel sınıfı OBJ_CHANNEL nesne tipini geri döndürür ve kanalları işlediği için üç çift fiyat/tarih parametresi Create() yöntemine geçirilir:

class CChartObjectChannel : public CChartObjectTrend
  {
public:
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,datetime time1,double price1,
                               datetime time2,double price2,datetime time3,double price3);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_CHANNEL); }
  };

CChartObjectStdDevChannel sınıfı Deviations() özellik değiştiricisini ve ek sapma parametresini Create() yöntemine ekler:

class CChartObjectStdDevChannel : public CChartObjectTrend
  {
public:
   //--- methods of access to properties of the object
   double            Deviations() const;
   bool              Deviations(double deviation);
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,
                           datetime time1,datetime time2,double deviation);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_STDDEVCHANNEL); }
   //--- methods for working with files
   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
  };

CChartObjectRegression sınıfı regresyon trend çizgisini oluşturur, sadece Create() ve Type() yöntemleri CChartObjectTrend sınıfındakilerden geçersiz kılınır:

class CChartObjectRegression : public CChartObjectTrend
  {
public:
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,datetime time1,datetime time2);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_REGRESSION); }
  };

CChartObjectPitchfork sınıfı dirgen tipini işler, ayrıca sadece Create() ve Type() yöntemleri değiştirilir:

class CChartObjectPitchfork : public CChartObjectTrend
  {
public:
   //--- method of creating the object
   bool              Create(long chart_id,string name,int window,datetime time1,double price1,
                               datetime time2,double price2,datetime time3,double price3);
   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_CHANNEL); }
  };

 Bu hızlı tarama, bazı başka sınıflara dayalı yeni grafik nesnesi sınıfını yazarken uygulanan temel kuralları göstermiştir:

  • nesne oluşturma için Create() yöntemini değiştirme
  • nesne tipini geri döndürmek için Type() yöntemini değiştirme
  • özellik erişim değiştiricileri ekleme 

Tüm kuralların uygulanması gerekmez, sadece yeni erişim değiştiriciler eklenebilir veya sınıfa yeni değişkenler ve/veya nesneler eklenebilir.

Daha fazla ayrıntıya girmeden önce, CChartObject yöntemlerinin grafik nesneleri üzerinde nasıl kullanılacağını açıklayayım.

ObjectSet ve ObjectGet yöntemleri grubunu kullanmak ve nesne özelliklerini kullanmak yerine, CChartObject veya aynı soydan gelen bir nesneyi belirlemek ve istenen özelliklerini değiştiren yöntemleri uygulamak yeterlidir. Bunu daha kolay hale getirmek için sıradan bir etiket örneği veriyorum. 

Yazmak yerine:

void OnStart()
  {
//---
   string label_name="my_OBJ_LABEL_object";
   if(ObjectFind(0,label_name)<0)
     {
      Print("Object ",label_name," not found. Error code = ",GetLastError());
      ObjectCreate(0,label_name,OBJ_LABEL,0,0,0);           
      ObjectSetInteger(0,label_name,OBJPROP_XDISTANCE,200);
      ObjectSetInteger(0,label_name,OBJPROP_YDISTANCE,300);
      ObjectSetInteger(0,label_name,OBJPROP_COLOR,White);
      ObjectSetString(0,label_name,OBJPROP_TEXT,UP);
      ObjectSetString(0,label_name,OBJPROP_FONT,"Wingdings");
      ObjectSetInteger(0,label_name,OBJPROP_FONTSIZE,10);
      ObjectSetDouble(0,label_name,OBJPROP_ANGLE,-45);
      ObjectSetInteger(0,label_name,OBJPROP_SELECTABLE,false);
      ChartRedraw(0);                                      
     }
  }

Bunu OOP paradigmasını kullanarak uygulayabiliriz:

1. CChartObjectLabel nesnesini belirleyin:

CChartObjectLabel label;

2. Nesne üzerinde çalışın: 

int OnInit()
  {
//---
   label.Create(0, label_name, 0, 0);
   label.X_Distance(200);
   label.Y_Distance(300);
   label.Color(White);
   label.Description(UP);
   label.Font("Wingdings");
   label.FontSize(10);
   label.Angle(-45);
   label.Selectable(false);
//---
   return(0);
  }

Görebileceğiniz gibi, temel fark artık bir label_name dizgisi üzerinde çalışmadığımız: 

string label_name="my_OBJ_LABEL_object";

ve parametrelerden biri olarak label_name ile ObjectSetInteger(), ObjectGetInteger(), ObjectSetDouble(), ObjectGetDouble() fonksiyonlarını çağırmamızdır, fakat CChartObjectLabel nesnesini belirliyor ve bunun yöntemlerini kullanıyoruz. Bu sadece hatırlaması daha kolay ve uygulaması mantıklı olmakla kalmaz, aynı zamanda daha hızlı yazılır.

MQL5 kod düzenleyici bize nesne örneğinden sonra nokta (.) koyarken kod tamamlama işlevini sağlar. Belirli bir özelliği ayarlamak veya almak için hangi OBJPROP özelliğinin düzene koyulacağını görmek için MQL5 belgelerini taramaya gerek yoktur.

Önceden açıklanan CChartObjectTrend sınıfına benzer şekilde, bir sol veya sağ ışın almak veya ayarlamak için CChartObjectTrend nesnesini belirlemek ve RayRight() veya RayLeft() yöntemini uygulamak yeterlidir:

CChartObjectTrend trendline;
trendline.RayRight(true); 


2. ProgressBar

Uygulayacağımız ilk pencere öğesi ProgressBar’dır. İlerleme çubukları, 0’dan x yüzdeye kadar çalışma ilerlemesini gösterir.

Daha güçlü hale getirmek için, maksimum değeri 100 ile değil, fakat herhangi bir pozitif tamsayı değeri ile sınırlayalım. İlerleme çubuğuna göre boyutunu değiştirecek bir renkli şeride ihtiyacımız var. Akla ilk gelen şey iki dikdörtgen kullanmaktır, fakat ben başka bir yol seçtim: biri diğerinin içinde olan, farklı arka plan renklerine sahip iki CChartObjectEdit nesnesi kullanmak.

Kodlamayı basitleştirir ve değerini göstermek için ilerleme çubuğunun içerisine koyulabilen metin ekler. Gereksinime bağlı olarak İlerleme çubuğumuzun yatay veya dikey olması güzel olurdu.


2.1. ProgressBar uygulaması

CChartObjectProgress sınıfı CChartObjectEdit sınıfından türetilir.

Değeri tutmak için dahili özel değişkenler ve değer üzerinde kısıtlamalar ekledim: m_value, m_min, m_max.

İlerleme çubuğunun yönü, tamsayı değeri olarak ayarlanır ve m_direction değişkeni ile tutulur. Renk, m_color değişkeni ile tutulur. Herhangi bir şekilde amacımız için tanınan hiçbir değer olmadığından Type() yöntemi OBJ_EDIT değerini geri döndürür. Sınıf tanımı içinde CChartObjectEdit m_bar fark edilebilir - bu, m_value değişkenine bağlı olarak boyutunu değiştiren iç çubuktur. Ek değişkenler m_name ve m_chart dahili olarak m_bar değişkeni için değerleri tutar.

class CChartObjectProgressBar : public CChartObjectEdit
  {
private:
   int               m_value;
   int               m_min;
   int               m_max;
   int               m_direction;
   color             m_color;
   CChartObjectEdit  m_bar;
   string            m_name;
   long              m_chart_id;

public:
   int               GetValue();
   int               GetMin();
   int               GetMax();

   void              SetValue(int val);
   void              SetMin(int val);
   void              SetMax(int val);

   void              SetColor(color bgcol,color fgcol);
   bool              Create(long chart_id,string name,int window,int X,int Y,
                           int sizeX,int sizeY,int direction);

   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_EDIT); }
};

Create() yöntemi ProgressBar nesnesini oluşturur ve bunu grafiğe ekler.

Y değişkeninin dikey çubuğun çekilmesi durumunda sizeY değişkeninden çıkarıldığını fark edebilirsiniz, bunun nedeni normalde CChartObjectEdit’in üstten aşağıya doğru çizilmesidir ve ben alttan yukarıya doğru iç dikdörtgeni çizmek istedim:

bool CChartObjectProgressBar::Create(long chart_id,string name,int window,int X,int Y,
                                          int sizeX,int sizeY,int direction=0)
  {
   bool result=ObjectCreate(chart_id,name,(ENUM_OBJECT)Type(),window,0,0,0);

   m_name=name;
   m_chart_id=chart_id;
   m_direction=direction;

   if(direction!=0)
     {
      Y=Y-sizeY;
     }

   ObjectSetInteger(chart_id,name,OBJPROP_BGCOLOR,White);
   ObjectSetInteger(chart_id,name,OBJPROP_COLOR,White);
   ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false);
   ObjectSetInteger(chart_id,name,OBJPROP_READONLY,true);

   result&=m_bar.Create(chart_id,name+"m_bar",window,X,Y,sizeX,sizeY);
   m_bar.Color(White);
   m_bar.ReadOnly(true);
   m_bar.Selectable(false);

//---
   if(result) result&=Attach(chart_id,name,window,1);
   result&=X_Distance(X);
   result&=Y_Distance(Y);
   result&=X_Size(sizeX);
   result&=Y_Size(sizeY);
//---
   return(result);
  }

SetColor() yöntemi, her iki dikdörtgende arka plan ve ön plan renklerini ayarlar:

void CChartObjectProgressBar::SetColor(color bgCol,color fgCol=White)
  {
   m_color=bgCol;
   m_bar.BackColor(m_color);
   m_bar.Color(fgCol);
  }

SetValue() yöntemi, hem m_val değerini ayarlamaktan hem de iç dikdörtgen nesne boyutunu yeniden hesaplamaktan sorumludur.

Boyut yatay ve dikey çubuklar için farklı şekilde hesaplanır:

void CChartObjectProgressBar::SetValue(int val)
  {
   if(m_direction==0) // horizontal ProgressBar
     {
      double sizex=(double)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XSIZE,0);

      double stepSize=sizex/(m_max-m_min);

      m_value=val;
      m_bar.Create(m_bar.ChartId(),m_bar.Name(),m_bar.Window(),
                   m_bar.X_Distance(),m_bar.Y_Distance(),(int)MathFloor(stepSize*m_value),m_bar.Y_Size());
        } else {
      double sizey=(double)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YSIZE,0);

      double stepSize=sizey/(m_max-m_min);
      m_value=val;
      m_bar.Create(m_bar.ChartId(),m_bar.Name(),m_bar.Window(),
                   m_bar.X_Distance(),(int)(this.Y_Distance()+sizey-MathFloor(stepSize*m_value)),
                   m_bar.X_Size(),(int)MathFloor(stepSize*m_value));

     }

   m_bar.Description(IntegerToString(m_value));
  }


2.2. ProgressBar Demo

Halihazırda CChartObjectProgressBar sınıfını uyguladığımız için bunu eylem halinde görme zamanı.

Grafik üzerine yeni bir ilerleme çubuğu yerleştirmek için CChartObjectProgressBar nesnesini belirlemek ve Create() ve uygun özellik yöntemlerini kullanmak yeterlidir:

progressBar.Create(0, "progressBar1", 0, 10, 10, 200, 40);
progressBar.SetColor(YellowGreen);
progressBar.SetMin(0);
progressBar.SetMax(100);
progressBar.SetValue(0);

Grafik üzerine altı farklı ilerleme çubuğu koyan ve ekranda herhangi bir nesneye tıklandıktan sonra bunların değerini değiştiren demo bir Uzman Danışman (EA) yazdım.

Bu ve diğer demolar için tam kaynak kodu eklerdedir, lütfen aşağıdaki sunuma bakın: 

 


3. Değer Değiştirici

Değer değiştirici pencere öğesi, bir alan ve iki düğme içeren bir pencere öğesidir. Düğmelerden birine tıklayarak düzenleme alanında bir değeri artırmak veya azaltmak için kullanılır.

Nesneyi tasarlarken sadece tamsayı değerler üzerinde çalışmak istemedim, bu nedenle Değer değiştirici çift tipte çalışmak üzere tasarlandı. Değer değiştirici ayrıca mevcut değeri artırma veya azaltma değeri olan adım boyutunu tanımlayabilir. Ayrıca, aşılamayan minimum ve maksimum değere sahip olmalıdır.


3.1. Değer değiştiriciyi uygulama

MQL5’te CChartObjectSpinner sınıfı olarak birleştirilebilen CChartObjectEdit ve CChartObjectButton sınıflarına sahibiz. CChartObjectSpinner, CChartObjectEdit mirasçısıdır ve iki özel eleman CChartObjectButton nesnesi içerir.

m_min ve m_max eleman değişkenlerinde depolanan minimum ve maksimum m_value için kısıtlamalar vardır ve m_precision değişkeni n. hane değerine kadar hesaplama hassasiyetini depolar. Gerekli yöntemler değere erişim, artırma ve azaltma adım boyutunu ayarlamaya ve değeri ayarlamaya yöneliktir.

class CChartObjectSpinner: public CChartObjectEdit
  {

private:
   double            m_value;
   double            m_stepSize;
   double            m_min;
   double            m_max;
   int               m_precision;
   string            m_name;
   long              m_chart_id;
   CChartObjectButton m_up,m_down;

public:
   double            GetValue();
   double            GetMin();
   double            GetMax();

   void              SetValue(double val);
   void              SetMin(double val);
   void              SetMax(double val);

   double            Inc();
   double            Dec();

   bool              Create(long chart_id,string name,int window,int X,int Y,
                               int sizeX,int sizeY,double val,double stepSize,int precision);

   //--- method of identifying the object
   virtual int       Type() const { return(OBJ_EDIT); }
   
  };

Create() yöntemi yeni CChartObjectSpinner oluşturur ve bunu grafiğe ekler.

CChartObjectEdit’in sağ tarafında oluşturulan, her biri CChartObjectEdit yüksekliğinin yarım yüksekliğine sahip iki CChartObjectButtons vardır.

Artırma düğmesi ‘+’ işaretine ve azaltma düğmesi ‘-’ işaretine sahiptir.

bool CChartObjectSpinner::Create(long chart_id,string name,int window,int X,int Y,
                                     int sizeX,int sizeY,double val=0.0,double stepSize=1.0,int precision=8)
  {
   bool result=ObjectCreate(chart_id,name,(ENUM_OBJECT)Type(),window,0,0,0);

   m_name=name;
   m_chart_id=chart_id;
   m_value=val;
   m_stepSize=stepSize;
   m_precision=precision;

   ObjectSetInteger(chart_id,name,OBJPROP_BGCOLOR,White);
   ObjectSetInteger(chart_id,name,OBJPROP_COLOR,Black);
   ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false);
   ObjectSetInteger(chart_id,name,OBJPROP_READONLY,true);

   result&=m_up.Create(chart_id, name+"_up", window, X+sizeX, Y, 15, sizeY/2);
   result&=m_down.Create(chart_id, name+"_down", window, X+sizeX, Y+sizeY/2, 15, sizeY/2);
   m_up.Description("+");
   m_down.Description("-");
   ObjectSetString(chart_id,name,OBJPROP_TEXT,0,(DoubleToString(m_value,precision)));

//---
   if(result) result&=Attach(chart_id,name,window,1);
   result&=X_Distance(X);
   result&=Y_Distance(Y);
   result&=X_Size(sizeX);
   result&=Y_Size(sizeY);
//---
   return(result);
  }

SetValue() yöntemi, <m_min, m_max> aralığında olması koşuluyla özel m_value değişkenini çift değere ayarlar.

void CChartObjectSpinner::SetValue(double val)
  {
   if(val>=m_min && val<=m_max) m_value=val;
   this.Description(DoubleToString(m_value));
  }

Inc() yöntemi değeri m_max değerinden fazla olmamak kaydıyla belirli adım boyutunda artırır.

Çift değerleri verilen hassasiyetle karşılaştırmak için NormalizeDouble() fonksiyonunu kullanmak zorunda kaldığıma lütfen dikkat edin.

double CChartObjectSpinner::Inc(void)
  {
   if(NormalizeDouble(m_max-m_value-m_stepSize,m_precision)>0.0) m_value+=m_stepSize;
   else m_value=m_max;
   this.Description(DoubleToString(m_value, m_precision));
   m_up.State(false);
   return m_value;
  }

Dec() yöntemi değeri m_min değerinden az olmamak kaydıyla belirli adım boyutunda azaltır.

double CChartObjectSpinner::Dec(void)
  {
   if(NormalizeDouble(m_value-m_stepSize-m_min,m_precision)>0.0)
      m_value-=m_stepSize; else m_value=m_min;
   this.Description(DoubleToString(m_value,m_precision));
   m_down.State(false);

   return m_value;
  }


3.2. Değer Değiştirici Demo

Değer değiştirici nesnelerini test etme zamanı. Bunları kullanmak için, CChartObjectSpinner nesnesini belirlemek ve Create(), SetMin() ve SetMax() yöntemlerini kullanmak yeterlidir.

   spinner.Create(0, "spinner1", 0, 10, 10, 200, 40, 0.0, 0.4);
   spinner.SetMin(0);
   spinner.SetMax(100);

Üç Değer değiştirici pencere öğesi kullanan ve herhangi bir Değer değiştirici düğmesine tıklandıktan sonra tüm değerleri ekleyen bir demo hazırladım.

Bu, OnChartEvent() fonksiyonunun içinde yapılır;

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- Check the event by pressing a mouse button
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
     
     if (sparam=="spinner1_up") spinner.Inc();
     if (sparam=="spinner1_down") spinner.Dec();
     if (sparam=="spinner2_up") spinner2.Inc();
     if (sparam=="spinner2_down") spinner2.Dec();
     if (sparam=="spinner3_up") spinner3.Inc();
     if (sparam=="spinner3_down") spinner3.Dec();
     
     label.Description(DoubleToString(NormalizeDouble(spinner.GetValue()+spinner2.GetValue()+spinner3.GetValue(),10),10));
   
   ChartRedraw();
     }
  }

 Lütfen ekteki demoya bakın:

 

 

4. CChartObjectEditTable

Çok sayıda çoklu zaman dilimi (MTF) Uzman Danışmanında (EA), her bir zaman dilimi için ayrı şekilde görüntülenen gösterge değerleri vardır.

Bazen her bir zaman dilimi farklı renklerdeki dikdörtgenlerden veya karelerden oluşan 2D tablo formunda görüntülenen farklı gösterge ayarlarına sahiptir. CChartObjectEditTable sınıfını oluşturarak bu tür nesnelerden oluşan evrensel bir 2D tablo tasarladım. Bu sınıf, 2D dinamik nesne dizisi kullandığım için rastgele miktarda satır ve sütunu tutabilir.

Tasarım sırasında her bir hücre için ayrı bir renk tanımlamaya ve ayrıca herhangi bir hücreye farklı metin dizgileri koyma olanağını eklemeye karar verdim. Hücreler eşit boyuta sahiptir, fakat ağırlıklarını ve genişliklerini ve hücreler arasındaki boşluğu tanımlamak istedim.


4.1. CChartObjectEditTable uygulaması

CChartObjectEditTable sınıfı CArrayObj işaretçisini iki boyutlu bir nesne dizisinde tutar ve m_rows ve m_columns eleman değişkenleri tablodaki satırlar ve sütunların sayısını tutar.

Tüm hücre CChartObjectEdit nesnelerinin önekini tablo içinde tutan m_baseName eleman değişkeni vardır. GetColor(), SetColor(), GetText(), SetText() yöntemleri renk ve metin değerlerini istenen herhangi bir hücreye ayarlamaya ve almaya yöneliktir. Delete() yöntemi, Create() yöntemi ile oluşturulan tüm nesneleri siler.

class CChartObjectEditTable
  {

private:
   CArrayObj        *array2D;
   int               m_rows;
   int               m_cols;
   string            m_baseName;

public:

   bool              Create(long chart_id,string name,int window,int rows,int cols,int startX,int startY,
                                int sizeX,int sizeY,color Bg,int deltaX,int deltaY);
   bool              Delete();
   bool              SetColor(int row,int col,color newColor);
   color             GetColor(int row,int col);
   bool              SetText(int row,int col,string newText);
   string            GetText(int row,int col);


  };

Create() yöntemi, CChartObjectEdit nesnelerinin iki boyutlu dinamik tablosunu oluşturur.

Lütfen MQL5’te 2D nesne dizisinin nasıl oluşturulduğunu gözlemleyin: öncelikle 2D dizisine bir işaretçi belirliyoruz ve ardından diziyi belirli sayıda CArrayObj() nesnesi ile dolduruyoruz, yani dizi içinde diziler oluşturuyoruz. Tüm diziler tablonun sütunları için tutucular olarak görülebilir.

Her bir sütun, her biri görüntülenecek tek bir hücre olan CChartObjectEdit nesnelerini tutan satırlar içerir. 

bool CChartObjectEditTable::Create(long chart_id,string name,int window,int rows=1,int cols=1,
                                       int startX=0,int startY=0,int sizeX=15,int sizeY=15,
                                  color Bg=White,int deltaX=5,int deltaY=5)
  {
   m_rows=rows;
   m_cols=cols;
   m_baseName=name;
   int i=0,j=0;

   array2D=new CArrayObj();
   if (array2D==NULL) return false;
   
   for(j=0; j<m_cols; j++)
     {
      CArrayObj *new_array=new CArrayObj();
      if (array2D==NULL) return false;
   
      array2D.Add(new_array);
      for(i=0; i<m_rows; i++)
        {
         CChartObjectEdit *new_edit=new CChartObjectEdit();

         new_edit.Create(chart_id, name+IntegerToString(i)+":"+IntegerToString(j), window, 
                         startX+j*(sizeX+deltaX), startY+i*(sizeY+deltaY), sizeX, sizeY);
         new_edit.BackColor(Bg);
         new_edit.Color(White);
         new_edit.Selectable(false);
         new_edit.ReadOnly(true);
         new_edit.Description("");
         new_array.Add(new_edit);
        }
     }

   return true;
  }

SetColor() yöntemi, herhangi bir tek hücrenin rengini ayarlar. Başlangıçta, sütun dizisini ve ardından sütun dizisindeki n. elemanı bulur.

Ardından, elemanın renk değeri BackColor() yöntemi uygulanarak değiştirilir.

bool CChartObjectEditTable::SetColor(int row,int col,color newColor)
  {
   CArrayObj *sub_array;
   CChartObjectEdit *element;

   if((row>=0 && row<m_rows) && (col>=0 && col<m_cols))
     {
      if(array2D!=NULL)
        {
         sub_array=array2D.At(col);
         element=(CChartObjectEdit*)sub_array.At(row);
         element.BackColor(newColor);

         return true;
        }
     }

   return false;
  }

GetColor() yöntemi, hücreyi bulmak için SetColor() yöntemi ile aynı algoritmaya sahiptir, fakat belirli herhangi bir hücrenin renk değerini geri döndürür. 

color CChartObjectEditTable::GetColor(int row,int col)
  {
   CArrayObj *sub_array;
   CChartObjectEdit *element;

   if((row>=0 && row<m_rows) && (col>=0 && col<m_cols))
     {
      if(array2D!=NULL)
        {
         sub_array=array2D.At(col);
         element=(CChartObjectEdit*)sub_array.At(row);
         return element.BackColor();
        }
     }

   return NULL;
  }

SetText() yöntemi elemanı bulur ve Description() yöntemini uygulayarak metin değerini ayarlar.

bool CChartObjectEditTable::SetText(int row,int col,string newText)
  {
   CArrayObj *sub_array;
   CChartObjectEdit *element;

   if((row>=0 && row<m_rows) && (col>=0 && col<m_cols))
     {
      if(array2D!=NULL)
        {
         sub_array=array2D.At(col);
         element=(CChartObjectEdit*)sub_array.At(row);
         element.Description(newText);

         return true;
        }
     }

   return false;
  }

Delete() yöntemi, Create() yöntemi ile oluşturulan tüm nesneleri siler.

Başlangıçta, tüm sütun dizilerini siler ve ardından bellekten array2D nesnesini siler.

bool CChartObjectEditTable::Delete(void)
  {
   for(int j=0; j<m_cols; j++)
     {
      CArrayObj *column_array=array2D.At(j);
      column_array.Clear();
      delete column_array;
     }
   delete array2D;
   return true;
  }


4.2. CChartObjectEditTable Demo

CChartObjectEditTable pencere öğesini kullanmak için, CChartEditTable nesnesini belirlemek ve tablonun kaç tane satır ve sütun içermesi gerektiğini gösteren parametreler ile Create() yöntemini kullanmak gerekir.

Ardından, özellik değiştiriciler kullanılarak herhangi bir hücre üzerinde renk ve metin basitçe değiştirilebilir.

table.Create(0,"t",0,1,10,10,10,15,15,Yellow);
table.SetColor(2,2,Red);
table.SetText(2,2,"2");

Lütfen CChartObjectEditTable nesnesini kullanma olasılıklarını gösteren, tarafımca hazırlanan komut dosyasına bakın.

Komut dosyasının kaynak kodu ektedir.

 


Sonuç

Makalede CChartObject sınıfı üzerinde türetilen yeni grafik pencere öğelerini oluşturmaya yönelik bir işlemi açıkladım ve tanıttım. 

Uygulanan pencere öğelerini kullanmaya yönelik işlem çok basittir ve sadece birkaç kod satırı sürmektedir.

Pencere öğelerini kullanmak için lütfen Uzman Danışmana (EA) veya gösterge koduna ChartObjectsExtControls.mqh dosyasını dahil edin.


MetaQuotes Ltd tarafından İngilizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/en/articles/196

Ekli dosyalar |
progressbarea.mq5 (3.67 KB)
spinnerdemoea.mq5 (2.83 KB)
edittabledemo.mq5 (4.15 KB)
MetaTrader 5’te Paralel Hesaplamalar MetaTrader 5’te Paralel Hesaplamalar
İnsanlık tarihi boyunca zaman büyük bir değer olmuştur ve bunu gereksiz şekilde israf etmemeye çalışıyoruz. Bu makale, bilgisayarınız çok çekirdekli bir işlemciye sahipse Uzman Danışmanınızın (EA) çalışmasını nasıl hızlandıracağınızı açıklayacaktır. Ayrıca, önerilen yöntemin uygulaması MQL5 dışında başka hiçbir dilin bilinmesini gerektirmez.
Önceden tanımlanmış risk ve R/R oranına dayalı etkileşimli yarı otomatik sürükle ve bırak Uzman Danışman (EA) oluşturma Önceden tanımlanmış risk ve R/R oranına dayalı etkileşimli yarı otomatik sürükle ve bırak Uzman Danışman (EA) oluşturma
Bazı yatırımcılar tüm alım-satımları otomatik olarak yürütür ve bazıları birkaç göstergenin çıkışına bağlı olarak otomatik ve manuel alım-satımları karıştırır. Sonraki grubun bir üyesi olarak risk ve ödül seviyelerini doğrudan grafikten dinamik olarak değerlendirmek için etkileşimli bir araca ihtiyacım vardı. Bu makale, önceden tanımlanmış hisse senedi riski ve R/R oranı ile etkileşimli yarı otomatik bir Uzman Danışman (EA) uygulamanın bir yolunu sunacaktır. Uzman Danışman (EA) riski, RR ve lot boyutu parametreleri EA paneli üzerinde çalışma süresi boyunca değiştirilebilir.
Çizim Kanalları - İçeriden ve Dışarıdan Görünüm Çizim Kanalları - İçeriden ve Dışarıdan Görünüm
Kanalların piyasa analizi ve hareketli ortalamalardan sonra alım satım kararları almak için en popüler araç olduğunu söylersem sanırım abartmış olmam. Kanalları ve bileşenlerini kullanan alım satım stratejileri yığınına derinlemesine dalmadan, istemci terminalinin ekranında üç uçdeğer tarafından belirlenen bir kanal çizen bir göstergenin matematiksel temelini ve pratik uygulamasını açıklayacağız.
William Blau'nun MQL5'teki Göstergeleri ve Alım Satım Sistemleri. Bölüm 1: Göstergeler William Blau'nun MQL5'teki Göstergeleri ve Alım Satım Sistemleri. Bölüm 1: Göstergeler
Makalede, William Blau'nun "Momentum, Direction, and Divergence" kitabında açıklanan göstergeler sunulmaktadır. William Blau'nun yaklaşımı, fiyat eğrisindeki dalgalanmaları yaklaşık olarak hızlı ve doğru bir şekilde tahmin etmemize, fiyat hareketleri trendini ve dönüm noktalarını belirlememize ve fiyat gürültüsünü ortadan kaldırmamıza olanak tanır. Aynı zamanda, piyasanın aşırı alım/aşırı satım durumlarını ve bir trendin sona erdiğini ve fiyat hareketinin tersine döndüğünü gösteren sinyalleri de tespit edebiliyoruz.