在MQL5中创建交互式图形用户界面(第1部分):制作面板·进阶篇
🛠️

在MQL5中创建交互式图形用户界面(第1部分):制作面板·进阶篇

(2/3)· 很多交易者装了第三方 EA 却不会改界面,本篇用 6 步把面板骨架自己立起来

含代码示例偏理论 第 2/3 篇
直接抄别人 Panel 代码却连控件坐标都调不明白,改个按钮就满屏错位。不懂 MQL5 图形对象底层逻辑,加个表情符号都能把布局挤崩。先理清面板组装顺序,比盲目堆功能重要得多。

◍ 按钮对象的属性落地细节

在 MT5 里用 OBJ_BUTTON 做自定义面板时,边框宽度和颜色只在 borderType 设为 flat 时才生效,其余状态写了也白写。下面这段把边框、前景层级和可选中状态一次性锁死,避免按钮被误拖或被 K 线盖住。 ObjectSetInteger(0, objName, OBJPROP_WIDTH, widthBorder); // 边框线宽,仅 flat 边框有效 ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBorder); // 边框颜色,仅 flat 边框有效 ObjectSetInteger(0, objName, OBJPROP_BACK, false); // 不放入背景层 ObjectSetInteger(0, objName, OBJPROP_STATE, false); // 不进入 hover 高亮态 ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // 禁止鼠标选中 ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // 初始未选中 ChartRedraw(0); // 强制重绘当前图表 return(true); // 创建与属性设置均成功才返回 true createButton 函数的入参给了默认值:字体默认 "Arial Rounded MT Bold"、字号 12、文字色 clrBlack、背景与边框色 clrNONE。这意味着你不传 clrBg 时按钮就是透明底,传了 clrBorder 也不会显示——因为 borderType 没在这段里设成 flat。 实际验证时把 CORNER_LEFT_UPPER 和 XDISTANCE/YDISTANCE 调小到 10~20 像素,按钮就会贴左上角;外汇与贵金属图表波动剧烈,这类浮动面板在高波动时段可能被价格跳空遮挡,属于高风险环境下的显示异常,建议先在模拟盘跑通再上实盘。

MQL5 / C++
ObjectSetInteger(class="num">0, objName, OBJPROP_WIDTH, widthBorder); class=class="str">"cmt">// Border width(only if borderType is flat)
ObjectSetInteger(class="num">0, objName, OBJPROP_COLOR, clrBorder); class=class="str">"cmt">// Border class="type">class="kw">color (only if borderType is flat)
ObjectSetInteger(class="num">0, objName, OBJPROP_BACK, false); class=class="str">"cmt">// Not a background object
ObjectSetInteger(class="num">0, objName, OBJPROP_STATE, false); class=class="str">"cmt">// Not selectable
ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTABLE, false); class=class="str">"cmt">// Not selectable
ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTED, false); class=class="str">"cmt">// Not selected

ChartRedraw(class="num">0); class=class="str">"cmt">// Redraw the chart

