CAppDialog in Expert Advisors - terminal freezing after closing

 

Hello,

I tried to use new panel/controls interface in MetaTrader. I took SimplePanel.mq4+PanelDialog.mqh from Indicators\Examples directory, put them into one file SimplePanelEA.mq4, moved to Experts directory and I removed OnCalculate function and "#property indicator_*" lines. After attaching to a chart my new file SimplePanelEA works fine, but the problem is with closing. Only if I close using "X" in the upper right corner of the panel everything is fine. But if I try to close a chart or whole terminal then the terminal freezes. Sometimes I can have in logs information that the expert was closed by timeout.

So my questions is: should new controls be used differently in Expert Advisors than in Indicators? If so, what should be changed in attached code? Or is it a problem (bug) in MetaTrader 4? The same code in MetaTrader 5 (file renamed to SimplePanelEA.mq5) doesn't cause any troubles during closing.

Best regards
Vitovd

Files:
 
Vitovd5:

Hello,

I tried to use new panel/controls interface in MetaTrader. I took SimplePanel.mq4+PanelDialog.mqh from Indicators\Examples directory, put them into one file SimplePanelEA.mq4, moved to Experts directory and I removed OnCalculate function and "#property indicator_*" lines. After attaching to a chart my new file SimplePanelEA works fine, but the problem is with closing. Only if I close using "X" in the upper right corner of the panel everything is fine. But if I try to close a chart or whole terminal then the terminal freezes. Sometimes I can have in logs information that the expert was closed by timeout.

So my questions is: should new controls be used differently in Expert Advisors than in Indicators? If so, what should be changed in attached code? Or is it a problem (bug) in MetaTrader 4? The same code in MetaTrader 5 (file renamed to SimplePanelEA.mq5) doesn't cause any troubles during closing.

Best regards
Vitovd

Hi!

Is it works foi you? My problem with this is when a change the TF more then two times!

Can you help me? 

 
Vitovd5: But if I try to close a chart or whole terminal then the terminal freezes. Sometimes I can have in logs information that the expert was closed by timeout.
  1. Indicators must return in a reasonable time because until they do, the terminal is hung. (Indicators can not sleep, trade or any other blocking calls.)
  2. EA must return within 3 seconds when the chart/terminal is shutdown or they will be forcefully terminated.
  3. Why is your expert taking so long to process a tick?
 

Please, look the error when I change the TF some times!

Files:
 
Vitor Hervatin: Please, look the error when I change the TF some times!

English: If you have difficulty with the English language, consider using the Portuguese forum!

Português: Se tiver dificuldades com a língua Inglesa, considere utilizar o fórum em Português!

 

This is a Bug in Controls\Dialog.mqh when using Expert Advisor, if you use only INdicator, this bug dont occurs.


What you need do to fix it:


Insert into yout file Objects:

public:

   void              Destroy(const int reason);    

   int               m_deinit_reason;

   ENUM_PROGRAM_TYPE m_program_type;        // type of program

   string            m_indicator_name;

   string            m_program_name;        // name of program


and then, add the void Destroy(const int reason):

//+------------------------------------------------------------------+

//| Application dialog deinitialization function                     |

//+------------------------------------------------------------------+

void  CPanelDialog::Destroy(const int reason)

  {

//--- destroyed already?

// BUG NA CLASSE, REMOVER ESTA LINHA/ BUG ON DIALOG 

//  if(m_deinit_reason!=WRONG_VALUE) return;    


//---

   m_deinit_reason=reason;

   IniFileSave();

//--- detach chart object from chart

   m_chart.Detach();

//--- call parent destroy

   CDialog::Destroy();


//---

   if(reason==REASON_PROGRAM)

     {

      if(m_program_type==PROGRAM_EXPERT)

         ExpertRemove();

      if(m_program_type==PROGRAM_INDICATOR)

         ChartIndicatorDelete(m_chart_id,m_subwin,m_indicator_name);

     }

     

//--- send message

   EventChartCustom(m_chart_id,ON_APP_CLOSE,m_subwin,0.0,m_program_name);

  }

 
Dorival Cardozo:

This is a Bug in Controls\Dialog.mqh when using Expert Advisor, if you use only INdicator, this bug dont occurs.


What you need do to fix it:


Insert into yout file Objects:

public:

   void              Destroy(const int reason);    

   int               m_deinit_reason;

   ENUM_PROGRAM_TYPE m_program_type;        // type of program

   string            m_indicator_name;

   string            m_program_name;        // name of program


and then, add the void Destroy(const int reason):

//+------------------------------------------------------------------+

//| Application dialog deinitialization function                     |

//+------------------------------------------------------------------+

