Баг с созданием скриншота в индикаторе МТ5 - страница 6

 
Vitaly Muzichenko #:

Есть уже такое, но применение шаблона работает ещё печальней


может не хватает?


или дернуть туда-сюда 
 
Roman #:
Раз функция ChartScreenShot выполняется асинхронно, то по хорошему надо после скрина, выходить из OnCalculate
и на следующем заходе в OnCalculate, обрабатывать этот файл.
В общем надо подумать, но попозже. Надо отдохнуть.

Вот такая логика: Появилась стрелка, на экран выводим Alert() и параллельно отсылаем скрин в телегу

Кроме Таймера Я не вижу ничего другого.

Делать что-то в OnCalculate не особо хорошо, может открыться бар с сигналом, далее нет тика и следующий будет через 15 секунд - скрин придёт с опозданием.


 
Roman #:
Раз функция ChartScreenShot выполняется асинхронно, то по хорошему надо после скрина, выходить из OnCalculate
и на следующем заходе в OnCalculate, обрабатывать этот файл.
Vitaly Muzichenko #:


Так попробуй

bool signal = false;
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
{
   int bars = rates_total-prev_calculated;
   
   //на первом старте принудительно создаём файл, чтоб он уже был
   if(bars > 1)
      ChartScreenShot(0,filename,1024,768,ALIGN_RIGHT);
   
   
   if(signal)
   {
      SendScreenTG();
      signal = false;   
   }
   
   //рассчёт по новому бару, представим что это сигнал
   if(bars == 1)
   {
      if(ChartScreenShot(0,filename,1024,768,ALIGN_RIGHT))
         signal = true;   
   }      



  return(rates_total);
}
 
Roman #:

Так попробуй

Наверное это нужно добавить

if((size=FileReadArray(h,gif)) > 0) {

ChartScreenShot асинхронная, сразу возвращает true, даже если скрин не создан/перезаписан до конца.

Продолжу завтра, сегодня уже поздно

 
Vitaly Muzichenko #:

Наверное это нужно добавить

Продолжу завтра, сегодня уже поздно

Это же есть в SendScreenTG()

Тут смысл в том, что мы выходим из OnCalculate
и по идее файл при выходе из OnCalculate должен быть уже записан.
А на следующем заходе(тике) мы его забираем.
 
Roman #:

Это же есть в SendScreenTG()

Да, пора спать :)

 
Vitaly Muzichenko #:
Продолжу завтра, сегодня уже поздно
Лучше будет, если к этому внимание разработчиков привлечь. Пусть хоть что-то по этому поводу ответят. Иначе этот баг не будет исправлен никогда.
Если ChartScreenShot асинхронная, а она асинхронная, нужна возможность получить управление после завершения сохранения скриншота. Или нужна возможность исполняет ChartScreenShot в синхронном режиме.
 
Roman #:
Вот так наверно будет самое оно.
Костыль, который не гарантирует готовности файла скриншота на момент вызова функции SendScreenTG.
 
Стандартной нет функции ожидания.
А насколько WaitForFile будет корректно работать, я не знаю.

Но вроде пашет.

scr

scr

//+------------------------------------------------------------------+
//|                                                       SCREEN.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window

#property indicator_buffers 0
#property indicator_plots   0

string filename = "screen.png";
bool   signal   = false;
int    bars;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   EventSetMillisecondTimer(100);
   return(INIT_SUCCEEDED);
}
  
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer();

} 

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
{
   if(signal)
   {
      if(WaitForFile(filename))
      {
         SendScreenTG();
         //Allert();
         signal = false;
      }
   }   
}
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
{
   bars = rates_total-prev_calculated;
   
   //первый старт 
   if(bars > 1)
      ChartScreenShot(0,filename,1024,768,ALIGN_RIGHT);
   
      
   //рассчёт по новому бару, представим что это сигнал
   if(bars == 1)
   {
      if(/*твой сигнал && */ ChartScreenShot(0,filename,1024,768,ALIGN_RIGHT))
         signal = true;   
   }

  return(rates_total);
}



//-------------------------------------------------------------------
bool WaitForFile(string fname, int timeout_ms=5000)
{
   ulong start = GetTickCount64();
   while(GetTickCount64() - start < (ulong)timeout_ms)
   {
      if(FileIsExist(fname))
      {
         int h = FileOpen(fname, FILE_BIN|FILE_READ);
         if(h != INVALID_HANDLE)
         {
            uint size = (uint)FileSize(h);
            FileClose(h);
            
            if(size > 0) 
               return true;
         }
      }
      Sleep(100); //даём время терминалу
   }
   return false;
}

//-------------------------------------------------------------------
void SendScreenTG()
{  
   int h = FileOpen(filename, FILE_BIN|FILE_READ);
   if(h == INVALID_HANDLE) 
   {
      Print("Err open "+filename);
      return;
   }
  
   uint size;
   uchar png[];
    
   //прочитали файл в массив
   if((size=FileReadArray(h,png)) > 0) 
   {
      //
      //тут вся логика функции SendScreenTG
      //     
     
      Print("FileSize: ", size);     
   }
   else 
   {
      //FileReadArray вернул 0 элементов
   }
    
   FileClose(h);
}

 

На форуме были примеры запуска OrderSend и WebRequest из индикатора. Реализация через запуск соответствующего скрипта.

С созданием и отправкой скрина можно сделать по аналогии. В скрипте обсуждаемой асинхронности не будет.