English Русский Deutsch
preview
MQL5で取引管理者パネルを作成する(第3回):テーマ管理のための組み込みクラスの拡張(II)

MQL5で取引管理者パネルを作成する(第3回):テーマ管理のための組み込みクラスの拡張(II)

MetaTrader 5 | 17 12月 2024, 07:26
144 0
Clemence Benjamin
Clemence Benjamin

内容


はじめに

MQL5ではライブラリクラスを変更したり新規作成したりすることが可能です。ただし、組み込みライブラリはプラットフォームによって共有されるため、これらのファイルに変更を加えると、現在のプラットフォーム機能にプラスの影響を与えることも、マイナスの影響を与えることもあります。最近の記事では、パネルの外観に影響を与えるためにルートDialogクラスの色を編集する方法について簡単に説明しました。テーマ切り替えボタンはテキストの色を正常に変更しましたが、パネルのスキンやボタンの背景色は変更されませんでした。

調査を通じて、テーマ変更機能を利用可能なクラスに安全に統合する方法をようやく特定しました。これらの変更が正常に実装された後、新しく統合された機能に合わせて管理パネルのアルゴリズムを調整しました。

新しいパネルテーマ

テーマの切り替えに成功した

本日のディスカッションでは、右側に表示されている視覚的に魅力的なパネルを実現するためにおこなったプロセスに焦点を当てます。表示されるテーマの色は、開発中の色の選択に関する私の意見に基づいています。他のユーザーの好みに合わせてコード内で最適化できるため、さまざまな色を試して、自分に合った色を見つけることができます。パネルの全体的な機能に貢献するプログラムの主要コンポーネントを強調することが重要です。

以下にリストします。

  • テキストの色
  • ボタンのスキンの色
  • 境界
  • 背景色

基本的に、これらが私たちのプログラムの最も目立つ特徴です。テーマの変更をトリガーすると、各コンポーネントは表示プロパティを変更して、コードで定義されている目的の色を表示する必要があります。このディスカッションの最後までに、このプロジェクトで実証されているように、インターフェイスを操作するときに利用可能なクラスを変更および拡張するために必要なスキルを習得できるようにすることを目指しています。 

MQL5のクラスについて

専門家と初心者の両方が理解できるように、まずはMQL5で使用されているクラスの概念を皆さんに理解してもらいたいと思います。以下は、このプログラミング環境内でクラスがどのように機能するかを理解するのに役立つ定義と主要な概念です。

クラス

クラスはMQL5のオブジェクト指向プログラミング(OOP)の基盤であり、開発者は関連する変数(属性)と関数(メソッド)を1つのユニットにグループ化して、プログラム内の複雑な概念や動作を表すことができます。

クラスを2つに分割します。

  1. 属性: クラスのオブジェクトの状態またはデータを格納する変数
  2. メソッド: クラスのオブジェクトの動作やアクションを定義する関数

クラスの主な特徴の概要

  • クラス内のカプセル化には、データ(変数)とそのデータを操作するメソッド(関数)をバンドルすることが含まれており、外部からのアクセスや誤用から保護されます。
  • 継承により、クラスは別のクラスからプロパティとメソッドを継承できるようになり、コードの再利用が促進され、階層構造が作成されます。
  • ポリモーフィズムによりメソッドのオーバーライドが可能になり、サブクラスが親クラスで既に定義されているメソッドの特定の実装を提供できるようになります。
  • 抽象化により、関連するデータとメソッドのみに焦点を当て、不要な詳細をユーザーから隠すことで、複雑なシステムのモデリングが簡素化されます。
プロジェクトに役立つGUIクラスを含むMetaQuotesヘッダーファイルにアクセスするには、これらのファイルを見つける方法を示す次の画像を参照してください。

MQヘッダーファイルの検索

MQL5ヘッダーファイルの場所


クラスとその構造を実用的な観点から明確に理解できるように、典型的なMQL5クラスソースの抜粋を使用しました。以下のコードスニペットを参照してください。そのすぐ下に表形式でその構造を説明しています。

//Basic parts of a class.

class CDialog : public CWndContainer
{
public:
   // Constructor and Destructor (Methods)
   CDialog(void);   // Constructor
   ~CDialog(void);  // Destructor

   // Public Methods (Functions)
   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);
   string Caption(void) const;
   bool Caption(const string text);
   bool Add(CWnd *control);   // Add control by pointer
   bool Add(CWnd &control);   // Add control by reference
   virtual bool Save(const int file_handle);
   virtual bool Load(const int file_handle);
   void UpdateThemeColors(bool darkTheme);

protected:
   // Attributes (Variables)
   bool m_panel_flag;        // Panel visibility flag
   bool m_minimized;         // Minimized state flag
   CWnd m_caption;           // Caption control
   CWnd m_client_area;       // Client area control
   CRect m_norm_rect;        // Normal (non-minimized) rectangle
   CRect m_min_rect;         // Minimized rectangle
   CWnd m_white_border;      // White border control

   // Protected Methods (Internal functions)
   virtual bool CreateWhiteBorder(void);
   virtual bool CreateBackground(void);
   virtual bool CreateCaption(void);
   virtual bool CreateButtonClose(void);
   virtual bool CreateClientArea(void);
   virtual void OnClickCaption(void);
   virtual void OnClickButtonClose(void);
   virtual bool OnDialogDragStart(void);
   virtual bool OnDialogDragProcess(void);
   virtual bool OnDialogDragEnd(void);
};

この表は、上記のコードスニペットで使用可能な属性とその説明をまとめたものです。

属性(プロパティ) 詳細
bool m_panel_flag;

 パネルが表示されているかどうかを示すフラグ
bool m_minimized;

 ダイアログが最小化されているかどうかを示すフラグ
CWnd m_caption;

キャプションテキストのコントロール
CWnd m_client_area;

他の要素が存在するクライアント領域のコントロール
CRect m_norm_rect;

通常(最小化されていない)状態の座標
CRect m_min_rect;

最小化された状態の座標
CWnd m_white_border;

ダイアログの周囲の白い境界線を制御

この表は、サンプルクラスコードで使用されるメソッドをまとめたものです。

 メソッド 詳細
CDialog(void)
ダイアログを初期化するコンストラクタ
~CDialog(void)
リソースをクリーンアップするためのデストラクタ
Create(...)

ダイアログウィンドウとそのコントロールを作成する
 
OnEvent(...)

 ダイアログのチャートイベントを処理する
Caption(void)

現在のキャプションテキストを返す
Caption(const string text)

キャプションのテキストを設定する
Add(CWnd *control)

ポインタによってクライアント領域にコントロールを追加する
Add(CWnd &control)

参照によってクライアント領域にコントロールを追加する
Save(const int file_handle)

ダイアログの状態をファイルに保存する
Load(const int file_handle)

ファイルからダイアログの状態を読み込む
UpdateThemeColors(bool darkTheme)

テーマの色(暗い色または明るい色)を更新する
CreateWhiteBorder(void)
ダイアログの白い境界線を作成する
 
CreateBackground(void)
  ダイアログの背景を作成する
 
CreateCaption(void)

  キャプション領域を作成する
 
CreateButtonClose(void)
閉じるボタンを作成する  
 
CreateClientArea(void)

 クライアント領域を作成する
 
OnClickCaption(void)
  キャプションのクリックイベントを処理する
 
