Leinwand ist cool!

 

Ich habe mir eine Aufgabe gestellt: die Möglichkeiten von benutzerdefinierten Grafiken über die CCanvas-Klasse in einem kurzen Code zu demonstrieren.

Folgendes ist dabei herausgekommen.

Dieses Skript funktioniert sowohl in MQL5 als auch in MQL4. Aber auf MT5 geht es viel schneller.

Jedes Bild ist einmalig und wird nicht wiederholt, d. h. das Skript ist nicht zyklisch.

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


Vor dem Kompilieren muss das Array m_pixels[] in Canvas.mqh von protected: nach public verschoben werden:

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

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

Cool, auf jeden Fall!

Und kann sogar für nützliche Dinge verwendet werden ;)

 
Andrey Khatimlianskii:

Cool, auf jeden Fall!

Und kann sogar für nützliche Dinge verwendet werden ;)

Damit die Menschen anfangen, Kanvas für nützliche Dinge zu nutzen, müssen Sie damit beginnen, nutzlose Dinge zu zeigen. :))

 
Nikolai Semko:

Sie müssen das Array m_pixels[] in der Datei Canvas.mqh vor der Kompilierung von protected: nach public verschieben:

Sie brauchen in SB nichts zu ändern.

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:

Sie müssen nichts an der SB ändern.


Super! :))

Aber leider ist sie nicht kostenlos.

Ich habe es überprüft. Die Gesamtverlangsamung auf MT5 betrug ~11%.

 
Nikolai Semko:

Super! :))

Aber leider ist sie nicht kostenlos.

Ich habe es überprüft. Die Gesamtverlangsamung auf MT5 betrug ~11 %.

Ihr Fall verwendet 1% von CCanvas. Versuchen Sie es ohne CCanvas. Der Code wird nicht im Geringsten komplizierter, und die Geschwindigkeit wird sich noch weiter verbessern.

 
fxsaber:

In Ihrem Fall wird 1% von CCanvas verwendet. Versuchen Sie es ohne CCanvas. Der Code wird kein bisschen komplizierter, und die Geschwindigkeit wird noch höher sein.

Natürlich können Sie auch auf die CCanvas-Klasse verzichten. Aber der Code wird zunehmen, während die Verarbeitungsgeschwindigkeit nicht besser wird, da alles, was ich tatsächlich von der CCanvas-Klasse verwende, m_pixels[] Array von Grafikressourcen-Pixeln ist (und Update() und Destroy() Funktionen, aber sie werden nicht von Nutzen sein, und wir werden kaum Geld für sie sparen).

Aber ein Array ist immer noch ein Array. Wie kann man es schneller machen? Das können Sie nicht. Die CCanvas-Klasse kümmert sich einfach um einige Routinen, wenn Sie eine Ressource erstellen, aktualisieren (oder besser gesagt neu erstellen) und löschen.

Oder wollen Sie sagen, dass C.m_pixels[] nicht als direkter Array-Zugriff kompiliert wird? Ich denke, es ist direkt. Ohne jegliche Zwischengesten. Oder liege ich da falsch?

Es wäre noch logischer, wenn die Entwickler dieser Klasse die Funktion CreateBitmapLabel in den Klassenkonstruktor selbst verlagern würden, um ein Auflaufen zu vermeiden. Wenn Sie eine neue Instanz der Klasse ohne Parameter erstellen, dann erstellen Sie eine Leinwand mit der Größe im Fenster (wie in meinem Fall), und wenn Sie wollen, können Sie Parameter angeben, wenn Sie eine Instanz der Klasse erstellen. Ich habe es selbst so gemacht.

 
Nikolai Semko:

Natürlich könnte ich auf die CCanvas-Klasse verzichten. Aber der Code wird zunehmen, aber es wird keinen Geschwindigkeitsgewinn geben, denn alles, was ich von der CCanvas-Klasse verwende, ist das grafische Ressourcen-Array m_pixels[] (und die Update()- und Destroy()-Funktionen, aber Sie können sie vernachlässigen, denn sie werden kein Geld sparen).

Aber ein Array ist immer noch ein Array. Wie kann man es schneller machen? Das können Sie nicht. Die CCanvas-Klasse kümmert sich einfach um einige Routinen, wenn Sie eine Ressource erstellen, aktualisieren (oder besser gesagt neu erstellen) und löschen.

Oder wollen Sie sagen, dass C.m_pixels[] nicht als direkter Array-Zugriff kompiliert wird? Ich denke, es ist direkt. Ohne jegliche Zwischengesten. Oder täusche ich mich?

CCanvas ist ein Wrapper für ResourceCreate. So haben Sie zum Beispiel 20 fertige Bilder in Form von Arrays. Wenn Sie sie über Canvas ändern wollen, müssen Sie teures ArrayCopy+Update machen.

Und wenn Sie es ohne CCanvas machen, brauchen Sie nur ResourceCreate+ChartRerdraw. Ich habe mehrere Aufträge zum dynamischen Zeichnen in kodobase veröffentlicht. Es war offensichtlich, dass CCanvas nicht gut ist.

 
Nikolai Semko:

Sie müssen das Array m_pixels[] in der Datei Canvas.mqh vor dem Kompilieren von protected: nach public verschieben:

Sind Sie sicher, dass PixelSet nicht helfen wird?

 
Rashid Umarov:

Sind Sie sicher, dass PixelSet nicht helfen wird?

Natürlich wird es helfen, aber es wird furchtbar langsam sein. Erstens ist ein Funktionsaufruf nicht frei, da Parameter übergeben und gespeichert werden (in PixelSet geschieht dies nicht einmal per Referenz), alle Register müssen auf den Stack geschoben und dann wieder herausgezogen werden. Zweitens prüft die Funktion selbst, ob X und Y in den angegebenen Bereich fallen, und drittens berechnet sie den Array-Index. Und ich brauche das alles nicht, weil ich bereits einen Index habe und in meinem Algorithmus kann ich nicht aus dem Bereich herauskommen.

 
Coole Regenbogenkarte! Ich möchte auch, dass die Kerzen zur Musik tanzen und sich miteinander drehen!
Grund der Beschwerde: