ホーム » FX自動売買基礎と応用 » MT5版のボタン操作でオブジェクトを消去するツールを作成する【MQLプログラミングの基礎】

MT5版のボタン操作でオブジェクトを消去するツールを作成する【MQLプログラミングの基礎】

1.ファイルの新規作成

この記事では、チャートに設置したボタン操作でラインやテキスト等のオブジェクトを消去するツールを作成します。

※この記事はMQL5の内容です。MQL4に対応した類似記事は以下を参照してください。

MQLプログラミング言語でチャートにボタンを追加する方法

MetaEditorの「新規作成」アイコンをクリックしてMQLウィザードを開始します。

MQLウィザード新規作成

「カスタムインディケータ」を選択して「次へ」をクリック。

一般プロパティ

ファイル名を「DeleteButton.mq5」とし、「次へ」をクリック。

イベントハンドラ

イベントハンドラは一番上のOnCalculate(…,open,high,low,close)とOnTimer、OnChartEventを選択して「次へ」をクリック。

OnTimer関数は、押したボタンを自動で戻す機能で利用します。

OnChartEvent関数は、ボタンをクリックしたことを検知し、そのときに処理を実行する回路で利用します。

描画プロパティ

「カスタムインディケータの描画プロパティ」では、特に何も追加せず「完了」をクリックすれば、ファイルのベースが作成されます。

今回のファイルでは、インディケーターバッファを利用しないので、「#property indicator_chart_window」の行の下へ、下記を追記します。


#property indicator_buffers 0
#property indicator_plots   0

2.ボタンの設置

オブジェクトの名称の頭に共通の文字列を付けて管理するために、接頭辞を定義します。

ファイル上部のプロパティ「#property indicator_plots 0」の下に、下記を追記します。


#define PREFIX "DeleteButton_"

ボタンオブジェクトを表示するために、MQLリファレンス内にある関数を利用します。

MetaEditorメニューの「ヘルプ」から「MQL5リファレンス」を開いて「目次」タブを選択し、「標準的な定数、列挙と構造体」→「オブジェクト定数」→「オブジェクト型」にある「OBJ_BUTTON」を選択してください。

OBJ_BUTTON内にある「//| ボタンを作成する」以下にある「ButtonCreate」関数をコピーして、今回のプログラムの最下部へ貼り付けます。

――――― コピーして貼り付けするコード(ここから) ―――――


//+------------------------------------------------------------------+ 
//| ボタンを作成する                                                      | 
//+------------------------------------------------------------------+ 
bool ButtonCreate(const long              chart_ID=0,               // チャート識別子 
                const string            name="Button",           // ボタン名 
                const int               sub_window=0,             // サブウィンドウ番号 
                const int               x=0,                     // X 座標 
                const int               y=0,                     // Y 座標 
                const int               width=50,                 // ボタンの幅 
                const int               height=18,               // ボタンの高さ 
                const ENUM_BASE_CORNER  corner=CORNER_LEFT_UPPER, // アンカーに使用されるチャートのコーナー 
                const string            text="Button",           // テキスト 
                const string            font="Arial",             // フォント 
                const int               font_size=10,             // フォントサイズ 
                const color             clr=clrBlack,             // テキストの色 
                const color             back_clr=C'236,233,216', // 背景色 
                const color             border_clr=clrNONE,       // 境界線の色 
                const bool              state=false,             // 押される/放される 
                const bool              back=false,               // 背景で表示する 
                const bool              selection=false,         // 強調表示して移動 
                const bool              hidden=true,             // オブジェクトリストに隠す 
                const long              z_order=0)               // マウスクリックの優先順位 
 { 
//--- エラー値をリセットする 
  ResetLastError(); 
//--- ボタンを作成する 
  if(!ObjectCreate(chart_ID,name,OBJ_BUTTON,sub_window,0,0)) 
    { 
    Print(__FUNCTION__, 
          ": failed to create the button! Error code = ",GetLastError()); 
    return(false); 
    } 
//--- ボタン座標を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); 
  ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); 
//--- ボタンサイズを設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width); 
  ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height); 
