473 lines
16 KiB
MQL5
473 lines
16 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| WndContainer.mqh |
| |||
//| Copyright 2000-2025, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#include "Wnd.mqh"
| |||
#include <Arrays\ArrayObj.mqh>
| |||
//+------------------------------------------------------------------+
| |||
//| Class CWndContainer |
| |||
//| Usage: base class of the combined control |
| |||
//+------------------------------------------------------------------+
| |||
class CWndContainer : public CWnd
| |||
{
| |||
private:
| |||
CArrayObj m_controls; // container of the control
| |||
| |||
public:
| |||
CWndContainer(void);
| |||
~CWndContainer(void);
| |||
//--- release memory
| |||
virtual void Destroy(const int reason=0);
| |||
//--- chart event handler
| |||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
| |||
virtual bool OnMouseEvent(const int x,const int y,const int flags);
| |||
//--- access the contents of container
| |||
int ControlsTotal(void) const { return(m_controls.Total()); }
| |||
CWnd* Control(const int ind) const { return(dynamic_cast<CWnd *>(m_controls.At(ind))); }
| |||
virtual CWnd* ControlFind(const long id);
| |||
//--- for mouse cursor focus
| |||
virtual bool MouseFocusKill(const long id=-1);
| |||
//--- fill
| |||
bool Add(CWnd *control);
| |||
bool Add(CWnd &control);
| |||
//--- underflowing
| |||
bool Delete(CWnd *control);
| |||
bool Delete(CWnd &control);
| |||
//--- geometry
| |||
virtual bool Move(const int x,const int y);
| |||
virtual bool Move(const CPoint &point);
| |||
virtual bool Shift(const int dx,const int dy);
| |||
//--- ID
| |||
virtual long Id(const long id);
| |||
long Id(void) const { return(CWnd::Id()); }
| |||
//--- state
| |||
virtual bool Enable(void);
| |||
virtual bool Disable(void);
| |||
virtual bool Show(void);
| |||
virtual bool Hide(void);
| |||
//--- methods for working with files
| |||
virtual bool Save(const int file_handle);
| |||
virtual bool Load(const int file_handle);
| |||
| |||
protected:
| |||
//--- internal event handlers
| |||
virtual bool OnResize(void);
| |||
virtual bool OnActivate(void);
| |||
virtual bool OnDeactivate(void);
| |||
};
| |||
//+------------------------------------------------------------------+
| |||
//| Common handler of chart events |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
| |||
{
| |||
//--- if an object is being dragged, pass control to the special drag object
| |||
if(m_drag_object!=NULL && m_drag_object.OnEvent(id,lparam,dparam,sparam))
| |||
return(true);
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=total-1;i>=0;i--)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
if(control.OnEvent(id,lparam,dparam,sparam))
| |||
return(true);
| |||
}
| |||
//--- not handled
| |||
return(false);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Common handler of mouse events |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::OnMouseEvent(const int x,const int y,const int flags)
| |||
{
| |||
if(!IS_VISIBLE)
| |||
return(false);
| |||
//--- if an object is being dragged, pass control to the special drag object
| |||
if(m_drag_object!=NULL && m_drag_object.OnMouseEvent(x,y,flags))
| |||
return(true);
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=total-1;i>=0;i--)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
if(control.OnMouseEvent(x,y,flags))
| |||
return(true);
| |||
}
| |||
//--- call of the method of the parent class
| |||
return(CWnd::OnMouseEvent(x,y,flags));
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Constructor |
| |||
//+------------------------------------------------------------------+
| |||
CWndContainer::CWndContainer(void)
| |||
{
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Destructor |
| |||
//+------------------------------------------------------------------+
| |||
CWndContainer::~CWndContainer(void)
| |||
{
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Delete group of controls |
| |||
//+------------------------------------------------------------------+
| |||
void CWndContainer::Destroy(const int reason)
| |||
{
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(0);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
control.Destroy();
| |||
m_controls.Delete(0);
| |||
}
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Find control by specified ID |
| |||
//+------------------------------------------------------------------+
| |||
CWnd* CWndContainer::ControlFind(const long id)
| |||
{
| |||
CWnd *result=CWnd::ControlFind(id);
| |||
//---
| |||
if(result!=NULL)
| |||
return(result);
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
result=control.ControlFind(id);
| |||
if(result!=NULL)
| |||
break;
| |||
}
| |||
//--- return the result
| |||
return(result);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Remove the mouse focus from control |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::MouseFocusKill(const long id=-1)
| |||
{
| |||
if(!IS_ACTIVE)
| |||
return(false);
| |||
Deactivate();
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
control.MouseFocusKill();
| |||
}
| |||
//--- succeed
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Add control to the group (by pointer) |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Add(CWnd *control)
| |||
{
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
return(false);
| |||
//--- correct the coordinates of added control
| |||
control.Shift(Left(),Top());
| |||
//--- "projecting" the group flag "visibility" to the added element
| |||
if(IS_VISIBLE && control.IsVisible())
| |||
{
| |||
//--- element will be "visible" only if the group is "visible" and the element is completely "within" this group
| |||
control.Visible(Contains(control));
| |||
}
| |||
else
| |||
control.Hide();
| |||
//--- "projecting" the group flag "enabled" to the added element
| |||
if(IS_ENABLED)
| |||
control.Enable();
| |||
else
| |||
control.Disable();
| |||
//--- adding
| |||
return(m_controls.Add(control));
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Add control to the group (by reference) |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Add(CWnd &control)
| |||
{
| |||
//--- add by pointer
| |||
return(Add((CWnd*)GetPointer(control)));
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Delete control from the group (by pointer) |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Delete(CWnd *control)
| |||
{
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
return(false);
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *pointer=Control(i);
| |||
//--- check of pointer
| |||
if(pointer==NULL)
| |||
continue;
| |||
//--- delete item from group
| |||
if(pointer==control)
| |||
return(m_controls.Delete(i));
| |||
}
| |||
//--- failure
| |||
return(false);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Delete control from the group (by reference) |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Delete(CWnd &control)
| |||
{
| |||
//--- delete by pointer
| |||
return(Delete((CWnd*)GetPointer(control)));
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Absolute movement of the controls group |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Move(const int x,const int y)
| |||
{
| |||
//--- relative movement
| |||
return(Shift(x-Left(),y-Top()));
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Absolute movement of the controls group |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Move(const CPoint &point)
| |||
{
| |||
//--- relative movement
| |||
return(Shift(point.x-Left(),point.y-Top()));
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Relative movement of the controls group |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Shift(const int dx,const int dy)
| |||
{
| |||
//--- call of the method of the parent class
| |||
if(!CWnd::Shift(dx,dy)) return(false);
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
//--- move the group item
| |||
control.Shift(dx,dy);
| |||
}
| |||
//--- succeed
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Set ID of control |
| |||
//+------------------------------------------------------------------+
| |||
long CWndContainer::Id(const long id)
| |||
{
| |||
//--- reserve ID for container
| |||
long id_used=1;
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
id_used+=control.Id(id+id_used);
| |||
}
| |||
m_id=id;
| |||
//--- return number of used IDs
| |||
return(id_used);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Enables event handling by the group of controls |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Enable(void)
| |||
{
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
control.Enable();
| |||
}
| |||
//--- call of the method of the parent class
| |||
return(CWnd::Enable());
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Disables event handling by the group of controls |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Disable(void)
| |||
{
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
control.Disable();
| |||
}
| |||
//--- call of the method of the parent class
| |||
return(CWnd::Disable());
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Makes the group of controls visible |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Show(void)
| |||
{
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
control.Show();
| |||
}
| |||
//--- call of the method of the parent class
| |||
return(CWnd::Show());
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Makes the group of controls hidden |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Hide(void)
| |||
{
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
control.Hide();
| |||
}
| |||
//--- call of the method of the parent class
| |||
return(CWnd::Hide());
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Handler of resizing |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::OnResize()
| |||
{
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
if(!control.Align(Rect()))
| |||
return(false);
| |||
}
| |||
//--- handled
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Handler of activating the group of controls |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::OnActivate(void)
| |||
{
| |||
if(IS_ACTIVE)
| |||
return(false);
| |||
Activate();
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
control.Activate();
| |||
}
| |||
//--- handled
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Handler of deactivating the group of controls |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::OnDeactivate(void)
| |||
{
| |||
if(!IS_ACTIVE)
| |||
return(false);
| |||
Deactivate();
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
control.Deactivate();
| |||
}
| |||
//--- handled
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Save |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Save(const int file_handle)
| |||
{
| |||
bool result=true;
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
result&=control.Save(file_handle);
| |||
}
| |||
//--- result
| |||
return(result);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Load |
| |||
//+------------------------------------------------------------------+
| |||
bool CWndContainer::Load(const int file_handle)
| |||
{
| |||
bool result=true;
| |||
//--- loop by elements of group
| |||
int total=m_controls.Total();
| |||
for(int i=0;i<total;i++)
| |||
{
| |||
CWnd *control=Control(i);
| |||
//--- check of pointer
| |||
if(control==NULL)
| |||
continue;
| |||
result&=control.Load(file_handle);
| |||
}
| |||
//--- result
| |||
return(result);
| |||
}
| |||
//+------------------------------------------------------------------+
|