class="kw">return (true); class=class="str">"cmt">// Return true if object creation and class="kw">property settings are successful
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Function to create button |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool createButton(class="type">class="kw">string objName, class="type">int xD, class="type">int yD, class="type">int xS, class="type">int yS,
                  class="type">class="kw">string txt = "", class="type">class="kw">color clrTxt = clrBlack, class="type">int fontSize = class="num">12,
                  class="type">class="kw">color clrBg = clrNONE, class="type">class="kw">color clrBorder = clrNONE,
                  class="type">class="kw">string font = "Arial Rounded MT Bold") {
  class=class="str">"cmt">// Reset any previous errors
  ResetLastError();
  class=class="str">"cmt">// Attempt to create the button object
  if (!ObjectCreate(class="num">0, objName, OBJ_BUTTON, class="num">0, class="num">0, class="num">0)) {
    class=class="str">"cmt">// Print an error message if creation fails
    Print(__FUNCTION__, ": failed to create the button! Error code = ", _LastError);
    class="kw">return (false);
  }
  class=class="str">"cmt">// Set properties for the button
  ObjectSetInteger(class="num">0, objName, OBJPROP_XDISTANCE, xD); class=class="str">"cmt">// X distance from the corner
  ObjectSetInteger(class="num">0, objName, OBJPROP_YDISTANCE, yD); class=class="str">"cmt">// Y distance from the corner
  ObjectSetInteger(class="num">0, objName, OBJPROP_XSIZE, xS); class=class="str">"cmt">// Width of the button
  ObjectSetInteger(class="num">0, objName, OBJPROP_YSIZE, yS); class=class="str">"cmt">// Height of the button
  ObjectSetInteger(class="num">0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); class=class="str">"cmt">// Positioning corner
  ObjectSetString(class="num">0, objName, OBJPROP_TEXT, txt); class=class="str">"cmt">// Text displayed on the button

按钮与输入框的属性落地细节

在 MT5 里用 ObjectSetInteger / ObjectSetString 给 GUI 对象填属性时,按钮(OBJ_BUTTON)和编辑框(OBJ_EDIT)的很多参数是共通的。上面这段把文字色、字号、字体、背景色、边框色一次性设完,再把 OBJPROP_BACK 设 false 让背景透明、OBJPROP_SELECTABLE 与 OBJPROP_SELECTED 都 false,意味着这个按钮不参与鼠标点选,纯粹做展示或触发用。 注意 OBJPROP_FONTSIZE 默认传 12,字体名写死 "Arial Rounded MT Bold";若你机器没装这款字体,MT5 会静默回退到系统默认,界面可能偏瘦。创建完必须调 ChartRedraw(0) 才会立刻重绘,否则对象已存在但屏幕不刷,容易误以为代码没跑。 编辑框函数 createEdit 的入参给了默认值:clrBg=clrNONE、clrBorder=clrNONE,也就是无背景无边框,视觉上像裸文本框。xD/yD 是距图表左上角的像素偏移,xS/yS 是宽高,这套坐标和按钮用的是同一套锚定逻辑,写面板时可以直接复用。 外汇与贵金属杠杆高、滑点大,任何 EA 面板都只是辅助,参数填错可能导致误下单,实盘前务必在策略测试器里用可视化模式点一遍。

MQL5 / C++
ObjectSetInteger(class="num">0, objName, OBJPROP_COLOR, clrTxt); class=class="str">"cmt">// Text class="type">class="kw">color
ObjectSetInteger(class="num">0, objName, OBJPROP_FONTSIZE, fontSize); class=class="str">"cmt">// Font size
ObjectSetString(class="num">0, objName, OBJPROP_FONT, font); class=class="str">"cmt">// Font name
ObjectSetInteger(class="num">0, objName, OBJPROP_BGCOLOR, clrBg); class=class="str">"cmt">// Background class="type">class="kw">color
ObjectSetInteger(class="num">0, objName, OBJPROP_BORDER_COLOR, clrBorder); class=class="str">"cmt">// Border class="type">class="kw">color
ObjectSetInteger(class="num">0, objName, OBJPROP_BACK, false); class=class="str">"cmt">// Transparent background
ObjectSetInteger(class="num">0, objName, OBJPROP_STATE, false); class=class="str">"cmt">// Button state(not pressed)
ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTABLE, false); class=class="str">"cmt">// Not selectable
ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTED, false); class=class="str">"cmt">// Not selected
class=class="str">"cmt">// Redraw the chart to display the button
ChartRedraw(class="num">0);
class="kw">return (true); class=class="str">"cmt">// Button creation successful
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Function to create edit field |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool createEdit(class="type">class="kw">string objName, class="type">int xD, class="type">int yD, class="type">int xS, class="type">int yS,
                class="type">class="kw">string txt = "", class="type">class="kw">color clrTxt = clrBlack, class="type">int fontSize = class="num">12,
                class="type">class="kw">color clrBg = clrNONE, class="type">class="kw">color clrBorder = clrNONE,
                class="type">class="kw">string font = "Arial Rounded MT Bold") {
  class=class="str">"cmt">// Reset any previous errors
  ResetLastError();
  class=class="str">"cmt">// Attempt to create the edit object
  if (!ObjectCreate(class="num">0, objName, OBJ_EDIT, class="num">0, class="num">0, class="num">0)) {
    class=class="str">"cmt">// Print an error message if creation fails
    Print(__FUNCTION__, ": failed to create the edit! Error code = ", _LastError);
    class="kw">return (false);
  }
  class=class="str">"cmt">// Set properties for the edit field
  ObjectSetInteger(class="num">0, objName, OBJPROP_XDISTANCE, xD); class=class="str">"cmt">// X distance from the corner
  ObjectSetInteger(class="num">0, objName, OBJPROP_YDISTANCE, yD); class=class="str">"cmt">// Y distance from the corner
  ObjectSetInteger(class="num">0, objName, OBJPROP_XSIZE, xS); class=class="str">"cmt">// Width of the edit field
  ObjectSetInteger(class="num">0, objName, OBJPROP_YSIZE, yS); class=class="str">"cmt">// Height of the edit field

「用代码在MT5图表上钉一个可编辑文本框」

想在MT5图表左上角放一个能手动改内容的编辑框,靠 ObjectSetInteger / ObjectSetString 把坐标锚点、文字、配色一次性写死即可。下面这段把 CORNER_LEFT_UPPER 设成锚点,文本框默认不只读、不进背景层、不被选中,属于典型的 HUD 控件初始化。 ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // 锚定左上角 ObjectSetString(0, objName, OBJPROP_TEXT, txt); // 填入默认文本 ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // 文字颜色 ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // 字号,默认常填12 ObjectSetString(0, objName, OBJPROP_FONT, font); // 字体名 ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // 背景色 ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // 边框色 ObjectSetInteger(0, objName, OBJPROP_ALIGN, ALIGN_LEFT); // 左对齐 ObjectSetInteger(0, objName, OBJPROP_READONLY, false); // 允许编辑 ObjectSetInteger(0, objName, OBJPROP_BACK, false); // 不透明背景 ObjectSetInteger(0, objName, OBJPROP_STATE, false); // 非激活态 ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // 不可被点选 ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // 未选中 ChartRedraw(0); // 重绘图表 return(true); // 创建成功 标签类对象走另一套:createLabel 用 OBJ_LABEL 建对象,先 ResetLastError 清错,再 ObjectCreate 失败就 Print 出 _LastError 码。外汇与贵金属杠杆高、滑点大,这类图表控件只辅助观察,不构成任何方向暗示。 开 MT5 按 F4 粘入这段,把 objName 改成自己前缀,跑完能在左上角看到可点进去改字的框;若 Print 报 4200 类错误,通常是名字冲突,换名即可。

MQL5 / C++
ObjectSetInteger(class="num">0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); class=class="str">"cmt">// Positioning corner
ObjectSetString(class="num">0, objName, OBJPROP_TEXT, txt); class=class="str">"cmt">// Default text in the edit field
ObjectSetInteger(class="num">0, objName, OBJPROP_COLOR, clrTxt); class=class="str">"cmt">// Text class="type">class="kw">color
ObjectSetInteger(class="num">0, objName, OBJPROP_FONTSIZE, fontSize); class=class="str">"cmt">// Font size
ObjectSetString(class="num">0, objName, OBJPROP_FONT, font); class=class="str">"cmt">// Font name
ObjectSetInteger(class="num">0, objName, OBJPROP_BGCOLOR, clrBg); class=class="str">"cmt">// Background class="type">class="kw">color
ObjectSetInteger(class="num">0, objName, OBJPROP_BORDER_COLOR, clrBorder); class=class="str">"cmt">// Border class="type">class="kw">color
ObjectSetInteger(class="num">0, objName, OBJPROP_ALIGN, ALIGN_LEFT); class=class="str">"cmt">// Text alignment(left-aligned)
ObjectSetInteger(class="num">0, objName, OBJPROP_READONLY, false); class=class="str">"cmt">// Edit field is not read-only
ObjectSetInteger(class="num">0, objName, OBJPROP_BACK, false); class=class="str">"cmt">// Transparent background
ObjectSetInteger(class="num">0, objName, OBJPROP_STATE, false); class=class="str">"cmt">// Edit field state(not active)
ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTABLE, false); class=class="str">"cmt">// Not selectable
ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTED, false); class=class="str">"cmt">// Not selected
class=class="str">"cmt">// Redraw the chart to display the edit field
ChartRedraw(class="num">0);
class="kw">return (true); class=class="str">"cmt">// Edit field creation successful
}
ObjectSetInteger(class="num">0, objName, OBJPROP_ALIGN, ALIGN_LEFT); class=class="str">"cmt">// Text alignment(left-aligned)
ObjectSetInteger(class="num">0, objName, OBJPROP_READONLY, false); class=class="str">"cmt">// Edit field is not read-only
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|  Function to create text label                                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool createLabel(class="type">class="kw">string objName, class="type">int xD, class="type">int yD,
                 class="type">class="kw">string txt, class="type">class="kw">color clrTxt = clrBlack, class="type">int fontSize = class="num">12,
                 class="type">class="kw">string font = "Arial Rounded MT Bold") {
  class=class="str">"cmt">// Reset any previous errors
  ResetLastError();
  class=class="str">"cmt">// Attempt to create the label object
  if (!ObjectCreate(class="num">0, objName, OBJ_LABEL, class="num">0, class="num">0, class="num">0)) {
    class=class="str">"cmt">// Print an error message if creation fails
    Print(__FUNCTION__, ": failed to create the label! Error code = ", _LastError);
    class="kw">return (false);

◍ 用 OBJPROP 把标签钉死在左上角

在 MT5 里画一个不可选中的文字标签,核心是把角落、偏移和显示属性一次性写进对象。下面这段收尾代码把标签定位到左上角(CORNER_LEFT_UPPER),XD/YD 控制距角落的像素,背景透明、不可选中,最后 ChartRedraw(0) 强制重绘才看得见。 ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD) 设水平偏移,ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD) 设垂直偏移;OBJPROP_BACK 设 false 让标签浮在 K 线上方而不是沉到背景。OBJPROP_SELECTABLE 与 OBJPROP_SELECTED 都置 false,实盘挂 EA 时不会误点到它。 实际调用时,createRecLabel(MAIN_REC,10,30,250,400,clrWhite,1,clrBlack) 表示距左 10px、距上 30px、宽 250 高 400 的白底黑字框;而 MAIN_SUB_REC 用 15/35/240/390 的浅蓝底(clrLightBlue)做内嵌层,比外层各缩 5px 形成边框错觉。MAIN_LINE_UP 把高度压成 1px、MAIN_LINE_DN 宽度压成 1px,用 BORDER_RAISED 做出两条立体分隔线。外汇与贵金属波动剧烈,这类覆盖层只辅助读图,不改交易决策。

MQL5 / C++
   }
   class=class="str">"cmt">// Set properties for the label
   ObjectSetInteger(class="num">0, objName, OBJPROP_XDISTANCE, xD); class=class="str">"cmt">// X distance from the corner
   ObjectSetInteger(class="num">0, objName, OBJPROP_YDISTANCE, yD); class=class="str">"cmt">// Y distance from the corner
   ObjectSetInteger(class="num">0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); class=class="str">"cmt">// Positioning corner
   ObjectSetString(class="num">0, objName, OBJPROP_TEXT, txt); class=class="str">"cmt">// Text displayed on the label
   ObjectSetInteger(class="num">0, objName, OBJPROP_COLOR, clrTxt); class=class="str">"cmt">// Text class="type">class="kw">color
   ObjectSetInteger(class="num">0, objName, OBJPROP_FONTSIZE, fontSize); class=class="str">"cmt">// Font size
   ObjectSetString(class="num">0, objName, OBJPROP_FONT, font); class=class="str">"cmt">// Font name
   ObjectSetInteger(class="num">0, objName, OBJPROP_BACK, false); class=class="str">"cmt">// Transparent background
   ObjectSetInteger(class="num">0, objName, OBJPROP_STATE, false); class=class="str">"cmt">// Label state(not active)
   ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTABLE, false); class=class="str">"cmt">// Not selectable
   ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTED, false); class=class="str">"cmt">// Not selected
   class=class="str">"cmt">// Redraw the chart to display the label
   ChartRedraw(class="num">0);
   class="kw">return (true); class=class="str">"cmt">// Label creation successful
}

用 GUI 对象拼出交易面板骨架

在 MT5 自定义指标或 EA 里做盯盘面板,第一步不是算信号,而是把界面元素用对象函数堆出来。下面这段就是典型做法:先打标题,再用 Webdings 字体把字符映射成图标,最后用矩形和文字标签分区。 createLabel(LABEL_NAME,25,35,"DashBoard v1.0",clrBlue,14,"Cooper Black"); 这一行在坐标 (25,35) 处放了蓝色 14 号字标题,字体 Cooper Black。紧跟着用 #define 把 ICON_HEART 等宏指向字符串,再分别以 Webdings 字体画 'Y' '@' 'h' 三个字符——它们实际显示成心形、工具、小车图标,x 坐标 190/210/230 错开 20 像素避免重叠。 分区靠 createRecLabel 画 1 像素高的浅灰矩形当分隔线:LINE1 在 y=60,LINE2 在 y=87,宽度都是 240-10=230。中间 65 像素高度内排了 Close / Market / Profit / Loss / Pend'n 五个标签,x 从 25 起每 45 像素一个,用 Impact 字体区分颜色——盈利绿、亏损红,未平仓深灰。 手调手数区更实在:BTN_LOTS 按钮在 (25,95) 宽 130 高 25,左侧写 LotSize 小字,右侧用 Wingdings 3 的字符码 240 画下拉箭头。EDIT_LOTS 编辑框在 x=165 处预设 "0.01" 手,白底黑字。外汇和贵金属波动剧烈,面板预设小手数只是降低试错成本,实际风险仍高,开 MT5 把这段代码贴进脚本就能看到布局。

MQL5 / C++
  createLabel(LABEL_NAME,class="num">25,class="num">35,"DashBoard v1.class="num">0",clrBlue,class="num">14,"Cooper Black");
class="macro">#define ICON_HEART "ICON_HEART"
class="macro">#define ICON_TOOL "ICON_TOOL"
class="macro">#define ICON_CAR "ICON_CAR"
...
  createLabel(ICON_HEART,class="num">190,class="num">35,"Y",clrRed,class="num">15,"Webdings");
  createLabel(ICON_TOOL,class="num">210,class="num">35,"@",clrBlue,class="num">15,"Webdings");
  createLabel(ICON_CAR,class="num">230,class="num">35,"h",clrBlack,class="num">15,"Webdings");
class="macro">#define LINE1 "LINE1"
class="macro">#define BTN_CLOSE "BTN_CLOSE"
class="macro">#define BTN_MARKET "BTN_MARKET"
class="macro">#define BTN_PROFIT "BTN_PROFIT"
class="macro">#define BTN_LOSS "BTN_LOSS"
class="macro">#define BTN_PENDING "BTN_PENDING"
class="macro">#define LINE2 "LINE2"
...
  createRecLabel(LINE1,class="num">15+class="num">10,class="num">60,class="num">240-class="num">10,class="num">1,C&class="macro">#x27;class="num">245,class="num">245,class="num">245&class="macro">#x27;,class="num">1,clrNONE,BORDER_RAISED);
  createLabel(BTN_CLOSE,class="num">25,class="num">65,"Close",clrBlack,class="num">13,"Impact");
  createLabel(BTN_MARKET,class="num">70,class="num">65,"Market",clrDarkRed,class="num">13,"Impact");
  createLabel(BTN_PROFIT,class="num">125,class="num">65,"Profit",clrGreen,class="num">13,"Impact");
  createLabel(BTN_LOSS,class="num">170,class="num">65,"Loss",clrRed,class="num">13,"Impact");
  createLabel(BTN_PENDING,class="num">205,class="num">65,"Pend&class="macro">#x27;n",clrDarkGray,class="num">13,"Impact");
  createRecLabel(LINE2,class="num">15+class="num">10,class="num">87,class="num">240-class="num">10,class="num">1,C&class="macro">#x27;class="num">245,class="num">245,class="num">245&class="macro">#x27;,class="num">1,clrNONE,BORDER_RAISED);

class="macro">#define BTN_LOTS "BTN_LOTS"
class="macro">#define LABEL_LOTS "LABEL_LOTS"
class="macro">#define ICON_DROP_DN1 "ICON_DROP_DN1"
  createButton(BTN_LOTS,class="num">25,class="num">95,class="num">130,class="num">25,"",clrBlack,class="num">12,C&class="macro">#x27;class="num">210,class="num">210,class="num">210&class="macro">#x27;,C&class="macro">#x27;class="num">150,class="num">150,class="num">150&class="macro">#x27;);
  createLabel(LABEL_LOTS,class="num">25+class="num">10,class="num">95+class="num">5,"LotSize",clrBlack,class="num">9);
  createLabel(ICON_DROP_DN1,class="num">130,class="num">95+class="num">5,CharToString(class="num">240),C&class="macro">#x27;class="num">070,class="num">070,class="num">070&class="macro">#x27;,class="num">20,"Wingdings class="num">3");
class="macro">#define EDIT_LOTS "EDIT_LOTS"
class="macro">#define BTN_P1 "BTN_P1"
class="macro">#define BTN_M1 "BTN_M1"
...
  createEdit(EDIT_LOTS,class="num">165,class="num">95,class="num">60,class="num">25,"class="num">0.01",clrBlack,class="num">14,clrWhite,C&class="macro">#x27;class="num">100,class="num">100,class="num">100&class="macro">#x27;,"Callibri");

「面板上的止损止盈与步进按钮布局」

在 MT5 自定义面板里,SL 与 TP 的输入区沿 Y 轴以 30 像素为步距向下排布:SL 块起点 y=125(95+30),TP 块再下移 30 到 y=155。每个块左侧是 130×25 的按钮底框,中间用 Wingdings 3 的字符 240 画下拉箭头,右侧 60×25 的编辑框默认填 100.0,代表初始止损止盈点数。 步进按钮成对贴在编辑框右边:BTN_P 系列画 Webdings 的 "5"(形似上三角),BTN_M 系列画 "6"(下三角),尺寸固定 20×12。以 SL 为例,加号钮位于 (225,125),减号钮位于 (225,137),刚好覆盖编辑框右侧 12 像素高的两格。 这种坐标写法把所有 magic number 写死在调用参数里,改布局就得动代码。若你想把 SL/TP 默认从 100.0 改成 50.0,直接搜 createEdit 里 "100.0" 字符串替换即可,但外汇与贵金属波动剧烈,面板预设点数不等于实际风险,开仓前仍须在 MT5 里核对点值。

MQL5 / C++
  createButton(BTN_P1,class="num">225,class="num">95,class="num">20,class="num">12,"class="num">5",clrBlack,class="num">12,clrLightGray,C&class="macro">#x27;class="num">100,class="num">100,class="num">100&class="macro">#x27;,"Webdings");
  createButton(BTN_M1,class="num">225,class="num">95+class="num">12,class="num">20,class="num">12,"class="num">6",clrBlack,class="num">12,clrLightGray,C&class="macro">#x27;class="num">100,class="num">100,class="num">100&class="macro">#x27;,"Webdings");
class="macro">#define BTN_SL "BTN_SL"
class="macro">#define LABEL_SL "LABEL_SL"
class="macro">#define ICON_DROP_DN2 "ICON_DROP_DN2"
class="macro">#define EDIT_SL "EDIT_SL"
class="macro">#define BTN_P2 "BTN_P2"
class="macro">#define BTN_M2 "BTN_M2"
class="macro">#define BTN_TP "BTN_TP"
class="macro">#define LABEL_TP "LABEL_TP"
class="macro">#define ICON_DROP_DN3 "ICON_DROP_DN3"
class="macro">#define EDIT_TP "EDIT_TP"
class="macro">#define BTN_P3 "BTN_P3"
class="macro">#define BTN_M3 "BTN_M3"
  createButton(BTN_SL,class="num">25,class="num">95+class="num">30,class="num">130,class="num">25,"",clrBlack,class="num">12,C&class="macro">#x27;class="num">210,class="num">210,class="num">210&class="macro">#x27;,C&class="macro">#x27;class="num">150,class="num">150,class="num">150&class="macro">#x27;);
  createLabel(LABEL_SL,class="num">35,class="num">95+class="num">30,"SL Pips",clrBlack,class="num">14);
  createLabel(ICON_DROP_DN2,class="num">130,class="num">100+class="num">30,CharToString(class="num">240),C&class="macro">#x27;class="num">070,class="num">070,class="num">070&class="macro">#x27;,class="num">20,"Wingdings class="num">3");
  createEdit(EDIT_SL,class="num">165,class="num">95+class="num">30,class="num">60,class="num">25,"class="num">100.0",clrBlack,class="num">13,clrWhite,C&class="macro">#x27;class="num">100,class="num">100,class="num">100&class="macro">#x27;,"Callibri");
  createButton(BTN_P2,class="num">225,class="num">95+class="num">30,class="num">20,class="num">12,"class="num">5",clrBlack,class="num">12,clrLightGray,C&class="macro">#x27;class="num">100,class="num">100,class="num">100&class="macro">#x27;,"Webdings");
  createButton(BTN_M2,class="num">225,class="num">107+class="num">30,class="num">20,class="num">12,"class="num">6",clrBlack,class="num">12,clrLightGray,C&class="macro">#x27;class="num">100,class="num">100,class="num">100&class="macro">#x27;,"Webdings");
  createButton(BTN_TP,class="num">25,class="num">95+class="num">30+class="num">30,class="num">130,class="num">25,"",clrBlack,class="num">12,C&class="macro">#x27;class="num">210,class="num">210,class="num">210&class="macro">#x27;,C&class="macro">#x27;class="num">150,class="num">150,class="num">150&class="macro">#x27;);
  createLabel(LABEL_TP,class="num">35,class="num">95+class="num">30+class="num">30,"TP Pips",clrBlack,class="num">14);
  createLabel(ICON_DROP_DN3,class="num">130,class="num">100+class="num">30+class="num">30,CharToString(class="num">240),C&class="macro">#x27;class="num">070,class="num">070,class="num">070&class="macro">#x27;,class="num">20,"Wingdings class="num">3");
  createEdit(EDIT_TP,class="num">165,class="num">95+class="num">30+class="num">30,class="num">60,class="num">25,"class="num">100.0",clrBlack,class="num">13,clrWhite,C&class="macro">#x27;class="num">100,class="num">100,class="num">100&class="macro">#x27;,"Callibri");
  createButton(BTN_P3,class="num">225,class="num">95+class="num">30+class="num">30,class="num">20,class="num">12,"class="num">5",clrBlack,class="num">12,clrLightGray,C&class="macro">#x27;class="num">100,class="num">100,class="num">100&class="macro">#x27;,"Webdings");
把面板骨架检查交给小布
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到对象层级与重叠预警,你专注决策而非调坐标。

常见问题

前者依赖终端图形对象系统、易做悬停但层级管理烦;后者走内存绘制、自由度高但需自写命中检测。进阶面板常混用。
不会编译失败,但文件会落到错误目录,后续 #include 路径全部断裂,表现为找不到自定义类。
目前小布盯盘侧重行情诊断与对象预警,不输出 EA 源码,但可对照其面板示例反推你的布局参数。
多因 OnTimer 里无差别重绘全部标签,应按脏标记只刷新变动控件,并放宽定时器周期。
需拦截 CHARTEVENT_OBJECT_DRAG 并锁定 Z 轴顺序,同时屏蔽图表自身拖拽热区重叠。