mql5语言的特点、微妙之处以及技巧 - 页 189

 
Nikolai Semko:

你需要运行CTestTimer类中的Timer4方法(以蓝色显示)。

没有进入它。

#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

我又得到了它。我认为这可能发生在重新登录的罕见情况下。

解决办法是,如果是假的,在短暂停顿后重试。

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

如果你进行手动重新登录,这个EA仍将工作。如果没有突出显示的字符串,它将自动删除。

 
fxsaber:

没有进入它。

谢谢你的时间。但我在上面 写到,这个方法应该是非静态的。很明显,这在静态方法中是可以实现的。静态方法根本就不是一个OOP。
很明显,我想要的太多了,或者说不可能。
我对在C++中可以这样做的事实感到困惑,但经过研究,我明白这样的指针具有相当不同的结构。

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


这也是可以理解的。

一个非静态类方法有一个单一的实现,它位于内存的某个地方,影响类的所有对象。
,但是每个对象都有自己独特的内部变量的当前状态,所以这样一个指向非静态方法的指针也必须有一个填充的对象参数结构,该方法此刻适用于这个对象。

我们需要寻找其他的方法来普遍控制不同类别的对象,对大家的浪费表示歉意。

无解的证明也是一种解。

 
Nikolai Semko:

谢谢你的时间。但我在上面 写到,这个方法应该是非静态的。很明显,这在静态下是可能的。

上面给了你两个例子。一个是全面实施的
 
TheXpert:
上面给了你两个例子。一个是全面实施的

你似乎没有理解我的问题。
它没有解决办法。

 
Nikolai Semko:

你似乎没有理解我的问题。
它没有解决办法。

当旁边有一扇门时,为什么要用头撞墙呢? 处理程序调用外部类的多定时器问题已经解决了。

这个 家伙在这里有一个解决你的问题的办法,就像你看到的那样,虽然是非公开的。

 
TheXpert:
旁边有一扇门,为什么要用头撞墙呢? 用处理程序调用外部类的多定时器任务就解决了。

这不是关于计时器的问题。
,我只是在做白日梦和愚蠢。

 
Nikolai Semko:

我只是在做白日梦,目瞪口呆。

我支持一个完整的类型化定义 或在mql中的相同绑定,但也就这样了。

 

是否有可能区分手动创建的图形对象和由指标 或EA创建的 对象?

在函数中

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

     }
  }
 
Vladimir Pastushak:

是否有可能区分手动创建的图形对象和由指标 或EA创建的 对象?

在函数中

你可以用鼠标左键控制来做。
比如说像这样。

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