OnClickButtonClose(void)

  閉じるボタンのクリックイベントを処理する
 
OnDialogDragStart(void)

  ダイアログドラッグイベントの開始を処理する
 
OnDialogDragProcess(void)

 ダイアログドラッグプロセスを処理する
 
OnDialogDragEnd(void)
   ダイアログドラッグイベントの終了を処理する

以下では、プログラムで使用している主要なクラスの1つを簡単に見てみましょう。 


CDialog、CEdit、CButtonへのテーマ管理メソッドの追加

これで、テーマ切り替えという目標を達成するために実装する必要がある方法をより明確に理解できたと思います。Dialogライブラリにはすでに必要な基本的な機能が含まれているため、次のステップでは必要なメソッドを組み込むことになります。


CDialogテーマ管理メソッド


CDialog

MQL5のCDialogクラスは、MetaTrader 5プラットフォーム内でカスタムグラフィカルダイアログウィンドウまたはパネルを作成および管理する役割を担います。これにより、開発者はキャプション、クライアント領域、境界線、閉じるボタンなどのUIコンポーネントを含むダイアログボックスを構築できます。このクラスは、ダイアログのクリックやドラッグなどのユーザー操作や、テーマの動的な更新(ダークモードとライトモードの切り替えなど)を処理します。さらに、ダイアログの状態を保存および読み込むメソッドも提供し、ダイアログのサイズ、位置、最小化ステータスが保持されるようにします。ボタンやテキストフィールドなどのコントロールをダイアログに追加できるため、取引アプリケーションでインタラクティブで視覚的に魅力的なインターフェイスを構築するための多目的ツールになります。

CDialogクラスでは、動的なテーマの更新を処理するためのメソッドを導入しました。 このメソッドは、darkThemeがアクティブかどうかに基づいて、ダイアログの外観を更新します。ここでは、メソッドがどのように組み込まれ、CDialogクラスの他のコンポーネントとどのように結び付けられるかを示します。2つのステップで説明します。ただし、色を定義するつもりがない場合は、最初の手順をスキップすることを検討してください。

ステップ1:テーマカラーを定義する

テーマの変更が呼び出されたときにプログラムが代替案を認識できるように、色を定義する必要があります。この実装では、メソッドは、暗いテーマと明るいテーマの両方に特定の色の定義を使用します。これらは、事前定義された定数、または渡されたパラメータである可能性があります。    

// Theme colors that can be defined elsewhere in our program
const color DARK_THEME_BG = clrBlack;
const color DARK_THEME_BORDER = clrGray;
const color LIGHT_THEME_BG = clrWhite;
const color LIGHT_THEME_BORDER = clrSilver;


ステップ2:テーマカラーの更新メソッド

この関数は、darkThemeがアクティブかどうか(trueまたはfalse)を確認し、それぞれの色を主要コンポーネントに適用します。白い境界線(m_white_border)は背景色と境界線色の両方で更新され、背景(m_background)は背景色と境界線色を調整し、キャプション(m_caption)はタイトルバーのテキストと背景色を変更し、クライアント領域(m_client_area)はクライアント領域に色の変更を適用します。最後に、関数はRedraw()を呼び出して、オブジェクトを再作成せずに新しいテーマが視覚的に適用されるようにします。手順2にスキップした場合、強調表示された色の定義は機能せず、色はClrBlackやClrBlueなどのように入力する必要があります。


//+------------------------------------------------------------------+
//| Method for dynamic theme updates                                 |
//+------------------------------------------------------------------+


void CDialog::UpdateThemeColors(bool darkTheme)
{
   color backgroundColor = darkTheme ? DARK_THEME_BG : LIGHT_THEME_BG;
   color borderColor = darkTheme ? DARK_THEME_BORDER : LIGHT_THEME_BORDER;

   // Update White Border colors
   m_white_border.ColorBackground(backgroundColor);
   m_white_border.ColorBorder(borderColor);

   // Update Background colors
   m_background.ColorBackground(backgroundColor);
   m_background.ColorBorder(borderColor);

   // Update Caption colors (optional for text-based themes)
   m_caption.Color(darkTheme ? clrWhite : clrBlack);
   m_caption.ColorBackground(backgroundColor);

   // Update Client Area colors
   m_client_area.ColorBackground(backgroundColor);
   m_client_area.ColorBorder(borderColor);

   // Redraw the controls to reflect the theme changes
   Redraw();
}


CButtonクラステーマ管理

上記と同じ用語を使用して、CButtonクラスにSetTextColor、SetBackgroundColor、SetBorderColorメソッドを追加しました。これらのメソッドを使用すると、ボタンのテキスト、背景、境界線の色をそれぞれ設定できます。以下はメソッドの実装を示すコードスニペットです。

 //--- theme methods
   void              SetTextColor(color clr)       { m_button.Color(clr);                           }
   void              SetBackgroundColor(color clr) { m_button.BackColor(clr);                       }
   void              SetBorderColor(color clr)     { m_button.BorderColor(clr);                     }

MQL5からのCButtonデフォルトプログラム

//+------------------------------------------------------------------+
//|                                                       Button.mqh |
//|                             Copyright 2000-2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "WndObj.mqh"
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//+------------------------------------------------------------------+
//| Class CButton                                                    |
//| Usage: control that is displayed by                              |
//|             the CChartObjectButton object                        |
//+------------------------------------------------------------------+
class CButton : public CWndObj
  {
private:
   CChartObjectButton m_button;             // chart object

public:
                     CButton(void);
                    ~CButton(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);
   //--- state
   bool              Pressed(void)          const { return(m_button.State());                       }
   bool              Pressed(const bool pressed)  { return(m_button.State(pressed));                }
   //--- properties
   bool              Locking(void)          const { return(IS_CAN_LOCK);                            }
   void              Locking(const bool flag);

protected:
   //--- handlers of object settings
   virtual bool      OnSetText(void)              { return(m_button.Description(m_text));           }
   virtual bool      OnSetColor(void)             { return(m_button.Color(m_color));                }
   virtual bool      OnSetColorBackground(void)   { return(m_button.BackColor(m_color_background)); }
   virtual bool      OnSetColorBorder(void)       { return(m_button.BorderColor(m_color_border));   }
   virtual bool      OnSetFont(void)              { return(m_button.Font(m_font));                  }
   virtual bool      OnSetFontSize(void)          { return(m_button.FontSize(m_font_size));         }
   //--- internal event handlers
   virtual bool      OnCreate(void);
   virtual bool      OnShow(void);
   virtual bool      OnHide(void);
   virtual bool      OnMove(void);
   virtual bool      OnResize(void);
   //--- íîâûå îáðàáîò÷èêè
   virtual bool      OnMouseDown(void);
   virtual bool      OnMouseUp(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CButton::CButton(void)
  {
   m_color           =CONTROLS_BUTTON_COLOR;
   m_color_background=CONTROLS_BUTTON_COLOR_BG;
   m_color_border    =CONTROLS_BUTTON_COLOR_BORDER;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CButton::~CButton(void)
  {
  }
//+------------------------------------------------------------------+
//| Create a control                                                 |
//+------------------------------------------------------------------+
bool CButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
//--- call method of the parent class
   if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
//--- create the chart object
   if(!m_button.Create(chart,name,subwin,x1,y1,Width(),Height()))
      return(false);
//--- call the settings handler
   return(OnChange());
  }
//+------------------------------------------------------------------+
//| Locking flag                                                     |
//+------------------------------------------------------------------+
void CButton::Locking(const bool flag)
  {
   if(flag)
      PropFlagsSet(WND_PROP_FLAG_CAN_LOCK);
   else
      PropFlagsReset(WND_PROP_FLAG_CAN_LOCK);
  }
//+------------------------------------------------------------------+
//| Create object on chart                                           |
//+------------------------------------------------------------------+
bool CButton::OnCreate(void)
  {
//--- create the chart object by previously set parameters
   return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height()));
  }
