帆布很酷!

 

我给自己定了一个任务:通过CCanvas类在简短的代码中展示自定义图形 的能力。

下面是它的结果。

这个脚本在MQL5和MQL4中都适用。但在MT5上则快得多。

每一帧都是唯一的,不会重复,也就是说,脚本不是循环的。

#include <Canvas\Canvas.mqh>

void OnStart()
  {
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CCanvas C;
   int Width=(ushort)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);  // получаем Ширину окна
   int Height=(ushort)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); // получаем Высоту окна
   if(!C.CreateBitmapLabel(0,0,"CanvasExamlple",0,0,Width,Height,COLOR_FORMAT_XRGB_NOALPHA)) // создаем канвас размером текущего окна
   Print("Error creating canvas: ",GetLastError()); 
   uint i=0,j=100000;
   int size=Width*Height;
   uchar h[25600];
   for (int w=0;w<25600;w++) 
   h[w]= uchar(128+128*sin(double(w)/256));//создаем массив для ускорения работы
   double X1=0,Y1=0,X2=0,Y2=0;
   while(!IsStopped())
     {
      int pos=int(i%size);
      if(pos==0)
        {
         C.Update();
         //Sleep(30);
         X1= Width-(sin((double)j/100)*(double)Width);
         Y1= Height-(cos((double)j/140)*(double)Height);
         X2= Width+(cos((double)j/80)*(double)Width);
         Y2= Height+(sin((double)j/20)*(double)Height);
         j++;
        }
      int X=pos%Width;
      int Y=int(pos/Width);
      double d= ((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))/(((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))+((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y)));
      C.m_pixels[pos]=XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]);
      i++;
     }
   C.Destroy();
  }


在编译之前,将Canvas.mqh中的数组m_pixels[]从protected: 移到public。

public:
   uint              m_pixels[];               // array of pixels

                     CCanvas(void);
                    ~CCanvas(void);
附加的文件:
Swirl.mq5  3 kb
Swirl.ex5  16 kb
 

酷,是肯定的!

甚至可以用来做有用的事情;)

 
Andrey Khatimlianskii:

酷,是肯定的!

甚至可以用来做有用的事情;)

要让人们开始使用Kanvas做有用的事情,你需要从展示无用的东西开始。:))

 
Nikolai Semko:

你需要在编译前将 Canvas.mqh 文件中的数组 m_pixels[] 从 protected: 移到 public。

你不需要改变SB中的任何东西。

class CCanvas2 : public CCanvas
{
private:
  int Pos;

public:
  CCanvas2* operator []( const int iPos )
  {
    this.Pos = iPos;
    
    return(&this);
  }
  
  void operator =( const uint Color )
  {
    this.m_pixels[this.Pos] = Color;
  }
};


CCanvas2 C;
//..
// C.m_pixels[pos]=XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]);
C[pos]=XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]);
 
fxsaber:

你不需要改变SB中的任何东西。


酷!:))

但不幸的是,这并不是免费的。

检查了一下。在MT5上的整体减速是~11%。

 
Nikolai Semko:

酷!:))

但不幸的是,这并不是免费的。

检查了一下。MT5上的总减速为~11%。

你的案例使用了CCanvas的1%。试试不使用CCanvas。代码不会有丝毫的复杂,速度会有更大的提高。

 
fxsaber:

在你的案例中,使用的是CCanvas的1%。试试不使用CCanvas。代码不会有丝毫的复杂,速度也会有更大的提高。

当然,你也可以不使用CCanvas类。但代码会增加,而处理速度不会有任何提高,因为我从CCanvas类中实际使用的只是图形资源数组m_pixels[](以及Update()和Destroy()函数,但它们不会有任何用处,我们几乎不会在它们身上省钱)。

但数组仍然是数组。如何让它更快?你不能。当你创建一个资源,更新它(或者说重新创建它)和删除它时,只有CCanvas类会处理一些常规工作。

或者你是说C.m_pixels[]不能被编译为直接的数组访问?我认为这很直接。没有任何中间的姿态。还是我错了?

这个类的开发者将CreateBitmapLabel塞进类的构造函数本身,以避免隐约可见,这将是更合理的做法。如果你创建一个没有参数的类的新实例,那么你就会在窗口中创建一个尺寸的画布(如我的例子),如果你愿意,你可以在创建类的实例时指定参数。我自己就是这样做的。

 
Nikolai Semko:

当然,我可以不使用CCanvas类。但代码会增加,但速度不会有任何提高,因为我从CCanvas类中使用的只是图形资源数组m_pixels[](以及Update()和Destroy()函数,但你可以忽略它们,因为它们不会省钱)。

但数组仍然是数组。如何让它更快?你不能。当你创建一个资源,更新它(或者说重新创建它)和删除它时,只有CCanvas类会处理一些常规工作。

或者你是说C.m_pixels[]不能被编译为直接的数组访问?我认为这很直接。没有任何中间的姿态。还是我搞错了?

CCanvas是ResourceCreate的一个包装器。因此,举例来说,你有20个现成的数组形式的图像。如果你想通过画布改变它们,你将不得不做昂贵的ArrayCopy+Update。

而如果你不使用CCanvas,你将只需要ResourceCreate+ChartRerdraw。我在kodobase中发布了几个动态绘图工作。在那里很明显,CCanvas是不好的。

 
Nikolai Semko:

你需要在编译前将 Canvas.mqh 文件中的数组 m_pixels[] 从 protected: 移到 public。

你确定 PixelSet 没有帮助吗?

 
Rashid Umarov:

你确定 PixelSet 没有帮助吗?

当然,这将有所帮助,但会非常缓慢。首先,函数调用是不自由的,因为参数被传递和存储(在PixelSet中,这甚至不是通过引用完成的),所有的寄存器必须被塞进堆栈,然后再拉出来。第二,函数本身检查X和Y是否落入指定的范围,第三,它计算数组索引。而且我不需要这些,因为我已经有了一个索引,在我的算法中,我不可能超出范围。

 
很酷的彩虹图!我还想让蜡烛随着音乐起舞,并相互扭动!
原因: