English Русский 中文 Español Deutsch Português
preview
任意の複雑さのレベルのグラフィカルなパネルを作成する方法

任意の複雑さのレベルのグラフィカルなパネルを作成する方法

MetaTrader 5 | 23 5月 2018, 10:18
4 895 0
Vladimir Karputov
Vladimir Karputov

目次

イントロダクション

今では多くのプログラマがMetaTrader5プラットフォームのインジケーターとEAを開発していますが、そのアプリケーションで利用可能なグラフィカルインターフェイスは扱っていません。 これは、標準ライブラリのPanel およびDialogクラスでは、メソッドの簡単な技術的説明のみを提供しているためだと考えられます。 言語リファレンスには、多くのグラフィカルコントロールのコメントを含むコード例が用意されています。 しかし、その構造と考え方を完全に理解することなく、独自のパネルの作成を開始することはできません。

筆者は試しにパネルの並べ方を理解してみました。 他の開発者と得られた知識を共有したいと思います。 CAppDialogクラスに基づいてグラフィカルパネルを作成する簡単なアプリケーションから始めました。 その後、段階的に修正し、得られた結果を分析しました。

この記事では、CAppDialog クラスの操作に必要なすべての詳細 (パネルの作成方法、必要な最小限の関数セット、およびボタンなど) を追加する方法について説明します。 パネルが構成されているオブジェクト、およびで作成されるべきオーダーを分析します。 また、パネルの作成に使用される定数とその変更方法についても説明します。


CAppDialog にパネルベースを作成する

背景となる情報から始めましょう。 

CAppDialogは、結合された "アプリケーションダイアログ " コントロールのクラスです。 CAppDialog クラスは、1つの MQL5 アプリケーション内で、関数的に接続された異種要素のグループを視覚的に結合します。

パネルを作成する最小コードは以下のとおりです。

//+------------------------------------------------------------------+
//|                                             LearnCAppDialog mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <Controls\Dialog.mqh>

CAppDialog AppWindow;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//[アプリケーションの作成] ダイアログ
   if(!AppWindow.Create(0,"AppWindow",0,20,20,360,324))
      return(INIT_FAILED);
//---実行アプリケーション
   AppWindow.Run();
//--- succeed
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---破棄ダイアログ
   AppWindow.Destroy(reason);
  }
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         //イベント ID
                  const long& lparam,   //ロングタイプのイベントパラメータ
                  const double& dparam, //double 型のイベントパラメータ
                  const string& sparam) //文字列型のイベントパラメータ
  {
   AppWindow.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+


LearnCAppDialog.mq5EAの実行結果は、作成されたコントロールパネルです。

CAppDialog パネル

LearnCAppDialog.mq5EAには、パネルの作成と操作に必要な最小限のコマンドセットがあります。 次の手順を実行します。

  • グローバルプログラムレベルでの CAppDialog クラスのインスタンスの宣言:
#include <Controls\Dialog.mqh>

CAppDialog AppWindow;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

  • AppWindow パネルの作成パネルの起動:
int OnInit()
  {
//[アプリケーションの作成] ダイアログ
   if(!AppWindow.Create(0,"AppWindow",0,20,20,360,324))
      return(INIT_FAILED);
//---実行アプリケーション
   AppWindow.Run();
//--- succeed
   return(INIT_SUCCEEDED);
  }

  • ChartEventイベントをAppWindow パネルに渡す:
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         //イベント ID
                  const long& lparam,   //ロングタイプのイベントパラメータ
                  const double& dparam, //double 型のイベントパラメータ
                  const string& sparam) //文字列型のイベントパラメータ
  {
   AppWindow.ChartEvent(id,lparam,dparam,sparam);
  }

そして最後の非常に重要なステップ:

  • 破棄方法を呼び出してコントロールを破棄する
void OnDeinit(const int reason)
  {
//---破棄ダイアログ
   AppWindow.Destroy(reason);
  }

パネルの破棄をしない場合は、時間枠やシンボルの各変更は、既存のもの上に新しい要素の追加につながります。


AppWindow ができること

CAppDialog ベースのパネルは、理論的には、次のイベントを処理することができます: 

//+------------------------------------------------------------------+
//| Events                                                           |
//+------------------------------------------------------------------+
#define ON_CLICK                (0)   //コントロールイベントのクリック
#define ON_DBL_CLICK            (1)   //コントロールイベントをダブルクリック
#define ON_SHOW                 (2)   //コントロールイベントの表示
#define ON_HIDE                 (3)   //コントロールイベントの非表示
#define ON_CHANGE               (4)   //変更, 制御イベント
#define ON_START_EDIT           (5)   //編集イベントの開始
#define ON_END_EDIT             (6)   //編集イベントの終了
#define ON_SCROLL_INC           (7)   //スクロールバーイベントのインクリメント
#define ON_SCROLL_DEC           (8)   //スクロールバーイベントのデクリメント
#define ON_MOUSE_FOCUS_SET      (9)   // "マウスカーソルがコントロール " イベントをエントリーしました
#define ON_MOUSE_FOCUS_KILL     (10)  // "マウスカーソルがコントロールを終了しました " 
#define ON_DRAG_START           (11)  //"コントロールのドラッグ開始 " イベント
#define ON_DRAG_PROCESS         (12)  // "コントロールがドラッグされています " 
#define ON_DRAG_END             (13)  // "コントロールドラッグエンド " 
#define ON_BRING_TO_TOP         (14)  // "マウスイベントの優先度の増加 " 
#define ON_APP_CLOSE            (100) // "アプリケーションの終了" 

イベントは、ファイル [データフォルダ]\MQL5\Include\ControlsDefines.mqhイベントブロックに含まれています。 イベントは、クリック、ダブルクリック、編集の開始と終了、フォーカスを取得、ドラッグ (開始、プロセスと終了)、パネル表示、ハイドがあります。 イベントの操作例については、「パネルとダイアログ」の例を参照してください。 ON_CHANGE イベントは、 CRadioGroupで処理され、ON_SCROLL_INC と ON_SCROLL_DEC はCScrollVで処理されます。


CAppDialog オブジェクトの構造

空のチャートでLearnCAppDialog.mq5EAを起動し、ctrl + B キーを押して [すべて ] をクリックすると、パネルで構成されているすべてのオブジェクトが表示されます。


