DoEasy. 控件 (第 25 部分): Tooltip WinForms 对象(基础篇)
📘

DoEasy. 控件 (第 25 部分): Tooltip WinForms 对象(基础篇)

第 1/3 篇

◍ 给控件挂上悬浮提示框

在 DoEasy 库里补一层 ToolTip WinForms 对象,能让任意控件在鼠标悬停时弹出轻量说明,省去交易者盯盘时反复翻面板查字段含义的麻烦。该实现随 2023 年 2 月 24 日发布的系列第 25 部分一同放出,原文示例在 MT5 里可直接挂载观察。 外汇与贵金属市场波动剧烈、杠杆风险高,这类界面增强只解决信息可读性问题,不改变任何下单逻辑或胜率。 实际落地时,先在库里继承出 ToolTip 类,绑定到目标控件的鼠标事件;MT5 里编译后把 EA 拖到图表,悬停按钮即可看到提示文本。下一步是按自己品种缩写习惯改提示内容,别照抄默认文案。

图形元素如何挂上工具提示

在 MT5 自定义控件库里,每个图形对象都具备设置工具提示(ToolTip)的能力,但并非所有元素默认都显示。核心思路是:容器类对象负责创建 ToolTip 控件,再把它指派给需要提示的图形元素,后者只持有一个指向该 ToolTip 的指针。 库里的图形元素彼此之间不需要互相“认识”。它们都被放进 ArrayObj 集合类,这个类接受任何从标准库基类派生的对象,所以一个控件可以静默附着到另一个控件上,可视化调度不会出问题。 典型交互是光标悬停一段时间后提示浮现;若同一对象绑定了多个提示,第一个出现后,后续提示几乎零延迟接续显示——这套多级提示逻辑留到后面文章展开,本节只做实基础:创建 ToolTip 并分配出去。 顺带扩展了函数库的绘图基元:标准图标、左右与上下箭头都能直接画。这些预定义图像不仅 ToolTip 能用,之前做的按钮、标签等元素也能“按原样”调用,后续会逐步铺开到全部图形组件。外汇与贵金属面板开发属高风险改造,建议在策略测试器里先验证控件附着逻辑再上真仓。

「给 DoEasy 库补上标准图标与工具提示骨架」

要在 MT5 的 DoEasy 函数库里画出信息、警告、错误等标准图标,第一步是扩展类型枚举与属性表。整数型图形元素属性从 122 扩到 129,字符串型属性总数增到 6,画布排序准则也加了新项,这样后续才能按新属性筛选和排序控件。 GBaseObj.mqh 的 TypeElementDescription() 方法需补一段:根据传入的对象类型,从 Data.mqh 新加的消息索引里回文本说明。GCnvElement.mqh 里重新加回写入基准对象指针的方法——之前删掉后发现工具提示仍需要它来绑定触发元素。 标准图标的绘制全在类外方法里硬画。信息图标先算圆心画填充圆加 Wu 平滑圆,再用两个矩形拼出“i”;警告图标画填充三角加偏移顶点让“i”视觉居中;错误图标是双圆加 X 线;四个方向箭头则按状态改色,非活动时画成灰色。 阴影对象引入 SetOpacityDraw() 单独管绘制不透明度,背景永远零透明。ShadowObj.mqh 里重命名旧方法并设模糊度默认值,WinFormBase.mqh 改重绘逻辑避免阴影被误擦。ArrowXButton 四个类直接调基类箭头方法,左键类调左箭头,以此类推。 外汇与贵金属图表加载这类自定义库属高风险操作,参数改错可能令 EA 在实盘中断连,建议先在策略测试器跑一遍。

MQL5 / C++
class=class="str">"cmt">//+-------------------------------------------------+
class=class="str">"cmt">//| The list of graphical element types              |
class=class="str">"cmt">//+-------------------------------------------------+
enum ENUM_GRAPH_ELEMENT_TYPE
  {
   GRAPH_ELEMENT_TYPE_STANDARD,                    class=class="str">"cmt">// Standard graphical object
   GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED,           class=class="str">"cmt">// Extended standard graphical object
   GRAPH_ELEMENT_TYPE_SHADOW_OBJ,                  class=class="str">"cmt">// Shadow object
   GRAPH_ELEMENT_TYPE_ELEMENT,                     class=class="str">"cmt">// Element
   GRAPH_ELEMENT_TYPE_FORM,                        class=class="str">"cmt">// Form
   GRAPH_ELEMENT_TYPE_WINDOW,                      class=class="str">"cmt">// Window
   class=class="str">"cmt">//--- WinForms
   GRAPH_ELEMENT_TYPE_WF_UNDERLAY,                 class=class="str">"cmt">// Panel object underlay
   GRAPH_ELEMENT_TYPE_WF_BASE,                     class=class="str">"cmt">// Windows Forms Base
   class=class="str">"cmt">//--- &class="macro">#x27;Container&class="macro">#x27; object types are to be set below
   GRAPH_ELEMENT_TYPE_WF_CONTAINER,                class=class="str">"cmt">// Windows Forms container base object
   GRAPH_ELEMENT_TYPE_WF_PANEL,                    class=class="str">"cmt">// Windows Forms Panel

◍ WinForms 图形元素枚举的底层类型清单

在 MT5 的自定义图形接口里,所有 Windows Forms 风格控件都靠一组 GRAPH_ELEMENT_TYPE_WF_* 枚举值来标识。从容器类的 GroupBox、TabControl、SplitContainer,到标准控件 Label、Button、CheckBox、RadioButton,均在这一体系内逐一映射。 下面这段代码列出了部分核心枚举常量,注释直接对应 WinForms 的原生组件: GRAPH_ELEMENT_TYPE_WF_GROUPBOX 是 GroupBox 容器,GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL 对应多页签 TabControl,GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER 则是可拖拽分隔的 SplitContainer。标准控件基类 GRAPH_ELEMENT_TYPE_WF_COMMON_BASE 之下的 Label、Button、CheckBox 等,都继承其通用属性。 辅助元素容易被忽略:比如 GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM 只是 ListBox 里的单行项,GRAPH_ELEMENT_TYPE_WF_TAB_HEADER 和 GRAPH_ELEMENT_TYPE_WF_TAB_FIELD 分别管页签头与页签内容区。箭头按钮更细,上下左右各有独立枚举(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP / DOWN / LEFT / RIGHT),还有 UD / LR 的组合箭头盒。 开 MT5 按 F4 进 MetaEditor,在包含文件里搜 GRAPH_ELEMENT_TYPE_WF_ 就能看到全量定义;写 CCanvas 或自定义面板时,用对枚举值才能正确捕获鼠标命中区域。外汇与贵金属交易界面自动化高风险,枚举用错可能让面板无响应。

MQL5 / C++
  GRAPH_ELEMENT_TYPE_WF_GROUPBOX,                         class=class="str">"cmt">// Windows Forms GroupBox
  GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,                     class=class="str">"cmt">// Windows Forms TabControl
  GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,                 class=class="str">"cmt">// Windows Forms SplitContainer
  class=class="str">"cmt">//--- &class="macro">#x27;Standard control&class="macro">#x27; object types are to be set below
  GRAPH_ELEMENT_TYPE_WF_COMMON_BASE,                     class=class="str">"cmt">// Windows Forms base standard control
  GRAPH_ELEMENT_TYPE_WF_LABEL,                            class=class="str">"cmt">// Windows Forms Label
  GRAPH_ELEMENT_TYPE_WF_BUTTON,                           class=class="str">"cmt">// Windows Forms Button
  GRAPH_ELEMENT_TYPE_WF_CHECKBOX,                         class=class="str">"cmt">// Windows Forms CheckBox
  GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON,                     class=class="str">"cmt">// Windows Forms RadioButton
  GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX,               class=class="str">"cmt">// Base list object of Windows Forms elements
  GRAPH_ELEMENT_TYPE_WF_LIST_BOX,                        class=class="str">"cmt">// Windows Forms ListBox
  GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX,                class=class="str">"cmt">// Windows Forms CheckedListBox
  GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX,                 class=class="str">"cmt">// Windows Forms ButtonListBox
  GRAPH_ELEMENT_TYPE_WF_TOOLTIP,                         class=class="str">"cmt">// Windows Forms ToolTip
  class=class="str">"cmt">//--- Auxiliary elements of WinForms objects
  GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM,                   class=class="str">"cmt">// Windows Forms ListBoxItem
  GRAPH_ELEMENT_TYPE_WF_TAB_HEADER,                      class=class="str">"cmt">// Windows Forms TabHeader
  GRAPH_ELEMENT_TYPE_WF_TAB_FIELD,                       class=class="str">"cmt">// Windows Forms TabField
  GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL,           class=class="str">"cmt">// Windows Forms SplitContainerPanel
  GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON,                    class=class="str">"cmt">// Windows Forms ArrowButton
  GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,                 class=class="str">"cmt">// Windows Forms UpArrowButton
  GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,               class=class="str">"cmt">// Windows Forms DownArrowButton
  GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,               class=class="str">"cmt">// Windows Forms LeftArrowButton
  GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,              class=class="str">"cmt">// Windows Forms RightArrowButton
  GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX,            class=class="str">"cmt">// Windows Forms UpDownArrowButtonsBox
  GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX,            class=class="str">"cmt">// Windows Forms LeftRightArrowButtonsBox
  GRAPH_ELEMENT_TYPE_WF_SPLITTER,                        class=class="str">"cmt">// Windows Forms Splitter
  GRAPH_ELEMENT_TYPE_WF_HINT_BASE,                       class=class="str">"cmt">// Windows Forms HintBase
  GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT,                  class=class="str">"cmt">// Windows Forms HintMoveLeft
  GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT,                 class=class="str">"cmt">// Windows Forms HintMoveRight
  GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP,                    class=class="str">"cmt">// Windows Forms HintMoveUp

画布控件枚举与提示框延时参数

在 MT5 自定义画布(Canvas)界面开发里,控件类型与布局方向都用枚举固化。比如分割容器方向只有垂直与水平两种:ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION 中 VERTICAL 对应纵向切分,HORISONTAL 负责横向排布,写面板布局时选错常量会导致子控件直接重叠。 预定义提示图标枚举 ENUM_CANV_ELEMENT_TOOLTIP_ICON 给了 5 个档位:NONE、INFO、WARNING、ERROR、USER。实盘挂单面板用 WARNING 标平价保护触发,比纯文字更抓眼。 整数属性枚举 ENUM_CANV_ELEMENT_PROP_INTEGER 末尾集中了 8 个 Tooltip 相关项。INITIAL_DELAY 管鼠标悬停多久才弹提示,AUTO_POP_DELAY 管停留时长,RESHOW_DELAY 管移到同窗另一控件后的再弹间隔;IS_BALLOON 切气泡样式,USE_FADING 控淡入淡出。 宏 CANV_ELEMENT_PROP_INTEGER_TOTAL 写死为 129,意味着整套画布整数属性目前封顶 129 个。开 MT5 在 Include 里搜这个宏,能反推你用的标准库版本是否含后续新增的 tooltip 字段。

MQL5 / C++
enum ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION
  {
  CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL,        class=class="str">"cmt">// Vertical
  CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL,      class=class="str">"cmt">// Horizontal
  };

enum ENUM_CANV_ELEMENT_TOOLTIP_ICON
  {
  CANV_ELEMENT_TOOLTIP_ICON_NONE,                    class=class="str">"cmt">// None
  CANV_ELEMENT_TOOLTIP_ICON_INFO,                    class=class="str">"cmt">// Info
  CANV_ELEMENT_TOOLTIP_ICON_WARNING,                 class=class="str">"cmt">// Warning
  CANV_ELEMENT_TOOLTIP_ICON_ERROR,                   class=class="str">"cmt">// Error
  CANV_ELEMENT_TOOLTIP_ICON_USER,                    class=class="str">"cmt">// User
  };

enum ENUM_CANV_ELEMENT_PROP_INTEGER
  {
  CANV_ELEMENT_PROP_ID = class="num">0,                          class=class="str">"cmt">// Element ID
  CANV_ELEMENT_PROP_TYPE,                            class=class="str">"cmt">// Graphical element type
  CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,class=class="str">"cmt">// Flag for collapsed panel class="num">2
  CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE, class=class="str">"cmt">// Panel class="num">2 minimum size
  CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY,           class=class="str">"cmt">// Tooltip display delay
  CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY,          class=class="str">"cmt">// Tooltip display duration
  CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY,            class=class="str">"cmt">// One element new tooltip display delay
  CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS,             class=class="str">"cmt">// Display a tooltip in inactive window
  CANV_ELEMENT_PROP_TOOLTIP_ICON,                    class=class="str">"cmt">// Icon displayed in tooltip
  CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON,              class=class="str">"cmt">// Tooltip in the form of a "cloud"
  CANV_ELEMENT_PROP_TOOLTIP_USE_FADING,              class=class="str">"cmt">// Fade when showing/hiding a tooltip
  };

class="macro">#define CANV_ELEMENT_PROP_INTEGER_TOTAL(class="num">129)         class=class="str">"cmt">// Total number of integer properties

「画布元素的字符串属性与排序枚举」

在 MT5 自定义画布上管理图形元素时,除了整型和双精度属性,字符串属性用来承载名称、文本与提示框内容。上面这段枚举 ENUM_CANV_ELEMENT_PROP_STRING 定义了 6 个字符串属性,其中 CANV_ELEMENT_PROP_TOOLTIP_TITLE 与 CANV_ELEMENT_PROP_TOOLTIP_TEXT 是后来补上的 tooltip 相关字段,专门控制悬停提示的标题与正文。 排序枚举 ENUM_SORT_CANV_ELEMENT_MODE 把整型、双精度、字符串三类属性统一编成连续索引。宏 FIRST_CANV_ELEMENT_STR_PROP 用「整型总数减跳过数 + 双精度总数减跳过数」算出字符串属性在排序表中的起始偏移,写库时改了属性总数就得同步这个宏,否则排序索引会错位。 tooltip 系列的排序键值得留意:SORT_BY_CANV_ELEMENT_TOOLTIP_INITIAL_DELAY 控制首次延迟,AUTO_POP_DELAY 管显示时长,RESHOW_DELAY 管同元素再次弹出的间隔。做面板时若想让某些控件优先响应悬停,直接按这些键排序图层就可能改变拾取顺序。外汇与贵金属图表挂这类自定义 UI 属高风险操作,参数乱改可能让 EA 界面卡死。

MQL5 / C++
class="macro">#define CANV_ELEMENT_PROP_INTEGER_SKIP(class="num">0) class=class="str">"cmt">// Number of integer properties not used in sorting
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| String properties of the graphical element on the canvas          |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_CANV_ELEMENT_PROP_STRING
  {
   CANV_ELEMENT_PROP_NAME_OBJ = (CANV_ELEMENT_PROP_INTEGER_TOTAL+CANV_ELEMENT_PROP_DOUBLE_TOTAL), class=class="str">"cmt">// Graphical element object name
   CANV_ELEMENT_PROP_NAME_RES,                                                        class=class="str">"cmt">// Graphical resource name
   CANV_ELEMENT_PROP_TEXT,                                                            class=class="str">"cmt">// Graphical element text
   CANV_ELEMENT_PROP_DESCRIPTION,                                                     class=class="str">"cmt">// Graphical element description
   CANV_ELEMENT_PROP_TOOLTIP_TITLE,                                                   class=class="str">"cmt">// Element tooltip title
   CANV_ELEMENT_PROP_TOOLTIP_TEXT,                                                    class=class="str">"cmt">// Element tooltip text
   };
class="macro">#define CANV_ELEMENT_PROP_STRING_TOTAL(class="num">6)                                            class=class="str">"cmt">// Total number of class="type">class="kw">string properties
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Possible sorting criteria of graphical elements on the canvas    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#define FIRST_CANV_ELEMENT_DBL_PROP(CANV_ELEMENT_PROP_INTEGER_TOTAL-CANV_ELEMENT_PROP_INTEGER_SKIP)
class="macro">#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
  {
class=class="str">"cmt">//--- Sort by integer properties
   SORT_BY_CANV_ELEMENT_ID = class="num">0,                                                       class=class="str">"cmt">// Sort by element ID
   SORT_BY_CANV_ELEMENT_TYPE,                                                         class=class="str">"cmt">// Sort by graphical element type
class=class="str">"cmt">//---...
class=class="str">"cmt">//---...
   SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_PANEL2_COLLAPSED,class=class="str">"cmt">// Sort by flag for collapsed panel class="num">2
   SORT_BY_CANV_ELEMENT_SPLIT_CONTAINER_PANEL2_MIN_SIZE, class=class="str">"cmt">// Sort by panel class="num">2 minimum size
   SORT_BY_CANV_ELEMENT_TOOLTIP_INITIAL_DELAY,                                           class=class="str">"cmt">// Sort by tooltip display delay
   SORT_BY_CANV_ELEMENT_TOOLTIP_AUTO_POP_DELAY,                                          class=class="str">"cmt">// Sort by tooltip display duration
   SORT_BY_CANV_ELEMENT_TOOLTIP_RESHOW_DELAY,                                            class=class="str">"cmt">// Sort by one element new tooltip display delay
   SORT_BY_CANV_ELEMENT_TOOLTIP_SHOW_ALWAYS,                                             class=class="str">"cmt">// Sort by a tooltip in inactive window
   SORT_BY_CANV_ELEMENT_TOOLTIP_ICON,                                                    class=class="str">"cmt">// Sort by icon displayed in a tooltip
   SORT_BY_CANV_ELEMENT_TOOLTIP_IS_BALLOON,                                              class=class="str">"cmt">// Sort by a cloud tooltip flag
   SORT_BY_CANV_ELEMENT_TOOLTIP_USE_FADING,                                              class=class="str">"cmt">// Sort by the flag of fading when showing/hiding a tooltip
class=class="str">"cmt">//--- Sort by real properties
class=class="str">"cmt">//--- Sort by class="type">class="kw">string properties

常见问题

在控件基类里挂一个 Tooltip 对象,绑定到画布元素枚举,设置延时参数后,鼠标移到控件上就会自动弹出悬浮说明。
需要先把 WinForms 图形元素枚举的底层类型清单列全,再补上画布控件枚举与字符串属性枚举,提示框才能读到图标和排序信息。
小布可以读取你的画布元素配置,自动生成Tooltip骨架代码并标出延时参数位置,你只需补具体文字就能用。
延时写在画布控件的 Tooltip 初始化参数里,单位是毫秒,调大数值即可避免鼠标划过就弹框。
不写的话提示框只能显示固定文本,写了才能按元素类型动态排序并拼接多语言说明,建议补上。