Die Betrachtung der CCanvas-Klasse. Wie man transparente Objekte zeichnet

Vladimir Karputov | 27 Juni, 2016

Inhaltsangaben


Einleitung

In MetaTrader 5 zu zeichnen, geht ganz einfach. Sie müssen dazu nur ein paar Feinheiten wissen. Eine davon hängt damit zusammen, wie der Terminalbildschirm angelegt ist. Genauer gesagt, sind wir daran interessiert, wie Grafiken auf diesem Bildschirm ausgegeben werden. So kann z.B. ein Chart im Vorder- oder im Hintergrund angezeigt werden. Die Farbwiedergabe auf dem Bildschirm hängt dann von der Anzeige des Charts ab. Einige grafische Objekte können ihre Farbe in überlappenden oder kreuzenden Bereich verändern.

Bevor wir uns direkt mit dem Zeichnen unter Verwendung der CCanvas-Klasse beschäftigen, sehen wir uns zunächst einige Definitionen im Zusammenhang mit Farbbearbeitung genauer an. Wir wollen z.B. herausfinden, was der Alpha-Kanal für eine Bedeutung hat.

Meiner Meinung nach ist die Implementierung von Transparenz die wichtigste Technologie, denn durch Farben wird jedes Bild erst richtig lebendig. So kann Transparenz z.B. zur Umsetzung einer attraktiveren Schnittstelle mit glatten Farbübergängen oder Schattierungen verwendet werden. Schattierungen oder Schatten geben einem Grafikobjekt mehr Dimension und glätten die Objektkanten für den Betrachter.


1 Transparenz (Alpha-Kanal)

Wir leben in einer dreidimensionalen Welt und nehmen alles um uns herum dreidimensional wahr. Diese Dreidimensionalität haben wir sogar mal tatsächlich gesehen oder gefühlt. In der dreidimensionalen Welt erkennen und verstehen wir, welches Objekt näher an uns dran ist.

Einige Objekte sind durchsichtig, z.B. ein klares Glas mit einer durchsichtige Flüssigkeit vor blauem Hintergrund. Der blaue Hintergrund ist durch das Glas samt seiner Flüssigkeit erkennbar, wobei seine Details vom Grad der Durchsichtigkeit oder Transparenz abhängen.


Abb. 1 Allgemeine Sichtweise der Dimensionalität

Abb. 1 Allgemeine Sichtweise der Dimensionalität


In diesem Beispiel ist die Transparenz nicht virtuell und auch nicht illusionär. Transparenz wird in diesem Fall als etwas ganz Normales, Selbstverständliches angesehen.

Doch wird ein Bild auf einem Computermonitor angezeigt, sieht alles komplett anders aus: Die Pixel-Matrix ist zweidimensional, d.h. das von der Matrix gezeigte Bild hat eine Höhe und eine Breite, jedoch fehlt im die dritte Dimension - seine Tiefe. Es ist daher nicht möglich, ein Pixel über ein anderes zu platzieren und die Situation zu simulieren, das untere Pixel wäre ein gelber Hintergrund und das obere Pixel eben ein durchsichtiges Glas. Jedes Bild eines dreidimensionalen und realistischen Objekts auf dem Computerbildschirm ist eine Illusion, die man durch den Einsatz von Farbe und Schatten erzeugt.

Als Beispiel kann ein Bild so betrachtet werden, dass es in zwei Schichten aufgeteilt werden kann: die untere Schicht - ein blauer Hintergrund, und die obere Schicht - ein Glas mit einer undurchsichtigen Flüssigkeit. Auf dem Bildschirm sieht das dann so aus:


Abb. 2 Undurchsichtiges Glas

Abb. 2 Undurchsichtiges Glas


Auf dem entstandenen Bild ist das Glas komplett undurchsichtig. Um Transparenz hinzuzufügen (oder zu verändern), müssen wir alle Farben des Bildes in die ARGB-Farbwiedergabe übersetzen.


2 ARGB-Farbwiedergabe

Keine Angst, ich habe die Transparenz des Glases nicht vergessen. Dazu kommen wir aber erst im zweiten Teil dieses Beitrags.

Die ARGB-Farbwiedergabe ist ein uint Type aus vier Bytes, in dem die folgenden Werte aufgezeichnet werden: ein Alpha-Kanal, Rot, Grün und Blau. Um also der Farbe im RGB-Format Transparenz zu verleihen, wird ein extra Byte mit dem Wert 'Transparenz' hinzugefügt - nämlich der sog. Alpha-Kanal.

