English Русский 中文 Español Deutsch Português
preview
DoEasy - コントロール(第25部):Tooltip WinFormsオブジェクト

DoEasy - コントロール(第25部):Tooltip WinFormsオブジェクト

MetaTrader 5 | 16 1月 2023, 13:02
144 0
Artyom Trishkin
Artyom Trishkin

内容


概念

コントロールにマウスを合わせてしばらくすると、説明のツールチップが表示されます。当然ながら、すべての要素にツールチップがあるわけではないですが、すべてのグラフィックオブジェクトにはツールチップを設定する機能があります。そのような可能性を、ライブラリのグラフィック要素に与えてみましょう。

ライブラリのすべてのグラフィック要素が他のグラフィック要素の存在を「知っている」わけではありませんが、これらのオブジェクトはすべて、管理された要素を自らに接続することができます。グラフィック要素に接続されるオブジェクトには、親要素が何も知らないオブジェクトが含まれることがあります。接続された要素の制御はグラフィック要素のコレクションクラスでおこなわれるため、様々なタイプのコントロールの可視性に問題はなく、コレクションクラスはそれらについてすべてを知っています。

また、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

添付されたファイル |
MQL5.zip (4557.73 KB)
データサイエンスと機械学習(第09回):K近傍法(KNN) データサイエンスと機械学習(第09回):K近傍法(KNN)
これは、訓練データセットから学習しない遅延アルゴリズムです。代わりにデータセットを保存し、新しいサンプルが与えられるとすぐに動作します。シンプルでありながら、実世界でさまざまなケースに応用されています。
母集団最適化アルゴリズム:蟻コロニー最適化(ACO) 母集団最適化アルゴリズム:蟻コロニー最適化(ACO)
今回は、蟻コロニー最適化アルゴリズムについて解析します。このアルゴリズムは非常に興味深く、複雑です。この記事では、新しいタイプのACOの作成を試みます。
知っておくべきMQL5ウィザードのテクニック(第04回):線形判別分析 知っておくべきMQL5ウィザードのテクニック(第04回):線形判別分析
今日のトレーダーは哲学者であり、ほとんどの場合、新しいアイデアを探して試し、変更するか破棄するかを選択します。これは、かなりの労力を要する探索的プロセスです。この連載では、MQL5ウィザードがこの取り組みにおけるトレーダーの主力であるべきであることを示しています。
ニューラルネットワークが簡単に(第31部):進化的アルゴリズム ニューラルネットワークが簡単に(第31部):進化的アルゴリズム
前回の記事では、非勾配最適化手法の調査を開始しました。遺伝的アルゴリズムについて学びました。今日は、このトピックを継続し、進化的アルゴリズムの別のクラスを検討します。