English Deutsch
preview
MQL5でインタラクティブなグラフィカルユーザーインターフェイスを作成する(第1回):パネルの製作

MQL5でインタラクティブなグラフィカルユーザーインターフェイスを作成する(第1回):パネルの製作

MetaTrader 5トレーディング | 28 8月 2024, 10:22
25 0
Allan Munene Mutiiria
Allan Munene Mutiiria

はじめに

MetaQuotes言語5 (MQL5)でカスタムグラフィカルユーザーインターフェイス(GUI)パネルを構築するための包括的なガイドの第1回目へようこそ。トレーダーとして、また開発者として、私たちは取引ツールの効率的でユーザーフレンドリーなインターフェイスの重要性を理解しています。本連載では、MQL5の世界に飛び込み、取引体験を向上させるパワフルなGUIパネルの作成方法を探ります。

第1回では、プロジェクトのセットアップ、パネルレイアウトのデザイン、必要なコントロールの追加といった基本的なことを説明します。第2回では、パネルをライブで、インタラクティブで、レスポンシブなものにします。この記事では、MQL5プログラマーとして経験を積んだ方でも、これからMQL5を始める方でも、機能的で視覚的に魅力的なGUIパネルを作成できるよう、ステップごとに説明します。以下のようなトピックを通じて、上記を達成します。

  1. 要素イラストレーション
  2. MQL5でGUIパネルを組み立てる
  3. 結論

この旅では、基となる統合開発環境(IDE)コーディング環境としてMetaQuotes言語5 (MQL5)を広範囲に使用し、MetaTrader 5 (MT5)取引端末でファイルを実行します。従って、上記のバージョンを持っていることが最も重要になります。始めましょう。


要素イラストレーション

本連載では、トレーダーが必要とする最も一般的なユーティリティツールを備えたGUIパネルを作成します。このように、カバーしなければならない要素は多岐にわたりますが、ここでは理解しやすいようにまとめて説明します。GUIの開発には4つの要素を使用し、これを通してGUIを作成します。このパネルでは、取引ボタン、シャープな四角形、ライブアップデート、絵文字の使用、さまざまなフォントスタイル、ラベル、移動可能なパネルパーツ、ホバーエフェクトなどが作成できます。その全体を説明するために、以下に例を挙げます。

サンプルGUI


MQL5でGUIパネルを組み立てる

パネルを作成するために、EAを基にします。 EAを作成するには、MetaTrader 5端末で[ツール]タブをクリックし、[MetaQuotes言語エディタ]を選択するか、キーボードのF4を押します。または、ツールバーのIDE(統合開発環境)アイコンをクリックすることもできます。これにより、自動売買ロボット、テクニカル指標、スクリプト、関数のライブラリを作成できるMetaQuotes言語エディタ環境が開きます。

IDE

MetaEditorを開いたら、ツールバーの[ファイル]タブで[新しいファイル]を選択するか、CTRL + Nキーを押して新規ドキュメントを開きます。または、[ツール]タブの新規アイコンをクリックすることもできます。MQLウィザードのポップアップが表示されます。

NEW EA

ウィザードが表示されたら、[EA(テンプレート)]を選択し、[次へ]をクリックします。

ウィザード

EAの一般プロパティで、[名前]フィールドにEAのファイル名を入力します。フォルダが存在しない場合にフォルダを指定または作成するには、EA名の前にバックスラッシュを使用することに注意してください。例えば、ここではデフォルトで「Experts」となっています。つまり、私たちのEAはExpertsフォルダに作成され、そこで見つけることができます。他のフィールドはごく簡単ですが、ウィザードの一番下にあるリンクから、正確な手順を知ることができます。

EA名

希望する EAファイル名を入力した後、[次へ]をクリックし、[完了]をクリックします。以上の作業を終えて、GUIパネルのコーディングとプログラミングの準備が整いました。

まず、必要な4つの要素の関数を作成する必要があります。つまり、矩形ラベル、ボタン、エディットフィールド、テキストラベルです。これは、類似のオブジェクトを作成するときにプロセス全体を繰り返す必要がなくなり、類似の関数を作成するときに同じ関数を再利用できるようになるため、非常に便利です。また、プロセスが迅速でわかりやすくなり、コードスニペットが短くなるため、多くの時間とスペースを節約できます。

矩形ラベルを作成するために、10個の引数またはパラメータを取る関数を作成します。

//+------------------------------------------------------------------+
//|     Function to create rectangle label                           |
//+------------------------------------------------------------------+

bool createRecLabel(string objName, int xD, int yD, int xS, int yS,
                    color clrBg, int widthBorder, color clrBorder = clrNONE,
                    ENUM_BORDER_TYPE borderType = BORDER_FLAT, ENUM_LINE_STYLE borderStyle = STYLE_SOLID) {

...
}

関数のシグネチャがすべてを物語っています。これはcreateRecLabelという名前のブール関数で、成功した場合と失敗した場合に、それぞれtrueかfalseの2つのブール型フラグを返すという意味です。そのパラメータを簡単に理解するために、以下にその概要を個別に説明しましょう。

  • objName:このパラメータは、矩形ラベルオブジェクトの一意な名前を表します。作成されるグラフィカル要素の識別子となります。
  • xDとyD:これらのパラメータは、矩形ラベルが配置されるコーナーからのXとYの距離を決定します。チャートに対する矩形の左上隅を定義する座標だと考えてください。
  • xSとyS:これらのパラメータは矩形の幅と高さを指定します。xS値は矩形の水平方向の幅を決定し、yS値は垂直方向の高さを制御します。

距離とサイズ

  • clrBg:矩形ラベルの背景色を表します。チャートの背景とのコントラストがよい色、または他の要素を引き立てる色を選択します。
  • widthBorder:矩形を囲む境界線の幅を定義します。境界線が必要な場合は正の値を設定し、境界線がない場合はゼロを使用します。
  • clrBorder:境界線の色を指定するオプションのパラメータです。境界線が必要な場合は、色を指定します(例えば、境界線の色がない場合はclrNONE)。
  • borderType:矩形の枠の種類を指定します。オプションには、flat、raised、その他のスタイルがあります。シンプルなflat境界線はBORDER_FLATを使用します。
  • borderStyle:flat境界線を選択した場合、このパラメータで線のスタイル(実線、破線など)を決定します。連続線にはSTYLE_SOLIDを使用します。

関数のシグネチャで、いくつかの引数がすでに何らかの値で初期化されていることに気づいたはずです。初期化値は、そのパラメータが関数呼び出し中に無視された場合に割り当てられるデフォルト値を表します。例えば、デフォルトの境界線カラーはnoneです。つまり、関数呼び出し時にカラー値が指定されなければ、矩形ラベルの境界線にはカラーが適用されません。 

中括弧({})で囲まれた関数本体の中で、オブジェクト生成プロシージャを定義します。 

    // Create a rectangle label object
    if (!ObjectCreate(0, objName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {
        Print(__FUNCTION__, ": failed to create rec label! Error code = ", _LastError);
        return (false); // Return false if object creation fails
    }

まず、if文を使用してオブジェクトが作成されていないかどうかをチェックします。ObjectCreate関数では、6つの引数を取るブール値が使用されます。この関数は、指定された名前、型、初期座標を持つオブジェクトを、指定されたチャートサブウィンドウに作成します。まず、チャートウィンドウを指定します。0は、オブジェクトがメインウィンドウ上に作成されることを意味します。次に、オブジェクト名を指定します。これは、特定のオブジェクトに一意に割り当てられる名前です。作成するオブジェクトの型はOBJ_RECTANGLE_LABELで、カスタムグラフィカルインターフェイスを作成、デザインするためのオブジェクトを意味します。次に、現在のサブウィンドウを0として、サブウィンドウを指定します。最後に、時間と価格の値は、チャートに付けるのではなく、チャートウィンドウの座標に付けるので、ゼロとして提供します。ピクセルはマッピングの設定に使用されます。

オブジェクトの作成に失敗し、最終的にObjectCreate関数がfalseを返した場合、明らかに先に進む意味がありません。この場合、エラーコードの横にエラーを操作ログに印刷し、falseを返すことでエラーを通知します。そのため、最新のエラーを取得するには、前のエラーをクリアする必要があります。これは、オブジェクト作成ロジックの直前に、MQL5内蔵関数であるResetLastError関数を呼び出すことで実現します。 

    ResetLastError(); // Reset any previous error codes

この関数の目的は、定義済み変数「_LastError」の値をゼロに設定することです。この変数には、エラーが発生した最後の操作のエラーコードが格納されています。これを呼び出すことで、次の操作に進む前に、以前のエラーコードがクリアされていることを確認します。このステップは、以前のエラー状態に干渉されることなく、新しいエラーを独立して処理することを可能にするため、不可欠です。

この時点まで戻らなければ、オブジェクトを作成したことになるので、オブジェクトのプロパティ更新を続けることができます。内蔵関数ObjectSet...のセットは、対応するオブジェクトプロパティの値を設定します。オブジェクトプロパティは、datetime型、integer型、color型、boolean型、character型のいずれかでなければなりません。

    // Set properties for the rectangle label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Rectangle background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_TYPE, borderType); // Border type
    ObjectSetInteger(0, objName, OBJPROP_STYLE, borderStyle); // Border style (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, widthBorder); // Border width (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBorder); // Border color (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Not a background object
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

最初の特性ロジックに集中しましょう。

    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner

ここでは、内蔵のObjectSetInteger関数を使用して、それぞれパラメータを渡します。パラメータは以下の通りです。

  • Chart id:チャートの識別子です。0は現在のチャート(チャートID)を指します。このチャート内のオブジェクトのプロパティを調整しています。
  • Name:objNameは、矩形ラベルオブジェクトに割り当てられた固有の名前を表します。
  • Property id:オブジェクトプロパティのIDであり、その値はENUM_OBJECT_PROPERTY_INTEGER列挙の値のいずれかです。OBJPROP_XDISTANCEは、X距離プロパティを変更することを指定します。
  • Property value:プロパティの値です。xDに代入される値は、矩形ラベルの左上隅がチャートの左端から水平方向にどのくらい右(負の場合は左)に位置するかを決定します。

同様に、他のプロパティも同じ形式で設定します。OBJPROP_YDISTANCEは矩形ラベルのY距離プロパティを設定します。yD値は、矩形ラベルの左上隅がチャートの上端から垂直方向にどのくらい離れているかを決定します。言い換えれば、チャート領域内でのラベルの垂直配置を制御します。これは隅からのY距離を設定します。OBJPROP_XSIZEとOBJPROP_YSIZEはそれぞれ矩形の幅と高さを設定します。 

オブジェクトを配置するには、OBJPROP_CORNERプロパティを使い、チャートウインドウのどの隅にオブジェクトを配置するかを決めます。

    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner

プロパティは4種類しかありません。

  • CORNER_LEFT_UPPER:座標の中心はチャートの左上隅
  • CORNER_LEFT_LOWER:座標の中心はチャートの左下隅
  • CORNER_RIGHT_LOWER:座標の中心はチャートの右下隅
  • CORNER_RIGHT_UPPER:座標の中心はチャートの右上隅

図で表現するとこうなります。

CORNERS

その他の特性は単純明快です。わかりやすいようにコメントをつけました。その後、チャートを再描画するだけで、価格相場やチャートイベントの変化を待つことなく、変更が自動的に反映されます。 

    ChartRedraw(0); // Redraw the chart

最後に、オブジェクトプロパティの作成と更新が成功したことを示すtrueを返します。

    return (true); // Return true if object creation and property settings are successful

チャートウィンドウ上に矩形オブジェクトを作成する関数コードの全容は以下の通りです。

bool createRecLabel(string objName, int xD, int yD, int xS, int yS,
                    color clrBg, int widthBorder, color clrBorder = clrNONE,
                    ENUM_BORDER_TYPE borderType = BORDER_FLAT, ENUM_LINE_STYLE borderStyle = STYLE_SOLID) {
    ResetLastError(); // Reset any previous error codes
    
    // Create a rectangle label object
    if (!ObjectCreate(0, objName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {
        Print(__FUNCTION__, ": failed to create rec label! Error code = ", _LastError);
        return (false); // Return false if object creation fails
    }
    
    // Set properties for the rectangle label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Rectangle background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_TYPE, borderType); // Border type
    ObjectSetInteger(0, objName, OBJPROP_STYLE, borderStyle); // Border style (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, widthBorder); // Border width (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBorder); // Border color (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Not a background object
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected
    
    ChartRedraw(0); // Redraw the chart
    
    return (true); // Return true if object creation and property settings are successful
}

ボタンオブジェクトを作成するには、同じ関数を使用します。カスタムボタン関数を作成するコードは以下の通りです。

//+------------------------------------------------------------------+
//|     Function to create button                                    |
//+------------------------------------------------------------------+

bool createButton(string objName, int xD, int yD, int xS, int yS,
                  string txt = "", color clrTxt = clrBlack, int fontSize = 12,
                  color clrBg = clrNONE, color clrBorder = clrNONE,
                  string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the button object
    if (!ObjectCreate(0, objName, OBJ_BUTTON, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the button! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the button
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the button
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the button
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the button
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // Border color
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Button state (not pressed)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the button
    ChartRedraw(0);

    return (true); // Button creation successful
}

コードの違いは、矩形オブジェクトはその中にテキストを取ることができませんでしたが、ボタンは、それが必要とされる場合に備えて、ボタンの機能を説明するテキストを含んでいるということです。したがって、入力パラメータには、テキストプロパティ、ここではテキスト値、色、フォントサイズ、フォント名を考慮します。ボタンの境界線タイプは静的なので、そのプロパティを取り除き、境界線の色だけを保持します。 

作成するオブジェクトタイプはOBJ_BUTTONで、ボタンのグラフィカルオブジェクトを作成することを意味します。そのアンカーポイントはピクセル単位で設定されます。境界線プロパティは、境界線カラーとして残し、残りをテキスト入力プロパティに置き換えます。

編集フィールドボタンの作成にも同じロジックが使われます。 

//+------------------------------------------------------------------+
//|     Function to create edit field                                |
//+------------------------------------------------------------------+

bool createEdit(string objName, int xD, int yD, int xS, int yS,
                string txt = "", color clrTxt = clrBlack, int fontSize = 12,
                color clrBg = clrNONE, color clrBorder = clrNONE,
                string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the edit object
    if (!ObjectCreate(0, objName, OBJ_EDIT, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the edit! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the edit field
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the edit field
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the edit field
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Default text in the edit field
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // Border color
    ObjectSetInteger(0, objName, OBJPROP_ALIGN, ALIGN_LEFT); // Text alignment (left-aligned)
    ObjectSetInteger(0, objName, OBJPROP_READONLY, false); // Edit field is not read-only
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Edit field state (not active)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the edit field
    ChartRedraw(0);

    return (true); // Edit field creation successful
}

ボタン関数を作る場合と比較して、コードの大きな違いは、まずオブジェクトの型です。OBJ_EDITを使用して、編集可能なボタンを作りたいことを示します。次に、フィールドプロパティに、水平方向のテキストアライメントプロパティを追加します。この場合、テキストを水平に左寄せにします。 

    ObjectSetInteger(0, objName, OBJPROP_ALIGN, ALIGN_LEFT); // Text alignment (left-aligned)

最後の違いは、オブジェクト内のテキストを編集できるようにするプロパティです。編集を有効にするには、プロパティOBJPROP_READONLYの値をfalseに設定します。

    ObjectSetInteger(0, objName, OBJPROP_READONLY, false); // Edit field is not read-only

残りの論点は残っています。 

最後に、テキストラベルである最後の要素の機能が必要です。テキストラベルは背景オブジェクトを必要としないので、その実装は他の関数に比べて非常に簡単です。必要なのはテキストだけなので、テキストプロパティに集中します。コードは以下の通りです。

//+------------------------------------------------------------------+
//|     Function to create text label                                |
//+------------------------------------------------------------------+

bool createLabel(string objName, int xD, int yD,
                 string txt, color clrTxt = clrBlack, int fontSize = 12,
                 string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the label object
    if (!ObjectCreate(0, objName, OBJ_LABEL, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the label! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the label
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Label state (not active)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the label
    ChartRedraw(0);

    return (true); // Label creation successful
}

このコード構造でボタンの機能と大きく異なるのは、オブジェクトのサイズと境界線のプロパティです。関数のシグネチャで、オブジェクトのサイズと境界線のプロパティを取り除きます。オブジェクトタイプをOBJ_LABELと定義し、定義されたラベル座標に従ってラベルをチャートウィンドウに描画することを示します。最後に、sizeとborderのパラメータを取り除きます。簡単なことです。 

GUIを作成するのに必要な関数が揃ったので、それらを使用してパネルを作成してみましょう。オブジェクトの名前が必要になりますが、オブジェクト名の相互作用を簡単に管理するには、マクロを定義する方がずっと簡単です。 

#define MAIN_REC "MAIN_REC"

#defineキーワードを使用して、MAIN_RECというマクロを定義し、レベルを作成するたびに名前を繰り返し再入力する代わりに、メイン矩形のベース名を簡単に保存します。これにより、時間が大幅に節約され、名前を間違って指定する可能性が減ります。基本的に、マクロはコンパイル時のテキスト置換に使用されます。

私たちのコードは、初期化インスタンスでパネルを作成したいので、EAの初期化セクションに大きく依存します。したがって、OnInitイベントハンドラがコード構造の大半を占めることになります。 

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int OnInit(){

   ...
   
   return(INIT_SUCCEEDED);
}

OnInit関数は、EAの初期化インスタンスで呼び出されるイベントハンドラであり、必要に応じて必要な初期化をおこないます。 

次に、矩形ラベルを作成する関数を呼び出し、その名前とパラメータを入力します。

   createRecLabel(MAIN_REC,10,30,250,400,clrWhite,1,clrBlack);

ここでは、マクロの定義と同じように、矩形名をMAIN_RECとします。チャートウィンドウの左上隅からX軸(日時の目盛り)までの距離は10ピクセル、Y軸(価格の目盛り)までの距離は30ピクセルです。横幅は250ピクセル、縦幅は400ピクセルです。背景色は白、境界線の幅は1、境界線の色は黒とします。ピクセルをおおよその範囲にするためには、チャートを0にスケールダウンし、2つのクロスヘア座標間のバーの数を水平スケール上のピクセル数に等しくします。例を挙げれば、こういうことです。

クロスヘア

他のパラメータは省略されており、デフォルト値が自動的に適用されます。つまり、境界線タイプはflat、ラインスタイルは連続した実線となります。まとめると、これが現在の状況です。

PANEL1

すべてのパラメータを以下のようなデフォルト値にしたとしても、結果は常に同じです。

   createRecLabel(MAIN_REC,10,30,250,400,clrWhite,1,clrBlack,BORDER_FLAT,STYLE_SOLID);

サブフレームを作成するには、同じマクロを再び明示的に宣言します。

#define MAIN_SUB_REC "MAIN_SUB_REC"

次に、同じ関数を呼び出してサブフレームを作成します。ベースパネルの枠の中にフレームを入れたいので、少し違う色を使用する必要があります。そのために、水色を使い、5ピクセルの余白をとりました。

   createRecLabel(MAIN_SUB_REC,15,35,240,390,clrLightBlue,1,clrNONE);

5ピクセルの余白が欲しいので、左から5ピクセル、上から5ピクセル押します。したがって、X軸の距離は最初の10に余白5を加えた15ピクセルになります。Y軸のスケールも同様です。つまり、サイズも5ピクセル小さくする必要がありますが、ちょっと待ってください。パネルの右側にも5ピクセルの余白が必要です。そのため、2辺で各辺5ピクセルの縮小が必要となります。したがって、必要な画素数は5×2で10画素となります。従って、サブ矩形のサイズを10ピクセル縮小すると、サブフレームの矩形の幅は250 - 10 = 240ピクセル、高さは400 - 10 = 390ピクセルとなります。以下がその結果です。

PANEL2

水色は魅力的に見えないので、濃い色にします。使用する色をよりコントロールするために、背景色をリテラルで表現します。この場合、「C'000,000,000'」という形式になり、トリプルゼロは0から255までの数字になります。形式はRGB(赤、緑、青)形式を採用します。この3つの値は、それぞれ赤、緑、青の成分を0から255までのスケールで表しています。したがって、「245,245,245」はほぼ白に近い色合いとなります。 

   createRecLabel(MAIN_SUB_REC,15,35,240,390,C'245,245,245',1,clrNONE);

より魅力的なカラーブレンドを作るために、境界線カラーをnoneに設定しました。新しいGUI要素を追加するたびにプログラムをコンパイルし、結果を確認することを常にお勧めします。以下がその結果です。

PANEL3

縦と横の境界線を作るために、さらに2つのマクロを定義します。

#define MAIN_LINE_UP "MAIN_LINE_UP"
#define MAIN_LINE_DN "MAIN_LINE_DN"

構造は同じですが、今回はraised境界線タイプを使用しています。そのため、境界線カラーの使用を無視することになり、境界の錯覚が生じます。

   createRecLabel(MAIN_LINE_UP,15,35,240,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   createRecLabel(MAIN_LINE_DN,15,35-1,1,390+1,C'245,245,245',1,clrNONE,BORDER_RAISED);

これがその結果です。

PANEL4

ここまでで、GUIパネルのフレーム、余白、境界線の設定は完了です。次に、レスポンシブボタン、タイトル、編集フィールド、ラベルなどのパネルユーティリティを、そのプロパティとエフェクトの他に追加していきます。 

まず始めに、パネルにタイトルをつけましょう。 

#define LABEL_NAME "LABEL_NAME"
...
   createLabel(LABEL_NAME,25,35,"DashBoard v1.0",clrBlue,14,"Cooper Black");

まず、タイトル名のマクロを定義し、その名前を入力してラベル作成を担当する関数を呼び出します。X軸とY軸の距離はそれぞれ25ピクセルと35ピクセルとします。選択したテキスト入力は「DashBoard v1.0」で、パネルのタイプとバージョンを最初に示します。同時に、文字色を青、フォントサイズを14、フォントの種類をCooper Blackとします。フォントの種類については、値は大文字と小文字は区別されません。大文字でも小文字でも、あるいはその混合でも影響はありません。「cooper black」でも「COOPER BLACK」でも大丈夫です。重要なのは、正しいフォント名を提供する必要があるということだけです。コンパイルを開くと、以下のような結果が得られます。

PANEL5タイトル

フォントの種類が変更できることにお気づきでしたか。音楽に砂糖を加え、その曲がどのように演奏されるかを見てみましょう。フォントの種類によっては、アイコンや絵文字が含まれているものもあります。現在、MQL5はその一部を受け入れ、取り入れています。フォントの例としては、Webdings、Wingdings、Wingdings 2、Wingdings 3があります。他にもたくさんありますが、ここでは前述のものを使用することにします。つまり、これらのアイコンや絵文字フォントを使用することで、パネルを派手にすることができるのです。これらは以下の通りです。

FONTS

パネル名の前に3つのアイコン(ハート、ツール、救急車)を追加します。もちろん、好みに応じて選ぶことができます。そのためには、アイコンの名前を保持し、後でアイコンの作成に使用するために、3つのマクロを定義する必要があります。ロジックはこうです。

#define ICON_HEART "ICON_HEART"
#define ICON_TOOL "ICON_TOOL"
#define ICON_CAR "ICON_CAR"

...
   createLabel(ICON_HEART,190,35,"Y",clrRed,15,"Webdings");

同じ関数を使い、軸の距離、色、フォントサイズを指定します。しかし、フォント名がWebdingsに変わり、テキスト値が大文字のYになっていることにお気づきでしょうか。これは、出力としてYを表示するという意味ではありません。その文字に対応するアイコンを表示します。フォントについては、文字の下のアイコンは以下の通り、ハートのアイコンです。

ハートアイコン

小文字のyと大文字のYではアイコンが異なるので、大文字と小文字は区別されます。まとめるとこうなります。 

PANEL6

他の2つのアイコンは、前のアイコンと同じ方法で追加できます。

   createLabel(ICON_TOOL,210,35,"@",clrBlue,15,"Webdings");
   createLabel(ICON_CAR,230,35,"h",clrBlack,15,"Webdings");

次に、同じ実装を使用して、他のユーティリティオブジェクトをチャートに追加します。以下はそのロジックです。

#define LINE1 "LINE1"
#define BTN_CLOSE "BTN_CLOSE"
#define BTN_MARKET "BTN_MARKET"
#define BTN_PROFIT "BTN_PROFIT"
#define BTN_LOSS "BTN_LOSS"
#define BTN_PENDING "BTN_PENDING"
#define LINE2 "LINE2"

...

   createRecLabel(LINE1,15+10,60,240-10,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   createLabel(BTN_CLOSE,25,65,"Close",clrBlack,13,"Impact");
   createLabel(BTN_MARKET,70,65,"Market",clrDarkRed,13,"Impact");
   createLabel(BTN_PROFIT,125,65,"Profit",clrGreen,13,"Impact");
   createLabel(BTN_LOSS,170,65,"Loss",clrRed,13,"Impact");
   createLabel(BTN_PENDING,205,65,"Pend'n",clrDarkGray,13,"Impact");
   createRecLabel(LINE2,15+10,87,240-10,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
  

オブジェクトのマクロ名を定義し、それぞれのカスタム関数を呼び出してオブジェクトを作成します。2本の垂直境界線のインスタンスが作成され、ラベルユーティリティボタンを挟み込みます。ラベルはClose、Market、Profit、Loss、Pendingで、枠内の文言に対応するためにPend'nに変更されています。これらはそれぞれ、すべての成行注文と未決済注文の決済、成行注文のみの決済、テイクプロフィットのみのポジションの決済、ストップロスのみのポジションの決済、未決済注文の削除を意図しています。コンパイルすると、このような結果になります。

PANEL7

ここまでで、パネルのヘッダーセクションの作成は成功しました。次にボタンユーティリティを作成します。まず、取引量ボタンに注目してみましょう。ボタンにはラベルとドロップダウンキャップがあります。

#define BTN_LOTS "BTN_LOTS"
#define LABEL_LOTS "LABEL_LOTS"
#define ICON_DROP_DN1 "ICON_DROP_DN1"

マクロの定義は終わりました。その後、button関数を呼び出してボタンを作成します。

   createButton(BTN_LOTS,25,95,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');

ここでも、ボタンのxとyの距離を、それぞれ幅130ピクセル、高さ25ピクセルで指定します。テキストに関しては、値を指定することもできたが、テキストの位置をコントロールしたかったので、空白またはNULLのままにしておきました。ボタンの背景と境界線を設定するために、最終的に文字どおりの色表現が使用されます。デフォルトのボタンラベルを省略することにしたので、以下の関数を使用して、ボタンに近接する新しいテキストラベルを作成しました。

   createLabel(LABEL_LOTS,25+10,95+5,"LotSize",clrBlack,9);

この関数はもうお馴染みで、渡されるパラメータもお分かりでしょう。ドロップダウンのアイコンには、アイコンを提供するフォントタイプを使用します。

   createLabel(ICON_DROP_DN1,130,95+5,CharToString(240),C'070,070,070',20,"Wingdings 3");

これは、文字列の代わりに対応する文字コードを提供する別の方法であり、銘柄コードをすでに知っている場合に便利です。編集フィールドボタンの作成も同じ手順でおこないます。 

#define EDIT_LOTS "EDIT_LOTS"
#define BTN_P1 "BTN_P1"
#define BTN_M1 "BTN_M1"

...

   createEdit(EDIT_LOTS,165,95,60,25,"0.01",clrBlack,14,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P1,225,95,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M1,225,95+12,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");


いつものようにマクロ名を定義し、関数を呼び出します。編集ボタンを作成するために、幅と高さはそれぞれ60ピクセルと25ピクセルのサイズを使用します。デフォルトのテキストは0.01に設定され、テキストカラーは黒、フォントサイズは14、フォントタイプはCallibriです。ボタンの背景は白に設定され、境界線カラーは濃い色に近いシェードカラーに設定されています。取引数量の増加分と減少分には、それぞれWebdingsフォントタイプとテキスト値5と6を使用します。その集大成がこのマイルストーンです。

PANEL8

これは良い進歩です。他のストップロスとテイクプロフィットのボタンユーティリティを作成するには、同じロジックが以下のコードで適用されます。 

#define BTN_SL "BTN_SL"
#define LABEL_SL "LABEL_SL"
#define ICON_DROP_DN2 "ICON_DROP_DN2"
#define EDIT_SL "EDIT_SL"
#define BTN_P2 "BTN_P2"
#define BTN_M2 "BTN_M2"

#define BTN_TP "BTN_TP"
#define LABEL_TP "LABEL_TP"
#define ICON_DROP_DN3 "ICON_DROP_DN3"
#define EDIT_TP "EDIT_TP"
#define BTN_P3 "BTN_P3"
#define BTN_M3 "BTN_M3"

...

   createButton(BTN_SL,25,95+30,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_SL,35,95+30,"SL Pips",clrBlack,14);
   createLabel(ICON_DROP_DN2,130,100+30,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_SL,165,95+30,60,25,"100.0",clrBlack,13,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P2,225,95+30,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M2,225,107+30,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");

   createButton(BTN_TP,25,95+30+30,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_TP,35,95+30+30,"TP Pips",clrBlack,14);
   createLabel(ICON_DROP_DN3,130,100+30+30,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_TP,165,95+30+30,60,25,"100.0",clrBlack,13,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P3,225,95+30+30,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M3,225,107+30+30,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   

ユーティリティマクロが定義され、その作成のためにそれぞれの関数が呼び出されます。このコードは、取引量ボタンを作成するために使用した初期とロジックに違いはありません。コンパイルすると、このような結果が得られるはずです。

PANEL 9

#define BTN_BUY "BTN_BUY"
#define LABEL_BUY "LABEL_BUY"
#define LABEL_BUY_PRICE "LABEL_BUY_PRICE"
#define BTN_OVERLAY "BTN_OVERLAY"
#define BTN_SPREAD "BTN_SPREAD"

#define BTN_SELL "BTN_SELL"
#define LABEL_SELL "LABEL_SELL"
#define LABEL_SELL_PRICE "LABEL_SELL_PRICE"

#define BTN_CONTACT "BTN_CONTACT"

...

   
   createRecLabel(BTN_SELL,25,335,105,60,clrRed,1,clrNONE);
   createLabel(LABEL_SELL,35,335,"Sell",clrWhite,15,"ARIAL black");
   createLabel(LABEL_SELL_PRICE,35,335+30,DoubleToString(Bid(),_Digits),clrWhite,13,"ARIAL black");
   createRecLabel(BTN_BUY,140,335,105,60,clrGreen,1,clrNONE);
   createLabel(LABEL_BUY,150+35,335,"Buy",clrWhite,15,"ARIAL black");
   createLabel(LABEL_BUY_PRICE,150,335+30,DoubleToString(Ask(),_Digits),clrWhite,13,"ARIAL black");
   createRecLabel(BTN_OVERLAY,90,335,90,25,C'245,245,245',0,clrNONE);
   createButton(BTN_SPREAD,95,335,80,20,(string)Spread(),clrBlack,13,clrWhite,clrBlack);
   createButton(BTN_CONTACT,25,335+62,230-10,25,"https://t.me/Forex_Algo_Trader",clrBlack,10,clrNONE,clrBlack);
   

売買ボタン、オーバーレイボタン、追加情報ボタン、スプレッドボタンを作成するために、上記のコードを実装します。変更されるのは、売値と買値のテキストとスプレッドの値だけです。Bid、Ask、Spreadという追加のカスタム関数が値を埋めるために呼び出されます。bid関数とask関数はdoubleデータ型の値を返すので、doubleを文字列に変換するために内蔵のDoubleToString関数が呼び出されます。スプレッドについては、整数値を文字列に直接型キャストします。カスタム関数は以下の通りです。

double Ask(){return(NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits));}
double Bid(){return(NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits));}
int Spread(){return((int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD));}

関数はそれぞれの銘柄情報のデータ型を返します。コンパイルすると、次のような結果が得られます。

PANEL10

次に、鋭角のボタンを作成する方法を説明するために使用する追加ボタンと、ホバー効果を自動化するために使用する複製を作成します。

#define BTN_SHARP "BTN_SHARP"
#define LABEL_SHARP "LABEL_SHARP"
#define BTN_HOVER "BTN_HOVER"
#define LABEL_HOVER "LABEL_HOVER"

...

   createRecLabel(BTN_SHARP,25,190,220,35,C'220,220,220',2,C'100,100,100');
   createLabel(LABEL_SHARP,25+20,190+5,"Sharp Edged Button",clrBlack,12,"ARIAL black");
   //createRecLabel(BTN_HOVER,25,230,220,35,C'220,220,220',3,C'050,050,255');
   createRecLabel(BTN_HOVER,25,230,220,35,C'220,220,220',3,C'100,100,100');
   createLabel(LABEL_HOVER,25+50,230+5,"Hover Effect",clrBlack,12,"ARIAL black");

以下はそのマイルストーンです。

PANEL11

他のユーティリティに使える余分なスペースがあるが、絵文字やアイコン文字で埋めましょう。

#define LABEL_EXTRA1 "LABEL_EXTRA1"
#define LABEL_EXTRA2 "LABEL_EXTRA2"
#define LABEL_EXTRA3 "LABEL_EXTRA3"
#define LABEL_EXTRA4 "LABEL_EXTRA4"

...

   createLabel(LABEL_EXTRA1,25,290,"_",clrBlack,25,"WEBDINGS");
   createLabel(LABEL_EXTRA2,25+40,290,"J",clrBlack,25,"WINGDINGS");
   createLabel(LABEL_EXTRA3,25+40+40,290,"{",clrBlack,25,"WINGDINGS 2");
   createLabel(LABEL_EXTRA4,25+40+40+40,290,"G",clrBlack,25,"WINGDINGS 3");

取引量ボタンがクリックされたら、さまざまなオプションを選択できるドロップダウンリストを作成するインスタンスを用意します。3つのオプションと、最初の作成ポイントから離れた場所にリストをドラッグできるアイコンが必要です。同じ理屈です。

#define BTN_DROP_DN "BTN_DROP_DN"
#define LABEL_OPT1 "LABEL_OPT1"
#define LABEL_OPT2 "LABEL_OPT2"
#define LABEL_OPT3 "LABEL_OPT3"
#define ICON_DRAG "ICON_DRAG"

...

void createDropDown(){
   createRecLabel(BTN_DROP_DN,25,95+25,130,70,clrWhite,2,clrBlack);
   createLabel(LABEL_OPT1,25+10,95+25,"LotSize",clrBlack,12,"stencil");
   createLabel(LABEL_OPT2,25+10,95+25+20,"Risk Percent %",clrBlack,12,"calibri Italic");
   createLabel(LABEL_OPT3,25+10,95+25+20+20,"Money Balance",clrBlack,12,"Arial bold");
   createLabel(ICON_DRAG,25+10+95,95+25,"d",clrRoyalBlue,15,"webdings");
}

ここでは、カスタム関数の中にボタンとラベルを作成し、取引量がクリックされたら関数を呼び出すようにしています。しかし、ユーティリティの位置を表示するために、関数をコールするが、コールされた関数は後でコメントアウトします。

   createDropDown();

最終的なマイルストーンは以下の通りです。

PANEL12.最終パート1

最後に、EAがチャートから削除されたら、作成したオブジェクトを破棄して削除する必要があります。これを実現するために、作成されたオブジェクトを削除する別の関数を描きます。

void destroyPanel(){
   ObjectDelete(0,MAIN_REC);
   ObjectDelete(0,MAIN_SUB_REC);
   ObjectDelete(0,MAIN_LINE_UP);
   
   //... other objects
   
   ChartRedraw(0);
}

voidカスタム関数は、何も返さないことを意味します。渡されたそれぞれのオブジェクトを削除するには、組み込み関数ObjectDeleteを使用します。これは2つの引数、チャートID、現在のチャートの場合は0、そして削除するオブジェクトの名前を取ります。これは、EAの初期化解除機能中に呼び出されます。

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
//---
   destroyPanel();
}

以下は、MQL5 forMetaTrader 5 (MT5)に示されているGUIパネルの作成を担当する完全なソースコードです。

//+------------------------------------------------------------------+
//|                                             DASHBOARD PART 1.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

//--- DEFINE MACRO PROPERTIES

#define MAIN_REC "MAIN_REC"
#define MAIN_SUB_REC "MAIN_SUB_REC"
#define MAIN_LINE_UP "MAIN_LINE_UP"
#define MAIN_LINE_DN "MAIN_LINE_DN"
#define LABEL_NAME "LABEL_NAME"
#define ICON_HEART "ICON_HEART"
#define ICON_TOOL "ICON_TOOL"
#define ICON_CAR "ICON_CAR"
#define LINE1 "LINE1"
#define BTN_CLOSE "BTN_CLOSE"
#define BTN_MARKET "BTN_MARKET"
#define BTN_PROFIT "BTN_PROFIT"
#define BTN_LOSS "BTN_LOSS"
#define BTN_PENDING "BTN_PENDING"
#define LINE2 "LINE2"

#define BTN_LOTS "BTN_LOTS"
#define LABEL_LOTS "LABEL_LOTS"
#define ICON_DROP_DN1 "ICON_DROP_DN1"
#define EDIT_LOTS "EDIT_LOTS"
#define BTN_P1 "BTN_P1"
#define BTN_M1 "BTN_M1"

#define BTN_SL "BTN_SL"
#define LABEL_SL "LABEL_SL"
#define ICON_DROP_DN2 "ICON_DROP_DN2"
#define EDIT_SL "EDIT_SL"
#define BTN_P2 "BTN_P2"
#define BTN_M2 "BTN_M2"

#define BTN_TP "BTN_TP"
#define LABEL_TP "LABEL_TP"
#define ICON_DROP_DN3 "ICON_DROP_DN3"
#define EDIT_TP "EDIT_TP"
#define BTN_P3 "BTN_P3"
#define BTN_M3 "BTN_M3"

#define BTN_BUY "BTN_BUY"
#define LABEL_BUY "LABEL_BUY"
#define LABEL_BUY_PRICE "LABEL_BUY_PRICE"
#define BTN_OVERLAY "BTN_OVERLAY"
#define BTN_SPREAD "BTN_SPREAD"

#define BTN_SELL "BTN_SELL"
#define LABEL_SELL "LABEL_SELL"
#define LABEL_SELL_PRICE "LABEL_SELL_PRICE"

#define BTN_CONTACT "BTN_CONTACT"

#define BTN_SHARP "BTN_SHARP"
#define LABEL_SHARP "LABEL_SHARP"
#define BTN_HOVER "BTN_HOVER"
#define LABEL_HOVER "LABEL_HOVER"

#define LABEL_EXTRA1 "LABEL_EXTRA1"
#define LABEL_EXTRA2 "LABEL_EXTRA2"
#define LABEL_EXTRA3 "LABEL_EXTRA3"
#define LABEL_EXTRA4 "LABEL_EXTRA4"

#define BTN_DROP_DN "BTN_DROP_DN"
#define LABEL_OPT1 "LABEL_OPT1"
#define LABEL_OPT2 "LABEL_OPT2"
#define LABEL_OPT3 "LABEL_OPT3"
#define ICON_DRAG "ICON_DRAG"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int OnInit(){

   createRecLabel(MAIN_REC,10,30,250,400,clrWhite,1,clrBlack);
   createRecLabel(MAIN_SUB_REC,15,35,240,390,C'245,245,245',1,clrNONE);
   createRecLabel(MAIN_LINE_UP,15,35,240,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   createRecLabel(MAIN_LINE_DN,15,35-1,1,390+1,C'245,245,245',1,clrNONE,BORDER_RAISED);

   createLabel(LABEL_NAME,25,35,"DashBoard v1.0",clrBlue,14,"Cooper Black");
   
   createLabel(ICON_HEART,190,35,"Y",clrRed,15,"Webdings");
   createLabel(ICON_TOOL,210,35,"@",clrBlue,15,"Webdings");
   createLabel(ICON_CAR,230,35,"h",clrBlack,15,"Webdings");
   createRecLabel(LINE1,15+10,60,240-10,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   createLabel(BTN_CLOSE,25,65,"Close",clrBlack,13,"Impact");
   createLabel(BTN_MARKET,70,65,"Market",clrDarkRed,13,"Impact");
   createLabel(BTN_PROFIT,125,65,"Profit",clrGreen,13,"Impact");
   createLabel(BTN_LOSS,170,65,"Loss",clrRed,13,"Impact");
   createLabel(BTN_PENDING,205,65,"Pend'n",clrDarkGray,13,"Impact");
   createRecLabel(LINE2,15+10,87,240-10,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   
   createButton(BTN_LOTS,25,95,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_LOTS,25+10,95+5,"LotSize",clrBlack,9);
   //createLabel(ICON_DROP_DN1,150,75,CharToString(100),clrBlack,12,"Wingdings");
   createLabel(ICON_DROP_DN1,130,95+5,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_LOTS,165,95,60,25,"0.01",clrBlack,14,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P1,225,95,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M1,225,95+12,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");

   createButton(BTN_SL,25,95+30,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_SL,35,95+30,"SL Pips",clrBlack,14);
   createLabel(ICON_DROP_DN2,130,100+30,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_SL,165,95+30,60,25,"100.0",clrBlack,13,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P2,225,95+30,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M2,225,107+30,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");

   createButton(BTN_TP,25,95+30+30,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_TP,35,95+30+30,"TP Pips",clrBlack,14);
   createLabel(ICON_DROP_DN3,130,100+30+30,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_TP,165,95+30+30,60,25,"100.0",clrBlack,13,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P3,225,95+30+30,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M3,225,107+30+30,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   
   createRecLabel(BTN_SELL,25,335,105,60,clrRed,1,clrNONE);
   createLabel(LABEL_SELL,35,335,"Sell",clrWhite,15,"ARIAL black");
   createLabel(LABEL_SELL_PRICE,35,335+30,DoubleToString(Bid(),_Digits),clrWhite,13,"ARIAL black");
   createRecLabel(BTN_BUY,140,335,105,60,clrGreen,1,clrNONE);
   createLabel(LABEL_BUY,150+35,335,"Buy",clrWhite,15,"ARIAL black");
   createLabel(LABEL_BUY_PRICE,150,335+30,DoubleToString(Ask(),_Digits),clrWhite,13,"ARIAL black");
   createRecLabel(BTN_OVERLAY,90,335,90,25,C'245,245,245',0,clrNONE);
   createButton(BTN_SPREAD,95,335,80,20,(string)Spread(),clrBlack,13,clrWhite,clrBlack);
   createButton(BTN_CONTACT,25,335+62,230-10,25,"https://t.me/Forex_Algo_Trader",clrBlack,10,clrNONE,clrBlack);
   
   createRecLabel(BTN_SHARP,25,190,220,35,C'220,220,220',2,C'100,100,100');
   createLabel(LABEL_SHARP,25+20,190+5,"Sharp Edged Button",clrBlack,12,"ARIAL black");
   //createRecLabel(BTN_HOVER,25,230,220,35,C'220,220,220',3,C'050,050,255');
   createRecLabel(BTN_HOVER,25,230,220,35,C'220,220,220',3,C'100,100,100');
   createLabel(LABEL_HOVER,25+50,230+5,"Hover Effect",clrBlack,12,"ARIAL black");

   createLabel(LABEL_EXTRA1,25,290,"_",clrBlack,25,"WEBDINGS");
   createLabel(LABEL_EXTRA2,25+40,290,"J",clrBlack,25,"WINGDINGS");
   createLabel(LABEL_EXTRA3,25+40+40,290,"{",clrBlack,25,"WINGDINGS 2");
   createLabel(LABEL_EXTRA4,25+40+40+40,290,"G",clrBlack,25,"WINGDINGS 3");
   
   // createDropDown();
   
   return(INIT_SUCCEEDED);
}

double Ask(){return(NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits));}
double Bid(){return(NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits));}
int Spread(){return((int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD));}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
//---
   destroyPanel();
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

}
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|     Function to create rectangle label                           |
//+------------------------------------------------------------------+

bool createRecLabel(string objName, int xD, int yD, int xS, int yS,
                    color clrBg, int widthBorder, color clrBorder = clrNONE,
                    ENUM_BORDER_TYPE borderType = BORDER_FLAT, ENUM_LINE_STYLE borderStyle = STYLE_SOLID) {
    ResetLastError(); // Reset any previous error codes
    
    // Create a rectangle label object
    if (!ObjectCreate(0, objName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {
        Print(__FUNCTION__, ": failed to create rec label! Error code = ", _LastError);
        return (false); // Return false if object creation fails
    }
    
    // Set properties for the rectangle label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Rectangle background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_TYPE, borderType); // Border type
    ObjectSetInteger(0, objName, OBJPROP_STYLE, borderStyle); // Border style (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, widthBorder); // Border width (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBorder); // Border color (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Not a background object
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected
    
    ChartRedraw(0); // Redraw the chart
    
    return (true); // Return true if object creation and property settings are successful
}

//+------------------------------------------------------------------+
//|     Function to create button                                    |
//+------------------------------------------------------------------+

bool createButton(string objName, int xD, int yD, int xS, int yS,
                  string txt = "", color clrTxt = clrBlack, int fontSize = 12,
                  color clrBg = clrNONE, color clrBorder = clrNONE,
                  string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the button object
    if (!ObjectCreate(0, objName, OBJ_BUTTON, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the button! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the button
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the button
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the button
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the button
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // Border color
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Button state (not pressed)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the button
    ChartRedraw(0);

    return (true); // Button creation successful
}

//+------------------------------------------------------------------+
//|     Function to create edit field                                |
//+------------------------------------------------------------------+

bool createEdit(string objName, int xD, int yD, int xS, int yS,
                string txt = "", color clrTxt = clrBlack, int fontSize = 12,
                color clrBg = clrNONE, color clrBorder = clrNONE,
                string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the edit object
    if (!ObjectCreate(0, objName, OBJ_EDIT, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the edit! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the edit field
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the edit field
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the edit field
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Default text in the edit field
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // Border color
    ObjectSetInteger(0, objName, OBJPROP_ALIGN, ALIGN_LEFT); // Text alignment (left-aligned)
    ObjectSetInteger(0, objName, OBJPROP_READONLY, false); // Edit field is not read-only
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Edit field state (not active)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the edit field
    ChartRedraw(0);

    return (true); // Edit field creation successful
}

//+------------------------------------------------------------------+
//|     Function to create text label                                |
//+------------------------------------------------------------------+

bool createLabel(string objName, int xD, int yD,
                 string txt, color clrTxt = clrBlack, int fontSize = 12,
                 string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the label object
    if (!ObjectCreate(0, objName, OBJ_LABEL, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the label! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the label
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Label state (not active)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the label
    ChartRedraw(0);

    return (true); // Label creation successful
}

//+------------------------------------------------------------------+
//|     Function to create the drop down utilities                   |
//+------------------------------------------------------------------+

void createDropDown(){
   createRecLabel(BTN_DROP_DN,25,95+25,130,70,clrWhite,2,clrBlack);
   createLabel(LABEL_OPT1,25+10,95+25,"LotSize",clrBlack,12,"stencil");
   createLabel(LABEL_OPT2,25+10,95+25+20,"Risk Percent %",clrBlack,12,"calibri Italic");
   createLabel(LABEL_OPT3,25+10,95+25+20+20,"Money Balance",clrBlack,12,"Arial bold");
   createLabel(ICON_DRAG,25+10+95,95+25,"d",clrRoyalBlue,15,"webdings");
}

//+------------------------------------------------------------------+
//|    Function to destroy the entire GUI Panel                      |
//+------------------------------------------------------------------+

void destroyPanel(){
   ObjectDelete(0,MAIN_REC);
   ObjectDelete(0,MAIN_SUB_REC);
   ObjectDelete(0,MAIN_LINE_UP);
   ObjectDelete(0,MAIN_LINE_DN);
   ObjectDelete(0,BTN_LOTS);
   ObjectDelete(0,LABEL_NAME);
   ObjectDelete(0,LABEL_LOTS);
   ObjectDelete(0,ICON_HEART);
   ObjectDelete(0,ICON_TOOL);
   ObjectDelete(0,ICON_CAR);
   ObjectDelete(0,ICON_DROP_DN1);
   ObjectDelete(0,LINE1);
   ObjectDelete(0,BTN_CLOSE);
   ObjectDelete(0,BTN_MARKET);
   ObjectDelete(0,BTN_PROFIT);
   ObjectDelete(0,BTN_LOSS);
   ObjectDelete(0,BTN_PENDING);
   ObjectDelete(0,LINE2);
   ObjectDelete(0,EDIT_LOTS);
   ObjectDelete(0,BTN_P1);
   ObjectDelete(0,BTN_M1);
   
   ObjectDelete(0,BTN_SL);
   ObjectDelete(0,LABEL_SL);
   ObjectDelete(0,ICON_DROP_DN2);
   ObjectDelete(0,EDIT_SL);
   ObjectDelete(0,BTN_P2);
   ObjectDelete(0,BTN_M2);
   
   ObjectDelete(0,BTN_TP);
   ObjectDelete(0,LABEL_TP);
   ObjectDelete(0,ICON_DROP_DN3);
   ObjectDelete(0,EDIT_TP);
   ObjectDelete(0,BTN_P3);
   ObjectDelete(0,BTN_M3);
   
   ObjectDelete(0,BTN_BUY);
   ObjectDelete(0,LABEL_BUY);
   ObjectDelete(0,LABEL_BUY_PRICE);
   ObjectDelete(0,BTN_OVERLAY);
   ObjectDelete(0,BTN_SPREAD);
   
   ObjectDelete(0,BTN_SELL);
   ObjectDelete(0,LABEL_SELL);
   ObjectDelete(0,LABEL_SELL_PRICE);
   
   ObjectDelete(0,BTN_CONTACT);
   
   ObjectDelete(0,BTN_SHARP);
   ObjectDelete(0,LABEL_SHARP);
   ObjectDelete(0,BTN_HOVER);
   ObjectDelete(0,LABEL_HOVER);
   
   ObjectDelete(0,LABEL_EXTRA1);
   ObjectDelete(0,LABEL_EXTRA2);
   ObjectDelete(0,LABEL_EXTRA3);
   ObjectDelete(0,LABEL_EXTRA4);
   
   ObjectDelete(0,BTN_DROP_DN);
   ObjectDelete(0,LABEL_OPT1);
   ObjectDelete(0,LABEL_OPT2);
   ObjectDelete(0,LABEL_OPT3);
   ObjectDelete(0,ICON_DRAG);
   
   ChartRedraw(0);
}


結論

結論として、GUIパネルの作成は認識されているほど複雑ではないことがお分かりいただけたでしょう。このプロセスには、パネル寸法の定義、つまり絶対座標またはチャート相対座標を使用できるパネルの位置、サイズ、外観の決定から、ボタン、ラベル、編集フィールド、矩形ラベルなどの様々なグラフィカルオブジェクトの作成、それらのプロパティ(色、テキスト、フォントなど)の指定、パネルの作成とユーザーインタラクションのためのイベントハンドラへの実装までの一連のステップが含まれます。

この第1回の焦点はパネルを作成することでした。第2回は、パネルが反応するようにすることで、パネルに命を吹き込みます。クリック時にボタンが反応するようにしたり、ティックごとに価格相場を更新したり、ドロップダウンリストをドラッグできるようにしたり、ボタンにホバーエフェクトを追加したりするなどです。この記事がGUIパネルの作成に役立てば幸いです。ここで説明した知識は、より複雑で派手なGUIパネルを作成する際にも利用できます。


MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/15205

添付されたファイル |
PatchTST機械学習アルゴリズムによる24時間の値動きの予測 PatchTST機械学習アルゴリズムによる24時間の値動きの予測
この記事では、PatchTSTと呼ばれる2023年にリリースされた比較的複雑なニューラルネットワークアルゴリズムを適用し、今後24時間の値動きを予測します。公式リポジトリを使用し、若干の修正を加え、EURUSDのモデルを訓練し、PythonとMQL5の両方で将来の予測をおこなうために適用します。
母集団最適化アルゴリズム:クジラ最適化アルゴリズム(WOA) 母集団最適化アルゴリズム:クジラ最適化アルゴリズム(WOA)
(WOA)は、ザトウクジラの行動と狩猟戦略に着想を得たメタヒューリスティクスアルゴリズムです。WOAの主なアイデアは、クジラが獲物の周囲に泡を作り、螺旋状の動きで獲物に襲いかかる、いわゆる「バブルネット」と呼ばれる捕食方法を模倣することです。
データサイエンスと機械学習(第25回):回帰型ニューラルネットワーク(RNN)を用いたFX時系列予測 データサイエンスと機械学習(第25回):回帰型ニューラルネットワーク(RNN)を用いたFX時系列予測
回帰型ニューラルネットワーク(Recurrent Neural Network: RNN)は、過去の情報を活用して将来の出来事を予測することに優れています。その驚くべき予測能力は、さまざまな領域で応用され、大きな成功を収めています。この記事では、外為市場のトレンドを予測するためにRNNモデルを導入し、外為取引における予測精度を高める可能性を示します。
知っておくべきMQL5ウィザードのテクニック(第25回):多時間枠のテストと取引 知っておくべきMQL5ウィザードのテクニック(第25回):多時間枠のテストと取引
アセンブリクラスで使用されているMQL5コードアーキテクチャの制限によって、複数の時間枠に基づく戦略は、デフォルトではウィザードで組み立てられたEAではテストできません。今回は、二次移動平均を使用したケーススタディで、複数の時間枠を使用する戦略について、この制限を回避する可能性を探ります。