Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 189

 
Nikolai Semko:

Sie müssen die Methode Timer4 (blau unterlegt) der Klasse CTestTimer ausführen

Ich bin nicht dazu gekommen.

#property indicator_chart_window
#include <Timer.mqh> // https://www.mql5.com/ru/code/31306

//+------------------------------------------------------------------+
class CTestTimer {
 private:
   //typedef void (CTestTimer::*TFunc2)(); // так работает в C++, но здесь не работает
 public:
   static int x4;
   CTestTimer() {
      //TFunc2 p=CTestTimer::Timer4;
      //TFunc2 p=Timer4;
      //timers.NewTimer(700,p);
      timers.NewTimer(700,Method2Function); // ошибка 'Timer4' - pointer to this function type is not supported yet
   };
   ~CTestTimer(){};
   static void Timer4() {
      x4++;
      if (x4==7) timers.KillTimer(Method2Function); // удаляем этот таймер
   }
};
//+------------------------------------------------------------------+

static int CTestTimer::x4 = 0;

void Method2Function()
{
  CTestTimer::Timer4();
}
 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Eigenheiten von mql5, Tipps und Tricks

fxsaber, 2020.05.14 02:57

Ich habe es wieder. Ich gehe davon aus, dass dies in seltenen Fällen beim erneuten Aufzeichnen auftreten kann.

Die Lösung besteht darin, es nach einer kurzen Pause erneut zu versuchen, wenn es falsch ist.

bool IsTradeAllowed( const int Attempts = 0 )
{        
  // https://www.mql5.com/ru/forum/170952/page174#comment_16363677
  bool Res = false;
  int Count = 0;
  
  // https://www.mql5.com/ru/forum/170952/page174#comment_16363677
  while (!(Res = ::MQLInfoInteger(MQL_TRADE_ALLOWED) &&
                 ::AccountInfoInteger(ACCOUNT_TRADE_EXPERT) &&
                 ::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) &&
                 ::TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) &&
         (Count++ < Attempts) && !::IsStopped())
    ::Sleep(100);
    
  return(Res);
}

Dies ist eine schlechte Lösung. Hier ist eine viel bessere Lösung.

const bool Init = EventSetMillisecondTimer(1);

bool Allowed()
{
  return(::MQLInfoInteger(MQL_TRADE_ALLOWED) &&
         ::AccountInfoInteger(ACCOUNT_TRADE_EXPERT) &&
         (::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) || !::TerminalInfoInteger(TERMINAL_CONNECTED)) &&
         ::TerminalInfoInteger(TERMINAL_TRADE_ALLOWED));
}

void OnTimer()
{
  if (!Allowed())
    ExpertRemove();
}

Wenn Sie eine manuelle Neuanmeldung vornehmen, funktioniert dieser EA trotzdem. Ohne die hervorgehobene Zeichenfolge löscht sie sich selbst.

 
fxsaber:

Ich bin nicht dazu gekommen.

Vielen Dank für Ihre Zeit. Aber ich habe oben geschrieben, dass die Methode nicht statisch sein sollte. Es ist klar, dass dies mit statischen Methoden möglich ist. Eine statische Methode ist überhaupt kein OOP.
Offensichtlich wollte ich zu viel, oder besser gesagt unmöglich.
Die Tatsache, dass dies in C++ möglich ist, hat mich verwirrt, aber bei näherer Betrachtung habe ich verstanden, dass ein solcher Zeiger eine völlig andere Struktur hat,

https://habr.com/ru/post/333334/


Und das ist verständlich.

Eine nicht-statische Klassenmethode hat eine einzige Implementierung, die irgendwo im Speicher liegt und alle Objekte der Klasse betrifft.
Aber jedes Objekt hat seinen eigenen, einzigartigen aktuellen Zustand der internen Variablen, so dass ein solcher Zeiger auf eine nicht-statische Methode auch eine ausgefüllte Parameterstruktur des Objekts haben muss, auf das er gerade angewendet wird.
Ich entschuldige mich bei allen für die verschwendete Zeit.
Wir müssen nach anderen Wegen suchen, um Objekte verschiedener Klassen allgemein zu kontrollieren.

Der Beweis, dass es keine Lösung gibt, ist auch eine Lösung.

 
Nikolai Semko:

Vielen Dank für Ihre Zeit. Aber ich habe oben geschrieben, dass die Methode nicht statisch sein sollte. Es ist klar, dass dies mit Statik möglich ist.

Oben wurden Ihnen zwei Beispiele genannt, eines davon mit vollständiger Umsetzung
 
TheXpert:
Oben wurden Ihnen zwei Beispiele genannt, eines davon mit vollständiger Umsetzung

Sie scheinen mein Problem nicht verstanden zu haben.
Es gibt keine Lösung.

 
Nikolai Semko:

Sie scheinen mein Problem nicht verstanden zu haben.
Es gibt keine Lösung.

Warum mit dem Kopf gegen die Wand schlagen, wenn es daneben eine Tür gibt? Das Multitimer-Problem mit einem Handler-Aufruf an eine externe Klasse wurde gelöst.

Dieser Mann hier hat eine Lösung für Ihr Problem, wie Sie es sehen, allerdings nicht öffentlich.

 
TheXpert:
Warum mit dem Kopf gegen die Wand schlagen, wenn eine Tür daneben ist? Die Multitimer-Aufgabe mit einem Handler-Aufruf an eine externe Klasse ist gelöst.

Es ging nicht um den Timer.
Ich habe nur geträumt und war dumm.

 
Nikolai Semko:

Ich habe nur geträumt und war verblüfft.

Ich bin für ein vollwertiges typedef oder die gleichen Bindungen in mql, aber das war's auch schon.

 

Ist es möglich, ein manuell erstelltes grafisches Objekt von einem Objekt zu unterscheiden, das von einem Indikator oder EA erstellt wurde?

In der Funktion

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
  {
   if(id == CHARTEVENT_OBJECT_CREATE)
     {

     }
  }
 
Vladimir Pastushak:

Ist es möglich, ein manuell erstelltes grafisches Objekt von einem Objekt zu unterscheiden, das von einem Indikator oder EA erstellt wurde?

In der Funktion

Sie können es mit der linken Maustaste steuern.
Zum Beispiel so:

#property indicator_chart_window
#include <Timer.mqh> //https://www.mql5.com/ru/code/31306

uint t_LMB=0;
int OnInit() {
   ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,0,true);
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,const int begin,const double &price[]) {
   return(rates_total);
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) {
   static string str=sparam;
   if(str!="1" && sparam=="1") t_LMB=GetTickCount(); // нажате левая кнопка мышки
   if(id == CHARTEVENT_OBJECT_CREATE) {
      CheckManual(GetTickCount());
   }
   str=sparam;
}
//+------------------------------------------------------------------+
void CheckManual(uint start=0) {
   static uint s=0;
   if (start>0) {
      s=start;
      timers.NewTimer(20,Timer1); // Создаем таймер на 20 милисекунд и функцией-обработчиком Timer1()
      return;
   }
   int pause = int(t_LMB-s);
   if (pause>=0 && pause<20) Print("Создан графический объект в ручную");
   else Print ("Создан графический объект программно");
   timers.KillTimer(Timer1); // удаляем таймер Timer1
}
//+------------------------------------------------------------------+
void Timer1() {CheckManual();}