標準ライブラリの [パネルとダイアログ] セクションのオブジェクトが作成され、次のオーダーで適用されます。 最初に "Border " オブジェクトが作成され、その中にパネルの背景が "Back " オブジェクトとして追加されます。 次に、クライアント領域 "ClientBack " がバックグラウンドで適用されます。 子コントロールは、クライアント領域内に追加できます。 パネルの名前と2つのコントロールボタンを持つキャプションオブジェクトが、パネルの上部に追加されます。

AppWindow パネルのグラフィカルコントロール

このプロセスは、オブジェクトの作成オーダーを表示するために、概略的に表すことができます。

Borderオブジェクトは、白い枠線の色セット(すべてのパネルのデフォルト値) を使用したOBJ_RECTANGLE_LABELです。 したがって、Borderオブジェクトは、純粋に審美的な目的で使用されます。 Borderオブジェクトのボディは、 Backオブジェクトの後ろに隠れるように、白い枠線を表示します。



オブジェクトの継承のスキーム

[パネルとダイアログ] セクションには、広範な関係と継承構造を持つクラスが多すぎると思われる場合があります。 しかし、階層は非常に簡単です。 したがって、CAppDialog がどのように構成され、どのように作成されるかを理解すれば、他のクラスの理解も容易になります。 次に、標準ライブラリからのすべてのクラスの継承スキームを示します。


LearnCAppDialog.mq5EAの AppWindow パネルは、ぞれが特定のタスクを実行する6つのオブジェクトで構成されています。


CAppDialog ベースのパネルは、EAまたはインジケーターから作成できます。 ただし、パネルの作成は、パネルを作成するプログラム (EAまたはインジケーター) の種類と、プログラムが実行されているサブによって異なる場合があります。

  • プログラムがEA (実行中のプログラムの種類が PROGRAM_EXPERT) の場合、パネルはメインウィンドウにのみ作成されます (ウィンドウインデックスは "0 ")、 CAppDialog:: CreateExpertmソッドのみを使用します。
  • プログラムがインジケーター (実行中のプログラムの種類が PROGRAM_INDICATOR) の場合は、プログラムが実行されているウィンドウの番号がチェックされます。
    • メインウィンドウ (ウィンドウ番号が 0) の場合、パネルはCAppDialog::CreateIndicatorメソッドを使用して作成されます。
    • サブの場合、パネルはCAppDialog:: CreateExpertメソッドを使用して作成されます

CAppDialog::CreateIndicatorメソッドの具体的な関数は、パネルが作成時に自動的に次のことを行うことです。

  • ウィンドウの幅に合わせて調整
  • ウィンドウの高さをパネルに合わせて調整

[データフォルダ] \MQL5\Indicators\Examples\Panels\SimplePanel\SimplePanel.mq5 の作成後に表示されるインジケーターパネルの例を次に示します。


CreateExpert はメインウィンドウ (ウィンドウ番号は 0) にパネルを作成し、パネルを作成するプログラムがEAであることを意味します。

ルールには例外があります: インジケーターからメインウィンドウにパネルを作成できます。 この場合、パネル作成のCreateIndicatorメソッドが適用されます。


オブジェクトを作成するための主な定数を見つけるために、#undef を使用してを再定義する場所

このコードは、 AppWindowEditDefine mq5EAで実装されます。

パネルとそのコントロールの基本的な定数は、CWnd クラスで接続されている MQL5\Include\Controls\Defines.mqh にあります。

//+------------------------------------------------------------------+
//|                                                         Wnd mqh |
//|                   Copyright 2009-2017, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Rect.mqh"
#include "Defines.mqh"
#include <Object.mqh>
class CDragWnd;

継承の階層は次のとおりです。

  • CWnd
    • CWndContainer
      • CDialog
        • CAppDialog

特に定数の次のグループに興味がある:

//+------------------------------------------------------------------+
//| Drawing styles and colors                                        |
//+------------------------------------------------------------------+
//---共通
#define CONTROLS_FONT_NAME                  "Trebuchet MS"
#define CONTROLS_FONT_SIZE                  (10)
//---テキスト
#define CONTROLS_COLOR_TEXT                 C'0x3B,0x29,0x28'
#define CONTROLS_COLOR_TEXT_SEL             White
#define CONTROLS_COLOR_BG                   White
#define CONTROLS_COLOR_BG_SEL               C'0x33,0x99,0xFF'
//---ボタン
#define CONTROLS_BUTTON_COLOR               C'0x3B,0x29,0x28'
#define CONTROLS_BUTTON_COLOR_BG            C'0xDD,0xE2,0xEB'
#define CONTROLS_BUTTON_COLOR_BORDER        C'0xB2,0xC3,0xCF'
//---ラベル
#define CONTROLS_LABEL_COLOR                C'0x3B,0x29,0x28'
//---編集
#define CONTROLS_EDIT_COLOR                 C'0x3B,0x29,0x28'
#define CONTROLS_EDIT_COLOR_BG              White
#define CONTROLS_EDIT_COLOR_BORDER          C'0xB2,0xC3,0xCF'
//---スクロール
#define CONTROLS_SCROLL_COLOR_BG            C'0xEC,0xEC,0xEC'
#define CONTROLS_SCROLL_COLOR_BORDER        C'0xD3,0xD3,0xD3'
//---クライアント
#define CONTROLS_CLIENT_COLOR_BG            C'0xDE,0xDE,0xDE'
#define CONTROLS_CLIENT_COLOR_BORDER        C'0x2C,0x2C,0x2C'
//---ListView
#define CONTROLS_LISTITEM_COLOR_TEXT        C'0x3B,0x29,0x28'
#define CONTROLS_LISTITEM_COLOR_TEXT_SEL    White
#define CONTROLS_LISTITEM_COLOR_BG          White
#define CONTROLS_LISTITEM_COLOR_BG_SEL      C'0x33,0x99,0xFF'
#define CONTROLS_LIST_COLOR_BG              White
#define CONTROLS_LIST_COLOR_BORDER          C'0xB2,0xC3,0xCF'
//---CheckGroup
#define CONTROLS_CHECKGROUP_COLOR_BG        C'0xF7,0xF7,0xF7'
#define CONTROLS_CHECKGROUP_COLOR_BORDER    C'0xB2,0xC3,0xCF'
//---RadioGroup
#define CONTROLS_RADIOGROUP_COLOR_BG        C'0xF7,0xF7,0xF7'
#define CONTROLS_RADIOGROUP_COLOR_BORDER    C'0xB2,0xC3,0xCF'
//---] ダイアログ
#define CONTROLS_DIALOG_COLOR_BORDER_LIGHT  White
#define CONTROLS_DIALOG_COLOR_BORDER_DARK   C'0xB6,0xB6,0xB6'
#define CONTROLS_DIALOG_COLOR_BG            C'0xF0,0xF0,0xF0'
#define CONTROLS_DIALOG_COLOR_CAPTION_TEXT  C'0x28,0x29,0x3B'
#define CONTROLS_DIALOG_COLOR_CLIENT_BG     C'0xF7,0xF7,0xF7'
#define CONTROLS_DIALOG_COLOR_CLIENT_BORDER C'0xC8,0xC8,0xC8'

マクロの置換を変更するには、 #undefディレクティブを使用します。

#undef ディレクティブは、以前に宣言したマクロを取り消すために使用されます。

したがって、次のアルゴリズムがあります: 以前に宣言したマクロをキャンセルします。次に、変更されたパラメータを使用してマクロを再宣言します。 次のようにする必要があります: Defines.mqhファイルをDialog.mqhの前に接続します。

//+------------------------------------------------------------------+
//|                                         AppWindowEditDefine mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.001"
#property description "Control Panels and Dialogs. デモンストレーションクラス CBmpButton  "
#include <Controls\Defines.mqh>


接続後にマクロをキャンセルする "Defines.mqh":

#undef CONTROLS_FONT_NAME 
#undef CONTROLS_FONT_SIZE 

#undef CONTROLS_BUTTON_COLOR
#undef CONTROLS_BUTTON_COLOR_BG
#undef CONTROLS_BUTTON_COLOR_BORDER

#undef CONTROLS_DIALOG_COLOR_BORDER_LIGHT
#undef CONTROLS_DIALOG_COLOR_BORDER_DARK
#undef CONTROLS_DIALOG_COLOR_BG
#undef CONTROLS_DIALOG_COLOR_CAPTION_TEXT
#undef CONTROLS_DIALOG_COLOR_CLIENT_BG
#undef CONTROLS_DIALOG_COLOR_CLIENT_BORDER 

インプットパラメータの書き込み:

input string   font_name                  = "Trebuchet MS";
input int      font_size                  = 10;

input color    button_color               = C'0x3B,0x29,0x28';
input color    button_color_bg            = C'0xDD,0xE2,0xEB';
input color    button_color_border        = C'0xB2,0xC3,0xCF';

input color    dialog_color_border_light  = White;
input color    dialog_color_border_dark   = C'0xB6,0xB6,0xB6';
input color    dialog_color_bg            = C'0xF0,0xF0,0xF0';
input color    dialog_color_caption_text  = C'0x28,0x29,0x3B';
input color    dialog_color_client_bg     = C'0xF7,0xF7,0xF7';
input color    dialog_color_client_border = C'0xC8,0xC8,0xC8';

最も興味深い部分: 再びマクロを宣言し、その値のインプットパラメータを使用してます:

#define CONTROLS_FONT_NAME                font_name
#define CONTROLS_FONT_SIZE                font_size

#define CONTROLS_BUTTON_COLOR             button_color
#define CONTROLS_BUTTON_COLOR_BG          button_color_bg
#define CONTROLS_BUTTON_COLOR_BORDER      button_color_border

#define CONTROLS_DIALOG_COLOR_BORDER_LIGHT dialog_color_border_light
#define CONTROLS_DIALOG_COLOR_BORDER_DARK dialog_color_border_dark
#define CONTROLS_DIALOG_COLOR_BG          dialog_color_bg
#define CONTROLS_DIALOG_COLOR_CAPTION_TEXT dialog_color_caption_text
#define CONTROLS_DIALOG_COLOR_CLIENT_BG   dialog_color_client_bg
#define CONTROLS_DIALOG_COLOR_CLIENT_BORDER dialog_color_client_border

#include <Controls\Dialog.mqh>
#include <Controls\BmpButton.mqh>

レイ:



CAppDialogのサムアップ

このパネルは、 CAppDialogクラスのオブジェクトです。 CWndContainerクラスからControlsTotalメソッド (コンテナ内のコントロールの数) を継承しています。 したがって、パネルのすべてのコントロールを通過し、アクションを適用することができます。 要素は、親CDialogクラスのプライベート領域で宣言されます。

//+------------------------------------------------------------------+
//| Class CDialog                                                    |
//| Usage: base class to create dialog boxes                         |
//|             and indicator panels                                 |
//+------------------------------------------------------------------+
class CDialog : public CWndContainer
  {
private:
   //従属コントロール
   CPanel            m_white_border;        // "ホワイトボーダー " オブジェクト
   CPanel            m_background;          //背景オブジェクト
   CEdit             m_caption;             //ウィンドウタイトルオブジェクト
   CBmpButton        m_button_close;        // "Close " ボタンオブジェクト
   CWndClient        m_client_area;         //クライアント領域オブジェクト

protected:

デバッガでは、オブジェクトの作成方法を確認できます。

//+------------------------------------------------------------------+
//|コントロールを作成する |
//+------------------------------------------------------------------+
bool CDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
//親クラスの呼び出しメソッド
   if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
//従属コントロールの作成
   if(!m_panel_flag && !CreateWhiteBorder())
      return(false);
   if(!CreateBackground())
      return(false);
   if(!CreateCaption())
      return(false);
   if(!CreateButtonClose())
      return(false);
   if(!CreateClientArea())
      return(false);

as well as how names are assigned to them: m_white_border -> "29437Border", m_background -> "29437Back", m_caption -> "29437Caption", m_button_close -> "29437Close", m_client_area -> "29437Client". 名前では、 "29437 " の数は、その有効期間のパネルの識別子です。

したがって、パネルの要素のプロパティを変更することができます。 たとえば、次のように、 m_client_areaおよびm_backgroundオブジェクトの色を変更できます。

//+------------------------------------------------------------------+
//|                                           LearnCAppDialog_1 mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <Controls\Dialog.mqh>

CAppDialog AppWindow;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//[アプリケーションの作成] ダイアログ
   if(!AppWindow.Create(0,"AppWindow",0,20,20,360,324))
      return(INIT_FAILED);
//---
   int total=AppWindow.ControlsTotal();
   CWndClient*myclient;
   for(int i=0;i<total;i++)
     {
      CWnd*obj=AppWindow.Control(i);
      string name=obj.Name();
      PrintFormat("%d is %s",i,name);
      //---色 
      if(StringFind(name,"Client")>0)
        {
         CWndClient *client=(CWndClient*)obj;
         client.ColorBackground(clrRed);
         myclient=client;
         Print("client.ColorBackground(clrRed);");
         ChartRedraw();
        }
      //---
      if(StringFind(name,"Back")>0)
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(clrGreen);
         Print("panel.ColorBackground(clrGreen);");
         ChartRedraw();
        }
     }
   AppWindow.Delete(myclient);
