Caractéristiques du langage mql5, subtilités et techniques - page 189

 
Nikolai Semko:

Vous devez exécuter la méthode Timer4 (surlignée en bleu) de la classe CTestTimer.

Je ne l'ai pas fait.

#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 sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Particularités de mql5, trucs et astuces

fxsaber, 2020.05.14 02:57

Je l'ai encore eu. Je suppose que cela peut se produire dans de rares situations lors de la reconnexion.

La solution est, si elle est fausse, de réessayer après une courte pause.

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

C'est une mauvaise solution. Voici une bien meilleure solution.

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

Si vous vous reconnectez manuellement, l'EA fonctionnera toujours. Sans la chaîne en surbrillance, il s'autodétruira.

 
fxsaber:

Je ne l'ai pas fait.

Merci pour votre temps. Mais j'ai écrit plus haut que la méthode devait être non statique. Il est clair que cela est possible avec les méthodes statiques. Une méthode statique n'est pas du tout OOP.
De toute évidence, je voulais trop, ou plutôt impossible.
J'étais confus par le fait qu'il était possible de le faire en C++, mais en l'examinant, j'ai compris qu'un tel pointeur a une structure totalement différente,

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


Et c'est compréhensible.

Une méthode de classe non statique a une implémentation unique, qui se trouve quelque part dans la mémoire et affecte tous les objets de la classe.
Mais chaque objet a son propre état actuel unique des variables internes, donc un tel pointeur vers une méthode non statique doit également avoir une structure de paramètres remplie de l'objet auquel il est appliqué à ce moment.
Toutes nos excuses pour la perte de temps.
Nous devons chercher d'autres moyens de contrôler de manière générale des objets de classes différentes.

La preuve qu'il n'y a pas de solution est aussi une solution.

 
Nikolai Semko:

Merci pour votre temps. Mais j'ai écrit plus haut que la méthode devait être non statique. Il est clair que cela est possible avec la statique.

On vous a donné deux exemples ci-dessus. L'un avec une mise en œuvre complète.
 
TheXpert:
On vous a donné deux exemples ci-dessus. L'un avec une mise en œuvre complète.

Vous ne semblez pas avoir compris mon problème.
Elle n'a pas de solution.

 
Nikolai Semko:

Vous ne semblez pas avoir compris mon problème.
Elle n'a pas de solution.

Pourquoi se frapper la tête contre le mur alors qu'il y a une porte à côté ? Le problème du multitimer avec un appel de handler à une classe externe a été résolu.

Cet homme a une solution à votre problème tel que vous le voyez, mais elle n'est pas publique.

 
TheXpert:
Pourquoi se frapper la tête contre le mur alors qu'il y a une porte à côté ? La tâche du multitimer avec un appel du handler à une classe externe a été résolue.

Ce n'était pas à propos du minuteur.
J'étais juste en train de rêvasser et d'être stupide.

 
Nikolai Semko:

Je rêvassais et j'étais abasourdi.

Je suis d'accord pour un typage complet ou les mêmes liens dans mql, mais c'est à peu près tout.

 

Est-il possible de distinguer un objet graphique créé manuellement d'un objet créé par un indicateur ou un EA ?

Dans la fonction

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

     }
  }
 
Vladimir Pastushak:

Est-il possible de distinguer un objet graphique créé manuellement d'un objet créé par un indicateur ou un EA ?

Dans la fonction

Vous pouvez le faire avec le contrôle du bouton gauche de la souris.
Par exemple, comme ceci :

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