DoEasy 函数库中的图形(第七十七部分):阴影对象类(基础篇)
◍ 给 DoEasy 补上阴影对象类
DoEasy 函数库在 2021-08-09 的第七十七次扩展里,把「阴影对象」正式收进了图形类体系,原文示例帖当时阅读量 1992、评论 2 条,说明这类偏底层的绘图封装在小圈子里有人盯。 阴影对象在 MT5 里不属于标准指标线,而是用来在图表上画半透明覆盖区(比如区间背景、事件带),过去要手写 OBJ_RECTANGLE 再调透明度,现在归到统一类里管。 这一步改进的直接好处:你开 MT5 加载 DoEasy 后,调用阴影类比自己拼对象属性少写一半参数,后续做价格行为的高亮区标记会更顺手。外汇和贵金属波动大,这类视觉辅助只降低盯盘负担,不替代风控。
「会话窗阴影为何用独立对象承载」
给 MT5 会话窗对象做阴影,有两条路:直接画在窗体画布上,或用一个躺在窗体之下的独立对象来画。我选了第二种,原因是实现和控制都更轻。 直接画在画布上的代价是,一旦要改阴影坐标,就得整体擦除、重算、逐像素重绘,还要处理阴影与下层对象的颜色合并和透明度叠加,算力消耗明显更高。独立对象则把阴影按自身颜色与透明度画好,终端自动把它叠在会话窗下方,无需手动算像素混合。 首个阴影实现借用了 ALGLIB 的高斯模糊,思路来自 Vladimir Karputov 那篇关于 CCanvas 抗锯齿与阴影的文章。阴影对象继承自图形元素基类,和会话窗本身是同一套派生体系;会话窗类里会封装快速建阴影、改属性的方法,方便直接调。 外汇与贵金属图表上跑这类自定义图形对象,属于高风险的界面扩展实验,任何视觉层改动都不影响报价风险,验证前请在策略测试器里先用模拟品种跑通。
给会话窗阴影留足画布余量
在 DoEasy 库里把会话窗阴影从概念落地,第一件事是改余量。原先每边留 5 像素画阴影,跑高斯模糊时发现画布边缘留残影——阴影理论透明了,背景却留污迹。实测模糊半径 4 像素时,每侧余量必须提到 16 像素才能干净。 Defines.mqh 中阴影默认余量由 5 改为 16;图形元素枚举里新增 Shadow 类型,建阴影对象时打这个标,后面就能一次性框选所有阴影统一处理。GraphINI.mqh 给会话窗样式补了参数:Shadow blur 管模糊半径,Form shadow color darkening 管依赖背景色时的变暗点数(背景转灰再按量压暗),Shadow X/Y axis shifts 是相对对象中心的偏移,正右下负左上,零则包边。参数总数由 5 改成 9,另加 Form outline rectangle color 做高对比框架。 GCnvElement 类补了重载。ChangeColorLightness() 原收 ARGB,现加收 color+不透明度的重载;又声明两组改饱和度的重载:把 HSL 的 S 分量左移清零即得灰调,正是阴影要的。实现里用 CColors::RGBtoHSL() 拆分量,S 乘 0.01 算新值并夹在 0–1,再 HSLtoRGB 回去。乘 0.01 只为方便——外部用整数 1/10/100 代替 0.01/0.1/1。 亮度改法同理动 L 分量,旧 ARGB 亮度法也同步乘 0.01 修正。之前漏写的设置阴影标志方法这次补实现。为做立体感,类里加 Erase() 渐变填充重载:收颜色数组、不透明度、垂直/横向渐变标志、循环标志、重绘标志,内部调 CColors::Gradient() 取色。外汇/贵金属面板搞这种浮层视觉,注意 MT5 对象堆多了会拖帧,属高风险定制。 下面这段是库里新增的消息索引片段,对应阴影对象创建失败等状态,直接抄进 Data.mqh 的消息枚举即可编译通过:
MSG_LIB_SYS_FAILED_DRAWING_ARRAY_RESIZE, class=class="str">"cmt">// Failed to change the array size of drawn buffers MSG_LIB_SYS_FAILED_COLORS_ARRAY_RESIZE, class=class="str">"cmt">// Failed to change the class="type">color array size MSG_LIB_SYS_FAILED_ARRAY_RESIZE, class=class="str">"cmt">// Failed to change the array size MSG_LIB_SYS_FAILED_ADD_BUFFER, class=class="str">"cmt">// Failed to add buffer object to the list MSG_LIB_SYS_FAILED_CREATE_BUFFER_OBJ, class=class="str">"cmt">// Failed to create "Indicator buffer" object class=class="str">"cmt">//--- CChartObjCollection MSG_CHART_COLLECTION_TEXT_CHART_COLLECTION, class=class="str">"cmt">// Chart collection MSG_CHART_COLLECTION_ERR_FAILED_CREATE_CHART_OBJ, class=class="str">"cmt">// Failed to create a new chart object MSG_CHART_COLLECTION_ERR_FAILED_ADD_CHART, class=class="str">"cmt">// Failed to add a chart object to the collection MSG_CHART_COLLECTION_ERR_CHARTS_MAX, class=class="str">"cmt">// Cannot open new chart. Number of open charts at maximum MSG_CHART_COLLECTION_CHART_OPENED, class=class="str">"cmt">// Chart opened MSG_CHART_COLLECTION_CHART_CLOSED, class=class="str">"cmt">// Chart closed MSG_CHART_COLLECTION_CHART_SYMB_CHANGED, class=class="str">"cmt">// Chart symbol changed MSG_CHART_COLLECTION_CHART_TF_CHANGED, class=class="str">"cmt">// Chart timeframe changed MSG_CHART_COLLECTION_CHART_SYMB_TF_CHANGED, class=class="str">"cmt">// Chart symbol and timeframe changed class=class="str">"cmt">//--- CForm MSG_FORM_OBJECT_TEXT_NO_SHADOW_OBJ_FIRST_CREATE_IT, class=class="str">"cmt">// No shadow object. Create it using the CreateShadowObj() method MSG_FORM_OBJECT_ERR_FAILED_CREATE_SHADOW_OBJ, class=class="str">"cmt">// Failed to create a new shadow object class=class="str">"cmt">//--- CShadowObj
◍ 图形库报错条目与画布参数定义
在 MQL5 自定义图形库里,报错文本常以俄英双字符串数组形式集中管理。例如绘制缓冲数组缩放失败、颜色数组缩放失败,以及图表对象集合创建失败等,都对应固定的双语条目,方便在 MT5 终端里直接定位异常环节。 画布底层参数多用宏定义固化。PAUSE_FOR_CANV_UPDATE 设为 16 毫秒,决定画布重绘的刷新节拍;NULL_COLOR 取 0x00FFFFFF,代表带 alpha 通道画布中的全透明像素;OUTER_AREA_SIZE 同样为 16,描述工作区外圈单边留白尺寸。 图形元素类型用枚举区分:GRAPH_ELEMENT_TYPE_ELEMENT 是普通元素,GRAPH_ELEMENT_TYPE_SHADOW_OBJ 是阴影对象,GRAPH_ELEMENT_TYPE_FORM 是窗体。若阴影对象未先经 CreateShadowObj() 创建就调用,会触发“There is no shadow object”报错,且图像过小或模糊半径过大时返回“Image size is very small or very large blur”。开 MT5 把 OUTER_AREA_SIZE 改成 32 可直观看到外圈留白翻倍。
class="macro">#define PAUSE_FOR_CANV_UPDATE(class="num">16) class=class="str">"cmt">// Canvas update frequency class="macro">#define NULL_COLOR(0x00FFFFFF) class=class="str">"cmt">// Zero for the canvas with the alpha channel class="macro">#define OUTER_AREA_SIZE(class="num">16) class=class="str">"cmt">// Size of one side of the outer area around the workspace enum ENUM_GRAPH_ELEMENT_TYPE { GRAPH_ELEMENT_TYPE_ELEMENT, class=class="str">"cmt">// Element GRAPH_ELEMENT_TYPE_SHADOW_OBJ, class=class="str">"cmt">// Shadow object GRAPH_ELEMENT_TYPE_FORM, class=class="str">"cmt">// Form };
「表单样式的参数枚举与默认值矩阵」
在 MT5 自定义图形界面里,表单(Form)的视觉风格被拆成了 9 个可控维度,从左右上下边框宽度到阴影模糊、偏移与暗化色都单独建了索引。下面这段枚举把每个维度列了出来,写面板时直接按索引取参,比硬编码字符串稳得多。 枚举 ENUM_FORM_STYLE_PARAMS 共 9 项,宏 TOTAL_FORM_STYLE_PARAMS 显式定义为 9,编译期就能做边界检查。其中 FORM_STYLE_FRAME_SHADOW_BLUR 控制阴影羽化半径,FORM_STYLE_DARKENING_COLOR_FOR_SHADOW 决定投影区相对底色的压暗比例。 二维数组 array_form_style 按「样式 × 参数」排布,首行即「Flat form」扁平风格的实参:四边边框宽统一为 3 像素,阴影不透明度 80、模糊 4、暗化 80。把这组数直接塞进 ObjCreate 后的属性回调,就能在 EURUSD 或 XAUUSD 的浮动面板上看到无立体感的浅影效果——外汇与贵金属行情波动剧烈,此类 HUD 仅作辅助参考,实盘仍属高风险。
enum ENUM_FORM_STYLE_PARAMS { FORM_STYLE_FRAME_WIDTH_LEFT, class=class="str">"cmt">// Form frame width to the left FORM_STYLE_FRAME_WIDTH_RIGHT, class=class="str">"cmt">// Form frame width to the right FORM_STYLE_FRAME_WIDTH_TOP, class=class="str">"cmt">// Form frame width on top FORM_STYLE_FRAME_WIDTH_BOTTOM, class=class="str">"cmt">// Form frame width below FORM_STYLE_FRAME_SHADOW_OPACITY, class=class="str">"cmt">// Shadow opacity FORM_STYLE_FRAME_SHADOW_BLUR, class=class="str">"cmt">// Shadow blur FORM_STYLE_DARKENING_COLOR_FOR_SHADOW, class=class="str">"cmt">// Form shadow class="type">color darkening FORM_STYLE_FRAME_SHADOW_X_SHIFT, class=class="str">"cmt">// Shadow X axis shift FORM_STYLE_FRAME_SHADOW_Y_SHIFT, class=class="str">"cmt">// Shadow Y axis shift }; class="macro">#define TOTAL_FORM_STYLE_PARAMS(class="num">9) class=class="str">"cmt">// Number of form style parameters class="type">int array_form_style[TOTAL_FORM_STYLES][TOTAL_FORM_STYLE_PARAMS]= { class=class="str">"cmt">//--- "Flat form" style parameters { class="num">3, class=class="str">"cmt">// Form frame width to the left class="num">3, class=class="str">"cmt">// Form frame width to the right class="num">3, class=class="str">"cmt">// Form frame width on top class="num">3, class=class="str">"cmt">// Form frame width below class="num">80, class=class="str">"cmt">// Shadow opacity class="num">4, class=class="str">"cmt">// Shadow blur class="num">80, class=class="str">"cmt">// Form shadow class="type">color darkening }
浮雕样式与配色枚举的落地参数
在自定义面板的视觉层,浮雕(Embossed)风格用一组固定数值控制边框与阴影。四边 frame 宽度均设为 4 像素,阴影不透明度 80、模糊 4、暗化 80,X/Y 轴偏移各 2,这套参数直接决定控件在 MT5 图表上的立体观感。 颜色主题走枚举管理,ENUM_COLOR_THEME_COLORS 定义了 4 个索引:背景、边框、外轮廓矩形、阴影。宏 TOTAL_COLOR_THEME_COLORS 显式写成 4,和枚举成员数严格对齐,改主题时漏加一项就会让数组越界。 开 MT5 把这段结构塞进你的面板基类,调一下 Shadow blur 从 4 到 0,能立刻看出浮雕变硬边——外汇与贵金属图表挂多面板时,这种视觉噪点变化可能影响盯盘专注度,属于高风险环境下的细节取舍。
{
class="num">4, class=class="str">"cmt">// Form frame width to the left
class="num">4, class=class="str">"cmt">// Form frame width to the right
class="num">4, class=class="str">"cmt">// Form frame width on top
class="num">4, class=class="str">"cmt">// Form frame width below
class="num">80, class=class="str">"cmt">// Shadow opacity
class="num">4, class=class="str">"cmt">// Shadow blur
class="num">80, class=class="str">"cmt">// Form shadow class="type">color darkening
class="num">2, class=class="str">"cmt">// Shadow X axis shift
class="num">2, class=class="str">"cmt">// Shadow Y axis shift
},
};
enum ENUM_COLOR_THEME_COLORS
{
COLOR_THEME_COLOR_FORM_BG, class=class="str">"cmt">// Form background class="type">color
COLOR_THEME_COLOR_FORM_FRAME, class=class="str">"cmt">// Form frame class="type">color
COLOR_THEME_COLOR_FORM_RECT_OUTER, class=class="str">"cmt">// Form outline rectangle class="type">color
COLOR_THEME_COLOR_FORM_SHADOW, class=class="str">"cmt">// Form shadow class="type">color
};
class="macro">#define TOTAL_COLOR_THEME_COLORS(class="num">4) class=class="str">"cmt">// Number of parameters in the class="type">color theme