如何使用MQL5的控件类创建交互式仪表板/面板(第一部分):设置面板·进阶篇
◍ 面板按钮对象的声明与初始化收尾
在 MT5 自定义面板里,先通过 #include <Controls/Button.mqh> 把标准按钮控件库挂进来,否则下面那一串 CButton 对象根本编不过。这一行通常放在全局作用域顶部,跟交易品种、手数参数分开管理。
随后用 CButton 逐个声明面板上的实体按钮:主按钮 obj_Btn_MAIN、标题栏 obj_Btn_HEADER、关闭叉 obj_Btn_X,以及交易相关的 obj_Btn_TRADE、obj_Btn_BUY、obj_Btn_SELL、obj_Btn_BUYSTOP 等共 16 个实例。每个对象在声明时还不占屏幕,只是预留了内存句柄。
初始化函数末尾要给主按钮定尺寸和颜色:Size(310,300) 把点击区拉到 310×300 像素,ColorBackground(C'070,070,070') 填深灰底,ColorBorder(clrBlack) 描黑边。改完属性必须调 ChartRedraw(0) 强制重绘,否则 MT5 图表不会即时刷新面板。
最后 return(INIT_SUCCEEDED) 告知终端初始化成功。若这里漏了 redraw,你可能会在回测里看到按钮属性已变、但视觉上没反应的坑,实盘拖拽面板时尤其明显。
class="macro">#include <Controls/Button.mqh> CButton obj_Btn_MAIN; CButton obj_Btn_HEADER; CButton obj_Btn_X; CButton obj_Btn_TRADE; CButton obj_Btn_CLOSE; CButton obj_Btn_INFO; CButton obj_Btn_RISK; CButton obj_Btn_POINTS; CButton obj_Btn_SELL; CButton obj_Btn_ENTRY; CButton obj_Btn_BUY; CButton obj_Btn_SELLSTOP; CButton obj_Btn_BUYSTOP; CButton obj_Btn_SELLLIMIT; CButton obj_Btn_BUYLIMIT; obj_Btn_MAIN.Size(class="num">310, class="num">300); class=class="str">"cmt">//--- Set size of the main button obj_Btn_MAIN.ColorBackground(C&class="macro">#x27;class="num">070,class="num">070,class="num">070&class="macro">#x27;); class=class="str">"cmt">//--- Set background class="type">class="kw">color of the main button obj_Btn_MAIN.ColorBorder(clrBlack); class=class="str">"cmt">//--- Set border class="type">class="kw">color of the main button ChartRedraw(class="num">0); class=class="str">"cmt">//--- Redraw the chart to update the panel class=class="str">"cmt">//--- End of initialization function class="kw">return(INIT_SUCCEEDED); class=class="str">"cmt">//--- Return initialization success status
「面板控件的对象声明与命名宏」
在 MT5 自定义面板里,先把界面元素以对象形式声明,后续才能用代码控制它们的位置、文本和点击事件。下面这段声明覆盖了底部按钮、编辑框和标签三类控件,是订单速填面板的骨架。 CButton 只定义了一个底部按钮对象 obj_Btn_FOOTER,用于承载面板最下方的功能键。编辑框部分通过 #include <Controls/Edit.mqh> 引入标准库,再声明 obj_Edit_RISK、obj_Edit_PRICE、obj_Edit_LOTS、obj_Edit_SL、obj_Edit_TP 五个实例,分别对应风控、价格、手数、止损、止盈的输入区。 标签部分用 #include <Controls/Label.mqh> 引入后,声明了 obj_Lbl_HEADER、obj_Lbl_PRICE、obj_Lbl_LOTS、obj_Lbl_SL、obj_Lbl_TP 五个静态文本对象,负责在各输入框前显示字段名。最后用 #define 把四个按钮映射成字符串常量:Btn_MAIN、Btn_HEADER、Btn_X、Btn_TRADE,之后在事件函数里直接写常量名就能定位控件,比散写字符串更不易拼错。 开 MT5 新建 EA 把这段贴进全局区,编译通过后会在初始化阶段生成空对象;若想在面板上真看到它们,还得在 OnCreate 里补坐标和尺寸——这一步漏了对象就不会显示。
CButton obj_Btn_FOOTER; class=class="str">"cmt">//--- Footer button object class="macro">#include <Controls/Edit.mqh> class=class="str">"cmt">//--- Include edit control library CEdit obj_Edit_RISK; class=class="str">"cmt">//--- Risk edit field object CEdit obj_Edit_PRICE; class=class="str">"cmt">//--- Price edit field object CEdit obj_Edit_LOTS; class=class="str">"cmt">//--- Lots edit field object CEdit obj_Edit_SL; class=class="str">"cmt">//--- Stop Loss edit field object CEdit obj_Edit_TP; class=class="str">"cmt">//--- Take Profit edit field object class="macro">#include <Controls/Label.mqh> class=class="str">"cmt">//--- Include label control library CLabel obj_Lbl_HEADER; class=class="str">"cmt">//--- Header label object CLabel obj_Lbl_PRICE; class=class="str">"cmt">//--- Price label object CLabel obj_Lbl_LOTS; class=class="str">"cmt">//--- Lots label object CLabel obj_Lbl_SL; class=class="str">"cmt">//--- Stop Loss label object CLabel obj_Lbl_TP; class=class="str">"cmt">//--- Take Profit label object class=class="str">"cmt">//--- Define button names for easier reference class="macro">#define Btn_MAIN "Btn_MAIN" class=class="str">"cmt">//--- Button name for the main button class="macro">#define Btn_HEADER "Btn_HEADER" class=class="str">"cmt">//--- Button name for the header button class="macro">#define Btn_X "Btn_X" class=class="str">"cmt">//--- Button name for the close button class="macro">#define Btn_TRADE "Btn_TRADE" class=class="str">"cmt">//--- Button name for the trade button
面板控件名的宏定义套路
在 MT5 自定义交易面板里,最容易被忽略但最影响维护成本的一步,就是给按钮和编辑框起统一的内部名字。上面这组宏把 13 个按钮和 4 个编辑框全部用 #define 固化成字符串常量,后续创建对象、响应点击事件时直接写 Btn_BUY 而不是手写 "Btn_BUY",能少敲很多字也少出错。 具体看,按钮覆盖了平仓、信息、风险、点数、即时卖买、挂单四类(止损买 Btn_BUYSTOP、限价卖 Btn_SELLLIMIT 等)以及底部栏 Btn_FOOTER;编辑框则锁定了风险额度、价格、手数、止损四个输入项。这种集中声明方式让界面元素数量一眼可数:按钮 13 个、编辑框 4 个。 开 MT5 新建 EA 时,把这段直接贴到全局区,改面板布局只需动宏后面的字符串,事件处理函数里的 OBJPROP_NAME 比对逻辑完全不用碰。外汇和贵金属波动大,这类一键面板若接实盘,先开模拟盘验证控件响应再谈风控。
class="macro">#define Btn_CLOSE "Btn_CLOSE" class=class="str">"cmt">//--- Button name for the close button class="macro">#define Btn_INFO "Btn_INFO" class=class="str">"cmt">//--- Button name for the info button class="macro">#define Btn_RISK "Btn_RISK" class=class="str">"cmt">//--- Button name for the risk button class="macro">#define Btn_POINTS "Btn_POINTS" class=class="str">"cmt">//--- Button name for the points button class="macro">#define Btn_SELL "Btn_SELL" class=class="str">"cmt">//--- Button name for the sell button class="macro">#define Btn_ENTRY "Btn_ENTRY" class=class="str">"cmt">//--- Button name for the entry button class="macro">#define Btn_BUY "Btn_BUY" class=class="str">"cmt">//--- Button name for the buy button class="macro">#define Btn_SELLSTOP "Btn_SELLSTOP" class=class="str">"cmt">//--- Button name for the sell stop button class="macro">#define Btn_BUYSTOP "Btn_BUYSTOP" class=class="str">"cmt">//--- Button name for the buy stop button class="macro">#define Btn_SELLLIMIT "Btn_SELLLIMIT" class=class="str">"cmt">//--- Button name for the sell limit button class="macro">#define Btn_BUYLIMIT "Btn_BUYLIMIT" class=class="str">"cmt">//--- Button name for the buy limit button class="macro">#define Btn_FOOTER "Btn_FOOTER" class=class="str">"cmt">//--- Button name for the footer button class=class="str">"cmt">//--- class=class="str">"cmt">//--- Define edit field names for easier reference class="macro">#define Edit_RISK "Edit_RISK" class=class="str">"cmt">//--- Edit field name for risk input class="macro">#define Edit_PRICE "Edit_PRICE" class=class="str">"cmt">//--- Edit field name for price input class="macro">#define Edit_LOTS "Edit_LOTS" class=class="str">"cmt">//--- Edit field name for lots input class="macro">#define Edit_SL "Edit_SL" class=class="str">"cmt">//--- Edit field name for stop loss input
◍ 面板控件的坐标与样式硬编码
在 MT5 的 EA 或指标里手搓控制面板,第一步往往是把各个子控件的名字和位置用宏或变量固定下来。下面这段把止盈输入框、表头标签、价格/手数/止损/止盈标签都做了 #define 别名,后续在 Create() 调用里直接写 Lbl_TP 比裸字符串不容易拼错,也方便全局替换。
表头按钮画在坐标 (30,30),宽 310 高 25,背景 clrLightBlue、边框 clrBlack;右上角关闭按钮 X 则偏移 280 像素放在 (310,31),尺寸压到 29×23,边框同背景色做视觉弱化。X 上的文字不是普通字母,而是用 CharToString(255) 取 Wingdings 字体里的叉号字形,字号 17——这种写法在 MT5 图形对象里很常见,比贴位图轻量。
表头标签 Lbl_HEADER 落在 (40,30),显示「Control Panel」,用 Cooper Black 14 号红字。注意坐标系统里 y 轴向下增长,所以 30 和 40 的微小错位就是标题栏和按钮的纵向叠放关系,调面板布局时改这几个数就能直接看到效果。外汇与贵金属品种波动剧烈,这类手动面板只解决下单交互,不改变任何风控本质,杠杆风险依旧高。
class="macro">#define Edit_TP "Edit_TP" class=class="str">"cmt">//--- Edit field name for take profit input class=class="str">"cmt">//--- Define label names for easier reference class="macro">#define Lbl_HEADER "Lbl_HEADER" class=class="str">"cmt">//--- Label name for the header class="macro">#define Lbl_PRICE "Lbl_PRICE" class=class="str">"cmt">//--- Label name for the price class="macro">#define Lbl_LOTS "Lbl_LOTS" class=class="str">"cmt">//--- Label name for the lots class="macro">#define Lbl_SL "Lbl_SL" class=class="str">"cmt">//--- Label name for the stop loss class="macro">#define Lbl_TP "Lbl_TP" class=class="str">"cmt">//--- Label name for the take profit class=class="str">"cmt">//--- HEADER BUTTON obj_Btn_HEADER.Create(class="num">0, Btn_HEADER, class="num">0, class="num">30, class="num">30, class="num">0, class="num">0); class=class="str">"cmt">//--- Create the header button at specified coordinates obj_Btn_HEADER.Size(class="num">310, class="num">25); class=class="str">"cmt">//--- Set size of the header button obj_Btn_HEADER.ColorBackground(clrLightBlue); class=class="str">"cmt">//--- Set background class="type">class="kw">color of the header button obj_Btn_HEADER.ColorBorder(clrBlack); class=class="str">"cmt">//--- Set border class="type">class="kw">color of the header button class=class="str">"cmt">//--- X BUTTON obj_Btn_X.Create(class="num">0, Btn_X, class="num">0, class="num">30 + class="num">280, class="num">30 + class="num">1, class="num">0, class="num">0); class=class="str">"cmt">//--- Create the close button(X) at specified coordinates obj_Btn_X.Size(class="num">30 - class="num">1, class="num">25 - class="num">1 - class="num">1); class=class="str">"cmt">//--- Set size of the close button obj_Btn_X.ColorBackground(clrLightBlue); class=class="str">"cmt">//--- Set background class="type">class="kw">color of the close button obj_Btn_X.ColorBorder(clrLightBlue); class=class="str">"cmt">//--- Set border class="type">class="kw">color of the close button obj_Btn_X.Text(CharToString(class="num">255)); class=class="str">"cmt">//--- Set the close button text to an "X" character obj_Btn_X.Color(clrBlack); class=class="str">"cmt">//--- Set text class="type">class="kw">color of the close button obj_Btn_X.Font("Wingdings"); class=class="str">"cmt">//--- Set font of the close button to Wingdings obj_Btn_X.FontSize(class="num">17); class=class="str">"cmt">//--- Set font size of the close button class=class="str">"cmt">//--- HEADER LABEL obj_Lbl_HEADER.Create(class="num">0, Lbl_HEADER, class="num">0, class="num">40, class="num">30, class="num">0, class="num">0); class=class="str">"cmt">//--- Create the header label at specified coordinates obj_Lbl_HEADER.Text("Control Panel"); class=class="str">"cmt">//--- Set text of the header label obj_Lbl_HEADER.Color(clrRed); class=class="str">"cmt">//--- Set text class="type">class="kw">color of the header label obj_Lbl_HEADER.Font("Cooper black"); class=class="str">"cmt">//--- Set font of the header label to Cooper Black obj_Lbl_HEADER.FontSize(class="num">14); class=class="str">"cmt">//--- Set font size of the header label class=class="str">"cmt">//--- TRADE BUTTON
「在图表上摆出三个功能按钮加底栏」
给自定义面板加交互控件时,用 CButton 的 Create 把对象挂到图表子窗口 0,再靠 X/Y 坐标排布。Trade 按钮落在 (40,60),宽 90 高 30,黄底黑字用 Arial Black 13 号,视觉上最跳。 Close 和 Inform'n 按钮都设为银色背景,尺寸同为 90x30,坐标用前一个按钮的 Width() 加 10 像素间距算出来,保证不重叠。这种链式偏移写法比写死坐标更不容易在改按钮宽度时错位。 底部 FOOTER 按钮单独放在 y=304 附近,宽 308 高 25,深灰底白字,字体用 Calibri bold italic,文字前面拼了 Unicode 0x23F0(闹钟符)再加 Telegram 链接串。外汇与贵金属图表挂这种带外链控件时需注意:MT5 对象本身不触发跳转,得在事件里自己处理,且实盘界面改 UI 有误操作风险,建议先在模拟盘验证。
obj_Btn_TRADE.Create(class="num">0, Btn_TRADE, class="num">0, class="num">40, class="num">60, class="num">0, class="num">0); class=class="str">"cmt">//--- Create the trade button at specified coordinates obj_Btn_TRADE.Size(class="num">90, class="num">30); class=class="str">"cmt">//--- Set size of the trade button obj_Btn_TRADE.ColorBackground(clrYellow); class=class="str">"cmt">//--- Set background class="type">class="kw">color of the trade button obj_Btn_TRADE.ColorBorder(clrYellow); class=class="str">"cmt">//--- Set border class="type">class="kw">color of the trade button obj_Btn_TRADE.Text("Trade"); class=class="str">"cmt">//--- Set text of the trade button obj_Btn_TRADE.Color(clrBlack); class=class="str">"cmt">//--- Set text class="type">class="kw">color of the trade button obj_Btn_TRADE.Font("Arial Black"); class=class="str">"cmt">//--- Set font of the trade button to Arial Black obj_Btn_TRADE.FontSize(class="num">13); class=class="str">"cmt">//--- Set font size of the trade button class=class="str">"cmt">//--- CLOSE BUTTON obj_Btn_CLOSE.Create(class="num">0, Btn_CLOSE, class="num">0, class="num">40 + obj_Btn_TRADE.Width() + class="num">10, class="num">60, class="num">0, class="num">0); class=class="str">"cmt">//--- Create the close button at specified coordinates obj_Btn_CLOSE.Size(class="num">90, class="num">30); class=class="str">"cmt">//--- Set size of the close button obj_Btn_CLOSE.ColorBackground(clrSilver); class=class="str">"cmt">//--- Set background class="type">class="kw">color of the close button obj_Btn_CLOSE.ColorBorder(clrSilver); class=class="str">"cmt">//--- Set border class="type">class="kw">color of the close button obj_Btn_CLOSE.Text("Close"); class=class="str">"cmt">//--- Set text of the close button obj_Btn_CLOSE.Color(clrBlack); class=class="str">"cmt">//--- Set text class="type">class="kw">color of the close button obj_Btn_CLOSE.Font("Arial Black"); class=class="str">"cmt">//--- Set font of the close button to Arial Black obj_Btn_CLOSE.FontSize(class="num">13); class=class="str">"cmt">//--- Set font size of the close button class=class="str">"cmt">//--- INFO BUTTON obj_Btn_INFO.Create(class="num">0, Btn_INFO, class="num">0, class="num">40 + obj_Btn_TRADE.Width() + class="num">10 + obj_Btn_CLOSE.Width() + class="num">10, class="num">60, class="num">0, class="num">0); class=class="str">"cmt">//--- Create the info button at specified coordinates obj_Btn_INFO.Size(class="num">90, class="num">30); class=class="str">"cmt">//--- Set size of the info button obj_Btn_INFO.ColorBackground(clrSilver); class=class="str">"cmt">//--- Set background class="type">class="kw">color of the info button obj_Btn_INFO.ColorBorder(clrSilver); class=class="str">"cmt">//--- Set border class="type">class="kw">color of the info button obj_Btn_INFO.Text("Inform&class="macro">#x27;n"); class=class="str">"cmt">//--- Set text of the info button obj_Btn_INFO.Color(clrBlack); class=class="str">"cmt">//--- Set text class="type">class="kw">color of the info button obj_Btn_INFO.Font("Arial Black"); class=class="str">"cmt">//--- Set font of the info button to Arial Black obj_Btn_INFO.FontSize(class="num">13); class=class="str">"cmt">//--- Set font size of the info button class=class="str">"cmt">//--- FOOTER BUTTON obj_Btn_FOOTER.Create(class="num">0, Btn_FOOTER, class="num">0, class="num">30 + class="num">1, class="num">305 - class="num">1, class="num">0, class="num">0); class=class="str">"cmt">//--- Create the footer button at specified coordinates obj_Btn_FOOTER.Size(class="num">310 - class="num">1 - class="num">1, class="num">25); class=class="str">"cmt">//--- Set size of the footer button obj_Btn_FOOTER.ColorBackground(C&class="macro">#x27;class="num">070,class="num">070,class="num">070&class="macro">#x27;); class=class="str">"cmt">//--- Set background class="type">class="kw">color of the footer button obj_Btn_FOOTER.ColorBorder(C&class="macro">#x27;class="num">070,class="num">070,class="num">070&class="macro">#x27;); class=class="str">"cmt">//--- Set border class="type">class="kw">color of the footer button obj_Btn_FOOTER.Text(ShortToString(0x23F0) + "https:class=class="str">"cmt">//t.me/Forex_Algo_Trader"); //--- Set text of the footer button with a link obj_Btn_FOOTER.Color(clrWhite); class=class="str">"cmt">//--- Set text class="type">class="kw">color of the footer button obj_Btn_FOOTER.Font("Calibri bold italic"); class=class="str">"cmt">//--- Set font of the footer button to Calibri bold italic
交易面板里的风险与报价控件
在 MT5 自定义面板里,交易区块的搭建从两个基础控件开始:一个显示「Risk based on Equity (%)」的绿松石色按钮,和一个默认填了 78 的编辑框。按钮宽 210、高 25,字号 11,用 Arial Black;编辑框宽 70、高 25,字号 15,用 Times new roman bold,这两个坐标错开 220 像素避免重叠。 价格部分更实用:标签写「Price」,后面紧跟的编辑框默认直接塞进当前卖价,靠 SymbolInfoDouble(_Symbol,SYMBOL_ASK) 配合 _Digits 动态生成。这意味着面板一挂上图表,报价框就不是死数,而是随品种精度刷新的活值,省得手动填。 外汇和贵金属波动剧烈、杠杆风险高,这种面板只是把仓位计算的输入项图形化,实际下单前仍要自己核对保证金与滑点。把下面这段代码丢进 MT5 的 EA 或指标源文件,改改坐标就能看到控件长什么样。
obj_Btn_FOOTER.FontSize(class="num">12); class=class="str">"cmt">//--- Set font size of the footer button class=class="str">"cmt">// BODY OF THE PANEL createSection_Trade(); class=class="str">"cmt">//--- Call function to create the trade section class="type">void createSection_Trade(){ class=class="str">"cmt">//--- } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| FUNCTION TO CREATE THE TRADE SECTION | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void createSection_Trade(){ class=class="str">"cmt">//--- RISK BUTTON obj_Btn_RISK.Create(class="num">0,Btn_RISK,class="num">0,class="num">40,class="num">100,class="num">0,class="num">0); class=class="str">"cmt">//--- Create the risk button obj_Btn_RISK.Size(class="num">210,class="num">25); class=class="str">"cmt">//--- Set the button size obj_Btn_RISK.ColorBackground(clrTurquoise); class=class="str">"cmt">//--- Set the background class="type">class="kw">color obj_Btn_RISK.ColorBorder(clrTurquoise); class=class="str">"cmt">//--- Set the border class="type">class="kw">color obj_Btn_RISK.Text("Risk based on Equity(%)"); class=class="str">"cmt">//--- Set the button text obj_Btn_RISK.Color(clrBlack); class=class="str">"cmt">//--- Set the text class="type">class="kw">color obj_Btn_RISK.Font("Arial Black"); class=class="str">"cmt">//--- Set the font style obj_Btn_RISK.FontSize(class="num">11); class=class="str">"cmt">//--- Set the font size class=class="str">"cmt">//--- RISK EDIT obj_Edit_RISK.Create(class="num">0,Edit_RISK,class="num">0,class="num">40+class="num">220,class="num">100,class="num">0,class="num">0); class=class="str">"cmt">//--- Create the risk edit field obj_Edit_RISK.Size(class="num">70,class="num">25); class=class="str">"cmt">//--- Set the edit field size obj_Edit_RISK.ColorBackground(clrWhite); class=class="str">"cmt">//--- Set the background class="type">class="kw">color obj_Edit_RISK.ColorBorder(clrBlack); class=class="str">"cmt">//--- Set the border class="type">class="kw">color obj_Edit_RISK.Text("class="num">78"); class=class="str">"cmt">//--- Set the class="kw">default text obj_Edit_RISK.Color(clrBlack); class=class="str">"cmt">//--- Set the text class="type">class="kw">color obj_Edit_RISK.Font("Times new roman bold"); class=class="str">"cmt">//--- Set the font style obj_Edit_RISK.FontSize(class="num">15); class=class="str">"cmt">//--- Set the font size class=class="str">"cmt">//--- PRICE LABEL obj_Lbl_PRICE.Create(class="num">0,Lbl_PRICE,class="num">0,class="num">40,class="num">130,class="num">0,class="num">0); class=class="str">"cmt">//--- Create the price label obj_Lbl_PRICE.Text("Price"); class=class="str">"cmt">//--- Set the label text obj_Lbl_PRICE.Color(clrWhite); class=class="str">"cmt">//--- Set the text class="type">class="kw">color obj_Lbl_PRICE.Font("Arial black"); class=class="str">"cmt">//--- Set the font style obj_Lbl_PRICE.FontSize(class="num">13); class=class="str">"cmt">//--- Set the font size class=class="str">"cmt">//--- PRICE EDIT obj_Edit_PRICE.Create(class="num">0,Edit_PRICE,class="num">0,class="num">40+class="num">60,class="num">130,class="num">0,class="num">0); class=class="str">"cmt">//--- Create the price edit field obj_Edit_PRICE.Size(class="num">90,class="num">25); class=class="str">"cmt">//--- Set the edit field size obj_Edit_PRICE.ColorBackground(clrWhite); class=class="str">"cmt">//--- Set the background class="type">class="kw">color obj_Edit_PRICE.ColorBorder(clrBlack); class=class="str">"cmt">//--- Set the border class="type">class="kw">color obj_Edit_PRICE.Text(DoubleToString(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits)); class=class="str">"cmt">//--- Set the class="kw">default text to current ask price obj_Edit_PRICE.Color(clrBlack); class=class="str">"cmt">//--- Set the text class="type">class="kw">color obj_Edit_PRICE.Font("Times new roman bold"); class=class="str">"cmt">//--- Set the font style obj_Edit_PRICE.FontSize(class="num">13); class=class="str">"cmt">//--- Set the font size class=class="str">"cmt">//--- LOTS LABEL