Особенности языка mql5, тонкости и приёмы работы - страница 189

 
Nikolai Semko:

Нужно чтобы запускался метод Timer4 (выделен синим цветом) класса CTestTimer

Не вникал.

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

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2020.05.14 02:57

Повторно нарвался. Предполагаю, что при релогине в редких ситуациях такое может проявляться.

Решение - если false, повторить попытку после небольшой паузы.

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

Это плохое решение. Вот гораздо лучше.

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

Если сделать ручной релогин, то этот советник останется работать. Без выделенной строки - самоудалится.

 
fxsaber:

Не вникал.

Спасибо за потраченное время. Но писал выше, что метод должен быть нестатический. Понятно что со статикой такое возможно. Статический метод это вообще не ООП.
Очевидно, что я захотел слишком многого, точнее невозможного.
Меня смутил факт, что в С++ такое делать возможно, но разобравшись, понял что такой указатель миеет совсем другую структуру,

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


И это понятно. 

Ведь у нестатического метода класса реализация то сидит где-то в памяти и он один на все объекты класса. 
Но ведь кажый объект обладает своим уникальным текущим состояние внутренних переменных, поэтому такой указатель на нестатический метод должен еще иметь еще заполненную структуру параметров объекта, к которому этот метод применяется в данный момент.
Прошу прощения всех за потраченное время. 
Нужно искать другие способы общего контроля объектов различных классов.

Доказательство отсутствия решения - тоже решение.

 
Nikolai Semko:

Спасибо за потраченное время. Но писал выше, что метод должен быть нестатический. Понятно что со статикой такое возможно.

вам же выше два примера привели. один с полной реализацией
 
TheXpert:
вам же выше два примера привели. один с полной реализацией

Вы, похоже, не поняли моей задачи.
Она не имеет решения.

 
Nikolai Semko:

Вы, похоже, не поняли моей задачи.
Она не имеет решения.

зачем биться головой об стену если рядом дверь? задача мультитаймера с вызовом обработчика у внешнего класса решена.

вот у этого товарища есть решение вашей задачи как вы ее видите, непубличное правда.

 
TheXpert:
зачем биться головой об стену если рядом дверь? задача мультитаймера с вызовом обработчика у внешнего класса решена.

Речь уже была не про таймер. 
Я просто размечтался и тупанул.

 
Nikolai Semko:

Я просто размечтался и тупанул.

я только за если в mql будет полноценный  typedef или те же bind'ы, но что имеем.

 

Возможно ли отличить как то графический обьект созданный в ручную от обьекта который создан индикатором или советником ?

В функции 

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

     }
  }
 
Vladimir Pastushak:

Возможно ли отличить как то графический обьект созданный в ручную от обьекта который создан индикатором или советником ?

В функции 

через контроль нажатия на левую кнопку мышки можно сделать.
Например так:

#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();}
Причина обращения: