DoEasy. 控件(第 4 部分):面板控件,Padding(填充)和 Dock(驻靠)参数(基础篇)
📘

DoEasy. 控件(第 4 部分):面板控件,Padding(填充)和 Dock(驻靠)参数(基础篇)

第 1/3 篇

◍ 面板控件的填充与驻靠参数怎么用

在 MT5 自建图形面板时,Padding(填充)和 Dock(驻靠)是两个决定控件布局行为的底层参数。Padding 控制控件内部边距,Dock 决定控件相对父容器的对齐与拉伸方式,二者共同影响面板在窗口缩放时的重绘逻辑。 以 DoEasy 库为例,其面板类在 2022-07-04 发布的第 4 部分示例中,已将对齐与内边距封装进基础控件结构,开发者无需每次手动计算坐标。实际调试时,把 Dock 设为全填充、Padding 设为 5~10 像素,能避免子元素贴边导致文本被截断。 外汇与贵金属图表加载这类自定义面板存在平台兼容性风险,建议先在 EURUSD 的 M1 周期挂测试面板,观察拖动窗口时控件是否错位,再决定是否用于实盘辅助。

「面板容器的 Padding 与 Dock 定位逻辑」

WinForm 里的 Panel 本质是个容器,能在里面塞别的 WinForm 对象。放子对象时你可以手写坐标定点,也可以靠 Dock 属性让对象自动贴边或填充。Dock 有六种绑定方式:贴上边沿宽度拉伸、贴下边沿宽度拉伸、贴左边沿高度拉伸、贴右边沿高度拉伸、全容器拉伸填充、以及不绑定只按原坐标原尺寸放置。 一旦选了贴边或填充,就要看容器的 Padding 值。Padding 决定子对象边界离容器边界的距离,不是直接贴死边。若容器内叠了多个同侧 Dock 对象,后放的不会粘到 Padding 处的容器边,而是粘到同侧前一个对象的边。 我在单对象容器里把六种 Dock 选项全实现了一遍,并给面板加了一个“参考底图”对象,它按 Padding 值整体平移。之后画任何东西都落在这张底图上,不用再手动算坐标和尺寸。 对外汇贵金属 MT5 自定义面板开发来说,这种按 Padding 自动排布能省掉大量硬算坐标的麻烦,但 EA/指标面板改 Dock 逻辑后务必在 MT5 里实跑验证,GUI 布局错误可能导致控件不可见。MT5 脚本开发本身不影响交易,但误用自动布局拖慢面板响应在高频盯盘时是高概率风险点。

给窗体库补上渐变与层级绑定能力

