DoEasy. 控件(第 4 部分):面板控件,Padding(填充)和 Dock(驻靠)参数(基础篇)
◍ 面板控件的填充与驻靠参数怎么用
在 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 分钟图挂脚本验证背景渐变与面板拖动是否如预期,这类图形库调整属低风险代码层改动,但策略逻辑误用仍可能导致实盘亏损。
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。 别把正态当圣经:枚举顺序和数组列序必须严格对齐,插一列就全乱。改风格时先调数组里的整数,再回头看枚举注释,能省掉一半界面错位调试。
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 终端响应。
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_ 宏就能定位是哪一步资源分配崩了,而不是盲目重试。
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 };