Diskussion zum Artikel "Erstellung eines Dashboards zur Anzeige von Daten in Indikatoren und EAs"

 

Neuer Artikel Erstellung eines Dashboards zur Anzeige von Daten in Indikatoren und EAs :

In diesem Artikel werden wir eine Dashboard-Klasse erstellen, die in Indikatoren und EAs verwendet werden kann. Dies ist ein einleitender Artikel in einer kleinen Serie von Artikeln mit Vorlagen für die Einbeziehung und Verwendung von Standardindikatoren in Expert Advisors. Ich beginne mit der Erstellung eines Panels, das dem MetaTrader 5-Datenfenster ähnelt.

In diesem Artikel werde ich ein Dashboard erstellen, das vom Entwickler festgelegte Daten anzeigen kann. Ein solches Panel eignet sich für die visuelle Darstellung von Daten in einem Chart und für das visuelle Debugging, da es bequemer ist, die erforderlichen Werte auf dem Panel zu sehen als sie im Debugger zu verfolgen. Ich meine Fälle, in denen die Strategie in Abhängigkeit von einigen Datenwerten debuggt wird.

Ich werde das Panel in Form eines Prototyps des Terminal-Datenfensters erstellen und es mit denselben Daten füllen:


Abb. 1. Datenfenster und Dashboard

Mit unserem nutzerdefinierten Panel können wir jede beliebige Menge der erforderlichen Daten hinzufügen, es signieren und die Messwerte über den Programmcode anzeigen und aktualisieren.

Es sollte möglich sein, das Panel mit der Maus auf dem Chart zu verschieben, es an der gewünschten Position anzudocken und es zu komprimieren/erweitern. Um die Daten bequem auf der Tafel zu platzieren, kann eine Tabelle mit der angegebenen Anzahl von Zeilen und Spalten angezeigt werden. Die Daten dieser Tabelle können im Journal angezeigt werden (X- und Y-Koordinaten jeder Tabellenzelle) und programmatisch abgerufen werden, um den Index der Zeile und der Spalte anzugeben, in der sich diese Daten befinden sollen, oder man kann die Koordinaten einfach ausdrucken und die gewünschten Koordinaten in den Code eingeben, direkt bei der Anzeige von Text und Daten. Die erste Methode ist bequemer, da sie vollständig automatisiert ist. Das Panel wird auch eine aktive Schließtaste haben, aber wir delegieren deren Handhabung an das Steuerprogramm, da nur der Programmentwickler entscheiden sollte, wie er auf das Drücken der Schließtaste reagiert. Wenn eine Schaltfläche angeklickt wird, wird ein nutzerdefiniertes Ereignis an die Ereignisbehandlung des Programms gesendet. Der Entwickler kann sie nach eigenem Ermessen bearbeiten.

Autor: Artyom Trishkin

 

Danke für die Mitteilung.

Diese Implementierung der Klasse hat einen großen Nachteil, wenn es eine Notwendigkeit, es zu erben.

1. Es gibt keinen Standardkonstruktor und der parametrische Konstruktor legt wichtige Parameter nach Größe fest. Wenn Sie zum Beispiel die Größe des Panels auf der Grundlage seiner Parameter im Nachfahren der Klasse berechnen müssen, dann muss diese Logik entweder außerhalb der Klasse oder in der Klasse implementiert werden, aber mit der Berechnung in einer separaten Funktion, was die Logik etwas übertrifft, da der Aufruf des parametrischen Konstruktors ohne den Standardkonstruktor in der Initialisierungsliste steht. Eine bessere Lösung wäre vielleicht, die Initialisierung vom Konstruktor in eine Klassenfunktion zu verlagern.

2. Der Abschnitt mit den Parametern ist als privat deklariert, was es dem Nachfahren nicht erlaubt, z.B. ein anderes Farbschema zu implementieren oder die Größe der Kopfzeile zu ändern

3. Ich verstehe, dass die Arbeit nicht abgeschlossen ist, aber einige Funktionen sind nicht implementiert, zum Beispiel SetButtonClose(On/Off), SetButtonMinimize(On/Off).