//+------------------------------------------------------------------+
//| Display object on chart                                          |
//+------------------------------------------------------------------+
bool CButton::OnShow(void)
  {
   return(m_button.Timeframes(OBJ_ALL_PERIODS));
  }
//+------------------------------------------------------------------+
//| Hide object from chart                                           |
//+------------------------------------------------------------------+
bool CButton::OnHide(void)
  {
   return(m_button.Timeframes(OBJ_NO_PERIODS));
  }
//+------------------------------------------------------------------+
//| Absolute movement of the chart object                            |
//+------------------------------------------------------------------+
bool CButton::OnMove(void)
  {
//--- position the chart object
   return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top));
  }
//+------------------------------------------------------------------+
//| Resize the chart object                                          |
//+------------------------------------------------------------------+
bool CButton::OnResize(void)
  {
//--- resize the chart object
   return(m_button.X_Size(m_rect.Width()) && m_button.Y_Size(m_rect.Height()));
  }
//+------------------------------------------------------------------+
//| Handler of click on the left mouse button                        |
//+------------------------------------------------------------------+
bool CButton::OnMouseDown(void)
  {
   if(!IS_CAN_LOCK)
      Pressed(!Pressed());
//--- call of the method of the parent class
   return(CWnd::OnMouseDown());
  }
//+------------------------------------------------------------------+
//| Handler of click on the left mouse button                        |
//+------------------------------------------------------------------+
bool CButton::OnMouseUp(void)
  {
//--- depress the button if it is not fixed
   if(m_button.State() && !IS_CAN_LOCK)
      m_button.State(false);
//--- call of the method of the parent class
   return(CWnd::OnMouseUp());
  }
//+------------------------------------------------------------------+


テーマ管理メソッドを組み込んだCButton

強調表示されたセクションを参照してください。

//+------------------------------------------------------------------+
//|                                                       Button.mqh |
//|                             Copyright 2000-2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "WndObj.mqh"
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//+------------------------------------------------------------------+
//| Class CButton                                                    |
//| Usage: control that is displayed by                              |
//|             the CChartObjectButton object                        |
//+------------------------------------------------------------------+
class CButton : public CWndObj
  {
private:
   CChartObjectButton m_button;             // chart object

public:
                     CButton(void);
                    ~CButton(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);
   //--- state
   bool              Pressed(void)          const { return(m_button.State());                       }
   bool              Pressed(const bool pressed)  { return(m_button.State(pressed));                }
   //--- properties
   bool              Locking(void)          const { return(IS_CAN_LOCK);                            }
   void              Locking(const bool flag);
   
   //--- theme methods
   void              SetTextColor(color clr)       { m_button.Color(clr);                           }
   void              SetBackgroundColor(color clr) { m_button.BackColor(clr);                       }
   void              SetBorderColor(color clr)     { m_button.BorderColor(clr);                     }

protected:
   //--- handlers of object settings
   virtual bool      OnSetText(void)              { return(m_button.Description(m_text));           }
   virtual bool      OnSetColor(void)             { return(m_button.Color(m_color));                }
   virtual bool      OnSetColorBackground(void)   { return(m_button.BackColor(m_color_background)); }
   virtual bool      OnSetColorBorder(void)       { return(m_button.BorderColor(m_color_border));   }
   virtual bool      OnSetFont(void)              { return(m_button.Font(m_font));                  }
   virtual bool      OnSetFontSize(void)          { return(m_button.FontSize(m_font_size));         }
   //--- internal event handlers
   virtual bool      OnCreate(void);
   virtual bool      OnShow(void);
   virtual bool      OnHide(void);
   virtual bool      OnMove(void);
   virtual bool      OnResize(void);
   virtual bool      OnMouseDown(void);
   virtual bool      OnMouseUp(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CButton::CButton(void)
  {
   m_color           =CONTROLS_BUTTON_COLOR;
   m_color_background=CONTROLS_BUTTON_COLOR_BG;
   m_color_border    =CONTROLS_BUTTON_COLOR_BORDER;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CButton::~CButton(void)
  {
  }
//+------------------------------------------------------------------+
//| Create a control                                                 |
//+------------------------------------------------------------------+
bool CButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
//--- call method of the parent class
   if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
//--- create the chart object
   if(!m_button.Create(chart,name,subwin,x1,y1,Width(),Height()))
      return(false);
//--- call the settings handler
   return(OnChange());
  }
//+------------------------------------------------------------------+
//| Locking flag                                                     |
//+------------------------------------------------------------------+
void CButton::Locking(const bool flag)
  {
   if(flag)
      PropFlagsSet(WND_PROP_FLAG_CAN_LOCK);
   else
      PropFlagsReset(WND_PROP_FLAG_CAN_LOCK);
  }
//+------------------------------------------------------------------+
//| Create object on chart                                           |
//+------------------------------------------------------------------+
bool CButton::OnCreate(void)
  {
//--- create the chart object by previously set parameters
   return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height()));
  }
//+------------------------------------------------------------------+
//| Display object on chart                                          |
//+------------------------------------------------------------------+
bool CButton::OnShow(void)
  {
   return(m_button.Timeframes(OBJ_ALL_PERIODS));
  }
//+------------------------------------------------------------------+
//| Hide object from chart                                           |
//+------------------------------------------------------------------+
bool CButton::OnHide(void)
  {
   return(m_button.Timeframes(OBJ_NO_PERIODS));
  }
//+------------------------------------------------------------------+
//| Absolute movement of the chart object                            |
//+------------------------------------------------------------------+
bool CButton::OnMove(void)
  {
//--- position the chart object
   return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top));
  }
//+------------------------------------------------------------------+
//| Resize the chart object                                          |
//+------------------------------------------------------------------+
bool CButton::OnResize(void)
  {
//--- resize the chart object
   return(m_button.X_Size(m_rect.Width()) && m_button.Y_Size(m_rect.Height()));
  }
//+------------------------------------------------------------------+
//| Handler of click on the left mouse button                        |
//+------------------------------------------------------------------+
bool CButton::OnMouseDown(void)
  {
   if(!IS_CAN_LOCK)
      Pressed(!Pressed());
//--- call of the method of the parent class
   return(CWnd::OnMouseDown());
  }
//+------------------------------------------------------------------+
//| Handler of click on the left mouse button                        |
//+------------------------------------------------------------------+
bool CButton::OnMouseUp(void)
  {
//--- depress the button if it is not fixed
   if(m_button.State() && !IS_CAN_LOCK)
      m_button.State(false);
//--- call of the method of the parent class
   return(CWnd::OnMouseUp());
  }
//+------------------------------------------------------------------+


CEditクラステーマ管理

これは、メッセージを入力する入力ボックスを制御する、プロジェクト内の主要なクラスの1つです。デフォルトでは、パネルとそのコンポーネントは白い背景と黒の前景テキストに設定されています。テーマ切り替えボタンをクリックすると、前景色が白に変わります。しかし、開発中に、入力ボックスの色が変更されず、テーマの切り替え時にテキストと混ざってしまうことがあることに気付きました。したがって、テーマの切り替えを処理し、テキスト入力ボックスがテーマの目的に合致するようにするために、CEditクラスにメソッドを追加する必要があります。

デフォルトのCEditクラスには、色を設定するためのメソッド(OnSetColor、OnSetColorBackground、OnSetColorBorder)がすでにあります。これらのメソッドを使用すると、テーマが変更されたときにCEditオブジェクトの外観を更新できます。テーマ切り替えに新しい方法を採用し、次の用語を追加します。CEditクラスにSetTextColor、SetBackgroundColor、SetBorderColorメソッドを追加します。これらのメソッドはそれぞれの色を更新し、既存のメソッド(OnSetColor、OnSetColorBackground、OnSetColorBorder)を呼び出して、変更をチャートオブジェクトに適用します。

//+------------------------------------------------------------------+
//| Set text color                                                   |
//+------------------------------------------------------------------+
bool CEdit::SetTextColor(const color clr)
  {
   m_color = clr;
   return(OnSetColor());
  }

//+------------------------------------------------------------------+
//| Set background color                                             |
//+------------------------------------------------------------------+
bool CEdit::SetBackgroundColor(const color clr)
  {
   m_color_background = clr;
   return(OnSetColorBackground());
  }

//+------------------------------------------------------------------+
//| Set border color                                                 |
//+------------------------------------------------------------------+
bool CEdit::SetBorderColor(const color clr)
  {
   m_color_border = clr;
   return(OnSetColorBorder());
  }

以下では、編集されていないCEditクラスのソースコードを確認し、そのすぐ下に組み込まれたプログラムを共有します。

MQL5からのCEditデフォルト

//+------------------------------------------------------------------+
//|                                                         Edit.mqh |
//|                             Copyright 2000-2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "WndObj.mqh"
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//+------------------------------------------------------------------+
//| Class CEdit                                                      |
//| Usage: control that is displayed by                              |
//|             the CChartObjectEdit object                          |
//+------------------------------------------------------------------+
class CEdit : public CWndObj
  {
private:
   CChartObjectEdit  m_edit;                // chart object
   //--- parameters of the chart object
   bool              m_read_only;           // "read-only" mode flag
   ENUM_ALIGN_MODE   m_align_mode;          // align mode

public:
                     CEdit(void);
                    ~CEdit(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);
   //--- chart event handler
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   //--- parameters of the chart object
   bool              ReadOnly(void)         const { return(m_read_only);                          }
   bool              ReadOnly(const bool flag);
   ENUM_ALIGN_MODE   TextAlign(void)        const { return(m_align_mode);                         }
   bool              TextAlign(const ENUM_ALIGN_MODE align);
   //--- data access
   string            Text(void)             const { return(m_edit.Description());                 }
   bool              Text(const string value)     { return(CWndObj::Text(value));                 }

protected:
   //--- handlers of object events
   virtual bool      OnObjectEndEdit(void);
   //--- handlers of object settings
   virtual bool      OnSetText(void)              { return(m_edit.Description(m_text));           }
   virtual bool      OnSetColor(void)             { return(m_edit.Color(m_color));                }
   virtual bool      OnSetColorBackground(void)   { return(m_edit.BackColor(m_color_background)); }
   virtual bool      OnSetColorBorder(void)       { return(m_edit.BorderColor(m_color_border));   }
   virtual bool      OnSetFont(void)              { return(m_edit.Font(m_font));                  }
   virtual bool      OnSetFontSize(void)          { return(m_edit.FontSize(m_font_size));         }
   virtual bool      OnSetZOrder(void)            { return(m_edit.Z_Order(m_zorder));             }
   //--- internal event handlers
   virtual bool      OnCreate(void);
   virtual bool      OnShow(void);
   virtual bool      OnHide(void);
   virtual bool      OnMove(void);
   virtual bool      OnResize(void);
   virtual bool      OnChange(void);
   virtual bool      OnClick(void);
  };
//+------------------------------------------------------------------+
//| Common handler of chart events                                   |
//+------------------------------------------------------------------+
bool CEdit::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
   if(m_name==sparam && id==CHARTEVENT_OBJECT_ENDEDIT)
      return(OnObjectEndEdit());
//--- event was not handled
   return(CWndObj::OnEvent(id,lparam,dparam,sparam));
  }
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CEdit::CEdit(void) : m_read_only(false),
                     m_align_mode(ALIGN_LEFT)
  {
   m_color           =CONTROLS_EDIT_COLOR;
   m_color_background=CONTROLS_EDIT_COLOR_BG;
   m_color_border    =CONTROLS_EDIT_COLOR_BORDER;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CEdit::~CEdit(void)
  {
  }
//+------------------------------------------------------------------+
//| Create a control                                                 |
//+------------------------------------------------------------------+
bool CEdit::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
//--- call method of the parent class
   if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
//--- create the chart object
   if(!m_edit.Create(chart,name,subwin,x1,y1,Width(),Height()))
      return(false);
//--- call the settings handler
   return(OnChange());
  }
//+------------------------------------------------------------------+
//| Set parameter                                                    |
//+------------------------------------------------------------------+
bool CEdit::ReadOnly(const bool flag)
  {
//--- save new value of parameter
   m_read_only=flag;
//--- set up the chart object
   return(m_edit.ReadOnly(flag));
  }
//+------------------------------------------------------------------+
//| Set parameter                                                    |
//+------------------------------------------------------------------+
bool CEdit::TextAlign(const ENUM_ALIGN_MODE align)
  {
//--- save new value of parameter
   m_align_mode=align;
//--- set up the chart object
   return(m_edit.TextAlign(align));
  }
//+------------------------------------------------------------------+
//| Create object on chart                                           |
//+------------------------------------------------------------------+
bool CEdit::OnCreate(void)
  {
//--- create the chart object by previously set parameters
   return(m_edit.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height()));
  }
//+------------------------------------------------------------------+
//| Display object on chart                                          |
//+------------------------------------------------------------------+
bool CEdit::OnShow(void)
  {
   return(m_edit.Timeframes(OBJ_ALL_PERIODS));
  }
//+------------------------------------------------------------------+
//| Hide object from chart                                           |
//+------------------------------------------------------------------+
bool CEdit::OnHide(void)
  {
   return(m_edit.Timeframes(OBJ_NO_PERIODS));
  }
//+------------------------------------------------------------------+
//| Absolute movement of the chart object                            |
//+------------------------------------------------------------------+
bool CEdit::OnMove(void)
  {
//--- position the chart object
   return(m_edit.X_Distance(m_rect.left) && m_edit.Y_Distance(m_rect.top));
  }
//+------------------------------------------------------------------+
//| Resize the chart object                                          |
//+------------------------------------------------------------------+
bool CEdit::OnResize(void)
  {
//--- resize the chart object
   return(m_edit.X_Size(m_rect.Width()) && m_edit.Y_Size(m_rect.Height()));
  }