DoEasy 图形库原先只支持窗体单色背景,且对象绑定容器的边界枚举把「未绑定」常数放在列表末尾,判断起来很别扭。这次改动把样式参数从 9 个扩到 11 个,并在 Defines.mqh 里把「绑定到容器边界类型缺失」常数挪到枚举首位、赋 0 值,等价于布尔 false,后续直接用返回方法判空即可。 GCnvElement 类新增了渐变填充颜色数组与相关存取方法:SetColorBackground() 现在不仅写对象属性,还会调 SaveColorsBG() 把单色塞进数组;SetColorsBackground() 接收颜色数组,首色作背景、余色作渐变。返回颜色的方法里,数组长为 0 时退回到 m_color_bg 变量,索引越界则返回末色——这一套让单色和渐变用同一接口就能处理。 层级附着带来一个新概念:主对象。一个面板里挂两个 WinForm,面板是它们的基准容器;当这个面板再挂到外层面板,外层就成了主对象。类里加了「整个层次结构主对象」指针,嵌套对象据此同时知道自己的基准容器和顶层主对象,移动父对象时坐标追踪不再乱。 Panel 类把参考底图对象(padding 区域内精准贴合的 GraphElement)正式纳入:设置 Dock 模式、四边距、边框宽度时,立刻同步参考底图属性。以前漏写的面板可移动性标志、边框浮雕类型也补上了,否则重绘时边框会被忽略。 GraphElementsCollection 里所有建窗体/面板的方法,把传「数组首色」改成传整个渐变数组;测试时往 ZOrder 调整方法里插了一段临时代码,把绑定面板的子对象 ID 和 ZOrder 打印出来,确认分配无误后便会移除。 涉及外汇/贵金属的 EA 界面开发同样受 MT5 对象模型限制,改完请于 MetaEditor 编译并在 EURUSD 15 分钟图挂脚本验证背景渐变与面板拖动是否如预期,这类图形库调整属低风险代码层改动,但策略逻辑误用仍可能导致实盘亏损。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| List of form style parameter indices                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_FORM_STYLE_PARAMS
  {

◍ 表单样式参数的枚举与数组落地

在 MT5 自定义控件库里,表单视觉风格被拆成一组枚举常量,覆盖 CForm 与 CPanel 两个层级。CForm 管阴影与渐变:透明度、模糊半径、暗化色、XY 偏移,以及垂直/循环渐变开关;CPanel 则单独定义左、右、上、下四个边框宽度。 这些常量最终被收进一个二维数组 array_form_style,由宏 TOTAL_FORM_STYLE_PARAMS 锁定为 11 列,即每种风格恰好 11 个数值参数。下面这段「Flat form」的首组实测数据可直接抄进 MT5 验证:阴影透明度 80、模糊 4、暗化 80、XY 偏移各 2,两个渐变标志均为 false。 别把正态当圣经:枚举顺序和数组列序必须严格对齐,插一列就全乱。改风格时先调数组里的整数,再回头看枚举注释,能省掉一半界面错位调试。

MQL5 / C++
class=class="str">"cmt">//--- CForm
FORM_STYLE_FRAME_SHADOW_OPACITY,           class=class="str">"cmt">// Shadow opacity
FORM_STYLE_FRAME_SHADOW_BLUR,               class=class="str">"cmt">// Shadow blur
FORM_STYLE_DARKENING_COLOR_FOR_SHADOW,      class=class="str">"cmt">// Form shadow class="type">class="kw">color darkening
FORM_STYLE_FRAME_SHADOW_X_SHIFT,            class=class="str">"cmt">// Shadow X axis shift
FORM_STYLE_FRAME_SHADOW_Y_SHIFT,            class=class="str">"cmt">// Shadow Y axis shift
FORM_STYLE_GRADIENT_V,                      class=class="str">"cmt">// Vertical gradient filling flag
FORM_STYLE_GRADIENT_C,                      class=class="str">"cmt">// Cyclic gradient filling flag
class=class="str">"cmt">//--- CPanel
FORM_STYLE_FRAME_WIDTH_LEFT,                class=class="str">"cmt">// Panel frame width to the left
FORM_STYLE_FRAME_WIDTH_RIGHT,               class=class="str">"cmt">// Panel frame width to the right
FORM_STYLE_FRAME_WIDTH_TOP,                 class=class="str">"cmt">// Panel frame width on top
FORM_STYLE_FRAME_WIDTH_BOTTOM,              class=class="str">"cmt">// Panel frame width below
};
class="macro">#define TOTAL_FORM_STYLE_PARAMS(class="num">11)    class=class="str">"cmt">// Number of form style parameters
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Array containing form style parameters                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int array_form_style[TOTAL_FORM_STYLES][TOTAL_FORM_STYLE_PARAMS]=
  {
class=class="str">"cmt">//--- "Flat form" style parameters
   {
   class=class="str">"cmt">//--- CForm
   class="num">80,                                       class=class="str">"cmt">// Shadow opacity
   class="num">4,                                        class=class="str">"cmt">// Shadow blur
   class="num">80,                                       class=class="str">"cmt">// Form shadow class="type">class="kw">color darkening
   class="num">2,                                        class=class="str">"cmt">// Shadow X axis shift
   class="num">2,                                        class=class="str">"cmt">// Shadow Y axis shift
   class="kw">false,                                    class=class="str">"cmt">// Vertical gradient filling flag
   class="kw">false,                                    class=class="str">"cmt">// Cyclic gradient filling flag
   class=class="str">"cmt">//--- CPanel

「浮雕样式下的面板边框与阴影参数」

在 MT5 自定义控件的样式枚举里,浮雕(Embossed)风格用一组固定顺序的数值控制面板外框与投影。CPanel 的四边边框宽度都设为 3 像素,左、右、上、下均一致,意味着面板边缘是等宽细线,不会因方向产生视觉偏移。 CForm 部分的阴影参数更值得盯:阴影不透明度 80、模糊半径 4、暗化量 80,X/Y 轴偏移各为 2。这组值让浮层在图表上呈现轻微右下投影像素位移,立体感来自 2 像素错位而非大范围羽化。 垂直渐变填充标记为 true、循环渐变标记为 false,说明背景只做单向由上至下过渡。若你在 EA 面板里觉得立体感太弱,优先把 Shadow Y axis shift 从 2 调到 3~4,比改模糊半径更见效。外汇与贵金属图表加载此类图形界面时需注意,过度渲染可能拖慢老机型 MT5 终端响应。

MQL5 / C++
class="num">3,                                                                       class=class="str">"cmt">// Panel frame width to the left
class="num">3,                                                                       class=class="str">"cmt">// Panel frame width to the right
class="num">3,                                                                       class=class="str">"cmt">// Panel frame width on top
class="num">3,                                                                       class=class="str">"cmt">// Panel frame width below
 },
class=class="str">"cmt">//--- "Embossed form" style parameters
  {
    class=class="str">"cmt">//--- CForm
    class="num">80,                                                                   class=class="str">"cmt">// Shadow opacity
    class="num">4,                                                                   class=class="str">"cmt">// Shadow blur
    class="num">80,                                                                   class=class="str">"cmt">// Form shadow class="type">class="kw">color darkening
    class="num">2,                                                                   class=class="str">"cmt">// Shadow X axis shift
    class="num">2,                                                                   class=class="str">"cmt">// Shadow Y axis shift
    true,                                                                class=class="str">"cmt">// Vertical gradient filling flag
    class="kw">false,                                                               class=class="str">"cmt">// Cyclic gradient filling flag
    class=class="str">"cmt">//--- CPanel
    class="num">3,                                                                   class=class="str">"cmt">// Panel frame width to the left
    class="num">3,                                                                   class=class="str">"cmt">// Panel frame width to the right
    class="num">3,                                                                   class=class="str">"cmt">// Panel frame width on top
    class="num">3,                                                                   class=class="str">"cmt">// Panel frame width below
  },
  };

