DoEasy. 控件 (第 13 部分): 优化 WinForms 对象与鼠标的交互,启动开发 TabControl WinForms 对象·进阶篇
🖱️

DoEasy. 控件 (第 13 部分): 优化 WinForms 对象与鼠标的交互,启动开发 TabControl WinForms 对象·进阶篇

(2/3)· 相邻 WinForms 对象光标移出后外观卡死?4 像素间距陷阱与命名链过长一并拆解

案例拆解新手友好 第 2/3 篇

把按钮和标签贴到 3 像素内,鼠标从右往左移出,控件就赖着高亮不还原——这不是你代码写错,是库里对象复位逻辑认方向。很多人靠拉远间距掩盖问题,却卡住了 TabControl 这类紧凑布局的进度。

◍ 画布控件的状态与对齐枚举

在 MT5 自定义画布界面里,复选类控件先靠枚举区分三种勾选态:未勾选、已勾选、未定(undefined)。这三者对应 ENUM_CANV_ELEMENT_CHEK_STATE,写面板逻辑时若漏掉 INDETERMINATE 分支,半选状态的指标开关会直接失响应。 控件相对容器的摆放位置由 ENUM_CANV_ELEMENT_ALIGNMENT 决定,仅支持上、下、左、右四个基准位,没有居中枚举。实测若想让按钮在画布正中,只能先取画布宽高再手动减控件尺寸,靠对齐枚举本身办不到。 被高亮的几行整数属性专门管「开启态」配色:前景色与背景色各拆出 STATE_ON、STATE_ON_MOUSE_DOWN、STATE_ON_MOUSE_OVER 三组。也就是说,一个开关按钮在「开 + 悬停」和「开 + 按下」时,文字与底色的整数属性要分开设,混用普通 MOUSE_OVER 会让开启态视觉反馈丢失。 开 MT5 新建 canvas 指标,把上面枚举抄进代码,故意让某个 toggle 处于 INDETERMINATE,看事件回调是否走了默认分支,就能验证你这套 UI 状态机有没有漏洞。

MQL5 / C++
enum ENUM_CANV_ELEMENT_CHEK_STATE
  {
   CANV_ELEMENT_CHEK_STATE_UNCHECKED,                     class=class="str">"cmt">// Unchecked
   CANV_ELEMENT_CHEK_STATE_CHECKED,                       class=class="str">"cmt">// Checked
   CANV_ELEMENT_CHEK_STATE_INDETERMINATE,                 class=class="str">"cmt">// Undefined
  };
enum ENUM_CANV_ELEMENT_ALIGNMENT
  {
   CANV_ELEMENT_ALIGNMENT_TOP,                            class=class="str">"cmt">// Top
   CANV_ELEMENT_ALIGNMENT_BOTTOM,                         class=class="str">"cmt">// Bottom
   CANV_ELEMENT_ALIGNMENT_LEFT,                           class=class="str">"cmt">// Left
   CANV_ELEMENT_ALIGNMENT_RIGHT,                          class=class="str">"cmt">// Right
  };
  CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_DOWN,                class=class="str">"cmt">// Default control text class="type">color when clicking on the control
  CANV_ELEMENT_PROP_FORE_COLOR_MOUSE_OVER,                class=class="str">"cmt">// Default control text class="type">color when hovering the mouse over the control
  CANV_ELEMENT_PROP_FORE_COLOR_STATE_ON,                  class=class="str">"cmt">// Text class="type">color of the control which is on
  CANV_ELEMENT_PROP_FORE_COLOR_STATE_ON_MOUSE_DOWN,       class=class="str">"cmt">// Default control text class="type">color when clicking on the control which is on
  CANV_ELEMENT_PROP_FORE_COLOR_STATE_ON_MOUSE_OVER,       class=class="str">"cmt">// Default control text class="type">color when hovering the mouse over the control which is on
  CANV_ELEMENT_PROP_BACKGROUND_COLOR,                     class=class="str">"cmt">// Control background class="type">color
  CANV_ELEMENT_PROP_BACKGROUND_COLOR_OPACITY,             class=class="str">"cmt">// Opacity of control background class="type">color
  CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_DOWN,          class=class="str">"cmt">// Control background class="type">color when clicking on the control
  CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_OVER,          class=class="str">"cmt">// Control background class="type">color when hovering the mouse over the control
  CANV_ELEMENT_PROP_BACKGROUND_COLOR_STATE_ON,            class=class="str">"cmt">// Background class="type">color of the control which is on
  CANV_ELEMENT_PROP_BACKGROUND_COLOR_STATE_ON_MOUSE_DOWN, class=class="str">"cmt">// Control background class="type">color when clicking on the control which is on
  CANV_ELEMENT_PROP_BACKGROUND_COLOR_STATE_ON_MOUSE_OVER, class=class="str">"cmt">// Control background class="type">color when hovering the mouse over control which is on
  CANV_ELEMENT_PROP_BOLD_TYPE,                            class=class="str">"cmt">// Font width type
  CANV_ELEMENT_PROP_BORDER_STYLE,                         class=class="str">"cmt">// Control frame style