Abb. 3 ARGB

Abb. 3 ARGB

Der Wert eines Alpha-Kanals wird von 0 (die Farbe eines Vordergrund-Pixels ändert die Anzeige eines darunter liegenden nicht) bis 255 (die Farbe eines darunter liegenden Pixels wird komplett durch die Farbe des Vordergrund-Pixels ersetzt) eingestellt. Die Farbtransparenz wird in Prozentwerten folgendermaßen berechnet:

Formel 1.1

Mit anderen Worten: je kleiner der Wert des Alpha-Kanals ist, umso transparenter wird die Farbe. Wenn wir die gewünschte Transparenz kennen, kann der Alpha-Wert folgendermaßen berechnet werden:

Formel 1.2

Die Umwandlung von Farbe in ARGB erfolgt mit Hilfe der ColorToARGB-Funktion (Farbe, alpha).


3 Schema der Objektzeichnung im Terminal

Zum besseren Verständnis, wie Farbe bearbeitet wird, betrachten wir uns das Schema der gegenseitigen Anordnung von Grafikobjekten mit zwei unterschiedlich eingerichteten Charts - eins im Hintergrund und eins im Vordergrund.

3.1 Chart im Hintergrund

Für diese Option, auf das Chart klicken und dann aus dem Dropdown-Menü "Eigenschaften..." auswählen und zur Registerkarte "Allgemein" gehen.


Abb. 4 Chart im Hintergrund

Abb. 4 Chart im Hintergrund


Ein Chartfenster im Terminal besteht aus vier Schichten. Auf den zwei extremen Schichten ("Hintergrund" und "Vordergrund") kann gezeichnet werden:

Abb. 5 Schema des Chartfensters

Abb. 5 Schema des Chartfensters


Im Hintergrund, sowie auch im Vordergrund, wird ein gezeichnetes Objekt durch ein anderes in Übereinstimmung mit den Zeiten ihrer Zeichnung überlagert.

Das bedeutet: das älteste Objekte befindet sich ganz weit hinten, auf der hintersten Schicht des "Hintergrunds" und auf der hintersten Schicht des "Vordergrunds". Jüngere Objekte erscheinen weiter vorne.


Abb. 6 Position von Objekten nach Zeit ihrer Zeichnung

Abb. 6 Position von Objekten nach Zeit ihrer Zeichnung


Nicht alle Objekte können sich, ohne Neuzeichnung der zugrunde liegenden Grafikobjekten in dem Feld (oder Feldern) wo sie überlappen, komplett überlappen .

Die Tabelle fasst die Charakteristika der Grafikobjekte zusammen, gefolgt von einer Erklärung der Überlappung der Objekte, die in den überlappenden Bereichen neu gezeichnet werden müssen.

ID Objekt Beschreibung Überlappung mit einem darunter liegenden Objekt
 OBJ_VLINE  Senkrechte Linie  Keine Neuzeichnung
 OBJ_HLINE  Waagrechte Linie Keine Neuzeichnung
 OBJ_TREND    Trendlinie Keine Neuzeichnung
 OBJ_TRENDBYANGLE    Trendlinie nach Winkel  Keine Neuzeichnung
 OBJ_CYCLES    Kreislinien Keine Neuzeichnung
 OBJ_ARROWED_LINE    Bepfeilte Linie Keine Neuzeichnung
 OBJ_CHANNEL    Abstandsgleicher Kanal Keine Neuzeichnung
 OBJ_STDDEVCHANNEL    Standardabweichungskanal  Keine Neuzeichnung
 OBJ_REGRESSION    Linearer Regressionskanal Keine Neuzeichnung
 OBJ_PITCHFORK    Andrews’ Pitchfork Keine Neuzeichnung
 OBJ_GANNLINE    Gann-Line Keine Neuzeichnung
 OBJ_GANNFAN    Gann-Fächer Keine Neuzeichnung
 OBJ_GANNGRID    Gann-Raster Keine Neuzeichnung
 OBJ_FIBO    Fibonacci-Retracement Keine Neuzeichnung
 OBJ_FIBOTIMES     Fibonacci-Zeitzonen Keine Neuzeichnung
 OBJ_FIBOFAN    Fibonacci-Fächer Keine Neuzeichnung
 OBJ_FIBOARC  Fibonacci-Bögen Keine Neuzeichnung
 OBJ_FIBOCHANNEL    Fibonacci-Kanal Keine Neuzeichnung
 OBJ_EXPANSION    Fibonacci-Expansion Keine Neuzeichnung
 OBJ_ELLIOTWAVE5    Elliott Waves - 5 Keine Neuzeichnung
 OBJ_ELLIOTWAVE3    Elliott Waves - 3 Keine Neuzeichnung
 OBJ_RECTANGLE    Rechteck Keine Neuzeichnung, wenn ohne Füllung;