停靠模式与报错枚举的底层定义

在自绘面板库里,元素怎么贴边由 ENUM_CANV_ELEMENT_DOCK_MODE 控制。NONE 是绝对坐标定位且尺寸锁死;TOP/BOTTOM 贴上下边并随容器宽度拉伸;LEFT/RIGHT 贴左右边并随高度拉伸;FILL 则是宽高全铺满。 报错枚举暴露了资源操作的薄弱点。比如 MSG_LIB_SYS_FAILED_ARRAY_COPY 表示数组拷贝失败,MSG_CANV_ELEMENT_ERR_FAILED_SET_WIDTH 和 _HEIGHT 说明画布尺寸设定可能在某些设备上下文下返回失败,MSG_PANEL_OBJECT_ERR_FAILED_CREATE_UNDERLAY_OBJ 则指向底板对象创建这一环容易掉链子。 这些常量直接决定了你在 MT5 里调 GUI 时的容错分支。开 MT5 把下面枚举贴进头文件,搜对应 MSG_ 宏就能定位是哪一步资源分配崩了,而不是盲目重试。

MQL5 / C++
enum ENUM_CANV_ELEMENT_DOCK_MODE
  {
   CANV_ELEMENT_DOCK_MODE_NONE,                 class=class="str">"cmt">// Attached to the specified coordinates, size does not change
   CANV_ELEMENT_DOCK_MODE_TOP,                  class=class="str">"cmt">// Attaching to the top and stretching along the container width
   CANV_ELEMENT_DOCK_MODE_BOTTOM,               class=class="str">"cmt">// Attaching to the bottom and stretching along the container width
   CANV_ELEMENT_DOCK_MODE_LEFT,                 class=class="str">"cmt">// Attaching to the left and stretching along the container height
   CANV_ELEMENT_DOCK_MODE_RIGHT,                class=class="str">"cmt">// Attaching to the right and stretching along the container height
   CANV_ELEMENT_DOCK_MODE_FILL,                 class=class="str">"cmt">// Stretching along the entire container width and height
   };
   MSG_LIB_SYS_FAILED_COLORS_ARRAY_RESIZE,      class=class="str">"cmt">// Failed to change the class="type">class="kw">color array size
   MSG_LIB_SYS_FAILED_ARRAY_RESIZE,             class=class="str">"cmt">// Failed to change the array size
   MSG_LIB_SYS_FAILED_ARRAY_COPY,               class=class="str">"cmt">// Failed to copy the array
   MSG_LIB_SYS_FAILED_ADD_BUFFER,               class=class="str">"cmt">// Failed to add buffer object to the list
   MSG_LIB_SYS_FAILED_CREATE_BUFFER_OBJ,        class=class="str">"cmt">// Failed to create "Indicator buffer" object
class=class="str">"cmt">//--- CGCnvElement
   MSG_CANV_ELEMENT_ERR_EMPTY_ARRAY,            class=class="str">"cmt">// Error! Empty array
   MSG_CANV_ELEMENT_ERR_ARRAYS_NOT_MATCH,       class=class="str">"cmt">// Error! Array-copy of the resource does not match the original
   MSG_CANV_ELEMENT_ERR_FAILED_SET_WIDTH,       class=class="str">"cmt">// Error! Failed to set the canvas width
   MSG_CANV_ELEMENT_ERR_FAILED_SET_HEIGHT,      class=class="str">"cmt">// Error! Failed to set the canvas height
class=class="str">"cmt">//--- CGStdGraphObjExtToolkit
   MSG_GRAPH_OBJ_EXT_FAILED_ARR_RESIZE_TIME_DATA,   class=class="str">"cmt">// Failed to change the size of the pivot point time data array
   MSG_GRAPH_OBJ_EXT_FAILED_ARR_RESIZE_PRICE_DATA,  class=class="str">"cmt">// Failed to change the size of the pivot point price data array
   MSG_GRAPH_OBJ_EXT_FAILED_CREATE_CTRL_POINT_FORM, class=class="str">"cmt">// Failed to create a form object to manage a pivot point
class=class="str">"cmt">//--- CPanel
   MSG_PANEL_OBJECT_ERR_FAILED_CREATE_UNDERLAY_OBJ, class=class="str">"cmt">// Failed to create the underlay object
   };

常见问题

给面板容器设 Padding 参数,指定上下左右内边距,子控件布局会自动避开这块区域。
用 Dock 驻靠参数设为右停靠,面板会绑定父容器右侧并随其尺寸变化自动贴边。
可以,小布能读取你的面板配置并标出停靠与填充叠加导致的布局异常,省去手动排查。
改边框宽度、阴影偏移与浮雕深度这几个枚举参数,数值调大立体感会明显增强。
多是停靠枚举越界或父容器未初始化,直接看报错枚举的底层定义就能定位具体错误码。