//+------------------------------------------------------------------+
//| Set up the chart object                                          |
//+------------------------------------------------------------------+
bool CEdit::OnChange(void)
  {
//--- set up the chart object
   return(CWndObj::OnChange() && ReadOnly(m_read_only) && TextAlign(m_align_mode));
  }
//+------------------------------------------------------------------+
//| Handler of the "End of editing" event                            |
//+------------------------------------------------------------------+
bool CEdit::OnObjectEndEdit(void)
  {
//--- send the ON_END_EDIT notification
   EventChartCustom(CONTROLS_SELF_MESSAGE,ON_END_EDIT,m_id,0.0,m_name);
//--- handled
   return(true);
  }
//+------------------------------------------------------------------+
//| Handler of the "click" event                                     |
//+------------------------------------------------------------------+
bool CEdit::OnClick(void)
  {
//--- if editing is enabled, send the ON_START_EDIT notification
   if(!m_read_only)
     {
      EventChartCustom(CONTROLS_SELF_MESSAGE,ON_START_EDIT,m_id,0.0,m_name);
      //--- handled
      return(true);
     }
//--- else send the ON_CLICK notification
   return(CWnd::OnClick());
  }
//+------------------------------------------------------------------+


テーマ管理メソッドを組み込んだCEdit

強調表示されたセクションを参照してください。

//+------------------------------------------------------------------+
//|                                                         Edit.mqh |
//|                             Copyright 2000-2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "WndObj.mqh"
#include <ChartObjects\ChartObjectsTxtControls.mqh>

//+------------------------------------------------------------------+
//| Class CEdit                                                      |
//| Usage: control that is displayed by                              |
//|             the CChartObjectEdit object                          |
//+------------------------------------------------------------------+
class CEdit : public CWndObj
  {
private:
   CChartObjectEdit  m_edit;                // chart object
   //--- parameters of the chart object
   bool              m_read_only;           // "read-only" mode flag
   ENUM_ALIGN_MODE   m_align_mode;          // align mode

public:
                     CEdit(void);
                    ~CEdit(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);
   //--- chart event handler
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   //--- parameters of the chart object
   bool              ReadOnly(void)         const { return(m_read_only);                          }
   bool              ReadOnly(const bool flag);
   ENUM_ALIGN_MODE   TextAlign(void)        const { return(m_align_mode);                         }
   bool              TextAlign(const ENUM_ALIGN_MODE align);
   //--- data access
   string            Text(void)             const { return(m_edit.Description());                 }
   bool              Text(const string value)     { return(CWndObj::Text(value));                 }
   //--- theme handling
   bool              SetTextColor(const color clr);
   bool              SetBackgroundColor(const color clr);
   bool              SetBorderColor(const color clr);

protected:
   //--- handlers of object events
   virtual bool      OnObjectEndEdit(void);
   //--- handlers of object settings
   virtual bool      OnSetText(void)              { return(m_edit.Description(m_text));           }
   virtual bool      OnSetColor(void)             { return(m_edit.Color(m_color));                }
   virtual bool      OnSetColorBackground(void)   { return(m_edit.BackColor(m_color_background)); }
   virtual bool      OnSetColorBorder(void)       { return(m_edit.BorderColor(m_color_border));   }
   virtual bool      OnSetFont(void)              { return(m_edit.Font(m_font));                  }
   virtual bool      OnSetFontSize(void)          { return(m_edit.FontSize(m_font_size));         }
   virtual bool      OnSetZOrder(void)            { return(m_edit.Z_Order(m_zorder));             }
   //--- internal event handlers
   virtual bool      OnCreate(void);
   virtual bool      OnShow(void);
   virtual bool      OnHide(void);
   virtual bool      OnMove(void);
   virtual bool      OnResize(void);
   virtual bool      OnChange(void);
   virtual bool      OnClick(void);
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CEdit::CEdit(void) : m_read_only(false),
                     m_align_mode(ALIGN_LEFT)
  {
   m_color           =CONTROLS_EDIT_COLOR;
   m_color_background=CONTROLS_EDIT_COLOR_BG;
   m_color_border    =CONTROLS_EDIT_COLOR_BORDER;
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CEdit::~CEdit(void)
  {
  }

//+------------------------------------------------------------------+
//| Create a control                                                 |
//+------------------------------------------------------------------+
bool CEdit::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
   //--- call method of the parent class
   if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
   //--- create the chart object
   if(!m_edit.Create(chart,name,subwin,x1,y1,Width(),Height()))
      return(false);
   //--- call the settings handler
   return(OnChange());
  }

//+------------------------------------------------------------------+
//| Set parameter                                                    |
//+------------------------------------------------------------------+
bool CEdit::ReadOnly(const bool flag)
  {
   //--- save new value of parameter
   m_read_only=flag;
   //--- set up the chart object
   return(m_edit.ReadOnly(flag));
  }

//+------------------------------------------------------------------+
//| Set parameter                                                    |
//+------------------------------------------------------------------+
bool CEdit::TextAlign(const ENUM_ALIGN_MODE align)
  {
   //--- save new value of parameter
   m_align_mode=align;
   //--- set up the chart object
   return(m_edit.TextAlign(align));
  }

//+------------------------------------------------------------------+
//| Set text color                                                   |
//+------------------------------------------------------------------+
bool CEdit::SetTextColor(const color clr)
  {
   m_color = clr;
   return(OnSetColor());
  }

//+------------------------------------------------------------------+
//| Set background color                                             |
//+------------------------------------------------------------------+
bool CEdit::SetBackgroundColor(const color clr)
  {
   m_color_background = clr;
   return(OnSetColorBackground());
  }

//+------------------------------------------------------------------+
//| Set border color                                                 |
//+------------------------------------------------------------------+
bool CEdit::SetBorderColor(const color clr)
  {
   m_color_border = clr;
   return(OnSetColorBorder());
  }

//+------------------------------------------------------------------+
//| Create object on chart                                           |
//+------------------------------------------------------------------+
bool CEdit::OnCreate(void)
  {
   //--- create the chart object by previously set parameters
   return(m_edit.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height()));
  }

//+------------------------------------------------------------------+
//| Display object on chart                                          |
//+------------------------------------------------------------------+
bool CEdit::OnShow(void)
  {
   return(m_edit.Timeframes(OBJ_ALL_PERIODS));
  }

//+------------------------------------------------------------------+
//| Hide object from chart                                           |
//+------------------------------------------------------------------+
bool CEdit::OnHide(void)
  {
   return(m_edit.Timeframes(OBJ_NO_PERIODS));
  }

//+------------------------------------------------------------------+
//| Absolute movement of the chart object                            |
//+------------------------------------------------------------------+
bool CEdit::OnMove(void)
  {
   //--- position the chart object
   return(m_edit.X_Distance(m_rect.left) && m_edit.Y_Distance(m_rect.top));
  }

//+------------------------------------------------------------------+
//| Resize the chart object                                          |
//+------------------------------------------------------------------+
bool CEdit::OnResize(void)
  {
   //--- resize the chart object
   return(m_edit.X_Size(m_rect.Width()) && m_edit.Y_Size(m_rect.Height()));
  }

//+------------------------------------------------------------------+
//| Set up the chart object                                          |
//+------------------------------------------------------------------+
bool CEdit::OnChange(void)
  {
   //--- set up the chart object
   return(CWndObj::OnChange() && ReadOnly(m_read_only) && TextAlign(m_align_mode));
  }

