English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
"Yeni Başlayanlar" için MQL: Nesne Sınıfları Nasıl Tasarlanır ve Oluşturulur?

"Yeni Başlayanlar" için MQL: Nesne Sınıfları Nasıl Tasarlanır ve Oluşturulur?

MetaTrader 5Uzman Danışmanlar | 15 Aralık 2021, 09:35
147 0
Sergey Pavlov
Sergey Pavlov

Nesne Yönelimli Programlamaya Giriş (OOP)

"Yeni Başlayanlar"ın soruları: Prosedürel programlama konusunda yalnızca çok muğlak bir anlayışa sahip olarak, OOP'de uzmanlaşmak ve bunu otomatik alım satım stratejileri yazarken kullanmak mümkün müdür? Veya bu iş sıradan bir kullanıcıyı aşıyor mu?

Genel olarak, bir MQL5 Expert Advisor'ı veya göstergesi yazmak için nesne yönelimli programlama dilini nesne yönelimli programlama prensiplerini takip etmeden kullanmak mümkündür. Geliştirmelerinizde yeni teknolojilerin kullanımı zorunlu değildir. En basit olduğunu düşündüğünüz yolu seçin. Ayrıca, OOP'nin daha fazla uygulanması, oluşturduğunuz alım satım robotlarının karlılığını garanti edemez.

Ancak, yeni (nesne yönelimli) bir yaklaşıma geçiş, dış değişikliklere tepki verecek ve piyasa ile senkronize olacak olan Expert Advisor'larına alım satım stratejilerinin daha karmaşık uyarlanabilir matematiksel modellerini uygulamak için yer açar.

OOP'nin dayandığı teknolojilere bir göz atalım:

  1. Olaylar
  2. Nesne sınıfları

Olaylar, OOP'nin ana temelidir. Programın tüm mantığı, sürekli gelen olayların işlenmesi üzerine kuruludur. Bunlara uygun tepkiler, nesne sınıflarında tanımlanır ve açıklanır. Diğer bir deyişle, bir sınıf nesnesi, olayların akışını yakalayarak ve işleyerek çalışır.

İkinci temel, sırasıyla "üç sütuna" dayanan nesneler sınıfıdır:

  1. Kapsülleme - Bir "kara kutu" prensibine dayalı sınıfın korunması: Nesne olaylara tepki verir, ancak gerçek uygulaması bilinmemektedir. 
  2. Devralma - "Üst" sınıfının tüm özelliklerini ve yöntemlerini korurken mevcut olandan yeni bir sınıf oluşturma imkanı.
  3. Çok Biçimlilik - Devralınan bir yöntemin bir "alt öğe" sınıfındaki uygulamasını değiştirme yeteneği.

Temel kavramlar, en iyi şekilde Expert Advisor kodunda gösterilir.

Olaylar:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()                        // OnInit event processing
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)     // OnDeInit event processing
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()                       // OnTick event processing
  {
  }
//+------------------------------------------------------------------+
//| Expert Timer function                                            |
//+------------------------------------------------------------------+
void OnTimer()                      // OnTimer event processing
  {
  }
//+------------------------------------------------------------------+
//| Expert Chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,     // OnChartEvent event processing
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
  }

Nesne Sınıfı:

class CNew:public CObject
  {
private:
   int               X,Y;
   void              EditXY();
protected:
   bool              on_event;      //events processing flag
public:
   // Class constructor
   void              CNew();
   // OnChart event processing method
   virtual void      OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);
  };

Kapsülleme:

private:
   int               X,Y;
   void              EditXY();

Devralma:

class CNew: public CObject

Çok Biçimlilik:

   // OnChart event processing method
   virtual void      OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);

Bu yöntemin sanal değiştiricisi, OnEvent işleyicisinin geçersiz kılınabileceği anlamına gelir fakat bu durumda yöntemin adı, üst sınıfınınkiyle aynı kalır.

2. Sınıfları Tasarlama

OOP'nin en önemli avantajlarından biri genişletilebilir olmasıdır; bu, mevcut sistemin herhangi bir değişiklik yapmadan yeni bileşenlerle çalışabileceği anlamına gelir. Bu aşamada yeni bileşenler eklenebilir.

MQL5 için MasterWindows sınıflarının görsel tasarım programını oluşturarak tasarım sürecini göz önünde bulundurun.

2.1. Aşama I: Proje Taslağı

Tasarım süreci, bir kağıda kurşun kalemle çizilmiş bir taslak ile başlar. Bu, programlamadaki en zorlu ve heyecan verici anlardan biridir. Yalnızca program ve kullanıcı (arayüz) arasındaki iletişimi değil, aynı zamanda veri işlemenin düzenlenmesini de dikkate almalıyız. Bu işlem bir günden uzun sürebilir. Arayüzle başlamak en iyisidir; zira (bazı durumlarda, örneğimizde olduğu gibi) bir algoritma yapılandırırken tanımlayıcı hale gelebilir.

