Ошибки, баги, вопросы - страница 3337

 
A100 #:
#define MACRO unsigned int

Не пойму тогда чего Вы добиваетесь...

Если нужно сделать такую запись:

#define MACRO такая \
запись

... то и будет "такая запись"

А если нужно сделать неразрывную запись:

#define MACRO не\
разрывная запись

... то и будет "неразрывная запись"

А в чём где ошибки?

 
Artyom Trishkin #:

А если нужно сделать неразрывную запись:

... то и будет "неразрывная запись"

А в чём где ошибки?


Ошибка в том, что не будет.
https://www.mql5.com/ru/forum/1111/page3326#comment_47234481
 
Столкнулся с непонятной особенностью CChekGroup.

Если создать группу чек-боксов, например, из 20 items,
которая не помещается целиком в окошко на панели CAppDialog,
то естественным образом возникает полоса прокрутки,
и все корректно работает при действиях мышкой.

Однако если програмно поставить галку в боксе, который
находится за пределами окна, то это вызывает ошибку на этапе исполнения:

array out of range in 'CheckGroup.mqh' (222,17)

При этом боксы в пределах окна прекрасно чекаются програмно,
то есть галка появляется, и никаких ошибок...

m_check_group.Check(i,1<<i); где i - номер бокса

Подскажите, плиз, в чем может быть дело?
 
44ex #:
Столкнулся с непонятной особенностью CChekGroup.

Если создать группу чек-боксов, например, из 20 items,
которая не помещается целиком в окошко на панели CAppDialog,
то естественным образом возникает полоса прокрутки,
и все корректно работает при действиях мышкой.

Однако если програмно поставить галку в боксе, который
находится за пределами окна, то это вызывает ошибку на этапе исполнения:

array out of range in 'CheckGroup.mqh' (222,17)

При этом боксы в пределах окна прекрасно чекаются програмно,
то есть галка появляется, и никаких ошибок...

m_check_group.Check(i,1<<i); где i - номер бокса

Подскажите, плиз, в чем может быть дело?

Попробуйте вставить такую строку в метод CCheckGroup::Check() в файле CheckGroup.mqh:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CCheckGroup::Check(const int idx,const int value)
  {
//--- check
   if(idx>=m_values.Total())
      return(false);
//---
   bool res=(m_states.Update(idx,value) && Redraw());
//--- change value
   if(res && idx<64)
     {
      Comment("m_rows.Size()=",m_rows.Size(),", idx=",idx);
      if(m_rows[idx].Checked())
         Value(m_value|m_values.At(idx));
      else
         Value(m_value&(~m_values.At(idx)));
     }
//---
   return(res);
  }
//+------------------------------------------------------------------+

На экране будет отображаться количество объектов CCheckBox в массиве m_rows и индекс idx, передаваемый в метод, по которому предполагается доступ в объекту в массиве.

Если при некоем условии индекс больше, либо равен количеству объектов в массиве, то тут и получается выход за пределы массива.

Соответственно, будет от чего отталкиваться для поиска и исправления ошибки в такой ситуации.

 
fxsaber #:

Интуитивно для меня это вторая строка того же макроса - продолжение.

У меня нет представления, что любой макрос - это всегда одна строка после применения.

Макрос после применения это всегда одна строка, но если Вам недостаточно теории, то вот подтверждающий пример:

#define MACRO Print(__LINE__);\
              Print(__LINE__);\
              Print(__LINE__);
void OnStart()
{
    MACRO
}
 
Artyom Trishkin #:

А в чём где ошибки?

Вот проще пример:

#define MACRO abc\
defg

int MACRO; //Error: 'defg' - semicolon expected

Компилятор не распознал abcdefg как единое целое

 
A100 #:

Макрос после применения это всегда одна строка, но если Вам недостаточно теории, то вот подтверждающий пример:

#define unsignedint double
#define MACRO1 unsigned\
int

void OnStart()
{
  Print(typename(MACRO1)); // хотите double.

  if (true)
  {
  // Тот же MACRO1, только сдвинул внутрь {} для лучшей читабельности.
  #define MACRO2 unsigned\
  int
  
    Print(typename(MACRO2)); // хотите uint.
    
  #undef MACRO2
  }
}


Получается, сдвинул макрос для лучшей читабельности и получил другой результат? Столь замечательный нюанс полезным не видится.


ЗЫ Предлагается такая запись?

#define unsignedint double

#ifdef __MQL5__
#define MACRO unsigned\
int
#endif // #ifdef __MQL5__


А вот более удобное визуальное (сдвинул пробелами внутри ifdef/endif) вложение уже меняет результат?

#define unsignedint double

#ifdef __MQL5__
  #define MACRO unsigned\
  int
#endif // #ifdef __MQL5__
 
Artyom Trishkin #:

Попробуйте вставить такую строку в метод CCheckGroup::Check() в файле CheckGroup.mqh:

На экране будет отображаться количество объектов CCheckBox в массиве m_rows и индекс idx, передаваемый в метод, по которому предполагается доступ в объекту в массиве.

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

Спасибо за ответ!

Да, я уже посмотрел файлы СБ, и в том и дело, что в CheckGroup.mqh массив m_rows 
еще при создании группы принудительно урезается до числа видимых в окне чек-боксов
(строка 106, метод CCheckGroup::Create(...) - ArrayResize(m_rows,m_total_view);,
а при скроллинге на графике в каждый момент присутствуют только объекты,
соответствующие видимым чек-боксам.
Поэтому при обращении за пределы окна гарантированно получим out of range.

Просто думал, что полностью понять их алгоритм не могу, поэтому надеялся,
что где-то моя ошибка...

Но вот воспроизвел этот эффект и в советнике Controls.mq5 из раздела примеров
в стандартной поставке терминала, из папки:
...\MQL5\Experts\Examples\Controls

Там если во включаемом файле ControlsDialog.mqh в методе CControlsDialog::CreateCheckGroup(void)
дополнить код, и создать не 5, а 8 чек-боксов
и затем выбрать програмно шестой, то после компиляции - тот же out of range

//--- fill out with strings
   for(int i=0;i<8;i++)
      if(!m_check_group.AddItem("Item "+IntegerToString(i),1<<i))
         return(false);
   m_check_group.Check(0,1<<0); // OK
   m_check_group.Check(6,1<<6); // !!!
//--- succeed
Выходит, все же баг?
Что печально...

 

С макросами ещё одна штука есть, с кривой их подсветкой.

Макрос в ME подсвечивается только ниже той строки, в которой он был определён, вроде правильно.

Но макросы из включаемого файла подсвечиваются во включающем тоже только после той строки, где определены во включаемом, а не где он включается.

 
fxsaber #:
Получается, сдвинул макрос для лучшей читабельности и получил другой результат? Столь замечательный нюанс полезным не видится.

А что мешает все такие макросы со смысловым переносом (MACRO1) определить один через другой и использовать в дальнейшем (сдвигать для удобства) уже другой (MACRO2) :

#define MACRO1 unsigned\
int
#define MACRO2    MACRO1

#ifdef __MQL5__
  #define MACRO3    MACRO2
#endif

Это также как и с дополнительными скобками () в макросах - можно их и не использовать (и компилятор не добавляет их сам), но тогда будьте готовы к сюрпризам

Нужно реализовать смысловой перенос - переопределите макрос и используйте его синоним

Не нужен смысловой перенос - делайте как обычно

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