bei Füllung Neuzeichnung
 OBJ_TRIANGLE    Dreieck Keine Neuzeichnung, wenn ohne Füllung;
bei Füllung Neuzeichnung
 OBJ_ELLIPSE    Ellipse Keine Neuzeichnung, wenn ohne Füllung;
bei Füllung Neuzeichnung
 OBJ_ARROW_THUMB_UP    Daumen hoch Keine Neuzeichnung
 OBJ_ARROW_THUMB_DOWN    Daumen nach unten Keine Neuzeichnung
 OBJ_ARROW_UP    Pfeil nach oben Keine Neuzeichnung
 OBJ_ARROW_DOWN    Pfeil nach unten Keine Neuzeichnung
 OBJ_ARROW_STOP    Stopp Keine Neuzeichnung
 OBJ_ARROW_CHECK    Häkchen Keine Neuzeichnung
 OBJ_ARROW_LEFT_PRICE    Linke Kurskennzeichnung Keine Neuzeichnung
 OBJ_ARROW_RIGHT_PRICE    Rechte Kurskennzeichnung Keine Neuzeichnung
 OBJ_ARROW_BUY    Kaufen-Markierung Keine Neuzeichnung
 OBJ_ARROW_SELL    Verkaufen-Markierung Keine Neuzeichnung
 OBJ_ARROW    Pfeilobjekt Keine Neuzeichnung
 OBJ_TEXT    Textobjekt Keine Neuzeichnung
 OBJ_LABEL    Textbeschriftungsobjekt Keine Neuzeichnung
 OBJ_BUTTON    Schaltflächenobjekt Keine Neuzeichnung
 OBJ_CHART    Chartobjekt Keine Neuzeichnung
 OBJ_BITMAP    Bitmap-Objekt Keine Neuzeichnung
 OBJ_BITMAP_LABEL    Bitmap-Label-Objekt Keine Neuzeichnung
 OBJ_EDIT    Bearbeitungsobjekt Keine Neuzeichnung
 OBJ_EVENT    Das Ereignis-Objekt, das zu einem Ereignis im Wirtschaftskalender passt Keine Neuzeichnung
 OBJ_RECTANGLE_LABEL    Das Rechteck-Kennzeichnungsobjekt, mit dem die individuell angepasste Grafikschnittstelle erzeugt und designed wurde  Keine Neuzeichnung

Tabelle 1 Überlagerung und Transparenz von Grafikobjekten


Sehen wir uns das Beispiel von drei Objekten des Typs OBJ_RECTANGLE (Rechtecke) an und besprechen den Algorithmus zur Neuzeichnung in den Überlappungsbereichen der Objekte, die neu gezeichnet werden sollten (xor.mq5 Datei).

Das Script (xor.mq5 Datei) richtet die weiße Hintergrundfarbe ein (0xFFFFFF) und zeichnet die gefüllten Rechtecke Nr. 1 und Nr. 2 in Blau (0x0000FF), Rechteck Nr. 3 ist Rot (0xFF0000) und gefüllt.


Abb. 7 Neuzeichnung. Chart im Hintergrund

Abb. 7 Neuzeichnung. Chart im Hintergrund


Wir haben zwei Kreuzungsbereiche, in denen sich die Farbe veränderte:

  1. Bereich Nr. 1 – die entstandene Farbe (0x000000) ist komplett transparent, sodass wir im Bereich Nr. 1 den Hintergrund und das Chart unverändert sehen können;
  2. Bereich Nr. 2 – die entstandene Farbe (0x00FF00).

Wenn sich Grafikobjekte wie z.B. Rechtecke überlappen, werden sie vom Algorithmus des Bitwise OR neu gezeichnet.


Abb. 6 unten zeigt ein Beispiel der Neuzeichnung von Farben für beide Bereiche:

Buchstäbliche Darstellung Ganzzahlige Darstellung Binäre Darstellung Anmerkung
C’0,0,255’ 0x0000FF 0000 0000 0000 0000 1111 1111 Blau


XOR
C’0,0,225’ 0x0000FF 0000 0000 0000 0000 1111 1111 Blau


=
C’0,0,0’ 0x000000 0000 0000 0000 0000 0000 0000 Transparent


XOR
C’255,255,255’ 0xFFFFFF 1111 1111 1111 1111 1111 1111 Weiß (Hintergrund)


=
C’255,255,255’ 0xFFFFFF 1111 1111 1111 1111 1111 1111 Weiß

Tabelle 2 Bitwise OR für Blau + Blau + Weiß


Buchstäbliche Darstellung Ganzzahlige Darstellung Binäre Darstellung Anmerkung
C’0,0,255’ 0x0000FF 0000 0000 0000 0000 1111 1111 Blau


XOR
C’255,0,0’ 0xFF0000 1111 1111 0000 0000 0000 0000 Rot


=
С’255,0,255’ 0xFF00FF 1111 1111 0000 0000 1111 1111


XOR
C’255,255,255’ 0xFFFFFF 1111 1111 1111 1111 1111 1111 Weiß (Hintergrund)


=
С’0,255,0’ 0x00FF00 1111 1111 1111 0000 0000 0000

Tabelle 3 Bitwise OR für Blau + Rot + Weiß


3.2 Chart im Vordergrund

Ist der Parameter 'Chart im Vordergrund' aktiviert, unterscheidet sich die Anordnung der Ebenen des Chartfensters von der des Charts im Hintergrund:


Abb. 8 Schema des Chartfensters. Chart vorne

Abb. 8 Schema des Chartfensters. Chart vorne


Ist die 'Chart im Vordergrund' Option aktiviert, verschmelzen die zwei Zeichnungsebenen 'Vordergrund' und 'Hintergrund' zu einer gemeinsamen Ebene. Diese gemeinsame Ebene befindet sich unter den Ebenen mit den Balken und Rastern.


3.3 Neuzeichnung für "obersten Chart"

Wie schon in Abb. 7, betrachten wir uns nun auch den Algorithmus zur Neuzeichnung an den Überlappungen der Objekte, die neu gezeichnet sind (xor.mq5 Datei).


Das Script (xor.mq5 Datei) richtet die weiße Hintergrundfarbe ein (0xFFFFFF) und zeichnet die gefüllten Rechtecke Nr. 1 und Nr. 2 in Blau (0x0000FF), Rechteck Nr. 3 ist Rot (0xFF0000) und gefüllt.


Abb. 9 Neuzeichnung. Chart im Vordergrund

Abb. 9 Neuzeichnung. Chart im Vordergrund

Vergleichen wir jetzt Abbildungen 7 und 9 miteinander, erkennen wir schnell, dass die sich überlappenden Bereiche gleich neu gezeichnet wurden.


4 Farben mischen - Entstehende Farbe

Wie bereits erwähnt, ist Transparenz auf dem Bildschirm eine Illusion. Farbmanipulationen. Um Abb. 2 auf dem Bildschirm zu simulieren, müssen wir nur verstehen, wie man eine Farbe mit Transparenz auf dem Bildschirm anzeigt, d.h. wir müssen die entstehende Farbe des Pixels berechnen.

Angenommen, wir wollen Rot mit Alpha-Kanal 128 auf einer Leinwand vor weißem Hintergrund zeichnen (Chart-Hintergrund im "Schwarz-auf-Weiß" Farbschema). Im ARGB-Format ist die Farbe 0x80FF0000. Zur Berechnung der entstehenden Farbe, müssen wir die Farbe jeder der Kanäle berechnen (Rot, Grün und Blau).

Und dies ist die Formel zur Berechnung der entstehenden Farbe mit einem, auf Farbe angewendeten und auf "1" normalisierten, Alpha-Kanal:

Formel 1.3

wobei:

  • Ergebnis der Ergebniswert der Farbkanal-Intensität ist. Ist dieser Wert > 255, wird 255 geliefert.
  • Hintergrund der Wert des Hintergrund-Farbkanals ist.
  • Vordergrund der Wert des Farbkanals des überlappenden Bildes ist.
  • alpha ein Alpha-Wert ist, der auf "1" normalisiert wurde.