Da der Quellcode verfügbar ist, ist es kein Problem, ihn fertigzustellen, aber trotzdem...

 
Evgeny #:

Vielen Dank für die Mitteilung.

Diese Implementierung der Klasse hat einen großen Nachteil, wenn es eine Notwendigkeit, es zu erben.

1. Es gibt keinen Standardkonstruktor und der parametrische Konstruktor legt wichtige Parameter nach Größe fest. Wenn Sie zum Beispiel die Größe des Panels auf der Grundlage seiner Parameter im Nachkommen der Klasse berechnen müssen, dann muss diese Logik entweder außerhalb der Klasse oder in der Klasse implementiert werden, aber mit der Berechnung in einer separaten Funktion, was die Logik etwas untergräbt, da der Aufruf des parametrischen Konstruktors ohne den Standardkonstruktor in der Initialisierungsliste steht. Eine bessere Lösung wäre vielleicht, die Initialisierung vom Konstruktor in eine Klassenfunktion zu verlagern.

2. Der Abschnitt mit den Parametern ist als privat deklariert, was es dem Nachfahren nicht ermöglicht, z.B. ein anderes Farbschema zu implementieren oder die Größe der Kopfzeile zu ändern

3. Mir ist klar, dass die Arbeit noch nicht abgeschlossen ist, aber einige Funktionen sind nicht implementiert, zum Beispiel SetButtonClose(On/Off), SetButtonMinimize(On/Off).

Da der Quellcode verfügbar ist, ist es kein Problem, ihn fertigzustellen, aber trotzdem...

Der Artikel ist ein Tutorium. In ihm deckt das Panel die Mindestanforderungen ab.

1. Der Nachkomme hat seinen eigenen Konstruktor, in seiner Initialisierungsliste sollte der Konstruktor des Elternteils stehen. Darin geben Sie die erforderlichen Abmessungen an.

(2) An Farbschemata habe ich noch gar nicht gedacht) sowie die Größe der Kopfzeile.

3) Solche Methoden werden im öffentlichen Bereich deklariert. Es ist seltsam, dass sie nicht implementiert sind. Ich erinnere mich genau, dass ich ihre Aktivierung/Deaktivierung getestet habe.... Ich musste diese Klasse von Grund auf neu schreiben, weil ihre erste Version von Windows zerstört wurde, als der Speicherplatz auf der Festplatte zu Ende ging. Ich muss dann vergessen haben, sie wiederherzustellen. Danke, ich werde es korrigieren.

Ja, mit der Verfügbarkeit des Quellcodes liegen alle Karten in den Händen der Leser. Darauf zielen die Artikel in den Tutorials ab.

 
Artyom Trishkin #:

Der Artikel ist lehrreich. Darin deckt das Gremium die Mindestanforderungen ab.

1. Der Nachkomme hat seinen eigenen Konstruktor, seine Initialisierungsliste sollte den Konstruktor des Elternteils enthalten. Darin geben Sie die erforderlichen Abmessungen an.

(2) Ich habe nicht einmal über Farbschemata nachgedacht) sowie die Größe der Kopfzeile.

(3) Solche Methoden werden im öffentlichen Bereich deklariert. Es ist seltsam, dass sie nicht implementiert sind. Ich erinnere mich genau, dass ich ihre Aktivierung/Deaktivierung getestet habe.... Ich musste diese Klasse von Grund auf neu schreiben, weil ihre erste Version von Windows zerstört wurde, als der Speicherplatz auf der Festplatte zu Ende ging. Ich muss dann vergessen haben, sie wiederherzustellen. Danke, ich werde es korrigieren.

Ja, mit der Verfügbarkeit des Quellcodes liegen alle Karten in den Händen der Leser. Darauf zielen die Artikel in den Tutorials ab.

1. Ja, aber wenn der Vorfahrenkonstruktor in der Initialisierungsliste aufgerufen wird , muss die Berechnung der Parameter, die ihm übergeben werden sollen, irgendwo durchgeführt werden. Vor allem, wenn es nicht der primitivste ist.

