Чтение бинарных файлов из индикатора - страница 2

 
Vladimir Simakov:

Неуж-то разрабы забыли handle закрыть? Так, мысли вслух.

не знаю, проверил лишь тот код что выложил, но "просмотр фотографий" Вин10 тож пишет, что изображение не доступно для просмотра

ЗЫ: не 5-10 секунд, второй раз запустил свой код, вообще до закрытия терминала файлы были заблокированы, в общем в индикаторе на МТ5 не получится сделать и отправить скриншот....мануалов не хватает )))

 
Igor Makanu:

не знаю, проверил лишь тот код что выложил, но "просмотр фотографий" Вин10 тож пишет, что изображение не доступно для просмотра

ЗЫ: не 5-10 секунд, второй раз запустил свой код, вообще до закрытия терминала файлы были заблокированы, в общем в индикаторе на МТ5 не получится сделать и отправить скриншот....мануалов не хватает )))

Точно, забыли. Баг. Модератор, ветку в тему про баги перенеси.

 
Vladimir Simakov:

Точно, забыли. Баг. Модератор, ветку в тему про баги перенеси.

тогда в довесок:

2019.12.07 21:45:17.090 Terminal MetaTrader 5 x64 build 2265 started (MetaQuotes Software Corp.)

2019.12.07 21:45:17.091 Terminal Windows 10 (build 18363) x64, IE 11, UAC, Intel Core i3-4170  @ 3.70GHz, Memory: 9057 / 12157 Mb, Disk: 212 / 297 Gb, GMT+4

 
Igor Makanu:

по моему там еще что то мешает

вот набросал код индикатора - пишем каждые 10 секунд:

в теории все работает - вижу папку MQL5\Files\ScreenShots\20191207 в ней появляются файлы

но пока индикатор работает, не могу в Вин10 открыть скриншоты для просмотра, т.е. файлы заблокированы, даже если удалить индикатор, превью в проводнике Вин10 заработает секунд через 5-10 , т.е. лишь тогда файлы скриншотов станут доступны для чтения

Попробуй изменить код, теперь блокировки нет.

void OnTimer()
  {
   ResetLastError();
   if(!SaveScreenShot())
      Print("Ошибка сохранения скриншота № ",GetLastError());
   else
      Print("Сохранил скриншот");

   EventKillTimer();    EventSetTimer(10);

     }
 
SEM:

Попробуй изменить код, теперь блокировки нет.

неинтересно, все равно не правильно работает, по моему таймер как раз и предназначен для таких простых вещей 

ЗЫ: проверил все таки, да если убить таймер, то проводник Вин10 видит скриншоты сразу

 
//+------------------------------------------------------------------+
//|                                                         Test.mq5 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots   1
#property indicator_buffers 1
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   ::EventSetMillisecondTimer(500);
   return(INIT_SUCCEEDED);
  }
  
  void OnDeinit(const int reason) {
   ::EventKillTimer();
}

void OnTimer() {
   ::EventKillTimer();
   TestPhoto();
}
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

void TestPhoto() {
   string name;
   MqlDateTime  dtLocal;
   TimeToStruct(TimeLocal(), dtLocal);
   string date = IntegerToString(dtLocal.year) + IntegerToString(dtLocal.mon, 2, '0') + IntegerToString(dtLocal.day, 2, '0');
   string time = IntegerToString(dtLocal.hour, 2, '0') + "." + IntegerToString(dtLocal.min, 2, '0') + "." + IntegerToString(dtLocal.sec, 2, '0');
   name = "ScreenShots/" + date + "/" + _Symbol + "_" +date + "_" + time + ".png";
   
   if (!ChartScreenShot(0, name, 1920,1200, ALIGN_RIGHT))
      return;

   ResetLastError();
   
   for (int i=0; i < 100000; i++){
      if (FileIsExist(name,false) && FileSize(name) > 0)
         break;
   }
   //---
   int flags=FILE_READ|FILE_BIN|FILE_SHARE_READ;

   //---
   int file=FileOpen(name,flags);
   if(file<0) {
      Print("Операция FileOpen неудачна, ошибка ",GetLastError());
      return;
}
   uchar photo[];
   FileReadArray(file,photo);
   FileClose(file);
   
   Print(ArraySize(photo));
}

