Características da linguagem mql5, subtilezas e técnicas - página 189

 
Nikolai Semko:

É necessário executar o método Timer4 (destacado a azul) da classe CTestTimer

Não entrou nela.

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

Fórum sobre comércio, sistemas automatizados de comércio e teste de estratégias comerciais

Peculiaridades de mql5, dicas e truques

fxsaber, 2020.05.14 02:57

Consegui-o novamente. Presumo que isto possa ocorrer em situações raras quando se faz um novo registo.

A solução é, se falsa, tentar de novo após uma curta 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 é uma má solução. Aqui está uma solução muito melhor.

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

Se fizer um novo registo manual, esta EA ainda funcionará. Sem a corda realçada, auto-extinguir-se-á.

 
fxsaber:

Não entrou nela.

Obrigado pelo seu tempo. Mas escrevi acima que o método deve ser não-estático. É evidente que isto é possível com métodos estáticos. Um método estático não é de todo um OOP.
Obviamente que eu queria demasiado, ou melhor, impossível.
Fiquei confuso com o facto de ter sido possível fazê-lo em C++, mas ao examiná-lo, compreendi que tal ponteiro tem uma estrutura totalmente diferente,

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


E é compreensível.

Um método de classe não estático tem uma única implementação, que fica algures na memória e afecta todos os objectos da classe.
Mas cada objecto tem o seu próprio estado actual único de variáveis internas, pelo que um tal ponteiro para um método não estático deve também ter uma estrutura de parâmetros preenchida do objecto ao qual é aplicado no momento.
Peço desculpa a todos pela perda de tempo.
Precisamos de procurar outras formas de controlar geralmente objectos de diferentes classes.

A prova de não haver solução é também uma solução.

 
Nikolai Semko:

Obrigado pelo seu tempo. Mas escrevi acima que o método deve ser não-estático. É evidente que isto é possível com estática.

Foram-lhe dados dois exemplos acima. um com implementação completa
 
TheXpert:
Foram-lhe dados dois exemplos acima. um com implementação completa

Parece não ter compreendido o meu problema.
Não tem solução.

 
Nikolai Semko:

Parece não ter compreendido o meu problema.
Não tem solução.

Porquê bater com a cabeça contra a parede quando há uma porta ao seu lado? O problema do multitemporizador com uma chamada de um manipulador para uma classe externa foi resolvido.

Este colega aqui tem uma solução para o seu problema tal como o vê, mas não pública.

 
TheXpert:
Porquê bater com a cabeça contra a parede quando há uma porta ao seu lado? A tarefa multitemporizada com uma chamada de um manipulador para uma classe externa foi resolvida.

Não se tratava do temporizador.
Eu estava apenas a sonhar acordado e estúpido.

 
Nikolai Semko:

Estava apenas a sonhar acordado e estupefacto.

Sou a favor de uma dactilografia completa ou das mesmas ligas em mql, mas é tudo.

 

É possível distinguir um objecto gráfico criado manualmente de um objecto criado por um indicador ou EA?

Na função

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

     }
  }
 
Vladimir Pastushak:

É possível distinguir um objecto gráfico criado manualmente de um objecto criado por um indicador ou EA?

Na função

Pode fazê-lo com o controlo do botão esquerdo do rato.
Por exemplo, como este:

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