MQLで書かれたUIのギャラリー - ページ 77

 
Doerk Hilger #:
UIはまだ100%純粋なMQLです。
すべてベクターベースで、完全にスケーラブルで、どんなディスプレイにも調整可能です。 すべてのビジュアル表示は、サブスクリプション設定とイベント優先順位に基づいて、すべてのMQLイベントを処理し、オブジェクトに分配するコアクラス内で非同期に動作します。


非常に興味深いスレッドを盗んでいないことを願っていますし、もし盗んでいたらピーターに許してください。もしそうなら、それはOOPとして正しいのでしょうか?それともイベント・ドリブン・プログラミングとして受け入れられるのでしょうか?もしそうなら、このスレッドをハイジャックしないよう、できるだけ短くまとめましょう。

 
Amir Yacoby #:

非常に興味深いスレッドを盗んでいないことを願っていますし、もし盗んでいたらピーターに許してください。もしそうなら、それはOOPとして正しいのでしょうか?それともイベント駆動型プログラミングとして受け入れられるのでしょうか?もしそうなら、このスレッドをハイジャックしないよう、できるだけ短くまとめましょう。


簡単な説明:

コアはすべての MetaTrader イベントを受信し、どのオブジェクトもコアにサブスクライブできます。そのため、CObject クラスも再設計/変更する必要があり、どのオブジェクトも "public: virtual void OnEACycle(CCycleParams * cpm)" という関数を持つようにしました。このようなサイクルは、チャート・イベント、init、deinitなどになる。また、すべてのオブジェクトは "public: virtual void OnEATick() "を持つことができる。副次的な効果として、サイクルの終了をサブスクライブすることができる。

さらに、すべてのオブジェクトは子オブジェクトとサブスクライバーを持つことができる。つまり、オブジェクトは、何かがクリックされたときなど、それ自身のイベントをトリガーすることができる。その場合、object.SubEvent(STH_CLICKED, params)を実行すればいい。このようにすれば、オブジェクト自身は、誰がこの情報を必要としているかは気にせず、サブスクライバーに配信されます。サブスクライバーはOnSubEvent(int msg, CSubEventParams * sep)を受け取り、それを使って好きなことができます。

全体として、この方法は、私たちがC#で知っているコーディング方法に似ています。

実装はそれほど超複雑ではありませんが、もちろん、最終的には詳細が課題です。なぜなら、それは、あらゆるシナリオで機能しなければならない将来のすべてのEAやインジケータのコア/ベースだからです。

 
class CEAMain : public CObject
   {
   public: CEAMain()
      {
      m_classname="CEAMain";
      SubscribeToCycle(EA_CYCLE_LOAD);
      SubscribeToCycle(EA_CYCLE_PARAMS);   
      SubscribeToCycle(EA_CYCLE_INIT);   
      SubscribeToCycle(EA_CYCLE_ACTIVATE);
      SubscribeToCycle(EA_CYCLE_TICK);
      SubscribeToCycle(EA_CYCLE_DEINIT);
      SubscribeToCycle(EA_CYCLE_UNLOAD);
      }
      //+------------------------------------------------------------------+
      //| Cycles handler                                                   |
      //+------------------------------------------------------------------+
      public: virtual void OnEACycle(CEACycleParams * cpm)
         {
         switch (cpm.Cycle)
            {
            case EA_CYCLE_LOAD:        cpm.CycleResult(OnEALoad(PTR(cpm.Init))); break;
            case EA_CYCLE_PARAMS:      cpm.CycleResult(OnEAParams()); break;
            case EA_CYCLE_INIT:        cpm.CycleResult(OnEAInit(PTR(cpm.Init))); break;
            case EA_CYCLE_ACTIVATE:    OnEAActivate(); break;
            case EA_CYCLE_DEINIT:      OnEADeinit(PTR(cpm.Deinit)); break;
            case EA_CYCLE_UNLOAD:      OnEAUnload(PTR(cpm.Deinit)); break;
            case EA_CYCLE_BOOKEVENT:   OnEABookEvent(PTR(cpm.BookEvent)); break;
            }
         }
      //+------------------------------------------------------------------+
      //| Cycles override                                                  |
      //+------------------------------------------------------------------+
      protected: virtual bool OnEALoad(CEAInitParams * ipm)                   { return true; }
      protected: virtual bool OnEAParams(void)                                { return true; }
      protected: virtual bool OnEAInit(CEAInitParams * ipm)                   { return true; } 
      protected: virtual void OnEAActivate(void)                              {}
      protected: virtual void OnEADeinit(CEADeinitParams * dpm)               {}
      protected: virtual void OnEAUnload(CEADeinitParams * dpm)               {}
      protected: virtual void OnEAChartEvent(CEAChartEventParams * cep)       {}
      protected: virtual void OnEABookEvent(CEABookEventParams * cpm)         {}
         
   };
そして、最終的なEAは次のようになります:

class CMain : public CEAMain
   {
      public: CMain()
         {
         m_classname="MainEA";
         }
      public: ~CMain()
         {
         }         

      //+------------------------------------------------------------------+
      //| Load                                                             |
      //+------------------------------------------------------------------+
      protected: virtual bool OnEALoad(CEAInitParams * ipm)
         {
         Print("Welcome :)");
         return true;
         }
      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      protected: virtual bool OnEAInit(CEAInitParams * ipm)
         { 
         if (ipm.IsFirstInit) return true;
         //--- Account changed init
         if (ipm.IsAccountChanged)
            {
            }
         //--- Symbol change init
         else if (ipm.IsSymbolChanged)    
            {
            }
         return true;
        }
        
      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      protected: virtual void OnEADeinit(CEADeinitParams * dpm)
        {
        }
      protected: virtual void OnEAUnload(CEADeinitParams * dpm)
         {
         DeInit();
         Print("Bye.");
         }  
      ...
      ...
};

// Create the main EA object on a global scope. 
CMain __MainEA;
 
もちろん、Load/Unload/Activateなどはカスタムだが、このイベントコアがあるため、ない場合よりもはるかに柔軟性があり、あらゆることをコントロールできる
時間があれば、記事を書いてソースを提供したい。秘密でも魔法でもありません。
 
Doerk Hilger コントロールできる。
あなたが作成したGUIを見ました。とても気に入っているよ。自分で書いたのですか、それともMQLライブラリを使ったのですか?
 
Реter Konow #:
あなたが作ったGUIを見ました。とても気に入ったよ。自分で書いたのですか、それともMQLのライブラリを使ったのですか?

ありがとう。
いいえ、ライブラリは使っていません。ゼロから自分でデザインしました。実はCCanvasだけはオリジナルのものを使っていて、他には何も使っていません。

 
Doerk Hilger #:

ありがとう。
いや、ライブラリはないよ。ゼロから自分で開発しました。実は、CCanvasだけはオリジナルのものを流用しています。

このようなものを作るのは簡単ではありません。)

私の知る限り、標準のCcanvasクラスには色のグラデーションを描画する機能はありません。
 
Реter Konow #:
こういうものを作るのは簡単じゃない。)

私の知る限り、標準のCcanvasクラスには色のグラデーションを描画する機能はありません。

ライト・エフェクトのこと?そうですね、光を追加しました :D 説明したように、CCanvasも基本的な部分とその構造だけが適応されており、細部は適応されていません。

//+------------------------------------------------------------------+
//| Macro to generate color                                          |
//+------------------------------------------------------------------+
#define XRGB(r,g,b)    (0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b))
#define ARGB(a,r,g,b)  ((uchar(a)<<24)|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b))
#define TRGB(a,rgb)    ((uchar(a)<<24)|(rgb))
#define GETRGB(clr)    ((clr)&0xFFFFFF)
#define GETRGBA(clr)   uchar((clr)>>24)
#define GETRGBR(clr)   uchar((clr)>>16)
#define GETRGBG(clr)   uchar((clr)>>8)
#define GETRGBB(clr)   uchar(clr)
#define COLOR2RGB(clr) (0xFF000000|(uchar(clr)<<16)|(uchar((clr)>>8)<<8)|uchar((clr)>>16))
#define RGB2COLOR(rgb) ((uchar(rgb)<<16)|(uchar((rgb)>>8)<<8)|uchar((rgb)>>16))


//+------------------------------------------------------------------+
//| Add light to rectangular area                                    |
//+------------------------------------------------------------------+
void CCanvasExt::AddLight(int x1, int y1, int x2, int y2, bool updown=true, double intensity=.5, int isoftedge=20, color lightcolor=C'255,255,255')
   {
   if (intensity==0)
      return;
      
   int tmp;
//--- sort vertexes
   if(x2<x1)
     {
      tmp=x1;
      x1 =x2;
      x2 =tmp;
     }
   if(y2<y1)
     {
      tmp=y1;
      y1 =y2;
      y2 =tmp;
     }
//--- out of screen boundaries
   if(x2<0 || y2<0 || x1>=m_width || y1>=m_height)
      return;
//--- stay withing screen boundaries
   if(x1<0)
      x1=0;
   if(y1<0)
      y1=0;
   if(x2>=m_width)
      x2=m_width -1;
   if(y2>=m_height)
      y2=m_height-1;


//--- calculate softedge
   isoftedge=MIN(100,isoftedge);
   int softedge=isoftedge>0 ? isoftedge*(y2-y1)/100 : 0;

//--- correct height
   y2-=(y2-y1)/2;
   y2+=(softedge/2);
   y2++;
   y2=MIN(m_height-1,y2);   
   
//--- prepare 
   COLOR_RGBA rgb=_ColorLumaMult(lightcolor,ABS(intensity));
   double r=(int)GETRGBR(rgb);
   double g=(int)GETRGBG(rgb);
   double b=(int)GETRGBB(rgb);  
   
   if (intensity<0)
      {
      r=0-r;
      g=0-g;
      b=0-b;
      }
   uint pixel;     
   int istart;
   int iend;
   int i;

//--- check direction
   if (updown)
      {
   //--- add main light   
      for(;y1<y2-softedge;y1++)
         {
         istart=y1*m_width+x1;
         iend=istart+(x2-x1);
         for (i=istart;i<=iend;i++)
            {
            pixel=m_pixels[i];
            m_pixels[i]=ARGB(GETRGBA(pixel),MIN(GETRGBR(pixel)+r,0xFF),MIN(GETRGBG(pixel)+g,0xFF),MIN(GETRGBB(pixel)+b,0xFF));// m_pixels[i]+=XRGB(r,g,b);
            //m_pixels[i]|=rgb;
            }
         }
      if (softedge==0)
         return;
   
   //-- Add soft edge 
      double decr=r/softedge;
      double decg=g/softedge;
      double decb=b/softedge;
   
   //--- Loop rows separate and adjust color each row   
      for (;y1<=y2;y1++)
         {
         r-=decr; r=MAX(0,r); 
         g-=decg; g=MAX(0,g); 
         b-=decb; b=MAX(0,b); 
         
         istart=y1*m_width+x1;
         iend=istart+(x2-x1);
         for (i=istart;i<=iend;i++)
            {
            pixel=m_pixels[i];
            m_pixels[i]=ARGB(GETRGBA(pixel),MIN(GETRGBR(pixel)+r,0xFF),MIN(GETRGBG(pixel)+g,0xFF),MIN(GETRGBB(pixel)+b,0xFF));// m_pixels[i]+=XRGB(r,g,b);
            }
         }
      }   
  }   
 
Doerk Hilger #: 照明効果のことですか?そうですね、ライトを追加しました :D おっしゃるとおり、CCanvas も基本や構造だけは適応していますが、細部は適応していません。
なるほど、ありがとう。)
 
Реter Konow #:
なるほど、ありがとう。)


追記:updownは実は役に立たないんですね。とにかく、光は上から来るのが普通だ。