画布控件枚举里新补的排版属性

在画布图形库的枚举定义里,近期补进了几项跟控件内部排版相关的整型属性。ListBox 支持横向多列显示与列宽控制,TabControl 则多出多行标签与标签对齐位置两项,普通对象也加了在控件内的对齐方式属性。 这些新增项在源码里以高亮标出:CANV_ELEMENT_PROP_TAB_MULTILINE、CANV_ELEMENT_PROP_TAB_ALIGNMENT、CANV_ELEMENT_PROP_ALIGNMENT,分别对应多行标签、标签位置、对象位置。它们同步在排序枚举里出现 SORT_BY_ 前缀的对应项,说明库已支持按这些属性做元素排序。 整型属性总数宏定义为 88:#define CANV_ELEMENT_PROP_INTEGER_TOTAL (88),而跳过排序的整型属性为 0。开 MT5 在 MetaEditor 搜 CANV_ELEMENT_PROP_ALIGNMENT,能直接看到枚举上下文并改自己的 CCanvas 面板布局。 消息文本枚举也补了 MSG_LIB_TEXT_TOP/BOTTOM/LEFT/RIGHT 与 MSG_LIB_TEXT_CORNER_LEFT_UPPER,方便把方位词本地化。做多语言 HUD 时别手写中文「上/下」,改用库消息常量,后续切英语包不用动逻辑。

MQL5 / C++
CANV_ELEMENT_PROP_LIST_BOX_MULTI_COLUMN,              class=class="str">"cmt">// Horizontal display of columns in the ListBox control
CANV_ELEMENT_PROP_LIST_BOX_COLUMN_WIDTH,              class=class="str">"cmt">// Width of each ListBox control column
CANV_ELEMENT_PROP_TAB_MULTILINE,                      class=class="str">"cmt">// Several lines of tabs in TabControl
CANV_ELEMENT_PROP_TAB_ALIGNMENT,                      class=class="str">"cmt">// Location of tabs inside the control
CANV_ELEMENT_PROP_ALIGNMENT,                          class=class="str">"cmt">// Location of an object inside the control
};
class="macro">#define CANV_ELEMENT_PROP_INTEGER_TOTAL(class="num">88)          class=class="str">"cmt">// Total number of integer properties
class="macro">#define CANV_ELEMENT_PROP_INTEGER_SKIP(class="num">0)            class=class="str">"cmt">// Number of integer properties not used in sorting
SORT_BY_CANV_ELEMENT_LIST_BOX_MULTI_COLUMN,           class=class="str">"cmt">// Sort by horizontal column display flag in the ListBox control
SORT_BY_CANV_ELEMENT_LIST_BOX_COLUMN_WIDTH,           class=class="str">"cmt">// Sort by the width of each ListBox control column
SORT_BY_CANV_ELEMENT_TAB_MULTILINE,                   class=class="str">"cmt">// Sort by the flag of several rows of tabs in TabControl
SORT_BY_CANV_ELEMENT_TAB_ALIGNMENT,                   class=class="str">"cmt">// Sort by the location of tabs inside the control
SORT_BY_CANV_ELEMENT_ALIGNMENT,                       class=class="str">"cmt">// Sort by the location of the object inside the control
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
};
MSG_LIB_TEXT_BUTTON_STATE_PRESSED,                    class=class="str">"cmt">// Pressed
MSG_LIB_TEXT_BUTTON_STATE_DEPRESSED,                  class=class="str">"cmt">// Released
MSG_LIB_TEXT_TOP,                                     class=class="str">"cmt">// Top
MSG_LIB_TEXT_BOTTOM,                                  class=class="str">"cmt">// Bottom
MSG_LIB_TEXT_LEFT,                                    class=class="str">"cmt">// Left
MSG_LIB_TEXT_RIGHT,                                   class=class="str">"cmt">// Right
MSG_LIB_TEXT_CORNER_LEFT_UPPER,                       class=class="str">"cmt">// Center of coordinates at the upper left corner of the chart

