
MQL5で取引管理者パネルを作成する(第3回):テーマ管理のための組み込みクラスの拡張(II)
内容
- はじめに
- MQL5のクラスについて
- CDialog、CEdit、CButtonへのテーマ管理メソッドの追加
- CButtonクラステーマ管理
- CEditクラステーマ管理
- テーマ切り替えのための管理パネルの調整
- 最終コードと結果
- 結論
はじめに
MQL5ではライブラリクラスを変更したり新規作成したりすることが可能です。ただし、組み込みライブラリはプラットフォームによって共有されるため、これらのファイルに変更を加えると、現在のプラットフォーム機能にプラスの影響を与えることも、マイナスの影響を与えることもあります。最近の記事では、パネルの外観に影響を与えるためにルートDialogクラスの色を編集する方法について簡単に説明しました。テーマ切り替えボタンはテキストの色を正常に変更しましたが、パネルのスキンやボタンの背景色は変更されませんでした。
調査を通じて、テーマ変更機能を利用可能なクラスに安全に統合する方法をようやく特定しました。これらの変更が正常に実装された後、新しく統合された機能に合わせて管理パネルのアルゴリズムを調整しました。
テーマの切り替えに成功した
本日のディスカッションでは、右側に表示されている視覚的に魅力的なパネルを実現するためにおこなったプロセスに焦点を当てます。表示されるテーマの色は、開発中の色の選択に関する私の意見に基づいています。他のユーザーの好みに合わせてコード内で最適化できるため、さまざまな色を試して、自分に合った色を見つけることができます。パネルの全体的な機能に貢献するプログラムの主要コンポーネントを強調することが重要です。
以下にリストします。
- テキストの色
- ボタンのスキンの色
- 境界
- 背景色
基本的に、これらが私たちのプログラムの最も目立つ特徴です。テーマの変更をトリガーすると、各コンポーネントは表示プロパティを変更して、コードで定義されている目的の色を表示する必要があります。このディスカッションの最後までに、このプロジェクトで実証されているように、インターフェイスを操作するときに利用可能なクラスを変更および拡張するために必要なスキルを習得できるようにすることを目指しています。
MQL5のクラスについて
専門家と初心者の両方が理解できるように、まずはMQL5で使用されているクラスの概念を皆さんに理解してもらいたいと思います。以下は、このプログラミング環境内でクラスがどのように機能するかを理解するのに役立つ定義と主要な概念です。
クラス
クラスはMQL5のオブジェクト指向プログラミング(OOP)の基盤であり、開発者は関連する変数(属性)と関数(メソッド)を1つのユニットにグループ化して、プログラム内の複雑な概念や動作を表すことができます。
クラスを2つに分割します。
- 属性: クラスのオブジェクトの状態またはデータを格納する変数
- メソッド: クラスのオブジェクトの動作やアクションを定義する関数
クラスの主な特徴の概要
- クラス内のカプセル化には、データ(変数)とそのデータを操作するメソッド(関数)をバンドルすることが含まれており、外部からのアクセスや誤用から保護されます。
- 継承により、クラスは別のクラスからプロパティとメソッドを継承できるようになり、コードの再利用が促進され、階層構造が作成されます。
- ポリモーフィズムによりメソッドのオーバーライドが可能になり、サブクラスが親クラスで既に定義されているメソッドの特定の実装を提供できるようになります。
- 抽象化により、関連するデータとメソッドのみに焦点を当て、不要な詳細をユーザーから隠すことで、複雑なシステムのモデリングが簡素化されます。
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):SetTextColor、SetBackgroundColor、および 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; } }
新しいテーマの管理パネル
下の画像は、エラー処理を含め、パネルで実行されるすべての操作を示しています。カスタムメッセージを送信できない原因としてはTelegramボットトークンとチャットIDエントリが欠落しているか間違っていることが考えられます。画像に見られるように、これらのフィールドは空白のままになっています。これらの資格情報は操作にとって非常に重要なので、正しく入力されていることを確認することが重要です。不正アクセスを防ぐために、これらの資格情報を安全に保管してください。
エキスパートログ
結論
これは、私たちの取引システム管理パネルの開発における新たなマイルストーンとなります。同じライブラリに依存する他のプラットフォーム機能に影響を与えるパフォーマンスの問題は観察されず、テーマ管理アルゴリズムを既存のクラスに正常に組み込むことができました。これらの進歩は主に学習と研究の目的でおこなわれます。ただし、クラスを変更して新しいメソッドを統合すると、プラスの影響が得られる可能性がありますが、正しく実装されていない場合は望ましくない結果が生じるリスクもあります。私たちのプロジェクトは現在、Telegramの機能と高度な視覚化機能の両方を統合し、より複雑になっています。
私たちの進歩に満足しており、MQL5のライブラリファイルの操作から貴重な洞察が得られれば幸いです。このプロジェクトで採用されているいくつかのアプローチを使用すれば、さらに多くのことが達成できます。変更したソースファイルを下記に添付しました。テーマ切り替え機能はこれらのライブラリクラスの存在に依存することに注意してください。問題が発生した場合は、MetaTrader 5を再インストールして、システムファイルを復元し、クラスをデフォルト状態にリセットすることを検討してください。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/16045




- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索