期货量化软件:赫兹量化中利用 MQL 创建您自己的图形库的提示和技巧

概述

开发 MetaTrader 5 关联环境中的 GUI 函数库是任何人都能想到的最大非特性项目之一,其它还有 AI、(优秀的)神经网络、和......熟练运用您尚未开发出的 GUI 函数库。

最后一点我是半开玩笑的,当然,学习如何使用已经制作完成的函数库更容易(即使外面的 GUI 函数库 非常庞大)! 但是,若我能学会如何使用一个比我自行打造更好的函数库,为什么还要从头开始创建一个呢?

好吧,有几个很好的理由。 您也许考虑到对于您的特定项目它太慢了,您若需要一些非常特殊的东西,而这些又没包含在函数库中,或者原来的实现不可能做到的功能,您也许就需要扩展它(有些函数库可能很难扩展),它可能有一个漏洞(不包括那些因滥用函数库而引起的错误)......或者您可能只是想学习它。 这些问题中的大多数都可由那些特定函数库的作者来解决,但您只能依赖他们注意到或愿意这样做(譬如扩展功能的情况)。

在本文中,我们的目标不是教导您如何制作一个界面,亦非展示开发一个全功能函数库的步骤。 取而代之,我们将提供一些如何制作一些特殊 GUI 函数库的示例,如此它们就可以作为打造一个函数库的起点,从而解决您已经发现的特定问题,或者初步理解有关已完成 GUI 函数库的庞大代码库内所发生的一切。
程序结构和对象层次

在开始制作 GUI 函数库之前,我们应该问:什么是 GUI 函数库? 简言之,它是对象的美化层次结构,即跟踪其它(图表)对象,并修改其属性以便生成不同的效果,并触发移动、单击、或更改颜色等事件。 这种层次结构的组织方式可能因实现而异,不过最常见的(也是我最喜欢的)是元素的树结构,其中一个元素可以有其它子元素。

为了创建它,我们将从一个元素的基本实现开始:

class CElement
{
private:
   //Variable to generate names
   static int        m_element_count;

   void              AddChild(CElement* child);

protected:
   //Chart object name
   string            m_name;

   //Element relations
   CElement*         m_parent;
   CElement*         m_children[];
   int               m_child_count;

   //Position and size
   int               m_x;
   int               m_y;
   int               m_size_x;
   int               m_size_y;

public:
                     CElement();
                    ~CElement();

   void              SetPosition(int x, int y);
   void              SetSize(int x, int y);
   void              SetParent(CElement* parent);

   int               GetGlobalX();
   int               GetGlobalY();

   void              CreateChildren();
   virtual void      Create(){}
};
目前,基础元素类仅包含有关位置、大小、以及与其它元素关系的信息。

位置变量 m_x 和 m_y 是其父对象上下文内的局部位置。 这就需要一个全局位置函数来判定对象应该在屏幕中的实际位置。 您在下面能看到我们如何通过递归获取全局位置(在本例中为 X):

int CElement::GetGlobalX(void)
{
   if (CheckPointer(m_parent)==POINTER_INVALID)
      return m_x;

   return m_x + m_parent.GetGlobalX();
}
在构造函数中,我们需要为每个对象确定一个唯一的名称。 为此,我们可以使用一个静态变量。 我们不打算在本文中讨论这一点,出于此原因,我更喜欢将该变量放在程序类当中,稍后我们就会看到,但出于简单起见,我们将它放在元素之中。

请您务必记住在析构函数中删除子元素,从而避免内存泄漏!

int CElement::m_element_count = 0;

//+------------------------------------------------------------------+
//| Base Element class constructor                                   |
//+------------------------------------------------------------------+
CElement::CElement(void) : m_child_count(0), m_x(0), m_y(0), m_size_x(100), m_size_y(100)
{
   m_name = "element_"+IntegerToString(m_element_count++);
}

//+------------------------------------------------------------------+
//| Base Element class destructor (delete child objects)             |
//+------------------------------------------------------------------+
CElement::~CElement(void)
{
   for (int i=0; i<m_child_count; i++)
      delete m_children[i];
}
最后,我们定义关系函数 AddChild 和 SetParent,由于在元素之间我们需要两个引用来进行通信:例如,为了获得全局位置,子项需要知道父项的位置,但在父项位置变更时,需要通知子项(我们稍后将在最后一部分实现这些)。 为了避免冗余,我们已将 AddChild 标记为私密。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值