DoEasy 函数库中的图形(第八十六部分):图形对象集合 - 管理属性修改·进阶篇
📊

DoEasy 函数库中的图形(第八十六部分):图形对象集合 - 管理属性修改·进阶篇

(2/3)·同步轮询会拖垮图表,事件模型才是管控大量对象属性变更的正路

进阶 第 2/3 篇
很多人在函数库里用定时器轮询 ObjectGetXXX 读每个对象属性,殊不知这些是同步函数,对象一多就卡死主线程。测试器里还根本跑不了这套,白白浪费算力。

「对象属性的整数快照怎么抓」

在 MT5 自定义指标或 EA 里接管已有图形对象时,第一步往往是把它的整数类属性整批读进自己的结构体数组。下面这段代码用 ObjectGetInteger 按 chart_id + name 逐个拉取,覆盖了层级、隐藏、选中、可选、时间点、颜色、线型与线宽八个通用字段。 注意 OBJPROP_ZORDER 决定鼠标点击图表时事件的派发优先级,OBJPROP_HIDDEN 只影响终端对象列表里是否显示名字,不改变图上可见性。这两个值读错,后续交互逻辑可能静默失效。 代码后半段把填充、只读、水平线数量、水平线颜色/线型/线宽、文本对齐、字号、射线左右延伸等「异类对象才有」的属性直接置 0。这不是偷懒,而是给不归属当前对象类型的属性一个确定初值,避免数组里残留上一次复用时的脏数据。 开 MT5 新建脚本跑一遍,把 m_long_prop 数组打印出来,你能直接看到黄金分时图里趋势线对象的 OBJPROP_WIDTH 默认是 1、OBJPROP_STYLE 默认是 0(实线)。外汇与贵金属图表对象属性受报价跳变影响,实操有高风险,数值仅作本地验证参考。

MQL5 / C++
  this.m_long_prop[GRAPH_OBJ_PROP_ZORDER]      = ::ObjectGetInteger(chart_id,name,OBJPROP_ZORDER);      class=class="str">"cmt">// Priority of a graphical object for receiving the event of clicking on a chart
  this.m_long_prop[GRAPH_OBJ_PROP_HIDDEN]      = ::ObjectGetInteger(chart_id,name,OBJPROP_HIDDEN);      class=class="str">"cmt">// Disable displaying the name of a graphical object in the terminal object list
  this.m_long_prop[GRAPH_OBJ_PROP_SELECTED]    = ::ObjectGetInteger(chart_id,name,OBJPROP_SELECTED);    class=class="str">"cmt">// Object selection
  this.m_long_prop[GRAPH_OBJ_PROP_SELECTABLE]  = ::ObjectGetInteger(chart_id,name,OBJPROP_SELECTABLE);  class=class="str">"cmt">// Object availability
  this.m_long_prop[GRAPH_OBJ_PROP_TIME]        = ::ObjectGetInteger(chart_id,name,OBJPROP_TIME);        class=class="str">"cmt">// First point time coordinate
  this.m_long_prop[GRAPH_OBJ_PROP_COLOR]       = ::ObjectGetInteger(chart_id,name,OBJPROP_COLOR);       class=class="str">"cmt">// Color
  this.m_long_prop[GRAPH_OBJ_PROP_STYLE]       = ::ObjectGetInteger(chart_id,name,OBJPROP_STYLE);       class=class="str">"cmt">// Style
  this.m_long_prop[GRAPH_OBJ_PROP_WIDTH]       = ::ObjectGetInteger(chart_id,name,OBJPROP_WIDTH);       class=class="str">"cmt">// Line width
  class=class="str">"cmt">//--- Properties belonging to different graphical objects
  this.m_long_prop[GRAPH_OBJ_PROP_FILL]                                 = class="num">0;  class=class="str">"cmt">// Object class="type">class="kw">color filling
  this.m_long_prop[GRAPH_OBJ_PROP_READONLY]                             = class="num">0;  class=class="str">"cmt">// Ability to edit text in the Edit object
  this.m_long_prop[GRAPH_OBJ_PROP_LEVELS]                               = class="num">0;  class=class="str">"cmt">// Number of levels
  this.m_long_prop[GRAPH_OBJ_PROP_LEVELCOLOR]                           = class="num">0;  class=class="str">"cmt">// Level line class="type">class="kw">color
  this.m_long_prop[GRAPH_OBJ_PROP_LEVELSTYLE]                           = class="num">0;  class=class="str">"cmt">// Level line style
  this.m_long_prop[GRAPH_OBJ_PROP_LEVELWIDTH]                           = class="num">0;  class=class="str">"cmt">// Level line width
  this.m_long_prop[GRAPH_OBJ_PROP_ALIGN]                                = class="num">0;  class=class="str">"cmt">// Horizontal text alignment in the Edit object(OBJ_EDIT)
  this.m_long_prop[GRAPH_OBJ_PROP_FONTSIZE]                             = class="num">0;  class=class="str">"cmt">// Font size
  this.m_long_prop[GRAPH_OBJ_PROP_RAY_LEFT]                             = class="num">0;  class=class="str">"cmt">// Ray goes to the left
  this.m_long_prop[GRAPH_OBJ_PROP_RAY_RIGHT]                            = class="num">0;  class=class="str">"cmt">// Ray goes to the right

图形对象长整型属性的默认归零

在 MT5 自建图形对象封装类里,构造函数通常会把一组长整型属性一次性置 0,避免残留内存值干扰后续绘制。下面这段初始化覆盖了从射线、椭圆到内嵌图表对象的 18 个属性枚举,是对象干净起手的前提。 垂直射线属性设为 0 表示线体贯穿图表所有子窗口,而非仅限主图;斐波那契弧的椭圆标志 0 则代表显示完整弧线而非局部。箭头对象的 arrowcode、江恩线的 direction、艾略特波的 degree 与 drawlines 同为 0,意味着使用默认箭头样式、零度趋势方向、以及不绘制波浪辅助线。 内嵌图表对象(OBJ_CHART)相关的 chart_id、period、各类 scale 与 chart_scale 全部归零,代表先不绑定具体图表与周期,尺寸类 xsize / ysize / xoffset 也置 0,等待后续用 Create 或 Attach 时再赋值。开 MT5 把这段贴进你的 CGraphObject 派生类构造函数,断点看一下 m_long_prop 数组前 18 项是否确为 0,就能验证封装是否漏了某项。

MQL5 / C++
  this.m_long_prop[GRAPH_OBJ_PROP_RAY]                = class="num">0;  class=class="str">"cmt">// Vertical line goes through all windows of a chart
  this.m_long_prop[GRAPH_OBJ_PROP_ELLIPSE]             = class="num">0;  class=class="str">"cmt">// Display the full ellipse of the Fibonacci Arc object
  this.m_long_prop[GRAPH_OBJ_PROP_ARROWCODE]           = class="num">0;  class=class="str">"cmt">// Arrow code for the "Arrow" object
  this.m_long_prop[GRAPH_OBJ_PROP_ANCHOR]              = class="num">0;  class=class="str">"cmt">// Position of the binding point of the graphical object
  this.m_long_prop[GRAPH_OBJ_PROP_XDISTANCE]           = class="num">0;  class=class="str">"cmt">// Distance from the base corner along the X axis in pixels
  this.m_long_prop[GRAPH_OBJ_PROP_YDISTANCE]           = class="num">0;  class=class="str">"cmt">// Distance from the base corner along the Y axis in pixels
  this.m_long_prop[GRAPH_OBJ_PROP_DIRECTION]           = class="num">0;  class=class="str">"cmt">// Gann object trend
  this.m_long_prop[GRAPH_OBJ_PROP_DEGREE]              = class="num">0;  class=class="str">"cmt">// Elliott wave marking level
  this.m_long_prop[GRAPH_OBJ_PROP_DRAWLINES]           = class="num">0;  class=class="str">"cmt">// Display lines for Elliott wave marking
  this.m_long_prop[GRAPH_OBJ_PROP_STATE]               = class="num">0;  class=class="str">"cmt">// Button state(pressed/released)
  this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_CHART_ID]  = class="num">0;  class=class="str">"cmt">// Chart object ID(OBJ_CHART).
  this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_PERIOD]    = class="num">0;  class=class="str">"cmt">// Chart object period<
  this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE]= class="num">0;  class=class="str">"cmt">// Time scale display flag for the Chart object
  this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE]= class="num">0; class=class="str">"cmt">// Price scale display flag for the Chart object
  this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE]= class="num">0; class=class="str">"cmt">// Chart object scale
  this.m_long_prop[GRAPH_OBJ_PROP_XSIZE]               = class="num">0;  class=class="str">"cmt">// Object width along the X axis in pixels.
  this.m_long_prop[GRAPH_OBJ_PROP_YSIZE]               = class="num">0;  class=class="str">"cmt">// Object height along the Y axis in pixels.
  this.m_long_prop[GRAPH_OBJ_PROP_XOFFSET]             = class="num">0;  class=class="str">"cmt">// X coordinate of the upper-left corner of the visibility area.

◍ 对象属性的初始化与快照留存

在封装图形对象的类构造函数里,先把一批整型属性压成默认值 0,相当于给控件定了锚点:Y 偏移、背景色、绑定角、边框类型与边框色全部归零,意味着新建的 OBJ_EDIT、OBJ_BUTTON 类控件默认贴左上角、无底色无边框。 随后进入“真实属性”留存阶段,double 类只把价格坐标通过 ObjectGetDouble 读进来,其余如水平值、缩放、角度、标准差通道偏离全部置 0,说明这套快照并不负责还原 Gann 或斐波那契弧的几何参数,仅保价格锚。 字符串属性则把对象名直接接住,描述文本与悬浮提示用 ObjectGetString 拉取,水平描述留空串。你在 MT5 里若想扩展这个类,只要改 IndexProp 映射并把对应 ObjectGetXxx 补全即可,外汇与贵金属图表对象受报价跳空影响,读取价格坐标可能偏离预期,属高风险操作。

MQL5 / C++
this.m_long_prop[GRAPH_OBJ_PROP_YOFFSET]                 = class="num">0;  class=class="str">"cmt">// Y coordinate of the upper-left corner of the visibility area.
this.m_long_prop[GRAPH_OBJ_PROP_BGCOLOR]                 = class="num">0;  class=class="str">"cmt">// Background class="type">class="kw">color for OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL
this.m_long_prop[GRAPH_OBJ_PROP_CORNER]                  = class="num">0;  class=class="str">"cmt">// Chart corner for binding a graphical object
this.m_long_prop[GRAPH_OBJ_PROP_BORDER_TYPE]             = class="num">0;  class=class="str">"cmt">// Border type for "Rectangle border"
this.m_long_prop[GRAPH_OBJ_PROP_BORDER_COLOR]            = class="num">0;  class=class="str">"cmt">// Border class="type">class="kw">color for OBJ_EDIT and OBJ_BUTTON

class=class="str">"cmt">//--- Save real properties
this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_PRICE)]      = ::ObjectGetDouble(chart_id,name,OBJPROP_PRICE);  class=class="str">"cmt">// Price coordinate
this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_LEVELVALUE)] = class="num">0;                                                       class=class="str">"cmt">// Level value
this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_SCALE)]      = class="num">0;                                                       class=class="str">"cmt">// Scale(class="kw">property of Gann objects and Fibonacci Arcs objects)
this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_ANGLE)]      = class="num">0;                                                       class=class="str">"cmt">// Angle
this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_DEVIATION)]  = class="num">0;                                                       class=class="str">"cmt">// Deviation of the standard deviation channel

class=class="str">"cmt">//--- Save class="type">class="kw">string properties
this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_NAME)]       = name;                                                    class=class="str">"cmt">// Object name
this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_TEXT)]       = ::ObjectGetString(chart_id,name,OBJPROP_TEXT);   class=class="str">"cmt">// Object description(the text contained in the object)
this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_TOOLTIP)]    = ::ObjectGetString(chart_id,name,OBJPROP_TOOLTIP);class=class="str">"cmt">// Tooltip text
this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_LEVELTEXT)]  = "";                                                      class=class="str">"cmt">// Level description

「标准图形对象的初始化与属性落盘」

在 MT5 自建图形对象类里,CGStdGraphObj 的构造函数先把对象类型、归属窗口和图表 ID 这些骨架信息写死。注意 this.SetName(name) 紧跟在 this.m_type=obj_type 之后调用,名字若传空串,后续 SetSubwindow 按 chart_id+name 定位子窗口时会拿不到正确锚点。 字符串类属性在初始化阶段统一置空:字体、BMP 文件名、图表对象 symbol 三个槽位都给 "",意味着新对象默认不绑定任何外部资源。若你要在 EURUSD 上画 Bitmap Level 却忘了补 BMP 文件名,对象可能倾向不渲染。 整数与布尔属性则从父类 GetProperty 回读后强制转型保存:m_create_time 转 datetime,m_back / m_selected / m_selectable / m_hidden 转 bool。这套回读机制保证对象重建时基础状态不丢。 Digits 通过 SymbolInfoInteger(ChartSymbol(chart_id), SYMBOL_DIGITS) 实时取,黄金 XAUUSD 通常返回 2,外汇交叉盘可能返回 3~5,写价格标签时直接用 m_digits 控精度即可避免小数点错位。

MQL5 / C++
  this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_FONT)]                 = "";                                                                             class=class="str">"cmt">// Font
  this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_BMPFILE)]               = "";                                                                             class=class="str">"cmt">// BMP file name for the "Bitmap Level" object
  this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL)]= "";                                                                                   class=class="str">"cmt">// Chart object symbol 

class=class="str">"cmt">//--- Save basic properties in the parent object
  this.m_create_time=(class="type">class="kw">datetime)this.GetProperty(GRAPH_OBJ_PROP_CREATETIME);
  this.m_back=(class="type">bool)this.GetProperty(GRAPH_OBJ_PROP_BACK);
  this.m_selected=(class="type">bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTED);
  this.m_selectable=(class="type">bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTABLE);
  this.m_hidden=(class="type">bool)this.GetProperty(GRAPH_OBJ_PROP_HIDDEN);
  this.m_name=this.GetProperty(GRAPH_OBJ_PROP_NAME);
}
class=class="str">"cmt">//+-------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Protected parametric constructor                                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
CGStdGraphObj::CGStdGraphObj(class="kw">const ENUM_OBJECT_DE_TYPE obj_type,
                             class="kw">const ENUM_GRAPH_OBJ_BELONG belong,
                             class="kw">const ENUM_GRAPH_OBJ_GROUP group,
                             class="kw">const class="type">long chart_id,class="kw">const class="type">class="kw">string name)
  {
class=class="str">"cmt">//--- Set the object(class="num">1) type, type of graphical(class="num">2) object, (class="num">3) element, (class="num">4) subwindow affiliation and(class="num">5) index, as well as(class="num">6) chart symbol Digits
  this.m_type=obj_type;
  this.SetName(name);
  CGBaseObj::SetChartID(chart_id);
  CGBaseObj::SetTypeGraphObject(CGBaseObj::GraphObjectType(obj_type));
  CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_STANDARD);
  CGBaseObj::SetBelong(belong);
  CGBaseObj::SetGroup(group);
  CGBaseObj::SetSubwindow(chart_id,name);
  CGBaseObj::SetDigits((class="type">int)::SymbolInfoInteger(::ChartSymbol(chart_id),SYMBOL_DIGITS));

class=class="str">"cmt">//--- Save integer properties
  class=class="str">"cmt">//--- properties inherent in all graphical objects but not present in a graphical object
  this.m_long_prop[GRAPH_OBJ_PROP_CHART_ID]     = CGBaseObj::ChartID();           class=class="str">"cmt">// Chart ID
  this.m_long_prop[GRAPH_OBJ_PROP_WND_NUM]      = CGBaseObj::SubWindow();         class=class="str">"cmt">// Chart subwindow index
  this.m_long_prop[GRAPH_OBJ_PROP_TYPE]         = CGBaseObj::TypeGraphObject();   class=class="str">"cmt">// Graphical object type(ENUM_OBJECT)

图形对象属性的初始化与整数属性抓取

在自定义图形对象类里,构造函数先把通用元数据写进 m_long_prop 数组:元素类型、归属、分组直接取自基类静态方法,ID 和列表序号先置 0。随后调 PropertiesRefresh() 把对象固有属性刷进数组,再把创建时间、背景层、选中态、可选性、隐藏标志从属性表同步到成员标量,最后用 PropertiesCopyToPrevData() 把当前状态存为“上一帧”,方便后续做变更比对。 整数属性的实际读取落在 GetAndSaveINT() 里,它逐个用 ObjectGetInteger 向图表对象要值:创建时间(OBJPROP_CREATETIME)、各周期可见性(OBJPROP_TIMEFRAMES)、是否背景对象(OBJPROP_BACK)、点击优先级(OBJPROP_ZORDER)、是否隐藏于终端列表(OBJPROP_HIDDEN)。这些字段都是 long 型,读回来直接落进 m_long_prop 对应枚举槽位。 开 MT5 自己验证时,可在这段后面加一句 Print(m_long_prop[GRAPH_OBJ_PROP_ZORDER]),在 EURUSD 图表上画个矩形看优先级返回值;外汇与贵金属杠杆高,自动化对象脚本若误改 BACK 或 HIDDEN 可能导致图形丢失,需先在策略测试器跑一遍。

MQL5 / C++
this.m_long_prop[GRAPH_OBJ_PROP_ELEMENT_TYPE]= CGBaseObj::TypeGraphElement(); class=class="str">"cmt">// Graphical element type(ENUM_GRAPH_ELEMENT_TYPE)
this.m_long_prop[GRAPH_OBJ_PROP_BELONG]      = CGBaseObj::Belong();            class=class="str">"cmt">// Graphical object affiliation
this.m_long_prop[GRAPH_OBJ_PROP_GROUP]       = CGBaseObj::Group();             class=class="str">"cmt">// Graphical object group
this.m_long_prop[GRAPH_OBJ_PROP_ID]          = class="num">0;                              class=class="str">"cmt">// Object ID
this.m_long_prop[GRAPH_OBJ_PROP_NUM]         = class="num">0;                              class=class="str">"cmt">// Object index in the list
class=class="str">"cmt">//--- Save the properties inherent in all graphical objects and present in a graphical object
this.PropertiesRefresh();
class=class="str">"cmt">//--- Save basic properties in the parent object
this.m_create_time=(class="type">class="kw">datetime)this.GetProperty(GRAPH_OBJ_PROP_CREATETIME);
this.m_back=(class="type">bool)this.GetProperty(GRAPH_OBJ_PROP_BACK);
this.m_selected=(class="type">bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTED);
this.m_selectable=(class="type">bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTABLE);
this.m_hidden=(class="type">bool)this.GetProperty(GRAPH_OBJ_PROP_HIDDEN);
class=class="str">"cmt">//--- Save the current properties to the previous ones
this.PropertiesCopyToPrevData();
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Get and save the integer properties                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void CGStdGraphObj::GetAndSaveINT(class="type">void)
  {
  class=class="str">"cmt">//--- Properties inherent in all graphical objects and present in a graphical object
  this.m_long_prop[GRAPH_OBJ_PROP_CREATETIME]  = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_CREATETIME); class=class="str">"cmt">// Object creation time
  this.m_long_prop[GRAPH_OBJ_PROP_TIMEFRAMES]  = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_TIMEFRAMES); class=class="str">"cmt">// Object visibility on timeframes
  this.m_long_prop[GRAPH_OBJ_PROP_BACK]        = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_BACK);       class=class="str">"cmt">// Background object
  this.m_long_prop[GRAPH_OBJ_PROP_ZORDER]      = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_ZORDER);     class=class="str">"cmt">// Priority of a graphical object for receiving the event of clicking on a chart
  this.m_long_prop[GRAPH_OBJ_PROP_HIDDEN]      = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_HIDDEN);     class=class="str">"cmt">// Disable displaying the name of a graphical object in the terminal object list

◍ 把图形对象属性抓进类成员里

封装图形对象时,最容易被忽略的一步是「把 MT5 图表上对象的实时状态同步进自己的类」。下面这段直接调 ObjectGetInteger,把选中态、可编辑性、时间坐标、颜色、线型、线宽一次性读进 m_long_prop 数组,省得每次画图都重新查。 注意 OBJPROP_FILL、OBJPROP_READONLY、OBJPROP_LEVELS 这些不是所有对象都通用——斐波那契或矩形才用得到填充,Edit 对象才用得到只读和水平对齐。读不存在的属性 MT5 不会报错,但返回 0,调试时容易误判。 跑这段代码前,确认 this.Name() 返回的对象已经在当前 ChartID() 对应的图表里创建过,否则所有值都是 0。外汇和贵金属行情跳空频繁,对象时间坐标可能被挪,建议每次 OnChartEvent 里重读一次 GRAPH_OBJ_PROP_TIME。

MQL5 / C++
  this.m_long_prop[GRAPH_OBJ_PROP_SELECTED]    = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_SELECTED);   class=class="str">"cmt">// Object selection
  this.m_long_prop[GRAPH_OBJ_PROP_SELECTABLE]   = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_SELECTABLE); class=class="str">"cmt">// Object availability
  this.m_long_prop[GRAPH_OBJ_PROP_TIME]         = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_TIME);        class=class="str">"cmt">// First point time coordinate
  this.m_long_prop[GRAPH_OBJ_PROP_COLOR]        = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_COLOR);       class=class="str">"cmt">// Color
  this.m_long_prop[GRAPH_OBJ_PROP_STYLE]        = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_STYLE);       class=class="str">"cmt">// Style
  this.m_long_prop[GRAPH_OBJ_PROP_WIDTH]        = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_WIDTH);       class=class="str">"cmt">// Line width
  class=class="str">"cmt">//--- Properties belonging to different graphical objects
  this.m_long_prop[GRAPH_OBJ_PROP_FILL]         = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_FILL);         class=class="str">"cmt">// Fill an object with class="type">class="kw">color
  this.m_long_prop[GRAPH_OBJ_PROP_READONLY]     = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_READONLY);     class=class="str">"cmt">// Ability to edit text in the Edit object
  this.m_long_prop[GRAPH_OBJ_PROP_LEVELS]       = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_LEVELS);       class=class="str">"cmt">// Number of levels
  this.m_long_prop[GRAPH_OBJ_PROP_LEVELCOLOR]   = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_LEVELCOLOR); class=class="str">"cmt">// Level line class="type">class="kw">color
  this.m_long_prop[GRAPH_OBJ_PROP_LEVELSTYLE]   = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_LEVELSTYLE); class=class="str">"cmt">// Level line style
  this.m_long_prop[GRAPH_OBJ_PROP_LEVELWIDTH]   = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_LEVELWIDTH); class=class="str">"cmt">// Level line width
  this.m_long_prop[GRAPH_OBJ_PROP_ALIGN]        = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_ALIGN);        class=class="str">"cmt">// Horizontal text alignment in the Edit object(OBJ_EDIT)
  this.m_long_prop[GRAPH_OBJ_PROP_FONTSIZE]     = ::ObjectGetInteger(this.ChartID(),this.Name(),OBJPROP_FONTSIZE);     class=class="str">"cmt">// Font size
让小布替你跑这套
把对象属性变更的监控逻辑交给小布盯盘,AIGC 已内置事件响应模块,打开对应品种页即可看到实时对象状态,你只管判断形态。

常见问题

ObjectGetXXX 系列是同步函数,会等待命令执行,对象数量大时严重占用资源,且在策略测试器中无法处理图表对象事件。
主要通过属性对话框更改对象属性时触发,配合拖拽等事件可覆盖大部分手动变更,但测试器环境受限无法响应。
可以,小布盯盘的品种页内置了基于事件模型的图形对象状态跟踪,省去自己写 OnChartEvent 的重复劳动。
规划中是由各图表事件处理程序发事件到主图表,函数库统一收集,本文先验证单图表逻辑再延伸。
重命名通常伴随删除和创建事件序列,需在集合中做对应映射更新,避免残留旧对象引用。