Z.B. Berechnung der X, Y Position für die anfängliche Anzeige in der rechten unteren Ecke, Berechnung der Höhe in Abhängigkeit von der erwarteten Anzahl der Tabellenzeilen.... Dies erfordert 3 zusätzliche Klassenfunktionen, die nicht alle in einem Stück Code in ihrem Konstruktor mit dem anschließenden Aufruf des Vorgängerkonstruktors enthalten sind. Es sieht eher wie eine Krücke aus, obwohl es funktioniert. Nun, es ist kein besonders schöner Code, wenn man die Klassenarchitektur für weitere Änderungen anpassungsfähiger machen kann. (Natürlich ist dies eine Bemerkung aus den Notizen eines Perfektionisten).

2. Kleine Verschönerungen machen das Produkt qualitativ besser. Aber Ihr Code ist im Allgemeinen schön und Ihre Lösungen sind interessant, es ist angenehm, ihn zu lesen.

3. Ich habe Verständnis, Datenverlust ist immer sehr unangenehm, daher ist ein zuverlässiges Backup unser Ein und Alles.

Vielen Dank, wir warten auf neue Artikel.

 
MetaQuotes:

Sehen Sie sich den neuen Artikel an: Erstellung eines Dashboards zur Anzeige von Daten in Indikatoren und EAs.

Autor: Artyom Trishkin

Danke für das sehr schöne Tutorial


Ich habe es zu einem dunklen Look modifiziert und möchte auch die Farben von Titel und Daten ändern

Außerdem habe ich eine Funktion erstellt, um Text auf einfache Weise hinzuzufügen

void DrawData(int cell, string title, string data, color clr ) {
   dashboard.DrawText(title,  dashboard.CellX(cell,0)+2,   dashboard.CellY(cell,0)+2, clr);
   dashboard.DrawText(data,   dashboard.CellX(cell,1)+2,   dashboard.CellY(cell,1)+2,90, clr);
   ChartRedraw(ChartID());
}

aber ich finde es schwierig, die Farben dieser Texte zu ändern, ich bin mir nicht sicher, was falsch ist, da die Farben langweilig aussehen, hier ist die modifizierte DrawText-Funktion

//+------------------------------------------------------------------+
//| Anzeige einer Textnachricht an den angegebenen Koordinaten |
//+------------------------------------------------------------------+
void CDashboard::DrawText(const string text,const int x,const int y,const color clr,const int width=WRONG_VALUE,const int height=WRONG_VALUE)
  {
//--- Deklarieren Sie Variablen, um die Textbreite und -höhe darin festzuhalten
   int w=width;
   int h=height;
//--- Wenn die Breite und Höhe des an die Methode übergebenen Textes Nullwerte haben,
//--- dann wird der gesamte Arbeitsbereich mit der transparenten Farbe vollständig geleert
   if(width==0 && height==0)
      this.m_workspace.Erase(0x00FFFFFF);
//--- Andernfalls
   else
     {
      //--- Wenn die übergebenen Werte für Breite und Höhe Standardwerte sind (-1), erhalten wir die Breite und Höhe aus dem Text
      if(width==WRONG_VALUE && height==WRONG_VALUE)
         this.m_workspace.TextSize(text,w,h);
      //--- sonst,
      else
        {
         //--- wenn die an die Methode übergebene Breite den Standardwert (-1) hat - die Breite aus dem Text holen, oder
         //--- wenn die an die Methode übergebene Breite einen Wert größer als Null hat, wird die an die Methode übergebene Breite verwendet, oder
         //--- wenn die an die Methode übergebene Breite einen Nullwert hat, wird der Wert 1 für die Breite verwendet
         w=(width ==WRONG_VALUE ? this.m_workspace.TextWidth(text)  : width>0  ? width  : 1);
         //--- wenn die an die Methode übergebene Höhe einen Standardwert (-1) hat, wird die Höhe aus dem Text ermittelt, oder
         //--- wenn die an die Methode übergebene Höhe einen Wert größer als Null hat, wird die an die Methode übergebene Höhe verwendet, oder
         //--- wenn die an die Methode übergebene Höhe einen Nullwert hat, wird der Wert 1 für die Höhe verwendet
         h=(height==WRONG_VALUE ? this.m_workspace.TextHeight(text) : height>0 ? height : 1);
        }
      //--- Füllen Sie den Raum entsprechend den angegebenen Koordinaten und der sich daraus ergebenden Breite und Höhe mit einer transparenten Farbe (löschen Sie den vorherigen Eintrag)
      this.m_workspace.FillRectangle(x,y,x+w,y+h,0x00FFFFFF);
     }
//--- Anzeige des Textes an der Stelle, an der der vorherige Text gelöscht wurde, und Aktualisierung des Arbeitsbereichs ohne Neuzeichnen des Bildschirms
   this.m_workspace.TextOut(x,y,text,::ColorToARGB(clr,this.m_alpha));
   this.m_workspace.Update(false);
  }
 

Arpit T # :

//--- Anzeige des Textes an der Stelle, an der der vorherige Text gelöscht wurde, und Aktualisierung des Arbeitsbereichs ohne Neuzeichnen des Bildschirms
   this .m_workspace. TextOut (x,y,text,:: ColorToARGB (clr, this .m_alpha ));
   this .m_workspace.Update( false );

Die hervorgehobene Farbe ist die Transparenz des Feldes selbst, nicht des Textes. Für Text ist es besser, die Transparenz (oder besser gesagt, die Deckkraft) auf den Standardwert von 255 zu setzen - völlig undurchsichtiger Text. Sie können jedoch mit dem Wert der Deckkraft "herumspielen", indem Sie anstelle von this.m_alpha reguläre numerische Werte von 0 bis 255 eingeben. 0 ist eine völlig transparente Farbe, 255 ist eine völlig undurchsichtige Farbe.

 
Artyom Trishkin #:

Die hervorgehobene Farbe ist die Transparenz des Feldes selbst, nicht des Textes. Für Text ist es besser, die Transparenz (oder besser gesagt, die Deckkraft) auf den Standardwert von 255 zu setzen - völlig undurchsichtiger Text. Sie können jedoch mit dem Wert der Deckkraft "herumspielen", indem Sie anstelle von this.m_alpha reguläre numerische Werte von 0 bis 255 eingeben. 0 ist eine völlig transparente Farbe, 255 ist eine völlig undurchsichtige Farbe.

Danke, jetzt ist alles gut


void DrawData(int cell, string title, string data, color clr ) {
   dashboard.DrawText(title,  dashboard.CellX(cell,0)+2,   dashboard.CellY(cell,0)+2, clr);
   dashboard.DrawText(data,   dashboard.CellX(cell,1)+2,   dashboard.CellY(cell,1)+2,90, clr);
   ChartRedraw(ChartID());
}

der hervorgehobene Code war das Problem, ich habe ihn entfernt und alles ist gut.

 
gut gemacht Arbeit dunkel ist schön
 
VIKRAM SINGH #:
gut gemacht Arbeit dunkel ist schön

Danke

Hier ist der geänderte Konstruktor für das dunkle Aussehen in dashboard.mqh, falls Sie dieses Thema verwenden möchten

