对象优先级(Z 轴顺序)
图表上的对象不仅提供信息展示,还能通过事件与用户及 MQL 程序进行交互,我们将在 下一章对此进行详细探讨。其中一个事件源是鼠标指针。具体来说,图表能够追踪鼠标移动和按键操作。
如果某个对象位于鼠标下方,则可以针对该对象执行特定的事件处理。然而,对象可能会相互重叠(当它们的坐标在考虑 尺寸的情况下重叠时)。在这种情况下,整数特性 OBJPROP_ZORDER 开始发挥作用。该特性用于设置图形对象接收鼠标事件的优先级。当多个对象重叠时,只有优先级最高的对象才能接收到事件。
默认情况下,创建对象时,其 Z 轴顺序为零,但可根据需要增大该值。
需特别注意,Z 轴顺序仅影响鼠标事件的处理顺序,而不影响对象的绘制顺序。对象始终按照其添加到图表的先后顺序进行绘制。这一点可能会导致误解。例如,当一个对象在视觉上位于另一个对象之上时,可能因被重叠对象的 Z 轴优先级更高(见示例)而无法显示其工具提示。
在ObjectZorder.mq5脚本中,我们将创建 12 个 OBJ_RECTANGLE_LABEL 类型的对象,并按类似钟面将其排列成圆形。对象的添加顺序对应小时刻度:从 1 到 12。为清晰起见,所有矩形将设置随机颜色(关于 OBJPROP_BGCOLOR 特性,请参阅 下一节)和随机优先级。当用户将鼠标悬停在对象上时,可通过工具提示确定当前所属对象。
为方便设置对象特性,我们定义了从 Object Selector派生的特殊类 ObjectBuilder。
#include "ObjectPrefix.mqh"
|
对象标识符 (id) 和图表标识符 (host) 的字段已存在于ObjectSelector 类中。在派生类中,我们添加了对象类型 (ENUM_OBJECT type) 和窗口编号 (int window)。构造函数会调用 ObjectCreate。
特性的设置和读取完全继承自 ObjectSelector中的一组 get 和 set 方法。
与之前的测试脚本一样,我们将确定脚本放置的窗口、窗口尺寸和中心点坐标。
void OnStart()
|
由于 OBJ_RECTANGLE_LABEL 对象类型支持显式像素尺寸,因此我们将每个矩形的宽度 dx和高度dy 计算为窗口的四分之一。我们使用这些值来设置 OBJPROP_XSIZE 和 OBJPROP_YSIZE 特性(相关说明请参阅 确定对象宽度和高度章节。
const int dx = w / 4;
|
接下来,在循环中创建 12 个对象。变量 px和py 包含“表盘”上下一个“标记”相对于中心点 (x, y) 的偏移量。z轴优先级采用随机选择。对象名称及其工具提示 (OBJPROP_TOOLTIP) 包含类似“XX - YYY”的字符串,其中 XX 表示“小时”编号(表盘上的位置 1 至 12),YYY 表示优先级值。
for(int i = 0; i < 12; ++i)
|
在调用 ObjectBuilder构造函数后,针对新的 builder 对象,可以通过链式调用重载的 set 方法设置不同特性(set 方法返回对象自身指针)。
由于图形对象创建和配置完成后不再需要 MQL 对象,因此我们会立即删除 builder。
脚本执行后,图表上会出现如下对象:
对象叠加和 Z 轴顺序优先级工具提示
每次运行时颜色和优先级都会不同,但矩形的视觉叠加顺序始终一致,按照创建顺序从最底层的 1 到最顶层的 12 排列(此处指的是对象的叠加层级,而非 12 一定位于表盘顶部)。
在图中,鼠标光标位于存在两个对象的位置,即 01(荧光酸橙绿)和 12(沙色)。此时,01 号对象的工具提示可见,尽管视觉上 12 号对象显示在 01 号之上。这是因为 01 号被随机生成了比 12 号更高的优先级。
由于一次只能显示一个工具提示,因此可以将鼠标移至没有对象重叠的其他区域,通过工具提示中的信息来查看优先级关系,此时工具提示中的信息属于光标下方的单个对象。
在下一章学习鼠标事件处理时,我们可以改进此示例,测试 Z 轴顺序对鼠标点击对象的影响。
要删除创建的对象,可使用 ObjectCleanup1.mq5脚本。