//+------------------------------------------------------------------+
//| Handler of the "End of editing" event                            |
//+------------------------------------------------------------------+
bool CEdit::OnObjectEndEdit(void)
  {
   //--- send the ON_END_EDIT notification
   EventChartCustom(CONTROLS_SELF_MESSAGE,ON_END_EDIT,m_id,0.0,m_name);
   //--- handled
   return(true);
  }

//+------------------------------------------------------------------+
//| Handler of the "click" event                                     |
//+------------------------------------------------------------------+
bool CEdit::OnClick(void)
  {
   //--- if editing is enabled, send the ON_START_EDIT notification
   if(!m_read_only)
     {
      EventChartCustom(CONTROLS_SELF_MESSAGE,ON_START_EDIT,m_id,0.0,m_name);
      //--- handled
      return(true);
     }
   //--- else send the ON_CLICK notification
   return(CWnd::OnClick());
  }

//+------------------------------------------------------------------+
管理パネルのコントロールインクルードファイルの準備が完了し、これまで以上にプロジェクトの完了に近づいています。次のセグメントでは、最近の開発に合わせてテーマの切り替えをサポートするように管理パネルのエキスパートアドバイザー(EA)コードを調整することで、取り組みを終了します。

テーマ切り替えのために管理パネルを調整します。

私たちのテーマ管理には、論理的に4つの主要領域があります。 

  • 管理パネルのテーマ切り替え機能は、darkThemeブール変数とUpdateThemeColors()関数を中心にする必要があります。仕組みは次のとおりです。

bool darkTheme = false;

  • 上記のフラグは、現在のテーマが暗いか明るいかを決定します。以下に示すように、toggleThemeButtonを押すと切り替わります。

void OnToggleThemeButtonClick()
{
    darkTheme = !darkTheme;
    UpdateThemeColors();
    Print("Theme toggled: ", darkTheme ? "Dark" : "Light");
}

  • テーマ切り替えボタンをクリックするとこの関数が呼び出され、darkThemeフラグを設定し、その後UpdateThemeColors()を介してUIのテーマを更新します。

void UpdateThemeColors()
{
    // Determine colors based on the current theme
    color textColor = darkTheme ? clrWhite : clrBlack;
    color buttonBgColor = darkTheme ? clrDarkSlateGray : clrGainsboro;
    color borderColor = darkTheme ? clrSlateGray : clrGray;
    color bgColor     = darkTheme ? clrDarkBlue : clrWhite;

    // Set text box colors
    inputBox.SetTextColor(textColor);
    inputBox.SetBackgroundColor(bgColor);
    inputBox.SetBorderColor(borderColor);

    // Update button colors
    UpdateButtonTheme(clearButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(sendButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(toggleThemeButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(changeFontButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(minimizeButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(maximizeButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(closeButton, textColor, buttonBgColor, borderColor);

    // Update quick message buttons
    for (int i = 0; i < ArraySize(quickMessageButtons); i++)
    {
        UpdateButtonTheme(quickMessageButtons[i], textColor, buttonBgColor, borderColor);
    }

    // Update character counter color
    charCounter.Color(textColor);

    // Redraw chart to apply changes
    ChartRedraw();
}

 darkThemeフラグに基いて、テキスト、ボタンの背景、境界線、背景に異なる色を選択しました。色は次のようにさまざまなUIコンポーネントに適用されます。

  • テキストボックス(inputBox):SetTextColorSetBackgroundColor、および SetBorderColor関数は、テーマを適用するために使用されます。
  • ボタン:各ボタンに対してUpdateButtonTheme()関数が呼び出され、テキストの色、背景色、境界線の色が決定どおりに設定されます。
  • 文字数カウンタ:テーマボタンをクリックすると、色が直接設定されます。

//Theme button application
void UpdateButtonTheme(CButton &button, color textColor, color bgColor, color borderColor)
{
    button.SetTextColor(textColor);
    button.SetBackgroundColor(bgColor);
    button.SetBorderColor(borderColor);
}

上記のヘルパー関数を使用して、関連するすべてのテーマ関連の色設定を任意のボタンに適用しました。これにより、繰り返しのコードがクリーンアップされ、ボタン間の一貫性が確保されます。すべてのコードスニペットをまとめ、メインの管理パネルプログラムに統合すると、すべての機能が目標どおりに実行されるようになります。


最終コードと結果

新しい機能を備えたプログラムの最終的な下書きを以下に示します。


//+------------------------------------------------------------------+
//|                                             Admin Panel.mq5      |
//|                     Copyright 2024, Clemence Benjamin            |
//|     https://www.mql5.com/ja/users/billionaire2024/seller         |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Clemence Benjamin"
#property link      "https://www.mql5.com/ja/users/billionaire2024/seller"
#property version   "1.12"

#include <Trade\Trade.mqh>
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#include <Controls\Edit.mqh>
#include <Controls\Label.mqh>

// Input parameters
input string QuickMessage1 = "Updates";
input string QuickMessage2 = "Close all";
input string QuickMessage3 = "In deep profits";
input string QuickMessage4 = "Hold position";
input string QuickMessage5 = "Swing Entry";
input string QuickMessage6 = "Scalp Entry";
input string QuickMessage7 = "Book profit";
input string QuickMessage8 = "Invalid Signal";
input string InputChatId = "Enter Chat ID from Telegram bot API";
input string InputBotToken = "Enter BOT TOKEN from your Telegram bot";

// Global variables
CDialog adminPanel;
CButton sendButton, clearButton, changeFontButton, toggleThemeButton;
CButton quickMessageButtons[8], minimizeButton, maximizeButton, closeButton;
CEdit inputBox;
CLabel charCounter;
bool minimized = false;
bool darkTheme = false;
int MAX_MESSAGE_LENGTH = 4096;
string availableFonts[] = { "Arial", "Courier New", "Verdana", "Times New Roman" };
int currentFontIndex = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // Initialize the Dialog
    if (!adminPanel.Create(ChartID(), "Admin Panel", 0, 30, 30, 500, 500))
    {
        Print("Failed to create dialog");
        return INIT_FAILED;
    }

    // Create controls
    if (!CreateControls())
    {
        Print("Control creation failed");
        return INIT_FAILED;
    }

    adminPanel.Show();
    UpdateThemeColors();

    Print("Initialization complete");
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Create necessary UI controls                                     |
//+------------------------------------------------------------------+
bool CreateControls()
{
    long chart_id = ChartID();

    // Create the input box
    if (!inputBox.Create(chart_id, "InputBox", 0, 5, 25, 460, 95))
    {
        Print("Failed to create input box");
        return false;
    }
    adminPanel.Add(inputBox);

    // Character counter
    if (!charCounter.Create(chart_id, "CharCounter", 0, 380, 5, 460, 25))
    {
        Print("Failed to create character counter");
        return false;
    }
    charCounter.Text("0/" + IntegerToString(MAX_MESSAGE_LENGTH));
    adminPanel.Add(charCounter);

    // Clear button
    if (!clearButton.Create(chart_id, "ClearButton", 0, 235, 95, 345, 125))
    {
        Print("Failed to create clear button");
        return false;
    }
    clearButton.Text("Clear");
    adminPanel.Add(clearButton);

    // Send button
    if (!sendButton.Create(chart_id, "SendButton", 0, 350, 95, 460, 125))
    {
        Print("Failed to create send button");
        return false;
    }
    sendButton.Text("Send");
    adminPanel.Add(sendButton);

    // Change font button
    if (!changeFontButton.Create(chart_id, "ChangeFontButton", 0, 95, 95, 230, 115))
    {
        Print("Failed to create change font button");
        return false;
    }
    changeFontButton.Text("Font<>");
    adminPanel.Add(changeFontButton);

    // Toggle theme button
    if (!toggleThemeButton.Create(chart_id, "ToggleThemeButton", 0, 5, 95, 90, 115))
    {
        Print("Failed to create toggle theme button");
        return false;
    }
    toggleThemeButton.Text("Theme<>");
    adminPanel.Add(toggleThemeButton);

    // Minimize button
    if (!minimizeButton.Create(chart_id, "MinimizeButton", 0, 375, -22, 405, 0))
    {
        Print("Failed to create minimize button");
        return false;
    }
    minimizeButton.Text("_");
    adminPanel.Add(minimizeButton);

    // Maximize button
    if (!maximizeButton.Create(chart_id, "MaximizeButton", 0, 405, -22, 435, 0))
    {
        Print("Failed to create maximize button");
        return false;
    }
    maximizeButton.Text("[ ]");
    adminPanel.Add(maximizeButton);

    // Close button
    if (!closeButton.Create(chart_id, "CloseButton", 0, 435, -22, 465, 0))
    {
        Print("Failed to create close button");
        return false;
    }
    closeButton.Text("X");
    adminPanel.Add(closeButton);

    // Quick messages
    return CreateQuickMessageButtons();
}

//+------------------------------------------------------------------+
//| Create quick message buttons                                     |
//+------------------------------------------------------------------+
bool CreateQuickMessageButtons()
{
    string quickMessages[8] = { QuickMessage1, QuickMessage2, QuickMessage3, QuickMessage4, QuickMessage5, QuickMessage6, QuickMessage7, QuickMessage8 };
    int startX = 5, startY = 160, width = 222, height = 65, spacing = 5;

    for (int i = 0; i < 8; i++)
    {
        if (!quickMessageButtons[i].Create(ChartID(), "QuickMessageButton" + IntegerToString(i + 1), 0, startX + (i % 2) * (width + spacing), startY + (i / 2) * (height + spacing), startX + (i % 2) * (width + spacing) + width, startY + (i / 2) * (height + spacing) + height))
        {
            Print("Failed to create quick message button ", i + 1);
            return false;
        }
        quickMessageButtons[i].Text(quickMessages[i]);
        adminPanel.Add(quickMessageButtons[i]);
    }
    return true;
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    adminPanel.Destroy();
    Print("Deinitialization complete");
}

//+------------------------------------------------------------------+
//| Handle chart events                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
    switch (id)
    {
        case CHARTEVENT_OBJECT_CLICK:
            if (sparam == "SendButton") OnSendButtonClick();
            else if (sparam == "ClearButton") OnClearButtonClick();
            else if (sparam == "ChangeFontButton") OnChangeFontButtonClick();
            else if (sparam == "ToggleThemeButton") OnToggleThemeButtonClick();
            else if (sparam == "MinimizeButton") OnMinimizeButtonClick();
            else if (sparam == "MaximizeButton") OnMaximizeButtonClick();
            else if (sparam == "CloseButton") OnCloseButtonClick();
            else if (StringFind(sparam, "QuickMessageButton") != -1)
            {
                long index = StringToInteger(StringSubstr(sparam, 18));
                OnQuickMessageButtonClick(index - 1);
            }
            break;

        case CHARTEVENT_OBJECT_ENDEDIT:
            if (sparam == "InputBox") OnInputChange();
            break;
    }
}

//+------------------------------------------------------------------+
//| Handle custom message send button click                          |
//+------------------------------------------------------------------+
void OnSendButtonClick()
{
    string message = inputBox.Text();
    if (message != "")
    {
        if (SendMessageToTelegram(message))
            Print("Custom message sent: ", message);
        else
            Print("Failed to send custom message.");
    }
    else
    {
        Print("No message entered.");
    }
}

//+------------------------------------------------------------------+
//| Handle clear button click                                        |
//+------------------------------------------------------------------+
void OnClearButtonClick()
{
    inputBox.Text("");
    OnInputChange();
    Print("Input box cleared.");
}

//+------------------------------------------------------------------+
//| Handle quick message button click                                |
//+------------------------------------------------------------------+
void OnQuickMessageButtonClick(int index)
{
    string quickMessages[8] = { QuickMessage1, QuickMessage2, QuickMessage3, QuickMessage4, QuickMessage5, QuickMessage6, QuickMessage7, QuickMessage8 };
    string message = quickMessages[index];

    if (SendMessageToTelegram(message))
        Print("Quick message sent: ", message);
    else
        Print("Failed to send quick message.");
}

//+------------------------------------------------------------------+
//| Update character counter                                         |
//+------------------------------------------------------------------+
void OnInputChange()
{
    int currentLength = StringLen(inputBox.Text());
    charCounter.Text(IntegerToString(currentLength) + "/" + IntegerToString(MAX_MESSAGE_LENGTH));
    ChartRedraw();
}

//+------------------------------------------------------------------+
//| Handle toggle theme button click                                 |
//+------------------------------------------------------------------+
void OnToggleThemeButtonClick()
{
    darkTheme = !darkTheme;
    UpdateThemeColors();
    Print("Theme toggled: ", darkTheme ? "Dark" : "Light");
}

//+------------------------------------------------------------------+
//| Update theme colors for the panel                                |
//+------------------------------------------------------------------+
void UpdateThemeColors()
{
    // Use the dialog's theme update method as a placeholder.
    adminPanel.UpdateThemeColors(darkTheme);

    color textColor = darkTheme ? clrWhite : clrBlack;
    color buttonBgColor = darkTheme ? clrDarkSlateGray : clrGainsboro;
    color borderColor = darkTheme ? clrSlateGray : clrGray;
    color bgColor     = darkTheme?  clrDarkBlue : clrWhite;

          inputBox.SetTextColor(textColor);
          inputBox.SetBackgroundColor(bgColor);
          inputBox.SetBorderColor(borderColor);

    UpdateButtonTheme(clearButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(sendButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(toggleThemeButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(changeFontButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(minimizeButton, textColor, buttonBgColor, borderColor);
    UpdateButtonTheme(maximizeButton, textColor, buttonBgColor,borderColor);
    UpdateButtonTheme(closeButton, textColor, buttonBgColor, borderColor);
    

    for (int i = 0; i < ArraySize(quickMessageButtons); i++)
    {
        UpdateButtonTheme(quickMessageButtons[i], textColor, buttonBgColor, borderColor);
    }

    charCounter.Color(textColor);

    ChartRedraw();
}

//+------------------------------------------------------------------+
//| Apply theme settings to a button                                 |
//+------------------------------------------------------------------+
void UpdateButtonTheme(CButton &button, color textColor, color bgColor, color borderColor)
{
    button.SetTextColor(textColor);
    button.SetBackgroundColor(bgColor);
    button.SetBorderColor(borderColor);
}

//+------------------------------------------------------------------+
//| Handle change font button click                                  |
//+------------------------------------------------------------------+
void OnChangeFontButtonClick()
{
    currentFontIndex = (currentFontIndex + 1) % ArraySize(availableFonts);

    inputBox.Font(availableFonts[currentFontIndex]);
    clearButton.Font(availableFonts[currentFontIndex]);
    sendButton.Font(availableFonts[currentFontIndex]);
    toggleThemeButton.Font(availableFonts[currentFontIndex]);
    changeFontButton.Font(availableFonts[currentFontIndex]);

    for (int i = 0; i < ArraySize(quickMessageButtons); i++)
    {
        quickMessageButtons[i].Font(availableFonts[currentFontIndex]);
    }

    Print("Font changed to: ", availableFonts[currentFontIndex]);
    ChartRedraw();
}

//+------------------------------------------------------------------+
//| Handle minimize button click                                     |
//+------------------------------------------------------------------+
void OnMinimizeButtonClick()
{
    minimized = true;
    adminPanel.Hide();
    minimizeButton.Hide();
    maximizeButton.Show();
    closeButton.Show();
    Print("Panel minimized.");
}

//+------------------------------------------------------------------+
//| Handle maximize button click                                     |
//+------------------------------------------------------------------+
void OnMaximizeButtonClick()
{
    if (minimized)
    {
        adminPanel.Show();
        minimizeButton.Show();
        maximizeButton.Hide();
        closeButton.Hide();
        Print("Panel maximized.");
    }
}

//+------------------------------------------------------------------+
//| Handle close button click                                        |
//+------------------------------------------------------------------+
void OnCloseButtonClick()
{
    ExpertRemove();
    Print("Admin Panel closed.");
}

//+------------------------------------------------------------------+
//| Send the message to Telegram                                     |
//+------------------------------------------------------------------+
bool SendMessageToTelegram(string message)
{
    string url = "https://api.telegram.org/bot" + InputBotToken + "/sendMessage";
    string jsonMessage = "{\"chat_id\":\"" + InputChatId + "\", \"text\":\"" + message + "\"}";
    char post_data[];
    ArrayResize(post_data, StringToCharArray(jsonMessage, post_data, 0, WHOLE_ARRAY) - 1);

    int timeout = 5000;
    char result[];
    string responseHeaders;

    int res = WebRequest("POST", url, "Content-Type: application/json\r\n", timeout, post_data, result, responseHeaders);

    if (res == 200)
    {
        Print("Message sent successfully: ", message);
        return true;
    }
    else
    {
        Print("Failed to send message. HTTP code: ", res, " Error code: ", GetLastError());
        Print("Response: ", CharArrayToString(result));
        return false;
    }
}


コンパイルに成功した後、以下に示すようにプログラムを起動し、テーマボタンからの印象的な効果をいくつか紹介しました。テーマ切り替え機能が効果的に動作し、視覚的なプレゼンテーションが大幅に強化されます。驚くべき点の1つは、これらの色を好みに合わせてコード内で最適化できることです。さらに、コード外で色のカスタマイズを可能にするために、色入力オプションを組み込むこともできます。


高度な管理パネル

新しいテーマの管理パネル

下の画像は、エラー処理を含め、パネルで実行されるすべての操作を示しています。カスタムメッセージを送信できない原因としてはTelegramボットトークンとチャットIDエントリが欠落しているか間違っていることが考えられます。画像に見られるように、これらのフィールドは空白のままになっています。これらの資格情報は操作にとって非常に重要なので、正しく入力されていることを確認することが重要です。不正アクセスを防ぐために、これらの資格情報を安全に保管してください。 

エキスパートログ

エキスパートログ

結論

これは、私たちの取引システム管理パネルの開発における新たなマイルストーンとなります。同じライブラリに依存する他のプラットフォーム機能に影響を与えるパフォーマンスの問題は観察されず、テーマ管理アルゴリズムを既存のクラスに正常に組み込むことができました。これらの進歩は主に学習と研究の目的でおこなわれます。ただし、クラスを変更して新しいメソッドを統合すると、プラスの影響が得られる可能性がありますが、正しく実装されていない場合は望ましくない結果が生じるリスクもあります。私たちのプロジェクトは現在、Telegramの機能と高度な視覚化機能の両方を統合し、より複雑になっています。

私たちの進歩に満足しており、MQL5のライブラリファイルの操作から貴重な洞察が得られれば幸いです。このプロジェクトで採用されているいくつかのアプローチを使用すれば、さらに多くのことが達成できます。変更したソースファイルを下記に添付しました。テーマ切り替え機能はこれらのライブラリクラスの存在に依存することに注意してください。問題が発生した場合は、MetaTrader 5を再インストールして、システムファイルを復元し、クラスをデフォルト状態にリセットすることを検討してください。

MQL5ライブラリファイル、特にGUIコンポーネントに関連するファイルに関する変更と議論は、教育目的のみで提供されます。これらのファイルを編集すると視覚的に魅力的な結果が得られますが、慎重に進めてください。ヘッダーファイルを変更すると、取引アプリケーション内で予期しない動作、不安定性、または互換性の問題が発生する可能性があります。おこなわれる変更を完全に理解し、元のファイルのバックアップを保持することが重要です。変更内容を実際の取引システムに導入する前に、安全な環境でテストすることをお勧めします。この資料の作成者は、MQL5ヘッダーファイルの編集によって発生する可能性のある問題について一切責任を負いません。


目次に戻る


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

添付されたファイル |
Admin_Panel.mq5 (14.69 KB)
名義変数の順序符号化 名義変数の順序符号化
この記事では、PythonとMQL5の両方を使用して、名義予測値を機械学習アルゴリズムに適した数値フォーマットに変換する方法について議論し、実演します。
Connexusにおけるヘッダ(第3部):リクエスト用HTTPヘッダの使い方をマスターする Connexusにおけるヘッダ(第3部):リクエスト用HTTPヘッダの使い方をマスターする
Connexusライブラリの開発を続けます。この章では、HTTPプロトコルにおけるヘッダの概念を探求し、ヘッダとは何か、何のためにあるのか、リクエストでどのように使うのかを説明します。APIとの通信で使用される主なヘッダを取り上げ、ライブラリでの設定方法の実践例を紹介します。
知っておくべきMQL5ウィザードのテクニック(第42回):ADXオシレーター 知っておくべきMQL5ウィザードのテクニック(第42回):ADXオシレーター
ADXは、一部のトレーダーが一般的なトレンドの強さを測定するために使用する、もう1つの比較的人気のあるテクニカルインジケーターです。これは他の2つのインジケーターの組み合わせとして機能し、オシレーターとして表示されます。この記事では、MQL5ウィザードアセンブリとそのサポートクラスを使用して、そのパターンについて説明します。
ボリンジャーバンドを活用したピラニア戦略に基づくMQL5エキスパートアドバイザーの作成 ボリンジャーバンドを活用したピラニア戦略に基づくMQL5エキスパートアドバイザーの作成
この記事では、ボリンジャーバンドを利用したピラニア戦略に基づいてMQL5でエキスパートアドバイザー(EA)を作成し、取引の有効性を高めます。この戦略の重要な原則、コーディングの実装、テストと最適化の方法について説明します。この知識によって、取引シナリオにEAを効果的に導入することが可能になります。