Kullanıcı tanımlı tipler

C++ da kullanılanılan typedef sözcüğü kullanıcı tanımlı veri tiplerinin oluşturulmasını sağlar. Bunun için varolan bir veri tipine yeni bir isim verin. Burada yeniş bir veri tipi oluşturulmayacaktır. Bunun yerine varolan tip için yeni bir isim tanımlanacaktır. Kullanıcı tanımlı tipler uygulamalarınızı daha esnek hale getirir: bazen ikame makroları (#define) kullanarak typedef'i değiştirmek yeterlidir. Kullanıcı tanımlı tipler kodun okunaklılığını artırır (çünkü typedef kullanımıyla standart veri tiplerine daha anlaşılır isimler verebilirsiniz). Kullanıcı tanımlı veri tipi oluşturmak için genel format:

   typedef type yeni_isim;

Burada, type kullanılabilir veri tipidir, yeni_isim ise söz konusu tipin yeni ismidir. Yeni isim sadece mevcut isme ek olarak ayarlanır (onun yerini almaz). MQL5 dili, typedef kullanımı ile fonksiyon işaretçileri oluşturabilmenizi sağlar.

Fonksiyon işaretçisi

Fonksiyon işaretçileri genelde şu şekilde tanımlanır

   typedef fonksiyon_sonuç_tipi (*Fonksiyon_isim_tipi)(giriş_parametrelerinin_tipleri);

burada typedef sözcüğünden sonra, fonksiyonun imzası (giriş parametrelerinin sayısı ve tipleri ve fonksiyonun dönüş tipi) ayarlanır. Aşağıda bir fonksiyona işaretçi ayarlanmasını gösteren bir örnek verilmiştir:

//--- int tipli iki giriş parametresi olan bir fonksiyonun işaretçisini bildir
   typedef int (*TFunc)(int,int);
//--- burada TFunc bir tiptir ve fonksiyon değişken işaretçisiyle bildirilebilir
   TFunc func_ptr; // fonksiyon işaretçisi
//--- TFunc tanımına karşılık gelen fonksiyonları bildir
   int sub(int x,int y) { return(x-y); }  // diğerinden bir sayı çıkar
   int add(int x,int y) { return(x+y); }  // iki sayının eklenmesi
   int neg(int x)       { return(~x);  }  // değişken bitlerini tersine çevir
//--- func_ptr değişkeni daha sonra kulanılmak üzere fonksiyonun adresini saklayabilir
   func_ptr=sub;
   Print(func_ptr(10,5));
   func_ptr=add;
   Print(func_ptr(10,5));
   func_ptr=neg;           // hata: neg fonksiyonu int (int,int) tipine sahip değil
   Print(func_ptr(10));    // hata: iki parametre gerekli

Bu örnekte func_ptr değişkeni sub ve add fonksiyonlarını alabilir (int tipli iki girdi değişken TFunc fonksiyon işaretçisinde tanımlanmış). Aksine, neg fonksiyonu işareti farklı olduğu için func_ptr işaretçisine atanamaz.

Kullanıcı arayüzündeki olay modellerinin düzenlenmesi

Kullanıcı arayüzleri oluştururken fonksiyon işaretçileri ile olay işleyicileri oluşturebilirsiniz. Düğmeler oluşturmak ve bunlara basıldığında ilgili olayın işlenmesini sağlayacak fonksiyonları eklemek için CButton bölümünden bir örnek kullanalım. Önce, düğmeye basıldığında çağrılacak TAction fonksiyonunun işaretçisini tanımlayın ve TAction açıklamasına göre üç fonksiyon oluşturun.

//--- özel fonksiyon tipi oluştur
typedef int(*TAction)(string,int);
//+------------------------------------------------------------------+
//|  Dosyayı aç                                                     |
//+------------------------------------------------------------------+
int Open(string name,int id)
  {
   PrintFormat("%s fonksiyonu çağrıldı (isim=%s tanıtıcı=%d)",__FUNCTION__,name,id);
   return(1);
  }
//+------------------------------------------------------------------+
//|  Dosyayı kaydet                                                 |
//+------------------------------------------------------------------+
int Save(string name,int id)
  {
   PrintFormat("%s fonksiyonu çağrıldı (isim=%s tanıtıcı=%d)",__FUNCTION__,name,id);
   return(2);
  }
//+------------------------------------------------------------------+
//|  Dosyayı Kapat                                                   |
//+------------------------------------------------------------------+
int Close(string name,int id)
  {
   PrintFormat("%s fonksiyonu çağrıldı (isim=%s tanıtıcı=%d)",__FUNCTION__,name,id);
   return(3);
  }
 

Sonra, CButton sınıfını kullanarak MyButton sınıfını oluşturun, burada TAction işaretçisini fonksiyona eklemeliyiz.

//+------------------------------------------------------------------+
//| Olay işleme fonksiyonu olan bir düğme sınıfı oluştur             |
//+------------------------------------------------------------------+
class MyButton: public CButton
  {
private:
   TAction           m_action;                    // çizelge olayları işleyicisi
public:
                     MyButton(void){}
                    ~MyButton(void){}
   //--- olay işleme fonksiyonunun işaretçisini ve düğme metnini belirten yapıcı
                     MyButton(string text, TAction act)
     {
      Text(text);
      m_action=act;
     }
   //--- OnEvent() olay işleyicisinden çağrılacak özel fonksiyonu ayarla
   void              SetAction(TAction act){m_action=act;}
   //--- standart çizelge olayları işleyicisi
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) override
     {      
      if(m_action!=NULL && lparam==Id())
        { 
         //--- özel m_action() işleyicisini çağır
         m_action(sparam,(int)lparam);
         return(true);
        }
      else
      //--- CButton ana sınıfından çağrılan işleyicinin sonucunu göster
         return(CButton::OnEvent(id,lparam,dparam,sparam));
     }
  };

CControlsDialog sınıfını CAppDialog sınıfından türeterek oluştur, MyButton tipli düğmeleri kaydetmek için m_buttons dizisini ve AddButton(MyButton &button) ve CreateButtons() yöntemlerini ekle.

//+------------------------------------------------------------------+
//| CControlsDialog sınıfı                                           |
//| Amaç: uygulamanın yönetilmesi için kullanılacak grafik panel  |
//+------------------------------------------------------------------+
class CControlsDialog : public CAppDialog
  {
private:
   CArrayObj         m_buttons;                     // düğme dizisi
public:
                     CControlsDialog(void){};
                    ~CControlsDialog(void){};
   //--- oluştur
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) override;
   //--- düğmeyi ekle
   bool              AddButton(MyButton &button){return(m_buttons.Add(GetPointer(button)));m_buttons.Sort();};
protected:
   //--- düğmeleri oluştur 
   bool              CreateButtons(void);
  };
//+------------------------------------------------------------------+
//| CControlsDialog nesnesini çizelgede oluştur                      |
//+------------------------------------------------------------------+
bool CControlsDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
   if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
   return(CreateButtons());
//---
  }
//+------------------------------------------------------------------+
//| tanımlar                                                         |
//+------------------------------------------------------------------+
//--- girintiler ve boşluklar
#define INDENT_LEFT                         (11)      // sol girinti (çerçeve payıyla birlikte)
#define INDENT_TOP                          (11)      // üst girinti (çerçeve payıyla birlikte)
#define CONTROLS_GAP_X                      (5)       // X koordinatına göre boşluk
#define CONTROLS_GAP_Y                      (5)       // Y koordinatına göre boşluk
//--- düğmeler için
#define BUTTON_WIDTH                        (100)     // X koordinatına göre genişkik
#define BUTTON_HEIGHT                       (20)      // Y koordinatına göre genişlik
//--- gösterge alanı için
#define EDIT_HEIGHT                         (20)      // Y koordinatına göre genişlik
//+------------------------------------------------------------------+
//| Düğmeleri oluşturup ControlsDialog paneline ekle              |
//+------------------------------------------------------------------+
bool CControlsDialog::CreateButtons(void)
  {
//--- düğme koordinatlarını hesapla
   int x1=INDENT_LEFT;
   int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y);
   int x2;
   int y2=y1+BUTTON_HEIGHT;
//--- düğme nesnelerini fonksiyon işaretçilerine ekle
   AddButton(new MyButton("Open",Open));
   AddButton(new MyButton("Save",Save));
   AddButton(new MyButton("Close",Close));
//--- düğmeleri grafiksel olarak oluştur
   for(int i=0;i<m_buttons.Total();i++)
     {
      MyButton *b=(MyButton*)m_buttons.At(i);
      x1=INDENT_LEFT+i*(BUTTON_WIDTH+CONTROLS_GAP_X);
      x2=x1+BUTTON_WIDTH;
      if(!b.Create(m_chart_id,m_name+"bt"+b.Text(),m_subwin,x1,y1,x2,y2))
        {
         PrintFormat("%s %d düğmesi oluşturulamadı",b.Text(),i);
         return(false);
        }
      //--- her düğmeyi CControlsDialog taşıyıcısına ekle
      if(!Add(b))
         return(false);
     }
//--- başarılı
   return(true);
  }

Şimdi, üç düğmeli (Open, Save ve Close) kontrol paneli CControlsDialog ile programı geliştirebiliriz. Bir düğmeye basıldığında, TAction işaretçisi biçimindeki uygun bir fonksiyon çağrılacaktır.

//--- program başlatıldığında otomatik olarak oluşturulması için nesneyi global seviyede bildir
CControlsDialog MyDialog;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- şimdi nesneyi çizelgede oluştur
   if(!MyDialog.Create(0,"Controls",0,40,40,380,344))
      return(INIT_FAILED);
//--- uygulamayı çalıştır
   MyDialog.Run();
//--- uygulama başarıyla çalıştırıldı
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- iletişim kutusunu yok et
   MyDialog.Destroy(reason);
  }
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // olay tanıtıcısı  
                  const long& lparam,   // long tipli olay parametresi
                  const double& dparam, // double tipli olay parametresi
                  const string& sparam) // string tipli olay parametresi
  {
//--- çizelge olayları için gereken işleyiciyi (CAppDialog) ana sınıftan çağır
   MyDialog.ChartEvent(id,lparam,dparam,sparam);
  }

Çalıştırılan uygulamanın görünümü ve düğmelerin tıklanmalarının sonuçları ekran görüntüsünde verilmiştir.

panel_buttons

 

Programın tam kaynak kodu

//+------------------------------------------------------------------+
//|                                                Panel_Buttons.mq5 |
//|                         Copyright 2000-2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
 
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property description "Birkaç CButton düğmesi içeren panel"
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
//+------------------------------------------------------------------+
//| tanımlar                                                         |
//+------------------------------------------------------------------+
//--- girintiler ve boşluklar
#define INDENT_LEFT                         (11)      // sol girinti (çerçeve payıyla birlikte)
#define INDENT_TOP                          (11)      // üst girinti (çerçeve payıyla birlikte)
#define CONTROLS_GAP_X                      (5)       // X koordinatına göre boşluk
#define CONTROLS_GAP_Y                      (5)       // Y koordinatına göre boşluk
//--- düğmeler için
#define BUTTON_WIDTH                        (100)     // X koordinatına göre genişkik
#define BUTTON_HEIGHT                       (20)      // Y koordinatına göre genişlik
//--- gösterge alanı için
#define EDIT_HEIGHT                         (20)      // Y koordinatına göre genişlik
 
//--- özel fonksiyon tipini oluştur
typedef int(*TAction)(string,int);
//+------------------------------------------------------------------+
//|  Dosyayı aç                                                     |
//+------------------------------------------------------------------+
int Open(string name,int id)
  {
   PrintFormat("%s fonksiyonu çağrıldı (isim=%s tanıtıcı=%d)",__FUNCTION__,name,id);
   return(1);
  }
//+------------------------------------------------------------------+
//|  Dosyayı kaydet                                                 |
//+------------------------------------------------------------------+
int Save(string name,int id)
  {
   PrintFormat("%s fonksiyonu çağrıldı (isim=%s tanıtıcı=%d)",__FUNCTION__,name,id);
   return(2);
  }
//+------------------------------------------------------------------+
//|  Dosyayı Kapat                                                   |
//+------------------------------------------------------------------+
int Close(string name,int id)
  {
   PrintFormat("%s fonksiyonu çağrıldı (isim=%s tanıtıcı=%d)",__FUNCTION__,name,id);
   return(3);
  }
