如何使用MQL5的控件类创建交互式仪表板/面板(第一部分):设置面板(基础篇)
📘

如何使用MQL5的控件类创建交互式仪表板/面板(第一部分):设置面板(基础篇)

第 1/3 篇

「用控件类搭一个MT5交互面板骨架」

MQL5 的 CAppDialog 及其派生控件类(按钮、标签、编辑框等)能直接在 MT5 图表上画出可交互面板,不必依赖外部 DLL 或网页。比起自己用 OBJ_RECTANGLE 硬拼坐标,控件类已封装了鼠标命中、焦点切换和重绘逻辑,开发成本明显下降。 先建一个继承自 CAppDialog 的子类,在构造函数里指定面板左上角坐标与宽高。下面这段最小骨架在图表上开出一个 300×200 的对话框,标题栏写“Demo Panel”,编译后拖到任意品种图表即可看到空面板。 外汇与贵金属品种波动剧烈、杠杆风险高,面板只是辅助观察与下单的工具,任何信号都只是概率倾向,不等于稳赚。

MQL5 / C++
class="macro">#include <Controls/Dialog.mqh>
class CDemoPanel : class="kw">public CAppDialog
{
class="kw">public:
   CDemoPanel(class="type">void) : CAppDialog() {}
   ~CDemoPanel(class="type">void) {}
   class="kw">virtual class="type">bool Create(const class="type">long chart, const class="type">class="kw">string name, const class="type">int subwin, const class="type">int x, const class="type">int y, const class="type">int w, const class="type">int h)
   {
      if(!CAppDialog::Create(chart, name, subwin, x, y, w, h)) class="kw">return false;
      CAppDialog::Caption("Demo Panel");
      class="kw">return true;
   }
};
CDemoPanel g_panel;
class="type">int OnInit()
{
   if(!g_panel.Create(class="num">0, "demo", class="num">0, class="num">10, class="num">10, class="num">300, class="num">200)) class="kw">return INIT_FAILED;
   g_panel.Show();
   class="kw">return INIT_SUCCEEDED;
}
class="type">void OnDeinit(const class="type">int reason) { g_panel.Destroy(); }
class="type">int OnCalculate(const class="type">int rates_total, const class="type">int prev_calculated, const class="type">class="kw">datetime &time[], const class="type">class="kw">double &open[], const class="type">class="kw">double &high[], const class="type">class="kw">double &low[], const class="type">class="kw">double &close[], const class="type">long &tick_volume[], const class="type">long &volume[], const class="type">int &spread[]) { class="kw">return rates_total; }

◍ 先搭一个能用的面板骨架

用 MQL5 的控件类做交互式仪表板,第一步不是堆功能,而是把布局骨架定下来:标题栏、导航按钮、对应操作区,这三块构成后续复杂面板的核心容器。骨架定好后,交易体验才可能往简洁、快速、直观的方向走。 导航区先放三个按钮:交易、平仓、信息。交易区预留交易量、价格、SL、TP 及买入/卖出/买入止损的执行键;平仓区给“平仓所有盈利”“平仓所有挂单”这类批量键;信息区负责吐出交易状态与关键数据。 开发环境锁定 MetaEditor 里的 MQL5,程序直接在 MT5 终端跑,这样才能盯实时行情并和面板无缝交互。动手前务必装最新版 MQL5 与 MT5,老版本可能缺控件类或接口不兼容。外汇与贵金属波动剧烈、杠杆风险高,面板只是执行工具,不替你过滤行情风险。 本文拆成三块推进:元素展示、MQL5 组装 GUI、收尾结论。环境就绪后,下一节直接看控件长什么样。

面板三大导航与功能分区

交互式 GUI 面板的核心由三个导航按钮构成:交易、平仓、信息,各自挂载独立操作区,目的是把高频动作压缩到一两步内完成。 交易区放置交易量、价格、SL、TP 的设定键,以及市价买、市价卖、买入止损等执行键;平仓区给出“平仓所有盈利”“平仓所有挂单”这类批量管理入口,避免手动逐个关闭。信息区实时刷新账户余额、保证金占用与行情变动。 原文给出了一张布局图,标出上述组件在面板中的排布顺序,后续搭建 GUI 时直接按图接线即可,不必重新设计层级。

「用 MQL5 控件库搭出面板主按钮」