Oluşturulan programın iletişiminin düzenlenmesi için, Windows uygulama penceresine benzer bir form kullanacağız (Şekil 1'deki taslağa bakınız). Bu, çizgiler içerir ve bu çizgiler sırayla hücrelerden ve grafik nesnelerinin hücrelerinden oluşur. Ve böylece, daha kavramsal tasarım aşamasında, programın yapısını ve nesnelerin sınıflandırılmasını görmeye başlarız.

Şekil 1. Sınıf oluşturucusunun formu (taslak)

Şekil 1. Sınıf oluşturucusunun formu (taslak)

Formda yeterince fazla sayıda satır ve hücre (alan) ile, bunlar yalnızca iki tür grafik nesnesinden oluşturulur: OBJ_EDIT ve OBJ_BUTTON. Böylece programın oluşturduğu görsel görünümü, yapıyı ve temel nesneleri belirlediğimizde, tasarımın taslağının hazır olduğunu ve bir sonraki aşamaya geçme zamanının geldiğini varsayabiliriz.

2.2 Aşama II: Temel Sınıfı Tasarlama

Şimdiye kadar bu tür üç sınıf vardır ve daha sonra daha fazlası eklenebilir (gerekirse):

  • CCell sınıfı hücresi,
  • CRow sınıf satırı; CCell sınıfının hücrelerinden oluşur,
  • CWin sınıf penceresi; CRow sınıfının satırlarından oluşur.

Şimdi doğrudan programlama sınıflarına geçebiliriz, ancak... Henüz çok önemli bir görevi çözmemiz gerekiyor; sınıfların nesneleri arasında veri alışverişi. Bu amaçlar için, MQL5'in dili, olağan değişkenlerin yanı sıra, yeni bir tür - yapı içerir. Elbette tasarımın bu aşamasında bağlantıların tamamını göremiyoruz ve bunları hesaplamak oldukça zor. Bu nedenle, proje ilerledikçe sınıfların ve yapıların açıklamasını kademeli olarak dolduracağız. Ayrıca, OOP'nin prensipleri yalnızca bunu engellemekle kalmaz, aslında tam tersi - teknolojiyi veya programlamayı teşvik eder.

WinCell Yapısı:

struct WinCell
  {
   color             TextColor;     // text color
   color             BGColor;       // background color
   color             BGEditColor;   // background color while editing
   ENUM_BASE_CORNER  Corner;         // anchor corner
   int               H;            // cell height
   int               Corn;         // displacement direction (1;-1)
  };

Dinamik dizilerin dizelerini ve nesnelerini içermeyen yapılar basit yapı olarak adlandırılır. Bu tür yapıların değişkenleri, farklı yapılar olsalar dahi birbirlerine serbestçe kopyalanabilir. Yerleşik yapı tam olarak bu türdendir. Etkililiğini daha sonra değerlendireceğiz.

CCell temel sınıfı:

//+------------------------------------------------------------------+
//| CCell base class                                                 |
//+------------------------------------------------------------------+
class CCell
  {
private:
protected:
   bool              on_event;      // event processing flag
   ENUM_OBJECT       type;           // cell type
public:
   WinCell           Property;     // cell property
   string            name;          // cell name
   //+---------------------------------------------------------------+
   // Class constructor
   void              CCell();
   virtual     // Draw method
   void              Draw(string m_name,
                          int m_xdelta,
                          int m_ydelta,
                          int m_bsize);
   virtual     // Event processing method
   void              OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);
  };

CRow temel sınıfı:

//+------------------------------------------------------------------+
//| CRow base class                                                  |
//+------------------------------------------------------------------+
class CRow
  {
protected:
   bool              on_event;      // event processing flag
public:
   string            name;          // row name
   WinCell           Property;     // row property
   //+---------------------------------------------------------------+
   // Class constructor
   void              CRow();
   virtual     // Draw method
   void              Draw(string m_name,
                          int m_xdelta,
                          int m_ydelta,
                          int m_bsize);
   virtual     // Event processing method
   void              OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);
  };

CWin temel sınıfı:

//+------------------------------------------------------------------+
//| Base CWin class (WINDOW)                                         |
//+------------------------------------------------------------------+
class CWin
  {
private:
   void              SetXY(int m_corner); //Coordinates
protected:
   bool              on_event;   // event processing flag
public:
   string            name;       // window name
   int               w_corner;   // window corner
   int               w_xdelta;   // vertical delta
   int               w_ydelta;   // horizontal detla
   int               w_xpos;     // X coordinate
   int               w_ypos;     // Y coordinate
   int               w_bsize;    // Window width
   int               w_hsize;    // Window height
   int               w_h_corner; // hide mode corner
   WinCell           Property;   // Property
   //---
   CRowType1         STR1;       // CRowType1
   CRowType2         STR2;       // CRowType2
   CRowType3         STR3;       // CRowType3
   CRowType4         STR4;       // CRowType4
   CRowType5         STR5;       // CRowType5
   CRowType6         STR6;       // CRowType6
   //+---------------------------------------------------------------+
   // Class constructor
   void              CWin();
   // Set window properties
   void              SetWin(string m_name,
                            int m_xdelta,
                            int m_ydelta,
                            int m_bsize,
                            int m_corner);
   virtual     // Draw window method
   void              Draw(int &MMint[][3],
                          string &MMstr[][3],
                          int count);
   virtual     // OnEventTick handler
   void              OnEventTick();
   virtual     // OnChart event handler method
   void              OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);
  };

Açıklamalar ve öneriler:

  • Tüm temel sınıflar (bu projedeki) olayları işleme yöntemlerini içerir. Bunlar, zincir boyunca olayları yakalamak ve iletmek için gereklidir. Olayları almak ve göndermek için bir mekanizma olmadan, program (veya modül) etkileşimini kaybeder.
  • Bir temel sınıf geliştirirken, onu minimum sayıda yöntemle oluşturmaya çalışın. Ardından, oluşturulan nesnelerin işlevselliğini artıracak olan "azalan" sınıflarda bu sınıfın çeşitli uzantılarını uygulayın.
  • Başka bir sınıfın dahili verilerine doğrudan başvuru kullanmayın!

2.3. Aşama III: Çalışma Projesi

Bu noktada programın adım adım oluşturulmasına başlıyoruz. Destekleyici çerçeveden başlayarak, işlevsel bileşenlerini artıracağız ve içerikle dolduracağız. Bu esnada işin doğruluğunu izleyeceğiz, optimize edilmiş bir kodla hata ayıklama uygulayacağız ve ortaya çıkan hataları takip edeceğiz.

Burada duralım ve hemen hemen her program için çalışacak olan çerçeve oluşturma teknolojisini göz önünde bulunduralım. Bunun için temel gereklilik hemen çalışır durumda olmasıdır (hatasız derleyin ve yürütme sırasında çalıştırın). Dil tasarımcıları bununla ilgilendiler; çerçeve olarak MQL5 Sihirbazı tarafından oluşturulan Expert Advisor şablonunu kullanmanızı tavsiye ediyorlar.

Örnek olarak, bu şablona ait kendi sürümümüzü ele alalım:

1) Program = Expert Advisor

//+------------------------------------------------------------------+
//|                                                MasterWindows.mq5 |
//|                                                 Copyright DC2008 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "DC2008"
#property link      "http://www.mql5.com"
#property version   "1.00"
//--- include files with classes
#include <ClassMasterWindows.mqh>
//--- Main module declaration
CMasterWindows    MasterWin;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Launch of the main module
   MasterWin.Run();
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Deinitialization of the main module
   MasterWin.Deinit();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- call OnTick event handler of main module
   MasterWin.OnEventTick();
  }
//+------------------------------------------------------------------+
//| Expert Event function                                            |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- call OnChartEvent handler of main module
   MasterWin.OnEvent(id,lparam,dparam,sparam);
  }

Bu, Expert Advisor'ın tamamlanmış kodudur. Proje boyunca herhangi bir ek bir değişiklik yapılmasına gerek yoktur!

2) Ana modül = sınıf

Projenin ana ve yardımcı modüllerinin tamamı buradan geliştirilmeye başlayacak. Bu yaklaşım, karmaşık çok modüllü projelerin programlanmasını ve olası hataların aranmasını kolaylaştırır. Ama bunları bulması çok zordur. Bazen bulunması zor "hataları" aramaktansa yeni bir proje yazmak daha kolay ve hızlıdır.

//+------------------------------------------------------------------+
//|                                           ClassMasterWindows.mqh |
//|                                                 Copyright DC2008 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "DC2008"
#property link      "http://www.mql5.com"
//+------------------------------------------------------------------+
//| Main module: CMasterWindows class                                |
//+------------------------------------------------------------------+
class CMasterWindows
  {
protected:
   bool              on_event;   // event processing flag
public:
   // Class constructor
   void              CMasterWindows();
   // Method of launching the main module (core algorithm)
   void              Run();
   // Deinitialization method
   void              Deinit();
   // OnTick event processing method
   void              OnEventTick();
   // OnChartEvent event processing method
   void              OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);
  };

Aşağıda, sınıfın ana yöntemlerinin kabataslak bir başlangıç açıklaması yer almaktadır.

//+------------------------------------------------------------------+
//| CMasterWindows class constructor                                 |
//+------------------------------------------------------------------+
void CMasterWindows::CMasterWindows()
   {
//--- class members initialization
   on_event=false;   // disable events processing
   }
//+------------------------------------------------------------------+
//| Метод запуска главного модуля (основной алгоритм)                |
//+------------------------------------------------------------------+
void CMasterWindows::Run()
   {
//--- Main functional of the class: runs additional modules
   ObjectsDeleteAll(0,0,-1);
   Comment("MasterWindows for MQL5     © DC2008");
//---
   on_event=true;   // enable events processing
   }
//+------------------------------------------------------------------+
//| Deinitialization method                                          |
//+------------------------------------------------------------------+
void CMasterWindows::Deinit()
   {
//--- 
   ObjectsDeleteAll(0,0,-1);
   Comment("");
   }
//+------------------------------------------------------------------+
//| OnTick() event processing method                                 |
//+------------------------------------------------------------------+
void CMasterWindows::OnEventTick()
   {
   if(on_event) // event processing is enabled
     {
     //---
     }
   }
//+------------------------------------------------------------------+
//| OnChartEvent() event processing method                           |
//+------------------------------------------------------------------+
void CMasterWindows::OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam)
  {
   if(on_event) // event processing is enabled
     {
     //---
     }
  }

3) Temel ve türetilmiş sınıfların kitaplığı

Kitaplık herhangi bir sayıda türetilmiş sınıf içerebilir ve bunları temel sınıfla (varsa) birlikte dahil edilen ayrı dosyalarda gruplandırmak en iyisidir. Bu şekilde, gerekli değişiklikleri ve eklemeleri yapmak ve hataları aramak daha kolay olacaktır.