//+------------------------------------------------------------------+
//| Olay işleme fonksiyonu olan bir düğme sınıfı oluştur             |
//+------------------------------------------------------------------+
class MyButton: public CButton
  {
private:
   TAction           m_action;                    // çizelge olayları işleyicisi
public:
                     MyButton(void){}
                    ~MyButton(void){}
   //--- olay işleme fonksiyonunun işaretçisini ve düğme metnini belirten yapıcı
                     MyButton(string text,TAction act)
     {
      Text(text);
      m_action=act;
     }
   //--- OnEvent() olay işleyicisinden çağrılacak özel fonksiyonu ayarla
   void              SetAction(TAction act){m_action=act;}
   //--- standart çizelge olayları işleyicisi
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) override
     {
      if(m_action!=NULL && lparam==Id())
        {
         //--- özel işleyiciyi çağır
         m_action(sparam,(int)lparam);
         return(true);
        }
      else
      //--- CButton ana sınıfından çağrılan işleyicinin sonucunu göster
         return(CButton::OnEvent(id,lparam,dparam,sparam));
     }
  };
//+------------------------------------------------------------------+
//| CControlsDialog sınıfı                                           |
//| Amaç: uygulamanın yönetilmesi için kullanılacak grafik panel  |
//+------------------------------------------------------------------+
class CControlsDialog : public CAppDialog
  {
private:
   CArrayObj         m_buttons;                     // düğme dizisi
public:
                     CControlsDialog(void){};
                    ~CControlsDialog(void){};
   //--- oluştur
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) override;
   //--- düğmeyi ekle
   bool              AddButton(MyButton &button){return(m_buttons.Add(GetPointer(button)));m_buttons.Sort();};
protected:
   //--- düğmeleri oluştur 
   bool              CreateButtons(void);
  };
//+------------------------------------------------------------------+
//| CControlsDialog nesnesini çizelgede oluştur                      |
//+------------------------------------------------------------------+
bool CControlsDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
   if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
   return(CreateButtons());
//---
  }
//+------------------------------------------------------------------+
//| Düğmeleri oluşturup ControlsDialog paneline ekle              |
//+------------------------------------------------------------------+
bool CControlsDialog::CreateButtons(void)
  {
//--- düğme koordinatlarını hesapla
   int x1=INDENT_LEFT;
   int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y);
   int x2;
   int y2=y1+BUTTON_HEIGHT;
//--- düğme nesnelerini fonksiyon işaretçilerine ekle
   AddButton(new MyButton("Open",Open));
   AddButton(new MyButton("Save",Save));
   AddButton(new MyButton("Close",Close));
//--- düğmeleri grafiksel olarak oluştur
   for(int i=0;i<m_buttons.Total();i++)
     {
      MyButton *b=(MyButton*)m_buttons.At(i);
      x1=INDENT_LEFT+i*(BUTTON_WIDTH+CONTROLS_GAP_X);
      x2=x1+BUTTON_WIDTH;
      if(!b.Create(m_chart_id,m_name+"bt"+b.Text(),m_subwin,x1,y1,x2,y2))
        {
         PrintFormat("%s %d düğmesi oluşturulamadı",b.Text(),i);
         return(false);
        }
      //--- her düğmeyi CControlsDialog taşıyıcısına ekle
      if(!Add(b))
         return(false);
     }
//--- başarılı
   return(true);
  }
//--- program başlatıldığında otomatik olarak oluşturulması için nesneyi global seviyede bildir
CControlsDialog MyDialog;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- şimdi nesneyi çizelgede oluştur
   if(!MyDialog.Create(0,"Controls",0,40,40,380,344))
      return(INIT_FAILED);
//--- uygulamayı çalıştır
   MyDialog.Run();
//--- uygulama başarıyla çalıştırıldı
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- iletişim kutusunu yok et
   MyDialog.Destroy(reason);
  }
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // olay tanıtıcısı  
                  const long& lparam,   // long tipli olay parametresi
                  const double& dparam, // double tipli olay parametresi
                  const string& sparam) // string tipli olay parametresi
  {
//--- çizelge olayları için gereken işleyiciyi (CAppDialog) ana sınıftan çağır
   MyDialog.ChartEvent(id,lparam,dparam,sparam);
  }

 

Ayrıca bakınız

Değişkenler, Fonksiyonlar