Переинициализация панели с параметрами и падение

 

Имеется панель:

CPanelMain ExtDialog();
//class CPanelMain : public CAppDialog

В OnInit() прописано:

int OnInit()
  {
   if(UninitializeReason() == REASON_CHARTCHANGE)//Сделано, чтобы не крашилась при смене ТФ
     {
      return(INIT_SUCCEEDED);
     }
   if(!ExtDialog.Create(0, "Risk Order Panel", 0, 40, 40, DEFAULT_WIDTH, 320)) //Создаем окно панели
      return(INIT_FAILED);

   ExtDialog.Run();//Активируем окно

   return(INIT_SUCCEEDED);
  }

В OnDeinit

void OnDeinit(const int reason)
  {
   if(UninitializeReason() == REASON_CHARTCHANGE)//Сделано, чтобы не крашилась при смене ТФ
     {
      return;
     }
   ExtDialog.Destroy(reason);
  }

Дополнительно имеется 3 внешних переменных (пока не используются):

input color EntryColor = clrBlue;
input color SLColor = clrRed;
input color TPColor = clrGreen;

Проблема:

Кидается советник на график, всё корректно. Ок - панель появляется, ее можно перемещать, менять ТФ и т.д.

Жму F7 (настройки советника) - Ок. Ничего не меняется, приходит код деинициализации 5 (REASON_PARAMETERS) - все корректно, как будто поменяли какие то входные данные.

Жму F7 второй раз - Ок. Прилетает код деинициализации 8 (REASON_INITFAILED), окно крашится, график закрывается.

В Функции Create панели код:










bool CPanelMain::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2)
  {
   if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2))//Сама панель
      return(false);
   if(!CreateButtonCalc())//1 кнопка
      return(false);
  }

Код кнопки тоже стандартный:

bool CPanelMain::CreateButtonCalc(void)
  {

//--- Задаем координаты объекта
   int x1 = INDENT_LEFT + 2 * (BUTTON_WIDTH + CONTROLS_GAP_X);
   int y1 = INDENT_TOP + BUTTON_HEIGHT * 4 + CONTROLS_GAP_Y * 10;
   int x2 = x1 + BUTTON_WIDTH;
   int y2 = y1 + BUTTON_HEIGHT;
//--- Создаем объект
   if(!m_ButtonCalc.Create(0, "ButtonCalc", 0, x1, y1, x2, y2))
      return(false);
   if(!m_ButtonCalc.Text("Расчёт"))
      return(false);
   if(!Add(m_ButtonCalc))
      return(false);
//--- succeed

   return(true);
  }


Не могу понять, в чем причина вылета именно на второй раз. В первый раз то всё отрабатывает нормально.... Если настройки не открывать, то вся панель работает корректно, вылетов нет. Такое ощущение, что где-то что-то забыл сделать....


P.S. Статью https://www.mql5.com/ru/articles/4503 читал кучу раз :)

Торговые советники и собственные индикаторы - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
Торговые советники и собственные индикаторы - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
  • www.metatrader5.com
Среди программ для автоматического трейдинга можно выделить две большие категории: торговые роботы и индикаторы. Первые предназначены для совершения торговых операций на рынках, а вторые — для анализа котировок и выявления закономерностей в их изменении. При этом индикаторы могут использоваться непосредственно в роботах, образуя полноценную...
 

Похоже я нашел таки баг...

За основу взят файл из статьи . Там готовый советник AppWindowTwoButtons.mq5 (прекрасно работает и в МТ4 после смены расширения на mq4).

Так вот, баг появляется даже в этом коде исключительно в том случае, если добавить внешнюю переменную типа:

input color EntryColor = clrBlue;


Тип переменной значения не имеет (проверял int, double и т.д.). Главное, что при добавлении input советник начинает получать уведомления (код деинициализации 5 (REASON_PARAMETERS) ) и после этого крашится или некорректно отрабатывает Destroy, оставляя артефакты в виде неудалившихся контролов.

Как создать графическую панель любой сложности и как это работает
Как создать графическую панель любой сложности и как это работает
  • www.mql5.com
До сих пор большинство программистов, которые пишут индикаторы и советники для платформы MetaTrader 5, почти не пользуются возможностями по созданию графических интерфейсов в своих приложениях.  Основная причина такого положения дел, на мой взгляд, заключается в том, что классы Панели и диалоги из Стандартной библиотеки содержат только сухое...
 

Копаем дальше.Проблема кроется в файле Dialog.mqh.

При подкидывании файла от МТ5 - всё отрабатывает штатно, как и положено.

Вопрос - как исправить данный баг? Мой продукт использует штатные заголовочные файлы и выставлен в Маркете. Соответственно, я не могу подсунуть "свой" Dialog.mqh в него. Можно, конечно, скопировать весь код из корректного файла и вставить в эксперта, но, как мне кажется, лучше все таки разработчикам централизованно исправить ошибку, тем более что файлы в МТ4 и МТ5 отличаются всего в 5 местах и изменения мизерные.

 
Aleksei Firsov:

Копаем дальше.Проблема кроется в файле Dialog.mqh.

При подкидывании файла от МТ5 - всё отрабатывает штатно, как и положено.

Вопрос - как исправить данный баг? Мой продукт использует штатные заголовочные файлы и выставлен в Маркете. Соответственно, я не могу подсунуть "свой" Dialog.mqh в него. Можно, конечно, скопировать весь код из корректного файла и вставить в эксперта, но, как мне кажется, лучше все таки разработчикам централизованно исправить ошибку, тем более что файлы в МТ4 и МТ5 отличаются всего в 5 местах и изменения мизерные.

Вопрос по какому терминалу: старому или MetaTrader 5?

 
Vladimir Karputov:

Вопрос по какому терминалу: старому или MetaTrader 5?

MetaTrader 4
 
Aleksei Firsov:
MetaTrader 4

Это MQL5 форум, а для старого терминале есть спец. раздел  MQL4 и MetaTrader 4 - все вопросы по старому терминалу пишите туда. 

Вашу тему перенесу.

 
Создавай указатель на панель
CPanelMain *ExtDialog
 

Не помогло.

CPanelMain *ExtDialog = new CPanelMain(true);

Теперь в окне "Эксперты" выдается (на второй попытке изменить параметры): "20632 bytes of leaked memory" и перечень контролов, которые не удалились.

 
Удалось побороть путем объявления указателя в OnInit и уничтожения в OnDeinit.
 
Aleksei Firsov:
Удалось побороть путем объявления указателя в OnInit и уничтожения в OnDeinit.
Что весьма логично!!!
 
if(UninitializeReason() == REASON_CHARTCHANGE)

вместо функции 

UninitializeReason

просто

if(reason == REASON_CHARTCHANGE)