La tela è forte!

 

Mi sono dato un compito: dimostrare le capacità della grafica personalizzata tramite la classe CCanvas in un breve codice.

Ecco cosa ne è venuto fuori.

Questo script funziona sia in MQL5 che in MQL4. Ma è molto più veloce su MT5.

Ogni fotogramma è unico e non si ripete, cioè lo script non è ciclico.

#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();
  }


Prima di compilare, spostare l'array m_pixels[] da protected: a public in Canvas.mqh:

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

                     CCanvas(void);
                    ~CCanvas(void);
File:
Swirl.mq5  3 kb
Swirl.ex5  16 kb
 

Fico, di sicuro!

E può anche essere usato per cose utili ;)

 
Andrey Khatimlianskii:

Fico, di sicuro!

E può anche essere usato per cose utili ;)

Affinché le persone inizino ad usare Kanvas per cose utili, è necessario iniziare a mostrare cose inutili. :))

 
Nikolai Semko:

È necessario spostare l'array m_pixels[] da protected: a public nel file Canvas.mqh prima della compilazione:

Non c'è bisogno di cambiare nulla nel 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:

Non devi cambiare nulla nel SB.


Fico! :))

Ma purtroppo non è gratis.

Ho controllato. Il rallentamento totale su MT5 era ~11%.

 
Nikolai Semko:

Fico! :))

Ma purtroppo non è gratis.

Ho controllato. Il rallentamento totale su MT5 era ~11%.

Il tuo caso usa l'1% di CCanvas. Senza CCanvas, fate una prova. Il codice non sarà minimamente più complicato e la velocità migliorerà ancora di più.

 
fxsaber:

Nel vostro caso, l'1% è usato da CCanvas. Prova senza CCanvas. Il codice non sarà minimamente più complicato e la velocità sarà ancora maggiore.

Naturalmente, potete anche fare a meno della classe CCanvas. Ma il codice aumenterà, mentre la velocità di elaborazione non migliorerà, dato che tutto ciò che effettivamente uso dalla classe CCanvas è l'array m_pixels[] di pixel di risorse grafiche (e le funzioni Update() e Destroy(), ma non saranno di alcuna utilità, e ci risparmieremo appena).

Ma un array è sempre un array. Come puoi renderlo più veloce? Non si può. Solo la classe CCanvas si occupa di alcune routine, quando si crea una risorsa, la si aggiorna (o meglio la si ricrea) e la si elimina.

O stai dicendo che C.m_pixels[] non compila come accesso diretto all'array? Penso che sia diretto. Senza alcun gesto intermedio. O mi sbaglio?

Sarebbe ancora più logico per gli sviluppatori di questa classe spingere il CreateBitmapLabel nel costruttore della classe stessa per evitare l'incombenza. Se si crea una nuova istanza della classe senza parametri, allora si crea una tela con le dimensioni nella finestra (come nel mio caso), e se si vuole, si possono specificare i parametri quando si crea un'istanza della classe. L'ho fatto anch'io in questo modo.

 
Nikolai Semko:

Naturalmente, potrei fare a meno della classe CCanvas. Ma il codice aumenterà, ma non ci sarà alcun guadagno in velocità, perché tutto ciò che uso dalla classe CCanvas è l'array di risorse grafiche m_pixels[] (e le funzioni Update() e Destroy(), ma potete trascurarle, perché non faranno risparmiare).

Ma un array è sempre un array. Come puoi renderlo più veloce? Non si può. Solo la classe CCanvas si occupa di alcune routine, quando si crea una risorsa, la si aggiorna (o meglio la si ricrea) e la si elimina.

O stai dicendo che C.m_pixels[] non compila come accesso diretto all'array? Penso che sia diretto. Senza alcun gesto intermedio. O mi sbaglio?

CCanvas è un wrapper per ResourceCreate. Così, per esempio, avete 20 immagini pronte sotto forma di array. Se volete cambiarli via canvas, dovrete fare ArrayCopy+Update costosi.

E se lo fate senza CCanvas, avrete bisogno solo di ResourceCreate+ChartRerdraw. Ho pubblicato diversi lavori di disegno dinamico in kodobase. Lì era ovvio che CCanvas non è buono.

 
Nikolai Semko:

È necessario spostare l'array m_pixels[] da protected: a public nel file Canvas.mqh prima della compilazione:

Sei sicuro che PixelSet non ti aiuterà?

 
Rashid Umarov:

Sei sicuro che PixelSet non ti aiuterà?

Certo, aiuterà, ma sarà terribilmente lento. In primo luogo, una chiamata di funzione non è libera, perché i parametri vengono passati e salvati (in PixelSet, non è nemmeno per riferimento), tutti i registri devono essere spinti sullo stack e poi tirati fuori di nuovo. In secondo luogo, la funzione stessa controlla se X e Y rientrano nell'intervallo specificato, e in terzo luogo, calcola l'indice dell'array. E non ho bisogno di tutto questo perché ho già un indice e nel mio algoritmo non posso uscire dall'intervallo.

 
Fantastico grafico dell'arcobaleno! Mi piacerebbe anche far danzare le candele sulla musica e farle girare l'una con l'altra!