DoEasy. 控件 (第 25 部分): Tooltip WinForms 对象·进阶篇
📘

DoEasy. 控件 (第 25 部分): Tooltip WinForms 对象·进阶篇

第 2/3 篇

◍ 画布控件的排序键与提示框属性枚举

在 MT5 自定义图形界面库里,画布元素(Canvas Element)支持按多种字段排序,枚举从 SORT_BY_CANV_ELEMENT_NAME_OBJ 起,依次覆盖对象名、资源名、元素文本、描述,以及容易被忽略的 ToolTip 头部与文本(SORT_BY_CANV_ELEMENT_TOOLTIP_HEADER / SORT_BY_CANV_ELEMENT_TOOLTIP_TEXT)。做列表控件排序时,若要用悬浮提示内容做主键,这两个枚举值才是正解,而非复用文本字段。 CForm 与 CFrame 的消息常量里,标黄部分集中暴露了 ToolTip 相关的新增能力:MSG_FORM_TOOLTIP_OBJ_ALREADY_EXISTS 提示同对象重复创建会被拦截;MSG_GRAPH_ELEMENT_TYPE_WF_TOOLTIP 把提示框列为独立控件类型;而 MSG_CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY、AUTO_POP_DELAY、RESHOW_DELAY 三者在源码注释中分别对应‘首次延迟 / 持续时长 / 同元素再显示延迟’,单位为毫秒级。 另有 MSG_CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS 控制非活跃窗口是否仍弹提示,MSG_CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON 切换云状样式,MSG_CANV_ELEMENT_PROP_TOOLTIP_USE_FADING 决定是否淡入淡出。外汇与贵金属图表挂这类界面属高风险环境,实盘前应在策略测试器里先验证消息枚举不会因对象归属(MSG_GRAPH_OBJ_BELONG_PROGRAM)判断失误而漏建控件。 开 MT5 打开标准库 CWnd 派生代码,搜 MSG_CANV_ELEMENT_PROP_TOOLTIP 前缀,能直接看到上述枚举定义;改 INITIAL_DELAY 默认值可能让悬浮提示响应更跟手,但需自行回测交互卡顿概率。

MQL5 / C++
SORT_BY_CANV_ELEMENT_NAME_OBJ = FIRST_CANV_ELEMENT_STR_PROP, class=class="str">"cmt">// Sort by an element object name
SORT_BY_CANV_ELEMENT_NAME_RES, class=class="str">"cmt">// Sort by the graphical resource name
SORT_BY_CANV_ELEMENT_TEXT, class=class="str">"cmt">// Sort by graphical element text
SORT_BY_CANV_ELEMENT_DESCRIPTION, class=class="str">"cmt">// Sort by graphical element description
SORT_BY_CANV_ELEMENT_TOOLTIP_HEADER, class=class="str">"cmt">// Sort by ToolTip header for an element
SORT_BY_CANV_ELEMENT_TOOLTIP_TEXT, class=class="str">"cmt">// Sort by ToolTip text for an element
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//--- CForm
MSG_FORM_OBJECT_TEXT_NO_SHADOW_OBJ_FIRST_CREATE_IT, class=class="str">"cmt">// No shadow object. Create it using the CreateShadowObj() method
MSG_FORM_OBJECT_ERR_FAILED_CREATE_SHADOW_OBJ, class=class="str">"cmt">// Failed to create new shadow object
MSG_FORM_OBJECT_ERR_FAILED_CREATE_PC_OBJ, class=class="str">"cmt">// Failed to create new pixel copier object
MSG_FORM_OBJECT_PC_OBJ_ALREADY_IN_LIST, class=class="str">"cmt">// Pixel copier object with ID already present in the list 
MSG_FORM_OBJECT_PC_OBJ_NOT_EXIST_LIST, class=class="str">"cmt">// No pixel copier object with ID in the list 
MSG_FORM_OBJECT_ERR_NOT_INTENDED, class=class="str">"cmt">// The method is not meant for creating such an object: 
MSG_FORM_TOOLTIP_OBJ_ALREADY_EXISTS, class=class="str">"cmt">// ToolTip object already exists
class=class="str">"cmt">//--- CFrame
MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP, class=class="str">"cmt">// HintMoveLeft control
MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN, class=class="str">"cmt">// HintMoveLeft control
MSG_GRAPH_ELEMENT_TYPE_WF_TOOLTIP, class=class="str">"cmt">// ToolTip control
MSG_GRAPH_OBJ_BELONG_PROGRAM, class=class="str">"cmt">// Graphical object belongs to a program
MSG_GRAPH_OBJ_BELONG_NO_PROGRAM, class=class="str">"cmt">// Graphical object does not belong to a program
MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED, class=class="str">"cmt">// Flag for collapsed panel class="num">1
MSG_CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE, class=class="str">"cmt">// Panel class="num">2 minimum size
MSG_CANV_ELEMENT_PROP_TOOLTIP_INITIAL_DELAY, class=class="str">"cmt">// Tooltip display delay
MSG_CANV_ELEMENT_PROP_TOOLTIP_AUTO_POP_DELAY, class=class="str">"cmt">// Tooltip display duration
MSG_CANV_ELEMENT_PROP_TOOLTIP_RESHOW_DELAY, class=class="str">"cmt">// One element new tooltip display delay
MSG_CANV_ELEMENT_PROP_TOOLTIP_SHOW_ALWAYS, class=class="str">"cmt">// Display a tooltip in inactive window
MSG_CANV_ELEMENT_PROP_TOOLTIP_ICON, class=class="str">"cmt">// Icon displayed in a tooltip
MSG_CANV_ELEMENT_PROP_TOOLTIP_IS_BALLOON, class=class="str">"cmt">// Tooltip in the form of a "cloud"
MSG_CANV_ELEMENT_PROP_TOOLTIP_USE_FADING, class=class="str">"cmt">// Fade when showing/hiding a tooltip

class=class="str">"cmt">//--- Real properties of graphical elements

「画布控件的字符串属性与提示框字段」

在 MT5 自定义图形库里,画布元素有一组字符串属性用于标识自身与资源:对象名、图形资源名、元素文本、描述,以及两项目 tooltip 相关字段(标题与正文)。这些常量通常定义在枚举中,供 CCanvas 派生类读写。 CForm 类报错文本暴露了底层依赖:影子对象须先经 CreateShadowObj() 创建,否则会返回「There is no shadow object」;像素拷贝器按 ID 管理,重复 ID 会触发「There is already a pixel copier object in the list with ID 」。 CFrame 部分高亮了 ToolTip 系列本地化键:初始延迟(Tooltip initial delay)、自动消失延迟(Tooltip autopoop delay,原库拼写如此)、同元素重显延迟(Tooltip reshow delay),以及是否总显示、是否气泡形、是否渐隐等开关。 直接在 MQ5 里搜 MSG_CANV_ELEMENT_PROP_TOOLTIP_TEXT 或「Tooltip initial delay」,能定位到标准库源文件,改一处延迟常量即可影响所有面板悬停提示节奏。外汇与贵金属图表挂 EA 做 UI 实验属高风险操作,参数改动前建议在策略测试器离线验证。

MQL5 / C++
class=class="str">"cmt">//--- String properties of graphical elements
   MSG_CANV_ELEMENT_PROP_NAME_OBJ,                 class=class="str">"cmt">// Graphical element object name
   MSG_CANV_ELEMENT_PROP_NAME_RES,                 class=class="str">"cmt">// Graphical resource name
   MSG_CANV_ELEMENT_PROP_TEXT,                     class=class="str">"cmt">// Graphical element text
   MSG_CANV_ELEMENT_PROP_DESCRIPTION,              class=class="str">"cmt">// Graphical element description
   MSG_CANV_ELEMENT_PROP_TOOLTIP_TITLE,            class=class="str">"cmt">// Element tooltip title
   MSG_CANV_ELEMENT_PROP_TOOLTIP_TEXT,             class=class="str">"cmt">// Element tooltip text
   };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//--- 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"},

class=class="str">"cmt">//--- 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"},
   {"Флаг свёрнутости панели class="num">2","Flag to indicate that panel class="num">2 is collapsed"},
   {"Минимальный размер панели class="num">2","Min size of Panel class="num">2"},
   {"Задержка отображения подсказки","Tooltip initial delay"},
   {"Длительность отображения подсказки","Tooltip autopoop delay"},
   {"Задержка отображения новой подсказки одного элемента","Tooltip reshow delay"},
   {"Отображать подсказку в неактивном окне","Tooltip show always"},
   {"Значок, отображаемый в подсказке","Tooltip icon"},
   {"Подсказка в форме \"облачка\"","Tooltip as \"Balloon\""},
   {"Угасание при отображении и скрытии подсказки","Tooltip uses fading"},
