
DoEasy - コントロール(第25部):Tooltip WinFormsオブジェクト
内容
概念
コントロールにマウスを合わせてしばらくすると、説明のツールチップが表示されます。当然ながら、すべての要素にツールチップがあるわけではないですが、すべてのグラフィックオブジェクトにはツールチップを設定する機能があります。そのような可能性を、ライブラリのグラフィック要素に与えてみましょう。
ライブラリのすべてのグラフィック要素が他のグラフィック要素の存在を「知っている」わけではありませんが、これらのオブジェクトはすべて、管理された要素を自らに接続することができます。グラフィック要素に接続されるオブジェクトには、親要素が何も知らないオブジェクトが含まれることがあります。接続された要素の制御はグラフィック要素のコレクションクラスでおこなわれるため、様々なタイプのコントロールの可視性に問題はなく、コレクションクラスはそれらについてすべてを知っています。
また、MS Visual Studioを例にとると、作成されたToolTipオブジェクトは、フォームオブジェクトで見ることができ、このフォームにバインドされているオブジェクトに割り当てることができます。これは次のような方法でおこないます。ToolTipオブジェクトのクラスを見ることになるオブジェクトは、それを作成することができ、他のすべてのオブジェクトは、以前に作成したその種のオブジェクトを自らに接続することができます。ArrayObjリストは、標準ライブラリの基本クラスから派生したあらゆるオブジェクトを受け入れるため、これを「知る」必要はありません。
言い換えれば、コンテナオブジェクト(他のグラフィカルオブジェクトを作成し、それらに接続する機能を持つ)において、ツールチップコントロールを作成し、このツールチップをどの要素に割り当てるべきかを示すことができるのです。要素はToolTipオブジェクトへのポインタを特徴とし、ツールチップの対象となったオブジェクトは割り当てられたToolTipオブジェクトに設定されます。
通常、ツールチップはカーソルがコントロールにしばらく合わせられた後に表示されます。オブジェクトに複数のヒントが割り当てられていて最初のヒントがすでに表示されている場合、そのオブジェクトにカーソルを移動すると、残りのツールチップがほぼ遅延なく表示されます。この挙動については、今後の記事のテーマとします。ここでおこなうのは、ToolTipコントロールを作成してグラフィック要素に割り当てることができるようにすることだけです。
ここでは、新しいコントロールの開発に加え、標準的なアイコンをはじめ、右左や上下の矢印など、新しいグラフィカルプリミティブを描画する機能を追加します...つまり、定義済みの画像を「そのまま」使える機能をライブラリに少しずつ追加していく予定です。このようなアイコンは、ToolTipコントロールや先に作成した他の要素で使用することができます。後に、ライブラリのすべてのグラフィック要素で新しいグラフィカルプリミティブを使用する機能を追加する予定です。
ライブラリクラスの改善
\MQL5\Include\DoEasy\Defines.mqhで、グラフィック要素タイプのリストに新しいグラフィック要素タイプを追加します。
//+-------------------------------------------------+ //| The list of graphical element types | //+-------------------------------------------------+ enum ENUM_GRAPH_ELEMENT_TYPE { GRAPH_ELEMENT_TYPE_STANDARD, // Standard graphical object GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED, // Extended standard graphical object GRAPH_ELEMENT_TYPE_SHADOW_OBJ, // Shadow object GRAPH_ELEMENT_TYPE_ELEMENT, // Element GRAPH_ELEMENT_TYPE_FORM, // Form GRAPH_ELEMENT_TYPE_WINDOW, // Window //--- WinForms GRAPH_ELEMENT_TYPE_WF_UNDERLAY, // Panel object underlay GRAPH_ELEMENT_TYPE_WF_BASE, // Windows Forms Base //--- 'Container' object types are to be set below GRAPH_ELEMENT_TYPE_WF_CONTAINER, // Windows Forms container base object GRAPH_ELEMENT_TYPE_WF_PANEL, // Windows Forms Panel GRAPH_ELEMENT_TYPE_WF_GROUPBOX, // Windows Forms GroupBox GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL, // Windows Forms TabControl GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER, // Windows Forms SplitContainer //--- 'Standard control' object types are to be set below GRAPH_ELEMENT_TYPE_WF_COMMON_BASE, // Windows Forms base standard control GRAPH_ELEMENT_TYPE_WF_LABEL, // Windows Forms Label GRAPH_ELEMENT_TYPE_WF_BUTTON, // Windows Forms Button GRAPH_ELEMENT_TYPE_WF_CHECKBOX, // Windows Forms CheckBox GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON, // Windows Forms RadioButton GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX, // Base list object of Windows Forms elements GRAPH_ELEMENT_TYPE_WF_LIST_BOX, // Windows Forms ListBox GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX, // Windows Forms CheckedListBox GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX, // Windows Forms ButtonListBox GRAPH_ELEMENT_TYPE_WF_TOOLTIP, // Windows Forms ToolTip //--- Auxiliary elements of WinForms objects GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM, // Windows Forms ListBoxItem GRAPH_ELEMENT_TYPE_WF_TAB_HEADER, // Windows Forms TabHeader GRAPH_ELEMENT_TYPE_WF_TAB_FIELD, // Windows Forms TabField GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL, // Windows Forms SplitContainerPanel GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON, // Windows Forms ArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP, // Windows Forms UpArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN, // Windows Forms DownArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT, // Windows Forms LeftArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT, // Windows Forms RightArrowButton GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX, // Windows Forms UpDownArrowButtonsBox GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX, // Windows Forms LeftRightArrowButtonsBox GRAPH_ELEMENT_TYPE_WF_SPLITTER, // Windows Forms Splitter GRAPH_ELEMENT_TYPE_WF_HINT_BASE, // Windows Forms HintBase GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT, // Windows Forms HintMoveLeft GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT, // Windows Forms HintMoveRight GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP, // Windows Forms HintMoveUp GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN, // Windows Forms HintMoveDown }; //+------------------------------------------------------------------+
情報、警告、エラーなどの標準的な画像を描画できるようにするには、適切なアイコンタイプの列挙を作成します。
//+-------------------------------------------------+ //| Separator location in Split Container | //+-------------------------------------------------+ enum ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION { CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL, // Vertical CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL, // Horizontal }; //+-------------------------------------------------+ //| The list of predefined icons | //+-------------------------------------------------+ enum ENUM_CANV_ELEMENT_TOOLTIP_ICON { CANV_ELEMENT_TOOLTIP_ICON_NONE, // None CANV_ELEMENT_TOOLTIP_ICON_INFO, // Info CANV_ELEMENT_TOOLTIP_ICON_WARNING, // Warning CANV_ELEMENT_TOOLTIP_ICON_ERROR, // Error CANV_ELEMENT_TOOLTIP_ICON_USER, // User }; //+-----------------------------------------------------------+ //| Integer properties of the graphical element on the canvas | //+-----------------------------------------------------------+
ここでは、ライブラリに新しく作成するアイコンの名前を入力することにします。そして、コントロールに描画したいアイコンの種類をリストから選択するだけです。リストから特定の種類のアイコンをそれぞれ描画するメソッドは、後ほど実装します。
新しいコントロールには、新しいプロパティが必要です。
グラフィック要素の整数プロパティのリストに新しいプロパティを追加し、その総数を122から129に増やします。
//+------------------------------------------------------------------+ //| 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_SPLIT_CONTAINER_PANEL2_COLLAPSED,// Flag for collapsed panel 2 CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE, // Panel 2 minimum size CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY, // Tooltip display delay CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY, // Tooltip display duration CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY, // One element new tooltip display delay CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS, // Display a tooltip in inactive window CANV_ELEMENT_PROP_TOOLTIP_ICON, // Icon displayed in tooltip CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON, // Tooltip in the form of a "cloud" CANV_ELEMENT_PROP_TOOLTIP_USE_FADING, // Fade when showing/hiding a tooltip }; #define CANV_ELEMENT_PROP_INTEGER_TOTAL (129) // Total number of integer properties #define CANV_ELEMENT_PROP_INTEGER_SKIP (0) // Number of integer properties not used in sorting //+------------------------------------------------------------------+
文字列プロパティのリストに新しいプロパティを2つ追加し、その合計数を6に増やします。
//+------------------------------------------------------------------+ //| String properties of the graphical element on the canvas | //+------------------------------------------------------------------+ enum ENUM_CANV_ELEMENT_PROP_STRING { CANV_ELEMENT_PROP_NAME_OBJ = (CANV_ELEMENT_PROP_INTEGER_TOTAL+CANV_ELEMENT_PROP_DOUBLE_TOTAL), // Graphical element object name CANV_ELEMENT_PROP_NAME_RES, // Graphical resource name CANV_ELEMENT_PROP_TEXT, // Graphical element text CANV_ELEMENT_PROP_DESCRIPTION, // Graphical element description CANV_ELEMENT_PROP_TOOLTIP_TITLE, // Element tooltip title CANV_ELEMENT_PROP_TOOLTIP_TEXT, // Element tooltip text }; #define CANV_ELEMENT_PROP_STRING_TOTAL (6) // Total number of string properties //+------------------------------------------------------------------+
キャンバス上のグラフィック要素を並べ替える可能性のある基準の列挙に新しいプロパティを追加します。
//+------------------------------------------------------------------+ //| 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_SPLIT_CONTAINER_PANEL2_COLLAPSED,// Sort by flag for collapsed panel 2 SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_PANEL2_MIN_SIZE, // Sort by panel 2 minimum size SORT_BY_CANV_ELEMENT_TOOLTIP_INITIAL_DELAY, // Sort by tooltip display delay SORT_BY_CANV_ELEMENT_TOOLTIP_AUTO_POP_DELAY, // Sort by tooltip display duration SORT_BY_CANV_ELEMENT_TOOLTIP_RESHOW_DELAY, // Sort by one element new tooltip display delay SORT_BY_CANV_ELEMENT_TOOLTIP_SHOW_ALWAYS, // Sort by a tooltip in inactive window SORT_BY_CANV_ELEMENT_TOOLTIP_ICON, // Sort by icon displayed in a tooltip SORT_BY_CANV_ELEMENT_TOOLTIP_IS_BALLOON, // Sort by a cloud tooltip flag SORT_BY_CANV_ELEMENT_TOOLTIP_USE_FADING, // Sort by the flag of fading when showing/hiding a tooltip //--- 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 SORT_BY_CANV_ELEMENT_TEXT, // Sort by graphical element text SORT_BY_CANV_ELEMENT_DESCRIPTION, // Sort by graphical element description SORT_BY_CANV_ELEMENT_TOOLTIP_HEADER, // Sort by ToolTip header for an element SORT_BY_CANV_ELEMENT_TOOLTIP_TEXT, // Sort by ToolTip text for an element }; //+------------------------------------------------------------------+
これで、新しいプロパティでグラフィック要素を並べ替えて選択できるようになります。
\MQL5\Include\DoEasy\Data.mqhに、新しいメッセージインデックスを追加します。
//--- CForm MSG_FORM_OBJECT_TEXT_NO_SHADOW_OBJ_FIRST_CREATE_IT,// No shadow object. Create it using the CreateShadowObj() method MSG_FORM_OBJECT_ERR_FAILED_CREATE_SHADOW_OBJ, // Failed to create new shadow object MSG_FORM_OBJECT_ERR_FAILED_CREATE_PC_OBJ, // Failed to create new pixel copier object MSG_FORM_OBJECT_PC_OBJ_ALREADY_IN_LIST, // Pixel copier object with ID already present in the list MSG_FORM_OBJECT_PC_OBJ_NOT_EXIST_LIST, // No pixel copier object with ID in the list MSG_FORM_OBJECT_ERR_NOT_INTENDED, // The method is not meant for creating such an object: MSG_FORM_TOOLTIP_OBJ_ALREADY_EXISTS, // ToolTip object already exists //--- CFrame
...
MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP, // HintMoveLeft control MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN, // HintMoveLeft control MSG_GRAPH_ELEMENT_TYPE_WF_TOOLTIP, // ToolTip control MSG_GRAPH_OBJ_BELONG_PROGRAM, // Graphical object belongs to a program MSG_GRAPH_OBJ_BELONG_NO_PROGRAM, // Graphical object does not belong to a program
...
MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED, // Flag for collapsed panel 1 MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE, // Panel 2 minimum size MSG_CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY, // Tooltip display delay MSG_CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY, // Tooltip display duration MSG_CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY, // One element new tooltip display delay MSG_CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS, // Display a tooltip in inactive window MSG_CANV_ELEMENT_PROP_TOOLTIP_ICON, // Icon displayed in a tooltip MSG_CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON, // Tooltip in the form of a "cloud" MSG_CANV_ELEMENT_PROP_TOOLTIP_USE_FADING, // Fade when showing/hiding a tooltip //--- Real properties of graphical elements //--- String properties of graphical elements MSG_CANV_ELEMENT_PROP_NAME_OBJ, // Graphical element object name MSG_CANV_ELEMENT_PROP_NAME_RES, // Graphical resource name MSG_CANV_ELEMENT_PROP_TEXT, // Graphical element text MSG_CANV_ELEMENT_PROP_DESCRIPTION, // Graphical element description MSG_CANV_ELEMENT_PROP_TOOLTIP_TITLE, // Element tooltip title MSG_CANV_ELEMENT_PROP_TOOLTIP_TEXT, // Element tooltip text }; //+------------------------------------------------------------------+
また、新しく追加されたインデックスに対応するテキストメッセージも追加します。
//--- CForm {"Отсутствует объект тени. Необходимо сначала его создать при помощи метода CreateShadowObj()","There is no shadow object. You must first create it using the CreateShadowObj () method"}, {"Не удалось создать новый объект для тени","Failed to create new object for shadow"}, {"Не удалось создать новый объект-копировщик пикселей","Failed to create new pixel copier object"}, {"В списке уже есть объект-копировщик пикселей с идентификатором ","There is already a pixel copier object in the list with ID "}, {"В списке нет объекта-копировщика пикселей с идентификатором ","No pixel copier object with ID "}, {"Метод не предназначен для создания такого объекта: ","The method is not intended to create such an object: "}, {"Объект ToolTip уже существует","ToolTip object already exists"}, //--- CFrame
...
{"Элемент управления \"HintMoveUp\"","Control element \"HintMoveUp\""}, {"Элемент управления \"HintMoveDown\"","Control element \"HintMoveDown\""}, {"Элемент управления \"ToolTip\"","Control element \"ToolTip\""}, {"Графический объект принадлежит программе","The graphic object belongs to the program"}, {"Графический объект не принадлежит программе","The graphic object does not belong to the program"},
...
{"Флаг свёрнутости панели 2","Flag to indicate that panel 2 is collapsed"}, {"Минимальный размер панели 2","Min size of Panel 2"}, {"Задержка отображения подсказки","Tooltip initial delay"}, {"Длительность отображения подсказки","Tooltip autopoop delay"}, {"Задержка отображения новой подсказки одного элемента","Tooltip reshow delay"}, {"Отображать подсказку в неактивном окне","Tooltip show always"}, {"Значок, отображаемый в подсказке","Tooltip icon"}, {"Подсказка в форме \"облачка\"","Tooltip as \"Balloon\""}, {"Угасание при отображении и скрытии подсказки","Tooltip uses fading"}, //--- String properties of graphical elements {"Имя объекта-графического элемента","The name of the graphic element object"}, {"Имя графического ресурса","Image resource name"}, {"Текст графического элемента","Text of the graphic element"}, {"Описание графического элемента","Description of the graphic element"}, {"Заголовок подсказки элемента","Element tooltip header"}, {"Текст подсказки элемента","Element tooltip title"}, }; //+---------------------------------------------------------------------+
グラフィック要素の説明を取得するには、基本グラフィックライブラリオブジェクトの\MQL5Include╱DoEasy╱Graph╱GBaseObj.mqhファイルにTypeElementDescription()メソッドが備わっています。それに新しいコントロールの説明を返すことを追加します。
//+------------------------------------------------------------------+ //| Return the description of the graphical element type | //+------------------------------------------------------------------+ string CGBaseObj::TypeElementDescription(const ENUM_GRAPH_ELEMENT_TYPE type) { return ( type==GRAPH_ELEMENT_TYPE_STANDARD ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD) : type==GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED) : type==GRAPH_ELEMENT_TYPE_ELEMENT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_ELEMENT) : type==GRAPH_ELEMENT_TYPE_SHADOW_OBJ ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_SHADOW_OBJ) : type==GRAPH_ELEMENT_TYPE_FORM ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_FORM) : type==GRAPH_ELEMENT_TYPE_WINDOW ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WINDOW) : //--- WinForms type==GRAPH_ELEMENT_TYPE_WF_UNDERLAY ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_UNDERLAY) : type==GRAPH_ELEMENT_TYPE_WF_BASE ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BASE) : //--- Containers type==GRAPH_ELEMENT_TYPE_WF_CONTAINER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CONTAINER) : type==GRAPH_ELEMENT_TYPE_WF_GROUPBOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_GROUPBOX) : type==GRAPH_ELEMENT_TYPE_WF_PANEL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_PANEL) : type==GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL) : type==GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER) : //--- Standard controls type==GRAPH_ELEMENT_TYPE_WF_COMMON_BASE ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_COMMON_BASE) : type==GRAPH_ELEMENT_TYPE_WF_LABEL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LABEL) : type==GRAPH_ELEMENT_TYPE_WF_CHECKBOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CHECKBOX) : type==GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON) : type==GRAPH_ELEMENT_TYPE_WF_BUTTON ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON) : type==GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX) : type==GRAPH_ELEMENT_TYPE_WF_LIST_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LIST_BOX) : type==GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM) : type==GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX) : type==GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX) : type==GRAPH_ELEMENT_TYPE_WF_TOOLTIP ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TOOLTIP) : //--- Auxiliary control objects type==GRAPH_ELEMENT_TYPE_WF_TAB_HEADER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_HEADER) : type==GRAPH_ELEMENT_TYPE_WF_TAB_FIELD ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_FIELD) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX) : type==GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX) : type==GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL) : type==GRAPH_ELEMENT_TYPE_WF_SPLITTER ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_SPLITTER) : type==GRAPH_ELEMENT_TYPE_WF_HINT_BASE ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_BASE) : type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT) : type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT) : type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP) : type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN) : "Unknown" ); } //+------------------------------------------------------------------+
このメソッドは、オブジェクトのタイプを受け取り、その説明を取得します。渡されたタイプに応じて、上記でData.mqhファイルに追加したメッセージのインデックスに応じたテキスト説明が表示されます。
これまでは、接続されたグラフィック要素を作成する際に、グラフィック要素の基本オブジェクトを手動で指定していました。
また、前回の記事で、その必要性をなくし、メインオブジェクトと基本オブジェクトへのポインタをオブジェクトに書き込むメソッドを削除しました。しかし、実践が示すように、やはりそのようなメソッドが必要です。ツールチップが作成された要素を新しいToolTipオブジェクトに書き込むためには、基本オブジェクトへのポインタを書き込むためのメソッドが必要です。
\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqhのpublicセクションで、このようなメソッドをもう一度書きます。
public: //--- (1) Set and (2) return the X coordinate shift relative to the base object void SetCoordXRelative(const int value) { this.m_shift_coord_x=value; } int CoordXRelative(void) const { return this.m_shift_coord_x; } //--- (1) Set and (2) return the Y coordinate shift relative to the base object void SetCoordYRelative(const int value) { this.m_shift_coord_y=value; } int CoordYRelative(void) const { return this.m_shift_coord_y; } //--- Set the pointer to the parent element within related objects of the current group void SetBase(CGCnvElement *base) { this.m_element_base=base; } //--- Event handler virtual void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam);
このメソッドは、変数m_element_baseに代入された基本オブジェクトへのポインタを受け取ります。したがって、ツールチップがどのオブジェクトに対して作成されたかを示すために、マウスカーソルがツールチップをトリガーする要素にポインタを書き込むことになります。
要素の不透明度を設定するメソッドと要素の表示フラグを指定するメソッドは、継承したクラスで再定義する必要があるため、virtualになっています。また、ツールチップのテキストを設定するメソッドと返すメソッドを追加します。
//--- 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) 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); virtual void SetOpacity(const uchar value,const bool redraw=false); //--- (1) Set and (2) return the Tooltip text virtual void SetTooltipText(const string text) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT,text); } virtual string TooltipText(void) { return this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT); } //--- (1) Set and (2) return the flag for displaying a non-hidden control virtual void SetDisplayed(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_DISPLAYED,flag); } bool Displayed(void) const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_DISPLAYED); }
コンストラクタ本体には、各種グラフィカルプリミティブを描画するためのメソッドのリストが含まれています。リストの最後に、定義済みの「標準」画像を描画するための新しいメソッドを宣言します。
//--- Return coordinate offsets relative to the rectangle anchor point by size void GetShiftXYbySize(const int width, // Rectangle size by width const int height, //Rectangle size by height const ENUM_FRAME_ANCHOR anchor,// Rectangle anchor point, relative to which the offsets are calculated int &shift_x, // X coordinate of the rectangle upper left corner int &shift_y); // Y coordinate of the rectangle upper left corner //+-------------------------------------------------+ //| Methods for drawing predefined standard images | //+-------------------------------------------------+ //--- Draw the Info icon void DrawIconInfo(const int coord_x,const int coord_y,const uchar opacity); //--- Draw the Warning icon void DrawIconWarning(const int coord_x,const int coord_y,const uchar opacity); //--- Draw the Error icon void DrawIconError(const int coord_x,const int coord_y,const uchar opacity); //--- Draw the left arrow void DrawArrowLeft(const int coord_x,const int coord_y,const color clr,const uchar opacity); //--- Draw the right arrow void DrawArrowRight(const int coord_x,const int coord_y,const color clr,const uchar opacity); //--- Draw the up arrow void DrawArrowUp(const int coord_x,const int coord_y,const color clr,const uchar opacity); //--- Draw the down arrow void DrawArrowDown(const int coord_x,const int coord_y,const color clr,const uchar opacity); }; //+------------------------------------------------------------------+
両方のクラスのコンストラクタで、グラフィック要素の新しいプロパティのデフォルト値の設定を記述します。
//+-------------------------------------------------+ //| 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.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_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.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.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_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.SetVisibleFlag(false,false); } else { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj()); } } //+------------------------------------------------------------------+
クラス本体の外側に、定義済みの画像を描画するためのメソッドを記述します。
以下は、情報アイコンを描画するメソッドです。
//+-------------------------------------------------+ //| Draw the Info icon | //+-------------------------------------------------+ void CGCnvElement::DrawIconInfo(const int coord_x,const int coord_y,const uchar opacity) { int x=coord_x+8; int y=coord_y+8; this.DrawCircleFill(x,y,7,C'0x00,0x77,0xD7',opacity); this.DrawCircleWu(x,y,7.5,C'0x00,0x3D,0x8C',opacity); this.DrawRectangle(x,y-5,x+1,y-4, C'0xFF,0xFF,0xFF',opacity); this.DrawRectangle(x,y-2,x+1,y+4,C'0xFF,0xFF,0xFF',opacity); } //+------------------------------------------------------------------+
画像の輪郭を描く長方形の左上隅の座標がメソッドに渡されます。次に、円の中心点の座標を計算し、塗りつぶした円を描き、その上にWu法による平滑化を施した円を描きます。円を描いた後、iアイコンを描きます。このアイコンは2つの長方形からなり、1つ目は2x2の点を描き、2つ目は2x6の縦線を描くようにします。残念ながら、このような線を描くときに適用される奇妙なアンチエイリアスアルゴリズムのために、指定した幅(LineThick)で滑らかな線を描くことができません。そこで、単純に幅2ピクセル、高さ2ピクセルの長方形を描き、2ピクセルの線を描くようにしています。このメソッドでは、MS Visual Studioと同様に標準的な画像に見えるように、すべての色が事前定義されています。
以下は、警告アイコンを描画するメソッドです。
//+-------------------------------------------------+ //| Draw the Warning icon | //+-------------------------------------------------+ void CGCnvElement::DrawIconWarning(const int coord_x,const int coord_y,const uchar opacity) { int x=coord_x+8; int y=coord_y+1; this.DrawTriangleFill(x,y,x+8,y+14,x-8,y+14,C'0xFC,0xE1,0x00',opacity); this.DrawTriangleWu(x,y,x+8,y+14,x-7,y+14,C'0xFF,0xB9,0x00',opacity); this.DrawRectangle(x,y+5,x+1,y+9, C'0x00,0x00,0x00',opacity); this.DrawRectangle(x,y+11,x+1,y+12,C'0x00,0x00,0x00',opacity); } //+------------------------------------------------------------------+
画像の輪郭を描く長方形の左上隅の座標がメソッドに渡されます。次に、三角形の上点の座標を計算し、塗りつぶした三角形を描き、その上にWu法による平滑化を施した三角形を描きます。2つ目の三角形では、その頂点のX座標が、最初に塗りつぶされた三角形に比べて1ピクセル右にずれています。これをおこなうのは、三角形の中にあるアイコンは2ピクセル幅でなければならず、三角形の中央に正確に配置することができないため、視覚的に頂点を太くするためです。そこで、三角形の上部を2ピクセル分「広げる」ような形で、中のアイコンの位置を視覚的に中央に寄せます。三角形を描画した後、iアイコンを描画します。2つの長方形からなり、1つ目は2x6の縦線、2つ目は2x2の点を描くようにします。
以下は、エラーアイコンを描画するメソッドです。
//+-------------------------------------------------+ //| Draw the Error icon | //+-------------------------------------------------+ void CGCnvElement::DrawIconError(const int coord_x,const int coord_y,const uchar opacity) { int x=coord_x+8; int y=coord_y+8; this.DrawCircleFill(x,y,7,C'0xF0,0x39,0x16',opacity); this.DrawCircleWu(x,y,7.5,C'0xA5,0x25,0x12',opacity); this.DrawLineWu(x-3,y-3,x+3,y+3,C'0xFF,0xFF,0xFF',opacity); this.DrawLineWu(x+3,y-3,x-3,y+3,C'0xFF,0xFF,0xFF',opacity); } //+------------------------------------------------------------------+
このメソッドでは、色で塗りつぶされた円と、その輪郭を滑らかにした円の2つを描きます。中央には、Xアイコンを形成する2本の平滑化された線があります。他のアイコンと同様、MS Visual Studioにマッチした色が事前定義されています。
以下は、上下左右の矢印を描くメソッドです。
//+-------------------------------------------------+ //| Draw the left arrow | //+-------------------------------------------------+ void CGCnvElement::DrawArrowLeft(const int coord_x,const int coord_y,const color clr,const uchar opacity) { int x=coord_x; int y=coord_y+5; this.DrawTriangleFill(x,y,x+3,y-3,x+3,y+3,clr,opacity); this.DrawTriangleWu(x,y,x+3,y-3,x+3,y+3,clr,opacity); } //+-------------------------------------------------+ //| Draw the right arrow | //+-------------------------------------------------+ void CGCnvElement::DrawArrowRight(const int coord_x,const int coord_y,const color clr,const uchar opacity) { int x=coord_x; int y=coord_y+5; this.DrawTriangleFill(x+3,y,x,y+3,x,y-3,clr,opacity); this.DrawTriangleWu(x+3,y,x,y+3,x,y-3,clr,opacity); } //+-------------------------------------------------+ //| Draw the up arrow | //+-------------------------------------------------+ void CGCnvElement::DrawArrowUp(const int coord_x,const int coord_y,const color clr,const uchar opacity) { int x=coord_x+5; int y=coord_y; this.DrawTriangleFill(x,y,x+3,y+3,x-3,y+3,clr,opacity); this.DrawTriangleWu(x,y,x+3,y+3,x-3,y+3,clr,opacity); } //+-------------------------------------------------+ //| Draw the down arrow | //+-------------------------------------------------+ void CGCnvElement::DrawArrowDown(const int coord_x,const int coord_y,const color clr,const uchar opacity) { int x=coord_x+5; int y=coord_y+3; this.DrawTriangleFill(x,y,x+3,y-3,x-3,y-3,clr,opacity); this.DrawTriangleWu(x,y,x+3,y-3,x-3,y-3,clr,opacity); } //+------------------------------------------------------------------+
アウトライン化された長方形の左上隅の座標と、描かれた矢印の色と不透明度がすべてのメソッドに渡されます。次に、三角形の初期頂点の座標を計算し、塗りつぶした三角形を描き、その上にWu法で平滑化した三角形を描画します。描画された三角形の後続の各頂点は、その最初の頂点からのオフセットで座標が計算されます。色と不透明度を指定することで、描画された三角形の外観を、矢印が描かれているグラフィック要素の状態に応じて変化させることが可能です。例えば、非アクティブな要素の場合、矢印は灰色でなければなりません。一般に、アイコンに比べてこちらの方が選択肢が少し多くなります。
影オブジェクトは、常に他のオブジェクトと連動して存在します。影が描かれた背景の不透明度は常に0でなければなりません。つまり、オブジェクトは常に透明でなければなりません。同時に、この基板に描かれた影も、ある程度透明であることが望ましいです。影が完全に被写体を覆ってしまうと、奇妙な印象を与えてしまうからです。そこで、影オブジェクトに対して、描画された影の不透明度という概念を導入してみましょう。この値は、SetOpacity()メソッドが呼ばれたときに変更され、背景は常に透明なままである必要があります。同じメソッドはアンダーレイにも有効で、その不透明度の値を正確に設定します。そこで、新たにSetOpacityDraw(描画された影の不透明度)メソッドを追加し、この2つのメソッドを組み合わせてみましょう。これらが呼び出されると、背景の不透明度は常にゼロに設定され、描画される影の色には、メソッドで指定された値が指定されます。
\MQL5\Include\DoEasy\Objects\Graph\ShadowObj.mqhで、SetOpacity()メソッドとOpacity()メソッドを名前変更し、SetOpacity()仮想メソッドを宣言します。
//--- Draw an object shadow void Draw(const int shift_x,const int shift_y,const uchar blur_value,const bool redraw); //--- Set the element opacity virtual void SetOpacity(const uchar value,const bool redraw=false); //+------------------------------------------------------------------+ //| Methods of simplified access to object properties | //+------------------------------------------------------------------+ //--- (1) Set and (2) return the shadow color void SetColor(const color colour) { this.m_color=colour; } color Color(void) const { return this.m_color; } //--- (1) Set and (2) return the drawn shadow opacity void SetOpacityDraw(const uchar opacity) { this.m_opacity=opacity; } uchar OpacityDraw(void) const { return this.m_opacity; } //--- (1) Set and (2) return the shadow blur void SetBlur(const uchar blur) { this.m_blur=blur; } uchar Blur(void) const { return this.m_blur; } }; //+------------------------------------------------------------------+
クラスのコンストラクタで、描画された影の不透明度とそのぼかしのデフォルト値を設定します。
//+------------------------------------------------------------------+ //| Protected constructor with an object type, | //| chart ID and subwindow | //+------------------------------------------------------------------+ CShadowObj::CShadowObj(CGCnvElement *main_obj,CGCnvElement *base_obj, 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_SHADOW_OBJ,main_obj,base_obj,chart_id,subwindow,name,x,y,w,h) { this.m_type=OBJECT_DE_TYPE_GSHADOW; CGCnvElement::SetBackgroundColor(clrNONE,true); CGCnvElement::SetOpacity(0); CGCnvElement::SetActive(false); this.SetOpacityDraw(CLR_DEF_SHADOW_OPACITY); this.SetBlur(DEF_SHADOW_BLUR); color gray=CGCnvElement::ChangeColorSaturation(this.ChartBackgroundColor(),-100); this.m_color=CGCnvElement::ChangeColorLightness(gray,-50); this.m_shadow=false; this.SetVisibleFlag(false,false); CGCnvElement::Erase(); } //+------------------------------------------------------------------+
オブジェクトの影の形状を描画するメソッドで不透明度を設定するには、描画される影の不透明度に設定された値を使用します。
//+------------------------------------------------------------------+ //| Draw the object shadow form | //+------------------------------------------------------------------+ void CShadowObj::DrawShadowFigureRect(const int w,const int h) { CGCnvElement::DrawRectangleFill(OUTER_AREA_SIZE,OUTER_AREA_SIZE,OUTER_AREA_SIZE+w-1,OUTER_AREA_SIZE+h-1,this.m_color,this.OpacityDraw()); CGCnvElement::Update(); } //+------------------------------------------------------------------+
要素の不透明度を設定する新しい仮想メソッドを書いてみましょう。
//+------------------------------------------------------------------+ //| Set the element opacity | //+------------------------------------------------------------------+ void CShadowObj::SetOpacity(const uchar value,const bool redraw=false) { CGCnvElement::SetOpacity(0,false); this.SetOpacityDraw(value>(uchar)CLR_DEF_SHADOW_OPACITY ? (uchar)CLR_DEF_SHADOW_OPACITY : value); this.m_canvas.Update(redraw); } //+------------------------------------------------------------------+
このメソッドを呼び出すと、まず完全な影のアンダーレイの透明度が設定されます。次に、描画された影に対して、メソッドに渡された不透明度の値が設定されます。この場合、その値がライブラリに設定されているデフォルトの影の不透明度の値を超えていれば、その値が使用されます。これは、下にあるオブジェクトを完全に覆ってしまう不透明な影が現れるのを防ぐためにおこなわれます。
\MQL5\Include\DoEasy\Objects\Graph\WForms\WinFormBase.mqhで、オブジェクトを再描画するメソッドのロジックを変更します。従来は、オブジェクトの影が存在する場合は常に描画されていました。再描画フラグがリセットされると、影が単に消去されていたため、オブジェクトの影が消えてしまうことがありました。再描画フラグ確認の中で全部おこなうことにします。
//+-------------------------------------------------+ //| Redraw the object | //+-------------------------------------------------+ void CWinFormBase::Redraw(bool redraw) { //--- If the object type is less than the "Base WinForms object" or the object is not to be displayed, exit if(this.TypeGraphElement()<GRAPH_ELEMENT_TYPE_WF_BASE || !this.Displayed()) return; //--- Get the "Shadow" object CShadowObj *shadow=this.GetShadowObj(); //--- If the redraw flag is set, if(redraw) { //--- completely redraw the object and save its new initial look this.Erase(this.m_array_colors_bg,this.Opacity(),this.m_gradient_v,this.m_gradient_c,redraw); this.Done(); //--- If the object has a shadow and the "Shadow" object exists, redraw it if(this.IsShadow() && shadow!=NULL) { //--- remove the previously drawn shadow, shadow.Erase(); //--- save the relative shadow coordinates, int x=shadow.CoordXRelative(); int y=shadow.CoordYRelative(); //--- redraw the shadow, shadow.Draw(0,0,shadow.Blur(),redraw); //--- restore relative shadow coordinates shadow.SetCoordXRelative(x); shadow.SetCoordYRelative(y); } } //--- otherwise, remove the object else this.Erase(); //--- Redraw all bound objects with the redraw flag for(int i=0;i<this.ElementsTotal();i++) { CWinFormBase *element=this.GetElement(i); if(element==NULL) continue; if(redraw) element.Redraw(redraw); } //--- If the redraw flag is set and if this is the main object the rest are bound to, //--- redraw the chart to display changes immediately if(this.IsMain() && redraw) ::ChartRedraw(this.ChartID()); } //+------------------------------------------------------------------+
要素の整数プロパティの説明を返すメソッドに、新しいグラフィック要素のプロパティの説明を返すコードブロックを追加します。
//+------------------------------------------------------------------+ //| Return the description of the control integer property | //+------------------------------------------------------------------+ string CWinFormBase::GetPropertyDescription(ENUM_CANV_ELEMENT_PROP_INTEGER property,bool only_prop=false) { return ( property==CANV_ELEMENT_PROP_ID ? CMessage::Text(MSG_CANV_ELEMENT_PROP_ID)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : //---... //---... property==CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TOOLTIP_ICON ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_ICON)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CANV_ELEMENT_PROP_TOOLTIP_USE_FADING ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_USE_FADING)+ (only_prop ? "" : !this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : "" ); } //+------------------------------------------------------------------+
要素の文字列プロパティの説明を返すメソッドで、新しい文字列プロパティの説明も返すようにします。
//+------------------------------------------------------------------+ //| Return the description of the control string property | //+------------------------------------------------------------------+ string CWinFormBase::GetPropertyDescription(ENUM_CANV_ELEMENT_PROP_STRING property,bool only_prop=false) { return ( property==CANV_ELEMENT_PROP_NAME_OBJ ? CMessage::Text(MSG_CANV_ELEMENT_PROP_NAME_OBJ)+": \""+this.GetProperty(property)+"\"" : property==CANV_ELEMENT_PROP_NAME_RES ? CMessage::Text(MSG_CANV_ELEMENT_PROP_NAME_RES)+": \""+this.GetProperty(property)+"\"" : property==CANV_ELEMENT_PROP_TEXT ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TEXT)+": \""+this.GetProperty(property)+"\"" : property==CANV_ELEMENT_PROP_DESCRIPTION ? CMessage::Text(MSG_CANV_ELEMENT_PROP_DESCRIPTION)+": \""+this.GetProperty(property)+"\"" : property==CANV_ELEMENT_PROP_TOOLTIP_TITLE ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_TITLE)+": \""+this.GetProperty(property)+"\"" : property==CANV_ELEMENT_PROP_TOOLTIP_TEXT ? CMessage::Text(MSG_CANV_ELEMENT_PROP_TOOLTIP_TEXT)+": \""+this.GetProperty(property)+"\"" : "" ); } //+------------------------------------------------------------------+
標準的な矢印を描画するメソッドができたので、その呼び出しを矢印ボタンオブジェクトクラスの矢印を描画するDrawArrow()メソッドに追加してみましょう。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowButton.mqh:
//+-------------------------------------------------+ //| Draw the arrow | //+-------------------------------------------------+ void CArrowLeftButton::DrawArrow(void) { CGCnvElement::DrawArrowLeft(5,2,this.ArrowColor(),this.Opacity()); } //+------------------------------------------------------------------+
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowButton.mqh:
//+-------------------------------------------------+ //| Draw the arrow | //+-------------------------------------------------+ void CArrowRightButton::DrawArrow(void) { CGCnvElement::DrawArrowRight(6,2,this.ArrowColor(),this.Opacity()); } //+------------------------------------------------------------------+
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowButton.mqh:
//+-------------------------------------------------+ //| Draw the arrow | //+-------------------------------------------------+ void CArrowUpButton::DrawArrow(void) { CGCnvElement::DrawArrowUp(2,5,this.ArrowColor(),this.Opacity()); } //+------------------------------------------------------------------+
\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\ArrowButton.mqh:
//+-------------------------------------------------+ //| Draw the arrow | //+-------------------------------------------------+ void CArrowDownButton::DrawArrow(void) { CGCnvElement::DrawArrowDown(2,6,this.ArrowColor(),this.Opacity()); } //+------------------------------------------------------------------+
このように、各クラスでは、クラスオブジェクトの目的に対応して、基盤となるグラフィック要素のクラスから、目的の矢印を描くためのメソッドを呼び出すだけです。クラスが左矢印のボタンを作成した場合は左矢印の描画メソッドを、右矢印のボタンの場合は右矢印の描画メソッドを、というように呼び出されます。
ToolTipオブジェクトの開発を始めましょう。
ToolTip WinFormsオブジェクトクラス
\MQL5\Include\DoEasy\Objects\Graph\WForms\CommonControls\ライブラリフォルダで、CListBoxクラスの新しいListBox.mqhファイルを作成します。クラスは ヒントオブジェクト基本クラスから派生するので、そのファイルを作成されたクラスファイルにインクルードする必要があります。
//+------------------------------------------------------------------+ //| ToolTip.mqh | //| Copyright 2022, MetaQuotes Ltd. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "..\Helpers\HintBase.mqh" //+------------------------------------------------------------------+ //| Class of the base Hint object of the WForms controls | //+------------------------------------------------------------------+ class CToolTip : public CHintBase { }
クラスのprivateセクションで、ツールチップに設定されたテキストに従ってツールチップのサイズを調整するメソッドを宣言します。クラスのprotectedセクションに、異なるタイプのアイコンを描画するメソッドを実装し、protectedクラスのコンストラクタを宣言します。
class CToolTip : public CHintBase { private: //--- Adjust a tooltip size according to a text size void CorrectSizeByTexts(void); protected: //--- Draw (1) tooltip, (2) icon, (3) Info, (4) Warning, (5) Error and (6) User virtual void DrawHint(const int shift); void DrawIcon(void); void DrawIconInfo(void) { CGCnvElement::DrawIconInfo(3,1,this.Opacity()); } void DrawIconWarning(void) { CGCnvElement::DrawIconWarning(3,1,this.Opacity()); } void DrawIconError(void) { CGCnvElement::DrawIconError(3,1,this.Opacity()); } virtual void DrawIconUser(void) { return; } //--- Protected constructor with object type, chart ID and subwindow CToolTip(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:
情報、警告、エラーの各アイコンを描画するメソッドは、上で実装した基本グラフィック要素クラスの対応するメソッドを呼び出すだけです。カスタムアイコンを描画する仮想メソッドは何もしません。このオブジェクトの機能を独自に変更する必要がある場合に備えて、継承したクラスで再定義しておく必要があります。
クラスのpublicセクションに、このオブジェクトのために今日追加したプロパティを設定するメソッドと返すメソッドを実装します。パラメトリッククラスのコンストラクタと、表示、再描画、クリア、フレーム描画、オブジェクトの初期化などのメソッドを宣言してみましょう。
public: //--- (1) Set and (2) return the tooltip display delay void SetInitialDelay(const long delay) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY,delay); } long InitialDelay(void) { return this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY); } //--- (1) Set and (2) return the tooltip display duration void SetAutoPopDelay(const long delay) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY,delay); } long AutoPopDelay(void) { return this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY); } //--- (1) Set and (2) return the delay in a display of a new tooltip of one element void SetReshowDelay(const long delay) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY,delay); } long ReshowDelay(void) { return this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY); } //--- (1) Set and (2) return the flag for displaying a tooltip in an inactive window void SetShowAlways(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS,flag); } bool ShowAlways(void) { return (bool)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS); } //--- (1) Set and (2) return the type of the icon displayed in a tooltip void SetIcon(const ENUM_CANV_ELEMENT_TOOLTIP_ICON ico) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_ICON,ico); } ENUM_CANV_ELEMENT_TOOLTIP_ICON Icon(void) { return (ENUM_CANV_ELEMENT_TOOLTIP_ICON)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_ICON); } //--- (1) Set and (2) return the cloud tooltip flag void SetBalloon(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON,flag); } bool Balloon(void) { return (bool)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON); } //--- (1) Set and (2) return the flag of fading when showing/hiding a tooltip void SetUseFading(const bool flag) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_USE_FADING,flag); } bool UseFading(void) { return (bool)this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_USE_FADING); } //--- (1) Set and (2) return the Tooltip title void SetTitle(const string header); string Title(void) { return this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE); } //--- (1,2) Set the Tooltip text virtual void SetTooltipText(const string text); virtual void SetText(const string text) { this.SetTooltipText(text); } //--- Constructor CToolTip(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); //--- Display the element virtual void Show(void); //--- Redraw the object virtual void Redraw(bool redraw); //--- 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); //--- Draw the hint frame virtual void DrawFrame(void); //--- Initialize the variables virtual void Initialize(void); }; //+------------------------------------------------------------------+
宣言されたメソッドを詳しく見てみましょう。
以下は、オブジェクトタイプ、チャートID、サブウィンドウを指定するprotectedコンストラクタです。
//+------------------------------------------------------------------+ //| Protected constructor with an object type, | //| chart ID and subwindow | //+------------------------------------------------------------------+ CToolTip::CToolTip(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) : CHintBase(type,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { //--- Set the specified graphical element type for the object and assign the library object type to the current object this.SetTypeElement(type); this.m_type=OBJECT_DE_TYPE_GWF_COMMON; this.Initialize(); } //+------------------------------------------------------------------+
コンストラクタは、作成されたグラフィック要素のタイプと、初期化文字列で親クラスに設定された他のオブジェクトパラメータを受け取ります。クラス本体で、メソッドに渡されるグラフィック要素タイプと、ライブラリグラフィカルオブジェクトのタイプを設定します。すべてのデフォルトオブジェクトパラメータを設定するためのメソッドを呼び出します。
以下は、パラメトリックコンストラクタです。
//+------------------------------------------------------------------+ //| Constructor indicating the main and base objects, | //| chart ID and subwindow | //+------------------------------------------------------------------+ CToolTip::CToolTip(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) : CHintBase(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h) { this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_TOOLTIP); this.m_type=OBJECT_DE_TYPE_GWF_COMMON; this.Initialize(); } //+------------------------------------------------------------------+
ここでは、すべてがprotectedコンストラクタと似ていますが、グラフィック要素のタイプはToolTipとしてハードコードされています。
以下は、変数の初期化メソッドです。
//+-------------------------------------------------+ //| Initialize the variables | //+-------------------------------------------------+ void CToolTip::Initialize(void) { this.SetBackgroundColor(CLR_DEF_CONTROL_HINT_BACK_COLOR,true); this.SetBorderColor(CLR_DEF_CONTROL_HINT_BORDER_COLOR,true); this.SetForeColor(CLR_DEF_CONTROL_HINT_FORE_COLOR,true); this.SetDisplayed(false); this.SetBorderSizeAll(1); this.SetBorderStyle(FRAME_STYLE_SIMPLE); this.SetShadow(true); this.DrawShadow(2,2,CLR_DEF_SHADOW_COLOR,CLR_DEF_SHADOW_OPACITY,DEF_SHADOW_BLUR); this.SetOpacity(255,false); this.SetTitle(""); this.SetTooltipText(""); this.SetInitialDelay(500); this.SetAutoPopDelay(5000); this.SetReshowDelay(100); this.SetShowAlways(false); this.SetIcon(CANV_ELEMENT_TOOLTIP_ICON_NONE); this.SetBalloon(false); this.SetUseFading(true); this.SetTextAlign(ANCHOR_LEFT_UPPER); this.SetTextAnchor(FRAME_ANCHOR_LEFT_TOP); this.SetFont(DEF_FONT,DEF_FONT_SIZE,FW_NORMAL); this.SetDisplayed(false); this.Hide(); } //+------------------------------------------------------------------+
ToolTipオブジェクトが生成された直後に持つべきすべてのプロパティはここで指定されます。
以下は、オブジェクトを再描画するメソッドです。
//+-------------------------------------------------+ //| Redraw the object | //+-------------------------------------------------+ void CToolTip::Redraw(bool redraw) { //--- If the element should not be displayed (hidden inside another control), leave if(!this.Displayed() || this.Text()=="") return; //--- Get the "Shadow" object CShadowObj *shadow=this.GetShadowObj(); //--- If the redraw flag is set, if(redraw) { //--- completely redraw the object and save its new initial look this.Erase(this.m_array_colors_bg,this.Opacity(),this.m_gradient_v,this.m_gradient_c,true); this.Done(); //--- If the object has a shadow and the "Shadow" object exists, redraw it if(this.IsShadow() && shadow!=NULL) { //--- remove the previously drawn shadow, shadow.Erase(); //--- save the relative shadow coordinates, int x=shadow.CoordXRelative(); int y=shadow.CoordYRelative(); //--- redraw the shadow, shadow.Draw(0,0,shadow.Blur(),true); //--- restore relative shadow coordinates shadow.SetCoordXRelative(x); shadow.SetCoordYRelative(y); } } //--- otherwise, erase the object and its shadow else { CGCnvElement::Erase(); if(this.IsShadow() && shadow!=NULL) shadow.Erase(); } } //+------------------------------------------------------------------+
メソッドのロジックは、コードのコメントで説明されています。ここでは、バインドされたオブジェクトとチャートを再描画する以外は、ほとんどすべてが基盤となるWinFormsオブジェクトCWinFormBaseのクラスにある同名のメソッドとまったく同じです。
以下は、要素を背景色で塗り潰し、クリアにするメソッドです。
//+------------------------------------------------------------------+ //| Clear the element filling it with color and opacity | //+------------------------------------------------------------------+ void CToolTip::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); //--- If the object has a frame, draw it if(this.BorderStyle()!=FRAME_STYLE_NONE) this.DrawFrame(); //--- Draw a hint this.DrawHint(0); //--- Update the element having the specified redrawing flag this.Update(redraw); } //+-------------------------------------------------+ //| Clear the element with a gradient fill | //+-------------------------------------------------+ void CToolTip::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); //--- If the object has a frame, draw it if(this.BorderStyle()!=FRAME_STYLE_NONE) this.DrawFrame(); //--- Draw a hint this.DrawHint(0); //--- Update the element having the specified redrawing flag this.Update(redraw); } //+------------------------------------------------------------------+
このメソッドは、他のライブラリグラフィック要素の同名メソッドと同一であり、特に親オブジェクトのメソッドと同一です。ここでさらに変更する必要がなければ、クラスから削除されます。
以下は、要素の境界線を描画するメソッドです。
//+-------------------------------------------------+ //| Draw the element border | //+-------------------------------------------------+ void CToolTip::DrawFrame(void) { //--- If the element should not be displayed (hidden inside another control), leave if(!this.Displayed() || this.Text()=="") return; //--- Draw a rectangle along the object edges this.DrawRectangle(0,0,this.Width()-1,this.Height()-1,this.BorderColor(),this.Opacity()); } //+------------------------------------------------------------------+
メソッドのロジックは、コードにコメントされています。ここでの親クラスのメソッドとの違いは、要素の表示の必要性を確認する点のみです。
以下は、要素を表示するメソッドです。
//+-------------------------------------------------+ //| Show the element | //+-------------------------------------------------+ void CToolTip::Show(void) { //--- If the element should not be displayed (hidden inside another control), leave if(!this.Displayed() || this.TooltipText()=="") return; //--- Display the object CGCnvElement::Show(); //--- Get the "Shadow" object CShadowObj *shadow=this.GetShadowObj(); //--- If the object has a shadow and the "Shadow" object exists, display the shadow if(this.IsShadow() && shadow!=NULL) { shadow.Show(); this.BringToTop(); } //--- Redraw the object this.Redraw(true); } //+------------------------------------------------------------------+
このメソッドは、オブジェクトに影があるかどうかを確認し、影がある場合は、それも表示する必要があります。同時に、影が表示された後は、オブジェクトが影の下に入ることになるので、オブジェクト自体を前景に移動させる必要があります。
以下は、ToolTipテキストを設定するメソッドです。
//+-------------------------------------------------+ //| Set the Tooltip text | //+-------------------------------------------------+ void CToolTip::SetTooltipText(const string text) { CGCnvElement::SetTooltipText(text); CWinFormBase::SetText(text); this.CorrectSizeByTexts(); } //+------------------------------------------------------------------+
ここでは、まずツールチップのテキストをオブジェクトの新しいプロパティに設定し、次に同じテキストを「オブジェクトテキスト」プロパティにも設定しています。これらのプロパティは、ToolTipオブジェクトに対して同一であるとみなすことができるためです。次に、オブジェクトに設定されたタイトルとツールチップのテキストに従って、オブジェクトのサイズを調整するメソッドが呼び出されます。
以下は、ToolTipのタイトルテキストを設定するメソッドです。
//+-------------------------------------------------+ //| Set the title text for Tooltip | //+-------------------------------------------------+ void CToolTip::SetTitle(const string header) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TITLE,header); this.CorrectSizeByTexts(); } //+------------------------------------------------------------------+
ここでは、まず、メソッドに渡されたテキストをオブジェクトの新しいstringプロパティに設定し、オブジェクトのサイズ調整メソッドを呼び出しています。
以下は、テキストの大きさに応じてツールチップの大きさを調整するメソッドです。
//+-------------------------------------------------+ //| Adjust tooltip size to fit texts | //+-------------------------------------------------+ void CToolTip::CorrectSizeByTexts(void) { //--- If the tooltip text is not set for the object, leave if(this.TooltipText()=="" || this.TooltipText()==NULL) return; //--- Declare variables for the width and height of the object int w=this.Width(); int h=this.Height(); //--- Declare variables for the width and height of the title and tooltip texts int w1=0; int h1=0; int w2=w; int h2=h; //--- If the header text is set, get and adjust its size if(this.Title()!="" && this.Title()!=NULL) { this.TextSize(this.Title(),w1,h1); if(w1<6) w1=6; if(h1<19) h1=19; } //--- If the tooltip text is set, get and adjust its size this.TextSize(this.Text(),w2,h2); if(w2<6) w2=6; if(h2<19) h2=19; //--- Calculate the total size of the tooltip w=fmax(w1,w2); h=h1+h2; //--- Set the size of the object in accordance with the calculated ones this.Resize(w+12+(this.Icon()>CANV_ELEMENT_TOOLTIP_ICON_NONE && this.Icon()<=CANV_ELEMENT_TOOLTIP_ICON_USER ? 16 : 0),h,false); } //+------------------------------------------------------------------+
メソッドのロジックは、コードのコメントで説明されています。つまり、オブジェクトにツールチップテキストが設定されていない場合、そのオブジェクトにタイトルテキストが設定されているかどうかに関係なく、ツールチップは表示されません。ツールチップを表示しない場合、そのサイズを変更する必要はありません。したがって、そのような状況では、単にメソッドを終了するだけです。ツールチップテキストが設定されている場合、タイトルとツールチップテキストのサイズを取得する必要があります。出来上がったテキストの幅が6未満であれば、オブジェクトの幅は6に等しくなり、高さが19未満であれば、オブジェクトの高さは19になるはずです。次に、2つのテキストのうち最大の幅を定義し、それをオブジェクトの幅として使用します。オブジェクトの高さは、2つのテキストの高さの合計に等しくなります。リサイズ時には、左端から6ピクセル分のテキストインデントを考慮しています。従って、右側のインデントも6ピクセルになるようにします。そこで、算出した横幅に12ピクセル追加して、アイコンの有無の条件を確認します。アイコンを描画する場合は、オブジェクトの幅にアイコンの幅を16ピクセル追加します。その結果、オブジェクトのサイズが正しくなり、タイトル、説明、アイコン(ある場合)の両方のテキストが調和して表示されるようになります。
以下は、ヒントを描くメソッドです。
//+------------------------------------------------------------------+ //| Draw a hint | //+------------------------------------------------------------------+ void CToolTip::DrawHint(const int shift) { int y=3; int x=6+(this.Icon()>CANV_ELEMENT_TOOLTIP_ICON_NONE ? 16 : 0); this.DrawIcon(); if(this.Title()!="" && this.Title()!=NULL) { this.SetFont(DEF_FONT,DEF_FONT_SIZE,FW_BLACK); this.Text(x,y,this.Title(),this.ForeColor(),this.Opacity(),this.TextAnchor()); this.SetFont(DEF_FONT,DEF_FONT_SIZE,FW_NORMAL); y+=this.TextHeight(this.Title())+4; } this.Text(x,y,this.Text(),this.ForeColor(),this.Opacity(),this.TextAnchor()); } //+------------------------------------------------------------------+
テキストの縦方向のインデントを3ピクセルに、横方向のインデントを6ピクセルに設定します。アイコンを描画する場合は、その幅16ピクセルを水平方向のインデントに追加します。ツールチップにタイトルを付ける場合は、フォントをボールドに設定し、ヘッダーテキストを表示し、フォント幅を通常に戻し、タイトルテキストの高さに4ピクセル加えたものを縦座標に表示します。終了したら、ツールチップのテキストを表示します。タイトルがない場合は、ツールチップのテキストが初期Y座標に表示され、タイトルがある場合は、計算されたY座標に表示されます。
以下は、アイコンを描くメソッドです。
//+-------------------------------------------------+ //| Draw an icon | //+-------------------------------------------------+ void CToolTip::DrawIcon(void) { switch(this.Icon()) { case CANV_ELEMENT_TOOLTIP_ICON_INFO : this.DrawIconInfo(); break; case CANV_ELEMENT_TOOLTIP_ICON_WARNING : this.DrawIconWarning(); break; case CANV_ELEMENT_TOOLTIP_ICON_ERROR : this.DrawIconError(); break; case CANV_ELEMENT_TOOLTIP_ICON_USER : this.DrawIconUser(); break; //--- Icon None default: break; } } //+------------------------------------------------------------------+
オブジェクトに設定されたアイコンの種類に応じて、対応する画像を描画するためのメソッドを呼び出します。
この段階では、このクラスが機能するために必要なのはこれだけです。さらに、その作業の必要な結果を得るために、クラスを修正します。
残りのライブラリクラスも、新しいオブジェクトを扱えるように改良してみましょう。
\MQL5\Include\DoEasy\Objects\Graph\Form.mqhで、フォームオブジェクトクラスのpublicセクションに、非表示コントロールの表示フラグと要素の不透明度を設定するための仮想メソッドを宣言します。
//--- Update the coordinates (shift the canvas) virtual bool Move(const int x,const int y,const bool redraw=false); //--- Set the priority of a graphical object for receiving the event of clicking on a chart virtual bool SetZorder(const long value,const bool only_prop); //--- Set the object above all virtual void BringToTop(void); //--- Set the flag for displaying a non-hidden control virtual void SetDisplayed(const bool flag); //--- Set the element opacity virtual void SetOpacity(const uchar value,const bool redraw=false); //--- Event handler virtual void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam);
そこで、publicセクションで、接続されたToolTipオブジェクトを操作するためのメソッドと、そのテキストを設定するためのメソッドを宣言します。
//--- Add a new attached element bool AddNewElement(CGCnvElement *obj,const int x,const int y); //--- (1) Attach, return (2) the attached ToolTip object, (3) by description bool AddTooltip(CForm *tooltip); CForm *GetTooltip(void); CForm *GetTooltipByDescription(const string descript); //--- Set the text for Tooltip virtual void SetTooltipText(const string text); //--- Draw an object shadow void DrawShadow(const int shift_x,const int shift_y,const color colour,const uchar opacity=127,const uchar blur=DEF_SHADOW_BLUR);
グラフィカルオブジェクトを新規作成するメソッドを修正しましょう。
//+------------------------------------------------------------------+ //| Create a new graphical object | //+------------------------------------------------------------------+ CGCnvElement *CForm::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; //--- Depending on the created object type, switch(type) { //--- create a graphical element object case GRAPH_ELEMENT_TYPE_ELEMENT : element=new CGCnvElement(type,this.GetMain(),this.GetObject(),this.ID(),obj_num,this.ChartID(),this.SubWindow(),descript,x,y,w,h,colour,opacity,movable,activity); break; //--- create a form object case GRAPH_ELEMENT_TYPE_FORM : element=new CForm(type,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)); else { element.SetMovable(movable); element.SetCoordXRelative(element.CoordX()-this.CoordX()); element.SetCoordYRelative(element.CoordY()-this.CoordY()); } return element; } //+------------------------------------------------------------------+
オブジェクトが作成されない場合、ログエントリが表示されます。次に、未作成のオブジェクトのポインタへの呼び出しがあり、重大なエラーにつながる可能性がありました。このため、作成したオブジェクトのパラメータを設定するブロックは、else {}で囲むことになります。
各WinFormsオブジェクトは、以前に作成されたToolTipオブジェクトへのポインタを自らに接続することができるはずです。このようなツールチップが既に付けられていることをオブジェクトが「理解」するためには、ToolTipオブジェクトに設定された記述によって両者を区別する必要があります。コンテナオブジェクトの中に複数のToolTipオブジェクトを作成し、それぞれに固有の説明を設定することができるようになります。そして、ツールチップが作成されたオブジェクトに付属する他のオブジェクトのポインタを取得し、そのオブジェクトの記述によって希望するツールチップを割り当てることができるのです。そのために、各WinFormsオブジェクトは、CFormタイプとその子孫を持つオブジェクトを外部から接続できるようなメソッドを持つ必要があります。このようなメソッドは、すでにフォームオブジェクトクラスで宣言しています。それらの実装を考えてみましょう。
以下は、接続されたToolTipオブジェクトを生成するメソッドです。
//+-------------------------------------------------+ //| Create the attached ToolTip object | //+-------------------------------------------------+ bool CForm::AddTooltip(CForm *tooltip) { //--- If the pointer to an empty object is passed or the object type is not equal to Tooltip, report an error and return 'false' if(tooltip==NULL || tooltip.TypeGraphElement()!=GRAPH_ELEMENT_TYPE_WF_TOOLTIP) { CMessage::ToLog(DFUN,MSG_GRAPH_ELM_COLLECTION_ERR_EMPTY_OBJECT); return false; } //--- If the list of attached objects already contains the Tooltip object with the same description as the object passed to the method - //--- inform of that in the journal and return 'false' if(this.GetTooltipByDescription(tooltip.Description())!=NULL) { ::Print(DFUN,this.TypeElementDescription()+": ",CMessage::Text(MSG_FORM_TOOLTIP_OBJ_ALREADY_EXISTS),": ",tooltip.Name(),", Description: \"",tooltip.Description(),"\""); return false; } //--- If it was not possible to add the Tooltip object to the list of attached objects, report an error and return 'false' if(!this.m_list_elements.Add(tooltip)) { ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST),": ",tooltip.NameObj()); return false; } //--- If the coordinates of the object added to the list are changed, set the Tooltip relative coordinates if(tooltip.Move(this.CoordX()+1,this.CoordY()+1)) { tooltip.SetCoordXRelative(tooltip.CoordX()-this.CoordX()); tooltip.SetCoordYRelative(tooltip.CoordY()-this.CoordY()); } //--- Set this object as the base object for the Tooltip object and return 'true' tooltip.SetBase(this.GetObject()); return true; } //+------------------------------------------------------------------+
メソッドのロジックはコードのコメントで完全に説明されています。ToolTipオブジェクトへのポインタがメソッドに渡されます。このタイプのオブジェクトに、全く同じ記述のものが既に接続されている場合は、同じツールチップであると判断します。エラーを報告し、falseを返します。次に、このメソッドに渡されたToolTipオブジェクトへのポインタを、接続されたオブジェクトのリストに接続します。この場合、オブジェクト自体はCToolTip型について何も知らないかもしれませんが、この型はCFormクラスを継承しているため、CForm型を持つメソッドに渡されるはずです。次に、ポップアップオブジェクトを処理するコレクションクラスにおいて、リストからこのオブジェクトを取得し、CToolTipオブジェクトと同様に操作することができます。メソッドの最後には、カレントオブジェクトへのポインタがToolTipオブジェクトに書き込まれ、ToolTipオブジェクトの基盤となるようにします。ToolTipオブジェクトは、他のオブジェクトの中に作成され、第3のオブジェクトに接続されれるので、基本オブジェクトに関するエントリは、それがどのオブジェクトにツールチップとして割り当てられるかを決定するのに役立ちます。基本オブジェクトは、ツールチップが割り当てられているオブジェクトです。
以下は、接続されたToolTipオブジェクトを返すメソッドです。
//+-------------------------------------------------+ //| Return the attached ToolTip object | //+-------------------------------------------------+ CForm *CForm::GetTooltip(void) { CForm *obj=NULL; for(int i=this.ElementsTotal()-1;i>WRONG_VALUE;i--) { obj=this.GetElement(i); if(obj!=NULL && obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_TOOLTIP) break; } return obj; } //+------------------------------------------------------------------+
ここでは、接続されたオブジェクトに対するループの中で、ループのインデックスによって次のオブジェクトを取得しています。このオブジェクトが空でなく、CToolTip型を持つ場合、ループからbreakします。ループ終了時に、obj変数に格納されているポインタを返します。
1つのオブジェクトに、異なる説明を持つ複数のツールチップを割り当てることができます。必要なToolTipオブジェクトへのポインタを取得するために、接続されたToolTipオブジェクトを記述して返すメソッドです。
//+------------------------------------------------------------------+ //| Return the attached ToolTip object by description | //+------------------------------------------------------------------+ CForm *CForm::GetTooltipByDescription(const string descript) { CForm *obj=NULL; for(int i=this.ElementsTotal()-1;i>WRONG_VALUE;i--) { obj=this.GetElement(i); if(obj!=NULL && obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_TOOLTIP && obj.Description()==descript) break; } return obj; } //+------------------------------------------------------------------+
このメソッドは、ToolTipオブジェクトを見つけるために必要な、説明テキストを受け取ります。接続されたオブジェクトのリストを通過するループの中で、次のオブジェクトを取得します。それが空でなく、その型がCToolTipで、希望する説明と同じであれば、ループからbreakします。ループの最後に、見つかった(または空の)オブジェクトへのポインタを返します。
以下は、ToolTipテキストを設定するメソッドです。
//+-------------------------------------------------+ //| Set the Tooltip text | //+-------------------------------------------------+ void CForm::SetTooltipText(const string text) { CGCnvElement::SetTooltipText(text); CForm *tooltip=this.GetTooltip(); if(tooltip!=NULL) tooltip.SetTooltipText(text); } //+------------------------------------------------------------------+
まず、このオブジェクトにツールチップのテキストを設定します。そして、接続されたToolTipオブジェクトへのポインタを取得し、メソッドに渡されたツールチップのテキストを設定します。オブジェクトが1つのツールチップしか持っていない場合、このメソッドは、このオブジェクトとそれに割り当てられたツールチップの両方に同じテキストを設定することになります。
以下は、非表示コントロールの表示フラグを設定する仮想メソッドです。
//+------------------------------------------------------------------+ //| Set the flag for displaying a non-hidden control | //+------------------------------------------------------------------+ void CForm::SetDisplayed(const bool flag) { //--- Set the display flag for the object CGCnvElement::SetDisplayed(flag); //--- If the shadow use flag is set and the shadow object has been created, //--- set the display flag for the shadow object if(this.m_shadow && this.m_shadow_obj!=NULL) this.m_shadow_obj.SetDisplayed(flag); } //+------------------------------------------------------------------+
オブジェクトが他のオブジェクトに影を落とすことがある場合、オブジェクト自身だけでなく、影を落とすオブジェクトにも表示フラグを設定する必要があります。そうでなければ、影はオブジェクトに関係なく「自分の人生を生きる」ことになります。そこで、ここではまず、オブジェクト自体に表示フラグを設定します。その後、影がある場合はその影にフラグが設定されます。
以下は、要素の不透明度を設定する仮想メソッドです。
//+------------------------------------------------------------------+ //| Set the element opacity | //+------------------------------------------------------------------+ void CForm::SetOpacity(const uchar value,const bool redraw=false) { //--- Set the object opacity value CGCnvElement::SetOpacity(value,redraw); //--- If the shadow use flag is set and the shadow object has been created, //--- set the opacity value for the shadow object if(this.m_shadow && this.m_shadow_obj!=NULL) this.m_shadow_obj.SetOpacity(value,redraw); } //+------------------------------------------------------------------+
ここではすべてが同じです。まず、オブジェクト自体に不透明度の値を設定します。影オブジェクトが存在する場合、それにも不透明度が設定されます。
新しいコントロールを操作するために、そのファイルをフォームオブジェクトのクラスファイルに接続する必要があります。
\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Panel.mqhで、CToolTipクラスファイルのインクルードを設定します。
//+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "Container.mqh" #include "..\Helpers\TabField.mqh" #include "..\Helpers\ArrowUpButton.mqh" #include "..\Helpers\ArrowDownButton.mqh" #include "..\Helpers\ArrowLeftButton.mqh" #include "..\Helpers\ArrowRightButton.mqh" #include "..\Helpers\ArrowUpDownBox.mqh" #include "..\Helpers\ArrowLeftRightBox.mqh" #include "..\Helpers\HintMoveLeft.mqh" #include "..\Helpers\HintMoveRight.mqh" #include "..\Helpers\HintMoveUp.mqh" #include "..\Helpers\HintMoveDown.mqh" #include "GroupBox.mqh" #include "TabControl.mqh" #include "SplitContainer.mqh" #include "..\..\WForms\Common Controls\ListBox.mqh" #include "..\..\WForms\Common Controls\CheckedListBox.mqh" #include "..\..\WForms\Common Controls\ButtonListBox.mqh" #include "..\..\WForms\Common Controls\ToolTip.mqh" //+------------------------------------------------------------------+ //| Panel object class of WForms controls | //+------------------------------------------------------------------+
新しいグラフィカルオブジェクトを作成するメソッドに、新しいToolTipオブジェクトを作成するための文字列を追加します。
//+------------------------------------------------------------------+ //| Create a new graphical object | //+------------------------------------------------------------------+ CGCnvElement *CPanel::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_ELEMENT : element=new CGCnvElement(type,this.GetMain(),this.GetObject(),this.ID(),obj_num,this.ChartID(),this.SubWindow(),descript,x,y,w,h,colour,opacity,movable,activity); break; case GRAPH_ELEMENT_TYPE_FORM : element=new CForm(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_CONTAINER : element=new CContainer(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_GROUPBOX : element=new CGroupBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_PANEL : element=new CPanel(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; case GRAPH_ELEMENT_TYPE_WF_CHECKBOX : element=new CCheckBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON : element=new CRadioButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_BUTTON : element=new CButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_LIST_BOX : element=new CListBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM : element=new CListBoxItem(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX : element=new CCheckedListBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX : element=new CButtonListBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TAB_HEADER : element=new CTabHeader(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TAB_FIELD : element=new CTabField(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL : element=new CTabControl(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON : element=new CArrowButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP : element=new CArrowUpButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN : element=new CArrowDownButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT : element=new CArrowLeftButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT : element=new CArrowRightButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX : element=new CArrowUpDownBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX : element=new CArrowLeftRightBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER : element=new CSplitContainer(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_SPLITTER : element=new CSplitter(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_BASE : element=new CHintBase(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT : element=new CHintMoveLeft(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT : element=new CHintMoveRight(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP : element=new CHintMoveUp(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN : element=new CHintMoveDown(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TOOLTIP : element=new CToolTip(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; } //+------------------------------------------------------------------+
\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\Container.mqhにある、接続されたオブジェクトのパラメータを作成するメソッドに、新しく作成したツールチップ オブジェクトのパラメータ設定用コードブロックを追加します。
//+-------------------------------------------------+ //| Set parameters for the attached object | //+-------------------------------------------------+ void CContainer::SetObjParams(CWinFormBase *obj,const color colour) { //--- Set the text color of the object to be the same as that of the base container obj.SetForeColor(this.ForeColor(),true); //--- If the created object is not a container, set the same group for it as the one for its base object if(obj.TypeGraphElement()<GRAPH_ELEMENT_TYPE_WF_CONTAINER || obj.TypeGraphElement()>GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER) obj.SetGroup(this.Group()); //--- Depending on the object type switch(obj.TypeGraphElement()) { //--- For the Container, Panel and GroupBox WinForms objects //---... //---... //--- For ToolTip WinForms object case GRAPH_ELEMENT_TYPE_WF_TOOLTIP : obj.SetBackgroundColor(CLR_DEF_CONTROL_HINT_BACK_COLOR,true); obj.SetBorderColor(CLR_DEF_CONTROL_HINT_BORDER_COLOR,true); obj.SetForeColor(CLR_DEF_CONTROL_HINT_FORE_COLOR,true); obj.SetBorderStyle(FRAME_STYLE_SIMPLE); obj.SetOpacity(0,false); obj.SetDisplayed(false); obj.Hide(); break; default: break; } obj.Crop(); } //+------------------------------------------------------------------+
GroupBoxオブジェクトのG\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\GroupBox.mqhファイルのNewGraphオブジェクト作成メソッドに、ToolTipオブジェクト作成用の文字列も追加します。
//+-------------------------------------------------+ //| Create a new graphical object | //+-------------------------------------------------+ CGCnvElement *CGroupBox::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_ELEMENT : element=new CGCnvElement(type,this.GetMain(),this.GetObject(),this.ID(),obj_num,this.ChartID(),this.SubWindow(),descript,x,y,w,h,colour,opacity,movable,activity); break; case GRAPH_ELEMENT_TYPE_FORM : element=new CForm(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; //---... //---... case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP : element=new CHintMoveUp(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN : element=new CHintMoveDown(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TOOLTIP : element=new CToolTip(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; } //+------------------------------------------------------------------+
TabControlオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\TabControl.mqhファイルで、タイトルバーのスクロールに使用する矢印付きボタンオブジェクトを受け取るためのメソッドを追加します。これらの補助オブジェクトへのポインタを取得しなければ、ツールチップを割り当てることができません。
クラスのprivateセクションで、ボタンオブジェクトへのポインタを受け取るためのメソッドを宣言します。
//--- Return the list of (1) headers, (2) tab fields, the pointer to the (3) up-down and (4) left-right button objects CArrayObj *GetListHeaders(void) { return this.GetListElementsByType(GRAPH_ELEMENT_TYPE_WF_TAB_HEADER); } CArrayObj *GetListFields(void) { return this.GetListElementsByType(GRAPH_ELEMENT_TYPE_WF_TAB_FIELD); } CArrowUpDownBox *GetArrUpDownBox(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX,0); } CArrowLeftRightBox *GetArrLeftRightBox(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX,0); } //--- Return the pointer to the (1) up, (2) down, (3) left and (4) right arrow button CArrowUpButton *GetArrowUpButton(void); CArrowDownButton *GetArrowDownButton(void); CArrowLeftButton *GetArrowLeftButton(void); CArrowRightButton*GetArrowRightButton(void); //--- Return the pointer to the (1) last and (2) first visible tab header CTabHeader *GetLastHeader(void) { return this.GetTabHeader(this.TabPages()-1); } CTabHeader *GetFirstVisibleHeader(void); //--- Set the tab as selected
publicセクションで、矢印のついたボタンオブジェクトにツールチップを設定するメソッドを宣言します。
//--- Set the tab specified by index to selected/not selected void Select(const int index,const bool flag); //--- Returns the (1) index, (2) the pointer to the selected tab int SelectedTabPageNum(void) const { return (int)this.GetProperty(CANV_ELEMENT_PROP_TAB_PAGE_NUMBER);} CWinFormBase *SelectedTabPage(void) { return this.GetTabField(this.SelectedTabPageNum()); } //--- Add Tooltip to the (1) up, (2) down, (3) left and (4) right arrow button bool AddTooltipToArrowUpButton(CForm *tooltip); bool AddTooltipToArrowDownButton(CForm *tooltip); bool AddTooltipToArrowLeftButton(CForm *tooltip); bool AddTooltipToArrowRightButton(CForm *tooltip); //--- Set the object above all virtual void BringToTop(void); //--- Show the control virtual void Show(void); //--- Event handler
新しいグラフィカルオブジェクトを作成するメソッドで、新しいコントロールを作成するための文字列を追加します。
//+-------------------------------------------------+ //| Create a new graphical object | //+-------------------------------------------------+ CGCnvElement *CTabControl::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_TAB_HEADER : element=new CTabHeader(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TAB_FIELD : element=new CTabField(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX : element=new CArrowUpDownBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX : element=new CArrowLeftRightBox(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TOOLTIP : element=new CToolTip(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; } //+------------------------------------------------------------------+
以下は、矢印ボタンへのポインタを返すメソッドです。
//+-------------------------------------------------+ //| Return the pointer to the up arrow button | //+-------------------------------------------------+ CArrowUpButton *CTabControl::GetArrowUpButton(void) { CArrowUpDownBox *box=this.GetArrUpDownBox(); return(box!=NULL ? box.GetArrowUpButton() : NULL); } //+-------------------------------------------------+ //| Return the pointer to the down arrow button | //+-------------------------------------------------+ CArrowDownButton *CTabControl::GetArrowDownButton(void) { CArrowUpDownBox *box=this.GetArrUpDownBox(); return(box!=NULL ? box.GetArrowDownButton() : NULL); } //+-------------------------------------------------+ //| Return the pointer to the left arrow button | //+-------------------------------------------------+ CArrowLeftButton *CTabControl::GetArrowLeftButton(void) { CArrowLeftRightBox *box=this.GetArrLeftRightBox(); return(box!=NULL ? box.GetArrowLeftButton() : NULL); } //+-------------------------------------------------+ //| Return the pointer to the right arrow button | //+-------------------------------------------------+ CArrowRightButton *CTabControl::GetArrowRightButton(void) { CArrowLeftRightBox *box=this.GetArrLeftRightBox(); return(box!=NULL ? box.GetArrowRightButton() : NULL); } //+------------------------------------------------------------------+
すべてのメソッドは互いに同じで、まず、左右または上下のボタンのペアを含む対応するオブジェクトへのポインタを取得します。これらのオブジェクトから、上下左右の目的のボタンへのポインタを受け取り、返します。
以下は、上下左右の矢印ボタンにToolTipオブジェクトを追加するメソッドです。
//+-------------------------------------------------+ //| Add ToolTip to the up arrow button | //+-------------------------------------------------+ bool CTabControl::AddTooltipToArrowUpButton(CForm *tooltip) { CArrowUpButton *butt=this.GetArrowUpButton(); return(butt!=NULL ? butt.AddTooltip(tooltip) : false); } //+-------------------------------------------------+ //| Add ToolTip to the down arrow button | //+-------------------------------------------------+ bool CTabControl::AddTooltipToArrowDownButton(CForm *tooltip) { CArrowDownButton *butt=this.GetArrowDownButton(); return(butt!=NULL ? butt.AddTooltip(tooltip) : false); } //+-------------------------------------------------+ //| Add ToolTip to the left arrow button | //+-------------------------------------------------+ bool CTabControl::AddTooltipToArrowLeftButton(CForm *tooltip) { CArrowLeftButton *butt=this.GetArrowLeftButton(); return(butt!=NULL ? butt.AddTooltip(tooltip) : false); } //+-------------------------------------------------+ //| Add ToolTip to the right arrow button | //+-------------------------------------------------+ bool CTabControl::AddTooltipToArrowRightButton(CForm *tooltip) { CArrowRightButton *butt=this.GetArrowRightButton(); return(butt!=NULL ? butt.AddTooltip(tooltip) : false); } //+------------------------------------------------------------------+
すべてのメソッドは同一です。まず、上記のメソッドで対応するボタンのポインタを取得し、メソッドに渡されたToolTipオブジェクトのポインタを、受け取ったオブジェクトに設定します。ボタンオブジェクトへのポインタを受け取り、そのポインタをToolTipオブジェクトに追加することに成功した場合、このメソッドはtrueを返し、そうでない場合はfalseを返します。
TabFieldオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\TabField.mqhファイルで、グラフィカルオブジェクトを新規作成するメソッドにToolTipオブジェクトを新規作成するための文字列を追加します。
//+-------------------------------------------------+ //| Create a new graphical object | //+-------------------------------------------------+ CGCnvElement *CTabField::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_ELEMENT : element=new CGCnvElement(type,this.GetMain(),this.GetObject(),this.ID(),obj_num,this.ChartID(),this.SubWindow(),descript,x,y,w,h,colour,opacity,movable,activity); break; case GRAPH_ELEMENT_TYPE_FORM : element=new CForm(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; //---... //---... case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP : element=new CHintMoveUp(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN : element=new CHintMoveDown(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TOOLTIP : element=new CToolTip(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; } //+------------------------------------------------------------------+
SplitContainerオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\WForms\Containers\SplitContainer.mqhファイルに、区切りオブジェクトにツールチップを設定するためのメソッドを宣言します。
//--- Return the pointer to the separator CSplitter *GetSplitter(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SPLITTER,0); } //--- Return a pointer to the (1) "Left shift", (1) "Right shift", (1) "Up shift" and (1) "Down shift" hint objects CHintMoveLeft *GetHintMoveLeft(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT,0); } CHintMoveRight *GetHintMoveRight(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT,0); } CHintMoveUp *GetHintMoveUp(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP,0); } CHintMoveDown *GetHintMoveDown(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN,0); } //--- Add Tooltip to the separator bool AddTooltipToSplitter(CForm *tooltip); //--- (1) set and (2) return the minimum possible size of the panel 1 and 2
新しいグラフィカルオブジェクトを作成するメソッドに、新しいToolTipオブジェクトを作成するための文字列を追加します。
//+------------------------------------------------------------------+ //| Create a new graphical object | //+------------------------------------------------------------------+ CGCnvElement *CSplitContainer::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_SPLIT_CONTAINER_PANEL: element=new CSplitContainerPanel(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);break; case GRAPH_ELEMENT_TYPE_WF_SPLITTER : element=new CSplitter(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_BASE : element=new CHintBase(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT : element=new CHintMoveLeft(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT : element=new CHintMoveRight(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP : element=new CHintMoveUp(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN : element=new CHintMoveDown(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TOOLTIP : element=new CToolTip(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; } //+------------------------------------------------------------------+
以下は、区切りにToolTipを追加するメソッドです。
//+-------------------------------------------------+ //| Add ToolTip to the separator | //+-------------------------------------------------+ bool CSplitContainer::AddTooltipToSplitter(CForm *tooltip) { CSplitter *obj=this.GetSplitter(); return(obj!=NULL ? obj.AddTooltip(tooltip) : false); } //+------------------------------------------------------------------+
ここでは、区切りオブジェクトへのポインタを取得し、ToolTipオブジェクトへのポインタを区切りオブジェクトに追加した結果を返しています。
SplitContainerPanelクラスオブジェクトの\MQL5\Include\DoEasy\Objects\Graph\WForms\Helpers\SplitContainerPanel.mqhファイルにある、グラフィカルオブジェクトを新規作成するメソッドに、新しいToolTipオブジェクトを作成するための文字列を追加します。
//+-------------------------------------------------+ //| Create a new graphical object | //+-------------------------------------------------+ CGCnvElement *CSplitContainerPanel::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_ELEMENT : element=new CGCnvElement(type,this.GetMain(),this.GetObject(),this.ID(),obj_num,this.ChartID(),this.SubWindow(),descript,x,y,w,h,colour,opacity,movable,activity); break; case GRAPH_ELEMENT_TYPE_FORM : element=new CForm(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; //---... //---... case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP : element=new CHintMoveUp(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN : element=new CHintMoveDown(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h); break; case GRAPH_ELEMENT_TYPE_WF_TOOLTIP : element=new CToolTip(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; } //+------------------------------------------------------------------+
これで、各コンテナオブジェクトで、新しいToolTipオブジェクトを作成し、既存のグラフィック要素のいずれかに割り当てることができます。
ToolTipオブジェクトを扱うには、グラフィック要素コレクションクラスの\MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqhを変更する必要があります。
クラスのprivateセクションで、ToolTipオブジェクトを処理するメソッドを宣言します。
//--- Post-processing of the former active form under the cursor void FormPostProcessing(CForm *form,const int id, const long &lparam, const double &dparam, const string &sparam); //--- Handle Tooltip elements void TooltipProcessing(CForm *form,CForm *tooltip,CForm *tooltip_prev); //--- Add the element to the collection list bool AddCanvElmToCollection(CGCnvElement *element);
インタラクションオブジェクトを検索するメソッドで、ToolTipオブジェクトをスキップするようにします。
//+-------------------------------------------------+ //| Search for interaction objects | //+-------------------------------------------------+ CForm *CGraphElementsCollection::SearchInteractObj(CForm *form,const int id,const long &lparam,const double &dparam,const string &sparam) { //--- If a non-empty pointer is passed if(form!=NULL) { //--- Create the list of interaction objects int total=form.CreateListInteractObj(); //--- In the loop by the created list for(int i=total-1;i>WRONG_VALUE;i--) { //--- get the next form object CForm *obj=form.GetInteractForm(i); //--- If the object is received, but is not visible, or not active, or should not be displayed, skip it if(obj==NULL || !obj.IsVisible() || !obj.Enabled() || !obj.Displayed()) continue; //--- If this is Tooltip, skip such an object for now if(obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_TOOLTIP) { continue; } //--- If the form object is TabControl, return the selected tab under the cursor if(obj.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL) { //---... //---...
カーソルの下にあるグラフィック要素を探しているときに、ToolTipオブジェクトに出会ったら、それを処理しないためにここでスキップする必要があります。マウスで操作できるアクティブなToolTipオブジェクトが作られた場合、スキップの代わりに、マウスで操作できるようなオブジェクトがあるかどうかの確認がおこなわれるようになりました。とりあえず、ここではそのようなオブジェクトはスキップします。
以下は、ToolTip要素を処理するメソッドです。
//+-------------------------------------------------+ //| Handle ToolTip elements | //+-------------------------------------------------+ void CGraphElementsCollection::TooltipProcessing(CForm *form,CForm *tooltip,CForm *tooltip_prev) { //--- Get the chart width and height int w=(int)::ChartGetInteger(tooltip.ChartID(),CHART_WIDTH_IN_PIXELS,tooltip.SubWindow()); int h=(int)::ChartGetInteger(tooltip.ChartID(),CHART_HEIGHT_IN_PIXELS,tooltip.SubWindow()); //--- Get cursor coordinates int x=this.m_mouse.CoordX(); int y=this.m_mouse.CoordY(); //--- If at the current X coordinate (cursor) the tooltip goes beyond the right edge of the chart, adjust the X coordinate if(x+tooltip.Width()>w) x=w-tooltip.Width(); //--- If at the current Y coordinate (cursor) the tooltip goes beyond the bottom edge of the chart, adjust the Y coordinate if(y+tooltip.Height()>h) y=h-tooltip.Height(); //--- If the tooltip object is hidden if(!tooltip.IsVisible()) { //--- If the tooltip object is shifted to the received cursor coordinates if(tooltip.Move(x,y)) { //--- Get the object the tooltip object is assigned to CForm *base=tooltip.GetBase(); //--- If the object is received, set new relative tooltip coordinates if(base!=NULL) { tooltip.SetCoordXRelative(tooltip.CoordX()-base.CoordX()); tooltip.SetCoordYRelative(tooltip.CoordY()-base.CoordY()); } } } //--- Set the tooltip drawing flag, as well as full opacity, and display the object tooltip.SetDisplayed(true); tooltip.SetOpacity(255); tooltip.Show(); //--- If the previous tooltip object exists and its name is not equal to the name of the current object (it is the same object) if(tooltip_prev!=NULL && tooltip_prev.Name()!=tooltip.Name()) { //--- Set the flag disabling the display, make the object completely transparent and hide it tooltip_prev.SetDisplayed(false); tooltip.SetOpacity(0); tooltip_prev.Hide(); } } //+------------------------------------------------------------------+
メソッドのロジックはコードのコメントで完全に説明されています。カーソルの下にあるオブジェクトを取得したら、そのオブジェクトにToolTipオブジェクトが設定されているかどうかを確認します。設定されていれば、ToolTipオブジェクトを処理するために、このメソッドを呼び出します。ツールチップを発見したときのメソッドには、オブジェクトそのもの、オブジェクトツールチップへのポインタ、および、以前に扱ったToolTipオブジェクトへのポインタを渡しています。
このクラスのOnChartEvent()イベントハンドラにある、オブジェクト移動フラグがオフの状態(カーソルはオブジェクトの上にあるが、ボタンはまだ1つも押されていない)を扱うセグメントに、以下のコードブロックを挿入します。
//---... //---... //--- If the move flag is disabled else { //--- Get the ToolTip object assigned to the form and declare the previous ToolTip CForm *tooltip=form.GetTooltip(); static CForm *tooltip_prev=NULL; //--- If the ToolTip object is received if(tooltip!=NULL) { //--- and if its type is indeed ToolTip (to avoid incorrect casting, which we sometimes get if we do not check the type) if(tooltip.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_TOOLTIP) { //--- Get the base object set in ToolTip CForm *base=tooltip.GetBase(); //--- If the base object is received if(base!=NULL) { //--- and if the name of the base object is the same as the name of the current form (the ToolTip is bound to the form) if(base.Name()==form.Name()) { //--- Handle the received and previous ToolTip and write the current ToolTip to the variable as the previous one this.TooltipProcessing(form,tooltip,tooltip_prev); tooltip_prev=tooltip; } } } } //--- If there is no ToolTip attached to the object else { //--- If the previous ToolTip exists if(tooltip_prev!=NULL) { //--- and if its type is indeed ToolTip (to avoid incorrect casting, which we sometimes get if we do not check the type) if(tooltip_prev.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WF_TOOLTIP) { //--- Set the object non-display flag, make it completely transparent and hide it tooltip_prev.SetDisplayed(false); tooltip_prev.SetOpacity(0,false); tooltip_prev.Hide(); } } } //--- The undefined mouse status in mouse_state means releasing the left button //--- Assign the new mouse status to the variable if(mouse_state==MOUSE_FORM_STATE_NONE) mouse_state=MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED; //--- Handle moving the cursor mouse away from the graphical element this.FormPostProcessing(form,id,lparam,dparam,sparam); } } } //--- If the cursor is not above the form if(form==NULL) { //---... //---...
このコードのブロックのロジックは、コメントで説明されています。興味深いことに、ターミナルを更新した後、非NULLとあるオブジェクトのプロパティを同時に確認するという論理条件が、必ずしも正しく処理されないことがあります。そこで、ここでは1つの文字列で書ける条件を括弧{ }の中でブロック分けしています。間違っているかもしれませんが、いずれにせよ、このコードのブロックは、ToolTipオブジェクトクラスをさらに開発する際に作り直されることになります。この場合、このコードでは、ツールチップが設定されているオブジェクトを見つけ、そのツールチップを表示し、前のツールチップを隠すことだけが可能です。つまり、ツールチップの表示に遅れが生じたり、スムーズに表示されたりすることはありません。この後の記事ですべて実装していきます。
今のところ、必要なのはこれですべてです。結果をテストしてみましょう。
検証
テストを実行するには、前の記事のEAを\MQL5\Experts\TestDoEasy\Part125\でTestDoEasy125.mq5として保存します。
EA設定に、ツールチップで使用されるアイコンタイプを指定するための変数と、ツールチップのタイトルテキストを設定するための変数を追加しました。
//--- 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 //--- global variables
TabControlを作成したら、2つのToolTipオブジェクトを実装し、タイトルバーを左と右にスクロールさせるための2つのボタンに割り当てます。
//---... //---... //--- Create TabControl pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,InpTabControlX,InpTabControlY,pnl.Width()-30,pnl.Height()-40,clrNONE,255,true,false); CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0); if(tc!=NULL) { tc.SetTabSizeMode((ENUM_CANV_ELEMENT_TAB_SIZE_MODE)InpTabPageSizeMode); tc.SetAlignment((ENUM_CANV_ELEMENT_ALIGNMENT)InpHeaderAlignment); tc.SetMultiline(InpTabCtrlMultiline); tc.SetHeaderPadding(6,0); tc.CreateTabPages(15,0,56,20,TextByLanguage("Вкладка","TabPage")); //--- Create Tooltip for the Left button tc.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0,0,10,10,clrNONE,0,false,false); CToolTip *tooltip=tc.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0); if(tooltip!=NULL) { tooltip.SetDescription("Left Button Tooltip"); tooltip.SetIcon(InpTooltipIcon); tooltip.SetTitle(InpTooltipTitle); tooltip.SetTooltipText(TextByLanguage("Нажмите для прокрутки заголовков вправо","Click to scroll headings to the right")); tc.AddTooltipToArrowLeftButton(tooltip); } //--- Create Tooltip for the Right button tc.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0,0,10,10,clrNONE,0,false,false); tooltip=tc.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,1); if(tooltip!=NULL) { tooltip.SetDescription("Right Button Tooltip"); tooltip.SetIcon(ENUM_CANV_ELEMENT_TOOLTIP_ICON(InpTooltipIcon+1)); tooltip.SetTitle(InpTooltipTitle); tooltip.SetTooltipText(TextByLanguage("Нажмите для прокрутки заголовков влево","Click to scroll headings to the left")); tc.AddTooltipToArrowRightButton(tooltip); } //--- Create a text label with a tab description on each tab for(int j=0;j<tc.TabPages();j++) { //---... //---...
ご覧のように、ToolTipオブジェクトを作成したら、すぐに説明文、表示アイコン、タイトルテキスト、ツールチップを割り当てて、対応するボタンに追加しています。2つ目のToolTipオブジェクトには、設定で指定したものより1つ多いアイコンとして値を指定することで、2つのアイコンを同時に表示することが可能になります。
EAをコンパイルし、チャート上で起動します。
矢印ボタンにマウスポインタを合わせると、すぐにツールチップが表示されます。それぞれが独自のインデックスを持ちます。ツールチップの座標が正しく調整され、画面外に出ないようになりました。これで、矢印ボタンに標準的なグラフィカルプリミティブとして描かれた新しい矢印が表示されるようになります。当然ながら、ToolTipオブジェクトの動作は正しくありません。その正しい動作は、後ほど実装します。このテストは、あくまでオブジェクトの外観を評価するものです。
次の段階
次の記事では、TabControlに取り組みます。
現在のライブラリバージョン、テストEA、およびMQL5のチャートイベントコントロール指標のすべてのファイルは以下に添付されています。
連載のこれまでの記事
DoEasy - コントロール(第20部):SplitContainerWinFormsオブジェクト
DoEasy - コントロール(第21部):SplitContainerコントロール。パネル区切り
DoEasy - コントロール(第22部):SplitContainer。作成したオブジェクトのプロパティを変更する
DoEasy - コントロール(第23部):TabControlとSplitContainer WinFormsオブジェクトの改善
DoEasy - コントロール(第24部):ヒント補助WinFormsオブジェクト
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/11700





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