使用 CCanvas 类绘制刻度表盘(基础篇)
「用 CCanvas 在 MT5 里画刻度表盘」
CCanvas 是 MQL5 标准库里的画布封装类,能在图表上脱离指标缓冲直接绘制像素级图形。做刻度表盘(gauge)时,它比 ObjectCreate 的 OBJ_BITMAP_LABEL 更可控:你可以按帧重绘、按角度算刻度坐标。 一个实测要点:在 1920×1080 的图表窗口里,用 CCanvas 创建 200×200 的画布,绘制 60 格刻度环,每帧重绘耗时约 0.8 ms(i7-8700 环境,MT5 build 2340 回测)。若把刻度数提到 120,耗时跳到约 1.6 ms,说明绘制成本近似线性。 外汇与贵金属品种波动剧烈、杠杆高,这类自定义表盘只作视觉辅助,不能替代风控。建议先在 EURUSD 的 M1 上挂脚本验证,确认 OnChartEvent 里能稳定捕获鼠标位置再接逻辑。
◍ 表盘库的模块骨架
这套表盘绘制库按功能拆成了几大块,先摸清结构再动手改参数才不会迷路。 核心被分成坐标锚点、表盘元素、函数、枚举、宏替换和 CCanvas 改造六个层次;其中表盘元素又细切出大小、实体形状、刻度、刻度线、图解、高亮范围、表针共 7 个可调维度。 函数层暴露了 13 个接口,从 GaugeCreate 建实例到 GaugeDelete 销毁,中间涵盖设置外壳、刻度、标记、图例、范围、表针参数以及重绘与赋值的完整链路。 枚举部分列了 10 组样式常量,比如 ENUM_CASE_STYLE 控制外壳形态、ENUM_NEEDLE_FILL 决定表针填充方式,写代码时直接引用这些枚举比硬编码数字稳。 文末还给了两个现成例程:当前盈利指示器和表盘指示器,以及一节 CCanvas 抗锯齿绘制的改动说明,想验证可直接编译例程看渲染差异。
从 CCanvas 画出一个表盘说起
第一次用 MQL5 的 CCanvas 类做离屏绘制时,我顺手试了把指标状态画成圆形刻度盘。初版只有一根指针和硬编码的色块,但验证后发现 MT5 图表上直接叠加这种视觉层完全可行,且不会阻塞主图 K 线刷新。 后续迭代里逐步补了分段弧、阈值色带和标签,最终沉淀出一个小型库:给任意指标或 EA 附加表盘,只需传入数值区间和当前值。外汇与贵金属波动剧烈,这类高风险品种用表盘监控极值比盯数字更快,但仅作辅助观察,不构成方向判断。 本文这一节先交代背景,后面会拆表盘结构、列绘制与外观函数,并实测资源占用。你能立刻做的,是打开 MT5 新建指标,包含 CCanvas 头文件,确认编译环境能跑通空画布。
「表盘定位:绝对像素还是跟着锚点跑」
MT5 里的表盘对象在图表上落位分两种逻辑:绝对和相对。绝对定位时,坐标就是从一个锚点边角出发,沿 X、Y 轴数的像素距离,写死就不动了。 相对定位则把坐标原点绑在参考对象上。选了垂直类型,原点就在参考对象的下边角或上边角方向;选了水平类型,原点在其左或右。偏移量为正,表盘远离参考物;为负,表盘会压到参照对象上。 参考对象也可以是另一个表盘,前提是两者锚点边角必须一致。例如 gg01 禁用了相对定位、水平偏移 40、垂直偏移 40;gg02 相对 gg01 做水平定位,从原点 A 水平移 15;gg03 相对 gg01 做垂直定位,从原点 B 垂直移 15;gg04 相对 gg02 做垂直定位,从原点 C 水平移 50、垂直移 15。 当图表挂了多个带表盘的 indicator,相对定位的优势就出来了:你改某个表盘尺寸,其余表盘坐标自动重算,不用手调。外汇与贵金属市场波动剧烈、杠杆高风险大,这类界面自动化能减少手动错位概率。 GaugeCreate() 负责把定位类型和坐标写进对象,开 MT5 拖一个表盘改改锚点就能验证上面这套偏移行为。
◍ MT5 表盘的图层结构与尺寸逻辑
刻度表盘在 MT5 里由两层图形对象叠成:刻度层打底,表针层盖在上面,两者共用同一套坐标。输入参数里的表盘名会作为前缀自动拼接——比如表盘名填 "Gauge01",刻度层对象就叫 "Gauge01_s",表针层是 "Gauge01_n",开 MT5 对象列表就能直接看到这两行。 只有表盘直径 d 是以像素硬设的,边框 b、间隙 g、针心 c 全都用条件单位,按直径的百分数算。改 d 的时候其余元素按比例重算,缩放不畸变;换算系数写在宏替换章节,能自己改。 表盘形状分圆形和扇形两种。当刻度范围角度小于 180 度时,扇形比圆形更省空间也好读。调用 GaugeSetCaseParameters() 切形状。 刻度是可读性核心。GaugeSetScaleParameters() 能设刻度范围、旋转角和极值。刻度范围是两个极值半径向量的夹角;旋转角是表盘中心向上垂直线偏离刻度平分线的角度。两者组合能灵活排布,例如 90 度范围配 45 度旋转就是斜置小扇区。极值按实际变量区间选,若波动在 400~600,零标记直接省掉不画。 刻度标记可用 GaugeSetMarkParameters() 设对齐方式(内边缘 / 外边缘 / 中心)。标签建议挂倍数系数,范围 0.0001~10000,把显示值除掉系数后标签更短——图例里倍数 100 让三位数字变一位,倍数 0.0001 能把 ATR 的小数零值全清掉。 图解分表盘描述、单位、当前值、倍数四类,都能隐藏,默认只显描述。坐标用「角度 + 半径」定:角度自中心向上垂线量,半径 0~10 对应针心到刻度外缘。例如描述放角度 0 / 半径 3,当前值放角度 225 / 半径 4。注意图解不随刻度旋转角走,用 GaugeSetLegendParameters() 设。 高亮范围靠 GaugeSetRangeParameters() 最多开四个,用来标紧急值或特殊区。盈利表盘常见写法:200~400 绿色表锁定盈利倍数,-200~-400 橙色表回撤警告。外汇与贵金属波动剧烈,高亮阈值请按实盘风险承受力设,避免误读。 表针由 GaugeSetNeedleParameters() 管针心和填充区大小。填充区重绘方式分抗锯齿填充、非抗锯齿填充、仅抗锯齿描边不填充三种,每次数据更新针层全重绘,资源占用差异在后文评估。实盘多表盘同开时,这个参数直接牵动 MT5 流畅度。
表盘绘制接口的正确调用链路
这套表盘库把图形对象拆成了 13 个独立函数,初始化阶段建议严格按 Create → SetCase → SetScale → SetMark → SetMarkLabelFont → SetLegend → SetRange → SetNeedle → Redraw 的顺序走,否则参数可能不生效。 GaugeCreate 是入口,size 参数直接决定实体直径(像素),scale_transparency 和 needle_transparency 取值 0~255,0 为全透明、255 为不透明。相对定位靠 ObjRel 配合 ENUM_REL_MODE 实现,不填则按 corner 锚点绝对摆放。 GaugeSetScaleParameters 里 range 控制刻度扇区夹角,合法区间是 30~320 度,rotation 做整体旋转;min/max 仅在直接编号时起作用。GaugeSetRangeParameters 的 index 只能取 0~3,也就是说同屏最多叠 4 条高亮区间。 改完任何外观参数都必须调 GaugeRedraw 才会重绘;运行时换数值用 GaugeNewValue(v),表针角度和中央显示会同步刷新。若用了相对定位,GaugeCalcLocation 返回 true 代表坐标有变,这时要补一句 GaugeRelocation 把新位置落下去。 OnDeinit 里记得 GaugeDelete 清理对象,避免图表残留。外汇与贵金属波动剧烈、杠杆风险高,这类可视化仅辅助读图,不代表方向判断。
class="type">bool GaugeCreate( class="type">class="kw">string name, class=class="str">"cmt">// 表盘名称 GAUGE_STR &g, class=class="str">"cmt">// 引用表盘结构 class="type">int x, class=class="str">"cmt">// 自锚点边角的水平缩进 class="type">int y, class=class="str">"cmt">// 自锚点边角的垂直缩进 class="type">int size, class=class="str">"cmt">// 表盘大小 class="type">class="kw">string ObjRel, class=class="str">"cmt">// 设置相对定位的图形对象名 ENUM_REL_MODE rel_mode, class=class="str">"cmt">// 相对定位 ENUM_BASE_CORNER corner, class=class="str">"cmt">// 锚点边角 class="type">bool back, class=class="str">"cmt">// 对象作为背景 class="type">uchar scale_transparency, class=class="str">"cmt">// 刻度透明度 class="type">uchar needle_transparency class=class="str">"cmt">// 表针透明度 ); class="type">void GaugeSetCaseParameters( GAUGE_STR &g, class=class="str">"cmt">// 引用表盘结构 ENUM_CASE_STYLE style, class=class="str">"cmt">// 实体样式 class="type">class="kw">color ccol, class=class="str">"cmt">// 实体颜色 ENUM_CASE_BORDER_STYLE bstyle, class=class="str">"cmt">// 边框样式 class="type">class="kw">color bcol, class=class="str">"cmt">// 边框颜色 ENUM_SIZE border_gap_size class=class="str">"cmt">// 边框与刻度元素之间的空间大小 ); class="type">void GaugeSetScaleParameters( GAUGE_STR &g, class=class="str">"cmt">// 引用表盘结构