//+------------------------------------------------------------------+
//| Konstruktor|
//+------------------------------------------------------------------+
CDashboard::CDashboard(const uint id,const int x,const int y, const int w,const int h,const int wnd=-1) : 
                        m_id(id),
                        m_chart_id(::ChartID()),
                        m_program_type((ENUM_PROGRAM_TYPE)::MQLInfoInteger(MQL_PROGRAM_TYPE)),
                        m_program_name(::MQLInfoString(MQL_PROGRAM_NAME)),
                        m_wnd(wnd==-1 ? GetSubWindow() : wnd),
                        m_chart_w((int)::ChartGetInteger(m_chart_id,CHART_WIDTH_IN_PIXELS,m_wnd)),
                        m_chart_h((int)::ChartGetInteger(m_chart_id,CHART_HEIGHT_IN_PIXELS,m_wnd)),
                        m_mouse_state(MOUSE_STATE_NOT_PRESSED),
                        m_x(x),
                        m_y(::ChartGetInteger(m_chart_id,CHART_SHOW_ONE_CLICK) ? (y<79 ? 79 : y) : y),
                        m_w(w),
                        m_h(h),
                        m_x_dock(m_x),
                        m_y_dock(m_y),
                        m_header(true),
                        m_butt_close(true),
                        m_butt_minimize(true),
                        m_butt_pin(true),
                        m_header_h(18),
                        
                        //--- Implementierung der Kopfzeile des Panels
                        m_header_alpha(255),
                        m_header_alpha_c(m_header_alpha),
                        m_header_back_color(clrBlack),
                        m_header_back_color_c(m_header_back_color),
                        m_header_fore_color(clrSnow),
                        m_header_fore_color_c(m_header_fore_color),
                        m_header_border_color(clrSnow),
                        m_header_border_color_c(m_header_border_color),
                        m_title("Dashboard"),
                        m_title_font("Calibri"),
                        m_title_font_size(-100),
                        
                        //--- Schaltfläche "Schließen
                        m_butt_close_back_color(clrBlack),
                        m_butt_close_back_color_c(m_butt_close_back_color),
                        m_butt_close_fore_color(clrSnow),
                        m_butt_close_fore_color_c(m_butt_close_fore_color),
                        
                        //--- Taste zum Zusammenklappen/Erweitern
                        m_butt_min_back_color(clrBlack),
                        m_butt_min_back_color_c(m_butt_min_back_color),
                        m_butt_min_fore_color(clrSnow),
                        m_butt_min_fore_color_c(m_butt_min_fore_color),
                        
                        //--- Pin-Taste
                        m_butt_pin_back_color(clrBlack),
                        m_butt_pin_back_color_c(m_butt_min_back_color),
                        m_butt_pin_fore_color(clrSnow),
                        m_butt_pin_fore_color_c(m_butt_min_fore_color),
                        
                        //--- Panel-Implementierung
                        m_alpha(255),
                        m_alpha_c(m_alpha),
                        m_fore_alpha(255),
                        m_fore_alpha_c(m_fore_alpha),
                        m_back_color(clrBlack),
                        m_back_color_c(m_back_color),
                        m_fore_color(clrSnow),
                        m_fore_color_c(m_fore_color),
                        m_border_color(clrSnow),
                        m_border_color_c(m_border_color),
                        m_font("Calibri"),
                        m_font_size(-100),
                        
                        m_minimized(false),
                        m_movable(true)
  {
//--- Legen Sie die Erlaubnis für das Diagramm fest, Nachrichten über Ereignisse beim Bewegen und Drücken von Maustasten zu senden,
//--- Maus-Scroll-Ereignisse sowie die Erstellung/Löschung von grafischen Objekten
   ::ChartSetInteger(this.m_chart_id,CHART_EVENT_MOUSE_MOVE,true);
   ::ChartSetInteger(this.m_chart_id,CHART_EVENT_MOUSE_WHEEL,true);
   ::ChartSetInteger(this.m_chart_id,CHART_EVENT_OBJECT_CREATE,true);
   ::ChartSetInteger(this.m_chart_id,CHART_EVENT_OBJECT_DELETE,true);
   
//--- Festlegen der Namen globaler Terminalvariablen zum Speichern von Feldkoordinaten, eingeklapptem/ausgeklapptem Zustand und Pinning
   this.m_name_gv_x=this.m_program_name+"_id_"+(string)this.m_id+"_"+(string)this.m_chart_id+"_X";
   this.m_name_gv_y=this.m_program_name+"_id_"+(string)this.m_id+"_"+(string)this.m_chart_id+"_Y";
   this.m_name_gv_m=this.m_program_name+"_id_"+(string)this.m_id+"_"+(string)this.m_chart_id+"_Minimize";
   this.m_name_gv_u=this.m_program_name+"_id_"+(string)this.m_id+"_"+(string)this.m_chart_id+"_Unpin";
   
//--- Wenn eine globale Variable nicht existiert, erstellen Sie sie und schreiben Sie den aktuellen Wert,
//--- andernfalls - den Wert aus der globalen Terminalvariable in diese einlesen
//--- X-Koordinate
   if(!::GlobalVariableCheck(this.m_name_gv_x))
      ::GlobalVariableSet(this.m_name_gv_x,this.m_x);
   else
      this.m_x=(int)::GlobalVariableGet(this.m_name_gv_x);
//--- Y-Koordinate
   if(!::GlobalVariableCheck(this.m_name_gv_y))
      ::GlobalVariableSet(this.m_name_gv_y,this.m_y);
   else
      this.m_y=(int)::GlobalVariableGet(this.m_name_gv_y);
//--- Zusammengeklappt/erweitert
   if(!::GlobalVariableCheck(this.m_name_gv_m))
      ::GlobalVariableSet(this.m_name_gv_m,this.m_minimized);
   else
      this.m_minimized=(int)::GlobalVariableGet(this.m_name_gv_m);
//--- Zusammengeklappt/nicht zusammengeklappt
   if(!::GlobalVariableCheck(this.m_name_gv_u))
      ::GlobalVariableSet(this.m_name_gv_u,this.m_movable);
   else
      this.m_movable=(int)::GlobalVariableGet(this.m_name_gv_u);

//--- Setzen Sie die Flags für die Größe des Panels, die die Größe des Diagrammfensters überschreitet
   this.m_higher_wnd=this.HigherWnd();
   this.m_wider_wnd=this.WiderWnd();

//--- Wenn die grafische Ressource des Panels erstellt wird,
   if(this.m_canvas.CreateBitmapLabel(this.m_chart_id,this.m_wnd,"P"+(string)this.m_id,this.m_x,this.m_y,this.m_w,this.m_h,COLOR_FORMAT_ARGB_NORMALIZE))
     {
      //--- die Schriftart der Leinwand festlegen und die Leinwand mit der transparenten Farbe füllen
      this.m_canvas.FontSet(this.m_title_font,this.m_title_font_size,FW_BOLD);
      this.m_canvas.Erase(0x00FFFFFF);
     }
//--- andernfalls - Bericht über die erfolglose Erstellung eines Objekts an das Journal
   else
      ::PrintFormat("%s: Error. CreateBitmapLabel for canvas failed",(string)__FUNCTION__);

//--- Wenn ein Arbeitsbereich für eine grafische Ressource erstellt wird,
   if(this.m_workspace.CreateBitmapLabel(this.m_chart_id,this.m_wnd,"W"+(string)this.m_id,this.m_x+1,this.m_y+this.m_header_h,this.m_w-2,this.m_h-this.m_header_h-1,COLOR_FORMAT_ARGB_NORMALIZE))
     {
      //--- die Schriftart für den Arbeitsbereich festlegen und ihn mit der transparenten Farbe füllen
      this.m_workspace.FontSet(this.m_font,this.m_font_size);
      this.m_workspace.Erase(0x00FFFFFF);
     }
//--- andernfalls - Bericht über die erfolglose Erstellung eines Objekts an das Journal
   else
      ::PrintFormat("%s: Error. CreateBitmapLabel for workspace failed",(string)__FUNCTION__);
  }
 
