Hört sich toll an, Peter, ich denke, wenn Sie die VE verwenden, um sich selbst zu bauen, wird sie Ihnen definitiv einige wertvolle Einblicke geben, wie Ihr UI-Design funktioniert. Ich freue mich auf das nächste Entwicklungsupdate.
Douglas Prager #: Das klingt großartig, Peter. Ich denke, wenn Sie VE verwenden, um selbst zu bauen, wird es Ihnen wertvolle Einblicke geben, wie Ihr UI-Design funktioniert. Ich freue mich schon auf das nächste Entwicklungsupdate.
Vielen Dank, Douglas. Sie haben Recht, das ist genau richtig. Es gibt einen minimalen technischen "Schwellenwert" zu überwinden.
Ich werde auch Ihre grundlegende Entwicklung mit Interesse verfolgen.
Doerk Hilger #: UI ist immer noch 100% reines MQL. Alles vektorbasiert, voll skalierbar und an jedes Display anpassbar. Alle visuellen Anzeigen arbeiten asychron innerhalb einer Kernklasse, die alle MQL-Ereignisse behandelt und an Objekte verteilt, abhängig von ihren Abonnementeinstellungen und basierend auf Ereignisprioritäten.
Ich hoffe, ich stehle nicht den sehr interessanten Thread und verzeihen Sie mir, Peter, wenn ich es tue, es wird keine Diskussion sein, ich hoffe nur auf eine kurze Antwort für das theorethische Interesse - meinen Sie, Sie haben eine Art statische Klasse, die alle im System instanziierten Klassenobjekte kennt (behält alle Objektzeiger im Auge) und jedes Objekt hat Zugang, um sich für erforderliche Ereignisse auf dieser statischen Steuerklasse zu abonnieren, und diese statische Steuersingletonklasse liefert einfach die Ereignisse an alle Objekte? Wenn ja, sehen Sie das als korrekt im Sinne von OOP an oder ist es vielleicht akzeptable ereignisgesteuerte Programmierung? Da Sie darüber geschrieben haben, nehme ich an, dass Sie Fragen dazu annehmen möchten, und wenn ja, lassen Sie sie uns bitte so kurz wie möglich halten, um diesen Thread nicht zu entführen, obwohl er damit zusammenhängt.
Ich hoffe, ich stehle nicht den sehr interessanten Thread und verzeihen Sie mir, Peter, wenn ich das tue, es wird keine Diskussion sein, sondern ich hoffe auf eine kurze Antwort für das theorethische Interesse - meinen Sie, dass Sie eine Art statische Klasse haben, die alle im System instanziierten Klassenobjekte kennt (behält den Überblick über alle Objektzeiger), und jedes Objekt hat Zugang, um sich für erforderliche Ereignisse auf dieser statischen Steuerklasse zu abonnieren, und diese statische Steuersingletonklasse liefert die Ereignisse einfach an alle Objekte? Wenn ja, sehen Sie das als korrekt im Sinne von OOP an oder ist es vielleicht akzeptable ereignisgesteuerte Programmierung? Da Sie darüber geschrieben haben, nehme ich an, dass Sie Fragen dazu annehmen möchten, und wenn ja, lassen Sie sie uns bitte so kurz wie möglich halten, um diesen Thread nicht zu entführen, obwohl er damit zusammenhängt.
Ja, genau das ist es. Kurzbeschreibung:
Der Kern empfängt alle MetaTrader-Ereignisse und jedes Objekt kann den Kern abonnieren. Daher musste auch die CObject-Klasse neu entworfen/geändert werden, so dass jedes Objekt eine Funktion namens "public: virtual void OnEACycle(CCycleParams * cpm)" hat. Ein solcher Zyklus könnte dann ein Chart-Ereignis, init, deinit usw. sein. Jedes Objekt kann auch ein "public: virtual void OnEATick()" haben. Netter Nebeneffekt ist, dass man auf diese Weise ein zusätzliches Feature erhält, denn man kann sich auch für das Ende eines Zyklus anmelden, egal welcher es ist. Ziemlich nützlich, um eine Datei zu schließen oder irgendetwas anderes zu beenden, einfach am Ende eines Zyklus.
Außerdem kann jedes CObject-Objekt Childs und auch Subscribers haben. Das heißt, ein Objekt kann seine eigenen Ereignisse auslösen, z.B. wenn etwas angeklickt wurde oder ähnliches. Dann führt man einfach ein object.SubEvent(STH_CLICKED, params) aus. Auf diese Weise kümmert sich das Objekt selbst nicht darum, wer diese Informationen benötigt, sie werden einfach an die Abonnenten verteilt, die ein OnSubEvent(int msg, CSubEventParams * sep) erhalten und damit machen können, was sie wollen.
Alles in allem ist diese Art der Programmierung mehr an die Art der Programmierung angelehnt, die wir aus C# kennen, wo man auch einfach .Invoke() verwendet, um Ereignisse auszulösen und sich nicht darum kümmert, wer sie bekommt.
Es ist eigentlich nicht so super-kompliziert zu implementieren, aber natürlich sind die Details am Ende die Herausforderung, da es ein Kern/Basis für jeden einzelnen EA oder Indikator für die Zukunft ist, der in jedem Szenario funktionieren muss.
Natürlich sind Load/Unload/Activate usw. benutzerdefiniert, aber da Sie diesen Event-Kern haben, haben Sie viel mehr Flexibilität als ohne und viel mehr Kontrolle über absolut alles. Wenn ich die Zeit hätte, würde ich einen Artikel schreiben und die Quellen angeben. Es ist kein Geheimnis, überhaupt keine Magie.
Ich habe mir die von Ihnen erstellte GUI angesehen. Sie gefällt mir sehr gut. Sagen Sie mir, haben Sie es selbst geschrieben oder haben Sie einige MQL-Bibliotheken verwendet?
Реter Konow #: Ich habe mir die von Ihnen erstellte GUI angesehen. Sie gefällt mir sehr gut. Sagen Sie mir, haben Sie es selbst geschrieben oder haben Sie einige MQL-Bibliotheken verwendet?
Ja, danke. Nein, keine Bibliotheken. Ich habe es von Grund auf selbst entwickelt. Eigentlich ist nur CCanvas von den ursprünglichen angepasst, nichts anderes.
Ich danke Ihnen. Nein, keine Bibliotheken. Ich habe es von Grund auf selbst entwickelt. Eigentlich ist nur CCanvas von den ursprünglichen angepasst, nichts anderes.
Es ist nicht einfach, so etwas zu entwickeln. )
Soweit ich weiß, gibt es in der Standard-CCanvas-Klasse keine Funktion zum Zeichnen eines Farbverlaufs, wie haben Sie das Problem mit dem Farbverlauf in Ihrer GUI gelöst?
Реter Konow #: Es ist nicht einfach, so etwas zu machen. )
Soweit ich weiß, gibt es in der Standard-Canvas-Klasse keine Funktion zum Zeichnen eines Farbverlaufs. Wie haben Sie das Problem mit einem Farbverlauf in Ihrer GUI gelöst?
Du meinst die Lichteffekte? Naja, Licht hinzugefügt :D Wie beschrieben, ist CCanvas auch nur in seinen Grundlagen und seiner Struktur angepasst, nicht in seinen Details.
//+------------------------------------------------------------------+
//| Macro to generate color |
//+------------------------------------------------------------------+
#define XRGB(r,g,b) (0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b))
#define ARGB(a,r,g,b) ((uchar(a)<<24)|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b))
#define TRGB(a,rgb) ((uchar(a)<<24)|(rgb))
#define GETRGB(clr) ((clr)&0xFFFFFF)
#define GETRGBA(clr) uchar((clr)>>24)
#define GETRGBR(clr) uchar((clr)>>16)
#define GETRGBG(clr) uchar((clr)>>8)
#define GETRGBB(clr) uchar(clr)
#define COLOR2RGB(clr) (0xFF000000|(uchar(clr)<<16)|(uchar((clr)>>8)<<8)|uchar((clr)>>16))
#define RGB2COLOR(rgb) ((uchar(rgb)<<16)|(uchar((rgb)>>8)<<8)|uchar((rgb)>>16))
//+------------------------------------------------------------------+//| Add light to rectangular area |//+------------------------------------------------------------------+void CCanvasExt::AddLight(int x1, int y1, int x2, int y2, bool updown=true, double intensity=.5, int isoftedge=20, color lightcolor=C'255,255,255')
{
if (intensity==0)
return;
int tmp;
//--- sort vertexesif(x2<x1)
{
tmp=x1;
x1 =x2;
x2 =tmp;
}
if(y2<y1)
{
tmp=y1;
y1 =y2;
y2 =tmp;
}
//--- out of screen boundariesif(x2<0 || y2<0 || x1>=m_width || y1>=m_height)
return;
//--- stay withing screen boundariesif(x1<0)
x1=0;
if(y1<0)
y1=0;
if(x2>=m_width)
x2=m_width -1;
if(y2>=m_height)
y2=m_height-1;
//--- calculate softedge
isoftedge=MIN(100,isoftedge);
int softedge=isoftedge>0 ? isoftedge*(y2-y1)/100 : 0;
//--- correct height
y2-=(y2-y1)/2;
y2+=(softedge/2);
y2++;
y2=MIN(m_height-1,y2);
//--- prepare
COLOR_RGBA rgb=_ColorLumaMult(lightcolor,ABS(intensity));
double r=(int)GETRGBR(rgb);
double g=(int)GETRGBG(rgb);
double b=(int)GETRGBB(rgb);
if (intensity<0)
{
r=0-r;
g=0-g;
b=0-b;
}
uint pixel;
int istart;
int iend;
int i;
//--- check directionif (updown)
{
//--- add main light for(;y1<y2-softedge;y1++)
{
istart=y1*m_width+x1;
iend=istart+(x2-x1);
for (i=istart;i<=iend;i++)
{
pixel=m_pixels[i];
m_pixels[i]=ARGB(GETRGBA(pixel),MIN(GETRGBR(pixel)+r,0xFF),MIN(GETRGBG(pixel)+g,0xFF),MIN(GETRGBB(pixel)+b,0xFF));// m_pixels[i]+=XRGB(r,g,b);//m_pixels[i]|=rgb;
}
}
if (softedge==0)
return;
//-- Add soft edge double decr=r/softedge;
double decg=g/softedge;
double decb=b/softedge;
//--- Loop rows separate and adjust color each row for (;y1<=y2;y1++)
{
r-=decr; r=MAX(0,r);
g-=decg; g=MAX(0,g);
b-=decb; b=MAX(0,b);
istart=y1*m_width+x1;
iend=istart+(x2-x1);
for (i=istart;i<=iend;i++)
{
pixel=m_pixels[i];
m_pixels[i]=ARGB(GETRGBA(pixel),MIN(GETRGBR(pixel)+r,0xFF),MIN(GETRGBG(pixel)+g,0xFF),MIN(GETRGBB(pixel)+b,0xFF));// m_pixels[i]+=XRGB(r,g,b);
}
}
}
}
Ich freue mich auf das nächste Entwicklungsupdate.
Das klingt großartig, Peter. Ich denke, wenn Sie VE verwenden, um selbst zu bauen, wird es Ihnen wertvolle Einblicke geben, wie Ihr UI-Design funktioniert.
Ich freue mich schon auf das nächste Entwicklungsupdate.
UI ist immer noch 100% reines MQL.
Alles vektorbasiert, voll skalierbar und an jedes Display anpassbar.
Alle visuellen Anzeigen arbeiten asychron innerhalb einer Kernklasse, die alle MQL-Ereignisse behandelt und an Objekte verteilt, abhängig von ihren Abonnementeinstellungen und basierend auf Ereignisprioritäten.
Ich hoffe, ich stehle nicht den sehr interessanten Thread und verzeihen Sie mir, Peter, wenn ich es tue, es wird keine Diskussion sein, ich hoffe nur auf eine kurze Antwort für das theorethische Interesse - meinen Sie, Sie haben eine Art statische Klasse, die alle im System instanziierten Klassenobjekte kennt (behält alle Objektzeiger im Auge) und jedes Objekt hat Zugang, um sich für erforderliche Ereignisse auf dieser statischen Steuerklasse zu abonnieren, und diese statische Steuersingletonklasse liefert einfach die Ereignisse an alle Objekte? Wenn ja, sehen Sie das als korrekt im Sinne von OOP an oder ist es vielleicht akzeptable ereignisgesteuerte Programmierung? Da Sie darüber geschrieben haben, nehme ich an, dass Sie Fragen dazu annehmen möchten, und wenn ja, lassen Sie sie uns bitte so kurz wie möglich halten, um diesen Thread nicht zu entführen, obwohl er damit zusammenhängt.
Ich hoffe, ich stehle nicht den sehr interessanten Thread und verzeihen Sie mir, Peter, wenn ich das tue, es wird keine Diskussion sein, sondern ich hoffe auf eine kurze Antwort für das theorethische Interesse - meinen Sie, dass Sie eine Art statische Klasse haben, die alle im System instanziierten Klassenobjekte kennt (behält den Überblick über alle Objektzeiger), und jedes Objekt hat Zugang, um sich für erforderliche Ereignisse auf dieser statischen Steuerklasse zu abonnieren, und diese statische Steuersingletonklasse liefert die Ereignisse einfach an alle Objekte? Wenn ja, sehen Sie das als korrekt im Sinne von OOP an oder ist es vielleicht akzeptable ereignisgesteuerte Programmierung? Da Sie darüber geschrieben haben, nehme ich an, dass Sie Fragen dazu annehmen möchten, und wenn ja, lassen Sie sie uns bitte so kurz wie möglich halten, um diesen Thread nicht zu entführen, obwohl er damit zusammenhängt.
Ja, genau das ist es.
Kurzbeschreibung:
Der Kern empfängt alle MetaTrader-Ereignisse und jedes Objekt kann den Kern abonnieren. Daher musste auch die CObject-Klasse neu entworfen/geändert werden, so dass jedes Objekt eine Funktion namens "public: virtual void OnEACycle(CCycleParams * cpm)" hat. Ein solcher Zyklus könnte dann ein Chart-Ereignis, init, deinit usw. sein. Jedes Objekt kann auch ein "public: virtual void OnEATick()" haben. Netter Nebeneffekt ist, dass man auf diese Weise ein zusätzliches Feature erhält, denn man kann sich auch für das Ende eines Zyklus anmelden, egal welcher es ist. Ziemlich nützlich, um eine Datei zu schließen oder irgendetwas anderes zu beenden, einfach am Ende eines Zyklus.
Außerdem kann jedes CObject-Objekt Childs und auch Subscribers haben. Das heißt, ein Objekt kann seine eigenen Ereignisse auslösen, z.B. wenn etwas angeklickt wurde oder ähnliches. Dann führt man einfach ein object.SubEvent(STH_CLICKED, params) aus. Auf diese Weise kümmert sich das Objekt selbst nicht darum, wer diese Informationen benötigt, sie werden einfach an die Abonnenten verteilt, die ein OnSubEvent(int msg, CSubEventParams * sep) erhalten und damit machen können, was sie wollen.
Alles in allem ist diese Art der Programmierung mehr an die Art der Programmierung angelehnt, die wir aus C# kennen, wo man auch einfach .Invoke() verwendet, um Ereignisse auszulösen und sich nicht darum kümmert, wer sie bekommt.
Es ist eigentlich nicht so super-kompliziert zu implementieren, aber natürlich sind die Details am Ende die Herausforderung, da es ein Kern/Basis für jeden einzelnen EA oder Indikator für die Zukunft ist, der in jedem Szenario funktionieren muss.
Und ein fertiger EA sieht dann so aus:
Wenn ich die Zeit hätte, würde ich einen Artikel schreiben und die Quellen angeben. Es ist kein Geheimnis, überhaupt keine Magie.
Ich habe mir die von Ihnen erstellte GUI angesehen. Sie gefällt mir sehr gut. Sagen Sie mir, haben Sie es selbst geschrieben oder haben Sie einige MQL-Bibliotheken verwendet?
Ja, danke.
Nein, keine Bibliotheken. Ich habe es von Grund auf selbst entwickelt. Eigentlich ist nur CCanvas von den ursprünglichen angepasst, nichts anderes.
Ich danke Ihnen.
Nein, keine Bibliotheken. Ich habe es von Grund auf selbst entwickelt. Eigentlich ist nur CCanvas von den ursprünglichen angepasst, nichts anderes.
Es ist nicht einfach, so etwas zu machen. )
Du meinst die Lichteffekte? Naja, Licht hinzugefügt :D Wie beschrieben, ist CCanvas auch nur in seinen Grundlagen und seiner Struktur angepasst, nicht in seinen Details.