Berechnen wir nun die entstehende Farbe gemäß der Formel (1.3):

Alpha-Kanal Alpha-Kanal, auf "1" normalisiert R G B Anmerkung


255 255 255 Weiß
128 0,5 255 0 0 Rot mit Alpha 128


255*(1-0,5)+255*0,5=255 255*(1-0,5)+0*0,5=127 255*(1-0,5)+0*0,5=127

Tabelle 4 Ergebnis der Berechnung mit Hilfe der Formel (1.3)

Die auf dem Bildschirm entstehende Farbe ist folgende:

Abb. 10 Entstehende Farbe

Abb. 10 Entstehende Farbe

4.1 Methoden zur Farbbearbeitung. ENUM_COLOR_FORMAT

Bei der Erzeugung einer Leinwand kann man eine der drei Methoden zur Farbbearbeitung festlegen (ENUM_COLOR_FORMAT):


ID Beschreibung
COLOR_FORMAT_XRGB_NOALPHA Die Alpha-Komponente wird ignoriert
COLOR_FORMAT_ARGB_RAW Farb-Komponenten werden vom Terminal nicht verarbeitet (sie sollten vom Benutzer exakt spezifiziert werden)
COLOR_FORMAT_ARGB_NORMALIZE Farb-Komponenten werden vom Terminal verarbeitet

Tabelle 5 Methoden zur Farbbearbeitung zur Leinwand-Erzeugung

Wenn man die exakte Überlagerung der RGB-Komponenten berücksichtigt, liefert COLOR_FORMAT_ARGB_NORMALIZE ein noch schöneres Bild. Die entstandene Farbe bei der Anwendung von Farbe mit einem Alpha-Kanal, wird gemäß der Formel berechnet (1.3).

COLOR_FORMAT_ARGB_RAW kontrolliert das 'Überlaufen' von RGB-Komponenten einer Farbe nicht, daher ist COLOR_FORMAT_ARGB_RAW im Vergleich zu COLOR_FORMAT_ARGB_NORMALIZE die schnellere Methode.

Hier ist die Formel zur Berechnung für die COLOR_FORMAT_ARGB_RAW Methode der entstandenen Farbe, mit einem auf die Farbe angewendeten Alpha-Kanal, der auf "1" normalisiert wurde:

Formel 1.4

wobei:

  • Ergebnis der Ergebniswert der Farbkanal-Intensität ist. Ist dieser Wert > 255, wird 255 geliefert.
  • Hintergrund der Wert des Hintergrund-Farbkanals ist.
  • Vordergrund der Wert des Farbkanals des überlappenden Bildes ist.
  • alpha ein Alpha-Wert ist, der auf "1" normalisiert wurde.

5 Die Illusion von Transparenz

Jetzt kommen wir endlich zur praktischen Implementierung von Transparenz.

Zeichnen wir also eine Anzahl gefüllter Rechtecke (Script "xor.mq5"). Zur Veranschaulichung der Unterschiede in den Methoden zur Farbbearbeitung, versuchen wir, drei sich nicht überlappende waagrechte Leinwände ganz oben auf dem Chart anzubringen.

Die erste wird mit Hilfe von COLOR_FORMAT_XRGB_NOALPHA verarbeitet, die zweite mit Hilfe von COLOR_FORMAT_ARGB_RAW, und die dritte mit Hilfe von COLOR_FORMAT_ARGB_NORMALIZE. Danach verändern wir die Transparenz schrittweise von 255 (komplett undurchsichtig) auf 0 (komplett transparent). Unser Script nennen wir der Einfachheit halber "Illusion.mq5".

Und das Video zeigt, wie "Illusion.mq5" funktioniert:


Abb. 11 So funktioniert das Script 'Illusion.mq5'


5.1 Erstellung des Scripts"Illusion.mq5"

Alle neuen oder veränderten Teile des Codes sind hervorgehoben.

Das leere Script-Template:

//+------------------------------------------------------------------+
//|                                                     Illusion.mq5 |
//|                              Copyright © 2015, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2015, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.0"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
  }

Dieses ergänzen wir mit der Script-Beschreibung, einer Option zur Eingabe von Parametern während des Starts des Scripts und verknüpfen es mit der CCanvas-Klasse, die das Zeichnen ermöglicht:

#property version   "1.0"
#property description "The illusion of transparency"
//--- show the window of input parameters when launching the script
#property script_show_inputs
#include <Canvas\Canvas.mqh>

Für den Script-Ablauf brauchen wir einige Variablen - Höhe und Breite des Charts, Höhe und Breite der Leinwand sowie Hilfsvariablen zum Zeichnen der Leinwand-Koordinaten:

#include <Canvas\Canvas.mqh>

//+------------------------------------------------------------------+
//| inputs                                                           |
//+------------------------------------------------------------------+
input color colr=clrRed;
input color clr_Circle=clrBlue;
//--- variable width and height of the chart.
int            ChartWidth=-1;
int            ChartHeight=-1;
//---
uchar alpha=0;                //alpha channel managing color transparency
int   can_width,can_height;   //width and height of the canvas
int   can_x1,can_y1,can_x2,can_y2,can_y3,can_x3;   //coordinates
Die Breite und Höhe des Charts bekommen wir mit Hilfe der Standard-Funktionen:

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
  }

//+------------------------------------------------------------------+
//| Chart property width                                             |
//+------------------------------------------------------------------+
int ChartWidthInPixels(const long chart_ID=0)
  {
//--- prepare the variable to get the property value
   long result=-1;
//--- reset the error value
   ResetLastError();
//--- receive the property value
   if(!ChartGetInteger(chart_ID,CHART_WIDTH_IN_PIXELS,0,result))
     {
      //--- display the error message in Experts journal
      Print(__FUNCTION__+", Error Code = ",GetLastError());
     }
//--- return the value of the chart property
   return((int)result);
  }
//+------------------------------------------------------------------+
//| Chart property height                                            |
//+------------------------------------------------------------------+
int ChartHeightInPixelsGet(const long chart_ID=0,const int sub_window=0)
  {
//--- prepare the variable to get the property value
   long result=-1;
//--- reset the error value
   ResetLastError();
//--- receive the property value
   if(!ChartGetInteger(chart_ID,CHART_HEIGHT_IN_PIXELS,sub_window,result))
     {
      //--- display the error message in Experts journal
      Print(__FUNCTION__+", Error Code = ",GetLastError());
     }
//--- return the value of the chart property
   return((int)result);
  }

Direkt zu OnStart() gehen.

Zur besseren Übersichtlichkeit zeigt Abb. 12 das Layout der Leinwände auf dem Chart und die Hilfsvariablen für die Leinwand-Koordinaten:


Abb. 12 Koordinaten auf dem Chart

Abb. 12 Koordinaten auf dem Chart


Holen wir uns nun die Höhe und Breite des Charts und berechnen die Hilfsvariablen für die Leinwand-Koordinaten:

void OnStart()
  {
//--- width and height of the chart
   ChartWidth=ChartWidthInPixels();
   ChartHeight=ChartHeightInPixelsGet()-50;
//---
   can_width=ChartWidth/3;   can_height=ChartHeight;
   can_x1=0;            can_y1=0;
   can_x2=can_width;    can_y2=0;
   can_x3=can_width*2;  can_y3=0;
  }

Mit der berechneten Breite und Höhe der Leinwand und den Hilfsvariablen können wir bereits zu zeichnen beginnen.

Als nächstes ändern wir den 'leeren' Typ der OnStart() Funktion auf 'int' und zeichnen auf der ersten Leinwand ein gefülltes Rechteck, einen Text mit dem Namen der die Farbe der Leinwand bearbeitenden Methode und einen gefüllten Kreis:

int OnStart()
  {
//--- width and height of the chart
   ChartWidth=ChartWidthInPixels();
   ChartHeight=ChartHeightInPixelsGet()-50;
//---
   can_width=ChartWidth/3;   can_height=ChartHeight;
   can_x1=0;            can_y1=0;
   can_x2=can_width;    can_y2=0;
   can_x3=can_width*2;  can_y3=0;
//--- create canvas COLOR_FORMAT_XRGB_NOALPHA
   CCanvas canvas_XRGB_NOALPHA,canvas_ARGB_RAW,canvas_XARGB_NORMALIZE;
   if(!canvas_XRGB_NOALPHA.CreateBitmapLabel("canvas_XRGB_NOALPHA",can_x1,can_y1,can_width-1,can_height,COLOR_FORMAT_XRGB_NOALPHA))
     {
      Print("Error creating canvas: ",GetLastError());
      return(-1);
     }
   canvas_XRGB_NOALPHA.Erase(ColorToARGB(colr,alpha));
   canvas_XRGB_NOALPHA.TextOut((can_width)/2,can_height/2,"canvas_XRGB_NOALPHA",ColorToARGB(clrBlue,255),TA_CENTER|TA_VCENTER);
   canvas_XRGB_NOALPHA.FillCircle((can_width)/2,can_height/2+50,25,ColorToARGB(clr_Circle,255));
   canvas_XRGB_NOALPHA.Update();
   return(0);
  }