Artem hallo! Ich lerne, wie man ein Info-Panel zu erstellen, kann ich nicht verstehen, eine Sache! Da ich nicht gerade ein Profi in diesem..... Im Allgemeinen sehen, CDashboard * Dashboard = NULL; Wir haben eine Instanz der Klasse ... richtig? und dann weisen wir ihr NULL zu...? right? then in oninit, we assign the descriptor... dashboard = new CDashboard(InpUniqID, InpPanelX, InpPanelY, 500, 700); Why like this? and not like this CDashboard dashboard; Or does it work like this with objects? Mein Kopf ist ein Chaos! Wenn es Ihnen nichts ausmacht?... auf eine einfache Weise zu erklären ... danke!
 
Igor Bakhrushen NULL; Wir haben eine Instanz der Klasse ... richtig? und dann weisen wir ihr NULL zu...? right? then in oninit, we assign the descriptor... dashboard = new CDashboard(InpUniqID, InpPanelX, InpPanelY, 500, 700); Why like this? and not like this CDashboard dashboard; Or does it work like this with objects? Mein Kopf ist ein Chaos! Wenn es Ihnen nichts ausmacht?... auf eine einfache Weise zu erklären ... danke!

Hallo.

Auf diese Art und Weise.

CDashboard  *dashboard = NULL;

