锚定窗口角点和屏幕坐标

对于采用图表(像素)点坐标系的对象,必须选择窗口四个角之一作为参考点,以此作为计算对象锚点在水平 X 轴与垂直 Y 轴方向的坐标值的基准。这些方面由下表中的特性控制。

标识符

说明

类型

OBJPROP_CORNER

图形对象锚定的图表角点

ENUM_BASE_CORNER

OBJPROP_XDISTANCE

距锚定角点 X 轴方向的距离,以像素为单位

int

OBJPROP_YDISTANCE

距锚定角点 Y 轴方向的距离,以像素为单位

int

OBJPROP_CORNER 的有效选项汇总在 ENUM_BASE_CORNER 枚举中。

标识符

坐标中心位置

CORNER_LEFT_UPPER

窗口左上角

CORNER_LEFT_LOWER

窗口左下角

CORNER_RIGHT_LOWER

窗口右下角

CORNER_RIGHT_UPPER

窗口右上角

默认值为左上角。

下图显示了四个按钮对象,在窗口中,它们具有相同的大小,且各自距锚定角点的距离相同。这些对象仅在绑定的角点本身有所不同。需注意,按钮有一个锚点,其始终位于按钮的左上角。

绑定到主窗口不同角点的对象布局

绑定到主窗口不同角点的对象布局

图表中所有四个对象当前均被选中,因此其锚点以对比色高亮显示。

当我们提及窗口角点时,指的是对象所在的特定窗口或子窗口,而非整个图表。换言之,对于子窗口中的对象,Y 坐标是从该子窗口的上边框或下边框开始测量的。

下图展示了子窗口中绑定到子窗口各角点的类似对象。

绑定到主窗口不同角点的对象位置

绑定到主窗口不同角点的对象位置

用户可使用 ObjectCornerLabel.mq5脚本测试文本标注的移动,其窗口锚定角通过输入参数 Corner 指定。

#property script_show_inputs
   
input ENUM_BASE_CORNER Corner = CORNER_LEFT_UPPER;

坐标会周期性变化,并显示在标注文本中。因此,标注会在窗口中移动,当移至边框时将产生反弹效果。对象将在鼠标放置脚本的窗口或子窗口内创建。

void OnStart()
{
   const int t = ChartWindowOnDropped();
   const string legend = EnumToString(Corner);
   
   const string name = "ObjCornerLabel-" + legend;
   int h = (int)ChartGetInteger(0CHART_HEIGHT_IN_PIXELSt);
   int w = (int)ChartGetInteger(0CHART_WIDTH_IN_PIXELS);
   int x = w / 2;
   int y = h / 2;
   ...

为正确定位,我们获取窗口的尺寸(然后检查其是否已更改),并找到对象初始放置的中间位置:使用坐标变量 xy

接下来,我们将创建并设置一个文本标注,暂不设置坐标。需要注意的是,我们启用了选择对象选择功能 (OBJPROP_SELECTABLE) 并将其选中 (OBJPROP_SELECTED),因为这能让我们看到对象本身的锚点,从而测量其与窗口角点(坐标远点)的距离。这两个特性在 对象状态管理章节有更详细的说明。

   ObjectCreate(0nameOBJ_LABELt00);
   ObjectSetInteger(0nameOBJPROP_SELECTABLEtrue);
   ObjectSetInteger(0nameOBJPROP_SELECTEDtrue);
   ObjectSetInteger(0nameOBJPROP_CORNERCorner);
   ...

在变量 pxpy, 中,我们将记录用于模拟运动的坐标增量。坐标修改本身将在无限循环中执行,直至被用户中断。迭代计数器允许每 50 次迭代时,随机改变移动方向。

   int px = 0py = 0;
   int pass = 0;
   
   for( ;!IsStopped(); ++pass)
   {
      if(pass % 50 == 0)
      {
         h = (int)ChartGetInteger(0CHART_HEIGHT_IN_PIXELSt);
         w = (int)ChartGetInteger(0CHART_WIDTH_IN_PIXELS);
         px = rand() * (w / 20) / 32768 - (w / 40);
         py = rand() * (h / 20) / 32768 - (h / 40);
      }
   
      // bounce off window borders so object doesn't hide
      if(x + px > w || x + px < 0px = -px;
      if(y + py > h || y + py < 0py = -py;
      // recalculate label positions
      x += px;
      y += py;
      
      // update the coordinates of the object and add them to the text
      ObjectSetString(0nameOBJPROP_TEXTlegend
         + "[" + (string)x + "," + (string)y + "]");
      ObjectSetInteger(0nameOBJPROP_XDISTANCEx);
      ObjectSetInteger(0nameOBJPROP_YDISTANCEy);
   
      ChartRedraw();
      Sleep(100);
   }
   
   ObjectDelete(0name);
}

尝试多次运行该脚本,并指定不同的锚定角点。

在下一节中,我们将通过控制对象上的锚点来增强该脚本。