「图形库多语言枚举与锚点定义」

在 MT5 标准库的消息映射结构里,图形元素的坐标锚点和控件类型是用一组枚举常量描述的。比如 MSG_LIB_TEXT_CORNER_LEFT_LOWER 到 MSG_LIB_TEXT_CORNER_RIGHT_UPPER 四个常量,分别把文本坐标系原点钉在图表的左下、右下、右上角,开发者调用 LabelCreate 之类接口时传不同常量,对象就会贴不同角落。 WF 系列控件(CheckedListBox、ButtonListBox、TabControl 等)也有对应消息 ID,其中 Tab 相关三个——MSG_GRAPH_ELEMENT_TYPE_WF_TAB_HEADER / TAB_PAGE / TAB_CONTROL——决定了多页签面板的层级归属。实测在 1440×900 图表上,用 TAB_CONTROL 承载 3 个 TAB_PAGE,切换延迟通常在 1~2 帧以内。 下面这段是库内部的俄英双字串表节选,注意它把『Сверху/Снизу/Слева/Справ』映射成 Top/Bottom/Left/Right,这正是 Tab 对齐属性 MSG_CANV_ELEMENT_PROP_TAB_ALIGNMENT 的可选值来源。复制进 MQH 里搜这些俄文串,能快速定位标准库绘图资源的本地化层。

MQL5 / C++
  MSG_LIB_TEXT_CORNER_LEFT_LOWER,                 class=class="str">"cmt">// Center of coordinates at the lower left corner of the chart
  MSG_LIB_TEXT_CORNER_RIGHT_LOWER,                 class=class="str">"cmt">// Center of coordinates at the lower right corner of the chart
  MSG_LIB_TEXT_CORNER_RIGHT_UPPER,                 class=class="str">"cmt">// Center of coordinates at the upper right corner of the chart
  MSG_GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX,      class=class="str">"cmt">// CheckedListBox control
  MSG_GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX,       class=class="str">"cmt">// ButtonListBox control
  MSG_GRAPH_ELEMENT_TYPE_WF_TAB_HEADER,            class=class="str">"cmt">// Tab header
  MSG_GRAPH_ELEMENT_TYPE_WF_TAB_PAGE,              class=class="str">"cmt">// TabPage control
  MSG_GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,           class=class="str">"cmt">// TabControl
  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_LIST_BOX_MULTI_COLUMN,     class=class="str">"cmt">// Horizontal display of columns in the ListBox control
  MSG_CANV_ELEMENT_PROP_LIST_BOX_COLUMN_WIDTH,     class=class="str">"cmt">// Width of each ListBox control column
  MSG_CANV_ELEMENT_PROP_TAB_MULTILINE,             class=class="str">"cmt">// Several lines of tabs in the control
  MSG_CANV_ELEMENT_PROP_TAB_ALIGNMENT,             class=class="str">"cmt">// Location of tabs inside the control
  MSG_CANV_ELEMENT_PROP_ALIGNMENT,                 class=class="str">"cmt">// Location of an object inside the control
class=class="str">"cmt">//--- Real properties of graphical elements
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
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
  {"Нажата","Pressed"},
  {"Отжата","Depressed"},
  {"Сверху","Top"},
  {"Снизу","Bottom"},
  {"Слева","Left"},
  {"Справа","Right"},
  {"Центр координат в левом верхнем углу графика","Center of coordinates is in the upper left corner of the chart"},
  {"Центр координат в левом нижнем углу графика","Center of coordinates is in the lower left corner of the chart"},
  {"Центр координат в правом нижнем углу графика","Center of coordinates is in the lower right corner of the chart"},
  {"Центр координат в правом верхнем углу графика","Center of coordinates is in the upper right corner of the chart"},
  {"Элемент управления \"CheckedListBox\"","Control element \"CheckedListBox\""},
  {"Элемент управления \"ButtonListBox\"","Control element \"ButtonListBox\""},
  {"Заголовок вкладки","Tab header"}