Artık, programın çerçevesine sahibiz. O halde onu test edelim ve doğru çalışıp çalışmadığını görelim: Derleyin ve çalıştırın. Test başarılı olursa projeyi ek modüllerle doldurmaya başlayabiliriz.

Türetilmiş sınıfların bağlantısıyla ve hücrelerle başlayalım:

Sınıf adı
Resim
 CCellText sınıfı

 CCellEdit sınıfı

 CCellButton sınıfı

 CCellButtonType sınıfı

Tablo 1. Hücre sınıfları kitaplığı

Tek bir türetilmiş CCellButtonType sınıfının oluşturulmasına ayrıntılı bir şekilde göz atalım. Bu sınıf, çeşitli türlerde düğmeler oluşturur.

//+------------------------------------------------------------------+
//| CCellButtonType class                                            |
//+------------------------------------------------------------------+
class CCellButtonType:public CCell
  {
public:
   ///Class constructor
   void              CCellButtonType();
   virtual     ///Draw method
   void              Draw(string m_name,
                          int m_xdelta,
                          int m_ydelta,
                          int m_type);
  };
//+------------------------------------------------------------------+
//| CCellButtonType class constructor                                |
//+------------------------------------------------------------------+
void CCellButtonType::CCellButtonType()
  {
   type=OBJ_BUTTON;
   on_event=false;   //disable events processing
  }
//+------------------------------------------------------------------+
//| CCellButtonType class Draw method                                |
//+------------------------------------------------------------------+
void CCellButtonType::Draw(string m_name,
                           int m_xdelta,
                           int m_ydelta,
                           int m_type)
  {
//--- creating an object with specified name
   if(m_type<=0) m_type=0;
   name=m_name+".Button"+(string)m_type;
   if(ObjectCreate(0,name,type,0,0,0,0,0)==false)
      Print("Function ",__FUNCTION__," error ",GetLastError());
//--- object properties initializartion
   ObjectSetInteger(0,name,OBJPROP_COLOR,Property.TextColor);
   ObjectSetInteger(0,name,OBJPROP_BGCOLOR,Property.BGColor);
   ObjectSetInteger(0,name,OBJPROP_CORNER,Property.Corner);
   ObjectSetInteger(0,name,OBJPROP_XDISTANCE,m_xdelta);
   ObjectSetInteger(0,name,OBJPROP_YDISTANCE,m_ydelta);
   ObjectSetInteger(0,name,OBJPROP_XSIZE,Property.H);
   ObjectSetInteger(0,name,OBJPROP_YSIZE,Property.H);
   ObjectSetInteger(0,name,OBJPROP_SELECTABLE,0);
   if(m_type==0) // Hide button
     {
      ObjectSetString(0,name,OBJPROP_TEXT,CharToString(MIN_WIN));
      ObjectSetString(0,name,OBJPROP_FONT,"Webdings");
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,12);
     }
   if(m_type==1) // Close button
     {
      ObjectSetString(0,name,OBJPROP_TEXT,CharToString(CLOSE_WIN));
      ObjectSetString(0,name,OBJPROP_FONT,"Wingdings 2");
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,8);
     }
   if(m_type==2) // Return button
     {
      ObjectSetString(0,name,OBJPROP_TEXT,CharToString(MAX_WIN));
      ObjectSetString(0,name,OBJPROP_FONT,"Webdings");
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,12);
     }
   if(m_type==3) // Plus button
     {
      ObjectSetString(0,name,OBJPROP_TEXT,"+");
      ObjectSetString(0,name,OBJPROP_FONT,"Arial");
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,10);
     }
   if(m_type==4) // Minus button
     {
      ObjectSetString(0,name,OBJPROP_TEXT,"-");
      ObjectSetString(0,name,OBJPROP_FONT,"Arial");
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,13);
     }
   if(m_type==5) // PageUp button
     {
      ObjectSetString(0,name,OBJPROP_TEXT,CharToString(PAGE_UP));
      ObjectSetString(0,name,OBJPROP_FONT,"Wingdings 3");
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,8);
     }
   if(m_type==6) // PageDown button
     {
      ObjectSetString(0,name,OBJPROP_TEXT,CharToString(PAGE_DOWN));
      ObjectSetString(0,name,OBJPROP_FONT,"Wingdings 3");
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,8);
     }
   if(m_type>6) // empty button
     {
      ObjectSetString(0,name,OBJPROP_TEXT,"");
      ObjectSetString(0,name,OBJPROP_FONT,"Arial");
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,13);
     }
   on_event=true;   //enable events processing
  }
//+------------------------------------------------------------------+

Gerekli açıklamalar:

  • Sınıf oluşturucusuna olayların işlenmesine bir yasak getiriyoruz. Bu, nesneyi çalışmaya hazırlamak ve gelen olayların dikkat dağıtıcı unsurlarını ortadan kaldırmak için gereklidir. Gerekli tüm işlemler tamamlandıktan sonra, bu işlemeye izin vereceğiz; nesne tam olarak çalışmaya başlayacaktır.
  • Çizim yöntemi, dahili verileri kullanır ve harici verileri alır. Bu nedenle, istisnai durumları önlemek için veriler önce uyumluluk açısından test edilmeli ve ancak bundan sonra işlenmelidir. Ancak bu özel durumda bu testi yapmayacağız. Peki neden? Sınıf nesnesinin bir asker olduğunu ve askerlerin komutanlarının planlarını bilmeleri gerekmediğini düşünün. Görevleri, alınan komutları analiz edip bağımsız kararlar almak yerine, komutanlarının emirlerini açık, hızlı ve titiz bir şekilde yerine getirmektir. Bu nedenle, sınıfıyla çalışmaya başlamadan önce tüm harici verilere uyulmalıdır.

Şimdi tüm hücre kitaplığını test etmeliyiz. Bunu yapmak için aşağıdaki kodu ana modüle (geçici olarak, test amaçlı) ekleyecek ve Expert Advisor'ı çalıştıracağız.

//--- include file with classes
#include <ClassUnit.mqh>
//+------------------------------------------------------------------+
//| Main module: CMasterWindows class                                |
//+------------------------------------------------------------------+
class CMasterWindows
  {
protected:
   bool              on_event;   // events processing flag
   WinCell           Property;   // cell property
   CCellText         Text;
   CCellEdit         Edit;
   CCellButton       Button;
   CCellButtonType   ButtonType;
public:
   // Class constructor
   void              CMasterWindows();
   // Main module run method (core algorithm)
   void              Run();
   // Deinitialization method
   void              Deinit();
   // OnTick event processing method
   void              OnEventTick();
   // OnChart event processing method
   void              OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);
  };
//+------------------------------------------------------------------+
//| Main module run method (core algorithm)                          |
//+------------------------------------------------------------------+
void CMasterWindows::Run()
  {
//--- core algorithm - it launches additional modules
   ObjectsDeleteAll(0,0,-1);
   Comment("MasterWindows for MQL5     © DC2008");
//--- Text field
   Text.Draw("Text",50,50,150,"Text field");
//--- Edit field
   Edit.Draw("Edit",205,50,150,"default value",true);
//--- LARGE BUTTON
   Button.Draw("Button",50,80,200,"LARGE BUTTON");
//--- Hide button
   ButtonType.Draw("type0",50,100,0);
//--- Close button
   ButtonType.Draw("type1",70,100,1);
//--- Return  button
   ButtonType.Draw("type2",90,100,2);
//--- Plus button
   ButtonType.Draw("type3",110,100,3);
//--- Minus button
   ButtonType.Draw("type4",130,100,4);
//--- None button
   ButtonType.Draw("type5",150,100,5);
//--- None button
   ButtonType.Draw("type6",170,100,6);
//--- None button
   ButtonType.Draw("type7",190,100,7);
//---
   on_event=true;   // enable events processing
  }

Ve ortaya çıkan sınıflar için olayları aktarmayı unutmamalıyız! Bu yapılmazsa, projeleri işlemek çok zor hatta imkansız hale gelebilir.

//+------------------------------------------------------------------+
//| CMasterWindows class OnChart event processing method             |
//+------------------------------------------------------------------+
void CMasterWindows::OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam)
  {
   if(on_event) // event processing is enabled
     {
      //--- process events for the cell class objects
      Text.OnEvent(id,lparam,dparam,sparam);
      Edit.OnEvent(id,lparam,dparam,sparam);
      Button.OnEvent(id,lparam,dparam,sparam);
      ButtonType.OnEvent(id,lparam,dparam,sparam);
     }
  }

Sonuç olarak, hücre sınıfları kitaplığının nesneleri için mevcut tüm seçenekleri görüyoruz.

Şekil 2. Hücre sınıfları kitaplığı

Şekil 2. Hücre sınıfları kitaplığı

Nesnelerin çalışma verimliliğini ve olaylara tepkilerini test edelim:

  • Düzenleme alanına "varsayılan" yerine farklı değişkenler giriyoruz. Değerler değişirse test başarılı olmuş demektir.
  • Düğmelere basıyoruz; düğmeler tekrar basılana kadar basılı durumda kalır. Ancak bu, tatmin edici bir tepki değildir. Düğmeye bir kez bastıktan sonra otomatik olarak eski haline dönmesi için düğmeye ihtiyacımız var. Ve işte burada OOP'nin gücünü - devralma olasılığını - gösterebiliriz. Programımız bir düzineden fazla düğme kullanıyor olabilir ve her biri için istenen işlevlerin ayrı ayrı eklenmesine gerek yoktur. CCell temel sınıfını değiştirmek yeterlidir ve türetilmiş sınıfların tüm nesneleri mucizevi bir şekilde düzgün çalışmaya başlayacaktır!
//+------------------------------------------------------------------+
//| CCell class OnChart event processing method                      |
//+------------------------------------------------------------------+
void CCell::OnEvent(const int id,
                    const long &lparam,
                    const double &dparam,
                    const string &sparam)
  {
   if(on_event) // event processing is enabled
     {
      //--- button click event
      if(id==CHARTEVENT_OBJECT_CLICK && StringFind(sparam,".Button",0)>0)
        {
         if(ObjectGetInteger(0,sparam,OBJPROP_STATE)==1)
           {
            //--- if button stays pressed
            Sleep(TIME_SLEEP);
            ObjectSetInteger(0,sparam,OBJPROP_STATE,0);
            ChartRedraw();
           }
        }
     }
  }

Böylece sınıf hücrelerinin kitaplığı test edilir ve projeye bağlanır.

Bir sonraki adım, bir satır kitaplığı eklemektir:

 Sınıf adı
Resim
 CRowType1 sınıfı (0)

 CRowType1 sınıfı (1)

 CRowType1 sınıfı (2)

 CRowType1 sınıfı (3)

 CRowType2 sınıfı

 CRowType3 sınıfı

 CRowType4 sınıfı

 CRowType5 sınıfı

 CRowType6 sınıfı

Tablo 2. Satır sınıfları kitaplığı

ve aynı şekilde test ediyoruz. Tüm testlerden sonra bir sonraki aşamaya geçiyoruz.

2.4 Aşama IV: Projeyi Oluşturma

Bu noktada, gerekli tüm modüller oluşturulmuş ve test edilmiştir. Şimdi projeyi oluşturmaya başlayalım. İlk önce bir basamak oluşturuyoruz: Pencerenin şekli Şekil 1'deki gibi olmalıdır, daha sonra onu işlevsellikle dolduruyoruz; yani tüm öğelerin ve modüllerin gelen olaylara programlanmış tepkileri.

Bunu yapmak için hazır bir program çerçevesine ve ana modülün hazırlanmasına sahibiz. O halde bununla başlayalım. Bu, CWin temel sınıfının "alt öğe" sınıflarından biridir; bu nedenle "üst" sınıfın tüm genel yöntemleri ve alanları devralma yoluyla kendisine iletilmiştir. Dolayısıyla, birkaç yöntemi geçersiz kılmamız gerekiyor; yeni bir CMasterWindows sınıfı hazırdır:

//--- include files with classes
#include <ClassWin.mqh>
#include <InitMasterWindows.mqh>
#include <ClassMasterWindowsEXE.mqh>
//+------------------------------------------------------------------+
//| CMasterWindows class                                             |
//+------------------------------------------------------------------+
class CMasterWindows:public CWin
  {
protected:
   CMasterWindowsEXE WinEXE;     // executable module
public:
   void              Run();      // Run method
   void              Deinit();   // Deinitialization method
   virtual                       // OnChart event processing method
   void              OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);
  };
//+------------------------------------------------------------------+
//| CMasterWindows class deinitialization method                     |
//+------------------------------------------------------------------+
void CMasterWindows::Deinit()
  {
//---(delete all objects)
   ObjectsDeleteAll(0,0,-1);
   Comment("");
  }
//+------------------------------------------------------------------+
//| CMasterWindows class Run method                                  |
//+------------------------------------------------------------------+
void CMasterWindows::Run()
  {
   ObjectsDeleteAll(0,0,-1);
   Comment("MasterWindows for MQL5     © DC2008");
//--- creating designer window and launch executable object
   SetWin("CWin1",1,30,250,CORNER_RIGHT_UPPER);
   Draw(Mint,Mstr,21);
   WinEXE.Init("CWinNew",30,18);
   WinEXE.Run();
  }
//+------------------------------------------------------------------+
//| CMasterWindows class event processing method                     |
//+------------------------------------------------------------------+
void CMasterWindows::OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam)
  {
   if(on_event) // event processing is enabled
     {
      //--- Close button click in the main window
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,"CWin1",0)>=0
         && StringFind(sparam,".Button1",0)>0)
        {
         ExpertRemove();
        }
      //--- OnChart event processing for all objects
      STR1.OnEvent(id,lparam,dparam,sparam);
      STR2.OnEvent(id,lparam,dparam,sparam);
      STR3.OnEvent(id,lparam,dparam,sparam);
      STR4.OnEvent(id,lparam,dparam,sparam);
      STR5.OnEvent(id,lparam,dparam,sparam);
      STR6.OnEvent(id,lparam,dparam,sparam);
      WinEXE.OnEvent(id,lparam,dparam,sparam);
     }
  }

Ana modül kendi başına oldukça küçüktür; zira uygulama penceresinin oluşturulmasından başka hiçbir şeyden sorumlu değildir. Ardından kontrolü, en ilginç şeyin (gelen olaylara tepkinin) gerçekleştiği yürütülebilir WinEXE modülüne iletir.

Daha önce nesneler arasında veri alışverişi için basit bir WinCell yapısı oluşturduk; şimdi bu yaklaşımın tüm avantajları netlik kazanıyor. Yapının tüm üyelerini kopyalama işlemi çok rasyonel ve kompakttır:

   STR1.Property = Property;
   STR2.Property = Property;
   STR3.Property = Property;
   STR4.Property = Property;
   STR5.Property = Property;
   STR6.Property = Property;

Bu aşamada, sınıf tasarımının ayrıntılı değerlendirmesini sonlandırabilir ve yeni sınıflar oluşturma sürecini önemli ölçüde hızlandıran yapılandırmaların görsel teknolojisine geçebiliriz.

3. Sınıfların görsel tasarımı

MQL5 için görsel MasterWindows tasarımı modunda bir sınıf çok daha hızlı oluşturulabilir ve daha kolay görselleştirilebilir:


Şekil 3. Görsel tasarım süreci

Şekil 3. Görsel tasarım süreci

Geliştiriciden gerekli olan tek şey, MasterWindows formunu kullanarak pencere formunu çizmek ve ardından yalnızca planlanan olaya tepkiyi belirlemektir. Kodun kendisi otomatik olarak oluşturulur. Hepsi bu kadar! Proje tamamlandı.

Expert Advisor'ın yanı sıra CMasterWindows sınıfının oluşturulan bir kodunun bir örneği Şekil 4'te gösterilmiştir (...\MQL5\Files klasöründe bir dosya oluşturulur):

//****** Project (Expert Advisor): project1.mq5
//+------------------------------------------------------------------+
//|        Code has been generated by MasterWindows Copyright DC2008 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "DC2008"
//--- include files with classes
#include <ClassWin.mqh>
int Mint[][3]=
  {
     {1,0,0},
     {2,100,0},
     {1,100,0},
     {3,100,0},
     {4,100,0},
     {5,100,0},
     {6,100,50},
     {}
  };
string Mstr[][3]=
  {
     {"New window","",""},
     {"NEW1","new1",""},
     {"NEW2","new2",""},
     {"NEW3","new3",""},
     {"NEW4","new4",""},
     {"NEW5","new5",""},
     {"NEW6","new6",""},
     {}
  };
//+------------------------------------------------------------------+
//| CMasterWindows class (main unit)                                 |
//+------------------------------------------------------------------+
class CMasterWindows:public CWin
  {
private:
   long              Y_hide;          // Window shift vertical in hide mode
   long              Y_obj;           // Window shift vertical
   long              H_obj;           // Window shift horizontal
public:
   bool              on_hide;         // HIDE mode flag
   CArrayString      units;           // Main window lines
   void              CMasterWindows() {on_event=false; on_hide=false;}
   void              Run();           // Run method
   void              Hide();          // Hide method
   void              Deinit()         {ObjectsDeleteAll(0,0,-1); Comment("");}
   virtual void      OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam);
  };
//+------------------------------------------------------------------+
//| CMasterWindows class Run method                                  |
//+------------------------------------------------------------------+
void CMasterWindows::Run()
  {
   ObjectsDeleteAll(0,0,-1);
   Comment("Code has been generated by MasterWindows for MQL5 © DC2008");
//--- creating main window and launch executable module
   SetWin("project1.Exp",50,100,250,CORNER_LEFT_UPPER);
   Draw(Mint,Mstr,7);
  }
//+------------------------------------------------------------------+
//| CMasterWindows class Hide method                                 |
//+------------------------------------------------------------------+
void CMasterWindows::Hide()
  {
   Y_obj=w_ydelta;
   H_obj=Property.H;
   Y_hide=ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,0)-Y_obj-H_obj;;
//---
   if(on_hide==false)
     {
      int n_str=units.Total();
      for(int i=0; i<n_str; i++)
        {
         long y_obj=ObjectGetInteger(0,units.At(i),OBJPROP_YDISTANCE);
         ObjectSetInteger(0,units.At(i),OBJPROP_YDISTANCE,(int)y_obj+(int)Y_hide);
         if(StringFind(units.At(i),".Button0",0)>0)
            ObjectSetString(0,units.At(i),OBJPROP_TEXT,CharToString(MAX_WIN));
        }
     }
   else
     {
      int n_str=units.Total();
      for(int i=0; i<n_str; i++)
        {
         long y_obj=ObjectGetInteger(0,units.At(i),OBJPROP_YDISTANCE);
         ObjectSetInteger(0,units.At(i),OBJPROP_YDISTANCE,(int)y_obj-(int)Y_hide);
         if(StringFind(units.At(i),".Button0",0)>0)
            ObjectSetString(0,units.At(i),OBJPROP_TEXT,CharToString(MIN_WIN));
        }
     }
//---
   ChartRedraw();
   on_hide=!on_hide;
  }
