图形界面 X: 时间控件, 复选框列表控件和表格排序 (集成编译 6)(基础篇)
给 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 逻辑跑偏,上实盘前务必在策略测试器里先验证。
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 ); } };