图形界面 X: 时间控件, 复选框列表控件和表格排序 (集成编译 6)(基础篇)
📘

图形界面 X: 时间控件, 复选框列表控件和表格排序 (集成编译 6)(基础篇)

第 1/3 篇

给 MT5 面板加上时间选择器和可勾选清单

在 MT5 自定义图形界面里,时间控件和复选框列表是两个常被忽略但极实用的交互元件。时间控件让用户在面板内直接选日期时间,避免来回切图表周期;复选框列表则适合做多品种、多指标开关的批量管理。 实现上通常封装成独立类。时间控件类负责绘制时钟图标、响应点击弹出日历并回写所选值;复选框列表类维护一个条目数组,每条带选中态,点击即翻转并触发父窗口重绘。 一个可验证的落点是:在 2017-02-13 发布的集成编译 6 示例中,这类控件已随函数库更新放出,原示例应用显示面板可正常响应时间选取与列表勾选。外汇与贵金属交易界面自动化高风险,参数误触可能下错单,建议先在策略测试器里跑通再挂实盘。 要验证,直接开 MT5 新建 EA 面板工程,把时间控件类挂到 CAppDialog 派生窗体,编译后看日历弹层是否跟随鼠标定位。

「这套界面库现在能做什么」

这一代函数库在上一版基础上继续扩张,核心新增了两块能力:时间控件和复选框列表控件,相当于把表单类交互补齐了一半。 CTable 类现在支持按列做升序或降序排序,这意味着你用表格呈现报价或信号日志时,不必再靠外部脚本重排,直接在控件内点列头就能切顺序。 完整库文件按归档目录结构放到同一层文件夹即可被 MT5 直接引用;每章文末都挂着当前最新阶段的库下载入口和已发布章节索引,想追进度直接从那里取压缩包。 外汇与贵金属品种波动剧烈,拿这套 UI 做盯盘面板时,仍要留好数据延迟和断线重连的余地,别默认它实时无丢帧。

◍ MT5 界面里的时间范围怎么选

在 MT5 给指标或智能系统做图形界面时,日内交易场景常需要让用户直接指定小时和分钟。系统自带的日历和下拉日历只能选日期,管不到具体时刻,所以得自己拼一个时间控件。 时间控件的视觉组成很固定:一块背景底板、一个时钟图标、一行描述文字,再加两个编辑框分别收小时和分钟。实际渲染出来就是背景托底,图标在左,描述在上或旁,两个输入框并排承接数值。 从类结构看,这个控件是把上述元素封装成一个可复用对象,外部调用时只需关心两个编辑框的回读值。想验证的话,开 MT5 新建一个空 EA 面板,按背景+图标+双编辑框的层级挂上去,就能在策略测试器里看到它和日历控件互不冲突。外汇与贵金属波动大,这类界面仅作参数输入辅助,不构成任何方向判断。

自绘时间输入控件的类结构

在 MT5 自定义面板里做时间输入,CTimeEdit 这个类把背景、图标、标签和编辑框全打包了。它继承自 CElement,所以拥有函数库引擎里标准控件那套容器方法,但对外暴露的属性足够你改皮肤:背景色、激活/阻塞两套图标、x/y 方向边距、说明文本、标签与各状态文字色、编辑框宽度,以及控件可用状态和数值重置模式。 类里 private 段先声明了这些可定制字段,比如 m_area_color 管背景,m_icon_file_on/off 管两种状态图标,m_edit_x_size 决定编辑框像素宽。public 段用一堆单行 setter 暴露出来:AreaColor() 改背景,IconXGap()/IconYGap() 调图标边距,LabelText() 重载了读写两种用法,LabelColorHover() 专门管鼠标悬停时的标签色。 时间控件是复合件,实际由 CRectLabel 背景、CBmpLabel 图标、CLabel 标签加两个 CSpinEdit(小时、分钟)拼成。CreateTimeEdit() 是总入口,内部再调 CreateArea/CreateIcon/CreateLabel/CreateHoursEdit/CreateMinutesEdit 五个 private 方法逐个建子控件。 想用代码读写当前值很简单:GetHours()、GetMinutes() 直接拿 int,SetHours(uint)、SetMinutes(uint) 调子控件的 ChangeValue 去改。外汇和贵金属图表挂这类面板属于高风险环境,参数误写可能让 EA 逻辑跑偏,上实盘前务必在策略测试器里先验证。