//--- ポイント座標が相対的に定義されているチャートのコーナーを設定 
  ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); 
//--- テキストを設定する 
  ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); 
//--- テキストフォントを設定する 
  ObjectSetString(chart_ID,name,OBJPROP_FONT,font); 
//--- フォントサイズを設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size); 
//--- テキストの色を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); 
//--- 背景色を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr); 
//--- 境界線の色を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_COLOR,border_clr); 
//--- 前景(false)または背景(true)に表示 
  ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); 
//--- ボタンの状態を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_STATE,state); 
//--- マウスでのボタンを移動させるモードを有効(true)か無効(false)にする 
  ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); 
  ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); 
//--- オブジェクトリストのグラフィックオブジェクトを非表示(true)か表示(false)にする 
  ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); 
//--- チャートのマウスクリックのイベントを受信するための優先順位を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); 
//--- 実行成功 
  return(true); 
 } 
//+------------------------------------------------------------------+

――――― コピーして貼り付けするコード(ここまで) ―――――

OnInit関数内に下記を追記し、ボタンを作成して表示します。


   ButtonCreate(0, PREFIX + "Button", 0, 0, 20, 30, 20, CORNER_LEFT_UPPER, "Del", "Arial Bold", 10, clrBlack, clrSilver, clrNONE);

上記のように引数を指定することで、チャートの左上を基準とし、X座標0、Y座標20の位置に、幅30、高さ20のボタンが表示されます。

ボタン色はSilver、文字色はBlack、フォントはArial Boldで「Del」という文字を表示させています。

インジケーターの削除や再読み込み時にボタンオブジェクトを消去するため、OnDeinit関数を追加します。

下記をOnInit関数の下などへ追加してください(他の関数の中でなければ、どこへ追加しても構いません)。


void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, PREFIX);
}

ここまでの状態でコンパイルし、インジケーターをチャートにセットするとボタンが表示されることを確認できます。

DeleteButton_設置チャート①

3.ボタン操作での消去

ボタンをクリックしたことを認識するために、下記のif文をOnChartEvent関数内へ追記します。


   if (id == CHARTEVENT_OBJECT_CLICK) {
      if (sparam == PREFIX + "Button") {
         
      }
   }

ボタンクリック時に自インジケーター関連以外のオブジェクトを全て削除するため、上記if文内に下記を追記します。


         for (int i = ObjectsTotal(0, -1); i >= 0; i--) {
            string name = ObjectName(0, i, -1);
            if (StringFind(name, PREFIX) == -1) ObjectDelete(0, name);
         }
         ChartRedraw();

コンパイル後、チャート上にライン等を描画し、「Del」ボタンをクリックすると、オブジェクト名にPREFIXが含まれていないオブジェクトは、全て削除されることが確認できます。

DeleteButton_設置チャート②
消去前

DeleteButton_設置チャート③
クリックでの消去後

4.ボタンの自動戻し回路

現在の状態では、ボタンを押すと押しっぱなしの状態になってしまいます。

押したボタンを自動で戻すために、OnTimer関数を利用します。

OnTimer関数を有効化するため、OnInit関数内に下記を追記します。


   EventSetMillisecondTimer(100);

0.1秒(100ミリ秒)間隔でOnTimer関数内の回路が繰り返し実行されるようになります。

インジケーター削除時にTimer回路を停止するため、OnDeinit関数内に下記を追記します。


   EventKillTimer();

ボタンが押されたとき、自動でボタンが戻るよう、OnTimer回路内に下記を追記します。


   static bool state = false;
   if (state) ObjectSetInteger(0, PREFIX + "Button", OBJPROP_STATE, false);
   state = ObjectGetInteger(0, PREFIX + "Button", OBJPROP_STATE);
   ChartRedraw();   }

ボタンが押されたことを認識してから、0.1秒後にボタンを元の状態に戻す動作となります。

今回のプログラムは、以上で完成です。

5.ソースコード

今回、作成したソースコードは下記の通りです。


