Features of the mql5 language, subtleties and tricks - page 189

 
Nikolai Semko:

You need to run Timer4 method (highlighted in blue) of CTestTimer class

Didn't get into it.

#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 on trading, automated trading systems and trading strategies testing

Peculiarities of mql5, tips and tricks

fxsaber, 2020.05.14 02:57

I got it again. I assume that this may occur in rare situations when re-logging.

The solution is, if false, to retry after a short 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);
}

This is a bad solution. Here is a much better 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();
}

If you do a manual re-login, this EA will still work. Without the highlighted string, it will self-delete.

 
fxsaber:

Didn't get into it.

Thanks for your time. But I wrote above that the method should be non-static. It's clear that this is possible with static methods. A static method is not OOP at all.
Obviously I wanted too much, or rather impossible.
I was confused by the fact that it was possible to do so in C++, but on examining it, I understood that such a pointer has a totally different structure,

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


And it's understandable.

A non-static class method has a single implementation, which sits somewhere in memory and affects all objects of the class.
But every object has its own unique current state of internal variables, so such a pointer to a non-static method must also have a filled in parameter structure of the object it's applied to at the moment.
Apologies to all for wasting time.
We need to look for other ways to generally control objects of different classes.

Proof of no solution is also a solution.

 
Nikolai Semko:

Thanks for your time. But I wrote above that the method should be non-static. It's clear that this is possible with static.

You were given two examples above. one with full implementation
 
TheXpert:
You were given two examples above. one with full implementation

You don't seem to have understood my problem.
It has no solution.

 
Nikolai Semko:

You don't seem to have understood my problem.
It has no solution.

Why bang your head against the wall when there's a door next to it? The multitimer problem with a handler call to an external class has been solved.

This fellow here has a solution to your problem as you see it, non-public though.

 
TheXpert:
Why bang your head against the wall when there's a door next to it? The multitimer task with a handler call to an external class has been solved.

It wasn't about the timer.
I was just daydreaming and stupid.

 
Nikolai Semko:

I was just daydreaming and dumbfounded.

I'm all for a full-fledged typedef or the same binds in mql, but that's about it.

 

Is it possible to distinguish a manually created graphical object from an object created by an indicator or EA?

In the function

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

     }
  }
 
Vladimir Pastushak:

Is it possible to distinguish a manually created graphical object from an object created by an indicator or EA?

In the function

You can do it with the left mouse button control.
For example like this:

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