MQL5 / C++
class CTimeEdit : class="kw">public CElement
{
class="kw">private :
class=class="str">"cmt">//--- 控件背景颜色
class="type">color              m_area_color;
class=class="str">"cmt">//--- 控件激活和阻塞状态的图标
class="type">class="kw">string             m_icon_file_on;
class="type">class="kw">string             m_icon_file_off;
class=class="str">"cmt">//--- 图表空余
class="type">int                m_icon_x_gap;
class="type">int                m_icon_y_gap;
class=class="str">"cmt">//--- 控件的说明文本
class="type">class="kw">string             m_label_text;
class=class="str">"cmt">//--- 文本标签空余
class="type">int                m_label_x_gap;
class="type">int                m_label_y_gap;
class=class="str">"cmt">//--- 文本在不同状态下的颜色
class="type">color              m_label_color;
class="type">color              m_label_color_hover;
class="type">color              m_label_color_locked;
class="type">color              m_label_color_array[];
class=class="str">"cmt">//--- Size of the Edit box
class="type">int                m_edit_x_size;
class=class="str">"cmt">//--- 编辑框空余
class="type">int                m_edit_x_gap;
class="type">int                m_edit_y_gap;
class=class="str">"cmt">//--- 控件状态 (可用/阻塞)
class="type">bool               m_time_edit_state;
class=class="str">"cmt">//--- 数值重置的模式
class="type">bool               m_reset_mode;
class=class="str">"cmt">//---
class="kw">public :
class=class="str">"cmt">//--- (class="num">1) 背景颜色, (class="num">2) 图表空余
class="type">void               AreaColor( class="kw">const class="type">color clr)                     { m_area_color=clr;                  }
class="type">void               IconXGap( class="kw">const class="type">int x_gap)                      { m_icon_x_gap=x_gap;                }
class="type">void               IconYGap( class="kw">const class="type">int y_gap)                      { m_icon_y_gap=y_gap;                }
class=class="str">"cmt">//--- (class="num">1) 控件的说明文本, (class="num">2) 文本标签空余
class="type">class="kw">string             LabelText( class="type">void )                           class="kw">const { class="kw">return (m_label.Description());     }
class="type">void               LabelText( class="kw">const class="type">class="kw">string text)                   { m_label.Description(text);         }
class="type">void               LabelXGap( class="kw">const class="type">int x_gap)                     { m_label_x_gap=x_gap;               }
class="type">void               LabelYGap( class="kw">const class="type">int y_gap)                     { m_label_y_gap=y_gap;               }
class=class="str">"cmt">//--- 文本标签在不同状态下的颜色
class="type">void               LabelColor( class="kw">const class="type">color clr)                    { m_label_color=clr;                 }
class="type">void               LabelColorHover( class="kw">const class="type">color clr)               { m_label_color_hover=clr;           }
class="type">void               LabelColorLocked( class="kw">const class="type">color clr)              { m_label_color_locked=clr;          }
class=class="str">"cmt">//--- (class="num">1) 编辑框大小, (class="num">2) 编辑框空余
class="type">void               EditXSize( class="kw">const class="type">int x_size)                    { m_edit_x_size=x_size;              }
class="type">void               EditXGap( class="kw">const class="type">int x_gap)                      { m_edit_x_gap=x_gap;                }
class="type">void               EditYGap( class="kw">const class="type">int y_gap)                      { m_edit_y_gap=y_gap;                }
class=class="str">"cmt">//--- (class="num">1) 当按下文本标签时的重置模式, (class="num">2) 文本选择模式
class="type">bool               ResetMode( class="type">void )                                { class="kw">return (m_reset_mode);              }
class="type">void               ResetMode( class="kw">const class="type">bool mode)                     { m_reset_mode=mode;                 }
};

class CTimeEdit : class="kw">public CElement
{
class="kw">private :
class=class="str">"cmt">//--- 创建控件对象
CRectLabel        m_area;
CBmpLabel         m_icon;
CLabel            m_label;
CSpinEdit         m_hours;
CSpinEdit         m_minutes;
class=class="str">"cmt">//---
class="kw">public :
class=class="str">"cmt">//--- 创建控件方法
class="type">bool               CreateTimeEdit( class="kw">const class="type">long chart_id, class="kw">const class="type">int subwin, class="kw">const class="type">class="kw">string label_text, class="kw">const class="type">int x_gap, class="kw">const class="type">int y_gap);
class=class="str">"cmt">//---
class="kw">private :
class="type">bool               CreateArea( class="type">void );
class="type">bool               CreateIcon( class="type">void );
class="type">bool               CreateLabel( class="type">void );
class="type">bool               CreateHoursEdit( class="type">void );
class="type">bool               CreateMinutesEdit( class="type">void );
class=class="str">"cmt">//---
class="kw">public :
class=class="str">"cmt">//--- 返回编辑框指针
CSpinEdit        *GetHoursEditPointer( class="type">void )                      { class="kw">return (:: GetPointer(m_hours));     }
CSpinEdit        *GetMinutesEditPointer( class="type">void )                    { class="kw">return (:: GetPointer(m_minutes));   }
};

class CTimeEdit : class="kw">public CElement
{
class="kw">public :
class=class="str">"cmt">//--- 获取和设置编辑框值
class="type">int                GetHours( class="type">void )                           class="kw">const { class="kw">return (( class="type">int )m_hours.GetValue());   }
class="type">int                GetMinutes( class="type">void )                         class="kw">const { class="kw">return (( class="type">int )m_minutes.GetValue()); }
class="type">void               SetHours( class="kw">const class="type">uint value )                     { m_hours.ChangeValue( value );        }
class="type">void               SetMinutes( class="kw">const class="type">uint value )                   { m_minutes.ChangeValue( value );      }
};

常见问题

用文中 CTime 类自绘时间控件,绑定到面板坐标后响应鼠标滚轮和点击,就能在图表上直接选起止时间,不用跳系统弹窗。
用 CCheckBoxList 类管理复选框数组,只重绘状态变化的行,勾选状态存成员变量,主循环里读变量执行逻辑即可。
可以,把你想选的时间字段和清单项告诉小布,它能产出对应类结构和事件处理骨架,你贴进工程改坐标就能跑。
文中给的表格类已带按列排序方法,调用 SortByColumn(col, order) 并触发重绘,点表头时传列号进去就行。
自绘的时区按终端本地算,跨时区账号要手动加偏移;另外鼠标移出控件区域要复位高亮状态,否则界面会粘指针。