在 MT5 里做 GUI 面板,第一步不是画界面,而是拿到标准控件库的访问权。打开 MetaEditor(终端按 F4 或 Ctrl+N 新建 Expert Advisor 模板),真正要用的类文件都在 Include\Controls 子目录下,比如按钮靠 Button.mqh 里的 CButton 类。 先把库包含进来,再声明一个按钮对象实例,代码层面就拥有了操作主按钮的句柄: #include <Controls\Button.mqh> CButton obj_Btn_MAIN; OnInit 里用 Create 把按钮挂到当前图表。参数顺序是:图表 ID 用 0(当前图)、名称字符串、子窗口索引 0(主图)、X/Y 坐标、宽高。下面这段把主按钮放在 (30,30),尺寸暂设 0(取默认): obj_Btn_MAIN.Create(0, "Btn_MAIN", 0, 30, 30, 0, 0); Create 的第六、七参数若填 0,按钮会按默认尺寸正向映射;若直接给第二组坐标(如 310,300),所有像素从原点 (0,0) 算起,容易算错反向尺寸。更稳的做法是用 Size 单独定宽高,从第一坐标正向延伸,不必管第二组: obj_Btn_MAIN.Size(20, 20); 视觉上用 RGB 控背景和边框。C'070,070,070' 是中等深灰(红绿蓝各 70/255),边框用 clrBlack 纯黑,能让后续亮色元素跳出来。代码: obj_Btn_MAIN.ColorBackground(C'070,070,070'); obj_Btn_MAIN.ColorBorder(clrBlack); 每次增删改图形对象后必须 ChartRedraw(0) 强制重绘,否则新按钮可能不显示或留旧属性。外汇与贵金属图表高波动,面板不刷新会直接误导下单。 主按钮成型后,可一口气把面板其余交互对象都声明出来:标题、关闭 X、交易、平仓、信息、风险、点数、买卖与挂单按钮,以及编辑框(CEdit)和标签(CLabel)。例如标题按钮放 (30,30) 宽 310 高 25,背景 clrLightBlue、黑边;关闭按钮塞进标题内(x=30+280, y=30+1,宽 29 高 23),背景边框同浅蓝消去割裂感。 跑完这套,你就已经在 MT5 里验证了:控件库不用自己写绘图,改坐标和 RGB 立刻能看到按钮位置与颜色变化,接下来只需往对象上绑交易逻辑。

MQL5 / C++
class="macro">#include <Controls\Button.mqh>
CButton obj_Btn_MAIN;

obj_Btn_MAIN.Create(class="num">0, "Btn_MAIN", class="num">0, class="num">30, class="num">30, class="num">0, class="num">0);
obj_Btn_MAIN.Size(class="num">20, class="num">20);
obj_Btn_MAIN.ColorBackground(C&class="macro">#x27;class="num">070,class="num">070,class="num">070&class="macro">#x27;);
obj_Btn_MAIN.ColorBorder(clrBlack);
ChartRedraw(class="num">0);

◍ 把交易面板拆成可复用模块

做 MT5 面板最忌把所有对象写死在 OnInit 里。上面这套控制面板把标题、导航键、页脚、交易区、账户信息区各自封成函数,初始化时按需调用,拆除时反向 Destroy,逻辑像盖楼和拆楼一样分层。 关闭键用 CharToString(255) 喂给 Wingdings 字体显示成 Windows 图标,文字黑色、字号 17;标题标签坐标锁在 x=40、y=30,字体 Cooper black、红色、14 号。页脚按钮宽 310-1-1、高 25,背景深灰 C'070,070,070',文本用 ShortToString(0x23F0) 拼电报链接,白字 Calibri bold italic 12 号。 账户类型那块没有现成函数直取,先用 AccountInfoInteger(ACCOUNT_TRADE_MODE) 拿枚举,再用 switch 分流:DEMO 标“Demo Account”、CONTEST 标“Contest Account”、其余落“Real Account”。登录号则 AccountInfoInteger(ACCOUNT_LOGIN) 配合 IntegerToString 转字符串再写进按钮。 删除组件不要在 OnDeinit 里手写一堆,按外墙→隔断→楼层→基础的顺序各写 Destroy 函数,事件里依次调。外汇与贵金属杠杆高,面板只是辅助,真金白银下单前先在模拟盘验一遍交互。 第一部分目标只是把界面组件立起来,按钮点击响应留到后续。你当下能做的:把上面坐标、RGB、字体参数原样丢进 MT5 编译,看输出的面板布局是否和描述一致。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                     CONTROL PANEL PART class="num">1.mq5 |
class=class="str">"cmt">//|          Copyright class="num">2024, Allan Munene Mutiiria. |
class=class="str">"cmt">//|                 https://forexalgo-trader.com |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2024, Allan Munene Mutiiria." class=class="str">"cmt">//--- Set copyright information
class="macro">#class="kw">property link      "https:class=class="str">"cmt">//forexalgo-trader.com"            //--- Link to the author&class="macro">#x27;s website
class="macro">#class="kw">property version   "class="num">1.00"                                   class=class="str">"cmt">//--- Version of the script

在 MT5 图表上落一个可定位的按钮

用标准库 CButton 在 EA 初始化阶段挂界面元素,比手绘 OBJ_BUTTON 省事。下面这段把创建、尺寸、配色一次走通,你直接抄进 OnInit 就能在图表左上角看到一块深灰面板。 #include <Controls/Button.mqh> CButton obj_Btn_MAIN; #define Btn_MAIN "Btn_MAIN" int OnInit() { obj_Btn_MAIN.Create(0, Btn_MAIN, 0, 30, 30, 0, 0); obj_Btn_MAIN.Size(310, 300); obj_Btn_MAIN.ColorBackground(C'070,070,070'); obj_Btn_MAIN.ColorBorder(clrBlack); ChartRedraw(0); return(INIT_SUCCEEDED); } Create 的第六、七参数是 x/y 坐标,原文里出现过 310、300 的写法,那会把按钮塞到图表偏右下;改回 0、0 就贴左上角。Size(310,300) 一步设宽高,比分开 Width/Height 更不容易漏参数。 外汇与贵金属杠杆高,EA 界面只是辅助,按钮触发下单前仍要自校验风控。跑之前在策略测试器里先点一下,确认面板渲染位置符合预期再上实盘。

MQL5 / C++
class="macro">#include <Controls/Button.mqh>                     class=class="str">"cmt">//--- 引入按钮控件库
CButton obj_Btn_MAIN;                               class=class="str">"cmt">//--- 主按钮对象

class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit() {
  class=class="str">"cmt">//--- 初始化函数开始
  class=class="str">"cmt">//--- 主按钮
  obj_Btn_MAIN.Create(class="num">0, Btn_MAIN, class="num">0, class="num">30, class="num">30, class="num">0, class="num">0); class=class="str">"cmt">//--- 在指定坐标创建主按钮(图表子窗口0、名称Btn_MAIN、基础Id0、宽30高30、x0 y0)
  class=class="str">"cmt">//--- 初始化函数结束
  class="kw">return(INIT_SUCCEEDED); class=class="str">"cmt">//--- 返回初始化成功状态
}

class=class="str">"cmt">//--- 定义按钮名便于引用
class="macro">#define Btn_MAIN "Btn_MAIN"                         class=class="str">"cmt">//--- 主按钮的名称
  class=class="str">"cmt">//--- 主按钮
  obj_Btn_MAIN.Create(class="num">0, Btn_MAIN, class="num">0, class="num">30, class="num">30, class="num">310, class="num">300); class=class="str">"cmt">//--- 在指定坐标创建主按钮(x310 y300,偏右下)
  class=class="str">"cmt">//--- 主按钮
  obj_Btn_MAIN.Create(class="num">0, Btn_MAIN, class="num">0, class="num">30, class="num">30, class="num">0, class="num">0); class=class="str">"cmt">//--- 在指定坐标创建主按钮(x0 y0,左上)
  obj_Btn_MAIN.Width(class="num">20);  class=class="str">"cmt">//--- 设置主按钮宽度20
  obj_Btn_MAIN.Height(class="num">20); class=class="str">"cmt">//--- 设置主按钮高度20
  class=class="str">"cmt">//--- 主按钮
  obj_Btn_MAIN.Create(class="num">0, Btn_MAIN, class="num">0, class="num">30, class="num">30, class="num">0, class="num">0); class=class="str">"cmt">//--- 在指定坐标创建主按钮
  class=class="str">"cmt">//obj_Btn_MAIN.Width(class="num">310);  //--- (已注释)设置主按钮宽度310
  class=class="str">"cmt">//obj_Btn_MAIN.Height(class="num">300); //--- (已注释)设置主按钮高度300
  obj_Btn_MAIN.Size(class="num">310, class="num">300);                   class=class="str">"cmt">//--- 一次性设置主按钮尺寸310x300
  obj_Btn_MAIN.ColorBackground(C&class="macro">#x27;class="num">070,class="num">070,class="num">070&class="macro">#x27;);  class=class="str">"cmt">//--- 设置主按钮背景色为深灰(class="num">70,class="num">70,class="num">70)
  obj_Btn_MAIN.ColorBorder(clrBlack);            class=class="str">"cmt">//--- 设置主按钮边框色为黑
  ChartRedraw(class="num">0);                                class=class="str">"cmt">//--- 重绘图表以刷新面板

class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit() {
  class=class="str">"cmt">//--- 初始化函数开始
  class=class="str">"cmt">//--- 主按钮
  obj_Btn_MAIN.Create(class="num">0, Btn_MAIN, class="num">0, class="num">30, class="num">30, class="num">0, class="num">0); class=class="str">"cmt">//--- 在指定坐标创建主按钮
  class=class="str">"cmt">//obj_Btn_MAIN.Width(class="num">310);  //--- (已注释)设置主按钮宽度310
  class=class="str">"cmt">//obj_Btn_MAIN.Height(class="num">300); //--- (已注释)设置主按钮高度300
}

常见问题

用控件库的 CButton 类直接实例化一个按钮对象,设置坐标和文字后加到面板容器里即可,不用自己处理鼠标消息。
在创建面板时给主窗口设好 X/Y 偏移和宽高,比如贴右上角留 10 像素边距,就能稳定避让主图价格区域。
小布可以读取你当前图表上的控件布局并给出分区建议,把导航、功能、状态区是否重叠一眼标出来,省去手动排查。
拆成可复用模块后只需改对应类的参数或方法,主框架不变,比全写在一个文件里好维护得多。
可以合,但分开写更利于后期加页签;基础篇先按三大分区搭,后面扩展不会乱。