void  CPanelDialog::Destroy(const int reason)

  {

//--- destroyed already?

// BUG NA CLASSE, REMOVER ESTA LINHA/ BUG ON DIALOG 

//  if(m_deinit_reason!=WRONG_VALUE) return;    


//---

   m_deinit_reason=reason;

   IniFileSave();

//--- detach chart object from chart

   m_chart.Detach();

//--- call parent destroy

   CDialog::Destroy();


//---

   if(reason==REASON_PROGRAM)

     {

      if(m_program_type==PROGRAM_EXPERT)

         ExpertRemove();

      if(m_program_type==PROGRAM_INDICATOR)

         ChartIndicatorDelete(m_chart_id,m_subwin,m_indicator_name);

     }

     

//--- send message

   EventChartCustom(m_chart_id,ON_APP_CLOSE,m_subwin,0.0,m_program_name);

  }

This really helped me as I faced the same issue, I want to share shorter work-around, since the issue occurs only in Experts, the we may only need to override the CAppDialog::Destroy and defining member variables and check if the calling program is Indicator or Expert are not mandatory.

In the derived class CPanelDialog, override Destroy function under public keyword:

public:
                     CPanelDialog();
                    ~CPanelDialog();
   //--- create
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
   virtual void      Destroy(const int reason=REASON_PROGRAM);

then define it as below:

void CPanelDialog::Destroy(const int reason) {
//---
   IniFileSave();
//--- detach chart object from chart
   m_chart.Detach();
//--- call parent destroy
   CDialog::Destroy();
//---
   if(reason==REASON_PROGRAM)
     {
      if(MQLInfoInteger(MQL_PROGRAM_TYPE)==PROGRAM_EXPERT)
         ExpertRemove();
     }
//--- send message
   EventChartCustom(m_chart_id,ON_APP_CLOSE,m_subwin,0.0,ProgramName());
}
 
Mohammad Mohi:

This really helped me as I faced the same issue, I want to share shorter work-around, since the issue occurs only in Experts, the we may only need to override the CAppDialog::Destroy and defining member variables and check if the calling program is Indicator or Expert are not mandatory.

In the derived class CPanelDialog, override Destroy function under public keyword:

then define it as below:


Same problem here, this is how it worked for me just by adding one line:

Edit Dialog.mqh

bool CAppDialog::CreateCommon(const long chart,const string name,const int subwin)
  {
//--- save parameters
   m_chart_id    =chart;
   m_name        =name;
   m_subwin      =subwin;
   m_program_name=name;

// ADD this line
   m_deinit_reason=WRONG_VALUE;

re compile Dialog, re compile EA, re load EA, it should work.

My problem now is that if I want to take the EA to another instalation I will always have to edit the class file dialog, if you know of any other way please let us know.

 
Dimanche:


Same problem here, this is how it worked for me just by adding one line:

Edit Dialog.mqh

re compile Dialog, re compile EA, re load EA, it should work.

My problem now is that if I want to take the EA to another instalation I will always have to edit the class file dialog, if you know of any other way please let us know.

I believe the best way is to create an instance of the class by 'new' keyword, define a pointer in global scope, create an instance of it in OnInit() by 'new' keyword and assign it to the pointer, then delete it in OnDeinit(), it is well described in the following post:

https://www.mql5.com/en/forum/64619/page2#comment_2052954

#include <Controls\Dialog.mqh>

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
CAppDialog *myDialog;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
      myDialog = new CAppDialog;
  
      if (!myDialog.Create(0,"My Dialog",0,2,25,150,180)){
         return(INIT_FAILED); 
      }
      
      if(!myDialog.Run()){
         return(INIT_FAILED);
      }  

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   
   myDialog.Destroy(reason);
   delete myDialog;
      
  }

Another work around would be setting 'm_deinit_reason' to WRONG_VALUE by overriding CAppDialog::Create function virtually, since it is a public method of the class and it is the only function that calls CreateCommon, and then use the new derived class instead.

#include <Controls\Dialog.mqh>

class CMyAppDialog : public CAppDialog
  {
private:
   //--- variables
   int               m_deinit_reason;

public:
                     CMyAppDialog(void){};
                    ~CMyAppDialog(void){};
   //--- main application dialog creation and destroy
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
  };

bool CMyAppDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
   m_deinit_reason=WRONG_VALUE;
   return(CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2));
  }
My panel breakout, when i change timeframe.
My panel breakout, when i change timeframe.
  • 2015.09.30
  • www.mql5.com
Dear Guys, I simply coding show panel on my chart. but My panel breakout when I change timeframe...
 
Mohammad Hossein Sadeghi:

I believe the best way is to create an instance of the class by 'new' keyword, define a pointer in global scope, create an instance of it in OnInit() by 'new' keyword and assign it to the pointer, then delete it in OnDeinit(), it is well described in the following post:

https://www.mql5.com/en/forum/64619/page2#comment_2052954

Another work around would be setting 'm_deinit_reason' to WRONG_VALUE by overriding CAppDialog::Create function virtually, since it is a public method of the class and it is the only function that calls CreateCommon, and then use the new derived class instead.

This is very good advice. I've found this fixes most issues with objects when switching charts causes errors. 

Reason: