DoEasyライブラリのグラフィックス(第76部): フォームオブジェクトと事前定義されたカラースキーム
内容
概念
前回の記事では、より複雑なライブラリグラフィカルオブジェクトを作成するための基礎として使用される基本的なグラフィック要素オブジェクトクラスを開発し、グラフィカルプリミティブとテキストを描画するためのメソッドを作成しました。今日は、このグラフィック要素オブジェクトをその子孫オブジェクトクラスであるフォームオブジェクトの基礎として使用します。フォームオブジェクトは、ライブラリに基づいてプログラムでコントロールを設計および表示し、視覚化を実行するための完全に独立したユニットにできます。
ただし、フォームオブジェクトを作成する前に、GUIとその設計方法について説明し、カラーテーマとグラフィカルオブジェクトプレゼンテーションの種類の初期セットを作成しましょう。
グラフィカルなデータ表現を使用し、グラフィックエンジンを介して外界との対話を提供する多くのプログラムでは、ユーザーはグラフィカルオブジェクトの外観とデザインをすばやく変更できます。一連のテーマを使用して、外観と配色をすばやく変更します。作成されたテーマのパラメータは別のライブラリファイルに含まれ、プログラムユーザーまたはプログラマーはグラフィカルオブジェクトの外観と色のさまざまな設定をすばやく変更できます。
現在の記事では、2つのテーマの開発を開始します。これらのテーマは、新しいライブラリオブジェクトと機能を開発するにつれて、徐々に異なるパラメータとその値を備えるようになります。
カスタムグラフィカルオブジェクトを作成するためにライブラリで開発されたテーマを使用することは必要ありませんが、後で使用するために特定のオブジェクトを正確に作成する方法の良い例として役立ちます。
ライブラリクラスの改善
いつものように、まず、\MQL5\Include\DoEasy\Data.mqhファイルに新しいライブラリメッセージのインデックスを追加します。
MSG_LIB_SYS_FAILED_ADD_SYM_OBJ, // Failed to add symbol MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ, // Failed to create the graphical element object MSG_LIB_SYS_OBJ_ALREADY_IN_LIST, // Such an object is already present in the list MSG_LIB_SYS_FAILED_GET_DATA_GRAPH_RES, // Failed to receive graphical resource data
...
MSG_LIB_SYS_FAILED_ADD_BUFFER, // Failed to add buffer object to the list MSG_LIB_SYS_FAILED_CREATE_BUFFER_OBJ, // Failed to create \"Indicator buffer\" object MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST, // Could not add object to the list
また、新しく追加したインデックスに対応するメッセージテキストも追加します。
{"Не удалось добавить символ ","Failed to add "}, {"Не удалось создать объект-графический элемент ","Failed to create graphic element object "}, {"Такой объект уже есть в списке","Such an object is already in the list"}, {"Не удалось получить данные графического ресурса","Failed to get graphic resource data"},
...
{"Не удалось добавить объект-буфер в список","Failed to add buffer object to list"}, {"Не удалось создать объект \"Индикаторный буфер\"","Failed to create object \"Indicator buffer\""}, {"Не удалось добавить объект в список","Failed to add object to the list"},
フォームオブジェクトを開発している間、フォームがオブジェクト上に投影する影を後で作成するために空白を作成します。その上にフォームが配置されます。フォームの周囲には小さなスペースが必要です。このスペースは、影を描くために使用されます。スペースのサイズを設定するには、このスペースの片側のサイズをピクセル単位で示すマクロ置換が必要です。5ピクセルを設定すると、フォームの上下左右に空き領域ができます(各辺に5ピクセル)。
グラフィック要素オブジェクトを処理すると、そのプロパティの一部がプロパティリストに必要ないことがわかります。これらは、オブジェクトの検索や並べ替えには使用されないため、要素オブジェクトの整数プロパティの列挙から削除して、通常のprotectedクラスメンバー変数に含まれるようにします。
\MQL5\Include\DoEasy\Defines.mqhを開いて、上記の変更を実装しましょう。
キャンバスパラメータのリストで、片側に影を挿入するためのオフセットを追加します。
//--- Parameters of the DOM snapshot series #define MBOOKSERIES_DEFAULT_DAYS_COUNT (1) // The default required number of days for DOM snapshots in the series #define MBOOKSERIES_MAX_DATA_TOTAL (200000) // Maximum number of stored DOM snapshots of a single symbol //--- Canvas parameters #define PAUSE_FOR_CANV_UPDATE (16) // Canvas update frequency #define NULL_COLOR (0x00FFFFFF) // Zero for the canvas with the alpha channel #define OUTER_AREA_SIZE (5) // Size of one side of the outer area around the workspace //+------------------------------------------------------------------+ //| Enumerations | //+------------------------------------------------------------------+
グラフィック要素の整数プロパティのリストから2つの不要なプロパティを削除します。
CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM, // Active area offset from the bottom edge of the element CANV_ELEMENT_PROP_OPACITY, // Element opacity CANV_ELEMENT_PROP_COLOR_BG, // Element background color CANV_ELEMENT_PROP_MOVABLE, // Element moveability flag
これで、整数プロパティのリストは次のようになります。
//+------------------------------------------------------------------+ //| Integer properties of the graphical element on the canvas | //+------------------------------------------------------------------+ enum ENUM_CANV_ELEMENT_PROP_INTEGER { CANV_ELEMENT_PROP_ID = 0, // Element ID CANV_ELEMENT_PROP_TYPE, // Graphical element type CANV_ELEMENT_PROP_NUM, // Element index in the list CANV_ELEMENT_PROP_CHART_ID, // Chart ID CANV_ELEMENT_PROP_WND_NUM, // Chart subwindow index CANV_ELEMENT_PROP_COORD_X, // Form's X coordinate on the chart CANV_ELEMENT_PROP_COORD_Y, // Form's Y coordinate on the chart CANV_ELEMENT_PROP_WIDTH, // Element width CANV_ELEMENT_PROP_HEIGHT, // Element height CANV_ELEMENT_PROP_RIGHT, // Element right border CANV_ELEMENT_PROP_BOTTOM, // Element bottom border CANV_ELEMENT_PROP_ACT_SHIFT_LEFT, // Active area offset from the left edge of the element CANV_ELEMENT_PROP_ACT_SHIFT_TOP, // Active area offset from the upper edge of the element CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT, // Active area offset from the right edge of the element CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM, // Active area offset from the bottom edge of the element CANV_ELEMENT_PROP_MOVABLE, // Element moveability flag CANV_ELEMENT_PROP_ACTIVE, // Element activity flag CANV_ELEMENT_PROP_COORD_ACT_X, // X coordinate of the element active area CANV_ELEMENT_PROP_COORD_ACT_Y, // Y coordinate of the element active area CANV_ELEMENT_PROP_ACT_RIGHT, // Right border of the element active area CANV_ELEMENT_PROP_ACT_BOTTOM, // Bottom border of the element active area }; #define CANV_ELEMENT_PROP_INTEGER_TOTAL (21) // Total number of integer properties #define CANV_ELEMENT_PROP_INTEGER_SKIP (0) // Number of integer properties not used in sorting //+------------------------------------------------------------------+
整数プロパティの総数を2つ減らし、23ではなく21を設定します。
また、可能なキャンバスベースのグラフィック要素の並べ替え基準の列挙から2つの不要な定数を削除します。
SORT_BY_CANV_ELEMENT_ACT_SHIFT_BOTTOM, // Sort by the active area offset from the bottom edge of the element SORT_BY_CANV_ELEMENT_OPACITY, // Sort by the element opacity SORT_BY_CANV_ELEMENT_COLOR_BG, // Sort by the element background color SORT_BY_CANV_ELEMENT_MOVABLE, // Sort by the element moveability flag
完全なリストは次のとおりです。
//+------------------------------------------------------------------+ //| Possible sorting criteria of graphical elements on the canvas | //+------------------------------------------------------------------+ #define FIRST_CANV_ELEMENT_DBL_PROP (CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP) #define FIRST_CANV_ELEMENT_STR_PROP (CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP+CANV_ELEMENT_PROP_DOUBLE_TOTAL-CANV_ELEMENT_PROP_DOUBLE_SKIP) enum ENUM_SORT_CANV_ELEMENT_MODE { //--- Sort by integer properties SORT_BY_CANV_ELEMENT_ID = 0, // Sort by element ID SORT_BY_CANV_ELEMENT_TYPE, // Sort by graphical element type SORT_BY_CANV_ELEMENT_NUM, // Sort by form index in the list SORT_BY_CANV_ELEMENT_CHART_ID, // Sort by chart ID SORT_BY_CANV_ELEMENT_WND_NUM, // Sort by chart window index SORT_BY_CANV_ELEMENT_COORD_X, // Sort by the element X coordinate on the chart SORT_BY_CANV_ELEMENT_COORD_Y, // Sort by the element Y coordinate on the chart SORT_BY_CANV_ELEMENT_WIDTH, // Sort by the element width SORT_BY_CANV_ELEMENT_HEIGHT, // Sort by the element height SORT_BY_CANV_ELEMENT_RIGHT, // Sort by the element right border SORT_BY_CANV_ELEMENT_BOTTOM, // Sort by the element bottom border SORT_BY_CANV_ELEMENT_ACT_SHIFT_LEFT, // Sort by the active area offset from the left edge of the element SORT_BY_CANV_ELEMENT_ACT_SHIFT_TOP, // Sort by the active area offset from the top edge of the element SORT_BY_CANV_ELEMENT_ACT_SHIFT_RIGHT, // Sort by the active area offset from the right edge of the element SORT_BY_CANV_ELEMENT_ACT_SHIFT_BOTTOM, // Sort by the active area offset from the bottom edge of the element SORT_BY_CANV_ELEMENT_MOVABLE, // Sort by the element moveability flag SORT_BY_CANV_ELEMENT_ACTIVE, // Sort by the element activity flag SORT_BY_CANV_ELEMENT_COORD_ACT_X, // Sort by X coordinate of the element active area SORT_BY_CANV_ELEMENT_COORD_ACT_Y, // Sort by Y coordinate of the element active area SORT_BY_CANV_ELEMENT_ACT_RIGHT, // Sort by the right border of the element active area SORT_BY_CANV_ELEMENT_ACT_BOTTOM, // Sort by the bottom border of the element active area //--- Sort by real properties //--- Sort by string properties SORT_BY_CANV_ELEMENT_NAME_OBJ = FIRST_CANV_ELEMENT_STR_PROP,// Sort by an element object name SORT_BY_CANV_ELEMENT_NAME_RES, // Sort by the graphical resource name }; //+------------------------------------------------------------------+
作成されたすべてのグラフィカルオブジェクトは、グラフィック要素オブジェクトに基づいています。オブジェクト自体は、すべてのライブラリグラフィカルオブジェクトの基本オブジェクトの子孫です(これは、CObjectの標準ライブラリ基本クラスの子孫です)。各親クラスのすべてのプロパティは、その子孫に受け継がれます。したがって、すべてのグラフィカルオブジェクトに共通のプロパティが必要な場合は、派生ツリー全体の基本オブジェクトに配置する必要があります。CGBaseObjクラスオブジェクトは、グラフィカルライブラリオブジェクトのオブジェクトとして機能します。
チャート上のグラフィカルオブジェクトの可視性を管理する必要がありますが、そのためにグラフィカルオブジェクトを削除したり非表示にしたりする必要はありません。グラフィカルオブジェクトのOBJPROP_TIMEFRAMESプロパティで必要なフラグを指定するだけで、削除することもチャートの他のすべてのコンテンツの上に表示することもできます。したがって、チャート上のオブジェクトの可視性を管理し、必要なオブジェクトを他のすべての上に配置することができます。これは、プログラムユーザーが操作する現在のオブジェクトとして機能します。
オブジェクトフラグのセット全体のうち、必要なフラグは、オブジェクトを非表示にするためのOBJ_NO_PERIODSとチャートにオブジェクトを表示するためのOBJ_ALL_PERIODSです。オブジェクトを前景に移動するには、単に非表示にしてからもう一度表示します。
新しいプロパティとメソッドを\MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqh基本オブジェクトファイルに追加しましょう。
クラスのprotectedセクションで、オブジェクトの可視性プロパティを格納するための変数を宣言します。
//+------------------------------------------------------------------+ //| Class of the base object of the library graphical objects | //+------------------------------------------------------------------+ class CGBaseObj : public CObject { private: protected: string m_name_prefix; // Object name prefix string m_name; // Object name long m_chart_id; // Chart ID int m_subwindow; // Subwindow index int m_shift_y; // Subwindow Y coordinate shift int m_type; // Object type bool m_visible; // Object visibility //--- Create (1) the object structure and (2) the object from the structure virtual bool ObjectToStruct(void) { return true; } virtual void StructToObject(void){;} public:
クラスのpublicセクションに、オブジェクトの可視性フラグを設定してプロパティ自体をオブジェクトに同時に設定するメソッドとチャート上でのオブジェクトの可視性をオブジェクトに返すメソッドを記述します。
public: //--- Return the values of class variables string Name(void) const { return this.m_name; } long ChartID(void) const { return this.m_chart_id; } int SubWindow(void) const { return this.m_subwindow; } //--- (1) Set and (2) return the object visibility void SetVisible(const bool flag) { long value=(flag ? OBJ_ALL_PERIODS : 0); if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_TIMEFRAMES,value)) this.m_visible=flag; } bool IsVisible(void) const { return this.m_visible; } //--- The virtual method returning the object type virtual int Type(void) const { return this.m_type; }
オブジェクトの可視性を設定するメソッドは、最初にフラグ値を確認し、渡された値(trueまたはfalse)に応じて、オブジェクトに値を設定するリクエストを送信するか、チャートにオブジェクトを表示するためにOBJ_ALL_PERIODS、または非表示にするために0を送信します。リクエストがチャートイベントキューに正常に配置されると、m_visible変数はメソッドに渡されたフラグ値を受け取ります。値は、変数値を返すIsVisible()メソッドを使用して明らかにすることができます。
クラスコンストラクタの初期化リストで、falseを使用して新しい変数を初期化します。
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CGBaseObj::CGBaseObj() : m_shift_y(0), m_type(0),m_visible(false), m_name_prefix(::MQLInfoString(MQL_PROGRAM_NAME)+"_") { } //+------------------------------------------------------------------+
\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqhのグラフィック要素オブジェクトクラスを改善しましょう。
クラスのprotectedセクションで、オブジェクトの影の有無が設定されているフラグ変数とチャートの背景色を格納する変数を宣言します。これは、将来、影を描くときに必要になります。
//+------------------------------------------------------------------+ //| Class of the base object of the library graphical objects | //+------------------------------------------------------------------+ class CGCnvElement : public CGBaseObj { protected: CCanvas m_canvas; // CCanvas class object CPause m_pause; // Pause class object bool m_shadow; // Shadow presence color m_chart_color_bg; // Chart background color //--- Return the cursor position relative to the (1) entire element and (2) the element's active area bool CursorInsideElement(const int x,const int y); bool CursorInsideActiveArea(const int x,const int y); //--- Create (1) the object structure and (2) the object from the structure virtual bool ObjectToStruct(void); virtual void StructToObject(void); private:
オブジェクト整数プロパティの列挙から2つの定数を削除したので、次にそれらをクラス変数に格納する必要があります。
privateセクションでそれらを宣言します。
long m_long_prop[ORDER_PROP_INTEGER_TOTAL]; // Integer properties double m_double_prop[ORDER_PROP_DOUBLE_TOTAL]; // Real properties string m_string_prop[ORDER_PROP_STRING_TOTAL]; // String properties ENUM_TEXT_ANCHOR m_text_anchor; // Current text alignment color m_color_bg; // Element background color uchar m_opacity; // Element opacity //--- Return the index of the array the order's (1) double and (2) string properties are located at
「要素の背景色」と「要素の不透明度」が設定され、これらの変数に読み込まれます。
グラフィカルオブジェクトの外観をデザインするには、色の明度を変更できるメソッドが必要です。
これは、HSLカラーモデルのコンポーネントの1つです。
HSL、HLS、HSI(色相、彩度、明度(強度)) は、色相、彩度、明度を色座標として使用するカラーモデルです。HSVとHSLは2つの異なるカラーモデルです(明度を明るさと混同しないでください)。
グラフィカルプリミティブを描画するときは、描画の従来の照明部分を明るくし、従来の陰影部分を暗くする必要があります。画像自体の色は影響を受けません。これを確実にするために、ARGBカラーモデルをHSLに変換するメソッドを適用して、画像の目的の部分のピクセルの明るさを変更します。
クラスのprivateセクションでこのメソッドを宣言します。
//--- Update the coordinates (shift the canvas) bool Move(const int x,const int y,const bool redraw=false); //--- Change the color lightness by the specified amount uint ChangeColorLightness(const uint clr,const double change_value); protected:
グラフィック要素オブジェクトは、その子孫となるより複雑なグラフィカルオブジェクトを作成するためのメインオブジェクトです。ライブラリオブジェクト(親クラスが作成された子孫オブジェクトのパラメータを指定するprotectedコンストラクタを特徴とする)を構築するという概念を念頭に置いて、要素オブジェクトのprotectedパラメトリックコンストラクタを作成します。protectedグラフィック要素(ここではフォームオブジェクト)に基づいて作成される子孫オブジェクトタイプに関する明確なパラメータを受け取ることです。
クラスのprotectedセクションで、新しい保護されたパラメトリックコンストラクタを宣言します。
protected: //--- Protected constructor CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const long chart_id, const int wnd_num, const string name, const int x, const int y, const int w, const int h); public:
これは、オブジェクトを作成するための基本的なパラメータのみを受け取ります。他のすべてのパラメータは、作成が成功した後にのみ設定されます。これは、ライブラリのグラフィカルオブジェクトコレクションクラスで実行されますが、まだ開始していません。
影が存在するかどうかのフラグの初期化とチャートの背景色をデフォルトの(ノンパラメトリック)コンストラクタ、つまり初期化リストに追加します。
public: //--- Parametric constructor CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id, const int element_num, const long chart_id, const int wnd_num, const string name, 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); //--- Default constructor/Destructor CGCnvElement() : m_shadow(false),m_chart_color_bg((color)::ChartGetInteger(::ChartID(),CHART_COLOR_BACKGROUND)) {;}
オブジェクトパラメータを簡単にアクセスできるように、メソッドのブロックにオブジェクトプロパティを設定するための新しいメソッドを追加します。
//+------------------------------------------------------------------+ //| Methods of simplified access to object properties | //+------------------------------------------------------------------+ //--- Set the (1) X, (2) Y coordinates, (3) element width, (4) height, (5) right (6) and bottom edge, bool SetCoordX(const int coord_x); bool SetCoordY(const int coord_y); bool SetWidth(const int width); bool SetHeight(const int height); void SetRightEdge(void) { this.SetProperty(CANV_ELEMENT_PROP_RIGHT,this.RightEdge()); } void SetBottomEdge(void) { this.SetProperty(CANV_ELEMENT_PROP_BOTTOM,this.BottomEdge()); } //--- Set the shift of the (1) left, (2) top, (3) right, (4) bottom edge of the active area relative to the element, //--- (5) all shifts of the active area edges relative to the element, (6) the element background color and (7) the element opacity void SetActiveAreaLeftShift(const int value) { this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT,fabs(value)); } void SetActiveAreaRightShift(const int value) { this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT,fabs(value)); } void SetActiveAreaTopShift(const int value) { this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP,fabs(value)); } void SetActiveAreaBottomShift(const int value) { this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM,fabs(value)); } void SetActiveAreaShift(const int left_shift,const int bottom_shift,const int right_shift,const int top_shift); void SetColorBackground(const color colour) { this.m_color_bg=colour; } void SetOpacity(const uchar value,const bool redraw=false); //--- Set the flag of (1) object moveability, (2) activity, (3) element ID, (4) element index in the list and (5) shadow presence void SetMovable(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,flag); } void SetActive(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,flag); } void SetID(const int id) { this.SetProperty(CANV_ELEMENT_PROP_ID,id); } void SetNumber(const int number) { this.SetProperty(CANV_ELEMENT_PROP_NUM,number); } void SetShadow(const bool flag); //--- Return the shift (1) of the left, (2) right, (3) top and (4) bottom edge of the element active area
背景色を返すメソッドと不透明度は、新しく宣言された変数に設定された値を返すようになりました:。
//--- Return (1) the background color, (2) the opacity, coordinate (3) of the right and (4) bottom element edge color ColorBackground(void) const { return this.m_color_bg; } uchar Opacity(void) const { return this.m_opacity; } int RightEdge(void) const { return this.CoordX()+this.m_canvas.Width(); } int BottomEdge(void) const { return this.CoordY()+this.m_canvas.Height(); } //--- Return the (1) X, (2) Y coordinates, (3) element width and (4) height,
リストの最後に、オブジェクトによって投影された影を描画するフラグを返すメソッド、チャートの背景色を返すメソッド、
オブジェクトをフォアグラウンドに移動するメソッド(チャート上の他のすべてのグラフィカルオブジェクトの上)を追加します。
//--- Return (1) the element ID, (2) element index in the list, (3) flag of the form shadow presence and (4) the chart background color int ID(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_ID); } int Number(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_NUM); } bool IsShadow(void) const { return this.m_shadow; } color ChartColorBackground(void) const { return this.m_chart_color_bg; } //--- Set the object above all void BringToTop(void) { CGBaseObj::SetVisible(false); CGBaseObj::SetVisible(true); } //+------------------------------------------------------------------+
ご覧のとおり、オブジェクトを他のすべての上に設定するには、上記で検討した親クラスのメソッドを使用して、非表示にしてすぐに再度表示する必要があります。
削除されたプロパティを設定する文字列をパラメトリックコンストラクタから削除します。
this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM,0); // Active area offset from the bottom edge of the element this.SetProperty(CANV_ELEMENT_PROP_OPACITY,opacity); // Element opacity this.SetProperty(CANV_ELEMENT_PROP_COLOR_BG,colour); // Element color this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,movable); // Element moveability flag
これらは新しいプロパティとともに新しい変数に設定されます。
//+------------------------------------------------------------------+ //| Parametric constructor | //+------------------------------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const int element_id, const int element_num, const long chart_id, const int wnd_num, const string name, 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.m_chart_color_bg=(color)::ChartGetInteger(chart_id,CHART_COLOR_BACKGROUND); this.m_name=this.m_name_prefix+name; this.m_chart_id=chart_id; this.m_subwindow=wnd_num; this.m_type=element_type; this.SetFont("Calibri",8); this.m_text_anchor=0; this.m_color_bg=colour; this.m_opacity=opacity; if(this.Create(chart_id,wnd_num,this.m_name,x,y,w,h,colour,opacity,redraw)) { 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_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 } else { ::Print(CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),this.m_name); } } //+------------------------------------------------------------------+
新しいprotectedパラメトリックコンストラクタは、上記で検討したものと同じです。
//+------------------------------------------------------------------+ //| Protected constructor | //+------------------------------------------------------------------+ CGCnvElement::CGCnvElement(const ENUM_GRAPH_ELEMENT_TYPE element_type, const long chart_id, const int wnd_num, const string name, const int x, const int y, const int w, const int h) : m_shadow(false) { this.m_chart_color_bg=(color)::ChartGetInteger(chart_id,CHART_COLOR_BACKGROUND); this.m_name=this.m_name_prefix+name; this.m_chart_id=chart_id; this.m_subwindow=wnd_num; this.m_type=element_type; this.SetFont("Calibri",8); this.m_text_anchor=0; this.m_color_bg=NULL_COLOR; this.m_opacity=0; if(this.Create(chart_id,wnd_num,this.m_name,x,y,w,h,this.m_color_bg,this.m_opacity,false)) { 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,0); // Element ID this.SetProperty(CANV_ELEMENT_PROP_NUM,0); // 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,false); // Element moveability flag this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,false); // Element activity 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 } else { ::Print(CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),this.m_name); } } //+------------------------------------------------------------------+
受け取る値が少なくなり、要素の背景色が透明な白に設定され、要素全体の透明度が設定されます。
不要になった文字列をオブジェクト構造の作成メソッドから削除します。
this.m_struct_obj.act_shift_bottom=(int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM);// Active area offset from the bottom edge of the element this.m_struct_obj.opacity=(uchar)this.GetProperty(CANV_ELEMENT_PROP_OPACITY); // Element opacity this.m_struct_obj.color_bg=(color)this.GetProperty(CANV_ELEMENT_PROP_COLOR_BG); // Element background color this.m_struct_obj.movable=(bool)this.GetProperty(CANV_ELEMENT_PROP_MOVABLE); // Element moveability flag
また、新しい変数からのパラメータを保存するようにします。
//+------------------------------------------------------------------+ //| 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.number=(int)this.GetProperty(CANV_ELEMENT_PROP_NUM); // Eleemnt ID in the list this.m_struct_obj.chart_id=this.GetProperty(CANV_ELEMENT_PROP_CHART_ID); // Chart ID this.m_struct_obj.subwindow=(int)this.GetProperty(CANV_ELEMENT_PROP_WND_NUM); // Chart subwindow index this.m_struct_obj.coord_x=(int)this.GetProperty(CANV_ELEMENT_PROP_COORD_X); // Form's X coordinate on the chart this.m_struct_obj.coord_y=(int)this.GetProperty(CANV_ELEMENT_PROP_COORD_Y); // Form's Y coordinate on the chart this.m_struct_obj.width=(int)this.GetProperty(CANV_ELEMENT_PROP_WIDTH); // Element width this.m_struct_obj.height=(int)this.GetProperty(CANV_ELEMENT_PROP_HEIGHT); // Element height this.m_struct_obj.edge_right=(int)this.GetProperty(CANV_ELEMENT_PROP_RIGHT); // Element right edge this.m_struct_obj.edge_bottom=(int)this.GetProperty(CANV_ELEMENT_PROP_BOTTOM); // Element bottom edge this.m_struct_obj.act_shift_left=(int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT); // Active area offset from the left edge of the element this.m_struct_obj.act_shift_top=(int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP); // Active area offset from the top edge of the element this.m_struct_obj.act_shift_right=(int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT); // Active area offset from the right edge of the element this.m_struct_obj.act_shift_bottom=(int)this.GetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM);// Active area offset from the bottom edge of the element this.m_struct_obj.movable=(bool)this.GetProperty(CANV_ELEMENT_PROP_MOVABLE); // Element moveability flag this.m_struct_obj.active=(bool)this.GetProperty(CANV_ELEMENT_PROP_ACTIVE); // Element activity flag this.m_struct_obj.coord_act_x=(int)this.GetProperty(CANV_ELEMENT_PROP_COORD_ACT_X); // X coordinate of the element active area this.m_struct_obj.coord_act_y=(int)this.GetProperty(CANV_ELEMENT_PROP_COORD_ACT_Y); // Y coordinate of the element active area this.m_struct_obj.coord_act_right=(int)this.GetProperty(CANV_ELEMENT_PROP_ACT_RIGHT); // Right border of the element active area this.m_struct_obj.coord_act_bottom=(int)this.GetProperty(CANV_ELEMENT_PROP_ACT_BOTTOM); // Bottom border of the element active area this.m_struct_obj.color_bg=this.m_color_bg; // Element background color this.m_struct_obj.opacity=this.m_opacity; // Element opacity //--- 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 //--- Save the structure to the uchar array ::ResetLastError(); if(!::StructToCharArray(this.m_struct_obj,this.m_uchar_array)) { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_SAVE_OBJ_STRUCT_TO_UARRAY),(string)::GetLastError()); 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_NUM,this.m_struct_obj.number); // Element index in the list this.SetProperty(CANV_ELEMENT_PROP_CHART_ID,this.m_struct_obj.chart_id); // Chart ID this.SetProperty(CANV_ELEMENT_PROP_WND_NUM,this.m_struct_obj.subwindow); // Chart subwindow index this.SetProperty(CANV_ELEMENT_PROP_COORD_X,this.m_struct_obj.coord_x); // Form's X coordinate on the chart this.SetProperty(CANV_ELEMENT_PROP_COORD_Y,this.m_struct_obj.coord_y); // Form's Y coordinate on the chart this.SetProperty(CANV_ELEMENT_PROP_WIDTH,this.m_struct_obj.width); // Element width this.SetProperty(CANV_ELEMENT_PROP_HEIGHT,this.m_struct_obj.height); // Element height this.SetProperty(CANV_ELEMENT_PROP_RIGHT,this.m_struct_obj.edge_right); // Element right edge this.SetProperty(CANV_ELEMENT_PROP_BOTTOM,this.m_struct_obj.edge_bottom); // Element bottom edge this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT,this.m_struct_obj.act_shift_left); // Active area offset from the left edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP,this.m_struct_obj.act_shift_top); // Active area offset from the upper edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT,this.m_struct_obj.act_shift_right); // Active area offset from the right edge of the element this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM,this.m_struct_obj.act_shift_bottom); // Active area offset from the bottom edge of the element this.SetProperty(CANV_ELEMENT_PROP_MOVABLE,this.m_struct_obj.movable); // Element moveability flag this.SetProperty(CANV_ELEMENT_PROP_ACTIVE,this.m_struct_obj.active); // Element activity flag this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_X,this.m_struct_obj.coord_act_x); // X coordinate of the element active area this.SetProperty(CANV_ELEMENT_PROP_COORD_ACT_Y,this.m_struct_obj.coord_act_y); // Y coordinate of the element active area this.SetProperty(CANV_ELEMENT_PROP_ACT_RIGHT,this.m_struct_obj.coord_act_right); // Right border of the element active area this.SetProperty(CANV_ELEMENT_PROP_ACT_BOTTOM,this.m_struct_obj.coord_act_bottom); // Bottom border of the element active area this.m_color_bg=this.m_struct_obj.color_bg; // Element background color this.m_opacity=this.m_struct_obj.opacity; // Element opacity //--- 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 } //+------------------------------------------------------------------+
グラフィカルオブジェクト要素を作成するメソッドでは、オブジェクトの背景が完全に消去され、白い透明色で塗りつぶされます。
//+------------------------------------------------------------------+ //| Create the graphical element object | //+------------------------------------------------------------------+ bool CGCnvElement::Create(const long chart_id, // Chart ID const int wnd_num, // Chart subwindow const string name, // Element name const int x, // X coordinate const int y, // Y coordinate const int w, // Width const int h, // Height const color colour, // Background color const uchar opacity, // Opacity const bool redraw=false) // Flag indicating the need to redraw { if(this.m_canvas.CreateBitmapLabel(chart_id,wnd_num,name,x,y,w,h,COLOR_FORMAT_ARGB_NORMALIZE)) { this.Erase(NULL_COLOR); this.m_canvas.Update(redraw); this.m_shift_y=(int)::ChartGetInteger(chart_id,CHART_WINDOW_YDISTANCE,wnd_num); return true; } return false; } //+------------------------------------------------------------------+
要素の不透明度を設定するメソッドでは、オブジェクトが削除されたプロパティではなく、不透明度が変数に設定されるようになりました。
//+------------------------------------------------------------------+ //| Set the element opacity | //+------------------------------------------------------------------+ void CGCnvElement::SetOpacity(const uchar value,const bool redraw=false) { this.m_canvas.TransparentLevelSet(value); this.m_opacity=value; this.m_canvas.Update(redraw); } //+------------------------------------------------------------------+
以下は、指定された量だけ色の明度を変更する新しいメソッドです。
//+------------------------------------------------------------------+ //| Change the color lightness by the specified amount | //+------------------------------------------------------------------+ uint CGCnvElement::ChangeColorLightness(const uint clr,const double change_value) { if(change_value==0.0) return clr; double a=GETRGBA(clr); double r=GETRGBR(clr); double g=GETRGBG(clr); double b=GETRGBB(clr); double h=0,s=0,l=0; CColors::RGBtoHSL(r,g,b,h,s,l); double nl=l+change_value; if(nl>1.0) nl=1.0; if(nl<0.0) nl=0.0; CColors::HSLtoRGB(h,s,nl,r,g,b); return ARGB(a,r,g,b); } //+------------------------------------------------------------------+
ここで
明度を変更するために渡された値を確認します。ゼロが渡された場合、何も変更せずに変更しない色を返します。
次に、メソッドに渡された色の各ARGB色成分を受け取り、 RGB成分をHSL色モデルに変換します。
各コンポーネントの値を変換した後、HSLモデルは対応する変数に設定されます(lコンポーネントが必要です)。
メソッドに渡された値を追加します(change_value値は-1.0から1.0まで変化する可能性があります)、許容値の範囲を超えたときに調整します。
次に、HSLモデルをRGBに変換し直し、HSLモデルからRGBに変換して生成された新しい色成分から取得したARGBモデルを返します。
色のテーマとフォームの種類
ライブラリは、グラフィック要素、関連するフォーム、ウィンドウなど、さまざまなオブジェクトの作成をサポートするためのものです。各フォーム、ウィンドウ、画像(フレーム、セパレーター、ドロップダウンリストなど)は、異なる表示スタイルを持つ場合があります。ただし、1つのプログラム内に、描画スタイル、色、装飾が異なるさまざまなオブジェクトが含まれているのはおかしいでしょう。
単一のプログラムに属する同じように見えるオブジェクトの開発を簡素化するために、描画スタイル、オブジェクトタイプ、および配色を紹介します。エンドユーザーはプログラム設定で目的のスタイルと色のテーマを選択できますが、プログラマーはそれほど気にする必要はありません。選択したテーマとスタイルは、単一の基準に従ってすべてのオブジェクトをすぐに再構築します。必要なすべての色、オブジェクトおよびプリミティブパラメータを備えたグラフィック設定のファイルに、必要な変更と追加を行うだけで済みます。
ライブラリメッセージクラスを開発するとき、すでにそのようなストラテジーを使用しましたメッセージインデックスのリストとメッセージインデックスに対応するテキストの配列を備えています。各記事の冒頭で通常最初に行うことは、新しいデータを設定することです。
グラフィカル設定のファイルも同じように配置されます。カラーテーマとオブジェクトスタイルの列挙、および適切な配列が特徴であり、新しく追加されたプロパティ、テーマ、または色ごとに新しいパラメータとその値を徐々に受け取ります。
\MQL5\Include\DoEasy\ルートフォルダに、新しいGraphINI.mqhインクルードファイルを作成し、それにカラーテーマの数を追加します。
//+------------------------------------------------------------------+ //| GraphINI.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/ja/users/artmedia70" //+------------------------------------------------------------------+ //| Macro substitutions | //+------------------------------------------------------------------+ #define TOTAL_COLOR_THEMES (2) // Number of color schemes //+------------------------------------------------------------------+
設定ファイルの使用法を示すには、2つのカラーテーマで十分です。その後、数を増やしていきます。
以下に、配色のインデックスと 1つのテーマパラメータのインデックスを設定します。各テーマには、同じ数のパラメータがあります。
//+------------------------------------------------------------------+ //| GraphINI.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/ja/users/artmedia70" //+------------------------------------------------------------------+ //| Macro substitutions | //+------------------------------------------------------------------+ #define TOTAL_COLOR_THEMES (2) // Number of color schemes //+------------------------------------------------------------------+ //| Enumerations | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| List of color scheme indices | //+------------------------------------------------------------------+ enum ENUM_COLOR_THEMES { COLOR_THEME_BLUE_STEEL, // Blue steel COLOR_THEME_LIGHT_CYAN_GRAY, // Light cyan gray }; //+------------------------------------------------------------------+ //| List of indices of color scheme parameters | //+------------------------------------------------------------------+ enum ENUM_COLOR_THEME_COLORS { COLOR_THEME_COLOR_FORM_BG, // Form background color COLOR_THEME_COLOR_FORM_FRAME, // Form frame color COLOR_THEME_COLOR_FORM_FRAME_OUTER, // Form outer frame color COLOR_THEME_COLOR_FORM_SHADOW, // Form shadow color }; #define TOTAL_COLOR_THEME_COLORS (4) // Number of parameters in the color theme //+------------------------------------------------------------------+
列挙定数名で各カラーテーマと必要なパラメータにアクセスすると便利です。
以下では、1番目の次元にカラーテーマを含み、2番目の次元にさまざまなオブジェクトプロパティを描画するためのカラーパラメータインデックスを含む 2次元配列を記述します。
//+------------------------------------------------------------------+ //| GraphINI.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/ja/users/artmedia70" //+------------------------------------------------------------------+ //| Macro substitutions | //+------------------------------------------------------------------+ #define TOTAL_COLOR_THEMES (2) // Number of color schemes //+------------------------------------------------------------------+ //| Enumerations | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| List of color scheme indices | //+------------------------------------------------------------------+ enum ENUM_COLOR_THEMES { COLOR_THEME_BLUE_STEEL, // Blue steel COLOR_THEME_LIGHT_CYAN_GRAY, // Light cyan gray }; //+------------------------------------------------------------------+ //| List of indices of color scheme parameters | //+------------------------------------------------------------------+ enum ENUM_COLOR_THEME_COLORS { COLOR_THEME_COLOR_FORM_BG, // Form background color COLOR_THEME_COLOR_FORM_FRAME, // Form frame color COLOR_THEME_COLOR_FORM_FRAME_OUTER, // Form outer frame color COLOR_THEME_COLOR_FORM_SHADOW, // Form shadow color }; #define TOTAL_COLOR_THEME_COLORS (4) // Number of parameters in the color theme //+------------------------------------------------------------------+ //| The array containing color schemes | //+------------------------------------------------------------------+ color array_color_themes[TOTAL_COLOR_THEMES][TOTAL_COLOR_THEME_COLORS]= { //--- Parameters of the "Blue steel" color scheme { C'134,160,181', // Form background color C'134,160,181', // Form frame color clrDimGray, // Form outer frame color C'46,85,117', // Form shadow color }, //--- Parameters of the "Light cyan gray" color scheme { C'181,196,196', // Form background color C'181,196,196', // Form frame color clrGray, // Form outer frame color C'130,147,153', // Form shadow color }, }; //+------------------------------------------------------------------+
これは、新しく追加されたグラフィカルオブジェクトパラメータごとに新しい色を徐々に受け取る配列です。その色は、選択した配色に依存する必要があります。
次に、プリミティブ、フレームスタイル、タイプ、フォームスタイルを描画するときに平滑化タイプの列挙を追加し、続いてカラーテーマ用に設計されたものと同様のフォームスタイルプロパティインデックスとそのパラメータの列挙を追加します。
//+------------------------------------------------------------------+ //| Smoothing types | //+------------------------------------------------------------------+ enum ENUM_SMOOTHING_TYPE { SMOOTHING_TYPE_NONE, // No smoothing SMOOTHING_TYPE_AA, // Anti-aliasing SMOOTHING_TYPE_WU, // Wu SMOOTHING_TYPE_THICK, // Thick SMOOTHING_TYPE_DUAL, // Dual }; //+------------------------------------------------------------------+ //| Frame styles | //+------------------------------------------------------------------+ enum ENUM_FRAME_STYLE { FRAME_STYLE_SIMPLE, // Simple frame FRAME_STYLE_FLAT, // Flat frame FRAME_STYLE_BEVEL, // Embossed (convex) FRAME_STYLE_STAMP, // Embossed (concave) }; //+------------------------------------------------------------------+ //| Form types | //+------------------------------------------------------------------+ enum ENUM_FORM_TYPE { FORM_TYPE_SQUARE, // Rectangular }; //+------------------------------------------------------------------+ //| Form styles | //+------------------------------------------------------------------+ enum ENUM_FORM_STYLE { FORM_STYLE_FLAT, // Flat form FORM_STYLE_BEVEL, // Embossed form }; #define TOTAL_FORM_STYLES //+------------------------------------------------------------------+ //| List of form style parameter indices | //+------------------------------------------------------------------+ enum ENUM_FORM_STYLE_PARAMS { FORM_STYLE_FRAME_WIDTH_LEFT, // Form frame width to the left FORM_STYLE_FRAME_WIDTH_RIGHT, // Form frame width to the right FORM_STYLE_FRAME_WIDTH_TOP, // Form frame width on top FORM_STYLE_FRAME_WIDTH_BOTTOM, // Form frame width below FORM_STYLE_FRAME_SHADOW_OPACITY, // Shadow opacity }; #define TOTAL_FORM_STYLE_PARAMS (5) // Number of form style parameters //+------------------------------------------------------------------+ //| Array containing form style parameters | //+------------------------------------------------------------------+ int array_form_style[TOTAL_FORM_STYLES][TOTAL_FORM_STYLE_PARAMS]= { //--- "Flat form" style parameters { 3, // Form frame width to the left 3, // Form frame width to the right 3, // Form frame width on top 3, // Form frame width below 80, // Shadow opacity }, //--- "Embossed form" style parameters { 4, // Form frame width to the left 4, // Form frame width to the right 4, // Form frame width on top 4, // Form frame width below 100, // Shadow opacity }, }; //+------------------------------------------------------------------+
構築ロジックがカラーテーマ配列と同じである2番目の配列は、要素、フォーム、ウィンドウ、およびその他のオブジェクトを構築するための新しい、選択したオブジェクトの外観のデザインスタイルに依存するパラメータを徐々に受け取ります。
\MQL5\Include\DoEasy\InpData.mqhにプログラム入力の新しい列挙を追加して、オブジェクトの作成に必要なスタイルとカラーテーマを選択できるようにします。最初に、新しく作成されたGraphINI.mqhファイルをインクルードます。
//+------------------------------------------------------------------+ //| InpData.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "GraphINI.mqh" //+------------------------------------------------------------------+
英語とロシア語でコンパイルするためのコードブロックで、カラーテーマを選択するための新しい入力列挙を追加します。
//+------------------------------------------------------------------+ //| InpData.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "GraphINI.mqh" //+------------------------------------------------------------------+ //| Macro substitutions | //+------------------------------------------------------------------+ #define COMPILE_EN // Comment out the string for compilation in Russian //+------------------------------------------------------------------+ //| Input enumerations | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| English language inputs | //+------------------------------------------------------------------+ #ifdef COMPILE_EN //+------------------------------------------------------------------+ //| Modes of working with symbols | //+------------------------------------------------------------------+ enum ENUM_SYMBOLS_MODE { SYMBOLS_MODE_CURRENT, // Work only with the current Symbol SYMBOLS_MODE_DEFINES, // Work with a given list of Symbols SYMBOLS_MODE_MARKET_WATCH, // Working with Symbols from the "Market Watch" window SYMBOLS_MODE_ALL // Work with a complete list of Symbols }; //+------------------------------------------------------------------+ //| Mode of working with timeframes | //+------------------------------------------------------------------+ enum ENUM_TIMEFRAMES_MODE { TIMEFRAMES_MODE_CURRENT, // Work only with the current timeframe TIMEFRAMES_MODE_LIST, // Work with a given list of timeframes TIMEFRAMES_MODE_ALL // Work with a complete list of timeframes }; //+------------------------------------------------------------------+ //| "Yes"/"No" | //+------------------------------------------------------------------+ enum ENUM_INPUT_YES_NO { INPUT_NO = 0, // No INPUT_YES = 1 // Yes }; //+------------------------------------------------------------------+ //| Select color themes | //+------------------------------------------------------------------+ enum ENUM_INPUT_COLOR_THEME { INPUT_COLOR_THEME_BLUE_STEEL, // Blue steel INPUT_COLOR_THEME_LIGHT_CYAN_GRAY, // Light cyan gray }; //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Russian language inputs | //+------------------------------------------------------------------+ #else //+------------------------------------------------------------------+ //| Modes of working with symbols | //+------------------------------------------------------------------+ enum ENUM_SYMBOLS_MODE { SYMBOLS_MODE_CURRENT, // Работа только с текущим символом SYMBOLS_MODE_DEFINES, // Работа с заданным списком символов SYMBOLS_MODE_MARKET_WATCH, // Работа с символами из окна "Обзор рынка" SYMBOLS_MODE_ALL // Работа с полным списком символов }; //+------------------------------------------------------------------+ //| Mode of working with timeframes | //+------------------------------------------------------------------+ enum ENUM_TIMEFRAMES_MODE { TIMEFRAMES_MODE_CURRENT, // Работа только с текущим таймфреймом TIMEFRAMES_MODE_LIST, // Работа с заданным списком таймфреймов TIMEFRAMES_MODE_ALL // Работа с полным списком таймфреймов }; //+------------------------------------------------------------------+ //| "Да"/"Нет" | //+------------------------------------------------------------------+ enum ENUM_INPUT_YES_NO { INPUT_NO = 0, // Нет INPUT_YES = 1 // Да }; //+------------------------------------------------------------------+ //| Select color themes | //+------------------------------------------------------------------+ enum ENUM_COLOR_THEME { COLOR_THEME_BLUE_STEEL, // Голубая сталь COLOR_THEME_LIGHT_CYAN_GRAY, // Светлый серо-циановый }; //+------------------------------------------------------------------+ #endif //+------------------------------------------------------------------+
これにより、プログラムの開始時に目的の配色を選択できるようになります。後で、オブジェクトの描画スタイルと構築タイプの選択を追加します。
フォームオブジェクトクラス
フォームオブジェクトは、グラフィカルオブジェクトのより高度なバージョンで、「次元」フレームやその他のプリミティブを描画したり、その他の要素をアタッチしたりできます。もちろん、必要なものはすべて「手動で」描くこともできますが、フォームを使用すると作業を自動化できます。
E:\MetaQuotes\MetaTrader 5\MQL5\Include\DoEasy\Objects\Graph\で、CFormクラスの新しい Form.mqh ファイルを作成します。クラスはグラフィック要素オブジェクトから継承するので、要素オブジェクトファイルもインクルードする必要があります。
//+------------------------------------------------------------------+ //| Form.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "GCnvElement.mqh" //+------------------------------------------------------------------+ //| Form object class | //+------------------------------------------------------------------+ class CForm : public CGCnvElement { }
クラスのprivateセクションで、必要なオブジェクト、変数、クラス補助メソッドを宣言します。
//+------------------------------------------------------------------+ //| Form object class | //+------------------------------------------------------------------+ class CForm : public CGCnvElement { private: CArrayObj m_list_elements; // List of attached elements CGCnvElement *m_shadow_obj; // Pointer to the shadow object color m_color_frame; // Form frame color color m_color_shadow; // Form shadow color int m_frame_width_left; // Form frame width to the left int m_frame_width_right; // Form frame width to the right int m_frame_width_top; // Form frame width at the top int m_frame_width_bottom; // Form frame width at the bottom //--- Initialize the variables void Initialize(void); //--- Create a new graphical object CGCnvElement *CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int element_num, const string name, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity); public:
クラスのpublicセクションには、ライブラリオブジェクトの標準であるメソッドといくつかのコンストラクタがあります。デフォルトコンストラクタと、指定されたチャートとサブウィンドウ、現在のチャートの指定されたサブウィンドウ、メインウィンドウの現在のチャートからオブジェクトを作成できるコンストラクタです。
public: //--- Constructors CForm(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h); CForm(const int subwindow, const string name, const int x, const int y, const int w, const int h); CForm(const string name, const int x, const int y, const int w, const int h); CForm() { this.Initialize(); } //--- Destructor ~CForm(); //--- Supported form properties (1) integer and (2) string ones virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_CANV_ELEMENT_PROP_STRING property) { return true; } //--- Return (1) the list of attached objects and (2) the shadow object CArrayObj *GetList(void) { return &this.m_list_elements; } CGCnvElement *GetShadowObj(void) { return this.m_shadow_obj; }
フォームオブジェクトを操作するメソッドは次のとおりです。
//--- Set the form (1) color scheme and (2) style virtual void SetColorTheme(const ENUM_COLOR_THEMES theme,const uchar opacity); virtual void SetFormStyle(const ENUM_FORM_STYLE style, const ENUM_COLOR_THEMES theme, const uchar opacity, const bool shadow=false, const bool redraw=false); //--- Create a new attached element bool CreateNewElement(const int element_num, const string name, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity); //--- Create a shadow object void CreateShadow(const uchar opacity); //--- Draw an object shadow void DrawShadow(const uchar opacity); //--- Draw the form frame void DrawFormFrame(const int wd_top, // Frame upper segment width const int wd_bottom, // Frame lower segment width const int wd_left, // Frame left segment width const int wd_right, // Frame right segment width const color colour, // Frame color const uchar opacity, // Frame opacity const ENUM_FRAME_STYLE style); // Frame style //--- Draw a simple frame void DrawFrameSimple(const int x, // X coordinate relative to the form const int y, // Y coordinate relative to the form const int width, // Frame width const int height, // Frame height const int wd_top, // Frame upper segment width const int wd_bottom, // Frame lower segment width const int wd_left, // Frame left segment width const int wd_right, // Frame right segment width const color colour, // Frame color const uchar opacity); // Frame opacity //--- Draw a flat frame void DrawFrameFlat(const int x, // X coordinate relative to the form const int y, // Y coordinate relative to the form const int width, // Frame width const int height, // Frame height const int wd_top, // Frame upper segment width const int wd_bottom, // Frame lower segment width const int wd_left, // Frame left segment width const int wd_right, // Frame right segment width const color colour, // Frame color const uchar opacity); // Frame opacity //--- Draw an embossed (convex) frame void DrawFrameBevel(const int x, // X coordinate relative to the form const int y, // Y coordinate relative to the form const int width, // Frame width const int height, // Frame height const int wd_top, // Frame upper segment width const int wd_bottom, // Frame lower segment width const int wd_left, // Frame left segment width const int wd_right, // Frame right segment width const color colour, // Frame color const uchar opacity); // Frame opacity //--- Draw an embossed (concave) frame void DrawFrameStamp(const int x, // X coordinate relative to the form const int y, // Y coordinate relative to the form const int width, // Frame width const int height, // Frame height const int wd_top, // Frame upper segment width const int wd_bottom, // Frame lower segment width const int wd_left, // Frame left segment width const int wd_right, // Frame right segment width const color colour, // Frame color const uchar opacity); // Frame opacity //--- Draw a simple field void DrawFieldFlat(const int x, // X coordinate relative to the form const int y, // Y coordinate relative to the form const int width, // Field width const int height, // Field height const color colour, // Field color const uchar opacity); // Field opacity //--- Draw an embossed (convex) field void DrawFieldBevel(const int x, // X coordinate relative to the form const int y, // Y coordinate relative to the form const int width, // Field width const int height, // Field height const color colour, // Field color const uchar opacity); // Field opacity //--- Draw an embossed (concave) field void DrawFieldStamp(const int x, // X coordinate relative to the form const int y, // Y coordinate relative to the form const int width, // Field width const int height, // Field height const color colour, // Field color const uchar opacity); // Field opacity //+------------------------------------------------------------------+ //| Methods of simplified access to object properties | //+------------------------------------------------------------------+ //--- (1) Set and (2) get the form frame color void SetColorFrame(const color colour) { this.m_color_frame=colour; } color ColorFrame(void) const { return this.m_color_frame; } //--- (1) Set and (2) return the form shadow color void SetColorShadow(const color colour) { this.m_color_shadow=colour; } color ColorShadow(void) const { return this.m_color_shadow; } }; //+------------------------------------------------------------------+
宣言されたメソッドについて詳しく考えてみましょう。
以下は、チャートとサブウィンドウIDを示すコンストラクタ:です。
//+------------------------------------------------------------------+ //| Constructor indicating the chart and subwindow ID | //+------------------------------------------------------------------+ CForm::CForm(const long chart_id, const int subwindow, const string name, const int x, const int y, const int w, const int h) : CGCnvElement(GRAPH_ELEMENT_TYPE_FORM,chart_id,subwindow,name,x,y,w,h) { this.Initialize(); } //+------------------------------------------------------------------+
コンストラクタは、チャートのIDと、フォームオブジェクトの作成に使用されるサブウィンドウのインデックス、その名前、左上のフォーム角度の座標、およびそのサイズを受け取ります。初期化リストで、Formオブジェクト型を指定して要素オブジェクトクラスコンストラクタを呼び出します。クラス本体で、初期化メソッドを呼び出します。
以下は、サブウィンドウを指定する現在のチャートコンストラクタです。
//+------------------------------------------------------------------+ //| Current chart constructor specifying the subwindow | //+------------------------------------------------------------------+ CForm::CForm(const int subwindow, const string name, const int x, const int y, const int w, const int h) : CGCnvElement(GRAPH_ELEMENT_TYPE_FORM,::ChartID(),subwindow,name,x,y,w,h) { this.Initialize(); } //+------------------------------------------------------------------+
コンストラクタは、フォームオブジェクトを作成するサブウィンドウの番号(現在のグラフ)、フォームオブジェクト名、左上のフォーム角度の座標、およびそのサイズを受け取ります。初期化リストで、Formオブジェクト型と現在のチャートIDを指定して要素オブジェクトクラスコンストラクタを呼び出します。クラス本体で、初期化メソッドを呼び出します。
以下は、メインチャートウィンドウの現在のチャートのコンストラクタです。
//+------------------------------------------------------------------+ //| Constructor on the current chart in the main chart window | //+------------------------------------------------------------------+ CForm::CForm(const string name, const int x, const int y, const int w, const int h) : CGCnvElement(GRAPH_ELEMENT_TYPE_FORM,::ChartID(),0,name,x,y,w,h) { this.Initialize(); } //+------------------------------------------------------------------+
コンストラクタは、フォームオブジェクトの名前、左上のフォーム角度の座標、およびそのサイズを受け取ります。初期化リストで、要素オブジェクトクラスコンストラクタを呼び出し、Formオブジェクト型と現在のチャートID、およびメインウィンドウインデックス(0)を指定します。クラス本体で、初期化メソッドを呼び出します。
クラスデストラクタで、影オブジェクトへのポインタの有効性を確認し、存在する場合はオブジェクトを削除します。
//+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CForm::~CForm() { if(m_shadow_obj!=NULL) delete m_shadow_obj; } //+------------------------------------------------------------------+
以下は、変数の初期化メソッドです。
//+------------------------------------------------------------------+ //| Initialize the variables | //+------------------------------------------------------------------+ void CForm::Initialize(void) { this.m_list_elements.Clear(); this.m_list_elements.Sort(); this.m_shadow_obj=NULL; this.m_shadow=false; this.m_frame_width_right=2; this.m_frame_width_left=2; this.m_frame_width_top=2; this.m_frame_width_bottom=2; } //+------------------------------------------------------------------+
ここでは、フォームに添付されている要素のリストをクリアし並べ替え済みリストフラグを設定して、影オブジェクトポインタ(NULL)、影描画フラグ(false)、フォームのフレームサイズ(各辺に2ピクセル)を指定します。
以下は、新しいグラフィカルオブジェクトを作成するprivateメソッド:です。
//+------------------------------------------------------------------+ //| Create a new graphical object | //+------------------------------------------------------------------+ CGCnvElement *CForm::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type, const int obj_num, const string obj_name, const int x, const int y, const int w, const int h, const color colour, const uchar opacity, const bool movable, const bool activity) { int pos=::StringLen(::MQLInfoString(MQL_PROGRAM_NAME)); string pref=::StringSubstr(NameObj(),pos+1); string name=pref+"_"+obj_name; CGCnvElement *element=new CGCnvElement(type,this.ID(),obj_num,this.ChartID(),this.SubWindow(),name,x,y,w,h,colour,opacity,movable,activity); if(element==NULL) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),": ",name); return element; } //+------------------------------------------------------------------+
このメソッドは、新しいオブジェクトの作成に必要なすべてのパラメータ(型、アタッチされたオブジェクトのリスト内のインデックス、名前、座標、サイズ、色、不透明度、オブジェクトの移動可能性、アクティビティのフラグ)を受け取ります。
クラス本体で、名前オブジェクトから末尾を取得します(名前は、プログラム名とその作成時に割り当てられたオブジェクト名で構成されます)。作成中にオブジェクト名を取得し、メソッドに渡された名前を追加する必要があります。
たとえば、名前がProgram_name_Form01の場合、Form01部分文字列を取得し、メソッドに渡された名前を追加します。影オブジェクトを作成してShadowという名前を渡すと、オブジェクト名はForm01_ Shadowになり、作成されたオブジェクトの最終的な名前はProgram_name_Form01_Shadowになります。
次に、型、チャートのパラメータ(現在のフォームオブジェクトが作成されている)、特定の名前、およびメソッドに渡されるその他のパラメータを指定して、新しいオブジェクトを作成します。作成されたオブジェクトへのメソッドポインタを返します。失敗した場合はNULLを返します。
以下は、新しい添付要素を作成するメソッドです。
//+------------------------------------------------------------------+ //| Create a new attached element | //+------------------------------------------------------------------+ bool CForm::CreateNewElement(const int element_num, const string element_name, 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 *obj=this.CreateNewGObject(GRAPH_ELEMENT_TYPE_ELEMENT,element_num,element_name,x,y,w,h,colour,opacity,movable,activity); if(obj==NULL) return false; this.m_list_elements.Sort(SORT_BY_CANV_ELEMENT_NAME_OBJ); int index=this.m_list_elements.Search(obj); if(index>WRONG_VALUE) { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_OBJ_ALREADY_IN_LIST),": ",obj.NameObj()); delete obj; return false; } if(!this.m_list_elements.Add(obj)) { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST),": ",obj.NameObj()); delete obj; return false; } return true; } //+------------------------------------------------------------------+
このメソッドは、上記のメソッドを使用して新しいグラフィック要素オブジェクトを作成し、それをフォームオブジェクト内の添付オブジェクトのリストに追加します。新しいオブジェクトの作成または添付オブジェクトのリストへの追加に失敗した場合は、エラーメッセージを表示してfalseを返します。新しい要素が正常に作成されてリストに追加されたら、trueを返します。
以下は、影オブジェクトを作成するメソッドです。
//+------------------------------------------------------------------+ //| Create the shadow object | //+------------------------------------------------------------------+ void CForm::CreateShadow(const uchar opacity) { //--- If the shadow flag is disabled, exit if(!this.m_shadow) return; //--- Calculate the shadow object coordinates according to the offset from the top and left int x=this.CoordX()-OUTER_AREA_SIZE; int y=this.CoordY()-OUTER_AREA_SIZE; //--- Calculate the width and height in accordance with the top, bottom, left and right offsets int w=this.Width()+OUTER_AREA_SIZE*2; int h=this.Height()+OUTER_AREA_SIZE*2; //--- Create a new element object and set the pointer to it in the variable this.m_shadow_obj=this.CreateNewGObject(GRAPH_ELEMENT_TYPE_ELEMENT,-1,"Shadow",x,y,w,h,this.m_chart_color_bg,opacity,Movable(),false); if(this.m_shadow_obj==NULL) return; //--- Move the form object to the foreground this.BringToTop(); } //+------------------------------------------------------------------+
メソッドロジックはコードでコメントされています。要するに、影が描かれる要素オブジェクトは、それが作成されるフォームオブジェクトよりも大きくなければならないので(影を描くために上下左右に空きスペースが必要です)、新しいサイズ オブジェクトは、OUTER_AREA_SIZEマクロ置換値に応じて計算されます。
オブジェクトが正常に作成されると、作成されたフォームオブジェクトの上に自動的に設定されます。したがって、フォームオブジェクトを強制的に前景に移動する必要があります。これは、メソッドの最後で実行されます。
以下は、影を描画するメソッドです。
//+------------------------------------------------------------------+ //| Draw the shadow | //+------------------------------------------------------------------+ void CForm::DrawShadow(const uchar opacity) { //--- If the shadow flag is disabled, exit if(!this.m_shadow) return; //--- Calculate rectangle coordinates relative to the shadow object borders int x=OUTER_AREA_SIZE+1; int y=OUTER_AREA_SIZE+1; //--- Draw a filled rectangle starting from the calculated coordinates and having the size of the current form object m_shadow_obj.DrawRectangleFill(x,y,x+Width(),y+Height(),this.ColorShadow(),opacity); //--- Update the shadow object for displaying changes m_shadow_obj.Update(); return; } //+------------------------------------------------------------------+
メソッドロジックは、コード内でコメントされています。現在、このメソッドは、オブジェクトの影を描く本格的なメソッドを作成するための単なるワークピースであり、影を描画するために作成された要素オブジェクトの現在のオブジェクトの右下にシフトされた単純な長方形を描画するだけです。
以下は、配色を設定するメソッドです。
//+------------------------------------------------------------------+ //| Set a color scheme | //+------------------------------------------------------------------+ void CForm::SetColorTheme(const ENUM_COLOR_THEMES theme,const uchar opacity) { this.SetOpacity(opacity); this.SetColorBackground(array_color_themes[theme][COLOR_THEME_COLOR_FORM_BG]); this.SetColorFrame(array_color_themes[theme][COLOR_THEME_COLOR_FORM_FRAME]); this.SetColorShadow(array_color_themes[theme][COLOR_THEME_COLOR_FORM_SHADOW]); } //+------------------------------------------------------------------+
このメソッドは、オブジェクトに指定されたカラーテーマを設定するために使用されます。このメソッドは、必要なテーマとフォームオブジェクトの不透明度の値を受け取ります。次に、フォームの不透明度、フォームの背景色、フォームのフレームの色、フォームの影の色が、上記で作成したカラーテーマの配列に記述された値から設定されます。
以下は、フォームのスタイルを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the form style | //+------------------------------------------------------------------+ void CForm::SetFormStyle(const ENUM_FORM_STYLE style, const ENUM_COLOR_THEMES theme, const uchar opacity, const bool shadow=false, const bool redraw=false) { //--- Set opacity parameters and the size of the form frame side this.m_shadow=shadow; this.m_frame_width_top=array_form_style[style][FORM_STYLE_FRAME_WIDTH_TOP]; this.m_frame_width_bottom=array_form_style[style][FORM_STYLE_FRAME_WIDTH_BOTTOM]; this.m_frame_width_left=array_form_style[style][FORM_STYLE_FRAME_WIDTH_LEFT]; this.m_frame_width_right=array_form_style[style][FORM_STYLE_FRAME_WIDTH_RIGHT]; //--- Set the color scheme this.SetColorTheme(theme,opacity); //--- Create the shadow object and draw a simple distinct shadow this.CreateShadow((uchar)array_form_style[style][FORM_STYLE_FRAME_SHADOW_OPACITY]); this.DrawShadow((uchar)array_form_style[style][FORM_STYLE_FRAME_SHADOW_OPACITY]); //--- Fill in the form background with color and opacity this.Erase(this.ColorBackground(),this.Opacity()); //--- Depending on the selected form style, draw the corresponding form frame and the outer bounding frame switch(style) { case FORM_STYLE_BEVEL : this.DrawFormFrame(this.m_frame_width_top,this.m_frame_width_bottom,this.m_frame_width_left,this.m_frame_width_right,this.ColorFrame(),this.Opacity(),FRAME_STYLE_BEVEL); this.DrawRectangle(0,0,Width()-1,Height()-1,array_color_themes[theme][COLOR_THEME_COLOR_FORM_FRAME_OUTER],this.Opacity()); break; //---FORM_STYLE_FLAT default: this.DrawFormFrame(this.m_frame_width_top,this.m_frame_width_bottom,this.m_frame_width_left,this.m_frame_width_right,this.ColorFrame(),this.Opacity(),FRAME_STYLE_FLAT); this.DrawRectangle(0,0,Width()-1,Height()-1,array_color_themes[theme][COLOR_THEME_COLOR_FORM_FRAME_OUTER],this.Opacity()); break; } } //+------------------------------------------------------------------+
メソッドロジックはコードでコメントされています。
実際、このメソッドは、必要なパラメータを使用してフォームオブジェクトを作成する例です。
以下は、フォームフレームを描画するメソッドです。
//+------------------------------------------------------------------+ //| Draw the form frame | //+------------------------------------------------------------------+ void CForm::DrawFormFrame(const int wd_top, // Frame upper segment width const int wd_bottom, // Frame lower segment width const int wd_left, // Frame left segment width const int wd_right, // Frame right segment width const color colour, // Frame color const uchar opacity, // Frame opacity const ENUM_FRAME_STYLE style) // Frame style { //--- Depending on the passed frame style switch(style) { //--- draw a dimensional (convex) frame case FRAME_STYLE_BEVEL : DrawFrameBevel(0,0,Width(),Height(),wd_top,wd_bottom,wd_left,wd_right,colour,opacity); break; //--- draw a dimensional (concave) frame case FRAME_STYLE_STAMP : DrawFrameStamp(0,0,Width(),Height(),wd_top,wd_bottom,wd_left,wd_right,colour,opacity); break; //--- draw a flat frame case FRAME_STYLE_FLAT : DrawFrameFlat(0,0,Width(),Height(),wd_top,wd_bottom,wd_left,wd_right,colour,opacity); break; //--- draw a simple frame default: //---FRAME_STYLE_SIMPLE DrawFrameSimple(0,0,Width(),Height(),wd_top,wd_bottom,wd_left,wd_right,colour,opacity); break; } } //+------------------------------------------------------------------+
フレームスタイルに応じて、適切なフォームフレームを描画します。
以下は、単純なフレームを描画するメソッドです。
//+------------------------------------------------------------------+ //| Draw a simple frame | //+------------------------------------------------------------------+ void CForm::DrawFrameSimple(const int x, // X coordinate relative to the form const int y, // Y coordinate relative to the form const int width, // Frame width const int height, // Frame height const int wd_top, // Frame upper segment width const int wd_bottom, // Frame lower segment width const int wd_left, // Frame left segment width const int wd_right, // Frame right segment width const color colour, // Frame color const uchar opacity) // Frame opacity { //--- Set rectangle coordinates int x1=x, y1=y; int x2=x1+width-1; int y2=y1+height-1; //--- Draw the first rectangle CGCnvElement::DrawRectangle(x1,y1,x2,y2,colour,opacity); //--- If the frame width exceeds 1 on all sides, draw the second rectangle if(wd_left>1 || wd_right>1 || wd_top>1 || wd_bottom>1) CGCnvElement::DrawRectangle(x1+wd_left-1,y1+wd_top-1,x2-wd_right+1,y2-wd_bottom+1,colour,opacity); //--- Search for "voids" between the lines of two rectangles and fill them with color if(wd_left>2 && wd_right>2 && wd_top>2 && wd_bottom>2) this.Fill(x1+1,y1+1,colour,opacity); else if(wd_left>2 && wd_top>2) this.Fill(x1+1,y1+1,colour,opacity); else if(wd_right>2 && wd_bottom>2) this.Fill(x2-1,y2-1,colour,opacity); else if(wd_left<3 && wd_right<3) { if(wd_top>2) this.Fill(x1+1,y1+1,colour,opacity); if(wd_bottom>2) this.Fill(x1+1,y2-1,colour,opacity); } else if(wd_top<3 && wd_bottom<3) { if(wd_left>2) this.Fill(x1+1,y1+1,colour,opacity); if(wd_right>2) this.Fill(x2-1,y1+1,colour,opacity); } } //+------------------------------------------------------------------+
メソッドロジックは、コード内の詳細なコメントを特徴としています。つまり、2つの入れ子になっている長方形を描画します。将来フレームの側面を形成するスポットの長方形の間に隙間がある場合(長方形の側面が重なっていない場合)、長方形の描画に使用したのと同じ色で塗りつぶします。
以下は、平らなフレームを描画するメソッドです。
//+------------------------------------------------------------------+ //| Draw the flat frame | //+------------------------------------------------------------------+ void CForm::DrawFrameFlat(const int x, const int y, const int width, const int height, const int wd_top, const int wd_bottom, const int wd_left, const int wd_right, const color colour, const uchar opacity) { //--- Draw a simple frame this.DrawFrameSimple(x,y,width,height,wd_top,wd_bottom,wd_left,wd_right,colour,opacity); //--- If the width of the frame top and bottom exceeds one pixel if(wd_top>1 && wd_bottom>1) { //--- Darken the horizontal sides of the frame for(int i=0;i<width;i++) { this.m_canvas.PixelSet(x+i,y,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y),-0.05)); this.m_canvas.PixelSet(x+i,y+height-1,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+height-1),-0.07)); } } //--- If the width of the frame left and right sides exceeds one pixel if(wd_left>1 && wd_right>1) { //--- Darken the vertical sides of the frame for(int i=1;i<height-1;i++) { this.m_canvas.PixelSet(x,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x,y+1),-0.01)); this.m_canvas.PixelSet(x+width-1,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+width-1,y+1),-0.02)); } } } //+------------------------------------------------------------------+
以下は、エンボス(凸)フレームを描画するメソッドです。
//+------------------------------------------------------------------+ //| Draw an embossed (convex) frame | //+------------------------------------------------------------------+ void CForm::DrawFrameBevel(const int x, const int y, const int width, const int height, const int wd_top, const int wd_bottom, const int wd_left, const int wd_right, const color colour, const uchar opacity) { //--- Draw a simple frame this.DrawFrameSimple(x,y,width,height,wd_top,wd_bottom,wd_left,wd_right,colour,opacity); //--- If the width of the frame top and bottom exceeds one pixel if(wd_top>1 && wd_bottom>1) { //--- Lighten and darken the required sides of the frame edges for(int i=0;i<width;i++) { this.m_canvas.PixelSet(x+i,y,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y),0.25)); this.m_canvas.PixelSet(x+i,y+height-1,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+height-1),-0.2)); } for(int i=wd_left;i<width-wd_right;i++) { this.m_canvas.PixelSet(x+i,y+wd_top-1,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+wd_top-1),-0.2)); this.m_canvas.PixelSet(x+i,y+height-wd_bottom,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+height-wd_bottom),0.1)); } } //--- If the width of the frame left and right sides exceeds one pixel if(wd_left>1 && wd_right>1) { //--- Lighten and darken the required sides of the frame edges for(int i=1;i<height-1;i++) { this.m_canvas.PixelSet(x,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x,y+i),0.1)); this.m_canvas.PixelSet(x+width-1,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+width-1,y+i),-0.1)); } for(int i=wd_top;i<height-wd_bottom;i++) { this.m_canvas.PixelSet(x+wd_left-1,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+wd_left-1,y+i),-0.1)); this.m_canvas.PixelSet(x+width-wd_right,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+width-wd_right,y+i),0.1)); } } } //+------------------------------------------------------------------+
以下は、エンボス(凹)フレームを描画するメソッドです。
//+------------------------------------------------------------------+ //| Draw an embossed (concave) frame | //+------------------------------------------------------------------+ void CForm::DrawFrameStamp(const int x, const int y, const int width, const int height, const int wd_top, const int wd_bottom, const int wd_left, const int wd_right, const color colour, const uchar opacity) { //--- Draw a simple frame this.DrawFrameSimple(x,y,width,height,wd_top,wd_bottom,wd_left,wd_right,colour,opacity); //--- If the width of the frame top and bottom exceeds one pixel if(wd_top>1 && wd_bottom>1) { //--- Lighten and darken the required sides of the frame edges for(int i=0;i<width;i++) { this.m_canvas.PixelSet(x+i,y,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y),-0.25)); this.m_canvas.PixelSet(x+i,y+height-1,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+height-1),0.2)); } for(int i=wd_left;i<width-wd_right;i++) { this.m_canvas.PixelSet(x+i,y+wd_top-1,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+wd_top-1),0.2)); this.m_canvas.PixelSet(x+i,y+height-wd_bottom,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+height-wd_bottom),-0.25)); } } //--- If the width of the frame left and right sides exceeds one pixel if(wd_left>1 && wd_right>1) { //--- Lighten and darken the required sides of the frame edges for(int i=1;i<height-1;i++) { this.m_canvas.PixelSet(x,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x,y+i),-0.1)); this.m_canvas.PixelSet(x+width-1,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+width-1,y+i),0.2)); } for(int i=wd_top;i<height-wd_bottom;i++) { this.m_canvas.PixelSet(x+wd_left-1,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+wd_left-1,y+i),0.2)); this.m_canvas.PixelSet(x+width-wd_right,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+width-wd_right,y+i),-0.2)); } } } //+------------------------------------------------------------------+
以下は、フィールドを描画するメソッド(シンプルおよびエンボスフィールド)です。
//+------------------------------------------------------------------+ //| Draw a simple field | //+------------------------------------------------------------------+ void CForm::DrawFieldFlat(const int x,const int y,const int width,const int height,const color colour,const uchar opacity) { //--- Draw a filled rectangle CGCnvElement::DrawRectangleFill(x,y,x+width-1,y+height-1,colour,opacity); //--- Darken all its edges for(int i=0;i<width;i++) { this.m_canvas.PixelSet(x+i,y,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y),-0.05)); this.m_canvas.PixelSet(x+i,y+height-1,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+height-1),-0.05)); } for(int i=1;i<height-1;i++) { this.m_canvas.PixelSet(x,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x,y+1),-0.05)); this.m_canvas.PixelSet(x+width-1,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+width-1,y+1),-0.05)); } } //+------------------------------------------------------------------+ //| Draw an embossed (convex) field | //+------------------------------------------------------------------+ void CForm::DrawFieldBevel(const int x,const int y,const int width,const int height,const color colour,const uchar opacity) { //--- Draw a filled rectangle CGCnvElement::DrawRectangleFill(x,y,x+width-1,y+height-1,colour,opacity); //--- Lighten its top and left and darken its bottom and right for(int i=0;i<width;i++) { this.m_canvas.PixelSet(x+i,y,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y),0.1)); this.m_canvas.PixelSet(x+i,y+height-1,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+height-1),-0.1)); } for(int i=1;i<height-1;i++) { this.m_canvas.PixelSet(x,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x,y+1),0.05)); this.m_canvas.PixelSet(x+width-1,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+width-1,y+1),-0.05)); } } //+------------------------------------------------------------------+ //| Draw an embossed (concave) field | //+------------------------------------------------------------------+ void CForm::DrawFieldStamp(const int x,const int y,const int width,const int height,const color colour,const uchar opacity) { //--- Draw a filled rectangle CGCnvElement::DrawRectangleFill(x,y,x+width-1,y+height-1,colour,opacity); //--- Darken its top and left and lighten its bottom and right for(int i=0;i<width;i++) { this.m_canvas.PixelSet(x+i,y,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y),-0.1)); this.m_canvas.PixelSet(x+i,y+height-1,CGCnvElement::ChangeColorLightness(this.GetPixel(x+i,y+height-1),0.1)); } for(int i=1;i<height-1;i++) { this.m_canvas.PixelSet(x,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x,y+1),-0.05)); this.m_canvas.PixelSet(x+width-1,y+i,CGCnvElement::ChangeColorLightness(this.GetPixel(x+width-1,y+1),0.05)); } } //+------------------------------------------------------------------+
上記のすべてのメソッドのロジックはほぼ同じであり、メソッドコードにコメントが含まれています。非常にわかりやすく、理解しやすいと思います。いずれにせよ、コメントセクションを使用してください。
今のところフォームオブジェクトの作成はこれで完了です。
検証
今日のテストは非常に簡単です。構築スタイルや色のテーマが異なる2つの異なるフォームを作成して、フォームが作成されたら、フィールドをフォームに追加します。上のフォームは次元の凹面フィールドを取得し、2番目のフォームは半透明の次元の凹面フィールドを取得します。
テストを実行するには、前の記事のEAを使用して、\MQL5\Experts\TestDoEasy\Part76\にTestDoEasyPart76.mq5として保存します。
ライブラリフォームオブジェクトファイルをEAに含めますそして要素オブジェクトのリストの名前をフォームオブジェクトのリストに変更します。
//+------------------------------------------------------------------+ //| TestDoEasyPart76.mq5 | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" //--- includes #include <Arrays\ArrayObj.mqh> #include <DoEasy\Services\Select.mqh> #include <DoEasy\Objects\Graph\Form.mqh> //--- defines #define FORMS_TOTAL (2) // Number of created forms //--- input parameters sinput bool InpMovable = true; // Movable flag //--- global variables CArrayObj list_forms; //+------------------------------------------------------------------+
OnInit()ハンドラで、2つのフォームを作成し、それらに凹型フィールドを描画します。
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Set the permissions to send cursor movement and mouse scroll events ChartSetInteger(ChartID(),CHART_EVENT_MOUSE_MOVE,true); ChartSetInteger(ChartID(),CHART_EVENT_MOUSE_WHEEL,true); //--- Set EA global variables //--- Create the specified number of form objects list_forms.Clear(); int total=FORMS_TOTAL; for(int i=0;i<total;i++) { //--- When creating an object, pass all the required parameters to it CForm *form=new CForm("Form_0"+(string)(i+1),300,40+(i*80),100,70); if(form==NULL) continue; //--- Set activity and moveability flags for the form form.SetActive(true); form.SetMovable(false); //--- Set the form ID equal to the loop index and the index in the list of objects form.SetID(i); form.SetNumber(0); // (0 - main form object) Auxiliary objects may be attached to the main one. The main object is able to manage them //--- Set the full opacity for the top form and the partial opacity for the bottom one uchar opacity=(i==0 ? 255 : 250); //--- Set the form style and its color theme depending on the loop index ENUM_FORM_STYLE style=(ENUM_FORM_STYLE)i; ENUM_COLOR_THEMES theme=(ENUM_COLOR_THEMES)i; //--- Set the form style and theme form.SetFormStyle(style,theme,opacity,true); //--- If this is the first (top) form if(i==0) { //--- Draw a concave field slightly shifted from the center of the form downwards form.DrawFieldStamp(3,10,form.Width()-6,form.Height()-13,form.ColorBackground(),form.Opacity()); form.Update(true); } //--- If this is the second (bottom) form if(i==1) { //--- Draw a concave semi-transparent "tainted glass" field in the center form.DrawFieldStamp(10,10,form.Width()-20,form.Height()-20,clrWheat,200); form.Update(true); } //--- Add objects to the list if(!list_forms.Add(form)) { delete form; continue; } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
OnChartEvent()ハンドラからオブジェクトへのマウスクリックの処理を削除します。
//+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- If clicking on an object if(id==CHARTEVENT_OBJECT_CLICK) { } } //+------------------------------------------------------------------+
EAをコンパイルし、チャート上で起動します。
ご覧のとおり、目的のスタイルと色のテーマを指定するだけで、コンポーネントの色と描画スタイルが異なる2つの異なるフォームを作成できました。
次の段階
次の記事では、フォームオブジェクトの開発を続け、その機能を広げます。
ライブラリの現在のバージョンのすべてのファイルは、テストおよびダウンロードできるように、MQL5のテストEAファイルと一緒に以下に添付されています。
質問や提案はコメント欄にお願いします。
**連載のこれまでの記事:
DoEasyライブラリのグラフィックス(第73部): グラフィック要素のフォームオブジェクト
DoEasyライブラリのグラフィックス(第74部): CCanvasクラスを使用した基本的グラフィック要素
DoEasyライブラリのグラフィックス(第75部): 基本的なグラフィック要素でプリミティブとテキストを処理するメソッド
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/9553
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索