//---実行アプリケーション
   AppWindow.Run();
//--- succeed
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---破棄ダイアログ
   AppWindow.Destroy(reason);
  }
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         //イベント ID
                  const long& lparam,   //ロングタイプのイベントパラメータ
                  const double& dparam, //double 型のイベントパラメータ
                  const string& sparam) //文字列型のイベントパラメータ
  {
   AppWindow.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+


次の行に注意を払ってください: グループ (コンテナ) から要素を削除する>CWndContainer::Deleteメソッドの呼び出しがあります。 グループからm_client_area要素を削除すると、パネルを移動しようとした場合に、適切なコマンドがm_client_areaオブジェクトに渡されなくなります。 クライアント領域は、次の位置にとどまります。


ただし、パネルを閉じると、 m_client_area 要素は他の要素と共にチャートから削除されます。

次の例では、 CWndContainer::Deleteの代わりにCWndContainer::D estroyメソッドを使用して、 m_client_areaオブジェクトを破棄します。

//+------------------------------------------------------------------+
//|                                           LearnCAppDialog_2 mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <Controls\Dialog.mqh>

CAppDialog AppWindow;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//[アプリケーションの作成] ダイアログ
   if(!AppWindow.Create(0,"AppWindow",0,20,20,360,324))
      return(INIT_FAILED);
//---
   int total=AppWindow.ControlsTotal();
   CWndClient*myclient;
   for(int i=0;i<total;i++)
     {
      CWnd*obj=AppWindow.Control(i);
      string name=obj.Name();
      PrintFormat("%d is %s",i,name);
      //---色 
      if(StringFind(name,"Client")>0)
        {
         CWndClient *client=(CWndClient*)obj;
         client.ColorBackground(clrRed);
         myclient=client;
         Print("client.ColorBackground(clrRed);");
         ChartRedraw();
        }
      //---
      if(StringFind(name,"Back")>0)
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(clrGreen);
         Print("panel.ColorBackground(clrGreen);");
         ChartRedraw();
        }
     }
   Sleep(5000);
   myclient.Destroy();
//---実行アプリケーション
   AppWindow.Run();
//--- succeed
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---破棄ダイアログ
   AppWindow.Destroy(reason);
  }
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         //イベント ID
                  const long& lparam,   //ロングタイプのイベントパラメータ
                  const double& dparam, //double 型のイベントパラメータ
                  const string& sparam) //文字列型のイベントパラメータ
  {
   AppWindow.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+


ここでは次のように動作します: 5秒のスリープにより、パネルの作成後に一時ストップし、クライアント領域が破壊されます:



新しいコントロールを追加する方法: 2 つのボタン

CButtonクラスに基づいて2つのボタンをパネルに追加し、 AppWindowTwoButtons.mq5として保存することにより、EA をセクション "CAppDialog に基づくパネルの作成" から変更してみましょう。 ボタンを追加する前に (任意のパネルのデザインに似ています)、まずそのサイズと位置を考える必要があります。 たとえば、次の図は、作成したいボタンを持つパネルを示しています。 


ただし:

  • TOPは、クライアント領域の上端からの距離 (INDENT_TOP 定数によって設定) です
  • LEFTは、クライアント領域の左端からの距離です (INDENT_LEFT 定数によって設定されます)
  • [HEIGHT] はボタンの高さです (BUTTON_HEIGHT 定数によって設定されます)
  • [WIDTH] はボタンの幅です (BUTTON_WIDTH 定数で設定)

必要とするもう一つの定数は、コントロール間の最小水平方向のインデントです。 "CONTROLS_GAP_X " と呼びましょう。 

CButtonクラスを使用するには、最初に接続する必要があります。

//+------------------------------------------------------------------+
//|                                         AppWindowTwoButtons mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.001"
#property description "Control Panels and Dialogs. Demonstration class CButton"
#include <Controls\Dialog.mqh>
#include<ControlsButton.mqh></ControlsButton.mqh>

次に、ボタンのサイズとポジションの定数を追加します。

//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
//---インデントとギャップ
#define INDENT_LEFT                         (11)      //左からインデント (境界線幅の許容値)
#define INDENT_TOP                          (11)      //上からインデント (罫線の幅に対して)
#define CONTROLS_GAP_X                      (5)       //X 座標によるギャップ
//ボタン
#define BUTTON_WIDTH                        (100)     //X 座標によるサイズ
#define BUTTON_HEIGHT                       (20)      //Y 座標によるサイズ
//---

グローバルプログラムレベルでの CButton クラスの2つのインスタンスの宣言:

#define BUTTON_HEIGHT                       (20)      //Y 座標によるサイズ
//---
CAppDialog           AppWindow;
CButton              m_button1;                       //ボタンオブジェクト
CButton              m_button2;                       //ボタンオブジェクト
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()

グローバルレベルでのボタンの宣言は、インスタンス (したがって、そのメソッド) は、EAのどこからでも見られるので、悪いスタイルです。 しかし、コード量を減らすために意図的にこのようにしました。

OnInit()はわずかに変更されます: ボタンの作成結果の呼び出しと検証を追加:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//[アプリケーションの作成] ダイアログ
   if(!AppWindow.Create(0,"AppWindow with Two Buttons",0,40,40,380,344))
      return(INIT_FAILED);
//従属コントロールの作成
   if(!CreateButton1())
      return(false);
   if(!CreateButton2())
      return(false);
//---実行アプリケーション
   AppWindow.Run();
//--- succeed
   return(INIT_SUCCEEDED);
  }


CreateButton1 () を分析して、ボタンの作成とパネルへのリンクのプロセスを詳細に見てみましょう。

CButton クラスのボタンを作成するためのCreate メソッドを使用します: :


 ボタンにテキストを追加するための text ( Textメソッドは、 CWndObjクラスから継承されます):


ボタンはこの段階で作成されますが、パネルとは別に存在します。 これらをバインドするには、CDialog:: Add メソッドを実行して、ボタンをパネルのクライアント領域に追加する必要があります。

   if(!AppWindow.Add(m_button1))
      return(false);
//--- succeed
   return(true);
  }

ボタンの作成の完全なコードです:

//+------------------------------------------------------------------+
//| Create the "Button1" button                                      |
//+------------------------------------------------------------------+
bool CreateButton1(void)
  {
//---座標
   int x1=INDENT_LEFT;        // x1            = 11  pixels
   int y1=INDENT_TOP;         // y1            = 11  pixels
   int x2=x1+BUTTON_WIDTH;    // x2 = 11 + 100 = 111 pixels
   int y2=y1+BUTTON_HEIGHT;   // y2 = 11 + 20  = 32  pixels
//--- create
   if(!m_button1.Create(0,"Button1",0,x1,y1,x2,y2))
      return(false);
   if(!m_button1.Text("Button1"))
      return(false);
   if(!AppWindow.Add(m_button1))
      return(false);
//--- succeed
   return(true);
  }

OnDeinit () でパネルを破壊し、すべてのイベントを OnChartEvent () のフォームに渡す必要があることを忘れないでください。

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Comment("");
//---破棄ダイアログ
   AppWindow.Destroy(reason);
  }
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         //イベント ID
                  const long& lparam,   //ロングタイプのイベントパラメータ
                  const double& dparam, //double 型のイベントパラメータ
                  const string& sparam) //文字列型のイベントパラメータ
  {
   AppWindow.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+
//| Create the "Button1" button                                      |
//+------------------------------------------------------------------+


ネストになったコントロールの移動と描画の方法

AppWindow パネルは、CDialog の子である CAppDialog クラスのオブジェクトであることに注意してください。 CDialog 自体は、 CWndContainerから派生します。

CWndContainer は、標準ライブラリのコントロールグループの基本クラスです。

したがって、親 CWndContainer クラスは、パネルに含まれているコントロールのグループ全体の移動を制御します。

パネルのすべてのコントロールの移動は、 CWndContainer:: Shiftのループで実行されます。

//+------------------------------------------------------------------+
//|コントロールグループの相対移動 |
//+------------------------------------------------------------------+
bool CWndContainer::Shift(const int dx,const int dy)
  {
//親クラスのメソッドの呼び出し
   if(!CWnd::Shift(dx,dy))
      return(false);
//グループの要素によるループ
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //ポインタのチェック
      if(control==NULL)
         continue;
      //グループアイテムを移動
      control.Shift(dx,dy);
     }
//--- succeed
   return(true);
  }

ここでは、参照- CBmpButton (パネルの MQL5ExpertsMyExpHelpWith にある) の例を使用しました。 EN\ControlsBmpButton.mq5).

CWndContainer:: Shiftメソッドへのアクセス:



CDialog を介してコントロールのグループに CAppDialog を追加する

上記の2つのボタンを持つパネルの例です。 グローバルレベルでのボタンを宣言する良い例ではないと述べたのは覚えているでしょうか。 より適切な例を次に示します。パネルとボタンを作成するためのコード全体を、 CAppDialogから派生したクラスに配置します。 パネルの作成例をAppWindowTwoButtonsClass.mq5に示します。

CAppWindowTwoButtonsは CAppDialog の子クラスで、次のメソッドがあります。

 Creation
 Create  メインコントロールの作成: パネル
 CreateButton1  従属コントロールの作成: ボタン #1
 CreateButton2  従属コントロールの作成: ボタン #2

AppWindowTwoButtonsClass.mq5のコード: クラス内にあるコードは、次のように色で強調表示されます。

//+------------------------------------------------------------------+
//|                                    AppWindowTwoButtonsClass mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.000"
#property description "Control Panels and Dialogs. Demonstration class CButton"
#include <Controls\Dialog.mqh>
#include<ControlsButton.mqh></ControlsButton.mqh>
//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
//---インデントとギャップ
#define INDENT_LEFT                         (11)      //左からインデント (境界線幅の許容値)
#define INDENT_TOP                          (11)      //上からインデント (罫線の幅に対して)
#define CONTROLS_GAP_X                      (5)       //X 座標によるギャップ
//ボタン
#define BUTTON_WIDTH                        (100)     //X 座標によるサイズ
#define BUTTON_HEIGHT                       (20)      //Y 座標によるサイズ
//---
//+------------------------------------------------------------------+
//| Class CAppWindowTwoButtons                                       |
//| Usage: main dialog of the Controls application                   |
//+------------------------------------------------------------------+
class CAppWindowTwoButtons : public CAppDialog
  {
private:
   CButton           m_button1;                       //ボタンオブジェクト
   CButton           m_button2;                       //ボタンオブジェクト

public:
                     CAppWindowTwoButtons(void);
                    ~CAppWindowTwoButtons(void);
   //--- create
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);

protected:
   //従属コントロールの作成
   bool              CreateButton1(void);
   bool              CreateButton2(void);

  };
//+------------------------------------------------------------------+
//|コンストラクタ |
//+------------------------------------------------------------------+
CAppWindowTwoButtons::CAppWindowTwoButtons(void)
  {
  }
//+------------------------------------------------------------------+
//|デストラクタ |
//+------------------------------------------------------------------+
CAppWindowTwoButtons::~CAppWindowTwoButtons(void)
  {
  }
//+------------------------------------------------------------------+
//|作成 |
//+------------------------------------------------------------------+
bool CAppWindowTwoButtons::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);
//従属コントロールの作成
   if(!CreateButton1())
      return(false);
   if(!CreateButton2())
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//|グローバル変数 |
//+------------------------------------------------------------------+
CAppWindowTwoButtons ExtDialog;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//[アプリケーションの作成] ダイアログ
   if(!ExtDialog.Create(0,"AppWindowClass with Two Buttons",0,40,40,380,344))
      return(INIT_FAILED);
//---実行アプリケーション
   ExtDialog.Run();
