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

 
Roman #:

Да, если удалить файл скрина из папки Files, то на первом создании файла он тупит и даёт ошибку,
но последующие идут все без 0 размера.

говорю попробуй такие флаги, у меня так

Вот что вы читаете:

Первый запуск инди: Получаю ошибку что файл нулевого размера, после этого создаётся скрин

Следующий сигнал отправляет файл созданный ранее, после этого его перезаписывает

Следующий сигнал снова отправляет прошлый файл и пишет новый.

По итогу, читаете прошлые файлы, а не текущий.

 
Vitaly Muzichenko #:

Мне нужно в дальнейшем записать в этот файл и отправить в телегу, так что флаг нужен

Зачем в этот файл что-то записывать? Это валидный, завершенный файл с картинкой. Если нужно его вставлять в сообщение для телеги, то это другой будет файл или просто буфер.

Вот такой скрипт спокойно генерит последовательность файлов. Если нужно, удаляйте после отправки.

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

//#include <MQL5Book/PRTF.mqh>
#define PRTF

input int Repeat = 10;

void OnStart()
{
  for(int i = 0; i < Repeat; i++)
  {
    const string filename = (string)(long)TimeCurrent() + "'" + (string)(GetTickCount() % 1000) + "-" + (string)i + ".png";
    if(PRTF(ChartScreenShot(0, filename, 1024, 768, ALIGN_RIGHT)))
    {
      SendScreenTG(filename);
    }
  }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SendScreenTG(const string filename)
{
  int h = PRTF(FileOpen(filename, FILE_READ | FILE_BIN | FILE_SHARE_READ | FILE_SHARE_WRITE));
  if(h == INVALID_HANDLE) return;
  uchar bytes[];
  PRTF(FileReadArray(h, bytes));
  FileClose(h);
  
  // TODO: write the bytes anywhere we want
}
Если подключите PRTF - увидите, что все функции работают без ошибок, без нулей и без задержек (файл доступен для чтения сразу после скриншота - уникальные имена это гарантируют).
 
Vitaly Muzichenko #:

Вот что вы читаете:

Первый запуск инди: Получаю ошибку что файл нулевого размера, после этого создаётся скрин

Следующий сигнал отправляет файл созданный ранее, после этого его перезаписывает

Следующий сигнал снова отправляет прошлый файл и пишет новый.

По итогу, читаете прошлые файлы, а не текущий.

Ага понял

Может попробовать проверку существования файла добавить? для первого старта.
Попробуй.

void SendScreenTG()
{
   if(!FileIsExist(filename))
      return;
   
   int h = FileOpen(filename, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_BIN|FILE_ANSI);
   if(h == INVALID_HANDLE) 
   {
      Print("Err open "+filename);
      return;
   }
  
   uint size;
   uchar gif[];
    
   //прочитали файл в массив
   if((size=FileReadArray(h,gif)) > 0) 
   {
      //
      //тут вся логика функции SendScreenTG
      //
      
     
     
      Print("FileSize: ", size);     
   }
   else 
   {
      Print("FileSize: ", size);     
   }
    
   FileClose(h);
}
 
Кстати говоря, если вы сами держите файл открытым (зачем-то), то следующая попытка сделать скриншот может ждать его освобождения.
 
Stanislav Korotky #:
Кстати говоря, если вы сами держите файл открытым (зачем-то), то следующая попытка сделать скриншот может ждать его освобождения.

Файл же закрывается каждый раз, в конце пользовательской функции.
Проблема возникает на первом старте, когда нет ещё созданного файла.
И получается сдвиг на один шаг.

 
Stanislav Korotky #:
Кстати говоря, если вы сами держите файл открытым (зачем-то), то следующая попытка сделать скриншот может ждать его освобождения.

Вот так получается в индикаторе

  for(int i = 0; i < Repeat; i++) {
    const string filenames = (string)(long)TimeCurrent() + "'" + (string)(GetTickCount() % 1000) + "-" + (string)i + ".png";
    if(PRTF(ChartScreenShot(0, filenames, 1024, 768, ALIGN_RIGHT))) {
      SendScreenTG(filenames);
    }
  }
  return(rates_total);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SendScreenTG(const string fnm)
{
  int h = PRTF(FileOpen(fnm, FILE_READ | FILE_BIN | FILE_SHARE_READ | FILE_SHARE_WRITE));
  if(h == INVALID_HANDLE) {
    Print("err= ",GetLastError());
    return;
  }


 
Roman #:

Ага понял

Может попробовать проверку существования файла добавить? для первого старта.
Попробуй.

У нас каждый первый старт = перезаписанный файл или созданный новый.

Сейчас мы всегда на шаг позади, функция отрабатывает при ещё не переписанном/созданном файле, и использует прошлый.

 

Проверил в эксперте и скрипте - работает любой вариант, скрин создаётся быстро и к нему сразу есть доступ.

Но никакой вариант не работает в индикаторе, нужна пауза примерно в 2 секунды

 
Vitaly Muzichenko #:

У нас каждый первый старт = перезаписанный файл или созданный новый.

Сейчас мы всегда на шаг позади, функция отрабатывает при ещё не переписанном/созданном файле, и использует прошлый.

У нас первый старт, нет ещё файла.

Идём

if(ChartScreenShot(0,filename,1024,768,ALIGN_RIGHT))
   SendScreenTG();


void SendScreenTG()
{
   if(!FileIsExist(filename))
      return;

На стартовой итерации мы вышли из пользовательской функции, так как файла нет, но физически первый файл создался.

На следующей итерации снова делам скрин, и уже проскакиваем это условие, так как файл существует

if(!FileIsExist(filename))
   return;


и уже текущий файл открывается для работы с ним.

По сути должен отправляться текущий перезаписанный файл.

 
Roman #:

У нас первый старт, нет ещё файла.

Идём

ChartScreenShot
SendScreenTG
if !FileIsExist
return

Из пользовательской функции мы вышли, первый файл создался, но мы его не отправили.

На следующей итерации делам скрин, и уже проскакиваем условие if !FileIsExist
и уже текущий файл открывается для работы с ним.

По сути должен отправляться текущий перезаписанный файл.

Где взять следующую итерацию через 2 секунды пока создаётся файл, кроме Таймера с флагом?

ChartScreenShot создаёт или перезаписывает файл очень долго