我们的 IDE 变更如下图所示:

正如您所看到的,设计本身有一些小的变化。 添加了两个新区域:一个将接收资产名称;另一个将接收当天的累计值。 好吧,这些东西对于我们来讲都是非刚需,它们不会影响我们的决定。 但无论如何,它们都很有趣。 我将展示往 IDE 中添加功能的最简单和正确的方法。 如此,在新界面中打开对象列表。 它如下显现:

这两个被圈起来的对象没有与之关联的事件,这意味着它们在 IDE 中不起作用。 所有其它对象均已某些事件正确关联,当这些事件在 EA 中发生时,MetaTrader 5 可以强制它们正确执行。 这就是说,我们可以根据自己的意愿修改 IDE 界面,但如果功能尚未实现,MetaTrader 5 则只在图表上显示对象。 我们需要那个 “EDIT 00” 对象来接收我们正在交易的资产名称,该名称应会显示在对象的中心。 “EDIT 01” 对象会接收某个时段内的累计值。 我们将采用日线时段来了解我们在日线中是盈利还是亏损。 如果该值为负值,则会以一种颜色显示;如果为正值,将采用另一种颜色。

这两个值显然不能由用户更改,因此您可以将其属性保留为只读,如下图所示。

但是,请记住,无法指定信息的显示方式,也就是说,我们无法对齐文本,使其显示在对象的中心。 如若需要,可以用代码完成此操作,因为有一个属性可以将文本设置为居中对齐。 参见 "对象属性" 了解更多详情。 请注意 表格里的 ENUM_ALIGN_MODE — 在它包含的对象上您可以使用对齐文本。

因此,无论我们要实现什么样的修改,我们需要做的第一件事就是准备一个计划:定义新特性、它们的表示形式、以及用户与它们交互的方式。 这允许 MetaTrader 5 通过自己的界面尽可能多地选择正确的对象,并配置它。 结果就是,我们将有一个现成的 IDE,我们只需要通过 MQL5 代码对其进行调整,这样 IDE 最终将 100% 正常工作。 如此,我们来继续修改。

修改

为了防止代码成为真正的弗兰肯斯坦式悲剧(Frankenstein,科学怪人),我们必须尽可能地自我组织,检查哪些功能已经存在,哪些实际需求尚将实现。 在许多情况下,只需对现有代码进行略微修改,得到新代码,并对其进行测试就足够了。 这段新代码会在我们即将实现的代码中重用,唯一要测试的就是为了创建全新功能,由我们后来添加的小控制函数。 优秀的程序员总是这样做:他们尝试通过向现有代码添加控制点,以某种方式重用现有代码。

修改 1. 添加资产名称

为了实现这一部分,我们不需要进行实质性的更改,但这些更改应该在正确的地方实现。 首先,我们为枚举添加一个新值,源代码如下所示:

enum eObjectsIDE {eRESULT, eBTN_BUY, eBTN_SELL, eCHECK_DAYTRADE, eBTN_CANCEL, eEDIT_LEVERAGE, eEDIT_TAKE, eEDIT_STOP};

以下是新代码;高亮显示的部分是已添加的部分。 请注意,我不会将新值添加到枚举的开头或结尾。 这样做是为了避免与其它已经存在,并正在运行的代码部分发生冲突。

enum eObjectsIDE {eRESULT, eLABEL_SYMBOL, eBTN_BUY, eBTN_SELL, eCHECK_DAYTRADE, eBTN_CANCEL, eEDIT_LEVERAGE, eEDIT_TAKE, eEDIT_STOP};

如果您在枚举的开头或结尾添加新值,则必须查找并更改所有引用这些极值的位置。 在许多情况下,可能由于健忘而导致遗漏,这将引发难以预料的错误。 您可能会认为这些错误看起来是由于新添加的内容引起的,而实际上是由于遗忘。 因此,我们应在极值之间添加修改。

之后,我们需要立即向系统添加一条消息,否则会出现运行时错误。 因此,在源代码中添加以下行。

static const string C_Chart_IDE::szMsgIDE[] = {"MSG_RESULT","MSG_NAME_SYMBOL","MSG_BUY_MARKET","MSG_SELL_MARKET","MSG_DAY_TRADE","MSG_CLOSE_POSITION","MSG_LEVERAGE_VALUE","MSG_TAKE_VALUE","MSG_STOP_VALUE"};

正如您所看到的,我们把它加在同一个地方,从而保持了顺序。 但目前常量可加在任何点位,这不会有任何区别,因为它只用于检查哪个对象会接收消息。 出于结构化目的,我们在加入时把它作为第二条消息。

现在,我们回到 MetaTrader 5,并进行如下更改:

现在,MetaTrader 5 已经将 IDE 中的对象识别为接收消息的对象,剩下的只是创建发送消息的过程。 消息中的文本只应添加一次,只要 MetaTrader 5 把 IDE 放在图表上,它就可以被发送。 这可由简单地将所需代码添加到对象类的 Create 函数末尾来实现。 但为了不让代码变成满面疤痕的弗兰肯斯坦,我们将在 DispatchMessage 函数内添加新代码。 原始函数如下所示:

void DispatchMessage(int iMsg, string szArg, double dValue = 0.0)
{if (m_CountObject < eEDIT_STOP) return;switch (iMsg){case CHARTEVENT_CHART_CHANGE:if (szArg == szMsgIDE[eRESULT]){ObjectSetInteger(Terminal.Get_ID(), m_ArrObject[eRESULT].szName, OBJPROP_BGCOLOR, (dValue < 0 ? clrLightCoral : clrLightGreen));ObjectSetString(Terminal.Get_ID(), m_ArrObject[eRESULT].szName, OBJPROP_TEXT, DoubleToString(dValue, 2));}break;case CHARTEVENT_OBJECT_CLICK:// ... The rest of the code...}
}

以下是完成相关修改后的代码:

void DispatchMessage(int iMsg, string szArg, double dValue = 0.0)
{if (m_CountObject < eEDIT_STOP) return;switch (iMsg){case CHARTEVENT_CHART_CHANGE:if (szArg == szMsgIDE[eRESULT]){ObjectSetInteger(Terminal.Get_ID(), m_ArrObject[eRESULT].szName, OBJPROP_BGCOLOR, (dValue < 0 ? clrLightCoral : clrLightGreen));ObjectSetString(Terminal.Get_ID(), m_ArrObject[eRESULT].szName, OBJPROP_TEXT, DoubleToString(dValue, 2));}else if (szArg == szMsgIDE[eLABEL_SYMBOL]){ObjectSetString(Terminal.Get_ID(), m_ArrObject[eLABEL_SYMBOL].szName, OBJPROP_TEXT, Terminal.GetSymbol());ObjectSetInteger(Terminal.Get_ID(), m_ArrObject[eLABEL_SYMBOL].szName, OBJPROP_ALIGN, ALIGN_CENTER);}break;case CHARTEVENT_OBJECT_CLICK:// ... The rest of the code}
}

创建 send 函数后,我们可以选择发送此消息的点。 最好的位置实际上是在对象类的 Create 函数的末尾,因此最终的代码如下所示:

bool Create(int nSub)
{m_CountObject = 0;if ((m_fp = FileOpen("Chart Trade\\IDE.tpl", FILE_BIN | FILE_READ)) == INVALID_HANDLE) return false;FileReadInteger(m_fp, SHORT_VALUE);for (m_CountObject = eRESULT; m_CountObject <= eEDIT_STOP; m_CountObject++) m_ArrObject[m_CountObject].szName = "";m_SubWindow = nSub;m_szLine = "";while (m_szLine != "</chart>"){if (!FileReadLine()) return false;if (m_szLine == "<object>"){if (!FileReadLine()) return false;if (m_szLine == "type"){if (m_szValue == "102") if (!LoopCreating(OBJ_LABEL)) return false;if (m_szValue == "103") if (!LoopCreating(OBJ_BUTTON)) return false;if (m_szValue == "106") if (!LoopCreating(OBJ_BITMAP_LABEL)) return false;if (m_szValue == "107") if (!LoopCreating(OBJ_EDIT)) return false;if (m_szValue == "110") if (!LoopCreating(OBJ_RECTANGLE_LABEL)) return false;}}}FileClose(m_fp);DispatchMessage(CHARTEVENT_CHART_CHANGE, szMsgIDE[eLABEL_SYMBOL]);return true;
}

添加的实际内容以绿色高亮显示。 请注意,在几乎不做任何更改的情况下,我们就已经有了一个 100% 实现的消息流,我们可以移步到需要实现的下一条消息。

修改2. 添加当天的累计值(覆盖点)

同样,我们遵循与添加资产名称时相同的逻辑,因此新代码如下所示:

enum eObjectsIDE {eRESULT, eLABEL_SYMBOL, eROOF_DIARY, eBTN_BUY, eBTN_SELL, eCHECK_DAYTRADE, eBTN_CANCEL, eEDIT_LEVERAGE, eEDIT_TAKE, eEDIT_STOP};// ... Rest of the codestatic const string C_Chart_IDE::szMsgIDE[] = {"MSG_RESULT","MSG_NAME_SYMBOL","MSG_ROOF_DIARY","MSG_BUY_MARKET","MSG_SELL_MARKET","MSG_DAY_TRADE","MSG_CLOSE_POSITION","MSG_LEVERAGE_VALUE","MSG_TAKE_VALUE","MSG_STOP_VALUE"};

之后,我们用一条新消息更改 IDE:

我们的新 IDE 已经准备就绪。 现在,我们将实现代码,来创建包含当天累计值的消息。 我们应该首先决定在哪个类中实现这个功能。 许多人可能会在 C_Chart_IDE 类中创建此函数,但出于组织原因,最好将其与处理订单的函数放在一起。 因此,代码是在 C_OrderView 类中实现的。 其代码示意如下:

double UpdateRoof(void)
{ulong   ticket;int     max;string  szSymbol = Terminal.GetSymbol();double  Accumulated = 0;HistorySelect(macroGetDate(TimeLocal()), TimeLocal());max = HistoryDealsTotal();for (int c0 = 0; c0 < max; c0++) if ((ticket = HistoryDealGetTicket(c0)) > 0)if (HistoryDealGetString(ticket, DEAL_SYMBOL) == szSymbol)Accumulated += HistoryDealGetDouble(ticket, DEAL_PROFIT);return Accumulated;
}

现在代码已经实现,我们需要将消息添加到系统中。 为了让操盘手的生活更轻松,我已经添加了代码来报告已完成的结果。 此为其代码:

void DispatchMessage(int iMsg, string szArg, double dValue = 0.0)
{static double AccumulatedRoof = 0.0;bool    b0;double  d0;if (m_CountObject < eEDIT_STOP) return;switch (iMsg){case CHARTEVENT_CHART_CHANGE:if ((b0 = (szArg == szMsgIDE[eRESULT])) || (szArg == szMsgIDE[eROOF_DIARY])){if (b0){ObjectSetInteger(Terminal.Get_ID(), m_ArrObject[eRESULT].szName, OBJPROP_BGCOLOR, (dValue < 0 ? clrLightCoral : clrLightGreen));ObjectSetString(Terminal.Get_ID(), m_ArrObject[eRESULT].szName, OBJPROP_TEXT, DoubleToString(dValue, 2));}else{AccumulatedRoof = dValue;dValue = 0;}d0 = AccumulatedRoof + dValue;ObjectSetString(Terminal.Get_ID(), m_ArrObject[eROOF_DIARY].szName, OBJPROP_TEXT, DoubleToString(MathAbs(d0), 2));ObjectSetInteger(Terminal.Get_ID(), m_ArrObject[eROOF_DIARY].szName, OBJPROP_BGCOLOR, (d0 >= 0 ? clrForestGreen : clrFireBrick));}else   if (szArg == szMsgIDE[eLABEL_SYMBOL]){ObjectSetString(Terminal.Get_ID(), m_ArrObject[eLABEL_SYMBOL].szName, OBJPROP_TEXT, Terminal.GetSymbol());ObjectSetInteger(Terminal.Get_ID(), m_ArrObject[eLABEL_SYMBOL].szName, OBJPROP_ALIGN, ALIGN_CENTER);}break;case CHARTEVENT_OBJECT_CLICK:// .... The rest of the code....}
}

一张图表上的多个指标(第 06 部分)相关推荐

  1. asp:boundfield 鼠标悬停后显示_设计了100张图表后,我学到了哪些经验?

    作者:William Bengtsson 译者: luserry 原文:https://medium.com/@william.bengtsson/learnings-from-designing-g ...

  2. tableau三轴合并_举个栗子!Tableau技巧(34):同一张图表如何呈现多个度量

    Tableau用户:怎样把条形状和折线图放在同一个图表里? 阿达:你想在同一个工作表里放入两个维度吗? Tableau用户:是的,有这样的栗子吗? 的确,在我们的日常数据分析工作中,常常需要对多个指标 ...

  3. 标题在图表上_Excel 2010基础应用:图表的创建与编辑

    在处理电子表格时,要对大量烦琐的数据进行分析和研究,有时需要利用图形方式再现数据变动和发展趋势.Excel提供了强有力的图表处理功能,使得用户很快就可得到所要的图表.下面介绍如何创建图表以及对图表的修 ...

  4. 英特尔提前发布财报源自一张图表被披露 公司已开始调查

    1月22日消息,据国外媒体报道,芯片巨头英特尔,在当地时间周四发布了2020年第四季度的财报,这是罗伯特·斯旺担任CEO期间发布的最后一次财报,虽然营收净利润同比均有下滑,但营收还是超出了他们在三季度 ...

  5. 项目管理—项目经理常用的10张图表推荐(华为项目管理10大模板)

    项目管理其实是有一些常用的工具和模板的,这也是项目经理们常用的,我们一些新入行的小白可能不怎么知道,有一些老人也不怎么会告诉,今天小编就给大家普及一下: 第一位的,当然就是甘特图了(甘特图的画法,项目 ...

  6. Python-matplotlib实现多条曲线画在一张图上

    调用Python包 import matplotlib.pyplot as plt import pandas as pd from matplotlib.pyplot import Multiple ...

  7. wps不能打印_Excel表格怎么打印在一张纸上?

    不知道小伙伴们有没有遇到过一个问题,就是在需要打印表格的时候,还是特别匆忙的情况下,结果打印机没有多余的纸了,只剩下那么一两张,这就很难为人呀.当然,还有一种情况是表格本来刚好可以打印一张纸,不用浪费 ...

  8. 使用Silverlight Toolkit绘制图表(上)--柱状图

       Silverlight Toolkit提供了绘制柱状图(Column,Bar),饼图(Pie),折线图(Line), 散点图(Scatter)等控件.我们可以很方便的将已有的数据源绑定到相应图形 ...

  9. QT自定义图表上不同元素的外观

    QT自定义图表上不同元素的外观 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 自定义图表上不同元素的外观. 项目技术 qt5.12,qt charts模块,C++ ...

最新文章

  1. vivo7.0系统机器(亲测有效)激活Xposed框架的教程
  2. 将string转成dict(Python)
  3. [算法系列之二十六]字符串匹配之KMP算法
  4. [汇编语言]用[bx+idata]的方式进行数组的处理-字母大小写转换
  5. 前缀表达式后缀表达式_你知道波兰表达式和逆波兰表达式吗
  6. 安装sql server 2008 management studio时,提示升级VS2008 到 SP1
  7. 三种方法实现二分查找
  8. Android通过Alpha实现渐变效果的几个方法
  9. 工作5年,别人成了架构师,你却还在基层打滚
  10. gd32f103驱动TLC59116(模拟i2c)
  11. webmax函数高级教程整理集2
  12. 4.4-软件开发中,“UI设计图”的作用与绘制方法说明
  13. 一台计算机安装几个操作系统,电脑装3个系统-一台电脑可以安装几个操作系统?...
  14. 浅析MultipartResolver
  15. 新买的电脑网速慢的解决方案
  16. matlab 设置position 位置 /xlabel/legend位置的设置方式
  17. GSM与GPRS区别介绍
  18. 台式计算机怎么加一个硬盘,台式机添加硬盘方法
  19. 在线帮助中心,轻松解决售后服务问题
  20. (十九)美萍酒店管理系统:系统维护_系统设置_房间设置_添加类型、修改类型

热门文章

  1. 从平安体系孵化,透过Q4财报看陆金所与金融壹账通的机与危
  2. 项目管理之敲门砖-PMP证书
  3. 开了家店但生意不好,又转不出去,一直在亏钱,怎么办?
  4. 一款实用延迟队列的自研历程
  5. 0079-【生信软件】-人类基因组hg19、hg38构建bwa索引
  6. C. k-Amazing Numbers(思维前缀最小值+枚举相同数距离)
  7. 烽火18台系列之八——Webshell,隐藏在网站之下的潘多拉魔盒
  8. Scala错误:找不到或无法加载主类 xxx解决方法
  9. JBPM知识点------JPDL3.1规范
  10. turn off x-window