
グラフィカルインタフェースVI:チェックボックスコントロール、編集コントロールとその混合型(チャプター 1)
コンテンツ
はじめに
初めの記事グラフィカルインタフェース I: ライブラリストラクチャの準備(チャプター 1)ではライブラリの目的が詳細に考察されます。記事へのリンクの完全なリストは各章の末尾でみられます。そこではまた、開発の現段階でのライブラリの完全版をダウンロードすることができます。ファイルはアーカイブと同じディレクトリに配置される必要があります。
シリーズの第六部は2章でできています。初めの章では4つのコントロールを作成します。
- チェックボックス
- 編集コントロール
- チェックボックスを持った編集コントロール
- チェックコンボボックス
ここではチェックボックスと編集コントロールのみについてお話しします。チェックボックスのついた編集コントロるとチェックコンボボックスについては今までにすべてお話ししたことばかりです。
2番目の記事は、以下の要素に専念されます。
- スライダー
- デュアルスライダー
チェックボックスコントロール
チェックボックスコントロールは、2つの状態しか持つことができないパラメータの管理にのために設計されています。2つのアイコンを持つボタンがコントロールが接続されているパラメータの現在の状態を識別するために使用されます。チェックマークの付いたアイコンは、パラメータが有効(オン)になっていることを意味します。チェックマークのないアイコンは、パラメータが無効(オフ)になっていることを意味します。パラメータの簡単な説明は、ボタンの近くに位置します。
この要素は、3つのグラフィカルオブジェクトで構成されます。それらは:
- 背景
- アイコン(ボタン)
- テキストラベル
図1。チェックボックスコントロールの複合部分
このコントロールのクラスを詳しく見てみましょう。
チェックボックスコントロール作成クラスの開発
シリーズの第三部では同じようなコントロールであるアイコンボタンとそのCIconButton クラスについてお話ししました(グラフィカルインタフェース III: シンプルボタンと多機能ボタン(チャプター 1)をご覧ください)。チェックボックスコントロールは、2ステートモードのアイコンボタンに似ています。ここでの唯一の違いは、ボタンの異なる状態(オン/オフ)では背景色と文字色が異なる一方(設定されている場合)、チェックボックスではアイコンとテキストの色のみが変わるということです(設定されている場合)。チェックボックスの背景色は、それが取り付けられているウィンドウの背景色と同じになります。背景は、ここでは境界に相対してマウスカーソルを識別する領域として、またマウスの左ボタンがコントロールを押下したのを識別するために使用されます。チェックボックスコントロールにはアイコンボタンよりユーザーが設定できる特性が少ないので、アイコンボタンより簡単です。
CheckBox.mqhファイルを作成してライブラリのWndContainer.mqhファイルに含みます。
//+------------------------------------------------------------------+ //| WndContainer.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "CheckBox.mqh"
CCheckBoxクラスとライブラリ要素に標準的なメソッドをCheckBox.mqhファイルで作成します。
//+------------------------------------------------------------------+ //| CheckBox.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "Element.mqh" #include "Window.mqh" //+------------------------------------------------------------------+ //| チェックボックス作成クラス | //+------------------------------------------------------------------+ class CCheckBox : public CElement { private: //--- 要素が取り付けられているフォームのポインタ CWindow *m_wnd; //--- public: CCheckBox(void); ~CCheckBox(void); //--- フォームポインタを格納する void WindowPointer(CWindow &object) { m_wnd=::GetPointer(object); } //--- public: //--- チャートイベントハンドラ virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); //--- タイマ virtual void OnEventTimer(void); //--- 要素の移動 virtual void Moving(const int x,const int y); //--- (1) 表示 (2) 非表示 (3) リセット (4) 削除 virtual void Show(void); virtual void Hide(void); virtual void Reset(void); virtual void Delete(void); //--- マウスの左ボタンの優先順位の(1) 設定 (2) リセット virtual void SetZorders(void); virtual void ResetZorders(void); //--- 色をリセットする virtual void ResetColors(void); };
コントロールが作成される前に、ユーザは、下記のプロパティをインストールするためのメソッドを使用できます。
- コントロールの背景
- チェックボックスのアクティブとブロック状態を示すアイコン
- テキストラベルの余白
- 異なる状態にあるテキストラベルの色
チェックボックスのボタンには、アクティブ状態用の2つとアイコンやブロックされた状態のための2 つの計4つのアイコンがあります。すべてのアイコンは記事の最後に用意されていますが、ご自分自身のものを使用することもできます。
class CCheckBox : public CElement { private: //--- チェックボックス背景色 color m_area_color; //--- アクティブとブロック状態のチェックボックスのアイコン string m_check_bmp_file_on; string m_check_bmp_file_off; string m_check_bmp_file_on_locked; string m_check_bmp_file_off_locked; //--- チェックボックスのテキスト string m_label_text; //--- テキストラベルの余白 int m_label_x_gap; int m_label_y_gap; //--- 異なる状態でのテキストラベルの色 color m_label_color; color m_label_color_off; color m_label_color_hover; color m_label_color_locked; color m_label_color_array[]; //--- 左マウスクリックの優先順位 int m_zorder; int m_area_zorder; //--- public: //--- アクティブとブロック状態のボタンラベルの設定 void CheckFileOn(const string file_path) { m_check_bmp_file_on=file_path; } void CheckFileOff(const string file_path) { m_check_bmp_file_off=file_path; } void CheckFileOnLocked(const string file_path) { m_check_bmp_file_on_locked=file_path; } void CheckFileOffLocked(const string file_path) { m_check_bmp_file_off_locked=file_path; } //--- テキストラベルの(1) 背景色 (2) 余白 void AreaColor(const color clr) { m_area_color=clr; } void LabelXGap(const int x_gap) { m_label_x_gap=x_gap; } void LabelYGap(const int y_gap) { m_label_y_gap=y_gap; } //--- 異なる状態でのテキストの色 void LabelColor(const color clr) { m_label_color=clr; } void LabelColorOff(const color clr) { m_label_color_off=clr; } void LabelColorHover(const color clr) { m_label_color_hover=clr; } void LabelColorLocked(const color clr) { m_label_color_locked=clr; } //--- チェックボックスの説明 string LabelText(void) const { return(m_label.Description()); } };
チェックボックスコントロールの作成には3つのprivateメソッドと1つの publicメソッドが必要です。
class CCheckBox : public CElement { private: //--- チェックボックス作成のためのオブジェクト CRectLabel m_area; CBmpLabel m_check; CLabel m_label; //--- public: //--- チェックボックス作成メソッド bool CreateCheckBox(const long chart_id,const int subwin,const string text,const int x,const int y); //--- private: bool CreateArea(void); bool CreateCheck(void); bool CreateLabel(void); };
チェックボックスの状態管理のためにCCheckBox::CheckButtonState()とCCheckBox::CheckBoxState()メソッドを作成しましょう。
class CCheckBox : public CElement { private: //--- チェックボックスボタンの状態 bool m_check_button_state; //--- チェックボックスの状態(利用可能/ブロック) bool m_checkbox_state; //--- public: //--- チェックボックスの状態を返す/設定する bool CheckBoxState(void) const { return(m_checkbox_state); } void CheckBoxState(const bool state); //--- チェックボックスボタンの状態を返す/設定する bool CheckButtonState(void) const { return(m_check.State()); } void CheckButtonState(const bool state); };
コントロールをブロックする/ブロック解除するにはCCheckBox::CheckBoxState()メソッドを使います。
//+------------------------------------------------------------------+ //| コントロールの状態の設定 | //+------------------------------------------------------------------+ void CCheckBox::CheckBoxState(const bool state) { //--- コントロールの状態 m_checkbox_state=state; //--- アイコン m_check.BmpFileOn((state)?"::"+m_check_bmp_file_on : "::"+m_check_bmp_file_on_locked); m_check.BmpFileOff((state)?"::"+m_check_bmp_file_off : "::"+m_check_bmp_file_off_locked); //--- テキストラベルの色 m_label.Color((state)?m_label_color : m_label_color_locked); }
チェックボックスボタンの状態を設定するにはCCheckBox::CheckButtonState()メソッドを使います。
//+------------------------------------------------------------------+ //| チェックボックスボタンの状態の設定 | //+------------------------------------------------------------------+ void CCheckBox::CheckButtonState(const bool state) { //--- コントロールがブロックされている場合は終了する if(!m_checkbox_state) return; //--- ボタンの状態を設定する m_check.State(state); m_check_button_state=state; //--- 現在の状態によって色を変える m_label.Color((state)?m_label_color : m_label_color_off); CElement::InitColorArray((state)?m_label_color : m_label_color_off,m_label_color_hover,m_label_color_array); }
チェックボックスコントロールの押下を処理するメソッドの作成のみが必要です。このメソッドはコントロールのメインハンドラであるCCheckBox::OnEvent() でCHARTEVENT_OBJECT_CLICK識別子を持ったイベントによって呼び出されます。 identifier. CCheckBox::OnClickLabel()と呼びましょう。このメソッドの開始時には、押下が制御の領域(その背景)を超えていたかどうかのチェックがあります。押下が正確にコントロールのどのオブジェクト上で起こったかの混乱を避けるために、左ボタンクリックの優先順位値は背景では1、他のオブジェクトでは0です。 したがって、カーソルがチェックボックスのボタンやテキストラベルを超えていたときにプレスがあった場合でも、それはコントロールの背景にクリックとして扱われます。これは、この地域で最も高い優先度を持つオブジェクトです。その後CCheckBox::CheckButtonState()メソッドを使ってチェックボックスボタンの反対の状態を設定します。メソッドの最後では (1) ON_CLICK_LABELイベント識別子(2) 要素識別子 (3) 要素の記述を持ったカスタムイベントが送信されます。
class CCheckBox : public CElement { private: //--- 要素押下の処理 bool OnClickLabel(const string clicked_object); }; //+------------------------------------------------------------------+ //| イベント処理 | //+------------------------------------------------------------------+ void CCheckBox::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- オブジェクトの左マウスボタンクリックの処理 if(id==CHARTEVENT_OBJECT_CLICK) { //--- チェックボックスのクリック if(OnClickLabel(sparam)) return; } } //+------------------------------------------------------------------+ //| 要素ラベルのクリック | //+------------------------------------------------------------------+ bool CCheckBox::OnClickLabel(const string clicked_object) { //--- 名前が違う場合には終了する if(m_area.Name()!=clicked_object) return(false); //--- コントロールがブロックされている場合には終了する if(!m_checkbox_state) return(false); //--- 反対側の状態に切り替える CheckButtonState(!m_check.State()); //--- マウスのかーそるが現在要素の上にある m_label.Color(m_label_color_hover); //--- それについてのメッセージを送信する ::EventChartCustom(m_chart_id,ON_CLICK_LABEL,CElement::Id(),0,m_label.Description()); return(true); }
チェックボックスコントロールの検証
CCheckBox クラスメソッドはすべて整ったので動作を検証しましょう。このコントロールのクラスを持つファイルが既にライブラリに含まれている必要があります。検証するEAは前回の記事からコピーできます。。メインメニューとステータスバーを除いたすべてのコントロールを削除します。 検証のための2つのチェックボックスを作成します。2番目のチェックボックスがチャート上にプログラムを読み込む瞬間にデフォルトでブロックされていることを確認します。1番目のチェックボックスは、無効状態ですがユーザとの相互作用のために利用できるようになります。1番目のチェックボックスの有効化は2番目のチェックボックスのブロック解除のシグナルになります。その反対も同じです。1番目のチェックボックスの無効化は2番目のチェックボックスをブロックするシグナルになります。
CProgramカスタムクラスでCCheckBoxクラスの2つのインスタンスを作成しチェックボックスのメソッドを2つ宣言し取り付けられているフォームからの余白を指定します。
//+------------------------------------------------------------------+ //| アプリケーション作成クラス | //+------------------------------------------------------------------+ class CProgram : public CWndEvents { private: //--- チェックボックス CCheckBox m_checkbox1; CCheckBox m_checkbox2; //--- private: //--- チェックボックス #define CHECKBOX1_GAP_X (7) #define CHECKBOX1_GAP_Y (50) bool CreateCheckBox1(const string text); #define CHECKBOX2_GAP_X (30) #define CHECKBOX2_GAP_Y (75) bool CreateCheckBox2(const string text); };
メソッド実装の唯一の違いは2番目のチェックボックスの可用性が1番目のチェックボックスの状態に依存することです。
//+------------------------------------------------------------------+ //| チェックボックス2を作成する | //+------------------------------------------------------------------+ bool CProgram::CreateCheckBox2(string text) { //--- パネルオブジェクトを引き渡す m_checkbox2.WindowPointer(m_window1); //--- 座標 int x=m_window1.X()+CHECKBOX2_GAP_X; int y=m_window1.Y()+CHECKBOX2_GAP_Y; //--- 作成前に優先順位を設定する m_checkbox2.XSize(90); m_checkbox2.YSize(18); m_checkbox2.AreaColor(clrWhiteSmoke); m_checkbox2.LabelColor(clrBlack); m_checkbox2.LabelColorOff(clrBlack); m_checkbox2.LabelColorLocked(clrSilver); //--- コントロールを作成する if(!m_checkbox2.CreateCheckBox(m_chart_id,m_subwin,text,x,y)) return(false); //--- 可用性は1番目のチェックボックスの現在の状態に依存する m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState()); //--- オブジェクトグループの共通配列にオブジェクトを追加する CWndContainer::AddToElementsArray(0,m_checkbox2); return(true); }
グラフィカルインターフェースを作成するためのメインメソッドでチェックボックスを作成するためのメソッドを呼び出します。コードの短縮版は以下に示されています。
//+------------------------------------------------------------------+ //| 取引パネルを作成する | //+------------------------------------------------------------------+ bool CProgram::CreateTradePanel(void) { //--- コントロールのフォーム1の作成 //--- コントロールの作成: // メインメニュー //--- コンテキストメニュー //--- ステータスバーの作成 //--- チェックボックス if(!CreateCheckBox1("Checkbox 1")) return(false); if(!CreateCheckBox2("Checkbox 2")) return(false); //--- チャートの再描画 m_chart.Redraw(); return(true); }
CProgramクラスのイベントハンドラではON_CLICK_LABEL識別子を持ったメッセージが受け取られ処理されます。下のコードに示されるように2番目のチェックボックスの可用性は1番目のチェックボックスの状態に依存します。
//+------------------------------------------------------------------+ //| イベントハンドラ | //+------------------------------------------------------------------+ void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- チェックボックス押下イベント if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL) { ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); //--- 1番目のチェックボックスが押下された場合 if(lparam==m_checkbox1.Id()) { //--- 2番目のチェックボックスの状態を設定する m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState()); } } }
ファイルをコンパイルしてEAをチャートに読み込みます。結果は以下のスクリーンショットのようなはずです。
図2。チェックボックスコントロールの検証
スクリーンショットは、2番目のチェックボックスがブロックされていることを示しています。ここでの表示は、テキストの色とこの状態に対応するボタンのアイコンの色です(色あせた色)。すべてがうまく行ったので、編集コントロールを作成するためのクラスの開発に移ります。
編集コントロール
編集コントロールは、テキストフィールドに数値を設定するために使用されています。値は、手動またはスクロールボタンの助けを借りて入力することができます。最大値と最小値(限界値)とスクロールするためのステップは、ユーザが定義することができます。 上/下矢印付きのボタンを1回押すと、その値は設定で指定されたステップだけ増加/減少されます。上/下矢印付きが長押しされると編集中の値が急速に変化します。スクロールは許可された最大値または最小値に達すると停止します。
このコントロールは5つのグラフィカルオブジェクトで構成されます。それらは:
- 背景
- テキストラベル
- 編集コントロール
- 編集コントロール内の値をスクロールするための2つのボタン
図3。編集コントロールの複合部分
本稿の次の部分では、このインタフェース要素を作成するためのクラスを記述します。
編集コントロール作成クラスの開発
チェックボックスコントロールと同様に、編集コントロールは、単純で混合型ではありません。換言すれば、それは単純なオブジェクトで構成されており他のコントロールが含まれていません。これがWndContainer.mqhファイルに追加がいらない理由です。編集コントロールクラスを持つファイルを含める必要があるのみです。
SpinEdit.mqhファイルを作成してWndContainer.mqhファイルに含みます。
//+------------------------------------------------------------------+ //| WndContainer.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "SpinEdit.mqh"
SpinEdit.mqhファイルでCSpinEditクラスを作成し、本稿で前述されたCCheckBoxクラスの記述でライブラリ要素に標準的なメソッドを追加します。それがすぐ編集コントロールのプロパティの説明に移る理由です。
下にあるのはユーザが設定できる編集コントロールのすべてのプロパティのリストです。
- 背景色
- 編集コントロールのテキストの説明
- テキストラベルの余白
- 異なる状態でのテキストの色
- 編集コントロールの大きさ
- 要素の右側からの編集コントロールの余白
- 異なる状態にある編集コントロールの色
- 異なる状態にある編集テキストの色
- 異なる状態にある編集フレームの色
- スイッチのアクティブとブロック状態を示すラベル
- (右側からの)ボタンの余白
- 値を最小にリセットするモード
- 最小値と最大値
- ボタンを使用して編集の値を変更する時のステップ
- テキストの配置モード
- 小数点以下の桁数
次のコードには、上記のプロパティを実装するためのフィールドとメソッドが含まれています。
//+------------------------------------------------------------------+ //| 編集コントロールの作成クラス | //+------------------------------------------------------------------+ class CSpinEdit : public CElement { private: //--- コントロールの背景色 color m_area_color; //--- 編集の説明のテキスト string m_label_text; //--- テキストラベルの余白 int m_label_x_gap; int m_label_y_gap; //--- 異なる状態でのテキストの色 color m_label_color; color m_label_color_hover; color m_label_color_locked; color m_label_color_array[]; //--- 編集コントロールの大きさ int m_edit_x_size; int m_edit_y_size; //--- 右側からの編集コントロールの余白 int m_edit_x_gap; //--- 異なる状態での編集コントロールとテキストの色 color m_edit_color; color m_edit_color_locked; color m_edit_text_color; color m_edit_text_color_locked; color m_edit_text_color_highlight; //--- 異なる状態での編集フレームの色 color m_edit_border_color; color m_edit_border_color_hover; color m_edit_border_color_locked; color m_edit_border_color_array[]; //--- アクティブとブロック状態のスイッチのラベル string m_inc_bmp_file_on; string m_inc_bmp_file_off; string m_inc_bmp_file_locked; string m_dec_bmp_file_on; string m_dec_bmp_file_off; string m_dec_bmp_file_locked; //--- ボタンの余白(右から) int m_inc_x_gap; int m_inc_y_gap; int m_dec_x_gap; int m_dec_y_gap; //--- 値を最小にリセットするモード bool m_reset_mode; //--- 最小値と最大値 double m_min_value; double m_max_value; //--- 編集コントロールで値を変えるステップ double m_step_value; //--- テキスト配置のモード ENUM_ALIGN_MODE m_align_mode; //--- 小数点以下の桁数 int m_digits; //--- public: //--- (1) 背景色 (2) 編集コントロールの説明テキスト (3) テキストラベルの余白 void AreaColor(const color clr) { m_area_color=clr; } string LabelText(void) const { return(m_label.Description()); } void LabelXGap(const int x_gap) { m_label_x_gap=x_gap; } void LabelYGap(const int y_gap) { m_label_y_gap=y_gap; } //--- 異なる状態でのテキストラベルの色 void LabelColor(const color clr) { m_label_color=clr; } void LabelColorHover(const color clr) { m_label_color_hover=clr; } void LabelColorLocked(const color clr) { m_label_color_locked=clr; } //--- (1) 編集コントロールの大きさ (2) 右側からの余白 void EditXSize(const int x_size) { m_edit_x_size=x_size; } void EditYSize(const int y_size) { m_edit_y_size=y_size; } void EditXGap(const int x_gap) { m_edit_x_gap=x_gap; } //--- 異なる状態での編集コントロールの色 void EditColor(const color clr) { m_edit_color=clr; } void EditColorLocked(const color clr) { m_edit_color_locked=clr; } //--- 異なる状態での編集テキストの色 void EditTextColor(const color clr) { m_edit_text_color=clr; } void EditTextColorLocked(const color clr) { m_edit_text_color_locked=clr; } void EditTextColorHighlight(const color clr) { m_edit_text_color_highlight=clr; } //--- 異なる状態での編集フレームの色 void EditBorderColor(const color clr) { m_edit_border_color=clr; } void EditBorderColorHover(const color clr) { m_edit_border_color_hover=clr; } void EditBorderColorLocked(const color clr) { m_edit_border_color_locked=clr; } //--- アクティブおよびブロックされた状態でボタンのラベルを設定する void IncFileOn(const string file_path) { m_inc_bmp_file_on=file_path; } void IncFileOff(const string file_path) { m_inc_bmp_file_off=file_path; } void IncFileLocked(const string file_path) { m_inc_bmp_file_locked=file_path; } void DecFileOn(const string file_path) { m_dec_bmp_file_on=file_path; } void DecFileOff(const string file_path) { m_dec_bmp_file_off=file_path; } void DecFileLocked(const string file_path) { m_dec_bmp_file_locked=file_path; } //--- 編集ボタンの余白 void IncXGap(const int x_gap) { m_inc_x_gap=x_gap; } void IncYGap(const int y_gap) { m_inc_y_gap=y_gap; } void DecXGap(const int x_gap) { m_dec_x_gap=x_gap; } void DecYGap(const int y_gap) { m_dec_y_gap=y_gap; } //--- テキストラベルが押されるとリセットモードが発生する bool ResetMode(void) { return(m_reset_mode); } void ResetMode(const bool mode) { m_reset_mode=mode; } //--- 最小値 double MinValue(void) const { return(m_min_value); } void MinValue(const double value) { m_min_value=value; } //--- 最大値 double MaxValue(void) const { return(m_max_value); } void MaxValue(const double value) { m_max_value=value; } //--- 値のステップ double StepValue(void) const { return(m_step_value); } void StepValue(const double value) { m_step_value=(value<=0)?1 : value; } //--- (1) 小数点以下の桁数 (2) テキスト配置モード void SetDigits(const int digits) { m_digits=::fabs(digits); } void AlignMode(ENUM_ALIGN_MODE mode) { m_align_mode=mode; } };
編集コントロールの作成には、グラフィックプリミティブオブジェクトを作成する5つのprivateメソッドと1つのpublicメソッドが必要で、これはグラフィカルインターフェースが作成されたときにカスタムクラスで呼び出されます。ボタンをスクロールするためのアイコンは本稿末尾でダウンロードすることができます。これらはデフォルトで使用されていますが、独自のものを使用することができます。
class CSpinEdit : public CElement { private: //--- 編集コントロール作成オブジェクト CRectLabel m_area; CLabel m_label; CEdit m_edit; CBmpLabel m_spin_inc; CBmpLabel m_spin_dec; //--- public: //--- 編集コントロール作成メソッド bool CreateSpinEdit(const long chart_id,const int subwin,const string label_text,const int x,const int y); //--- private: bool CreateArea(void); bool CreateLabel(void); bool CreateEdit(void); bool CreateSpinInc(void); bool CreateSpinDec(void); };
ここで、作成後にコントロールの状態とプロパティを管理するためのモードおよびメソッドをお話しします。編集コントロールの値を調整して格納するCSpinEdit::SetValue()メソッドと、最小値と最大限度が超過された場合に編集中のテキストを強調表示(点滅)するための補助的なCSpinEdit::HighlightLimit() メソッドから始めましょう。
CSpinEdit::SetValue()メソッドのはじめには、値を変更するステップを考慮した調整があります。次に来るのは、設定された制限値(最大値/最小値)を超えるかどうかのチェックです。制限値が肥えられた場合はチェックに対応する値が設定されてテキストの強調表示のためにCSpinEdit::HighlightLimit()メソッドが呼ばれます。チェック調整後の後で値が前に保存されたものから変更した場合は、新しい値で上書きします。
CSpinEdit::HighlightLimit()メソッドは非常に簡単です。そこでは、点滅の色が最初に設定されます。赤がデフォルトですがユーザによって再定義できます。その後、100ミリ秒のポーズがあります。これは色の一時的な変化が気づかれるために十分です。<テキストの初期色は最後に設定されています。
メソッドのコードは下記です。
class CSpinEdit : public CElement { private: //--- 編集コントロールの現在値 double m_edit_value; //--- public: //--- 編集コントロールの値を返す/設定する double GetValue(void) const { return(m_edit_value); } bool SetValue(const double value); //--- 限界に達したときに点滅する void HighlightLimit(void); }; //+------------------------------------------------------------------+ //| 現在値のチェック | //+------------------------------------------------------------------+ bool CSpinEdit::SetValue(double value) { //--- 調整 double corrected_value =0.0; //--- ステップを考慮して調整 corrected_value=::MathRound(value/m_step_value)*m_step_value; //--- 最小値と最大値を確認 if(corrected_value<m_min_value) { //--- 最小値に設定 corrected_value=m_min_value; //--- 状態をOnに設定 m_spin_dec.State(true); //--- 限界に達したことを示して点滅する HighlightLimit(); } if(corrected_value>m_max_value) { //--- 最大値に設定 corrected_value=m_max_value; //--- 状態をOnに設定< m_spin_inc.State(true); //--- 限界に達したことを示して点滅する< HighlightLimit(); } //--- 値が変わった場合 if(m_edit_value!=corrected_value) { m_edit_value=corrected_value; m_edit.Color(m_edit_text_color); return(true); } //--- 値が変わらなかった return(false); } //+------------------------------------------------------------------+ //| 制限値を強調表示 | //+------------------------------------------------------------------+ void CSpinEdit::HighlightLimit(void) { //--- 一時的にテキストの色を変える m_edit.Color(m_edit_text_color_highlight); //--- 更新する ::ChartRedraw(); //--- 初期色に変える前に少し待つ ::Sleep(100); //--- 初期色に変える m_edit.Color(m_edit_text_color); }
CSpinEdit::SetValue() メソッドは、設定された制限を超えた場合の値を調整するために設計されています。CSpinEdit:: ChangeValue() メソッドは編集コントロールの値を変えるのに使われます。
class CSpinEdit : public CElement { private: //--- 編集コントロールの値を変える void ChangeValue(const double value); }; //+------------------------------------------------------------------+ //| 編集コントロールの値を変える | //+------------------------------------------------------------------+ void CSpinEdit::ChangeValue(const double value) { //--- 新しい値を確、認調、格納する SetValue(value); //--- 新しい値を編集コントロールで設定する m_edit.Description(::DoubleToString(GetValue(),m_digits)); }
他の要素と同様に、以下のコードに示されるように編集コントロールの可用性を管理するためのメソッドが必要になります。
class CSpinEdit : public CElement { private: //--- チェックボックスの状態(利用可能/ブロック) bool m_spin_edit_state; //--- public: //--- 編集コントロールの有用性を返す/設定する bool SpinEditState(void) const { return(m_spin_edit_state); } void SpinEditState(const bool state); }; //+------------------------------------------------------------------+ //| コントロールの状態を設定する | //+------------------------------------------------------------------+ void CSpinEdit::SpinEditState(const bool state) { m_spin_edit_state=state; //--- テキストラベルの色 m_label.Color((state)?m_label_color : m_label_color_locked); //--- 編集コントロールの色 m_edit.Color((state)?m_edit_text_color : m_edit_text_color_locked); m_edit.BackColor((state)?m_edit_color : m_edit_color_locked); m_edit.BorderColor((state)?m_edit_border_color : m_edit_border_color_locked); //--- スイッチのアイコン m_spin_inc.BmpFileOn((state)?"::"+m_inc_bmp_file_on : "::"+m_inc_bmp_file_locked); m_spin_dec.BmpFileOn((state)?"::"+m_dec_bmp_file_on : "::"+m_dec_bmp_file_locked); //--- 現在の状態と早退した設定 if(!m_spin_edit_state) { //--- 優先順位 m_edit.Z_Order(-1); m_spin_inc.Z_Order(-1); m_spin_dec.Z_Order(-1); //--- 読み込み専用モードでの編集コントロール m_edit.ReadOnly(true); } else { //--- 優先順位 m_edit.Z_Order(m_edit_zorder); m_spin_inc.Z_Order(m_spin_zorder); m_spin_dec.Z_Order(m_spin_zorder); //--- 編集モードでの編集コントロール m_edit.ReadOnly(false); } }
ここで編集コントロールのイベントを処理するためのメソッドを検討します。ラベルの押下はカスタムイベントを生成し (1) ON_CLICK_LABELイベント識別子 (2) コントロール識別子 (3) コントロールインデックス (4) テキストラベルの説明が伴います。編集中に値を最小値にリセットするモードは、先に述べました。このモードはデフォルトで有効にされています(false)。それはCSpinEdit::ResetMode()メソッドで有効にされます。これにはその唯一の引数をtrueに設定します。値リセットモードが有効な場合テキストラベルの押下は編集コントロールに最小値を設定するメソッドが呼ばれます。
テキストラベルの押下を処理するCSpinEdit::OnClickLabel()メソッドは下記に示されます。
class CSpinEdit : public CElement { private: //--- テキストラベル押下の処理 bool OnClickLabel(const string clicked_object); }; //+------------------------------------------------------------------+ //| 要素ラベルのクリック | //+------------------------------------------------------------------+ bool CSpinEdit::OnClickLabel(const string clicked_object) { //--- 名前が違ったら終了する if(m_area.Name()!=clicked_object) return(false); //--- リセットモードが有効な場合 if(m_reset_mode) { //--- 最小値を設定する ChangeValue(MinValue()); } //--- それについてメッセージを送信する ::EventChartCustom(m_chart_id,ON_CLICK_LABEL,CElement::Id(),CElement::Index(),m_label.Description()); return(true); }
ユーザーは手動で新しい値を入力するかインクリメントとデクリメントのボタンを使って編集コントロールの値を変更することができます。カスタムイベントの識別子が必要です。これらをDefines.mqhファイルに追加します。
//+------------------------------------------------------------------+ //| Defines.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #define ON_END_EDIT (18) // 編集コントロールの最終値の編集 #define ON_CLICK_INC (19) // カウンタを変更 #define ON_CLICK_DEC (20) // ダウンカウンタを変更
新しい値の手動での入力を処理するためにCSpinEdit::OnEndEdit() メソッドを書きましょう。それはCSpinEdit::OnEvent() 共通ハンドラでCHARTEVENT_OBJECT_ENDEDIT識別子を持ったイベントが受け取られたときに呼ばれます。新しい値は必要が生じた場合には調整することができます。下にあるように、メソッドの終わりでは(1)ON_END_EDITイベント識別子(2) 要素識別子 (3) 要素インデックス (4) テキストラベルの記述を持ったカスタムイベントが再生されます。
class CSpinEdit : public CElement { private: //--- 編集コントロールへの値の入力の処理 bool OnEndEdit(const string edited_object); }; //+------------------------------------------------------------------+ //| 編集コントロールへの値の入力の処理 | //+------------------------------------------------------------------+ bool CSpinEdit::OnEndEdit(const string edited_object) { //--- 名前が異なる場合は終了する if(m_edit.Name()!=edited_object) return(false); //--- 入力された値を取得する double entered_value=::StringToDouble(m_edit.Description()); //--- 新しい値を確認、調整、格納する ChangeValue(entered_value); //--- それについてメッセージを送信する ::EventChartCustom(m_chart_id,ON_END_EDIT,CElement::Id(),CElement::Index(),m_label.Description()); return(true); }
増加/減少ボタンの押下の処理にはCSpinEdit::OnClickSpinInc() とCSpinEdit::OnClickSpinDec()の2つのメソッドが必要です。これは非常にシンプルです。グラフィックオブジェクトが押された後、それが私たちのコントロールのボタンであるかの名前によるチェックがあります。そして、編集コントロールの現在値が取得されコントロールのプロパティで設定されたステップが増加/減少されます。下のコードに見られるように、メソッドの終わりでは(1) ON_CLICK_INC/ON_CLICK_DECイベント識別子(2) 要素識別子 (3) 要素インデックス (4) テキストラベルの記述を持ったカスタムイベントが再生されます。
class CSpinEdit : public CElement { private: //--- 編集ボタンの押下の処理 bool OnClickSpinInc(const string clicked_object); bool OnClickSpinDec(const string clicked_object); }; //+------------------------------------------------------------------+ //| 増加スイッチの押下 | //+------------------------------------------------------------------+ bool CSpinEdit::OnClickSpinInc(const string clicked_object) { //--- 名前が異なる場合は終了する if(m_spin_inc.Name()!=clicked_object) return(false); //--- 現在値を取得する double value=GetValue(); //--- 1ステップで増加して制限値超過をチェックする ChangeValue(value+m_step_value); //--- 状態をOnにする m_spin_inc.State(true); //--- それについてのメッセージを送信する ::EventChartCustom(m_chart_id,ON_CLICK_INC,CElement::Id(),CElement::Index(),m_label.Description()); return(true); } //+------------------------------------------------------------------+ //| 減少スイッチの押下 | //+------------------------------------------------------------------+ bool CSpinEdit::OnClickSpinDec(const string clicked_object) { //--- 名前が異なる場合は終了する if(m_spin_dec.Name()!=clicked_object) return(false); //--- 現在値を取得する double value=GetValue(); //--- 1ステップで減少して制限値超過をチェックする ChangeValue(value-m_step_value); //--- 状態をOnにする m_spin_dec.State(true); //--- それについてのメッセージを送信する ::EventChartCustom(m_chart_id,ON_CLICK_DEC,CElement::Id(),CElement::Index(),m_label.Description()); return(true); }
以下のコードに示すように、すべてのこれらの処理メソッドは、イベント処理のためのメインメソッドで呼び出さなければなりません。処理メソッドの本体へのアクセスは、コントロールの現在の利用可能性によって制御されます.。
//+------------------------------------------------------------------+ //| イベント処理 | //+------------------------------------------------------------------+ void CSpinEdit::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- マウス左ボタンのオブジェクトクリックの処理 if(id==CHARTEVENT_OBJECT_CLICK) { //--- コントロールがブロックされている場合は終了する if(!m_spin_edit_state) return; //--- テキストラベルの押下の処理 if(OnClickLabel(sparam)) return; //--- 編集ボタンの押下の処理 if(OnClickSpinInc(sparam)) return; if(OnClickSpinDec(sparam)) return; //--- return; } //--- 編集イベントでの値の変化の処理 if(id==CHARTEVENT_OBJECT_ENDEDIT) { //--- コントロールがブロックされている場合は終了する if(!m_spin_edit_state) return; //--- 値の入力の処理 if(OnEndEdit(sparam)) return; } }
マウスの左ボタンがコントロールのスイッチボタンが押されたときの高速の値のスクローリングのために、コントロールのタイマーで呼び出されるCSpinEdit::FastSwitching()メソッドを書きます。このメソッドはスクロールバー付きのリストビューを作成するためのCListViewクラスについて話した時にお話ししました。このメソッドがリストをスクロールするために必要であったのに対し、ここでは編集中の値を増加または減少させる機能を持つことになります。CSpinEdit::FastSwitching() メソッドのもっと詳しいコードは下記で見られます。
class CSpinEdit : public CElement { private: //--- 編集値の高速のスクロール void FastSwitching(void); }; //+------------------------------------------------------------------+ //| タイマー | //+------------------------------------------------------------------+ void CSpinEdit::OnEventTimer(void) { //--- 要素がドロップダウンの場合 if(CElement::IsDropdown()) { ChangeObjectsColor(); FastSwitching(); } else { //--- 色の変化と値の高速のスクロールを追跡する // (フォームがブロックされていない場合) if(!m_wnd.IsLocked()) { ChangeObjectsColor(); FastSwitching(); } } } //+------------------------------------------------------------------+ //| 編集値の高速のスクロール | //+------------------------------------------------------------------+ void CSpinEdit::FastSwitching(void) { //--- コントロールがフォーカスされていない場合は終了する if(!CElement::MouseFocus()) return; //--- マウスボタンが離されたらカウンタを初期値に戻す if(!m_mouse_state) m_timer_counter=SPIN_DELAY_MSC; //--- マウスボタンが長押しされた場合 else { //--- 設定されたステップでカウンタを増加する m_timer_counter+=TIMER_STEP_MSC; //--- 0未満の場合は終了する if(m_timer_counter<0) return; //--- 現在の編集値を取得する double current_value=::StringToDouble(m_edit.Description()); //--- 増加の場合 if(m_spin_inc.State()) SetValue(current_value+m_step_value); //--- 減少の場合 else if(m_spin_dec.State()) SetValue(current_value-m_step_value); //--- スイッチボタンがまだ押されていたら値を変える if(m_spin_inc.State() || m_spin_dec.State()) m_edit.Description(::DoubleToString(GetValue(),m_digits)); } }
編集コントロールの検証
編集コントロールのすべてのメソッドが実装されました。先に用意したプログラムでテストしてみましょう。アプリケーションのCProgramカスタムクラスでCSpinEdit クラスのインスタンスを作成し編集コントロール作成メソッドを宣言します。
//+------------------------------------------------------------------+ //| アプリケーション作成クラス | //+------------------------------------------------------------------+ class CProgram : public CWndEvents { private: //--- 編集コントロール CSpinEdit m_spin_edit1; //--- private: //--- 編集コントロール #define SPINEDIT1_GAP_X (150) #define SPINEDIT1_GAP_Y (75) bool CreateSpinEdit1(const string text); };
2番目のチェックボックスに関連して行われたように、このコントロールの可用性を管理するための最初のチェックボックスを作ってみましょう。よって、下のコードにあるように、作成後のこのコントロールの可用性は1番目のチェックボックスの状態に依存します。
//+------------------------------------------------------------------+ //| 編集コントロール1を作成する | //+------------------------------------------------------------------+ bool CProgram::CreateSpinEdit1(string text) { //--- ウィンドウポインタを格納する m_spin_edit1.WindowPointer(m_window1); //--- 座標 int x=m_window1.X()+SPINEDIT1_GAP_X; int y=m_window1.Y()+SPINEDIT1_GAP_Y; //--- 値 double v=(m_spin_edit1.GetValue()==WRONG_VALUE) ?4 : m_spin_edit1.GetValue(); //--- 作成前に優先順位を設定する m_spin_edit1.XSize(150); m_spin_edit1.YSize(18); m_spin_edit1.EditXSize(76); m_spin_edit1.MaxValue(1000); m_spin_edit1.MinValue(-1000); m_spin_edit1.StepValue(1); m_spin_edit1.SetDigits(0); m_spin_edit1.SetValue(v); m_spin_edit1.ResetMode(true); m_spin_edit1.AreaColor(clrWhiteSmoke); m_spin_edit1.LabelColor(clrBlack); m_spin_edit1.LabelColorLocked(clrSilver); m_spin_edit1.EditColorLocked(clrWhiteSmoke); m_spin_edit1.EditTextColor(clrBlack); m_spin_edit1.EditTextColorLocked(clrSilver); m_spin_edit1.EditBorderColor(clrSilver); m_spin_edit1.EditBorderColorLocked(clrSilver); //--- コントロール作成 if(!m_spin_edit1.CreateSpinEdit(m_chart_id,m_subwin,text,x,y)) return(false); //--- 可用性は1番目のチェックボックスの状態に依存する m_spin_edit1.SpinEditState(m_checkbox1.CheckButtonState()); //--- オブジェクトをオブジェクトグループの共通配列に加える CWndContainer::AddToElementsArray(0,m_spin_edit1); return(true); }
他のコントロールに似てCProgram::CreateSpinEdit1()メソッドはプログラムのグラフィカルインターフェースを作成するメインメソッドで呼び出されます。下記はメソッドの短縮版です。
//+------------------------------------------------------------------+ //| 取引パネルを作成する | //+------------------------------------------------------------------+ bool CProgram::CreateTradePanel(void) { //--- コントロールのフォー1の作成 //--- コントロールの作成: // メインメニュー //--- コンテキストメニュー //--- ステータスバーの作成 //--- チェックボックス //--- 編集コントロール if(!CreateSpinEdit1("Spin Edit 1:")) return(false); //--- チャートの再描画 m_chart.Redraw(); return(true); }
CProgram::OnEvent() イベントハンドラに編集コントロールからのリスニングイベントのテストを加えて、1番目の編集コントロールが1番目のチェックボックスの状態に依存するよう指定します。
//+------------------------------------------------------------------+ //| イベントハンドラ | //+------------------------------------------------------------------+ void CProgram::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- テキストラベル押下イベント if(id==CHARTEVENT_CUSTOM+ON_CLICK_LABEL) { ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); //--- 1番目のチェックボックスが押された場合 if(lparam==m_checkbox1.Id()) { //--- 2番目のチェックボックスと1番目の編集コントロールの状態を設定する m_checkbox2.CheckBoxState(m_checkbox1.CheckButtonState()); m_spin_edit1.SpinEditState(m_checkbox1.CheckButtonState()); } } //--- 編集イベントでの値の入力の終わり if(id==CHARTEVENT_CUSTOM+ON_END_EDIT) { ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); } //--- 変数押下イベントのスイッチボタン if(id==CHARTEVENT_CUSTOM+ON_CLICK_INC || id==CHARTEVENT_CUSTOM+ON_CLICK_DEC) { ::Print(__FUNCTION__," > id: ",id,"; lparam: ",lparam,"; dparam: ",dparam,"; sparam: ",sparam); } }
コードをコンパイルしてプログラムをチャートに読み込みます。アプリケーションのグラフィカルインターフェースは、現在以下のスクリーンショットのように見えます。
図4。編集コントロールの検証
チェックボックスを持つ他のコントロール
チェックボックスや編集コントロールの他にチェックボックスをもった編集コントロールとチェックコンボボックスを検討することは本稿の冒頭で述べました。チェックボックスをもった編集コントロールはCSpinEditクラスの拡張版で、本稿で検討されたCCheckBoxクラスのフィールドとメソッドを持ちます。
図5。チェックボックスコントロールを持った編集コントロールの複合部分
チェックコンボボックスはCComboBoxおよびCCheckBoxクラスの組み合わせと似ています。
図6。チェックコンボボックスコントロールの複合部分
CCheckBoxEdit(チェックボックスを持った編集コントロール)とCCheckComboBox(チェックコンボボックス)の実装は自学の為に本稿添付のファイルで確認可能です。CCheckComboBox型のコントロールにはドロップダウンリストビューが含まれるのでWndContainer.mqhファイルには他のドロップダウンを含む要素ににている追加が必要です。この場合ドロップダウンリストビューのポインタはm_drop_lists[] プライベートポインタ配列に格納されます。詳しい方法はグラフィカルインタフェース V:コンボボックス要素(チャプター 3)稿で見られます。
どのように動作するか確認できるように、例としてこれらのコントロールでテストアプリケーションを追加します。CCheckBox型のチェックボックスを2つとCCheckBoxEditおよびCCheckComboBox型のチェックボックスを1つ追加しましょう。CCheckBoxEdit型のコントロールの可用性は3番目のチェックボックスの状態に依存しCCheckComboBox型のコントロールの可用性は4番目のチェックボックスの状態に依存します。
図7。混合タイプのコントロールの検証
おわりに
本稿では、チェックボックス、編集コントロールやチェックボックスやコンボボックスを持つ編集コントロールなどの、多くの異なる環境のグラフィカルインタフェースとして広く使用されるコントロールを開発しました。 第2章では、スライダーとデュアルスライダーコントロールを開発します。
- グラフィカルインタフェースVI:チェックボックスコントロール、編集コントロールとその混合型(チャプター 1)
- グラフィカルインタフェースVI:スライダーとデュアルスライダーコントロール(チャプター 2)
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/2466





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