//--- succeed
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Comment("");
//---破棄ダイアログ
   ExtDialog.Destroy(reason);
  }
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         //イベント ID
                  const long& lparam,   //ロングタイプのイベントパラメータ
                  const double& dparam, //double 型のイベントパラメータ
                  const string& sparam) //文字列型のイベントパラメータ
  {
   ExtDialog.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+
//| Create the "Button1" button                                      |
//+------------------------------------------------------------------+
boolCAppWindowTwoButtons:: CreateButton1 (void)
  {
//---座標
   int x1=INDENT_LEFT;        // x1            = 11  pixels
   int y1=INDENT_TOP;         // y1            = 11  pixels
   int x2=x1+BUTTON_WIDTH;    // x2 = 11 + 100 = 111 pixels
   int y2=y1+BUTTON_HEIGHT;   // y2 = 11 + 20  = 32  pixels
//--- create
   if(!m_button1.Create(0,"Button1",0,x1,y1,x2,y2))
      return(false);
   if(!m_button1.Text("Button1"))
      return(false);
   if(!Add(m_button1))
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Create the "Button2"                                             |
//+------------------------------------------------------------------+
boolCAppWindowTwoButtons:: CreateButton2 (void)
  {
//---座標
   int x1=INDENT_LEFT+2*(BUTTON_WIDTH+CONTROLS_GAP_X);   // x1 = 11  + 2 * (100 + 5) = 221 pixels
   int y1=INDENT_TOP;                                    // y1                       = 11  pixels
   int x2=x1+BUTTON_WIDTH;                               // x2 = 221 + 100           = 321 pixels
   int y2=y1+BUTTON_HEIGHT;                              // y2 = 11  + 20            = 31  pixels
//--- create
   if(!m_button2.Create(0,"Button2",0,x1,y1,x2,y2))
      return(false);
   if(!m_button2.Text("Button2"))
      return(false);
   if(!Add(m_button2))
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+

AppWindowTwoButtonsClass.mq5の例に基づいて、パネルとコントロールを作成するためのアルゴリズムを見てみましょう。 すべてのアクションは CAppWindowTwoButtons:: Create で実行されます。

  • パネルの作成:
   if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);

  • 従属コントロールの作成:
//従属コントロールの作成
   if(!CreateButton1())
      return(false);
   if(!CreateButton2())
      return(false);

  • 最も重要な瞬間は、ボタンが作成されたとき、パネルの従属要素ではなく、それ自体が存在するということです。 panel の従属要素の1つにするには、 Addメソッド (CDialog::Add ) を呼び出して、指定したポインタ/参照のクライアント領域にコントロールを追加します。
...
   if(!Add(m_button1))
      return(false);
...
   if(!Add(m_button2))
      return(false);
...

その後、コントロールは panel の従属要素になります: すべてのイベントは、パネルから従属コントロールに集中的にされます。

標準コントロールの動作をオーバーライドする方法

パネルを最小化すると、座標 (10; 10) に配置されます。 最小化されたパネルは、ワンクリックトレードパネルと部分的に重なっています。

このようなポジションを修正し、ワンクリックトレードパネルが最大化されているかどうかのチェックを追加してみましょう。 この目的のために、親 CAppDialog::Minimazeメソッドをオーバーライドする必要があります。 別の例を作成してみましょう: AppWindowTwoButtons.mq5のコードに基づいて、セクション "CDialog を介してコントロールのグループに CAppDialog を追加する " からAppWindowCorrectMinimization.mq5 です。

変更:最小化メソッドの宣言:

protected:
   //従属コントロールの作成
   bool              CreateButton1(void);
   bool              CreateButton2(void);
   //---親方法をオーバーライドします。
   virtual void      Minimize(void);

  };

そして、メソッド本体を書きます:

//+------------------------------------------------------------------+
//|                                                                 |
//+------------------------------------------------------------------+
void CAppWindowCorrectMinimization::Minimize(void)
  {
//ワンクリックトレードパネルをチェックするための変数
   long one_click_visible=-1;  //0-ワンクリックでトレードパネルがない
   if(!ChartGetInteger(m_chart_id,CHART_SHOW_ONE_CLICK,0,one_click_visible))
     {
      //エキスパートジャーナルにエラーメッセージを表示
      Print(__FUNCTION__+", Error Code = ",GetLastError());
     }
//最小化されたパネルの最小インデント
   int min_y_indent=28;
   if(one_click_visible)
      min_y_indent=100;  //チャートにワンクリックでトレードパネルがある場合は、このインデントを使用します。
//最小化されたパネルの現在のインデントを取得
   int current_y_top=m_min_rect.top;
   int current_y_bottom=m_min_rect.bottom;
   int height=current_y_bottom-current_y_top;
//アプリケーションの最小化されたパネルの上から最小インデントを計算
   if(m_min_rect.top!=min_y_indent)
     {
      m_min_rect.top=min_y_indent;
      //最小化されたアイコンの下罫線をシフト
      m_min_rect.bottom=m_min_rect.top+height;
     }
//---基本クラスの方法を呼び出すことができます
   CAppDialog::Minimize();
  }



イベント処理の種類の組み込みマクロを読み取る方法

このパネルでは、次の種類のイベントを処理できます ([データフォルダ]\MQL5\Include\ControlsDefines.mqh で、"Events" で定義されています)。

//+------------------------------------------------------------------+
//| Events                                                           |
//+------------------------------------------------------------------+
#define ON_CLICK                (0)   //コントロールイベントのクリック
#define ON_DBL_CLICK            (1)   //コントロールイベントをダブルクリック
#define ON_SHOW                 (2)   //コントロールイベントの表示
#define ON_HIDE                 (3)   //コントロールイベントの非表示
#define ON_CHANGE               (4)   //変更, 制御イベント
#define ON_START_EDIT           (5)   //編集イベントの開始
#define ON_END_EDIT             (6)   //編集イベントの終了
#define ON_SCROLL_INC           (7)   //スクロールバーイベントのインクリメント
#define ON_SCROLL_DEC           (8)   //スクロールバーイベントのデクリメント
#define ON_MOUSE_FOCUS_SET      (9)   // "マウスカーソルがコントロール " イベントをエントリーしました
#define ON_MOUSE_FOCUS_KILL     (10)  // "マウスカーソルがコントロールを終了しました " 
#define ON_DRAG_START           (11)  //"コントロールのドラッグ開始 " イベント
#define ON_DRAG_PROCESS         (12)  // "コントロールがドラッグされています " 
#define ON_DRAG_END             (13)  // "コントロールドラッグエンド " 
#define ON_BRING_TO_TOP         (14)  // "マウスイベントの優先度の増加 " 
#define ON_APP_CLOSE            (100) // "アプリケーションの終了" 

イベントは、CAppDialog:: OnEventメソッドで処理されます。 さまざまな種類のイベントを視覚的に認識するために、[データフォルダ]\MQL5\Include\ControlsDefines.mqh では、イベント処理マップのブロック "で定義されているマクロについて説明します。

//+------------------------------------------------------------------+
//|イベントハンドリングマップのマクロ |
//+------------------------------------------------------------------+
+------------------------------------------------------------------+ ...
//マップの先頭
#define EVENT_MAP_BEGIN(class_name)              bool class_name::OnEvent(const int id,const long& lparam,const double& dparam,const string& sparam) {
//---マップの終わり
#define EVENT_MAP_END(parent_class_name)         return(parent_class_name::OnEvent(id,lparam,dparam,sparam)); }
//数値 ID によるイベント処理
#define ON_EVENT(event,control,handler)          if(id==(event+CHARTEVENT_CUSTOM) && lparam==control.Id()) { handler(); return(true); }
//コントロールのポインターによる数値 ID によるイベント処理
#define ON_EVENT_PTR(event,control,handler)      if(control!=NULL && id==(event+CHARTEVENT_CUSTOM) && lparam==control.Id()) { handler(); return(true); }
//ID 分析を行わないイベント処理
#define ON_NO_ID_EVENT(event,handler)            if(id==(event+CHARTEVENT_CUSTOM)) { return(handler()); }
//行 ID によるイベント処理
#define ON_NAMED_EVENT(event,control,handler)    if(id==(event+CHARTEVENT_CUSTOM) && sparam==control.Name()) { handler(); return(true); }
//インデックス付きイベントの処理
#define ON_INDEXED_EVENT(event,controls,handler) { int total=ArraySize(controls); for(int i=0;i<total;i++) if(id==(event+CHARTEVENT_CUSTOM) && lparam==controls[i].Id()) return(handler(i)); }
//外部イベントの処理
#define ON_EXTERNAL_EVENT(event,handler)         if(id==(event+CHARTEVENT_CUSTOM)) { handler(lparam,dparam,sparam); return(true); }

イベント処理マップ "ブロック " イベント "および " マクロからの、OnEventメソッドは次のようになります。 

//+------------------------------------------------------------------+
//|イベントの取り扱い |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CControlsDialog)
ON_EVENT(ON_CLICK,m_bmpbutton1,OnClickBmpButton1)
ON_EVENT(ON_CLICK,m_bmpbutton2,OnClickBmpButton2)
EVENT_MAP_END(CAppDialog)

CBmpButtonからのコードであり、 CControlsDialogはクラスの形式のパネルである CAppDialog クラスのインスタンスです。 

"イベント処理マップのマクロ" からマクロを考慮すると、OnEvent は次のようになります。

bool CControlsDialog::OnEvent(const int id,const long& lparam,const double& dparam,const string& sparam) {
if(id==(ON_CLICK+CHARTEVENT_CUSTOM) && lparam==m_bmpbutton1.Id()) { OnClickBmpButton1(); return(true); }
if(id==(ON_CLICK+CHARTEVENT_CUSTOM) && lparam==m_bmpbutton2.Id()) { OnClickBmpButton2(); return(true); }
return(CAppDialog::OnEvent(id,lparam,dparam,sparam)); }

適用した後:

bool CControlsDialog::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
   if(id==(ON_CLICK+CHARTEVENT_CUSTOM) && lparam==m_bmpbutton1.Id())
     {
      OnClickBmpButton1();
      return(true);
     }
   if(id==(ON_CLICK+CHARTEVENT_CUSTOM) && lparam==m_bmpbutton2.Id())
     {
      OnClickBmpButton2();
      return(true);
     }
   return(CAppDialog::OnEvent(id,lparam,dparam,sparam));
  }