Вот попробовал с таймером, ничего не меняется, файл создается, но не читается

 
Andrei Kossarev:

Вот попробовал с таймером, ничего не меняется, файл создается, но не читается

Не так. Функция сохранения сама по себе, но в ней, имя сохраняемого скриншота добавляется в глобальный массив. А по таймеру прокручивается массив и делаются попытки читать файлы, если в файле есть данные, значит с ним стало все нормально и его можно отсылать, после отсылки удаляем имя из массива.

 
Dmitry Fedoseev:

Не так. Функция сохранения сама по себе, но в ней, имя сохраняемого скриншота добавляется в глобальный массив. А по таймеру прокручивается массив и делаются попытки читать файлы, если в файле есть данные, значит с ним стало все нормально и его можно отсылать, после отсылки удаляем имя из массива.

Так тоже не работает.

 

А вроде получилось. ChartRedraw() добавил и...

//+------------------------------------------------------------------+
//|                                                         Test.mq5 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots   1
#property indicator_buffers 1


string names[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {

   EventSetTimer(1);

   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   SaveImg();
}


void OnTimer(){
   int h;
   uchar photo[];
   
   Print(ArraySize(names));
   
   for(int i=0;i<ArraySize(names);i++){
      
      h=FileOpen(names[i],FILE_READ|FILE_BIN|FILE_SHARE_READ);
      if(h!=-1){
         ArrayResize(photo,0);
         FileReadArray(h,photo);      
         if(ArraySize(photo)>0){
            FileClose(h);
            FileMove(names[i],0,names[i]+"_ok",FILE_REWRITE); // типа отправки скриншота...
            ArrayCopy(names,names,i,i+1);
            ArrayResize(names,ArraySize(names)-1);
            i--;
         }
         else{
            FileClose(h);
         }
         
      }
   }


   
   

}

bool SaveImg() {

   string name;
   MqlDateTime  dtLocal;
   TimeToStruct(TimeLocal(), dtLocal);
   
   string date =  IntegerToString(dtLocal.year) + 
                  IntegerToString(dtLocal.mon, 2, '0') + 
                  IntegerToString(dtLocal.day, 2, '0');
   
   string time =  IntegerToString(dtLocal.hour, 2, '0') + "-" + 
                  IntegerToString(dtLocal.min, 2, '0') + "-" + 
                  IntegerToString(dtLocal.sec, 2, '0');
          
   name = "ScreenShots/" + date + "/" + _Symbol + "_" +date + "_" + time + ".png";      
            
   int n=1;
   while(FileIsExist(name)){
      name = "ScreenShots/" + date + "/" + _Symbol + "_" +date + "_" + time + "("+(string)n+").png";        
      n++;
   }                  
   
   if(!ChartScreenShot(0, name, 800, 600, ALIGN_RIGHT)){
      return(false);
   }
   
   ArrayResize(names,ArraySize(names)+1);
   names[ArraySize(names)-1]=name;
   
   ChartRedraw();
   
   return(true);
   
}   
      
 
 
Dmitry Fedoseev:

Оказывается, дело не в чтении файла, а в сохранении скриншота функцией ChartScreenShot(). Получается, что функция асинхронно работает. Сразу после вызова скриншот еще не успел сохраниться, файл есть, но он пустой. И это, скорее всего, не баг, а фича - чтобы индикаторы не тормозили. 

Если надо во что бы то ни стало, то после вызова ChartScreenShot() можно добавить какой-нибудь цикл, что бы паузу обеспечить, или в цикле проверять, пока в файле что-то не появится. 

Лучше не цикл, а событие, например чтение файла после того как изменился размер файла.

1-делаем скриншот

2-отслеживаем изменение длины файла ( т. е. при первом чтении сразу после создания она видимо нулевая )

3-чтение файла после того как размер стал не нулевой

Причина обращения: