文章 "图形界面 I:库结构(第一章)" - 页 3

 
AlexBar3073:

......但从 OOP 的角度来看,建议的方法最有可能得到实际应用。:)

说起来容易做起来难。

AlexBar3073:

...

例如,让我们考虑一下在图形上移动表格的函数。

在该函数中,我们需要枚举窗体的所有已创建对象。为什么呢?因为所有创建的元素都放在表单本身的容器(数组)中。为什么需要在函数中枚举所有创建的元素?为什么不能在容器中循环更改所有元素的坐标呢?

...

请注意数组(m_objects)的类型(CChartObject),该数组存储了该元素(CElement)的所有图形对象的指针。在这种情况下,您可以尝试使用动态类型转换,但这样代码会变得更加复杂,资源消耗也会更大,因为您必须对指针类型进行额外的检查。

至于Delete() 和类似方法,由于所有对象都是CChartObject 类型,因此可以循环使用(只是我还没有这样做)。

我谨慎地认为,在过渡到库开发的第二阶段后,一切都将变得更加容易,届时将绘制所有元素。也就是说,将只有一个元素--一个对象(bmp)。

 
Anatoli Kazharski:

对指针类型的附加检查。

如何在 MQL 中对指针类型进行检查?

根据我的资料,该语言没有这方面的任何手段。我想检查一个对象是否是一个特定类的实例,或者它是否是一个类在层次结构中的后代。

例如,我正在实现一种 MVC 模式,对于某些具有可编辑属性(具有共同祖先)的模型,我订阅了一个视图对象。以便显示该对象的属性表。在模型发生变化后,监听器(视图)会被重新绘制,模型对象也会被传递。

在这里,我们必须将模型转换为模型层次类型之一(可以返回属性)。但我们无法检查是否有正确类型的对象到达。

从理论上讲,第三方程序员在为一个接口创建应用程序时可能会犯错误,将该视图签到另一个模型(来自另一个层次结构,该层次结构没有一个具有可编辑属性的祖先)。这种情况无法在运行时处理,应用程序就会崩溃。

Anatoli Kazharski:

我谨慎地认为,在过渡到库开发的第二阶段后,一切都会变得容易得多,届时将绘制所有元素。也就是说,将只有一个元素--一个对象(bmp)。

几年前我就是这么做的。首先,我为界面、绘制基元、聚合视图、传递事件(弹出、停止)制作了一个 DOM 模型。一切都绘制在 MQL 图形对象上,原则上是可行的。但当对象数量超过 200 个时,由于重新绘制每个对象的开销,速度开始变慢。因此,在 Canvas 出现之前,一切都被放弃了一年。随后,通过替换视图的基本绘制方法和更新逻辑,一切都被迅速转移到了画布上,而没有改变其他任何东西。现在,即使在屏幕上显示几千个视图也不会导致延迟绘制,因为所有内容都会在内存中快速绘制和比较,而且输出只是一张图片,即图表上只有一个对象元素。

不过,去年由于没有空闲时间,用户界面库的开发工作几乎停止了。


 

为了避免证据不足,我将举例说明一个基于单一画布元素上的用户界面而构建的界面

 
Igor Volodin:

为了避免无凭无据,我将举例说明在用户界面的基础上构建一个界面的情况。

+ 喜欢 )
 
Igor Volodin:

如何检查 MQL 中的指针类型?

根据我的资料,该语言没有任何相关手段。我想检查一个对象是否是一个特定类的实例,或者它是否是一个类在层次结构中的后代。

例如,我正在实现一种 MVC 模式,对于某些具有可编辑属性(具有共同祖先)的模型,我订阅了一个视图对象。以便显示该对象的属性表。在模型发生变化后,监听器(视图)会被重新绘制,模型对象也会被传递。

在这里,我们必须将模型转换为模型层次类型之一(可以返回属性)。但我们无法检查是否有正确类型的对象到达。

从理论上讲,第三方程序员在为一个接口创建应用程序时可能会犯错误,将该视图签到另一个模型(来自另一个层次结构,该层次结构没有一个具有可编辑属性的祖先)。这种情况无法在运行时处理,应用程序就会崩溃。

...

也许可以通过dynamic_cast 来实现?当我开始开发这个库时,还没有dynamic_cast

类似这样(此处的 示例):

class CFoo { };
class CBar { };
//+------------------------------------------------------------------+
//| 脚本程序启动功能|
//+------------------------------------------------------------------+
void OnStart()
  {
   void *vptr[2];
   vptr[0]=new CFoo();
   vptr[1]=new CBar();
//---
   for(int i=0;i<ArraySize(vptr);i++)
     {
      if(dynamic_cast<CFoo *>(vptr[i])!=NULL)
         Print("CFoo * object at index ",i);
      if(dynamic_cast<CBar *>(vptr[i])!=NULL)
         Print("CBar * object at index ",i);
     }
   CFoo *fptr=vptr[1];  // 指针转换错误,vptr[1] 不是 CFoo 对象
  }
//+------------------------------------------------------------------+

//---

伊戈尔-沃洛金

几年前我也是这么做的。首先,我为界面、绘制基元、聚合视图、传递事件(弹出、停止)制作了一个 DOM 模型。一切都绘制在 MQL 图形对象上,原则上是可行的。但当对象数量超过 200 个时,由于重新绘制每个对象的开销,速度开始变慢。因此,在 Canvas 出现之前,一切都被放弃了一年。随后,通过替换视图的基本绘制方法和更新逻辑,一切都被迅速转移到了画布上,而没有改变其他任何东西。现在,即使在屏幕上显示几千个视图也不会导致延迟绘制,因为所有内容都会在内存中快速绘制和比较,而且输出的只是一张图片,即图表上的对象中只有一个元素。

在过去的一年中,由于缺乏空闲时间,用户界面库的开发实际上已经停止了。

这非常有趣。您是否也实现了自己的输入字段?

 
Igor Volodin:

为了避免证据不足,我将举例说明在一个位图元素的用户界面基础上构建的界面

看起来很酷。谢谢你的例子。)

有一个主题,您的建议将非常有用:在画布上制作一个众包项目

 
Anatoli Kazharski:

也许可以通过dynamic_cast 来实现?当我开始开发这个库的时候,还没有dynamic_cast

CFoo *foo = dynamic_cast<CFoo *>(&bar); // 不会出现关键执行错误


哦,我没看到。谢谢。原来他们是在八月份添加的。如果它返回 NULL 而且没有发生严重错误,那就已经很不错了。我们可以工作 )

Anatoli Kazharski:

您是否也实现了自己的输入字段?

输入字段是这样实现的

当事件焦点集中 在可编辑字段对象上时,用户界面中将插入一个带有当前值的所需配置的可编辑字段图形对象,您可以使用输入缓冲区进行操作(在界面中没有缓冲区是不行的)、

模糊 事件中,字段的值将被保存(同时删除系统图形对象 - 编辑)。该值将以文本形式显示在 bmp 上。

 

Igor Volodin:

...

输入字段的操作方法如下:

在可编辑字段对象的焦点 事件中,用户界面中将插入带有当前值的所需配置的可编辑字段 图形对象,您可以使用输入缓冲器等工具进行操作(在界面中没有缓冲器就无法操作)、

模糊 事件中, 字段值将被保存(系统图对象 - 编辑将被删除)。该值将以文本形式显示在 bmp 上。

啊哈,明白了。谢谢你的解释。

我认为这是最好的选择,但我想尝试将所有内容都绘制在一个对象上。这样就可以获得完全的独立性和经验,因为在什么环境下创建图形用户界面 并不重要。比方说,只有一个画布,没有其他任何东西。)

 
Anatoli Kazharski:

看起来很酷。谢谢你的例子。)

这里有一个主题,您的建议会派上用场:做一个众包 Canvas 项目

谢谢。看到你在界面上所做的大量工作,我为你点个大大的赞。如果是我,肯定做不到这一点。首先是宣传,其次是一致性。

众包?有风险。当然,如果你有稳定的收入和空闲时间,为社会造福是可能的。但 MQL 社会将用于商业产品,而非免费产品。而 GPL 许可证本身并不能禁止这一点。

简而言之,我看不到任何利润。

 
Anatoli Kazharski:

但最终,我还是想尝试以这样一种方式来实现一切,即在一个对象上绘制所有内容。这样就可以获得完全的独立性和体验,无论 在什么环境下创建图形界面 都没有关系。比方说,只有一个画布,没有其他任何东西。)

向 Renate 申请使用系统缓冲区的函数,就可以绘制一切了。