Características del lenguaje mql5, sutilezas y técnicas - página 189

 
Nikolai Semko:

Es necesario ejecutar el método Timer4 (resaltado en azul) de la clase CTestTimer

No se ha metido en ello.

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

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

Peculiaridades de mql5, consejos y trucos

fxsaber, 2020.05.14 02:57

Lo tengo de nuevo. Supongo que esto puede ocurrir en situaciones raras cuando se vuelve a registrar.

La solución es, si es falso, volver a intentarlo tras una breve pausa.

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

Esta es una mala solución. Aquí hay una solución mucho mejor.

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 haces un reinicio de sesión manual, este EA seguirá funcionando. Sin la cadena resaltada, se autoborrará.

 
fxsaber:

No se ha metido en ello.

Gracias por su tiempo. Pero he escrito más arriba que el método debe ser no estático. Está claro que esto es posible con los métodos estáticos. Un método estático no es un OOP en absoluto.
Obviamente quería demasiado, o más bien imposible.
Estaba confundido por el hecho de que es posible hacer esto en C++, pero al examinarlo, entendí que tal puntero tiene una estructura bastante diferente,

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


Y es comprensible.

Un método de clase no estático tiene una única implementación, que se encuentra en algún lugar de la memoria y afecta a todos los objetos de la clase.
Pero cada objeto tiene su propio y único estado actual de las variables internas, por lo que un puntero a un método no estático debe tener también una estructura de parámetros de objeto rellena, a la que el método se aplica en ese momento.
Disculpas a todos por perder el tiempo.
Tenemos que buscar otras formas de controlar en general objetos de diferentes clases.

La prueba de que no hay solución también es una solución.

 
Nikolai Semko:

Gracias por su tiempo. Pero he escrito más arriba que el método debe ser no estático. Está claro que esto es posible con la estática.

Se le han dado dos ejemplos arriba. uno con aplicación completa
 
TheXpert:
Se le han dado dos ejemplos arriba. uno con aplicación completa

Parece que no has entendido mi problema.
No tiene solución.

 
Nikolai Semko:

Parece que no has entendido mi problema.
No tiene solución.

¿Por qué golpearse la cabeza contra la pared cuando hay una puerta al lado? El problema de la multiplicidad de tiempos con una llamada a una clase externa ha sido resuelto.

Este compañero de aquí tiene una solución a tu problema como ves, aunque no pública.

 
TheXpert:
¿Por qué golpearse la cabeza contra la pared cuando hay una puerta al lado? La tarea del multitemporizador con una llamada a una clase externa ha sido resuelta.

No era por el temporizador.
Estaba soñando despierto y estúpido.

 
Nikolai Semko:

Estaba soñando despierto y aturdido.

Estoy a favor de un typedef completo o de los mismos binds en mql, pero eso es todo.

 

¿Es posible distinguir un objeto gráfico creado manualmente de un objeto creado por un indicador o EA?

En la función

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

     }
  }
 
Vladimir Pastushak:

¿Es posible distinguir un objeto gráfico creado manualmente de un objeto creado por un indicador o EA?

En la función

Puedes hacerlo con el control del botón izquierdo del ratón.
Por ejemplo, así:

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