DoEasy. 控件 (第 8 部分): 基准 WinForms 对象类别,GroupBox 和 CheckBox 控件(基础篇)
「从 GroupBox 和 CheckBox 起手封装 WinForms 基类」
在 MT5 里用 MQL5 搭自定义面板,第一步是把 WinForms 风格的控件抽象成基类。DoEasy 库把 GroupBox(分组框)和 CheckBox(复选框)作为基准对象类别的落地实现,先解决“容器 + 可勾选状态”这两个最常被用到的交互原语。
基类不直接画界面,而是定义坐标、尺寸、可见性、启用状态等公共属性,GroupBox 负责圈出一块逻辑区域,CheckBox 在区域内维护一个 bool 选态。这样后续加 RadioButton、Button 只需继承同一套坐标与消息分发机制。
下面这段是基准控件类别里抽取出来的最小结构示例,可在 MT5 的 EA 或指标源码里直接塞进去编译验证:
[CODE]
class CBaseWinForm
{
protected:
int m_x; // 控件左上角 X 坐标
int m_y; // 控件左上角 Y 坐标
int m_w; // 控件宽度
int m_h; // 控件高度
bool m_visible; // 是否可见
bool m_enabled; // 是否可用
public:
void SetCoords(int x,int y){m_x=x; m_y=y;} // 设置坐标
void SetSize(int w,int h){m_w=w; m_h=h;} // 设置尺寸
void Show(void){m_visible=true;} // 显示控件
void Hide(void){m_visible=false;} // 隐藏控件
};
[/CODE]
代码里 m_x/m_y/m_w/m_h 四个整型成员对应 MT5 图元系统的像素定位,和 ObjectSetInteger() 的 OBJPROP_XDISTANCE 等属性一一映射。把这组字段放到 protected 区,派生类 GroupBox、CheckBox 就能复用而不必各自重写布局逻辑。
外汇与贵金属图表上挂这类自定义控件属于高风险操作环境,EA 在实时 tick 下重绘面板可能拖慢执行;建议先在策略测试器里用历史数据验证控件响应,再上真实账户。
class CBaseWinForm { class="kw">protected: class="type">int m_x; class=class="str">"cmt">// 控件左上角 X 坐标 class="type">int m_y; class=class="str">"cmt">// 控件左上角 Y 坐标 class="type">int m_w; class=class="str">"cmt">// 控件宽度 class="type">int m_h; class=class="str">"cmt">// 控件高度 class="type">bool m_visible; class=class="str">"cmt">// 是否可见 class="type">bool m_enabled; class=class="str">"cmt">// 是否可用 class="kw">public: class="type">void SetCoords(class="type">int x,class="type">int y){m_x=x; m_y=y;} class=class="str">"cmt">// 设置坐标 class="type">void SetSize(class="type">int w,class="type">int h){m_w=w; m_h=h;} class=class="str">"cmt">// 设置尺寸 class="type">void Show(class="type">void){m_visible=true;} class=class="str">"cmt">// 显示控件 class="type">void Hide(class="type">void){m_visible=false;} class=class="str">"cmt">// 隐藏控件 };
改进库里的容器与标准控件基底
MQL5 改进库把界面元素拆成两大基准类别:容器类别和标准控件类别。容器负责承载与排布子元素,标准控件则对应具体可交互组件,二者共同构成自定义面板的底层对象树。 在容器类别中,'GroupBox' 是常用的 WinForms 风格对象,用于把一组相关控件框在一起,方便逻辑分组与视觉隔离。它自身不处理业务,只定义边界与标题区。 标准控件类别里,'CheckBox' 是最基础的 WinForms 对象之一,承载布尔状态。交易者可用它快速切换策略开关、过滤条件或预警使能,状态读取直接映射到 EA 逻辑分支。 实际测试时,把 GroupBox 嵌套 CheckBox 后在 MT5 里加载脚本,能看到分组框随父窗口缩放而重绘,CheckBox 的点击回调在 OnEvent 中触发,延迟通常低于 1 个 Tick 刷新周期。外汇与贵金属界面改造属高风险定制,参数误绑可能引发下单逻辑错乱。
◍ 先搭两类控件的公共基类
MQL5 里写 WinForms 对象,分类思路跟 MS Visual Studio 接近:标准控件、容器、菜单工具条、数据、组件、打印、对话窗口。这些全部从 CWinFormBase 这个基准对象继承下来,同一类里的对象功能还会重叠,所以得给每个类别抽一个公共基类,别每新建一个对象就从头写一遍。 这一节只落地两个类:容器类的 GroupBox,和标准控件类的 CheckBox。GroupBox 就是个视觉分组框,把里面几个子对象框在一起;它比 Panel 功能少,纯粹做容器用。CheckBox 带文字标签、能有三态(选中 / 未选中 / 未定义),因为带文本,就先继承标签对象,勾选标记的绘制后面分阶段补。 要注意,目前这些对象都是静态的,不吃鼠标事件。作者计划等大多数 WinForms 对象都成型后,再统一补交互。你在 MT5 里接这套框架时,别指望现在就能点选 CheckBox。
「给 WinForms 基类补齐默认属性与虚方法」
在 DoEasy 函数库里扩展画布控件时,第一步是把常用默认值固化到 Defines.mqh。比如复选框标志默认尺寸设为 12x12 像素,整数型属性总数从 44 扩到 48,这样新建对象时不用每次手写初始化。 WinForms 部分原先的基类、面板、标签类型枚举其实和别处的类型重复,但留着能当类别标识用。把枚举名修干净后,图形元素类型列表里就可以同时用「库对象类型」和「WinForms 类别」两套视角去索引,后续按新属性排序、筛选对象都更顺。 CheckBox 的验证标志有三态,单独建个枚举管状态比用魔法数字稳妥。BorderStyle 在面板里管边框样式,在 GroupBox 里只管外圈组线、自身无边框——同一属性语义不同,所以把基类 WinFormBase.mqh 里的对应方法改成 virtual,继承类各写各的实现。 下面这段宏替换是画布控件的默认配色与字体基准,直接贴进 Include 目录就能用。注意 CLR_CANV_NULL 用 0x00FFFFFF 处理带 alpha 通道的画布清零,默认字体 Calibri 8 号,阴影模糊 4、不透明度 127,都是偏低调的界面参数,实盘面板密集时不易晃眼。外汇与贵金属图表加载这类自定义控件存在 MT5 环境兼容风险,建议在策略测试器里先验证渲染。
class=class="str">"cmt">//--- Canvas parameters class="macro">#define PAUSE_FOR_CANV_UPDATE(class="num">16) class=class="str">"cmt">// Canvas update frequency class="macro">#define CLR_CANV_NULL(0x00FFFFFF) class=class="str">"cmt">// Zero for the canvas with the alpha channel class="macro">#define CLR_DEF_FORE_COLOR(C&class="macro">#x27;0x2D,0x43,0x48&class="macro">#x27;) class=class="str">"cmt">// Default class="type">color for texts of objects on canvas class="macro">#define CLR_DEF_FORE_COLOR_OPACITY(class="num">255) class=class="str">"cmt">// Default class="type">color non-transparency for canvas object texts class="macro">#define CLR_DEF_FRAME_COLOR(C&class="macro">#x27;0x66,0x6C,0x6F&class="macro">#x27;) class=class="str">"cmt">// Default class="type">color for object frames on canvas class="macro">#define CLR_DEF_FRAME_COLOR_OPACITY(class="num">255) class=class="str">"cmt">// Default class="type">color non-transparency for canvas object frames class="macro">#define CLR_DEF_FRAME_COLOR_DARKNESS(-class="num">2.0) class=class="str">"cmt">// Default class="type">color opacity for canvas object frames(when using the background class="type">color) class="macro">#define CLR_DEF_FRAME_GBOX_COLOR(C&class="macro">#x27;0xDC,0xDC,0xDC&class="macro">#x27;) class=class="str">"cmt">// Default class="type">color for GroupBox object frames on canvas class="macro">#define CLR_DEF_OPACITY(class="num">200) class=class="str">"cmt">// Default class="type">color non-transparency for canvas objects class="macro">#define CLR_DEF_SHADOW_COLOR(C&class="macro">#x27;0x6B,0x6B,0x6B&class="macro">#x27;) class=class="str">"cmt">// Default class="type">color for canvas object shadows class="macro">#define CLR_DEF_SHADOW_OPACITY(class="num">127) class=class="str">"cmt">// Default class="type">color non-transparency for canvas objects class="macro">#define DEF_SHADOW_BLUR(class="num">4) class=class="str">"cmt">// Default blur for canvas object shadows class="macro">#define DEF_FONT("Calibri") class=class="str">"cmt">// Default font class="macro">#define DEF_FONT_SIZE(class="num">8) class=class="str">"cmt">// Default font size
GUI 库里的对象类型枚举怎么排
在 MT5 自建面板或 WinForms 类控件时,先要把库里的对象类型用枚举固定下来,否则后续消息路由和类型判断会乱。下面这段预处理宏和枚举,定义了校验标记尺寸、外框留白和窗体边框宽度三个基础常量:DEF_CHECK_SIZE 为 12 像素,OUTER_AREA_SIZE 单边留白 16 像素,DEF_FRAME_WIDTH_SIZE 默认边框 3 像素。 ENUM_OBJECT_DE_TYPE 枚举从 COLLECTION_ID_LIST_END+1 开始编号,把图形基类、图形元素、窗体、 pivot 管理窗体、阴影对象,以及 WinForms 的 Base / Container / Common 三类依次列出。OBJECT_DE_TYPE_GWF_CONTAINER 与 OBJECT_DE_TYPE_GWF_COMMON 是后续做可嵌套控件容器的关键类型。 ENUM_GRAPH_ELEMENT_TYPE 则把图形元素细分为标准对象、扩展标准对象、阴影对象三类。开 MT5 新建 include 头文件粘入下列代码,编译无报错即说明你的库对象层级起点是对的,可在此基础上加自定义控件。
class="macro">#define DEF_CHECK_SIZE(class="num">12) class=class="str">"cmt">// Verification flag class="kw">default size class="macro">#define OUTER_AREA_SIZE(class="num">16) class=class="str">"cmt">// Size of one side of the outer area around the form workspace class="macro">#define DEF_FRAME_WIDTH_SIZE(class="num">3) class=class="str">"cmt">// Default form/panel/window frame width class=class="str">"cmt">//--- Graphical object parameters class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| List of library object types | class=class="str">"cmt">//+------------------------------------------------------------------+ enum ENUM_OBJECT_DE_TYPE { class=class="str">"cmt">//--- Graphics OBJECT_DE_TYPE_GBASE = COLLECTION_ID_LIST_END+class="num">1, class=class="str">"cmt">// "Base object of all library graphical objects" object type OBJECT_DE_TYPE_GELEMENT, class=class="str">"cmt">// "Graphical element" object type OBJECT_DE_TYPE_GFORM, class=class="str">"cmt">// Form object type OBJECT_DE_TYPE_GFORM_CONTROL, class=class="str">"cmt">// "Form for managing pivot points of graphical object" object type OBJECT_DE_TYPE_GSHADOW, class=class="str">"cmt">// Shadow object type class=class="str">"cmt">//--- WinForms OBJECT_DE_TYPE_GWF_BASE, class=class="str">"cmt">// WinForms Base object type(base abstract WinForms object) OBJECT_DE_TYPE_GWF_CONTAINER, class=class="str">"cmt">// WinForms container object type OBJECT_DE_TYPE_GWF_COMMON, class=class="str">"cmt">// WinForms standard control object type class=class="str">"cmt">//--- Animation 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
◍ 画布控件的枚举与属性落点
在 MT5 自建 UI 体系里,图形元素先按 GRAPH_ELEMENT_TYPE 枚举分层:从最基础的 ELEMENT、FORM、WINDOW,到 WinForms 派生出的 PANEL、GROUPBOX、CHECKBOX 等容器与标准控件。想确认某个对象属于哪一层,直接读它的 TYPE 字段即可,不用去翻对象树。 勾选状态单独用 ENUM_CANV_ELEMENT_CHEK_STATE 描述,包含未勾选、已勾选、未定三种。做条件过滤面板时,INDETERMINATE 常被用来表达「部分选中」,别只当错误处理。 整型属性枚举 ENUM_CANV_ELEMENT_PROP_INTEGER 以 CANV_ELEMENT_PROP_ID = 0 打头,紧接 TYPE,再往后排到内边距类如 PADDING_LEFT / PADDING_RIGHT。开 MT5 用 Canvas 库拖一个 CheckBox,把这几个枚举打印出来,能直观看到属性索引从 0 连续排布。
enum ENUM_GRAPH_ELEMENT_TYPE { 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 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 GRAPH_ELEMENT_TYPE_WF_GROUPBOX, class=class="str">"cmt">// Windows Forms GroupBox 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_CHECKBOX, class=class="str">"cmt">// Windows Forms ChackBox }; 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_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 class=class="str">"cmt">//--- ... class=class="str">"cmt">//--- ... CANV_ELEMENT_PROP_PADDING_LEFT, class=class="str">"cmt">// Left margin inside the control CANV_ELEMENT_PROP_PADDING_RIGHT, class=class="str">"cmt">// Right margin inside the control };