DoEasy 函数库中的图形(第九十二部分):标准图形对象记忆类。 对象属性变更历史记录·进阶篇
(2/3)·对象重命名后旧状态去哪了?本篇给标准图形对象装上变更历史记忆,滚动图表即可还原过往交易日属性
「图形对象排序枚举的剩余字段」
在 MT5 的 ObjectsTotal 与自定义排序逻辑里,SORT_BY_GRAPH_OBJ_* 这组枚举覆盖了图形对象的大量可排序属性。上面这段列出了从 SORT_BY_GRAPH_OBJ_ALIGN 到 SORT_BY_GRAPH_OBJ_YSIZE 共 24 个具体枚举值,每一个都对应对象某一可见或结构属性。 比如 SORT_BY_GRAPH_OBJ_RAY_LEFT 按射线是否向左延伸排序,SORT_BY_GRAPH_OBJ_XDISTANCE 按对象基准角沿 X 轴的像素距离排序,SORT_BY_GRAPH_OBJ_CHART_OBJ_PERIOD 则针对嵌入图表对象的周期字段排序。 如果你在写 EA 或指标时需要批量整理画在图上的对象,可以直接用这些枚举做 ObjectsSort() 的入参。开 MT5 按 F4 进 MetaEditor,搜 SORT_BY_GRAPH_OBJ 就能看到完整定义,复制这段枚举到自己的工具函数里就能跑。
SORT_BY_GRAPH_OBJ_ALIGN, class=class="str">"cmt">// Sort by the "Horizontal text alignment in the Entry field" class="kw">property SORT_BY_GRAPH_OBJ_FONTSIZE, class=class="str">"cmt">// Sort by font size SORT_BY_GRAPH_OBJ_RAY_LEFT, class=class="str">"cmt">// Sort by "Ray goes to the left" class="kw">property SORT_BY_GRAPH_OBJ_RAY_RIGHT, class=class="str">"cmt">// Sort by "Ray goes to the right" class="kw">property SORT_BY_GRAPH_OBJ_RAY, class=class="str">"cmt">// Sort by the "Vertical line goes through all windows of a chart" class="kw">property SORT_BY_GRAPH_OBJ_ELLIPSE, class=class="str">"cmt">// Sort by the "Display the full ellipse of the Fibonacci Arc object" class="kw">property SORT_BY_GRAPH_OBJ_ARROWCODE, class=class="str">"cmt">// Sort by an arrow code for the Arrow object SORT_BY_GRAPH_OBJ_ANCHOR, class=class="str">"cmt">// Sort by the position of a binding point of a graphical object SORT_BY_GRAPH_OBJ_XDISTANCE, class=class="str">"cmt">// Sort by a distance from the base corner along the X axis in pixels SORT_BY_GRAPH_OBJ_YDISTANCE, class=class="str">"cmt">// Sort by a distance from the base corner along the Y axis in pixels SORT_BY_GRAPH_OBJ_DIRECTION, class=class="str">"cmt">// Sort by the "Gann object trend" class="kw">property SORT_BY_GRAPH_OBJ_DEGREE, class=class="str">"cmt">// Sort by the "Elliott wave marking level" class="kw">property SORT_BY_GRAPH_OBJ_DRAWLINES, class=class="str">"cmt">// Sort by the "Display lines for Elliott wave marking" class="kw">property SORT_BY_GRAPH_OBJ_STATE, class=class="str">"cmt">// Sort by button state(pressed/released) SORT_BY_GRAPH_OBJ_OBJ_CHART_ID, class=class="str">"cmt">// Sort by Chart object ID. SORT_BY_GRAPH_OBJ_CHART_OBJ_PERIOD, class=class="str">"cmt">// Sort by Chart object period SORT_BY_GRAPH_OBJ_CHART_OBJ_DATE_SCALE, class=class="str">"cmt">// Sort by time scale display flag for the Chart object SORT_BY_GRAPH_OBJ_CHART_OBJ_PRICE_SCALE, class=class="str">"cmt">// Sort by price scale display flag for the Chart object SORT_BY_GRAPH_OBJ_CHART_OBJ_CHART_SCALE, class=class="str">"cmt">// Sort by Chart object scale SORT_BY_GRAPH_OBJ_XSIZE, class=class="str">"cmt">// Sort by Object width along the X axis in pixels SORT_BY_GRAPH_OBJ_YSIZE class=class="str">"cmt">// Sort by object height along the Y axis in pixels
◍ 图形对象排序枚举与快照消息常量
在 MT5 的标准库图形对象封装里,排序方式被拆成三类枚举:界面属性、真实数值属性、字符串属性。界面类从 X/Y 偏移、背景色到绑定边角都有独立常量,例如 SORT_BY_GRAPH_OBJ_XOFFSET 按可视区左上角横坐标排,SORT_BY_GRAPH_OBJ_CORNER 按对象绑定的图表边角排。 真实属性段以 FIRST_GRAPH_OBJ_DBL_PROP 为起点,SORT_BY_GRAPH_OBJ_PRICE 对应价格坐标,SORT_BY_GRAPH_OBJ_ANGLE 抓角度,SORT_BY_GRAPH_OBJ_DEVIATION 专门对应标准差通道的偏离值;这些常量直接决定 ObjectsArray 排序时的比较键。 字符串属性段从 FIRST_GRAPH_OBJ_STR_PROP 开始,覆盖名称、描述、tooltip、级别文字、字体、BMP 文件名与图表对象符号。实际调序时若传错段起点,数组可能返回空或乱序。 GStdGraphObj 相关消息枚举暴露了对象生命周期的典型失败点:MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_CLASS_OBJ 是类实例没建出来,MSG_GRAPH_STD_OBJ_ERR_NOT_FIND_SUBWINDOW 说明子窗口索引错了。带高亮的两条涉及变更历史快照——建失败和建成功分别有独立常量,可在 EA 日志里直接区分。
SORT_BY_GRAPH_OBJ_XOFFSET, class=class="str">"cmt">// Sort by X coordinate of the upper-left corner of the visibility area SORT_BY_GRAPH_OBJ_YOFFSET, class=class="str">"cmt">// Sort by Y coordinate of the upper-left corner of the visibility area SORT_BY_GRAPH_OBJ_BGCOLOR, class=class="str">"cmt">// Sort by background class="type">class="kw">color for OBJ_EDIT, OBJ_BUTTON and OBJ_RECTANGLE_LABEL SORT_BY_GRAPH_OBJ_CORNER, class=class="str">"cmt">// Sort by chart corner for binding a graphical object SORT_BY_GRAPH_OBJ_BORDER_TYPE, class=class="str">"cmt">// Sort by border type for the "Rectangle border" object SORT_BY_GRAPH_OBJ_BORDER_COLOR, class=class="str">"cmt">// Sort by frame class="type">class="kw">color for the OBJ_EDIT and OBJ_BUTTON objects class=class="str">"cmt">//--- Sort by real properties SORT_BY_GRAPH_OBJ_PRICE = FIRST_GRAPH_OBJ_DBL_PROP, class=class="str">"cmt">// Sort by price coordinate SORT_BY_GRAPH_OBJ_LEVELVALUE, class=class="str">"cmt">// Sort by level value SORT_BY_GRAPH_OBJ_SCALE, class=class="str">"cmt">// Sort by scale(class="kw">property of Gann objects and Fibonacci Arcs objects) SORT_BY_GRAPH_OBJ_ANGLE, class=class="str">"cmt">// Sort by angle SORT_BY_GRAPH_OBJ_DEVIATION, class=class="str">"cmt">// Sort by a deviation of the standard deviation channel class=class="str">"cmt">//--- Sort by class="type">class="kw">string properties SORT_BY_GRAPH_OBJ_NAME = FIRST_GRAPH_OBJ_STR_PROP, class=class="str">"cmt">// Sort by object name SORT_BY_GRAPH_OBJ_TEXT, class=class="str">"cmt">// Sort by object description SORT_BY_GRAPH_OBJ_TOOLTIP, class=class="str">"cmt">// Sort by tooltip text SORT_BY_GRAPH_OBJ_LEVELTEXT, class=class="str">"cmt">// Sort by level description SORT_BY_GRAPH_OBJ_FONT, class=class="str">"cmt">// Sort by font SORT_BY_GRAPH_OBJ_BMPFILE, class=class="str">"cmt">// Sort by BMP file name for the "Bitmap Level" object SORT_BY_GRAPH_OBJ_CHART_OBJ_SYMBOL, class=class="str">"cmt">// Sort by Chart object period symbol }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//--- GStdGraphObj MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_CLASS_OBJ, class=class="str">"cmt">// Failed to create the class object for a graphical object MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_STD_GRAPH_OBJ, class=class="str">"cmt">// Failed to create a graphical object MSG_GRAPH_STD_OBJ_ERR_NOT_FIND_SUBWINDOW, class=class="str">"cmt">// Failed to find the chart subwindow MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_SNAPSHOT, class=class="str">"cmt">// Failed to create a snapshot of the graphical object change history MSG_GRAPH_STD_OBJ_SUCCESS_CREATE_SNAPSHOT class=class="str">"cmt">// Created a snapshot of the graphical object change history
图形对象属性的消息枚举拆解
在 MT5 内部消息体系里,图形对象相关属性被拆成一长串 MSG_GRAPH_OBJ_PROP_* 枚举,用来在事件和属性查询中精确标识对象特征。从对象 ID、类型(ENUM_OBJECT)、元素类型(ENUM_GRAPH_ELEMENT_TYPE)到所属图表 ID、子窗口索引,每一行都对应一个可控可读的维度。 其中 MSG_GRAPH_OBJ_PROP_CHANGE_MEMORY 负责记录变更历史,MSG_GRAPH_OBJ_PROP_CREATETIME 给出创建时间,MSG_GRAPH_OBJ_PROP_TIMEFRAMES 控制对象在多周期上的可见性。这些字段是写自定义对象管理面板时绕不开的底层映射。 对象物种(SPECIES)进一步细分:LINES、CHANNELS、GANN、FIBO、ELLIOTT、SHAPES、ARROWS、GRAPHICAL,共 8 个子类,外加 GROUP 做归组。如果你用 ObjectType() 拿到类型后想自动分类,直接对照这组枚举能省掉大量字符串判断。 报错侧也有专用消息:MSG_GRAPH_OBJ_FAILED_CREATE_NEW_HIST_OBJ 等 4 条黄底枚举,专门描述变更历史对象的创建、入列、读取与数组扩容失败。实盘里若发现对象历史不记录,优先查这几条返回码而非盲目重画。
MSG_GRAPH_OBJ_PROP_ID, class=class="str">"cmt">// Object ID MSG_GRAPH_OBJ_PROP_TYPE, class=class="str">"cmt">// Graphical object type(ENUM_OBJECT) MSG_GRAPH_OBJ_PROP_ELEMENT_TYPE, class=class="str">"cmt">// Graphical element type(ENUM_GRAPH_ELEMENT_TYPE) MSG_GRAPH_OBJ_PROP_BELONG, class=class="str">"cmt">// Graphical object affiliation MSG_GRAPH_OBJ_PROP_CHART_ID, class=class="str">"cmt">// Chart ID MSG_GRAPH_OBJ_PROP_WND_NUM, class=class="str">"cmt">// Chart subwindow index MSG_GRAPH_OBJ_PROP_CHANGE_MEMORY, class=class="str">"cmt">// Change history MSG_GRAPH_OBJ_PROP_CREATETIME, class=class="str">"cmt">// Creation time MSG_GRAPH_OBJ_PROP_TIMEFRAMES, class=class="str">"cmt">// Object visibility on timeframes MSG_GRAPH_OBJ_PROP_SPECIES, class=class="str">"cmt">// Graphical object species MSG_GRAPH_OBJ_PROP_SPECIES_LINES, class=class="str">"cmt">// Lines MSG_GRAPH_OBJ_PROP_SPECIES_CHANNELS, class=class="str">"cmt">// Channels MSG_GRAPH_OBJ_PROP_SPECIES_GANN, class=class="str">"cmt">// Gann MSG_GRAPH_OBJ_PROP_SPECIES_FIBO, class=class="str">"cmt">// Fibo MSG_GRAPH_OBJ_PROP_SPECIES_ELLIOTT, class=class="str">"cmt">// Elliott MSG_GRAPH_OBJ_PROP_SPECIES_SHAPES, class=class="str">"cmt">// Shapes MSG_GRAPH_OBJ_PROP_SPECIES_ARROWS, class=class="str">"cmt">// Arrows MSG_GRAPH_OBJ_PROP_SPECIES_GRAPHICAL, class=class="str">"cmt">// Graphical objects MSG_GRAPH_OBJ_PROP_GROUP, class=class="str">"cmt">// Group of objects MSG_GRAPH_OBJ_TEXT_CLICK_COORD, class=class="str">"cmt">// (Chart click coordinate) MSG_GRAPH_OBJ_TEXT_ANCHOR_TOP, class=class="str">"cmt">// Arrow anchor point is located at the top MSG_GRAPH_OBJ_TEXT_ANCHOR_BOTTOM, class=class="str">"cmt">// Arrow anchor point is located at the bottom class=class="str">"cmt">//--- CDataPropObj MSG_DATA_PROP_OBJ_OUT_OF_PROP_RANGE, class=class="str">"cmt">// Passed class="kw">property is out of object class="kw">property range MSG_GRAPH_OBJ_FAILED_CREATE_NEW_HIST_OBJ, class=class="str">"cmt">// Failed to create an object of the graphical object change history MSG_GRAPH_OBJ_FAILED_ADD_OBJ_TO_HIST_LIST, class=class="str">"cmt">// Failed to add the change history object to the list MSG_GRAPH_OBJ_FAILED_GET_HIST_OBJ, class=class="str">"cmt">// Failed to receive the change history object MSG_GRAPH_OBJ_FAILED_INC_ARRAY_SIZE, class=class="str">"cmt">// Failed to increase the array size
「图形对象类的报错与箭头构造细节」
在 MT5 自定义图形对象库里,GStdGraphObj 这组字符串数组管的是多语言提示文本。俄文在前、英文在后,覆盖创建失败(如 Failed to create graphic object)、子窗口找不到、以及变更历史快照建立成功等状态。其中带高亮背景的几行,如「A snapshot of the history of changes to a graphical object has been created」和「Change history」,说明对象变更轨迹是可被快照记录的,做复盘脚本时别漏掉这个能力。 对象分类标签也在这段里铺开了:Lines、Channels、Gann、Fibonacci、Elliott、Shapes、Arrows 等,Arrows 类在构造时由 GRAPH_OBJ_SPECIES_ARROWS 常量锁定。外汇与贵金属图表上挂这类自定义对象,需注意跨周期可见性设置,否则小周期画的箭头在大周期可能消失,属于高频踩坑点。 CGStdArrowBuyObj 的构造器给出了可直接抄的写法:以 OBJECT_DE_TYPE_GSTD_ARROW_BUY 作类型、归属设为 GRAPH_OBJ_BELONG_NO_PROGRAM、物种常量填 GRAPH_OBJ_SPECIES_ARROWS,并强制锚点 ANCHOR_TOP。改 name 与 chart_id 就能在实盘图里批量生成买箭号,验证只需编译挂到 EURUSD 的 M5 看锚点是否贴顶。
class=class="str">"cmt">//--- GStdGraphObj {"Не удалось создать объект класса для графического объекта ","Failed to create class object for graphic object"}, {"Не удалось создать графический объект ","Failed to create graphic object "}, {"Не удалось найти подокно графика","Could not find chart subwindow"}, {"Не удалось создать снимок истории изменений графического объекта","Failed to create a snapshot of the change history of a graphic object"}, {"Создан снимок истории изменений графического объекта","A snapshot of the history of changes to a graphical object has been created"}, {"Идентификатор объекта","Object ID"}, {"Тип объекта","Object type"}, {"Тип графического элемента","Graphic element type"}, {"Принадлежность объекта","Object belongs to"}, {"Идентификатор графика объекта","Object chart ID"}, {"Номер подокна графика","Chart subwindow number"}, {"История изменений","Change history"}, {"Время создания","Time of creation"}, {"Видимость объекта на таймфреймах","Visibility of an object at timeframes"}, {"Вид графического объекта","Graphic object species"}, {"Линии","Lines"}, {"Каналы","Channels"}, {"Ганн","Gann"}, {"Фибоначчи","Fibonacci"}, {"Эллиотт","Elliott"}, {"Фигуры","Shapes"}, {"Стрелки","Arrows"}, {"Графические объекты","Graphical"}, {"Группа объектов","Object group"}, class=class="str">"cmt">//--- CDataPropObj {"Переданное свойство находится за пределами диапазона свойств объекта","The passed class="kw">property is outside the range of the object&class="macro">#x27;s properties"}, {"Не удалось создать объект истории изменений графического объекта","Failed to create a graphical object change history object"}, {"Не удалось добавить объект истории изменений в список","Failed to add change history object to the list"}, {"Не удалось получить объект истории изменений","Failed to get change history object"}, {"Не удалось увеличить размер массива","Failed to increase array size"}, class=class="str">"cmt">//--- Constructor CGStdArrowBuyObj(class="kw">const class="type">long chart_id,class="kw">const class="type">class="kw">string name) : CGStdGraphObj(OBJECT_DE_TYPE_GSTD_ARROW_BUY,GRAPH_OBJ_BELONG_NO_PROGRAM,GRAPH_OBJ_SPECIES_ARROWS,chart_id,class="num">1,name) { class=class="str">"cmt">//--- Specify the object class="kw">property CGStdGraphObj::SetProperty(GRAPH_OBJ_PROP_ANCHOR,class="num">0,ANCHOR_TOP); }
◍ 给箭头对象圈定可写的整数属性
在自建图形对象类里,先得声明哪些整数属性允许被外部读写,其余一律拒掉。下面这段 CGStdArrowBuyObj::SupportProperty 就是干这个拦截的:传入 ENUM_GRAPH_OBJ_PROP_INTEGER,命中白名单返回 true,否则 false。 白名单里列了 24 个属性,从 GRAPH_OBJ_PROP_ID 到 GRAPH_OBJ_PROP_ANCHOR 都放行,其中 GRAPH_OBJ_PROP_CHANGE_HISTORY 容易被忽略——它管的是对象修改历史记录开关。 紧接着的 CGBaseObj 基类把共用字段收拢到 protected:事件列表、图形对象类型、元素类型、归属程序、物种枚举和名称前缀。m_species 这个物种字段是区分箭头/线/标签等对象族系的关键,后面派生类会据此路由。 开 MT5 把这段塞进你的 EA 或指标源码,编译后试着给对象设一个不在白名单里的整数属性(比如 GRAPH_OBJ_PROP_LEVELS),会走 default 分支返回 false,验证拦截是否生效。
class="type">bool CGStdArrowBuyObj::SupportProperty(ENUM_GRAPH_OBJ_PROP_INTEGER class="kw">property) { class="kw">switch((class="type">int)class="kw">property) { class=class="str">"cmt">//--- Supported properties case GRAPH_OBJ_PROP_ID : case GRAPH_OBJ_PROP_TYPE : case GRAPH_OBJ_PROP_ELEMENT_TYPE : case GRAPH_OBJ_PROP_GROUP : case GRAPH_OBJ_PROP_BELONG : case GRAPH_OBJ_PROP_CHART_ID : case GRAPH_OBJ_PROP_WND_NUM : case GRAPH_OBJ_PROP_NUM : case GRAPH_OBJ_PROP_CREATETIME : case GRAPH_OBJ_PROP_CHANGE_HISTORY: case GRAPH_OBJ_PROP_TIMEFRAMES : case GRAPH_OBJ_PROP_BACK : case GRAPH_OBJ_PROP_ZORDER : case GRAPH_OBJ_PROP_HIDDEN : case GRAPH_OBJ_PROP_SELECTED : case GRAPH_OBJ_PROP_SELECTABLE : case GRAPH_OBJ_PROP_TIME : case GRAPH_OBJ_PROP_COLOR : case GRAPH_OBJ_PROP_STYLE : case GRAPH_OBJ_PROP_WIDTH : case GRAPH_OBJ_PROP_ANCHOR : class="kw">return true; class=class="str">"cmt">//--- Other properties are not supported class=class="str">"cmt">//--- Default is &class="macro">#x27;class="kw">false&class="macro">#x27; class="kw">default: break; } class="kw">return class="kw">false; } class CGBaseObj : class="kw">public CObject { class="kw">protected: CArrayObj m_list_events; class=class="str">"cmt">// Object event list ENUM_OBJECT m_type_graph_obj; class=class="str">"cmt">// Graphical object type ENUM_GRAPH_ELEMENT_TYPE m_type_element; class=class="str">"cmt">// Graphical element type ENUM_GRAPH_OBJ_BELONG m_belong; class=class="str">"cmt">// Program affiliation ENUM_GRAPH_OBJ_SPECIES m_species; class=class="str">"cmt">// Graphical object species class="type">class="kw">string m_name_prefix; class=class="str">"cmt">// Object name prefix
图形对象结构体的字段落点
在 MT5 自定义指标或 EA 里接管图形对象时,先把底层结构体看明白能少踩很多坑。下面这段声明覆盖了一个图形对象从身份到显示行为的全部关键属性,直接决定你在图表上能不能正确抓取和控制它。 string m_name; // 对象名称,作为后续 ObjectGet/ObjectSet 的检索键 long m_chart_id; // 所属图表 ID,多图表环境下定位必填 long m_object_id; // 对象内部 ID,由终端分配 long m_zorder; // 鼠标点击优先级,值越大越靠前接收事件 int m_subwindow; // 子窗口索引,主图是 0,附加指标窗口从 1 起算 int m_shift_y; // 子窗口内的 Y 坐标偏移,像素级微调用 int m_type; // 对象类型,对应 OBJ_HLINE、OBJ_TREND 等常量 int m_timeframes_visible; // 各周期可见性,按位标志组合 int m_digits; // 报价小数位,画价格线时对齐用 int m_group; // 对象分组,便于批量隐藏或删除 bool m_visible; // 当前是否可见 bool m_back; // 是否作为背景对象,决定绘制层级 bool m_selected; // 是否被选中 bool m_selectable; // 是否允许被选中 bool m_hidden; // 是否不在终端对象列表显示名称 datetime m_create_time; // 对象创建时间,UTC 实盘里如果发现有对象“点不到”,优先排查 m_zorder 和 m_selectable——这两位一个管层级一个管权限。外汇与贵金属杠杆高,用脚本批量建撤对象时建议先在模拟盘验证,避免误删关键位。
class="type">class="kw">string m_name; class=class="str">"cmt">// Object name class="type">long m_chart_id; class=class="str">"cmt">// Object chart ID class="type">long m_object_id; class=class="str">"cmt">// Object ID class="type">long m_zorder; class=class="str">"cmt">// Priority of a graphical object for receiving the mouse click event class="type">int m_subwindow; class=class="str">"cmt">// Subwindow index class="type">int m_shift_y; class=class="str">"cmt">// Subwindow Y coordinate shift class="type">int m_type; class=class="str">"cmt">// Object type class="type">int m_timeframes_visible; class=class="str">"cmt">// Visibility of an object on timeframes(a set of flags) class="type">int m_digits; class=class="str">"cmt">// Number of decimal places in a quote class="type">int m_group; class=class="str">"cmt">// Graphical object group class="type">bool m_visible; class=class="str">"cmt">// Object visibility class="type">bool m_back; class=class="str">"cmt">// "Background object" flag class="type">bool m_selected; class=class="str">"cmt">// "Object selection" flag class="type">bool m_selectable; class=class="str">"cmt">// "Object availability" flag class="type">bool m_hidden; class=class="str">"cmt">// "Disable displaying the name of a graphical object in the terminal object list" flag class="type">class="kw">datetime m_create_time; class=class="str">"cmt">// Object creation time class="kw">public: class=class="str">"cmt">//--- Set the values of the class variables