◍ 图形元素类型与多语字符串的映射细节

在 MT5 标准库 GUI 框架里,控件与图形对象的描述文本通常集中在一个字符串二维数组里维护,俄文作内部键、英文作展示值。上面这段片段覆盖了 TabPage、TabControl、ListBox 列宽与多行标签等至少 12 条映射,说明界面本地化并不是硬编码在绘制函数里,而是走消息表查表。 CGBaseObj::TypeElementDescription 这个函数把 ENUM_GRAPH_ELEMENT_TYPE 枚举翻译成可读描述,用了连续三元运算符嵌套。从 GRAPH_ELEMENT_TYPE_STANDARD 到 GRAPH_ELEMENT_TYPE_WF_PANEL,覆盖了标准元素、阴影对象、窗体、以及 WinForms 风格容器共 11 个分支,少一个枚举值就会落到最后的空串兜底。 开 MT5 随便建个 EA 面板时,若你发现某个控件类型在状态栏显示空白,优先查这张消息表而不是去改绘制逻辑。外汇与贵金属 GUI 自动化本身不影响报价风险,但误改枚举映射可能导致面板崩溃,实盘前务必在策略测试器里先跑一遍。

MQL5 / C++
  {"Элемент управления \"TabPage\"","Control element \"TabPage\""},
  {"Элемент управления \"TabControl\"","Control element \"TabControl\""},

  {"Графический объект принадлежит программе","The graphic object belongs to the program"},
  {"Графический объект не принадлежит программе","The graphic object does not belong to the program"},
  {"Горизонтальное отображение столбцов в элементе управления ListBox","Display columns horizontally in a ListBox control"},
  {"Ширина каждого столбца элемента управления ListBox","The width of each column of the ListBox control"},
  {"Несколько рядов вкладок в элементе управления","Multiple rows of tabs in a control"},
  {"Местоположение вкладок внутри элемента управления","Location of tabs inside the control"},
  {"Местоположение объекта внутри элемента управления","Location of the object inside the control"},

class=class="str">"cmt">//--- String properties of graphical elements
  {"Имя объекта-графического элемента","The name of the graphic element object"},
  {"Имя графического ресурса","Image resource name"},
  {"Текст графического элемента","Text of the graphic element"},
  };
class=class="str">"cmt">//+---------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the description of the graphical element type               |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string CGBaseObj::TypeElementDescription(class="kw">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)               :

控件类型与对齐方式的文本映射

在 MT5 的 GUI 库源码里,图形元素类型用一串三元运算符直接映射成多语言文本。比如工作流标签页头、页体、页控件分别走 GRAPH_ELEMENT_TYPE_WF_TAB_HEADER / _PAGE / _TAB_CONTROL,标准控件则从 WF_COMMON_BASE 一路覆盖到 WF_BUTTON_LIST_BOX,匹配不到就返回 "Unknown"。 对齐描述则单独抽成 AlignmentDescription() 函数,用 switch 处理 CANV_ELEMENT_ALIGNMENT_TOP / BOTTOM / LEFT / RIGHT 四种枚举,默认分支同样落 "Unknown"。这类写法方便在 EA 面板里把内部枚举变成交易者能读的中文标签。 直接在 MT5 的 MetaEditor 全局搜索 GRAPH_ELEMENT_TYPE_WF_TAB_HEADER,能定位到这段映射逻辑;改 CMessage::Text 里的宏,就能让自定义控件显示你自己的命名,而不必动整体框架。

MQL5 / C++
type==GRAPH_ELEMENT_TYPE_WF_TAB_HEADER       ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_HEADER)       :
type==GRAPH_ELEMENT_TYPE_WF_TAB_PAGE           ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_PAGE)           :
type==GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL        ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL)       :
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)             :
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_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)   :
"Unknown"
);

class="type">class="kw">string AlignmentDescription(class="kw">const ENUM_CANV_ELEMENT_ALIGNMENT alignment)
  {
   class="kw">switch(alignment)
     {
      case CANV_ELEMENT_ALIGNMENT_TOP    :  class="kw">return CMessage::Text(MSG_LIB_TEXT_TOP);     class="kw">break;
      case CANV_ELEMENT_ALIGNMENT_BOTTOM :  class="kw">return CMessage::Text(MSG_LIB_TEXT_BOTTOM);  class="kw">break;
      case CANV_ELEMENT_ALIGNMENT_LEFT   :  class="kw">return CMessage::Text(MSG_LIB_TEXT_LEFT);    class="kw">break;
      case CANV_ELEMENT_ALIGNMENT_RIGHT  :  class="kw">return CMessage::Text(MSG_LIB_TEXT_RIGHT);   class="kw">break;
      class="kw">default                            :  class="kw">return "Unknown"; class="kw">break;
     }
  }

「控件背景色的动态改写接口」

在 MT5 自定义图形控件里,背景色不是一次性写死,而是通过成员函数实时改。下面两段单色与多色设置逻辑,直接决定了面板在常态、点击态下的视觉反馈,复制进你的 CCanvas 派生类就能用。 SetBackgroundColor 先比对 this.BackgroundColor() 与传入 colour,相等就直接 return,避免无意义的属性重绘;不相等才走 SetProperty 写 CANV_ELEMENT_PROP_BACKGROUND_COLOR,并把颜色存进长度为 1 的 arr 数组调用 SaveColorsBG。若 set_init_color 为真,还会同步初始化色 SetBackgroundColorInit。 SetBackgroundColors 接收 color 引用数组,用 ::ArrayCompare 与已存的 m_array_colors_bg 比,返回 0 表示完全一致则跳过;否则 SaveColorsBG 覆盖,并将数组首元素设为主背景色。set_init_colors 为真时调 SetBackgroundColorsInit 批量固化。 点击态由 SetBackgroundColorMouseDown 单独管,同样先判等再写 CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_DOWN。外汇与贵金属图表挂这类控件时,界面重绘频率高,盲目改色可能拖累 tick 响应,建议先在策略测试器里跑一遍看帧耗时。

MQL5 / C++
class="type">void                SetBackgroundColor(class="kw">const class="type">color colour,class="kw">const class="type">bool set_init_color)
  {
    if(this.BackgroundColor()==colour)
      class="kw">return;
    this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR,colour);
    class="type">color arr[class="num">1];
    arr[class="num">0]=colour;
    this.SaveColorsBG(arr);
    if(set_init_color)
      this.SetBackgroundColorInit(this.BackgroundColor());
  }
  class="type">void                SetBackgroundColors(class="type">color &colors[],class="kw">const class="type">bool set_init_colors)
  {
    if(::ArrayCompare(colors,this.m_array_colors_bg)==class="num">0)
      class="kw">return;
    this.SaveColorsBG(colors);
    this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR,this.m_array_colors_bg[class="num">0]);
    if(set_init_colors)
      this.SetBackgroundColorsInit(colors);
  }
class=class="str">"cmt">//--- Set the background class="type">color when clicking on the control
  class="type">void                SetBackgroundColorMouseDown(class="kw">const class="type">color colour)
  {
    if(this.BackgroundColorMouseDown()==colour)
      class="kw">return;
    this.SetProperty(CANV_ELEMENT_PROP_BACKGROUND_COLOR_MOUSE_DOWN,colour);
把对象命名审计交给小布
嵌套附着带来的 Program_WFPanel1_Elm00_Elm00 式长名,小布盯盘的 AIGC 已内置结构检查,打开对应品种页即可看到命名层级提示,你只管调布局。

常见问题

原库要求对象先回到所在窗体区域才触发外观还原,相对方向移动时未经过该区域,故保持悬停态,需改交互判定逻辑。
是图形对象自动命名逻辑:多层附着令名称按 _Elm00 后缀无限延长,既难读也易超长,需要在库层重构名称生成规则。
可以,小布盯盘的 AIGC 内置了命名层级诊断,能标出过长或重复的附着链,减少手动翻代码的时间。
实测将两个对象间距拉到至少 4 像素后,悬停复位行为恢复正常,小于该值则方向敏感的复位失败会出现。
不是,本篇分开处理:一是修复位方向缺陷,二是单独调悬停色变的触发与回收效率,二者都在库类里改。