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.
|
|
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);
}
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()); }
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.
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)); }
- 2015.09.30
- www.mql5.com
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.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
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