Noch einige weitere Details zum zuletzt hinzugefügten Code-Teil.

canvas_XRGB_NOALPHA.CreateBitmapLabel("canvas_XRGB_NOALPHA",can_x1,can_y1,can_width-1,can_height,COLOR_FORMAT_XRGB_NOALPHA)

canvas_XRGB_NOALPHA.CreateBitmapLabel - Hier erzeugen wir eine Grafikressource, die an ein Chart-Objekt gebunden ist.

Die Farbbearbeitungsmethode bei der ersten Leinwand ist COLOR_FORMAT_XRGB_NOALPHA - die Alpha-Komponente wird ignoriert.

canvas_XRGB_NOALPHA.Erase(ColorToARGB(colr,alpha));

Füllt die gesamte Leinwand mit einer Farbe im ARGB-Format mit der Alpha-Transparenz.

Beim Füllen der Leinwand wird der Alpha-Kanal deswegen ignoriert, die hier ja die COLOR_FORMAT_XRGB_NOALPHA Methode zur Farbbearbeitung verwendet wird.

canvas_XRGB_NOALPHA.TextOut((can_width)/2,can_height/2,"canvas_XRGB_NOALPHA",ColorToARGB(clrBlue,255),TA_CENTER|TA_VCENTER);

Textausgabe - die Art der Bildverarbeitung für die Leinwand. Die Textfarbe ist im ARGB-Format und der Alpha-Kanal = 255, d.h., die Farbe des angezeigten Texts ist komplett undurchsichtig.

Der angezeigte Text ist waagrecht (TA_CENTER) und senkrecht (TA_VCENTER) zur Mitte des Rechtecks zugeschnitten.

canvas_XRGB_NOALPHA.FillCircle((can_width)/2,can_height/2+50,25,ColorToARGB(clr_Circle,255));

Zeichnung eine gefüllten Kreises. Den Kreis zeichnen wir über die Farbe, die die Leinwand füllt (canvas_XRGB_NOALPHA.Erase(ColorToARGB(colr, alpha));).

Damit soll gezeigt werden, dass eine auf die Leinwand (oder einen Bereich/Punkt) gezeichnete Form jedes auf der Leinwand darunter liegende Bild komplett bedeckt. D.h. es gibt auf der Leinwand keine Neuzeichnung, da die letzte Zeichnung den darunter liegenden Bereich komplett bedeckt.

canvas_XRGB_NOALPHA.Update();

Um alle gezeichneten Objekte auch auf dem Bildschirm anzeigen zu können, müssen wir den Bildschirm aktualisieren.

Auf ganz ähnliche Weise werden auch die beiden anderen Leinwände gezeichnet - die zweite Leinwand mit dem Anzeige-Modus COLOR_FORMAT_ARGB_RAW und die dritte mit COLOR_FORMAT_ARGB_NORMALIZE:

   canvas_XRGB_NOALPHA.Update();

//--- create canvas COLOR_FORMAT_ARGB_RAW
   if(!canvas_ARGB_RAW.CreateBitmapLabel("canvas_ARGB_RAW",can_x2,can_y2,can_width-1,can_height,COLOR_FORMAT_ARGB_RAW))
     {
      Print("Error creating canvas: ",GetLastError());
      return(-1);
     }
   canvas_ARGB_RAW.Erase(ColorToARGB(colr,alpha)); //clrNONE,0));
   canvas_ARGB_RAW.TextOut((can_width)/2,can_height/2,"canvas_ARGB_RAW",ColorToARGB(clrBlue,255),TA_CENTER|TA_VCENTER);
   canvas_ARGB_RAW.FillCircle((can_width)/2,can_height/2+50,25,ColorToARGB(clr_Circle,255));
   canvas_ARGB_RAW.Update();

