GUIを利用したインジケーターの作り方

サムネ
こんにちは。 fx-on.comエンジニアの岩淵です。 昨日はECBでしたね。 皆さんは勝てたでしょうか? 今日もマニアックなMQL4プログラミングをご紹介いたします。 今日はMT4にデフォルトで入っている、ヘッダーファイル「Dialog.mqh」を活用する例をご紹介します。

仕様

チャート内で自由にドラッグ&ドロップができ、 最小化や閉じることが可能なダイアログを作成する。 ダイアログの中にはボタンを表示する。 完成形はこんな感じ↓ 完成系イメージ図

コーディング

ポイント1

今回はダイアログを作成してその中にボタンを1つ追加したいと思います。 ダイアログを作るには、Controlsフォルダ内のDialog.mqhを読み込みます。 ボタンを作るには同じくControlsフォルダ内のButton.mqhを読み込みます。
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>

ポイント2

Dialog.mqhで作成されているCAppDialogを継承したMyDialogクラスを作成する。 必要なものはほとんどCAppDialog内に書かれているので、 自分で作る処理は殆どありません。 今回はダイアログに表示するCButtonインスタンスの作成と、Createの処理を修正だけを行います。
class MyDialog : public CAppDialog{
   private:
      CButton btn;
   public:
      virtual bool Create();
};

ポイント3

MyDialogクラスのCreate時の処理を修正しています。 大まかな流れは以下の通りです。 1.CAppDialogクラスのCreateを実行してダイアログを作成。 Createの第4~7引数は、チャート左上からの表示開始位置と終了位置をピクセル単位で表しています。 今回は数値を手打ちしていますが、全て変数と数式で表現するようにしておくと修正が楽です。 2.ボタンを作成・調整 Createで作成、FontでフォントをTerminalに指定、Textでボタンに表示する文字を指定しています。 Createの第4~7引数は、CButton単独であればチャート左上からの座標ですが、ダイアログ内に表示する場合にはダイアログの左上からの座標になるので注意して下さい。 余白などの関係によって微妙にズレるので気になる方は調整を行って下さい。 3.ダイアログ内にボタンを追加 Addの引数に追加するオブジェクトを指定してあげる。 途中何らかの処理が失敗した場合にはfalseを、何事も無く全て終了したらtrueを返しています。
bool MyDialog::Create(){
   if(!CAppDialog::Create(0, "MainDialog", 0, 100, 100, 300, 300)){
      return(false);
   }
   
   if(!btn.Create(0, "Button", 0, 20, 60, 180, 140)) return(false);
   if(!btn.Font("Terminal")) return(false);
   if(!btn.Text("Test")) return(false);
   
   if(!Add(btn)) return(false);
   
   return(true);
}
ちなみに私はメソッドの処理をクラスから出して書いてますが、普通にクラス内で書いても問題ありません。 そこは好みでお願いします。
class MyDialog : public CAppDialog{
   private:
      CButton btn;
   public:
      virtual bool Create(){
         if(!CAppDialog::Create(0, "MainDialog", 0, 100, 100, 300, 300)){
            return(false);
         }
         
         if(!btn.Create(0, "Button", 0, 20, 60, 180, 140)) return(false);
         if(!btn.Font("Terminal")) return(false);
         if(!btn.Text("Test")) return(false);
         if(!Add(btn)) return(false);
   
         return(true);
      }
};

ポイント4

MyDialogクラスの準備は一通り完了したので、インスタンスを作成します。
MyDialog dialog;

ポイント5

作成したMyDialogクラスを表示するには、CreateとRun(作ってないけどCAppDialogから継承してます)を実行します。 最初から表示したいので、OnInit内に書いていきます。 CreateやRunに失敗したらINIT_FAILEDで終了させます。
int OnInit(){
   if(!dialog.Create()) return(INIT_FAILED);
   if(!dialog.Run()) return(INIT_FAILED);

   return(INIT_SUCCEEDED);
}

ポイント6

インジケーター(あるいはEA)を終了後にダイアログが残っていると邪魔なので、OnDeinit内でDestroyを実行してダイアログを削除します。
void OnDeinit(const int reason){
   dialog.Destroy(reason);
}

ポイント7

ダイアログのドラッグ&ドロップなどを有効にするには、OnChartEvent内でChartEventを実行してあげます。
dialog.ChartEvent(id, lparam, dparam, sparam);

ポイント8

ボタンをクリックされた場合の処理を作成します。 OnChartEvent関数には4つの引数がありますが、簡単に説明すると以下の様な情報が渡されてきます。 id → チャートで起こったイベント内容 lparam → イベントが起きた場所 (X方向) dparam → イベントが起きた場所 (Y方向) sparam → (オブジェクトが操作されてたら)操作されたオブジェクトの名前 そこでまずはidに渡された情報を確認します。 チャートで起こった操作が、オブジェクトのクリックであるかどうかを判定します。
if(id == CHARTEVENT_OBJECT_CLICK){
   //何らかのオブジェクトがクリックされた
}
次にsparamの情報を参照して、クリックされたオブジェクトを判定します。 今回作成したボタンには、「Button」という名前をつけているので、sparamがこれと一致するか確認します。
if(sparam == "Button"){
   //Buttonがクリックされた
}
後はこのif文の中にボタンがクリックされた時に実行したい処理を書きます。 とりあえずAlertでも表示してみます。
if(id == CHARTEVENT_OBJECT_CLICK){
   if(sparam == "Button"){
      Alert("hoge");
   }
}
以上でコーディング完了です。 プログラム全体は以下の用になります。
#property strict
#property indicator_chart_window

#include 
#include 

class MyDialog : public CAppDialog{
   private:
      CButton btn;
   public:
      virtual bool Create();
};

bool MyDialog::Create(){
   if(!CAppDialog::Create(0, "MainDialog", 0, 100, 100, 300, 300)){
      return(false);
   }
   
   if(!btn.Create(0, "Button", 0, 20, 60, 180, 140)) return(false);
   if(!btn.Font("Terminal")) return(false);
   if(!btn.Text("Test")) return(false);
   
   if(!Add(btn)) return(false);
   
   return(true);
}

MyDialog dialog;

int OnInit(){
   if(!dialog.Create()) return(INIT_FAILED);
   if(!dialog.Run()) return(INIT_FAILED);

   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason){
   dialog.Destroy(reason);
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]){

   return(rates_total);
}

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam){
   dialog.ChartEvent(id, lparam, dparam, sparam);
   
   if(id == CHARTEVENT_OBJECT_CLICK){
      if(sparam == "Button"){
         Alert("hoge");
      }
   }
}
Testと表示されたボタンをクリックすると、ちゃんとアラートが表示されます。 ボタン動作確認 最小化、最大化の切り替え、インジケーターの終了、ドラッグ&ドロップも簡単にできます。

あとがき

今回はボタンを1つ表示するだけの簡単なプログラムでしたが、Controlsフォルダの中には他にもチェックボックス、コンボボックス、テキストボックスなどのUIを簡単に作成するためのファイルが入っております。 これらを組み合わせることで使いやすくて面白いEA・インジケーターが作成できますので、是非挑戦してみてください。
商号 株式会社ゴゴジャン
金融商品取引業の登録番号 関東財務局長(金商)第1960号
加入協会 一般社団法人 日本投資顧問業協会
商号 株式会社ゴゴジャン
金融商品取引業の登録番号
関東財務局長(金商)第1960号
加入協会 一般社団法人
日本投資顧問業協会
金融庁日本投資顧問業協会証券・金融商品あっせん相談センター証券取引等監視委員会

Copyright © 2024 GogoJungle Inc. All Rights Reserved.