wird eine Zeigervariable auf ein zukünftiges neues, dynamisch erzeugtes, Objekt der Klasse deklariert und sofort mit dem Wert NULL initialisiert.


Und gerade eine Instanz der Klasse wird so deklariert:

CDashboard   dashboard;

Aber in diesem Fall kann man eine Instanz nicht auf diese Weise deklarieren und erzeugen - die Klasse hat keinen Konstruktor ohne formale Parameter.

Wenn Sie also eine Instanz auf diese Weise deklarieren, müssen Sie alle notwendigen Parameter des Klassenobjekts angeben, die an den Klassenkonstruktor übergeben werden müssen:

CDashboard   dashboard(InpUniqID, InpPanelX, InpPanelY, 200, 250);

------------------------

Im Beispiel für die Arbeit mit der Klasse wird zunächst ein leerer Zeiger auf das zukünftige Objekt im Indikator erstellt, und dann wird in OnInit() ein Panel-Objekt erstellt, wobei der Zeiger auf das erstellte Objekt in die Zeigervariable geschrieben wird:

//--- Panel-Objekt erstellen
   dashboard=new CDashboard(InpUniqID,InpPanelX,InpPanelY,200,250);
   if(dashboard==NULL)
     {
      Print("Error. Failed to create dashboard object");
      return INIT_FAILED;
     }


In OnDeinit() wird das Objekt dann unter Verwendung dieses Zeigers im Speicher gelöscht:

//--- Wenn das Panel-Objekt existiert - löschen Sie es
   if(dashboard!=NULL)
      delete dashboard;

Wenn wir einfach ein neues Objekt mit dem new-Operator erstellen würden, ohne den Zeiger auf das erstellte Objekt in eine Variable zu schreiben, könnten wir es anschließend nicht löschen, was zu einem Speicherleck führen würde.

Kurz gesagt, in dem Beispiel aus dem Artikel

  1. Deklarieren Sie einen Variablen-Zeiger auf das zukünftige Klassenobjekt und initialisieren Sie ihn mit dem Wert NULL,
  2. ein neues Klassenobjekt erstellen und den Zeiger auf dieses Objekt in die zuvor erstellte Dashboard-Variable schreiben,
  3. beim Zugriff auf das erstellte Objekt verwenden wir die Zeigervariable und einen Punkt ( dashboard.AnyMethod() )
  4. am Ende der Arbeit löschen wir das dynamisch erstellte Klassenobjekt mit dem Zeiger darauf.

Wäre die benötigte Instanz der Klasse (CDashboard Dashboard) sofort erstellt worden, wären keine Zeiger darauf nötig gewesen - man hätte auf die gleiche Weise mit dem Operator "point" darauf zugreifen können. Und es wäre auch nicht nötig, sie zu löschen, wenn die Arbeit beendet ist - das Terminal-Subsystem macht das von selbst. Aber es wäre die einzige Instanz der Klasse im Programm.

Mit der dynamischen Erstellung können Sie neue Objekte der gewünschten Klasse im Handumdrehen erstellen und per Zeiger auf sie verweisen. Deshalb wurde im Beispiel die dynamische Erstellung eines Klassenobjekts verwendet. Vereinfacht, ohne auf einige Punkte einzugehen.