//--- create canvas COLOR_FORMAT_ARGB_NORMALIZE
   if(!canvas_XARGB_NORMALIZE.CreateBitmapLabel("canvas_XARGB_NORMALIZE",can_x3,can_y3,can_width-1,can_height,COLOR_FORMAT_ARGB_NORMALIZE))
     {
      Print("Error creating canvas: ",GetLastError());
      return(-1);
     }
   canvas_XARGB_NORMALIZE.Erase(ColorToARGB(colr,alpha));
   canvas_XARGB_NORMALIZE.TextOut((can_width)/2,can_height/2,"canvas_XARGB_NORMALIZE",ColorToARGB(clrBlue,255),TA_CENTER|TA_VCENTER);
   canvas_XARGB_NORMALIZE.FillCircle((can_width)/2,can_height/2+50,25,ColorToARGB(clr_Circle,255));
   canvas_XARGB_NORMALIZE.Update();
   return(0);
  }

Die Leinwand und die Grafikobjekte innerhalb der Leinwände sind gezeichnet worden.

Fügen wir jetzt die Schleife hinzu, die die Transparenz der gesamten Leinwand ändern wird:

   canvas_XARGB_NORMALIZE.FillCircle((can_width)/2,can_height/2+50,25,ColorToARGB(clr_Circle,255));
   canvas_XARGB_NORMALIZE.Update();
   //--- transparent from 255 to 0
   uchar transparent;
   for(transparent=255;transparent>0;transparent--)
     {
      canvas_XRGB_NOALPHA.TransparentLevelSet(transparent);
      canvas_XRGB_NOALPHA.Update();
      canvas_ARGB_RAW.TransparentLevelSet(transparent);
      canvas_ARGB_RAW.Update();
      canvas_XARGB_NORMALIZE.TransparentLevelSet(transparent);
      canvas_XARGB_NORMALIZE.Update();
      Sleep(50);
     }
   canvas_XRGB_NOALPHA.TransparentLevelSet(transparent);
   canvas_XRGB_NOALPHA.Update();
   canvas_ARGB_RAW.TransparentLevelSet(transparent);
   canvas_ARGB_RAW.Update();
   canvas_XARGB_NORMALIZE.TransparentLevelSet(transparent);
   canvas_XARGB_NORMALIZE.Update();
   Sleep(6000);
   return(0);
  }

Die Transparenz für alle Leinwände wird verändert mit Hilfe der Codezeilen:

.TransparentLevelSet(transparent)

Nach Ende der Zeichnung müssen wir 'aufräumen' - also Grafik-Ressourcen entfernen.

Da wir die Grafik-Ressourcen mit Verweis auf das Chart-Objekt erzeugt haben (die CreateBitmapLabel Methode), entfernen wir die Ressource nun mittels der Destroy() Methode, die zudem auch das Chart-Objekt (Bitmap-Label) vernichtet:

   canvas_XARGB_NORMALIZE.Update();
   Sleep(6000);
   //--- finish
   canvas_XRGB_NOALPHA.Destroy();
   canvas_ARGB_RAW.Destroy();
   canvas_XARGB_NORMALIZE.Destroy();
   return(0);
  }

Das Script, das die Transparenz ganz weich verändert, funktioniert.

Der Unterschied zwischen dem COLOR_FORMAT_ARGB_RAW und COLOR_FORMAT_ARGB_NORMALIZE Modus wird besser sichtbar, wenn man das Script zuerst im weißen Chart-Hintergrund laufen lässt und dann erst im schwarzen.


Fazit

Dieser Beitrag hat sich mit den Grundlagen der Arbeit mit Farben beschäftigt. Wir haben erfahren, wie man Objekte in einem Chart-Fenster zeichnen kann. Außerdem wurden auch die Grundlagen der Arbeit mit der CCanvas-Klasse der Standard Library und dem ARGB-Format der Farbwiedergabe mit Transparenz besprochen.

Das sind allerdings wirklich nur die Grundlagen - es gibt noch einige ganze Menge mehr zu entdecken, wie man verschiedenste grafische Effekte im MetaTrader 5 Terminal erzeugen kann. Dieser Beitrag hat sich mit Transparenz beschäftigt - und die wohl schönste Form zur Umfassung von Grafikobjekten erhält man mit der teilweisen Transparenz. Aufgrund der zweidimensionalen Natur des Monitor, ist die Transparenz im Chart eine Illusion, die mit Hilfe der Bearbeitung von Pixel erreicht werden kann.