class=class="str">"cmt">//--- String properties of graphical elements
   {"Имя объекта-графического элемента","The name of the graphic element object"},
   {"Имя графического ресурса","Image resource name"},
   {"Текст графического элемента","Text of the graphic element"}

图形元素类型的描述映射逻辑

在 MT5 自定义指标或 EA 的 GUI 框架里,图形元素并非只用枚举值传递,而是需要可读的描述文本。CGBaseObj::TypeElementDescription 这个函数就是干这件事的:传入 ENUM_GRAPH_ELEMENT_TYPE,返回对应语言的字符串。 从实现看,它覆盖了 6 类基础元素(标准、扩展标准、元素、阴影对象、表单、窗口)和 WinForms 系(底层、基类、容器、分组框、面板、选项卡、分割容器、通用基类、标签等)。每一条都走 CMessage::Text(MSG_*) 取多语言文案,说明这套架构原生考虑了俄英双语切换。 你在写自己的面板控件时,若想让日志或 tooltip 直接打印元素类别,可以照搬这个三元运算符链。外汇和贵金属图表上挂这类 GUI 工具属于高风险操作,参数误用可能导致面板不刷新或句柄泄漏。 下面这段是原文里的核心返回逻辑,注意每个 ? : 分支都对应一个 MSG 常量,改的时候别漏掉新增类型:

MQL5 / C++
class="type">class="kw">string CGBaseObj::TypeElementDescription(const ENUM_GRAPH_ELEMENT_TYPE type)
  {
   class="kw">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)                :
       class=class="str">"cmt">//--- 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)               :
       class=class="str">"cmt">//--- 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)    :
       class=class="str">"cmt">//--- 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)              :

◍ 工作流控件类型的字符串映射细节

在 MT5 的 GUI 框架里,工作流(WF)图形元素类型靠一连串三元表达式转成可读文本,方便调试时直接打印控件身份。上面这段分支覆盖了从 checkbox、radiobutton 到各类 list box、箭头按钮乃至 split container 的枚举映射。 其中 GRAPH_ELEMENT_TYPE_WF_TOOLTIP 与后续的 WF_TAB_HEADER、WF_ARROW_BUTTON 等被归在「Auxiliary control objects」注释下,说明它们是框架内部辅助控件,不一定直接暴露给终端用户。 如果你在写自定义面板,复制这段映射进 CMessage::Text 的调用链,能在日志里把 type 值还原成 MSG_GRAPH_ELEMENT_TYPE_WF_* 对应的中文或英文标签,省去查枚举表的麻烦。外汇与贵金属 GUI ea 开发涉及实时刷新,控件类型判错可能导致面板卡死,属高风险调试环节。

MQL5 / C++
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) :
class=class="str">"cmt">//--- 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):

「图形对象的相对坐标与基准指针」

在 MT5 自定义图形类里,子对象常需要挂在某个基准元素上做偏移布局。上面这段接口把 X/Y 相对位移拆成了独立的 Setter/Getter:SetCoordXRelative 写 m_shift_coord_x,CoordXRelative 只读返回,Y 方向同理,两个整型字段各自独立,互不干扰。 SetBase 接收 CGCnvElement* 指针,把当前对象绑到同组父元素上。没有这步绑定,后续按基准做相对坐标换算会指向空对象,图表上可能直接不渲染或报错。 active area 的边缘偏移用 SetActiveAreaLeftShift / RightShift 封装,内部走 SetProperty 且对入参取 fabs——也就是说传负数也会被转成绝对值,左/右偏移量实际只认大小不认方向。外汇与贵金属图表物件叠加时杠杆风险高,改这些偏移量前建议在策略测试器里先验证渲染位置。

MQL5 / C++
type==GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN) :
 "Unknown"
 );
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">public:
class=class="str">"cmt">//--- (class="num">1) Set and(class="num">2) class="kw">return the X coordinate shift relative to the base object
 class="type">void SetCoordXRelative(const class="type">int value) { this.m_shift_coord_x=value; }
 class="type">int CoordXRelative(class="type">void) const { class="kw">return this.m_shift_coord_x; }
class=class="str">"cmt">//--- (class="num">1) Set and(class="num">2) class="kw">return the Y coordinate shift relative to the base object
 class="type">void SetCoordYRelative(const class="type">int value) { this.m_shift_coord_y=value; }
 class="type">int CoordYRelative(class="type">void) const { class="kw">return this.m_shift_coord_y; }
class=class="str">"cmt">//--- Set the pointer to the parent element within related objects of the current group
 class="type">void SetBase(CGCnvElement *base) { this.m_element_base=base; }

class=class="str">"cmt">//--- Event handler
 class="kw">virtual class="type">void OnChartEvent(const class="type">int id,const class="type">long& lparam,const class="type">class="kw">double& dparam,const class="type">class="kw">string& sparam);
class=class="str">"cmt">//--- Set the shift of the(class="num">1) left, (class="num">2) top, (class="num">3) right, (class="num">4) bottom edge of the active area relative to the element,
class=class="str">"cmt">//--- (class="num">5) all shifts of the active area edges relative to the element, (class="num">6) opacity
 class="type">void SetActiveAreaLeftShift(const class="type">int value) { this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_LEFT,fabs(value)); }
 class="type">void SetActiveAreaRightShift(const class="type">int value) { this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_RIGHT,fabs(value)); }

画布控件的热区偏移与提示文本接口

在 MT5 自定义图形控件里,活跃区(active area)并不总等于控件可视矩形。用 SetActiveAreaTopShift 和 SetActiveAreaBottomShift 可以把可点击/可悬停区域向上或向下外扩,内部统一走 fabs(value) 取绝对值,所以传负数也不会让热区反向收缩。 [CODE] 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, const int height, const ENUM_FRAME_ANCHOR anchor, int &shift_x, [/CODE] 逐行看:第1行设置热区顶部外扩像素,第2行设置底部外扩;第4行 SetOpacity 支持传 redraw 标志,改透明度后是否立即重绘由调用方决定。Tooltip 两块最实用——SetTooltipText 写字符串进 CANV_ELEMENT_PROP_TOOLTIP_TEXT,TooltipText 再读回来,悬停提示就能随状态动态换文案。 SetDisplayed 控制控件是否参与显示(非隐藏态),Displayed 返回当前布尔值。GetShiftXYbySize 则按宽高与 ENUM_FRAME_ANCHOR 锚点算出左上角偏移 shift_x / shift_y,锚点不同,同样的矩形尺寸算出的坐标可能差出几十像素,排版错位时先查这里。 外汇与贵金属图表叠加自绘控件属高风险操作环境,图形层异常不保证行情判断正确,参数改完建议在策略测试器用历史数据验证热区命中范围。

MQL5 / C++
class="type">void SetActiveAreaTopShift(const class="type">int value) { this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_TOP,fabs(value)); }
class="type">void SetActiveAreaBottomShift(const class="type">int value) { this.SetProperty(CANV_ELEMENT_PROP_ACT_SHIFT_BOTTOM,fabs(value)); }
class="type">void SetActiveAreaShift(const class="type">int left_shift,const class="type">int bottom_shift,const class="type">int right_shift,const class="type">int top_shift);
class="kw">virtual class="type">void SetOpacity(const class="type">uchar value,const class="type">bool redraw=false);
class=class="str">"cmt">//--- (class="num">1) Set and(class="num">2) class="kw">return the Tooltip text
class="kw">virtual class="type">void SetTooltipText(const class="type">class="kw">string text) { this.SetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT,text); }
class="kw">virtual class="type">class="kw">string TooltipText(class="type">void) { class="kw">return this.GetProperty(CANV_ELEMENT_PROP_TOOLTIP_TEXT); }
class=class="str">"cmt">//--- (class="num">1) Set and(class="num">2) class="kw">return the flag for displaying a non-hidden control
class="kw">virtual class="type">void SetDisplayed(const class="type">bool flag) { this.SetProperty(CANV_ELEMENT_PROP_DISPLAYED,flag); }
class="type">bool Displayed(class="type">void) const { class="kw">return (class="type">bool)this.GetProperty(CANV_ELEMENT_PROP_DISPLAYED); }
class=class="str">"cmt">//--- Return coordinate offsets relative to the rectangle anchor point by size
class="type">void GetShiftXYbySize(const class="type">int width, const class="type">int height, const ENUM_FRAME_ANCHOR anchor, class="type">int &shift_x,

常见问题

在控件字符串属性枚举里找到提示框字段,运行时直接赋新字符串即可,热区偏移不变。
按图形元素类型枚举逐个比对描述映射表,确认基准指针和相对坐标是否一致。
可以,小布能扫描控件配置,标出提示框字段缺失或热区偏移异常并给修正建议。
翻工作流控件类型定义段,里面列了每种类型的字符串映射键值,照抄不会错。
先核基准指针指向的容器,再按相对坐标重算热区偏移,偏位通常来自基准选错。