//+------------------------------------------------------------------+
//| CMasterWindows class OnChartEvent event processing method        |
//+------------------------------------------------------------------+
void CMasterWindows::OnEvent(const int id,
                             const long &lparam,
                             const double &dparam,
                             const string &sparam)
  {
   if(on_event // event handling is enabled
      && StringFind(sparam,"project1.Exp",0)>=0)
     {
      //--- call of OnChartEvent handlers
      STR1.OnEvent(id,lparam,dparam,sparam);
      STR2.OnEvent(id,lparam,dparam,sparam);
      STR3.OnEvent(id,lparam,dparam,sparam);
      STR4.OnEvent(id,lparam,dparam,sparam);
      STR5.OnEvent(id,lparam,dparam,sparam);
      STR6.OnEvent(id,lparam,dparam,sparam);
      //--- creating graphic object
      if(id==CHARTEVENT_OBJECT_CREATE)
        {
         if(StringFind(sparam,"project1.Exp",0)>=0) units.Add(sparam);
        }
      //--- edit [NEW1] in Edit STR1
      if(id==CHARTEVENT_OBJECT_ENDEDIT
         && StringFind(sparam,".STR1",0)>0)
        {
        //--- event processing code
        }
      //--- edit [NEW3] : Plus button STR3
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR3",0)>0
         && StringFind(sparam,".Button3",0)>0)
        {
        //--- event processing code
        }
      //--- edit [NEW3] : Minus button STR3
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR3",0)>0
         && StringFind(sparam,".Button4",0)>0)
        {
        //--- event processing code
        }
      //--- edit [NEW4] : Plus button STR4
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR4",0)>0
         && StringFind(sparam,".Button3",0)>0)
        {
        //--- event processing code
        }
      //--- edit [NEW4] : Minus button STR4
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR4",0)>0
         && StringFind(sparam,".Button4",0)>0)
        {
        //--- event processing code
        }
      //--- edit [NEW4] : Up button STR4
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR4",0)>0
         && StringFind(sparam,".Button5",0)>0)
        {
        //--- event processing code
        }
      //--- edit [NEW4] : Down button STR4
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR4",0)>0
         && StringFind(sparam,".Button6",0)>0)
        {
        //--- event processing code
        }
      //--- [new5] button click STR5
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR5",0)>0
         && StringFind(sparam,".Button",0)>0)
        {
        //--- event processing code
        }
      //--- [NEW6] button click STR6
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR6",0)>0
         && StringFind(sparam,"(1)",0)>0)
        {
        //--- event processing code
        }
      //--- [new6] button click STR6
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR6",0)>0
         && StringFind(sparam,"(2)",0)>0)
        {
        //--- event processing code
        }
      //--- button click [] STR6
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".STR6",0)>0
         && StringFind(sparam,"(3)",0)>0)
        {
        //--- event processing code
        }
      //--- Close button click in the main window
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".Button1",0)>0)
        {
         ExpertRemove();
        }
      //--- Hide button click in the main window
      if(id==CHARTEVENT_OBJECT_CLICK
         && StringFind(sparam,".Button0",0)>0)
        {
         Hide();
        }
     }
  }
//--- Main module declaration
CMasterWindows MasterWin;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- launch main module
   MasterWin.Run();
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- main module deinitialization
   MasterWin.Deinit();
  }
//+------------------------------------------------------------------+
//| Expert Event function                                            |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- call OnChartEvent event handler
   MasterWin.OnEvent(id,lparam,dparam,sparam);
  }

Bunun başlatılmasıyla, aşağıdaki tasarlanmış pencereyi görürüz:

Şekil 4. Advisor projesi1 - sınıfların görsel tasarımının sonucu

Şekil 4. Expert Advisor projesi1 - sınıfların görsel tasarımının sonucu

Sonuç

  1. Sınıflar aşama aşama tasarlanmalıdır. Görev modüllere ayrılarak her biri için ayrı bir sınıf oluşturulur. Modüller, sırayla, türetilmiş veya temel sınıfların mikro modüllerine ayrılır.
  2. Temel sınıfları yerleşik yöntemlerle aşırı yüklememeye çalışın; bunların sayısı minimum düzeyde tutulmalıdır.
  3. Kod otomatik olarak oluşturulduğu için görsel tasarım ortamının kullanıldığı sınıfların tasarımı bir "yeni başlayan" için dahi çok basittir.

Eklerin konumu:

  • masterwindows.mq5 - ...\MQL5\Experts\
  • klasörde kalan - ...\MQL5\Include\

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

Ekli dosyalar |
Genetik Algoritmalar - Çok Kolay! Genetik Algoritmalar - Çok Kolay!
Bu makalede yazar, kişisel olarak geliştirilmiş bir genetik algoritmanın kullanımıyla gelişimsel hesaplamaları ele almaktadır. Algoritmanın işleyişini örnekler kullanarak göstermekte olup kullanımı için pratik öneriler sunmaktadır.
Yeni Başlayanlar için Çoklu Gösterge Arabelleği ile Bir Gösterge Oluşturma Yeni Başlayanlar için Çoklu Gösterge Arabelleği ile Bir Gösterge Oluşturma
Karmaşık kodlar bir dizi basit koddan meydana gelir. Bu kodlar hakkında bilgi sahibiyseniz, bu, o kadar karmaşık görünmez. Bu makalede, çoklu gösterge arabelleği ile bir göstergenin nasıl oluşturulacağını ele alacağız. Örnek olarak Aroon göstergesi ayrıntılı olarak analiz edilmiş ve kodun iki farklı sürümü sunulmuştur.
Farklı Kıtalardaki Saat Dilimi Farklılıklarına Dayalı Bir Alım Satım Stratejisi Örneği Farklı Kıtalardaki Saat Dilimi Farklılıklarına Dayalı Bir Alım Satım Stratejisi Örneği
İnternette gezinirken, size çeşitli önerilerde bulunacak birçok strateji bulmak kolaydır. İç yüzünü bilen bir kişinin yaklaşımını ele alalım ve farklı kıtalardaki saat dilimlerindeki farklılıklara dayalı olarak strateji oluşturma sürecini inceleyelim.
MetaTrader 5 ve MATLAB Etkileşimi MetaTrader 5 ve MATLAB Etkileşimi
Bu makale MetaTrader 5 ve MatLab matematiksel paketi arasındaki etkileşime ilişkin ayrıntıları içermektedir. Ayrıca MatLab masaüstü ile etkileşimde bulunmak için evrensel bir kitaplık geliştirme süreci olan veri dönüştürme mekanizması gösterilmektedir. Bunun yanı sıra MatLab ortamı tarafından oluşturulan DLL kullanımını da kapsamaktadır. Bu makale, C++ ve MQL5 hakkında bilgi sahibi olan deneyimli okuyuculara yöneliktir.