生成されたコードは次のように読み取ることができます。 m_bmpbutton1 要素の click のカスタムイベントが受信されると、OnClickBmpButton1 () メソッドが呼び出されます。 m_bmpbutton2 のクリックのカスタムイベントが受信されると、OnClickBmpButton2 () が呼び出されます。

イベント処理の例

AppWindowTwoButtonsClass.mq5を使用し、ボタンクリックイベントハンドラを追加してAppWindowTwoButtonsClasssEvents.mq5を作成します。

最初のステップは、OnEvent だけでなく、 OnClickButton1 と OnClickButton2宣言することです。

//+------------------------------------------------------------------+
//| Class CControlsDialog                                            |
//| Usage: main dialog of the Controls application                   |
//+------------------------------------------------------------------+
class CAppWindowTwoButtons : public CAppDialog
  {
private:
   CButton           m_button1;                       //ボタンオブジェクト
   CButton           m_button2;                       //ボタンオブジェクト

public:
                     CAppWindowTwoButtons(void);
                    ~CAppWindowTwoButtons(void);
   //--- create
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
   //---チャートイベントハンドラ
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

protected:
   //従属コントロールの作成
   bool              CreateButton1(void);
   bool              CreateButton2(void);
   //依存コントロールイベントのハンドラ
   void              OnClickButton1(void);
   void              OnClickButton2(void);

  };

ステップ 2: OnEventメソッドは、次の形式のマクロを使用しているため、 "イベント" と "イベント処理のマップ" のファイルの [data folder]\MQL5\Include\Controls\Defines.mqhで定義します。  

protected:
   //従属コントロールの作成
   bool              CreateButton1(void);
   bool              CreateButton2(void);
   //依存コントロールイベントのハンドラ
   void              OnClickButton1(void);
   void              OnClickButton2(void);

  };
//+------------------------------------------------------------------+
//|イベントの取り扱い |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CAppWindowTwoButtons)
ON_EVENT(ON_CLICK,m_button1,OnClickButton1)
ON_EVENT(ON_CLICK,m_button2,OnClickButton2)
EVENT_MAP_END(CAppDialog)
//+------------------------------------------------------------------+
//|コンストラクタ |
//+------------------------------------------------------------------+

OnClickButton1 と OnClickButton2 のボディを書く必要があります。 ボタン1をクリックすると、買いポジションを開き、ボタン2をクリックするとポジションが決済されます。 

よって、最初のボタンのテキストを変更してみましょう (変更は CreateButton1 と CreateButton2 で実装されています):

...
   if(!m_button1.Text("Open BUY"))
      return(false);
...
...
   if(!m_button2.Text("Close"))
      return(false);
...

次に、接続する必要があるクラスを決定します。トレーディングにはCTradeクラスが必要であり、ポジションのタスクにはCPositionInfoが必要であり、トレード口座のタイプはCAccountInfoから受信されます。

#property description "Control Panels and Dialogs. Demonstration class CButton"
#include <Controls\Dialog.mqh>
#include<ControlsButton.mqh></ControlsButton.mqh>
#include<TradePositionInfo.mqh></TradePositionInfo.mqh>
#include<TradeTrade.mqh></TradeTrade.mqh>
#include<TradeAccountInfo.mqh></TradeAccountInfo.mqh>
//+------------------------------------------------------------------+
//| defines                                                          |

このクラスを使用できるようにするには、このパネルの保護されたセクションでクラスのインスタンスを宣言する必要があります。

class CAppWindowTwoButtons : public CAppDialog
  {
protected:
   CPositionInfo     m_position;                      //トレードポジションオブジェクト
   CTrade            m_trade;                         //トレーディングオブジェクト
   CAccountInfo      m_account;                       //アカウント情報ラッパー

private:
   CButton           m_button1;                       //ボタンオブジェクト

[処理方法] をクリックします。

//+------------------------------------------------------------------+
//|イベントハンドラ |
//+------------------------------------------------------------------+
void CAppWindowTwoButtons::OnClickButton1(void)
  {
   if(m_account.TradeMode()==ACCOUNT_TRADE_MODE_DEMO)
      m_trade.Buy(1.0);
  }
//+------------------------------------------------------------------+
//|イベントハンドラ |
//+------------------------------------------------------------------+
void CAppWindowTwoButtons::OnClickButton2(void)
  {
   if(m_account.TradeMode()==ACCOUNT_TRADE_MODE_DEMO)
      for(int i=PositionsTotal()-1;i>=0;i--) //現在のポジションの数を返します。
         if(m_position.SelectByIndex(i)) //プロパティへのさらなるアクセスにインデックスによるポジションを選択します。
            if(m_position.Symbol()==Symbol())
               m_trade.PositionClose(m_position.Ticket()); //指定したシンボルでポジションを閉じる
  }

デモ口座上のパネルは、トレーディングパネルとして機能します: 最初のボタンをクリックすると、買いポジションを開き、2番目のボタンをクリックすると、すべてのポジションを閉じます。


独自のパネルを作成する-超簡単

この記事では、[パネルとダイアログ] セクションからクラスの継承の一般的なスキームを紹介しました。 CAppDialog クラスの例には、標準ライブラリに基づく任意のグラフィカルパネルの作成と管理が示されています。 また、この例では、CAppDialog に基づくパネルに含まれる任意のグラフィカルオブジェクトのプロパティにアクセスする方法を示しています。 同様に、 CWndクラスの任意の子を使用することもできます。

また、この記事では、CAppDialog に基づいて内部パネルコントロールのプロパティを変更するための非標準方法を提供しています。 これらのメソッドは、グラフィカルオブジェクトの動作を理解するのに役立ちます。

この例により、CAppDialog に基づいて独自のパネルを作成するのに役立つことを願っています。 また、[パネルとダイアログ] セクションからコントロールを作成する例についても学習することをお勧めします。

ファイル名コメント
 LearnCAppDialog.mq5 CAppDialog に基づくパネルの最小コード
 AppWindowEditDefine.mq5 Defines.mqhから定数を再定義したエキスパートアドバイザパネル
 LearnCAppDialog_1.mq5 オブジェクト "m_client_area " および "m_background " の色を変更。
 LearnCAppDialog_2.mq5 Instead of CWndContainer::Delete, we apply CWndContainer::Destroy to destroy the "m_client_area" object
 AppWindowTwoButtons.mq5 その中に2つのボタンがあるパネル
 AppWindowTwoButtonsClass.mq5 クラスとして2つのボタンを持つパネル
 AppWindowCorrectMinimization.mq5 パネルのデフォルトポジションの例
 AppWindowTwoButtonsClasssEvents.mq5 クラスとして2つのボタンを持つパネル。 ボタンイベントの処理


MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/4503

添付されたファイル |
MQL5.zip (14.12 KB)
MetaTrader 5での複数銘柄残高グラフ MetaTrader 5での複数銘柄残高グラフ
本稿では、グラフィカルインターフェイスに最後のテスト結果に基づいた複数銘柄の残高グラフと預金損失率グラフを備えたMQLアプリケーションの例を示します。
グラフィカルインタフェースを通して最適化の結果を処理する グラフィカルインタフェースを通して最適化の結果を処理する
最適化結果の分析と処理についての話を展開していきます。今回の課題は、100の最良の最適化結果を選択し、それらをグラフィカルインタフェースの表に表示することです。ユーザーが最適化結果の表で列を選択しつつ、残高とドローダウンのマルチシンボルのグラフを別々に入手できるようにします。
1つのツールで複数のチャートを異なる時間枠で同期させる 1つのツールで複数のチャートを異なる時間枠で同期させる
取引の決定を行う際に、取引の過程で複数の時間枠でチャートを同時に分析する必要があることが多々あります。また、チャート上にはグラフィック分析のオブジェクトがあるため、すべてのチャートに同じオブジェクトを適用するのは不便です。この記事では、チャート上のオブジェクトの複製の自動化をご紹介したいと思います。
オシレーターでZig Zagインジケータ - を作成してみましょう。技術課題の実施例 オシレーターでZig Zagインジケータ - を作成してみましょう。技術課題の実施例
この記事では、「インジケーターの開発を依頼するための要件定義を作成する方法」の記事で書いた課題例のうちの1つである、ZigZagインジケーターの作成をデモンストレーションします。インジケーターは、オシレーターによって決められる極値に基づいて作成されます。インジケーターには、WPR、CCI、Chaikin、RSI、Stochastic Oscillatorの5つのオシレーターの中から1つを選んで使用することができます。