
DoEasy - コントロール(第28部):ProgressBarコントロールのバースタイル
内容
概念
現在、ライブラリ用に作成されたProgressBarコントロールのプログレスバー表示スタイルは、連続線(Continuous)の一種類ですが、このようなコントロールの表示スタイルには後2つあります。分割ブロック(Blocks)とオブジェクト内のブロックの連続スクロール(Marquee)です。Blocksスタイルは非常に明確です(連続線が、別々に配置されたブロックに置き換えられます)。ProgressBarコントロールを使用して視覚的に表示する必要のある反復の回数が事前にわからない場合、Marqueeスタイルを使用することができます。この場合、プログレスバーの幅の半分に相当する1つのブロックが常にスクロールすることになります。
これら2つのスタイルを新たに作成するとともに、プログレスバーの内部に表示するテキストを追加してみます。テキスト自体は、ライブラリのCLabelクラスの通常のオブジェクトで表現され、プログレスバーオブジェクトではなく、ProgressBarコントロールのベースであるアンダーレイオブジェクトに結合されます。テキストは、プログレスバーの幅と高さに合わせた大きさの、完全に透明なテキストラベルオブジェクトの中に描画されます。このオブジェクトは、常にProgressBarコントロールのすべてのオブジェクトの前面に表示されます。
デフォルトでは、テキストはプログレスバーに表示されませんが、ライブラリベースのプログラムの実行中にいつでも追加することができます。出力テキストとその属性(フォント、サイズ、フォントフラグ、色、不透明度など)を指定するだけです。
ライブラリクラスの改善
ProgressBarコントロールの新しいスタイルの開発を始める前に、基本的なグラフィック要素のコンストラクタを簡素化してみましょう。オブジェクトを作成した後、protectedコンストラクタとパラメトリックコンストラクタでプロパティの値を設定します。どちらのコンストラクタにも、新しいオブジェクトが作成されるときに常に追加される、100種類以上のライブラリのグラフィック要素パラメータの長いリストがあります。そのため、オブジェクトのプロパティの設定を、CGCnvElementクラスのprotectedコンストラクタとパラメトリックコンストラクタで、常に2回記述する必要があります。これらのプロパティの設定は、別の初期化メソッドに移すのが論理的でしょう。同時に、いくつかのプロパティを異なるコンストラクタで異なるように設定する場合、それらは単に新しいメソッドの仮パラメータで渡されて示されることになります。
\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqhで、オブジェクト構造体に新しいプロパティを追加します。
struct SData { //--- Object integer properties int id; // Element ID int type; // Graphical element type //---... //---... //--- int group; // Group the graphical element belongs to int tab_size_mode; // Tab size setting mode int tab_page_number; // Tab index number int tab_page_row; // Tab row index int tab_page_column; // Tab column index int progress_bar_minimum; // The lower bound of the range ProgressBar operates in int progress_bar_maximum; // The upper bound of the range ProgressBar operates in int progress_bar_step; // ProgressBar increment needed to redraw it int progress_bar_style; // ProgressBar style int progress_bar_value; // Current ProgressBar value from Min to Max int progress_bar_marquee_speed; // Progress bar animation speed in case of Marquee style //--- ulong tooltip_initial_delay; // Tooltip display delay ulong tooltip_auto_pop_delay; // Tooltip display duration ulong tooltip_reshow_delay; // One element new tooltip display delay bool tooltip_show_always; // Display a tooltip in inactive window int tooltip_icon; // Icon displayed in a tooltip bool tooltip_is_balloon; // Tooltip in the form of a "cloud" bool tooltip_use_fading; // Fade when showing/hiding a tooltip //--- Object real properties //--- Object string properties uchar name_obj[64]; // Graphical element object name uchar name_res[64]; // Graphical resource name uchar text[256]; // Graphical element text uchar descript[256]; // Graphical element description uchar tooltip_title[256]; // Element tooltip title uchar tooltip_text[256]; // Element tooltip text }; SData m_struct_obj; // Object structure
グラフィカルオブジェクトの構造体は、オブジェクトのプロパティをファイルに正しく書き込み、復元時にファイルから読み取るために必要です。この構造体に書き込まれるようになったプロパティは、オブジェクトにはすでに追加されていますが、構造体にはまだ追加されていません。構造体のフィールドとオブジェクトの特性が一致しなくても、この段階では心配ありません。今のところ、オブジェクトをファイルに保存し、そのファイルからプロパティを読み出すという実装はしていません。その後、もちろんグラフィカルオブジェクトのプロパティをファイルに保存し、そこから読み込むことになります。このとき、構造体のフィールドとオブジェクトのプロパティを完全に一致させる必要があります。
クラスのprivateセクションで、グラフィカル要素のプロパティを初期化するための新しいメソッドを宣言します。
//--- Save the colors to the background color array void SaveColorsBG(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg,colors,DFUN); } void SaveColorsBGMouseDown(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg_dwn,colors,DFUN); } void SaveColorsBGMouseOver(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg_ovr,colors,DFUN); } void SaveColorsBGInit(color &colors[]) { this.CopyArraysColors(this.m_array_colors_bg_init,colors,DFUN); } //--- Initialize property values void Initialize(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id,const int element_num, const int x,const int y,const int w,const int h, const string descript,const bool movable,const bool activity); public:
作成されたオブジェクトのプロパティは、メソッドに渡されます。プロパティはコンストラクタごとに異なる値を持つか、コンストラクタの仮パラメータに直接指定される、つまり外部から渡されます。このようなプロパティはすべて、パラメータを介してメソッドに渡すことにします。
各コンストラクタでオブジェクトのプロパティを設定する長いリストを削除し、初期化メソッドの呼び出しに置き換えます。
//+---------------------------------------------+ //| Parametric constructor | //+---------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, CGCnvElement *main_obj,CGCnvElement *base_obj, const int element_id, const int element_num, const long chart_id, const int wnd_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable=true, const bool activity=true, const bool redraw=false) : m_shadow(false) { this.SetTypeElement(element_type); this.m_type=OBJECT_DE_TYPE_GELEMENT; this.m_element_main=main_obj; this.m_element_base=base_obj; this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND); this.m_name=this.CreateNameGraphElement(element_type); this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id); this.m_subwindow=wnd_num; this.SetFont(DEF_FONT,DEF_FONT_SIZE); this.m_text_anchor=0; this.m_text_x=0; this.m_text_y=0; this.SetBackgroundColor(colour,true); this.SetOpacity(opacity); this.m_shift_coord_x=0; this.m_shift_coord_y=0; if(::ArrayResize(this.m_array_colors_bg,1)==1) this.m_array_colors_bg[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_dwn,1)==1) this.m_array_colors_bg_dwn[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_ovr,1)==1) this.m_array_colors_bg_ovr[0]=this.BackgroundColor(); if(this.Create(chart_id,wnd_num,x,y,w,h,redraw)) { this.Initialize(element_type,element_id,element_num,x,y,w,h,descript,movable,activity); this.SetVisibleFlag(false,false); } else { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj()); } } //+---------------------------------------------+ //| Protected constructor | //+---------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int wnd_num, const string descript, const int x, const int y, const int w, const int h) : m_shadow(false) { this.m_type=OBJECT_DE_TYPE_GELEMENT; this.m_element_main=main_obj; this.m_element_base=base_obj; this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND); this.m_name=this.CreateNameGraphElement(element_type); this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id); this.m_subwindow=wnd_num; this.m_type_element=element_type; this.SetFont(DEF_FONT,DEF_FONT_SIZE); this.m_text_anchor=0; this.m_text_x=0; this.m_text_y=0; this.SetBackgroundColor(CLR_CANV_NULL,true); this.SetOpacity(0); this.m_shift_coord_x=0; this.m_shift_coord_y=0; if(::ArrayResize(this.m_array_colors_bg,1)==1) this.m_array_colors_bg[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_dwn,1)==1) this.m_array_colors_bg_dwn[0]=this.BackgroundColor(); if(::ArrayResize(this.m_array_colors_bg_ovr,1)==1) this.m_array_colors_bg_ovr[0]=this.BackgroundColor(); if(this.Create(chart_id,wnd_num,x,y,w,h,false)) { this.Initialize(element_type,0,0,x,y,w,h,descript,false,false); this.SetVisibleFlag(false,false); } else { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj()); } } //+------------------------------------------------------------------+
ご覧の通り、それぞれの固有のコンストラクタに固有の値が、両方のコンストラクタの初期化メソッドに渡されます。
新しい初期化メソッドでは、クラスのコンストラクタからプロパティ設定を削除します。
//+---------------------------------------------+ //| Initialize the properties | //+---------------------------------------------+ void CGCnvElement::Initialize(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id,const int element_num, const int x,const int y,const int w,const int h, const string descript,const bool movable,const bool activity) { this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,this.m_canvas.ResourceName()); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_CHART_ID,CGBaseObj::ChartID()); // Chart ID this.SetProperty(CANV_ELEMENT_PROP_WND_NUM,CGBaseObj::SubWindow()); // Chart subwindow index this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,CGBaseObj::Name()); // Element object name this.SetProperty(CANV_ELEMENT_PROP_TYPE,element_type); // Graphical element type this.SetProperty(CANV_ELEMENT_PROP_ID,element_id); // Element ID this.SetProperty(CANV_ELEMENT_PROP_NUM,element_num); // Element index in the list this.SetProperty(CANV_ELEMENT_PROP_COORD_X,x); // Element's X coordinate on the chart this.SetProperty(CANV_ELEMENT_PROP_COORD_Y,y); // Element's Y coordinate on the chart this.SetProperty(CANV_ELEMENT_PROP_WIDTH,w); // Element width this.SetProperty(CANV_ELEMENT_PROP_HEIGHT,h); // Element height this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT,0); // Active area offset from the left edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP,0); // Active area offset from the upper edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT,0); // Active area offset from the right edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM,0); // Active area offset from the bottom edge of the element this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,movable); // Element moveability flag this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,activity); // Element activity flag this.SetProperty(CANV_ELEMENT_PROP_INTERACTION,false); // Flag of interaction with the outside environment this.SetProperty(CANV_ELEMENT_PROP_ENABLED,true); // Element availability flag this.SetProperty(CANV_ELEMENT_PROP_RIGHT,this.RightEdge()); // Element right border this.SetProperty(CANV_ELEMENT_PROP_BOTTOM,this.BottomEdge()); // Element bottom border this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_X,this.ActiveAreaLeft()); // X coordinate of the element active area this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_Y,this.ActiveAreaTop()); // Y coordinate of the element active area this.SetProperty(CANV_ELEMENT_PROP_ACT_RIGHT,this.ActiveAreaRight()); // Right border of the element active area this.SetProperty(CANV_ELEMENT_PROP_ACT_BOTTOM,this.ActiveAreaBottom()); // Bottom border of the element active area this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_X,0); // Visibility scope X coordinate this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_Y,0); // Visibility scope Y coordinate this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_WIDTH,w); // Visibility scope width this.SetProperty(CANV_ELEMENT_PROP_VISIBLE_AREA_HEIGHT,h); // Visibility scope height this.SetProperty(CANV_ELEMENT_PROP_DISPLAYED,true); // Non-hidden control display flag this.SetProperty(CANV_ELEMENT_PROP_DISPLAY_STATE,CANV_ELEMENT_DISPLAY_STATE_NORMAL);// Control display state this.SetProperty(CANV_ELEMENT_PROP_DISPLAY_DURATION,DEF_CONTROL_PROCESS_DURATION); // Control display duration this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,0); // Control area X coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,0); // Control area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,0); // Control area width this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,0); // Control area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_RIGHT,0); // Right scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_RIGHT,0); // Right scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_RIGHT,0); // Right scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_RIGHT,0); // Right scroll area height this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_X_BOTTOM,0); // Bottom scroll area X coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_Y_BOTTOM,0); // Bottom scroll area Y coordinate this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_WIDTH_BOTTOM,0); // Bottom scroll area width this.SetProperty(CANV_ELEMENT_PROP_SCROLL_AREA_HEIGHT_BOTTOM,0); // Bottom scroll area height this.SetProperty(CANV_ELEMENT_PROP_BORDER_LEFT_AREA_WIDTH,0); // Left edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_BOTTOM_AREA_WIDTH,0); // Bottom edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,0); // Right edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,0); // Top edge area width //--- this.SetProperty(CANV_ELEMENT_PROP_BELONG,ENUM_GRAPH_OBJ_BELONG::GRAPH_OBJ_BELONG_PROGRAM); // Graphical element affiliation this.SetProperty(CANV_ELEMENT_PROP_ZORDER,0); // Priority of a graphical object for receiving the event of clicking on a chart this.SetProperty(CANV_ELEMENT_PROP_BOLD_TYPE,FW_NORMAL); // Font width type this.SetProperty(CANV_ELEMENT_PROP_BORDER_STYLE,FRAME_STYLE_NONE); // Control frame style this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_TOP,0); // Control frame top size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_BOTTOM,0); // Control frame bottom size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_LEFT,0); // Control frame left size this.SetProperty(CANV_ELEMENT_PROP_BORDER_SIZE_RIGHT,0); // Control frame right size this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR,this.BackgroundColor()); // Control frame color this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE,false); // Flag of the element auto resizing depending on the content this.SetProperty(CANV_ELEMENT_PROP_AUTOSIZE_MODE,CANV_ELEMENT_AUTO_SIZE_MODE_GROW); // Mode of the element auto resizing depending on the content this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL,false); // Auto scrollbar flag this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL_MARGIN_W,0); // Width of the field inside the element during auto scrolling this.SetProperty(CANV_ELEMENT_PROP_AUTOSCROLL_MARGIN_H,0); // Height of the field inside the element during auto scrolling this.SetProperty(CANV_ELEMENT_PROP_DOCK_MODE,CANV_ELEMENT_DOCK_MODE_NONE); // Mode of binding control borders to the container this.SetProperty(CANV_ELEMENT_PROP_MARGIN_TOP,0); // Top margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_BOTTOM,0); // Bottom margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_LEFT,0); // Left margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_MARGIN_RIGHT,0); // Right margin between the fields of this and another control this.SetProperty(CANV_ELEMENT_PROP_PADDING_TOP,0); // Top margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_BOTTOM,0); // Bottom margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_LEFT,0); // Left margin inside the control this.SetProperty(CANV_ELEMENT_PROP_PADDING_RIGHT,0); // Right margin inside the control this.SetProperty(CANV_ELEMENT_PROP_TEXT_ALIGN,ANCHOR_LEFT_UPPER); // Text position within text label boundaries this.SetProperty(CANV_ELEMENT_PROP_CHECK_ALIGN,ANCHOR_LEFT_UPPER); // Position of the checkbox within control borders this.SetProperty(CANV_ELEMENT_PROP_CHECKED,false); // Control checkbox status this.SetProperty(CANV_ELEMENT_PROP_CHECK_STATE,CANV_ELEMENT_CHEK_STATE_UNCHECKED); // Status of a control having a checkbox this.SetProperty(CANV_ELEMENT_PROP_AUTOCHECK,true); // Auto change flag status when it is selected //--- this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR,CLR_DEF_CHECK_BACK_COLOR); // Color of control checkbox background this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_OPACITY,CLR_DEF_CHECK_BACK_OPACITY); // Opacity of the control checkbox background color this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_DOWN,CLR_DEF_CHECK_BACK_MOUSE_DOWN);// Color of control checkbox background when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_BACKGROUND_COLOR_MOUSE_OVER,CLR_DEF_CHECK_BACK_MOUSE_OVER);// Color of control checkbox background when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR,CLR_DEF_CHECK_BORDER_COLOR); // Color of control checkbox frame this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_OPACITY,CLR_DEF_CHECK_BORDER_OPACITY); // Opacity of the control checkbox frame color this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_DOWN,CLR_DEF_CHECK_BORDER_MOUSE_DOWN);// Color of control checkbox frame when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_FORE_COLOR_MOUSE_OVER,CLR_DEF_CHECK_BORDER_MOUSE_OVER);// Color of control checkbox frame when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR,CLR_DEF_CHECK_FLAG_COLOR); // Control checkbox color this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_OPACITY,CLR_DEF_CHECK_FLAG_OPACITY); // Control checkbox color opacity this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_DOWN,CLR_DEF_CHECK_FLAG_MOUSE_DOWN); // Control checkbox color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_CHECK_FLAG_COLOR_MOUSE_OVER,CLR_DEF_CHECK_FLAG_MOUSE_OVER); // Control checkbox color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR,CLR_DEF_FORE_COLOR); // Default text color for all control objects this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_OPACITY,CLR_DEF_FORE_COLOR_OPACITY); // Opacity of the default text color for all control objects this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN,CLR_DEF_FORE_COLOR_MOUSE_DOWN); // Default control text color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER,CLR_DEF_FORE_COLOR_MOUSE_OVER); // Default control text color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_STATE_ON,CLR_DEF_FORE_COLOR); // Text color of the control which is on this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_STATE_ON_MOUSE_DOWN,CLR_DEF_FORE_COLOR_MOUSE_DOWN);// Default control text color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_FORE_COLOR_STATE_ON_MOUSE_OVER,CLR_DEF_FORE_COLOR_MOUSE_OVER);// Default control text color when hovering the mouse over the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_DOWN,this.BackgroundColor()); // Control background color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER,this.BackgroundColor()); // Control background color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_STATE_ON,CLR_DEF_CONTROL_STD_BACK_COLOR_ON);// Background color of the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_STATE_ON_MOUSE_DOWN,CLR_DEF_CONTROL_STD_BACK_DOWN_ON);// Control background color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_STATE_ON_MOUSE_OVER,CLR_DEF_CONTROL_STD_BACK_OVER_ON);// Control background color when clicking on the control which is on this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR_MOUSE_DOWN,CLR_DEF_BORDER_MOUSE_DOWN); // Control frame color when clicking on the control this.SetProperty(CANV_ELEMENT_PROP_BORDER_COLOR_MOUSE_OVER,CLR_DEF_BORDER_MOUSE_OVER); // Control frame color when hovering the mouse over the control this.SetProperty(CANV_ELEMENT_PROP_BUTTON_TOGGLE,false); // Toggle flag of the control featuring a button this.SetProperty(CANV_ELEMENT_PROP_BUTTON_STATE,false); // Status of the Toggle control featuring a button this.SetProperty(CANV_ELEMENT_PROP_BUTTON_GROUP,false); // Button group flag this.SetProperty(CANV_ELEMENT_PROP_LIST_BOX_MULTI_COLUMN,false); // Horizontal display of columns in the ListBox control this.SetProperty(CANV_ELEMENT_PROP_LIST_BOX_COLUMN_WIDTH,0); // Width of each ListBox control column this.SetProperty(CANV_ELEMENT_PROP_TAB_MULTILINE,false); // Several lines of tabs in TabControl this.SetProperty(CANV_ELEMENT_PROP_TAB_ALIGNMENT,CANV_ELEMENT_ALIGNMENT_TOP); // Location of tabs inside the control this.SetProperty(CANV_ELEMENT_PROP_ALIGNMENT,CANV_ELEMENT_ALIGNMENT_TOP); // Location of an object inside the control this.SetProperty(CANV_ELEMENT_PROP_TEXT,""); // Graphical element text this.SetProperty(CANV_ELEMENT_PROP_DESCRIPTION,descript); // Graphical element description this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_FIXED_PANEL,0); // Panel that retains its size when the container is resized this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_FIXED,true); // Separator moveability flag this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE,50); // Distance from edge to separator this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH,4); // Separator width this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,0); // Separator location this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,false); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE,25); // Panel 1 minimum size this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,false); // Flag for collapsed panel 1 this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE,25); // Panel 2 minimum size this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY,500); // Tooltip display delay this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY,5000); // Tooltip display duration this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY,100); // One element new tooltip display delay this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS,false); // Display a tooltip in inactive window this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_ICON,CANV_ELEMENT_TOOLTIP_ICON_NONE); // Icon displayed in a tooltip this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON,false); // Tooltip in the form of a "cloud" this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_USE_FADING,true); // Fade when showing/hiding a tooltip this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE,""); // Tooltip title for the element this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT,""); // Tooltip text for the element this.SetProperty(CANV_ELEMENT_PROP_GROUP,0); // Group the graphical element belongs to this.SetProperty(CANV_ELEMENT_PROP_TAB_SIZE_MODE,CANV_ELEMENT_TAB_SIZE_MODE_NORMAL);// Tab size setting mode this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_NUMBER,0); // Tab index number this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_ROW,0); // Tab row index this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_COLUMN,0); // Tab column index this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MAXIMUM,100); // The upper bound of the range ProgressBar operates in this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM,0); // The lower bound of the range ProgressBar operates in this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STEP,10); // ProgressBar increment needed to redraw it this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE,CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS); // ProgressBar style this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,50); // Current ProgressBar value from Min to Max this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,10); // Progress bar animation speed in case of Marquee style } //+------------------------------------------------------------------+
ここでは、クラスのコンストラクタから削除された文字列を単純に移動しています。コンストラクタによって異なっていたプロパティ値が、メソッドの仮パラメータによってオブジェクトのプロパティに渡され、設定されるようになりました。
オブジェクト構造体を作成するメソッドで、新しい構造体フィールドに適切なグラフィック要素プロパティ値を設定するようにします。
//+---------------------------------------------+ //| Create the object structure | //+---------------------------------------------+ bool CGCnvElement::ObjectToStruct(void) { //--- Save integer properties this.m_struct_obj.id=(int)this.GetProperty(CANV_ELEMENT_PROP_ID); // Element ID this.m_struct_obj.type=(int)this.GetProperty(CANV_ELEMENT_PROP_TYPE); // Graphical element type this.m_struct_obj.belong=(int)this.GetProperty(CANV_ELEMENT_PROP_BELONG); // Graphical element affiliation this.m_struct_obj.number=(int)this.GetProperty(CANV_ELEMENT_PROP_NUM); // Element ID in the list //---... //---... this.m_struct_obj.border_right_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH); // Right edge area width this.m_struct_obj.border_top_area_width=(int)this.GetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH); // Top edge area width //--- this.m_struct_obj.tooltip_initial_delay=this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY); // Tooltip display delay this.m_struct_obj.tooltip_auto_pop_delay=this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY); // Tooltip display duration this.m_struct_obj.tooltip_reshow_delay=this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY); // One element new tooltip display delay this.m_struct_obj.tooltip_show_always=this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS); // Display a tooltip in inactive window this.m_struct_obj.tooltip_icon=(int)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_ICON); // Icon displayed in the tooltip this.m_struct_obj.tooltip_is_balloon=(bool)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON); // Balloon tooltip this.m_struct_obj.tooltip_use_fading=(bool)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_USE_FADING); // Fade when showing and hiding the tooltip //--- this.m_struct_obj.group=(int)this.GetProperty(CANV_ELEMENT_PROP_GROUP); // Group the graphical element belongs to this.m_struct_obj.tab_size_mode=(int)this.GetProperty(CANV_ELEMENT_PROP_TAB_SIZE_MODE); // Tab size setting mode this.m_struct_obj.tab_page_number=(int)this.GetProperty(CANV_ELEMENT_PROP_TAB_PAGE_NUMBER); // Tab index number this.m_struct_obj.tab_page_row=(int)this.GetProperty(CANV_ELEMENT_PROP_TAB_PAGE_ROW); // Tab row index this.m_struct_obj.tab_page_column=(int)this.GetProperty(CANV_ELEMENT_PROP_TAB_PAGE_COLUMN); // Tab column index this.m_struct_obj.progress_bar_maximum=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MAXIMUM); // The upper bound of the range ProgressBar operates in this.m_struct_obj.progress_bar_minimum=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM); // The lower bound of the range ProgressBar operates in this.m_struct_obj.progress_bar_step=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STEP); // ProgressBar increment needed to redraw it this.m_struct_obj.progress_bar_style=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE); // ProgressBar style this.m_struct_obj.progress_bar_value=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE); // Current ProgressBar value from Min to Max this.m_struct_obj.progress_bar_marquee_speed=(int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED);// Progress bar animation speed in case of Marquee style //--- Save real properties //--- Save string properties ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_NAME_OBJ),this.m_struct_obj.name_obj); // Graphical element object name ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_NAME_RES),this.m_struct_obj.name_res); // Graphical resource name ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TEXT),this.m_struct_obj.text); // Graphical element text ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_DESCRIPTION),this.m_struct_obj.descript);// Graphical element description ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE),this.m_struct_obj.tooltip_title);// Tooltip title for the element ::StringToCharArray(this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT),this.m_struct_obj.tooltip_text); // Tooltip text for the element //--- Save the structure to the uchar array ::ResetLastError(); if(!::StructToCharArray(this.m_struct_obj,this.m_uchar_array)) { CMessage::ToLog(DFUN,MSG_LIB_SYS_FAILED_SAVE_OBJ_STRUCT_TO_UARRAY,true); return false; } return true; } //+------------------------------------------------------------------+
構造体からオブジェクトを生成するメソッドで、現在の記事で追加された対応する構造体フィールドからオブジェクトプロパティを設定するようにします。
//+---------------------------------------------+ //| Create the object from the structure | //+---------------------------------------------+ void CGCnvElement::StructToObject(void) { //--- Save integer properties this.SetProperty(CANV_ELEMENT_PROP_ID,this.m_struct_obj.id); // Element ID this.SetProperty(CANV_ELEMENT_PROP_TYPE,this.m_struct_obj.type); // Graphical element type this.SetProperty(CANV_ELEMENT_PROP_BELONG,this.m_struct_obj.belong); // Graphical element affiliation this.SetProperty(CANV_ELEMENT_PROP_NUM,this.m_struct_obj.number); // Element index in the list //---... //---... this.SetProperty(CANV_ELEMENT_PROP_BORDER_RIGHT_AREA_WIDTH,this.m_struct_obj.border_right_area_width); // Right edge area width this.SetProperty(CANV_ELEMENT_PROP_BORDER_TOP_AREA_WIDTH,this.m_struct_obj.border_top_area_width); // Top edge area width this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY,this.m_struct_obj.tooltip_initial_delay); // Tooltip display delay this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY,this.m_struct_obj.tooltip_auto_pop_delay);// Tooltip display duration this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY,this.m_struct_obj.tooltip_reshow_delay);// One element new tooltip display delay this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS,this.m_struct_obj.tooltip_show_always);// Display a tooltip in inactive window this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_ICON,this.m_struct_obj.tooltip_icon); // Icon displayed in a tooltip this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON,this.m_struct_obj.tooltip_is_balloon); // Balloon tooltip this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_USE_FADING,this.m_struct_obj.tooltip_use_fading); // Fade when showing/hiding a tooltip this.SetProperty(CANV_ELEMENT_PROP_GROUP,this.m_struct_obj.group); // Group the graphical element belongs to this.SetProperty(CANV_ELEMENT_PROP_TAB_SIZE_MODE,this.m_struct_obj.tab_size_mode); // Tab size setting mode this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_NUMBER,this.m_struct_obj.tab_page_number); // Tab index number this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_ROW,this.m_struct_obj.tab_page_row); // Tab row index this.SetProperty(CANV_ELEMENT_PROP_TAB_PAGE_COLUMN,this.m_struct_obj.tab_page_column); // Tab column index this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MAXIMUM,this.m_struct_obj.progress_bar_maximum);// The upper bound of the range ProgressBar operates in this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM,this.m_struct_obj.progress_bar_minimum);// The lower bound of the range ProgressBar operates in this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STEP,this.m_struct_obj.progress_bar_step); // ProgressBar increment needed to redraw it this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE,this.m_struct_obj.progress_bar_style); // ProgressBar style this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,this.m_struct_obj.progress_bar_value); // Current ProgressBar value from Min to Max this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,this.m_struct_obj.progress_bar_marquee_speed); // Progress bar animation speed in case of Marquee style //--- Save real properties //--- Save string properties this.SetProperty(CANV_ELEMENT_PROP_NAME_OBJ,::CharArrayToString(this.m_struct_obj.name_obj)); // Graphical element object name this.SetProperty(CANV_ELEMENT_PROP_NAME_RES,::CharArrayToString(this.m_struct_obj.name_res)); // Graphical resource name this.SetProperty(CANV_ELEMENT_PROP_TEXT,::CharArrayToString(this.m_struct_obj.text)); // Graphical element text this.SetProperty(CANV_ELEMENT_PROP_DESCRIPTION,::CharArrayToString(this.m_struct_obj.descript));// Graphical element description this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE,::CharArrayToString(this.m_struct_obj.tooltip_title));// Tooltip title for the element this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT,::CharArrayToString(this.m_struct_obj.tooltip_text)); // Tooltip text for the element } //+------------------------------------------------------------------+
これで、グラフィック要素オブジェクトが正しくファイルに保存され、ファイルから復元されるようになりました。
プログレスバーに沿ったグレアは、平行六面体のような形状になることがあります。これは、上面の頂点が下面の頂点から6ピクセル分ずれた、傾いた四角形です。小さなオブジェクトの場合、このオフセットでオブジェクトがかなり傾いて見えるようになりますが、高さが増すと、6ピクセルに固定された傾きでは見分けがつかなくなります。この状況を改善するためには、傾きを相対的な値にする必要があります。つまり、高いオブジェクトほど傾きが強くなります。そこで、頂点のオフセットの大きさを設定するために、オブジェクトの高さを使用します。そうすると、視覚的には45度の傾きになります。
\MQL5\Include\DoEasy\Objects\Graph\WForms\GlareObj.mqhにある、オブジェクトのグレア形状を平行四辺形で描画するメソッドで、頂点座標のパラメータの初期化を修正しました。数値6の代わりに、グラフィカルオブジェクトの高さの値を代入します。
//+------------------------------------------------------------------+ //| Draw the shape of the object glare as a parallelogram | //+------------------------------------------------------------------+ void CGlareObj::DrawFigureParallelogram(void) { int array_x[]={this.Height(),this.Width()-1,this.Width()-1-this.Height(),0}; int array_y[]={0,0,this.Height()-1,this.Height()-1}; CGCnvElement::DrawPolygonFill(array_x,array_y,this.m_color,this.OpacityDraw()); CGCnvElement::Update(); } //+------------------------------------------------------------------+
これで、頂点はオブジェクトの高さの値だけオフセットされ、オブジェクトの高さに関係なく、常に約45度の傾きを持つようになります。
各ブロックを直接作成したり、単純に描画したりと、さまざまなオプションを使って「分割ブロック」式のプログレスバーを作成することができます。これは、次のようにおこなうつもりです。すでに完全に塗りつぶされたプログレスバーがあるので、ブロックがないところだけこのオブジェクトの背景を消せばいいのです。この場合、分割されたブロックからなるプログレスバーの外観を得ることができます。この方法の欠点は各ブロックの位置を計算する必要があることで、利点は実装が簡単であることです。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\BarProgressBar.mqhのprivateセクションで、セグメントパラメータ格納用変数を追加してオブジェクト背景分割用メソッドを宣言します。
//+------------------------------------------------------------------+ //| BarProgressBar object class of the ProgressBar control | //+------------------------------------------------------------------+ class CBarProgressBar : public CWinFormBase { private: int m_segment_s; // Segment countdown start int m_segment_x; // Last segment X coordinate int m_segment_w; // Segment width int m_segment_d; // Distance between segments //--- Segment the background void Segmentation(void); //--- (1) Set and (2) return a pause before displaying the effect void SetShowDelay(const long delay) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY,delay); } ulong ShowDelay(void) { return this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY); } //--- Initialize the properties void Initialize(void); protected: //--- Protected constructor with object type, chart ID and subwindow CBarProgressBar(const ENUM_GRAPH_ELEMENT_TYPE type, CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); public:
宣言された変数には、セグメントの位置を計算するための初期パラメータが含まれます。セグメントの幅は常に高さの3/4となり、セグメント間の距離は結果として得られるセグメントの幅から計算されます。このデータは、オブジェクトの初期化時に記録され、その番号によって任意のセグメントの位置を計算することができるようになります。セグメントそのものを描くのではなく、セグメント間のスペースを描くので、開始点は0から数えても1から数えても最初のセグメントの幅となります。プログレスバーの高さが3ピクセル以上の場合は、オブジェクトの端の四方に1ピクセルの空白を描画する必要があります。これにより、セグメントとバーの外側の端が分離され、視覚的に独立した単位になります。この場合、最初のセグメントのインデントは、オブジェクトの端から最初のセグメントまでの1ピクセルの空白である1から開始する必要があります。プログレスバーの高さが3ピクセル以下であれば、空白を描く必要はなく、セグメントが描かれたオブジェクトの使用可能領域全体を占めることになります。この場合、最初のセグメントの開始点までのインデントは0でなければなりません。
クラスのpublicセクションに、プログレスバーのスタイルを返すメソッドと、セグメントの変数パラメータの値を返すメソッドを実装します。セグメントの幅とその間の距離を計算するメソッドを宣言してみましょう。また、オブジェクトの背景をクリアするための仮想メソッドも再定義する必要があります。
public: //--- Set the (1) animation speed in case of Marquee style, (2) display style, (3) increment value and (4) the current value of the ProgressBar control void SetMarqueeAnimationSpeed(const int value) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MARQUEE_ANIM_SPEED,value); } void SetStyle(const ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE style) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE,style); } void SetStep(const int value) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STEP,value); } void SetValue(const int value) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,value); } //--- Return the display style ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE Style(void) const { return (ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_STYLE); } //--- Return (1) the X coordinate of the last segment, (2) segment width, (3) distance between segments and (4) segment countdown start int SegmentX(void) const { return this.m_segment_x; } int SegmentWidth(void) const { return this.m_segment_w; } int SegmentDistance(void) const { return this.m_segment_d; } int SegmentStart(void) const { return this.m_segment_s; } //--- Calculate (1) the segment width and (2) the distance between segments int CalculateSegmentWidth(void); int CalculateSegmentDistance(const int width); //--- Supported object properties (1) integer, (2) real and (3) string ones virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_STRING property) { return true; } //--- Clear the element filling it with color and opacity virtual void Erase(const color colour,const uchar opacity,const bool redraw=false); //--- Clear the element with a gradient fill virtual void Erase(color &colors[],const uchar opacity,const bool vgradient,const bool cycle,const bool redraw=false); //--- Constructor CBarProgressBar(CGCnvElement *main_obj,CGCnvElement *base_obj, const long chart_id, const int subwindow, const string descript, const int x, const int y, const int w, const int h); //--- Timer virtual void OnTimer(void); }; //+------------------------------------------------------------------+
クリアメソッドでは、要素の背景がその背景色で塗りつぶされます。そのため、塗りつぶした後、セグメント間の隙間の背景を除去する必要があります。これらのメソッドでは、描画されたオブジェクトの背景を分割するために、privateセクションで宣言されたメソッドを呼び出すことになります。これらは仮想なので、オブジェクトがプログレスバーやそれから継承されたものであれば、クリーニングメソッドを呼び出す際に必ずこれらのメソッドが呼び出されることになります。
オブジェクトプロパティ初期化メソッドで、セグメンテーションパラメータを格納する変数のデフォルト値を入力します。最後のセグメントのx座標とカウントダウン開始はゼロに等しく、セグメント幅とその間の距離は一度に計算されます。
//+---------------------------------------------+ //| Initialize the properties | //+---------------------------------------------+ void CBarProgressBar::Initialize(void) { this.SetPaddingAll(0); this.SetMarginAll(0); this.SetBorderSizeAll(0); this.SetBackgroundColor(CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR,true); this.SetBorderColor(CLR_DEF_CONTROL_PROGRESS_BAR_BAR_COLOR,true); this.SetForeColor(CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR,true); this.SetShowDelay(2000); this.m_segment_x=0; this.m_segment_s=0; this.m_segment_w=this.CalculateSegmentWidth(); this.m_segment_d=this.CalculateSegmentDistance(this.m_segment_w); } //+------------------------------------------------------------------+
宣言されたメソッドについて詳しく考えてみましょう。
以下は、色と不透明度を指定して要素をクリアするメソッドです。
//+------------------------------------------------------------------+ //| Clear the element filling it with color and opacity | //+------------------------------------------------------------------+ void CBarProgressBar::Erase(const color colour,const uchar opacity,const bool redraw=false) { //--- Fill the element having the specified color and the redrawing flag CGCnvElement::EraseNoCrop(colour,opacity,false); //--- Segment the background this.Segmentation(); //--- If the object has a frame, draw it if(this.BorderStyle()!=FRAME_STYLE_NONE) this.DrawFormFrame(this.BorderSizeTop(),this.BorderSizeBottom(),this.BorderSizeLeft(),this.BorderSizeRight(),this.BorderColor(),this.Opacity(),this.BorderStyle()); //--- Crop the excess and update the element with the specified redraw flag this.Crop(); this.Update(redraw); } //+------------------------------------------------------------------+
ここでは、まず要素の背景全体が塗りつぶされます。そして、セグメンテーションメソッドが呼び出され、オブジェクトの中でセグメントがない場所の背景を消去します。オブジェクトがフレームを持つ場合は、フレームが描画されます。オブジェクトの親コンテナからはみ出した部分が切り取られ、オブジェクトの背景がメソッドに渡されたチャート再描画フラグで更新されます。
以下は、グラデーションで塗りつぶされた要素をクリアするメソッドです。
//+---------------------------------------------+ //| Clear the element with a gradient fill | //+---------------------------------------------+ void CBarProgressBar::Erase(color &colors[],const uchar opacity,const bool vgradient,const bool cycle,const bool redraw=false) { //--- Fill the element having the specified color array and the redrawing flag CGCnvElement::EraseNoCrop(colors,opacity,vgradient,cycle,false); //--- Segment the background this.Segmentation(); //--- If the object has a frame, draw it if(this.BorderStyle()!=FRAME_STYLE_NONE) this.DrawFormFrame(this.BorderSizeTop(),this.BorderSizeBottom(),this.BorderSizeLeft(),this.BorderSizeRight(),this.BorderColor(),this.Opacity(),this.BorderStyle()); //--- Crop the excess and update the element with the specified redraw flag this.Crop(); this.Update(redraw); } //+------------------------------------------------------------------+
メソッドのロジックは上記のメソッドと同じですが、メソッドに渡されるのは単色ではなく、グラデーション塗りの色配列とその方向フラグ(垂直/水平、周期的)であることが異なります。
以下は、セグメントの幅を計算するメソッドです。
//+---------------------------------------------+ //| Calculate the segment width | //+---------------------------------------------+ int CBarProgressBar::CalculateSegmentWidth(void) { int w=(int)::ceil((this.Height()-2)/1.75); return(w>3 ? w : 3); } //+------------------------------------------------------------------+
セグメントの幅は高さの3分の2でなければなりません。このメソッドでは、プログレスバーオブジェクトの高さをもとにセグメントの幅を計算します。オブジェクトの高さから2ピクセルを引いた値をとってみましょう。より多くの場合、プログレスバーの高さは3ピクセル以上になるため、プログレスバーの周囲に沿って両側に1ピクセルずつの空き領域が描かれ、セグメントの可視部の高さが2ピクセル(上と下に1ピクセルずつ)減少することになります。出来上がった高さを1.75で割ると、アスペクト比が3/4になります。高さが小さすぎるセグメントは幅が1~2ピクセルになると見栄えが悪くなるので、結果の幅が3ピクセルに満たない場合は、幅を3ピクセルにします。
以下は、セグメント間の距離を計算するメソッドです。
//+---------------------------------------------+ //| Calculate the distance between segments | //+---------------------------------------------+ int CBarProgressBar::CalculateSegmentDistance(const int width) { int d=(int)::ceil(width/6); return(d<1 ? 1 : d); } //+------------------------------------------------------------------+
簡単なことです。このメソッドは、インデントが計算されるべき幅を受け取ります。セグメント間の距離はブロックの幅の6分の1で、1ピクセル以上でなければなりません。
以下は、背景のセグメンテーションメソッドです。
//+---------------------------------------------+ //| Segment the background | //+---------------------------------------------+ void CBarProgressBar::Segmentation(void) { //--- If the drawing style is not "Segmented blocks", leave if(this.Style()!=CANV_ELEMENT_PROGRESS_BAR_STYLE_BLOCKS) return; //--- Reset the X coordinate of the segment this.m_segment_x=0; //--- Get the block width as 3/4 of its height int w=this.SegmentWidth(); //--- Get the distance between the segments (six times less than the block width) int d=this.SegmentDistance(); //--- Get the countdown start this.m_segment_s=w+(this.Height()>3 ? 1 : 0); //--- In the loop from the beginning of the countdown to the width of the progress bar with a step in the block width + indent between segments for(int i=this.SegmentStart();i<this.Width();i+=w+d) { //--- draw an empty fully transparent rectangle (erasing the element background) this.DrawRectangleFill(i,0,i+d-1,this.Height()-1,CLR_CANV_NULL,0); //--- Store the X coordinate of the segment this.m_segment_x=i; } //--- If the height of the progress line is more than three pixels, draw a completely transparent frame around the perimeter if(this.Height()>3) this.DrawRectangle(0,0,this.Width()-1,this.Height()-1,CLR_CANV_NULL,0); } //+------------------------------------------------------------------+
メソッドのロジックはコードのコメントで完全に説明されています。プログレスバーのスタイルが「分割ブロック」の場合、ループでオブジェクトの背景全体を調べ、セグメントがない所の背景を消します。オブジェクトの高さが3ピクセル以上の場合は、さらに周囲に沿った背景を1ピクセル幅の境界線で消去し、セグメントをプログレスバーの端から分離させます。
ProgressBarオブジェクトに、プログレスバーに表示される説明を含める機能を追加します。デフォルトでは、説明は表示されませんが、説明を有効にするためにテキストを定義するだけで十分です。説明は、オブジェクトに恒久的に添付されたCLabelオブジェクトによって構築されます。もちろん、そのようなオブジェクトをいくつでも作り、適材適所に配置することが可能になりますが、プログレスバーの説明オブジェクトは、ProgressBarの作成時にデフォルトで作成され、特別なメソッドを使用してアクセスすることが容易になります。
MQL5\Include\DoEasy\Objects\Graph\WForms\Common Controls\ProgressBar.mqh CProgressBarクラスファイルで、不要になったスキップステップ数を格納する変数をprivateセクションから削除しました。
//+------------------------------------------------------------------+ //| ArrowLeftRightBox object class of WForms controls | //+------------------------------------------------------------------+ class CProgressBar : public CContainer { private: int m_progress_bar_max; // Maximum progress bar width int m_value_by_max; // Value relative to Maximum int m_steps_skipped; // Number of skipped steps of increasing the width of the progress bar //--- Create a new graphical object
また、privateセクションで、プログレスバーの説明のあるテキストラベルのプロパティを格納するための変数を宣言します。
//+------------------------------------------------------------------+ //| ArrowLeftRightBox object class of WForms controls | //+------------------------------------------------------------------+ class CProgressBar : public CContainer { private: int m_progress_bar_max; // Maximum progress bar width int m_value_by_max; // Value relative to Maximum int m_progress_bar_text_x; // X coordinate of the text label with the description of the progress bar int m_progress_bar_text_y; // Y coordinate of the text label with the description of the progress bar color m_progress_bar_text_color; // Color of the text describing the progress bar uchar m_progress_bar_text_opacity; // Opacity of the text describing the progress bar string m_progress_bar_text; // Text describing the progress bar ENUM_FRAME_ANCHOR m_progress_bar_text_anchor; // Method for binding the text with a progress bar description //--- Create a new graphical object
この変数は、プログレスバーの説明として機能するテキストラベルオブジェクトのプロパティを設定したり、返したりするために必要です。
説明行に表示されるデータは、実行の各ステップを表示する実データと、すでに完了したステップの割合のいずれかを選択できます。
クラスのpublicセクションで、値をテキストとして返すメソッドと、数値とテキスト形式の割合を返すメソッドを実装します。
//--- (1) Set and (2) return the current value of the progress bar in the range from Min to Max as a number and (3) as a text void SetValue(const int value); int Value(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE); } string ValueDescription(void) const { return (string)this.Value(); } //--- Return the current progress bar value in the range from Min to Max as a percentage in the form of (1) a number and (2) a text double ValuePercent(void) const; string ValuePercentDescription(void) const { return ::DoubleToString(this.ValuePercent(),2)+"%"; } //--- (1) Set and (2) return the upper bound of the ProgressBar operating range
グレアのオブジェクトへのアクセスを簡略化するため、クラスのpublicセクションに、グレアのプロパティを設定するメソッドと、作成した添付オブジェクトへのポインタを取得するメソッドを宣言し、プログレスバー説明オブジェクトを扱うメソッドを宣言します。
//--- (1) Set and (2) return the lower bound of the ProgressBar operating range void SetMinimum(const int value) { this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM,value); } int Minimum(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_MINIMUM); } //--- Set (1) style, (2) opacity and (3) color for the glare object void SetGlareStyle(const ENUM_CANV_ELEMENT_VISUAL_EFF_STYLE style); void SetGlareOpacity(const uchar opacity); void SetGlareColor(const color clr); //--- Return the pointer to the (1) progress bar object, (2) glare object and (3) the text label object with the progress bar description CBarProgressBar *GetProgressBar(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR,0); } CGlareObj *GetGlareObj(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ,0); } CLabel *GetProgressDescriptionObj(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_LABEL,0); } //--- Set the (1) text, (2) color //--- (3) opacity, (4) X, (5) Y coordinates, (6) font, (7) size and (8) font flags to the progress bar text label void SetBarDescriptionText(const string text,const bool redraw=false); void SetBarDescriptionColor(const color clr,const bool redraw=false,const bool set_init_color=false); void SetBarDescriptionOpacity(const uchar opacity,const bool redraw=false); void SetBarDescriptionX(const int x,const bool redraw=false); void SetBarDescriptionY(const int y,const bool redraw=false); void SetBarDescriptionFontName(const string font,const bool redraw=false); void SetBarDescriptionFontSize(const int size,const bool relative=false,const bool redraw=false); void SetBarDescriptionFontFlags(const uint flags,const bool redraw=false); //--- (1) hide and (2) display the progress bar text label void HideBarDescription(void); void ShowBarDescription(void); //--- Resets the progress bar values to the set minimum
クラスコンストラクタで、すべての変数をデフォルト値で初期化します。
//+---------------------------------------------+ //| Initialize the element properties | //+---------------------------------------------+ void CProgressBar::Initialize(void) { this.SetBorderSizeAll(1); this.SetBorderStyle(FRAME_STYLE_SIMPLE); this.SetBackgroundColor(CLR_DEF_CONTROL_PROGRESS_BAR_BACK_COLOR,true); this.SetBorderColor(CLR_DEF_CONTROL_PROGRESS_BAR_BORDER_COLOR,true); this.SetForeColor(CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR,true); this.SetMarqueeAnimationSpeed(10); this.SetMaximum(100); this.SetMinimum(0); this.SetValue(50); this.SetStep(10); this.SetStyle(CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS); this.m_progress_bar_max=this.Width()-this.BorderSizeLeft()-this.BorderSizeRight(); this.m_value_by_max=this.Value()*100/this.Maximum(); this.m_progress_bar_text=""; this.m_progress_bar_text_x=1; this.m_progress_bar_text_y=0; this.m_progress_bar_text_color=CLR_DEF_CONTROL_PROGRESS_BAR_FORE_COLOR; this.m_progress_bar_text_opacity=255; this.m_progress_bar_text_anchor=FRAME_ANCHOR_LEFT_TOP; } //+------------------------------------------------------------------+
プログレスバーオブジェクトを作成するメソッドでは、グレアオブジェクトも作成します。また、プログレスバーの説明オブジェクトも追加して作成します。
//+---------------------------------------------+ //| Create the progress bar object | //+---------------------------------------------+ void CProgressBar::CreateProgressBar(void) { //--- Set the length of the progress bar equal to the object Value() //--- The height of the progress bar is set equal to the height of the object minus the top and bottom border sizes int w=this.CalculateProgressBarWidth(); int h=this.Height()-this.BorderSizeTop()-this.BorderSizeBottom(); if(h<1) h=1; //--- Create the progress bar object this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR,0,0,w,h,clrNONE,255,false,false); //--- Create a description of the progress bar, get the text label object and set the default parameters this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_LABEL,1,0,this.Width()-2,this.Height()-2,clrNONE,0,false,false); CLabel *obj=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_LABEL,0); if(obj!=NULL) { obj.SetText(this.m_progress_bar_text); obj.SetFontName(DEF_FONT); obj.SetFontSize(DEF_FONT_SIZE); obj.SetTextAnchor(FRAME_ANCHOR_LEFT_TOP); obj.SetTextAlign(ANCHOR_LEFT_UPPER); this.HideBarDescription(); } //--- Create the glare object this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ,0,0,w,h,CLR_CANV_NULL,0,true,false); //--- Add the current CProgressBar object to the list of active elements of the collection this.AddObjToListActiveElements(); } //+------------------------------------------------------------------+
テキストラベルを作成した直後に、このオブジェクトへのポインタを取得し、テキスト、フォント名、フォントサイズ、アンカー方法、テキストアライメントなどのプロパティを設定し、作成したオブジェクトを非表示にします。オブジェクトの残りのパラメータは、後でGetProgressDescriptionObj()メソッドでこのオブジェクトへのポインタを取得し、既に受信しているオブジェクトに必要なプロパティを設定することで取得できます。
オブジェクトをゼロサイズで作成することができないため、高さが1ピクセル未満のプログレスバーオブジェクトを作成しようとしてもうまくいきません。そこで、ゼロサイズに対するチェックを導入し、チェックが肯定的な場合に調整することにします。
新しいグラフィカルオブジェクトを作成するメソッドで、テキストラベルオブジェクトを作成するためのコードブロックを追加します。
//+---------------------------------------------+ //| Create a new graphical object | //+---------------------------------------------+ CGCnvElement *CProgressBar::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int obj_num, const string descript, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity) { CGCnvElement *element=NULL; switch(type) { case GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR : element=new CBarProgressBar(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ : element=new CGlareObj(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_LABEL : element=new CLabel(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; default: break; } if(element==NULL) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),this.TypeElementDescription(type)); return element; } //+------------------------------------------------------------------+
これで、ProgressBarオブジェクトは、ProgressBar、Glare、結合されたテキストラベル型のオブジェクトを作成できるようになりました。
ProgressBarオブジェクトは、タイマーの中で扱われるアクティブコントロールです。今のところ、タイマーはプログレスバーに沿って流れるグレアに対応しています。Marqueeスタイルで表示されるプログレスバーもタイマーで処理することになります。このモードでは、プログレスバーはオブジェクト全体の半分の幅で固定され、ProgressBarオブジェクトの内部で常にスクロールし、繰り返し回数が事前にわからない処理の進行状況を表示します。
オブジェクトタイマーハンドラに、以下のようなプログレスバーの処理を追加してみましょう。
//+---------------------------------------------+ //| Timer | //+---------------------------------------------+ void CProgressBar::OnTimer(void) { CBarProgressBar *bar=this.GetProgressBar(); if(bar!=NULL) { if(bar.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE) { int x=bar.CoordX()+8; if(x>this.RightEdge()) x=this.CoordX()-bar.Width(); bar.Move(x,bar.CoordY()); bar.Redraw(true); } else bar.OnTimer(); } } //+------------------------------------------------------------------+
ここでは、プログレスバーの表示スタイルが「連続スクロール」の場合、オブジェクトを移動させる必要があるX座標を取得します。現時点では、現在のX座標に8ピクセルのオフセットを加え、プログレスバーを新しい座標に水平方向に移動させます。この場合、オブジェクトのX座標を設定して、オブジェクトがコンテナの左端を越えて左側の幅の値になるようにします。Redraw()メソッドでは、オブジェクトを再描画するだけでなく、もう1つの機能として、コンテナの端からはみ出したオブジェクトの部分を切り落とします。コンテナの中でプログレスバーを動かすと同時に、端からはみ出した部分が切り落とされるという、完全なサイクルを作り出しました。
オブジェクトのレンダリングスタイルが異なる場合は、プログレスバーオブジェクトのタイマーを呼び出して、グレアオブジェクトを表示します。
プログレスバーの描画スタイルが「分割ブロック」になったので、プログレスバーの値を設定するメソッドを改良する必要があります。現在、このメソッドは、値を設定した後、直ちに新しい値に従ってオブジェクトのサイズを変更します。しかし、分割されたブロックはピクセル単位ではなく、ブロック単位で描画する必要があるため、設定されたプログレスバーの幅に何個のブロックが収まるかを把握する必要があります。もし、新しいセグメントを描くのに十分な幅があれば、オブジェクトはそのプロパティにすでに設定されている幅を変更します。幅が足りない場合(現在の描画セグメントが不完全で切り取られる)、オブジェクトの設定幅から1セグメントの幅を引き、ちょうどこの幅をプログレスバーに設定する必要があります。その場合、前のセグメントをすべて含む最後のセグメントのみが描画されます。したがって、オブジェクトの幅は、すべてのセグメントが切り取られずに完全に描画できる場合にのみ常に変化し、プログレスバーの可視幅がブロックごとに変化することになります。この場合、値は常にオブジェクトに渡されたものとなります。つまり、視覚的に離散的に幅を変えるだけで、中の値は常にそのオブジェクトに設定されているものになります。
プログレスバーの現在値を設定するメソッドに、上記のような改善点を実装する予定です。
//+---------------------------------------------+ //| Set the current value of the progress bar | //+---------------------------------------------+ void CProgressBar::SetValue(const int value) { //--- Correct the value passed to the method and set it to the object property int v=(value<this.Minimum() ? this.Minimum() : value>this.Maximum() ? this.Maximum() : value); this.SetProperty(CANV_ELEMENT_PROP_PROGRESS_BAR_VALUE,v); //--- Get the progress bar object CBarProgressBar *bar=this.GetProgressBar(); if(bar!=NULL) { //--- Set 'value' for the progress bar bar.SetValue(v); //--- Calculate the width of the progress bar object int w=this.CalculateProgressBarWidth(); //--- If the calculated width is greater than the maximum possible value, set the maximum width if(w>this.m_progress_bar_max) w=this.m_progress_bar_max; //--- If the width is less than 1, then if(w<1) { //--- hide the progress bar and redraw the chart to display changes immediately bar.Hide(); ::ChartRedraw(bar.ChartID()); } //--- If the width value is not less than 1 else { //--- If the progress bar is hidden, display it and if(!bar.IsVisible()) bar.Show(); //--- If the style of the progress bar is "Continuous line", change the width of the object to the calculated value if(this.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS) bar.Resize(w,bar.Height(),true); //--- Otherwise, if the progress bar style is "Segmented blocks" else if(this.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_BLOCKS) { //--- Segment width including indent int wd=bar.SegmentWidth()+bar.SegmentDistance(); //--- The number of segments that fit the width of the progress bar int num=w/(wd>0 ? wd : 1); //--- The X coordinate of the last segment calculated from the beginning of the segment count int wx=bar.SegmentStart()+num*wd; //--- If the calculated width of the progress bar is less than the coordinate of the last segment, and this is not the last segment, //--- set the width of the progress bar equal to the penultimate segment coordinate if(w<wx-bar.SegmentDistance() && w<this.m_progress_bar_max) w=wx-wd+bar.SegmentDistance(); //--- If the calculated width of the progress bar is less than the coordinate of the last segment, or it is not the last segment, if(w<wx-bar.SegmentDistance() || w==this.m_progress_bar_max) //--- change the size of the progress bar in accordance with the received and adjusted width bar.Resize(w,bar.Height(),true); } } //--- If the progress bar description text is set, if(this.m_progress_bar_text!="") { //--- get the object description of the progress bar and bring it to the foreground CLabel *obj=this.GetProgressDescriptionObj(); if(obj!=NULL) obj.BringToTop(); } } } //+------------------------------------------------------------------+
メソッドのロジックは、コードのコメントで説明されています。プログレスバーの値を変更するたびに、説明も変更する必要がある場合があります。したがって、このオブジェクトにテキストが設定されている場合は、常に前景に表示されます。
プログレスバーの幅を計算するメソッドは、プログレスバーのスタイルが「連続スクロール」に設定されている場合にProgressBarコントロールのサイズの半分を返すように改良する必要があります。
//+---------------------------------------------+ //| Calculate the width of the progress bar | //+---------------------------------------------+ int CProgressBar::CalculateProgressBarWidth(void) { this.m_value_by_max=this.Value()*100/this.Maximum(); return(this.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE ? this.m_progress_bar_max/2 : this.m_progress_bar_max*this.m_value_by_max/100); } //+------------------------------------------------------------------+
これで、このメソッドは、どの表示スタイルでも正しいスクロールバーのサイズを返すようになりました。
新しい幅を設定するメソッドでは、プログレスバーの説明を表示するためのテキストラベルオブジェクトにも、オブジェクトに設定された幅を割り当てる必要があります。
//+---------------------------------------------+ //| Set a new width | //+---------------------------------------------+ bool CProgressBar::SetWidth(const int width) { if(!CGCnvElement::SetWidth(width)) return false; this.m_progress_bar_max=this.Width()-this.BorderSizeLeft()-this.BorderSizeRight(); CBarProgressBar *bar=this.GetProgressBar(); if(bar==NULL) return false; int w=this.CalculateProgressBarWidth(); bar.SetWidth(w); CLabel *lbl=this.GetProgressDescriptionObj(); if(lbl!=NULL) lbl.SetWidth(w); return true; } //+------------------------------------------------------------------+
テキストラベルオブジェクトのサイズをプログレスバーのサイズに合わせないと、プログレスバーの見かけ上のサイズに合わせて書いたテキストが、見た目より小さい幅のオブジェクトに収まらない場合があります。これにより、テキストが単に切り取られることになります。そのため、テキストラベルとプログレスバーは同じ寸法であることが必要です。
ProgressBarコントロールに結合されているオブジェクトのプロパティへのアクセスを容易にする補助メソッドについて見てみましょう。
以下は、グレアオブジェクトにスタイルを設定するメソッドです。
//+---------------------------------------------+ //| Set the glare object style | //+---------------------------------------------+ void CProgressBar::SetGlareStyle(const ENUM_CANV_ELEMENT_VISUAL_EFF_STYLE style) { CGlareObj *obj=this.GetGlareObj(); if(obj==NULL) return; obj.SetVisualEffectStyle(style); } //+------------------------------------------------------------------+
ここでは、グレアオブジェクトへのポインタを取得し、その結果のオブジェクトにスタイルを設定しています。
以下は、グレアオブジェクトの不透明度を設定するメソッドです。
//+---------------------------------------------+ //| Set the opacity of the highlight object | //+---------------------------------------------+ void CProgressBar::SetGlareOpacity(const uchar opacity) { CGlareObj *obj=this.GetGlareObj(); if(obj==NULL) return; obj.SetOpacity(opacity); } //+------------------------------------------------------------------+
グレアオブジェクトへのポインタを取得し、結果のオブジェクトに不透明度を設定します。
以下は、グレアオブジェクトに色を設定するメソッドです。
//+---------------------------------------------+ //| Set the color for the glare object | //+---------------------------------------------+ void CProgressBar::SetGlareColor(const color clr) { CGlareObj *obj=this.GetGlareObj(); if(obj==NULL) return; obj.SetColor(clr); } //+------------------------------------------------------------------+
グレアオブジェクトへのポインタを取得し、メソッドに渡されたカラー値を結果のオブジェクトに設定します。
以下は、プログレスバーのテキストラベルにテキストを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set a text to the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionText(const string text,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text=text; obj.SetText(text); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
ここでは、テキストラベルオブジェクトへのポインタを取得しています。このメソッドに渡されたテキストをm_progress_bar_text変数に設定します。そして、そのテキストをオブジェクトに設定します。テキストはすぐにオブジェクトに表示されるので、テキストが他のテキストと重ならないように、背景とその上に描かれたものはすべて消去する必要があります。次に、テキストを表示し、要素を更新します。
以下は、プログレスバーのテキスト色をテキストラベルに設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the text color of the progress bar to the text label | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionColor(const color clr,const bool redraw=false,const bool set_init_color=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text_color=clr; obj.SetForeColor(clr,false); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
テキストラベルオブジェクトへのポインタを取得します。変数m_progress_bar_text_colorに、このメソッドに渡された色を設定します。次に、そのオブジェクトの色を文字色として設定します。テキストはすぐに表示されるため、テキストが他のテキストと重ならないように、テキストラベルの背景は消去されます。さらに、テキストが表示され、要素が更新されます。
以下は、プログレスバーのテキストラベルに不透明度を設定するメソッドです。
//+---------------------------------------------+ //| Set opacity to the progress bar text label | //+---------------------------------------------+ void CProgressBar::SetBarDescriptionOpacity(const uchar opacity,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text_opacity=opacity; obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
メソッドのロジックは上記と同じですが、不透明度の値を対応する変数とオブジェクトに設定しています。
以下は、プログレスバーのテキストラベルにX座標を設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the X coordinate to the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionX(const int x,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text_x=x; obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
以下は、プログレスバーのテキストラベルにY座標を設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the Y coordinate to the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionY(const int y,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; this.m_progress_bar_text_y=y; obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
以下は、プログレスバーのテキストラベルにフォントを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the font in the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionFontName(const string font,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetFontName(font); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
以下は、プログレスバーのテキストラベルにフォントサイズを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the font size to the progress bar text label | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionFontSize(const int size,const bool relative=false,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetFontSize(size,relative); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
以下は、プログレスバーのテキストラベルにフォントフラグを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the font flags in the text label of the progress bar | //+------------------------------------------------------------------+ void CProgressBar::SetBarDescriptionFontFlags(const uint flags,const bool redraw=false) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetFontFlags(flags); obj.Erase(false); obj.Text(this.m_progress_bar_text_x,this.m_progress_bar_text_y,this.m_progress_bar_text,this.m_progress_bar_text_color,this.m_progress_bar_text_opacity,this.m_progress_bar_text_anchor); obj.Update(redraw); } //+------------------------------------------------------------------+
上に示したメソッドはすべて同じロジックで、プログレスバーの記述に(テキストラベルに)希望のテキストとフォントのパラメータを素早く設定することができます。変更内容はすぐに画面に表示されます。
プログレスバーの記述を隠す必要がある場合、常に前景に出されることで表示されてしまうため、隠すだけでなく、オブジェクトに非表示フラグを設定する必要があるのです。オブジェクトを非表示にした後、そのオブジェクトに非表示フラグを設定すると、再び表示フラグを受け取るまで、オブジェクトは再描画されません。
以下は、プログレスバーのテキストラベルを非表示にするメソッドです。
//+---------------------------------------------+ //| Hide the progress bar text label | //+---------------------------------------------+ void CProgressBar::HideBarDescription(void) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetDisplayed(false); obj.Hide(); } //+------------------------------------------------------------------+
ここでは、プログレスバーの説明を記述したテキストラベルオブジェクトを取得し、それに非表示フラグを設定し、オブジェクトを非表示にしています。
以下は、プログレスバーのテキストラベルを表示するメソッドです。
//+---------------------------------------------+ //| Display a text label for the progress bar | //+---------------------------------------------+ void CProgressBar::ShowBarDescription(void) { CLabel *obj=this.GetProgressDescriptionObj(); if(obj==NULL) return; obj.SetDisplayed(true); obj.Show(); } //+------------------------------------------------------------------+
ここでは、プログレスバーの説明を記述したテキストラベルオブジェクトを取得し、その表示フラグを設定し、オブジェクトを表示しています。
以下は、MinからMaxまでの範囲の現在のプログレスバーの値を割合で返すメソッドです。
//+---------------------------------------------+ //| Return the current value of the progress bar| //| in the range from Min to Max as a percentage| //+---------------------------------------------+ double CProgressBar::ValuePercent(void) const { double range=this.Maximum()-this.Minimum(); return(this.Value()*100.0/(range>0 ? range : 1)); } //+------------------------------------------------------------------+
プログレスバーの値をMinからMaxまでの範囲の割合で取得する必要がある場合、このメソッドは指定した範囲の何割合がすでに処理されているかを計算し、その値を返します。100%は、ProgressBarオブジェクトに設定された最大値と最小値の差です。
結果を確認してみましょう。
検証
テストを実行するには、前の記事のEAを\MQL5\Experts\TestDoEasy\Part128\でTestDoEasy128.mq5として保存します。
英語版とユーザー言語版コンパイルのプログレスバー形式の列挙を作成します。
//--- enumerations by compilation language #ifdef COMPILE_EN enum ENUM_AUTO_SIZE_MODE { AUTO_SIZE_MODE_GROW=CANV_ELEMENT_AUTO_SIZE_MODE_GROW, // Grow AUTO_SIZE_MODE_GROW_SHRINK=CANV_ELEMENT_AUTO_SIZE_MODE_GROW_SHRINK // Grow and Shrink }; enum ENUM_BORDER_STYLE { BORDER_STYLE_NONE=FRAME_STYLE_NONE, // None BORDER_STYLE_SIMPLE=FRAME_STYLE_SIMPLE, // Simple BORDER_STYLE_FLAT=FRAME_STYLE_FLAT, // Flat BORDER_STYLE_BEVEL=FRAME_STYLE_BEVEL, // Embossed (bevel) BORDER_STYLE_STAMP=FRAME_STYLE_STAMP, // Embossed (stamp) }; enum ENUM_CHEK_STATE { CHEK_STATE_UNCHECKED=CANV_ELEMENT_CHEK_STATE_UNCHECKED, // Unchecked CHEK_STATE_CHECKED=CANV_ELEMENT_CHEK_STATE_CHECKED, // Checked CHEK_STATE_INDETERMINATE=CANV_ELEMENT_CHEK_STATE_INDETERMINATE, // Indeterminate }; enum ENUM_ELEMENT_ALIGNMENT { ELEMENT_ALIGNMENT_TOP=CANV_ELEMENT_ALIGNMENT_TOP, // Top ELEMENT_ALIGNMENT_BOTTOM=CANV_ELEMENT_ALIGNMENT_BOTTOM, // Bottom ELEMENT_ALIGNMENT_LEFT=CANV_ELEMENT_ALIGNMENT_LEFT, // Left ELEMENT_ALIGNMENT_RIGHT=CANV_ELEMENT_ALIGNMENT_RIGHT, // Right }; enum ENUM_ELEMENT_TAB_SIZE_MODE { ELEMENT_TAB_SIZE_MODE_NORMAL=CANV_ELEMENT_TAB_SIZE_MODE_NORMAL, // Fit to tab title text width ELEMENT_TAB_SIZE_MODE_FIXED=CANV_ELEMENT_TAB_SIZE_MODE_FIXED, // Fixed size ELEMENT_TAB_SIZE_MODE_FILL=CANV_ELEMENT_TAB_SIZE_MODE_FILL, // Fit TabControl Size }; enum ENUM_ELEMENT_PROGRESS_BAR_STYLE { ELEMENT_PROGRESS_BAR_STYLE_BLOCKS=CANV_ELEMENT_PROGRESS_BAR_STYLE_BLOCKS, // Blocks ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS=CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS, // Continuous ELEMENT_PROGRESS_BAR_STYLE_MARQUEE=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE, // Marquee }; #else enum ENUM_AUTO_SIZE_MODE { AUTO_SIZE_MODE_GROW=CANV_ELEMENT_AUTO_SIZE_MODE_GROW, // Increase only AUTO_SIZE_MODE_GROW_SHRINK=CANV_ELEMENT_AUTO_SIZE_MODE_GROW_SHRINK // Increase and decrease }; enum ENUM_BORDER_STYLE { BORDER_STYLE_NONE=FRAME_STYLE_NONE, // No frame BORDER_STYLE_SIMPLE=FRAME_STYLE_SIMPLE, // Simple frame BORDER_STYLE_FLAT=FRAME_STYLE_FLAT, // Flat frame BORDER_STYLE_BEVEL=FRAME_STYLE_BEVEL, // Embossed (convex) BORDER_STYLE_STAMP=FRAME_STYLE_STAMP, // Embossed (concave) }; enum ENUM_CHEK_STATE { CHEK_STATE_UNCHECKED=CANV_ELEMENT_CHEK_STATE_UNCHECKED, // Unchecked CHEK_STATE_CHECKED=CANV_ELEMENT_CHEK_STATE_CHECKED, // Checked CHEK_STATE_INDETERMINATE=CANV_ELEMENT_CHEK_STATE_INDETERMINATE, // Undefined }; enum ENUM_ELEMENT_ALIGNMENT { ELEMENT_ALIGNMENT_TOP=CANV_ELEMENT_ALIGNMENT_TOP, // Top ELEMENT_ALIGNMENT_BOTTOM=CANV_ELEMENT_ALIGNMENT_BOTTOM, // Bottom ELEMENT_ALIGNMENT_LEFT=CANV_ELEMENT_ALIGNMENT_LEFT, // Left ELEMENT_ALIGNMENT_RIGHT=CANV_ELEMENT_ALIGNMENT_RIGHT, // Right }; enum ENUM_ELEMENT_TAB_SIZE_MODE { ELEMENT_TAB_SIZE_MODE_NORMAL=CANV_ELEMENT_TAB_SIZE_MODE_NORMAL, // By tab title width ELEMENT_TAB_SIZE_MODE_FIXED=CANV_ELEMENT_TAB_SIZE_MODE_FIXED, // Fixed size ELEMENT_TAB_SIZE_MODE_FILL=CANV_ELEMENT_TAB_SIZE_MODE_FILL, // By TabControl size }; enum ENUM_ELEMENT_PROGRESS_BAR_STYLE { ELEMENT_PROGRESS_BAR_STYLE_BLOCKS=CANV_ELEMENT_PROGRESS_BAR_STYLE_BLOCKS, // Segmented blocks ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS=CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS, // Continuous bar ELEMENT_PROGRESS_BAR_STYLE_MARQUEE=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE, // Continuous scrolling }; #endif //--- input parameters
プログレスバーのスタイルとプログレスバーの値を割合で表示するフラグの2つの新しいパラメータを入力に追加しましょう。
//--- input parameters sinput bool InpMovable = true; // Panel Movable flag sinput ENUM_INPUT_YES_NO InpAutoSize = INPUT_YES; // Panel Autosize sinput ENUM_AUTO_SIZE_MODE InpAutoSizeMode = AUTO_SIZE_MODE_GROW; // Panel Autosize mode sinput ENUM_BORDER_STYLE InpFrameStyle = BORDER_STYLE_SIMPLE; // Label border style sinput ENUM_ANCHOR_POINT InpTextAlign = ANCHOR_CENTER; // Label text align sinput ENUM_INPUT_YES_NO InpTextAutoSize = INPUT_NO; // Label autosize sinput ENUM_ANCHOR_POINT InpCheckAlign = ANCHOR_LEFT; // Check flag align sinput ENUM_ANCHOR_POINT InpCheckTextAlign = ANCHOR_LEFT; // Check label text align sinput ENUM_CHEK_STATE InpCheckState = CHEK_STATE_UNCHECKED; // Check flag state sinput ENUM_INPUT_YES_NO InpCheckAutoSize = INPUT_YES; // CheckBox autosize sinput ENUM_BORDER_STYLE InpCheckFrameStyle = BORDER_STYLE_NONE; // CheckBox border style sinput ENUM_ANCHOR_POINT InpButtonTextAlign = ANCHOR_CENTER; // Button text align sinput ENUM_INPUT_YES_NO InpButtonAutoSize = INPUT_YES; // Button autosize sinput ENUM_AUTO_SIZE_MODE InpButtonAutoSizeMode= AUTO_SIZE_MODE_GROW; // Button Autosize mode sinput ENUM_BORDER_STYLE InpButtonFrameStyle = BORDER_STYLE_NONE; // Button border style sinput bool InpButtonToggle = true ; // Button toggle flag sinput bool InpButtListMSelect = false; // ButtonListBox Button MultiSelect flag sinput bool InpListBoxMColumn = true; // ListBox MultiColumn flag sinput bool InpTabCtrlMultiline = false; // Tab Control Multiline flag sinput ENUM_ELEMENT_ALIGNMENT InpHeaderAlignment = ELEMENT_ALIGNMENT_TOP; // TabHeader Alignment sinput ENUM_ELEMENT_TAB_SIZE_MODE InpTabPageSizeMode = ELEMENT_TAB_SIZE_MODE_FILL; // TabHeader Size Mode sinput int InpTabControlX = 10; // TabControl X coord sinput int InpTabControlY = 20; // TabControl Y coord sinput ENUM_CANV_ELEMENT_TOOLTIP_ICON InpTooltipIcon = CANV_ELEMENT_TOOLTIP_ICON_NONE; // Tooltip Icon sinput string InpTooltipTitle = ""; // Tooltip Title sinput ENUM_ELEMENT_PROGRESS_BAR_STYLE InpProgressBarStyle= ELEMENT_PROGRESS_BAR_STYLE_BLOCKS; // Progress Bar Style sinput bool InpProgressBarPercent= false; // Show progress bar values as a percentage //--- global variables
EAのOnInit()ハンドラでProgressBarコントロールを作成する際に、設定の変数からスタイルをプログレスバーに設定し、プログレスバーを記述するパラメータを設定します。
//--- If this is the first tab and the second panel if(n==0 && j==1) { //--- Create the ProgressBar control on it if(split_container.CreateNewElement(j,GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,4,4,100,12,clrNONE,255,false,false)) { CProgressBar *progress_bar=split_container.GetPanelElementByType(j,GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0); if(progress_bar!=NULL) { //--- Set the style of the progress bar specified in the EA settings progress_bar.SetStyle((ENUM_CANV_ELEMENT_PROGRESS_BAR_STYLE)InpProgressBarStyle); //--- Set the parameters for describing the progress bar progress_bar.SetBarDescriptionText("Progress Bar "); progress_bar.SetBarDescriptionColor(panel.BackgroundColor()); progress_bar.SetBarDescriptionOpacity(255); progress_bar.SetBarDescriptionY(-2); } } }
すべてのパネルを表示し再描画するループで、プログレスバーのスタイルが「連続線」の時に説明を表示します。プログレスバーの値を増加させるループの繰り返しごとに、設定に応じて値を割合または完了ステップで説明に表示します。ループ完了時に、プログレスバーの記述に、インクリメントループ完了のメッセージをフォントを太字に変えて記述します。
グレアオブジェクトのパラメータを設定するために、オブジェクトのクイックアクセスメソッドを使用することにします。
//--- Display and redraw all created panels for(int i=0;i<FORMS_TOTAL;i++) { //--- Get the panel object pnl=engine.GetWFPanel("WinForms Panel"+(string)i); if(pnl!=NULL) { //--- display and redraw the panel pnl.Show(); pnl.Redraw(true); //--- Get the TabControl object from the panel CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0); //--- Get the SplitContainer object from the first tab of the TabControl object CSplitContainer *sc=tc.GetTabElementByType(0,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,0); //--- Get the second panel from the SplitContainer object CSplitContainerPanel *scp=sc.GetPanel(1); //--- Get the ProgressBar object from the received panel CProgressBar *pb=scp.GetElementByType(GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,0); //--- Wait for 1/10 of a second Sleep(100); //--- Get the width of the ProgressBar object int w=pb.Width(); //--- In the loop, increase the width of the ProgressBar by 180 pixels with a delay of 1/50 for(int n=0;n<180;n++) { Sleep(20); pb.Resize(w+n,pb.Height(),true); } //--- Set the values for PerformStep of the ProgressBar object pb.SetValuesForProcessing(0,350,1,0); //--- Reset ProgressBar to minimum pb.ResetProgressBar(); //--- If the style of the progress bar is "Continuous line", display the progress bar description if(pb.Style()==CANV_ELEMENT_PROGRESS_BAR_STYLE_CONTINUOUS) pb.ShowBarDescription(); //--- Wait for 1/5 second Sleep(200); //--- If the style of the progress bar is not "Continuous scrolling" if(pb.Style()!=CANV_ELEMENT_PROGRESS_BAR_STYLE_MARQUEE) { //--- In the loop from the minimum to the maximum value of ProgressBar for(int n=0;n<=pb.Maximum();n++) { //--- call the method for increasing the progress bar by a given step with a wait of 1/5 second pb.PerformStep(); //--- Set the number of completed steps in the description of the progress bar pb.SetBarDescriptionText("Progress Bar, pass: "+(InpProgressBarPercent ? pb.ValuePercentDescription() : pb.ValueDescription())); Sleep(20); } } //--- Wait for 1/2 second, set the description font type to Bold and write a completion message on the progress bar Sleep(500); pb.SetBarDescriptionFontFlags(FW_BOLD); pb.SetBarDescriptionText("Progress Bar: Done"); //--- Set the glare object type - rectangle, opacity 40, color - white pb.SetGlareStyle(CANV_ELEMENT_VISUAL_EFF_STYLE_RECTANGLE); pb.SetGlareOpacity(40); pb.SetGlareColor(clrWhite); } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
EAをコンパイルし、チャート上で起動します。
このように、宣言したモードはすべてうまく機能します。
次の段階
次回は、TrackBarコントロールの開発に着手します。
連載のこれまでの記事
DoEasy-コントロール(第26部):ToolTipWinFormsオブジェクトの最終確認とProgressBar開発の開始
DoEasy-コントロール(第27部):ProgressBarWinFormsオブジェクトでの作業
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/11823




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