//+------------------------------------------------------------------+
//|                                                 DeleteButton.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0
#define PREFIX "DeleteButton_"

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   ButtonCreate(0, PREFIX + "Button", 0, 0, 20, 30, 20, CORNER_LEFT_UPPER, "Del", "Arial Bold", 10, clrBlack, clrSilver, clrNONE);
   EventSetMillisecondTimer(100);
//---
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, PREFIX);
   EventKillTimer();
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int32_t rates_total,
                const int32_t 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 int32_t &spread[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   static bool state = false;
   if (state) {
      ObjectSetInteger(0, PREFIX + "Button", OBJPROP_STATE, false);
      ChartRedraw();
   }
   state = ObjectGetInteger(0, PREFIX + "Button", OBJPROP_STATE);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int32_t id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   if (id == CHARTEVENT_OBJECT_CLICK) {
      if (sparam == PREFIX + "Button") {
         for (int i = ObjectsTotal(0, -1); i >= 0; i--) {
            string name = ObjectName(0, i, -1);
            if (StringFind(name, PREFIX) == -1) ObjectDelete(0, name);
         }
         ChartRedraw();
      }
   }
  } //+------------------------------------------------------------------+ 
//| ボタンを作成する                                                      | 
//+------------------------------------------------------------------+ 
bool ButtonCreate(const long              chart_ID=0,               // チャート識別子 
                const string            name="Button",           // ボタン名 
                const int               sub_window=0,             // サブウィンドウ番号 
                const int               x=0,                     // X 座標 
                const int               y=0,                     // Y 座標 
                const int               width=50,                 // ボタンの幅 
                const int               height=18,               // ボタンの高さ 
                const ENUM_BASE_CORNER  corner=CORNER_LEFT_UPPER, // アンカーに使用されるチャートのコーナー 
                const string            text="Button",           // テキスト 
                const string            font="Arial",             // フォント 
                const int               font_size=10,             // フォントサイズ  
                const color             clr=clrBlack,             // テキストの色 
                const color             back_clr=C'236,233,216', // 背景色 
                const color             border_clr=clrNONE,       // 境界線の色 
                const bool              state=false,             // 押される/放される 
                const bool              back=false,               // 背景で表示する 
                const bool              selection=false,         // 強調表示して移動 
                const bool              hidden=true,             // オブジェクトリストに隠す 
                const long              z_order=0)               // マウスクリックの優先順位 
 { 
//--- エラー値をリセットする 
  ResetLastError(); 
//--- ボタンを作成する 
  if(!ObjectCreate(chart_ID,name,OBJ_BUTTON,sub_window,0,0)) 
     { 
     Print(__FUNCTION__, 
           ": failed to create the button! Error code = ",GetLastError()); 
     return(false); 
     } 
//--- ボタン座標を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); 
   ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); 
//--- ボタンサイズを設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width); 
   ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height); 
//--- ポイント座標が相対的に定義されているチャートのコーナーを設定 
  ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); 
//--- テキストを設定する 
  ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); 
//--- テキストフォントを設定する 
  ObjectSetString(chart_ID,name,OBJPROP_FONT,font); 
//--- フォントサイズを設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size); 
//--- テキストの色を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); 
//--- 背景色を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr); 
//--- 境界線の色を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_COLOR,border_clr); 
//--- 前景(false)または背景(true)に表示 
  ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); 
//--- ボタンの状態を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_STATE,state); 
//--- マウスでのボタンを移動させるモードを有効(true)か無効(false)にする 
  ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); 
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); 
//--- オブジェクトリストのグラフィックオブジェクトを非表示(true)か表示(false)にする 
  ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); 
//--- チャートのマウスクリックのイベントを受信するための優先順位を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); 
//--- 実行成功 
  return(true); 
  } 
//+------------------------------------------------------------------+

本記事の監修者・HT FX

2013年にFXを開始し、その後専業トレーダーへ。2014年からMT4/MT5のカスタムインジケーターの開発に取り組む。ブログでは100本を超えるインジケーターを無料公開。投資スタイルは自作の秒足インジケーターを利用したスキャルピング。

EA(自動売買)を学びたい方へオススメコンテンツ

EA運用の注意点

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。


本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。

この記事をシェアする