Add files via upload

This commit is contained in:
amirghadiri1987
2025-02-07 19:12:13 +03:30
committed by GitHub
parent a9340e5d4e
commit 56b382609f
88 changed files with 274630 additions and 0 deletions
+385
View File
@@ -0,0 +1,385 @@
//+------------------------------------------------------------------+
//| Box.mqh |
//| Enrico Lambino |
//| www.mql5.com/en/users/iceron|
//+------------------------------------------------------------------+
#property copyright "Enrico Lambino"
#property link "www.mql5.com/en/users/iceron"
#include <Controls\WndClient.mqh>
#define CLASS_LAYOUT 999
#ifdef LAYOUT_BOX_DEBUG
#define COLOR_BOX_BORDER clrRed
#else
#define COLOR_BOX_BORDER clrNONE
#endif
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum LAYOUT_STYLE
{
LAYOUT_STYLE_VERTICAL,
LAYOUT_STYLE_HORIZONTAL
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum VERTICAL_ALIGN
{
VERTICAL_ALIGN_CENTER,
VERTICAL_ALIGN_CENTER_NOSIDES,
VERTICAL_ALIGN_TOP,
VERTICAL_ALIGN_BOTTOM
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum HORIZONTAL_ALIGN
{
HORIZONTAL_ALIGN_CENTER,
HORIZONTAL_ALIGN_CENTER_NOSIDES,
HORIZONTAL_ALIGN_LEFT,
HORIZONTAL_ALIGN_RIGHT
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CBox: public CWndClient
{
protected:
LAYOUT_STYLE m_layout_style;
VERTICAL_ALIGN m_vertical_align;
HORIZONTAL_ALIGN m_horizontal_align;
CSize m_min_size;
int m_controls_total;
int m_padding_top;
int m_padding_bottom;
int m_padding_left;
int m_padding_right;
int m_total_x;
int m_total_y;
public:
CBox();
~CBox();
virtual int Type() const
{
return CLASS_LAYOUT;
}
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 bool Pack();
void LayoutStyle(LAYOUT_STYLE style)
{
m_layout_style = style;
}
LAYOUT_STYLE LayoutStyle() const
{
return (m_layout_style);
}
void HorizontalAlign(const HORIZONTAL_ALIGN align)
{
m_horizontal_align = align;
}
HORIZONTAL_ALIGN HorizontalAlign() const
{
return (m_horizontal_align);
}
void VerticalAlign(const VERTICAL_ALIGN align)
{
m_vertical_align = align;
}
VERTICAL_ALIGN VerticalAlign() const
{
return (m_vertical_align);
}
void Padding(const int top, const int bottom, const int left, const int right,const int padding);
//void Padding(const int padding);
void PaddingTop(const int padding)
{
m_padding_top = padding;
}
int PaddingTop() const
{
return (m_padding_top);
}
void PaddingRight(const int padding)
{
m_padding_right = padding;
}
int PaddingRight() const
{
return (m_padding_right);
}
void PaddingBottom(const int padding)
{
m_padding_bottom = padding;
}
int PaddingBottom() const
{
return (m_padding_bottom);
}
void PaddingLeft(const int padding)
{
m_padding_left = padding;
}
int PaddingLeft() const
{
return (m_padding_left);
}
CSize GetMinSize() const
{
CSize sz;
sz.cx = m_min_size.cx + m_padding_left + m_padding_right;
sz.cy = m_min_size.cy + m_padding_top + m_padding_bottom;
return sz;
}
protected:
virtual void CheckControlSize(CWnd *control);
virtual void GetTotalControlsSize(void);
virtual bool GetSpace(int &x_space, int &y_space);
virtual bool Render(void);
virtual void Shift(CWnd *control, int &x, int &y, const int x_space, const int y_space);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::CBox():
m_layout_style(LAYOUT_STYLE_HORIZONTAL),
m_vertical_align(VERTICAL_ALIGN_CENTER),
m_horizontal_align(HORIZONTAL_ALIGN_CENTER),
m_controls_total(0),
m_padding_top(2),
m_padding_bottom(2),
m_padding_left(2),
m_padding_right(2),
m_total_x(0),
m_total_y(0)
{
m_min_size.cx = 0;
m_min_size.cy = 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::~CBox()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Create(const long chart, const string name, const int subwin,
const int x1, const int y1, const int x2, const int y2)
{
if(!CWndContainer::Create(chart, name, subwin, x1, y1, x2, y2))
return (false);
if(!CreateBack())
return (false);
if(!ColorBackground(CONTROLS_DIALOG_COLOR_CLIENT_BG))
return (false);
if(!ColorBorder(COLOR_BOX_BORDER))
return (false);
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Pack(void)
{
GetTotalControlsSize();
return (Render());
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::CheckControlSize(CWnd *control)
{
bool adjust = false;
CSize size = Size();
CSize control_size = control.Size();
if(control_size.cx > size.cx - (m_padding_left + m_padding_right))
{
control_size.cx = size.cx - (m_padding_left + m_padding_right);
adjust = true;
}
if(control_size.cy > size.cy - (m_padding_top + m_padding_bottom))
{
control_size.cy = size.cy - (m_padding_top + m_padding_bottom);
adjust = true;
}
if(adjust)
control.Size(control_size.cx, control_size.cy);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::GetTotalControlsSize(void)
{
m_total_x = 0;
m_total_y = 0;
m_controls_total = 0;
m_min_size.cx = 0;
m_min_size.cy = 0;
int total = ControlsTotal();
for(int i = 0; i < total; i++)
{
CWnd *control = Control(i);
if(control == NULL) continue;
if(control == &m_background) continue;
CheckControlSize(control);
if(control.Type() == CLASS_LAYOUT)
{
((CBox *)control).GetTotalControlsSize();
}
CSize control_size = control.Size();
if(m_min_size.cx < control_size.cx)
m_min_size.cx = control_size.cx;
if(m_min_size.cy < control_size.cy)
m_min_size.cy = control_size.cy;
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL) m_total_x += control_size.cx;
else m_total_x = MathMax(m_min_size.cx, m_total_x);
if(m_layout_style == LAYOUT_STYLE_VERTICAL) m_total_y += control_size.cy;
else m_total_y = MathMax(m_min_size.cy, m_total_y);
m_controls_total++;
}
CSize size = Size();
if(m_total_x > size.cx && m_layout_style == LAYOUT_STYLE_HORIZONTAL)
{
size.cx = m_total_x;
}
if(m_total_y > size.cy && m_layout_style == LAYOUT_STYLE_VERTICAL) // shrink
{
size.cy = m_total_y;
}
Size(size);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::GetSpace(int &x_space, int &y_space)
{
if(m_controls_total == 0)
return (true);
if(m_controls_total == 1)
{
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
m_horizontal_align = HORIZONTAL_ALIGN_CENTER;
if(m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
m_vertical_align = VERTICAL_ALIGN_CENTER;
}
CSize size = Size();
int x_space_total = 0;
int y_space_total = 0;
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL)
{
x_space_total = size.cx - (m_total_x + m_padding_left + m_padding_right);
y_space_total = size.cy - (m_min_size.cy + m_padding_top + m_padding_bottom);
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
x_space = x_space_total / (m_controls_total - 1);
else if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER)
x_space = x_space_total / (m_controls_total + 1);
else
x_space = x_space_total / m_controls_total;
if(m_vertical_align == VERTICAL_ALIGN_CENTER || m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
y_space = y_space_total / 2;
else
y_space = y_space_total;
}
else if(m_layout_style == LAYOUT_STYLE_VERTICAL)
{
x_space_total = size.cx - (m_min_size.cx + m_padding_left + m_padding_right);
y_space_total = size.cy - (m_total_y + m_padding_top + m_padding_bottom);
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER || m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
x_space = x_space_total / 2;
else
x_space = x_space_total;
if(m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
y_space = y_space_total / (m_controls_total - 1);
else if(m_vertical_align == VERTICAL_ALIGN_CENTER)
y_space = y_space_total / (m_controls_total + 1);
else
y_space = y_space_total / m_controls_total;
}
else
return (false);
if(x_space < 0) x_space = 0;
if(y_space < 0) y_space = 0;
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::Shift(CWnd *control, int &x, int &y, const int x_space, const int y_space)
{
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL)
x += x_space + control.Width();
else if(m_layout_style == LAYOUT_STYLE_VERTICAL)
y += y_space + control.Height();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Render(void)
{
int x_space = 0, y_space = 0;
if(!GetSpace(x_space, y_space))
return (false);
int x = Left() + m_padding_left +
((m_horizontal_align == HORIZONTAL_ALIGN_LEFT || m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES) ? 0 : x_space);
int y = Top() + m_padding_top +
((m_vertical_align == VERTICAL_ALIGN_TOP || m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES) ? 0 : y_space);
for(int j = 0; j < ControlsTotal(); j++)
{
CWnd *control = Control(j);
if(control == NULL)
continue;
if(control == GetPointer(m_background))
continue;
control.Move(x, y);
if(control.Type() == CLASS_LAYOUT)
{
CBox *container = control;
container.Pack();
}
if(j < ControlsTotal() - 1)
Shift(GetPointer(control), x, y, x_space, y_space);
}
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::Padding(const int top, const int right, const int bottom, const int left,const int padding)
{
m_padding_top = top;
m_padding_right = right;
m_padding_bottom = bottom;
m_padding_left = left;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// CBox::Padding(const int padding)
// {
// m_padding_top = padding;
// m_padding_right = padding;
// m_padding_bottom = padding;
// m_padding_left = padding;
// }
//+------------------------------------------------------------------+
+66
View File
@@ -0,0 +1,66 @@
//+------------------------------------------------------------------+
//| ComboBoxResizable.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//+------------------------------------------------------------------+
#include <Controls/ComboBox.mqh>
class ComboBoxResizable: public CComboBox
{
public:
virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override;
virtual bool OnResize(void) override
{
m_edit.Width(Width());
int x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_COMBO_BUTTON_X_OFF);
int y1 = (Height() - CONTROLS_BUTTON_SIZE) / 2;
m_drop.Move(Left() + x1, Top() + y1);
m_list.Width(Width());
return CWndContainer::OnResize();
}
virtual bool OnClickButton(void) override
{
// this is a hack to trigger resizing of elements in the list
// we need it because standard ListView is incorrectly coded in such a way
// that elements are resized only if vscroll is present
bool vs = m_list.VScrolled();
if(m_drop.Pressed())
{
m_list.VScrolled(true);
}
bool b = CComboBox::OnClickButton();
m_list.VScrolled(vs);
return b;
}
virtual bool Enable(void) override
{
m_edit.Show();
m_drop.Show();
return CComboBox::Enable();
}
virtual bool Disable(void) override
{
m_edit.Hide();
m_drop.Hide();
return CComboBox::Disable();
}
};
#define EXIT_ON_DISABLED \
if(!IsEnabled()) \
{ \
return false; \
}
EVENT_MAP_BEGIN(ComboBoxResizable)
EXIT_ON_DISABLED
ON_EVENT(ON_CLICK, m_drop, OnClickButton)
EVENT_MAP_END(CComboBox)
+153
View File
@@ -0,0 +1,153 @@
//+------------------------------------------------------------------+
//| Grid.mqh |
//| Enrico Lambino |
//| www.mql5.com/en/users/iceron|
//+------------------------------------------------------------------+
#property copyright "Enrico Lambino"
#property link "http://www.mql5.com"
#property strict
#include "Box.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CGrid: public CBox
{
protected:
int m_cols;
int m_rows;
int m_hgap;
int m_vgap;
CSize m_cell_size;
public:
CGrid();
CGrid(int rows, int cols, int hgap = 0, int vgap = 0);
~CGrid();
virtual int Type() const
{
return CLASS_LAYOUT;
}
virtual bool Init(int rows, int cols, int hgap = 0, int vgap = 0);
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 int Columns()
{
return (m_cols);
}
virtual void Columns(int cols)
{
m_cols = cols;
}
virtual int Rows()
{
return (m_rows);
}
virtual void Rows(int rows)
{
m_rows = rows;
}
virtual int HGap()
{
return (m_hgap);
}
virtual void HGap(int gap)
{
m_hgap = gap;
}
virtual int VGap()
{
return (m_vgap);
}
virtual void VGap(int gap)
{
m_vgap = gap;
}
virtual bool Pack();
protected:
virtual void CheckControlSize(CWnd *control);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGrid::CGrid()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGrid::CGrid(int rows, int cols, int hgap = 0, int vgap = 0)
{
Init(rows, cols, hgap, vgap);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGrid::~CGrid()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGrid::Init(int rows, int cols, int hgap = 0, int vgap = 0)
{
Columns(cols);
Rows(rows);
HGap(hgap);
VGap(vgap);
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGrid::Create(const long chart, const string name, const int subwin,
const int x1, const int y1, const int x2, const int y2)
{
return (CBox::Create(chart, name, subwin, x1, y1, x2, y2));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGrid::Pack()
{
CSize size = Size();
m_cell_size.cx = (size.cx - ((m_cols + 1) * m_hgap)) / m_cols;
m_cell_size.cy = (size.cy - ((m_rows + 1) * m_vgap)) / m_rows;
int x = Left(), y = Top();
int cnt = 0;
for(int i = 0; i < ControlsTotal(); i++)
{
CWnd *control = Control(i);
if(control == NULL)
continue;
if(control == GetPointer(m_background))
continue;
if(cnt == 0 || Right() - (x + m_cell_size.cx) < m_cell_size.cx + m_hgap)
{
if(cnt == 0)
y += m_vgap;
else
y += m_vgap + m_cell_size.cy;
x = Left() + m_hgap;
}
else
x += m_cell_size.cx + m_hgap;
CheckControlSize(control);
control.Move(x, y);
if(control.Type() == CLASS_LAYOUT)
{
CBox *container = control;
container.Pack();
}
cnt++;
}
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGrid::CheckControlSize(CWnd *control)
{
control.Size(m_cell_size.cx, m_cell_size.cy);
}
//+------------------------------------------------------------------+
+154
View File
@@ -0,0 +1,154 @@
//+------------------------------------------------------------------+
//| GridTk.mqh |
//| Enrico Lambino |
//| www.mql5.com/en/users/iceron|
//+------------------------------------------------------------------+
#property copyright "Enrico Lambino"
#property link "http://www.mql5.com"
#property strict
#include "Grid.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CGridConstraints: public CObject
{
protected:
CWnd *m_control;
int m_row;
int m_col;
int m_rowspan;
int m_colspan;
public:
CGridConstraints(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1);
~CGridConstraints();
CWnd *Control()
{
return (m_control);
}
int Row()
{
return (m_row);
}
int Column()
{
return (m_col);
}
int RowSpan()
{
return (m_rowspan);
}
int ColSpan()
{
return (m_colspan);
}
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridConstraints::CGridConstraints(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1)
{
m_control = control;
m_row = MathMax(0, row);
m_col = MathMax(0, column);
m_rowspan = MathMax(1, rowspan);
m_colspan = MathMax(1, colspan);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridConstraints::~CGridConstraints()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CGridTk: public CGrid
{
protected:
CArrayObj m_constraints;
public:
CGridTk();
~CGridTk();
bool Grid(CWnd *control, int row, int column, int rowspan, int colspan);
bool Pack();
CGridConstraints *GetGridConstraints(CWnd *control);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridTk::CGridTk(void)
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridTk::~CGridTk(void)
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGridTk::Grid(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1)
{
CGridConstraints *constraints = new CGridConstraints(control, row, column, rowspan, colspan);
if(!CheckPointer(constraints))
return (false);
if(!m_constraints.Add(constraints))
return (false);
return (Add(control));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGridTk::Pack()
{
CGrid::Pack();
CSize size = Size();
m_cell_size.cx = (size.cx - (m_cols + 1) * m_hgap) / m_cols;
m_cell_size.cy = (size.cy - (m_rows + 1) * m_vgap) / m_rows;
for(int i = 0; i < ControlsTotal(); i++)
{
int x = Left(), y = Top();
CWnd *control = Control(i);
if(control == NULL)
continue;
if(control == GetPointer(m_background))
continue;
CGridConstraints *constraints = GetGridConstraints(control);
if(constraints == NULL)
continue;
int column = constraints.Column();
int row = constraints.Row();
x += (column * m_cell_size.cx) + ((column + 1) * m_hgap);
y += (row * m_cell_size.cy) + ((row + 1) * m_vgap);
int colspan = constraints.ColSpan();
int rowspan = constraints.RowSpan();
control.Size(colspan * m_cell_size.cx + ((colspan - 1) * m_hgap), rowspan * m_cell_size.cy + ((rowspan - 1) * m_vgap));
control.Move(x, y);
if(control.Type() == CLASS_LAYOUT)
{
CBox *container = control;
container.Pack();
}
}
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridConstraints *CGridTk::GetGridConstraints(CWnd *control)
{
for(int i = 0; i < m_constraints.Total(); i++)
{
CGridConstraints *constraints = m_constraints.At(i);
CWnd *ctrl = constraints.Control();
if(ctrl == NULL)
continue;
if(ctrl == control)
return (constraints);
}
return (NULL);
}
//+------------------------------------------------------------------+
+337
View File
@@ -0,0 +1,337 @@
//+------------------------------------------------------------------+
//| MaximizableAppDialog.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//+------------------------------------------------------------------+
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#resource "res\\Expand2.bmp"
#resource "res\\size6.bmp"
#resource "res\\size10.bmp"
class MaximizableAppDialog: public CAppDialog
{
protected:
CBmpButton m_button_truemax;
CBmpButton m_button_size;
bool m_maximized;
CRect m_max_rect;
CSize m_size_limit;
bool m_sizing;
// window maximization
virtual bool CreateButtonMinMax(void) override;
virtual void OnClickButtonMinMax(void) override;
virtual void OnClickButtonTrueMax(void);
virtual void OnClickButtonSizeFixMe(void);
virtual void Expand(void);
virtual void Restore(void);
virtual void Minimize(void) override;
// window resizing
bool CreateButtonSize(void);
bool OnDialogSizeStart(void);
virtual bool OnDialogDragStart(void) override;
virtual bool OnDialogDragProcess(void) override;
virtual bool OnDialogDragEnd(void) override;
virtual void SelfAdjustment(const bool minimized = false) = 0;
public:
MaximizableAppDialog(): m_maximized(false), m_sizing(false) {}
virtual bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) override;
virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override;
virtual bool OnChartChange(const long &lparam, const double &dparam, const string &sparam);
void ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
void SetSizeLimit(const CSize &limit) { m_size_limit = limit; }
CSize GetSizeLimit() { return m_size_limit; }
};
void MaximizableAppDialog::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_CHART_CHANGE)
{
if(OnChartChange(lparam, dparam, sparam)) return;
}
CAppDialog::ChartEvent(id, lparam, dparam, sparam);
}
EVENT_MAP_BEGIN(MaximizableAppDialog)
ON_EVENT(ON_CLICK, m_button_truemax, OnClickButtonTrueMax)
ON_EVENT(ON_CLICK, m_button_size, OnClickButtonSizeFixMe)
ON_EVENT(ON_DRAG_START, m_button_size, OnDialogSizeStart)
ON_EVENT_PTR(ON_DRAG_PROCESS, m_drag_object, OnDialogDragProcess)
ON_EVENT_PTR(ON_DRAG_END, m_drag_object, OnDialogDragEnd)
EVENT_MAP_END(CAppDialog)
bool MaximizableAppDialog::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2)
{
// 1 * CONTROLS_BORDER_WIDTH - stays here, because the standard control library minimizes window
// when it's height is 1 pixel smaller than the entire chart height
m_max_rect.SetBound(0,
0,
(int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) - 0 * CONTROLS_BORDER_WIDTH,
(int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS) - 1 * CONTROLS_BORDER_WIDTH);
if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) return false;
if(!CreateButtonSize()) return false;
m_size_limit.cx = x2 - x1;
m_size_limit.cy = y2 - y1;
if(m_size_limit.cx >= m_max_rect.Width() || m_size_limit.cy >= m_max_rect.Height())
{
m_size_limit.cx = m_min_rect.Width() * 3;
m_size_limit.cy = m_min_rect.Height() * 7;
}
return true;
}
bool MaximizableAppDialog::CreateButtonMinMax(void) override
{
if(!CAppDialog::CreateButtonMinMax()) return false;
// add maximization button
int off = (m_panel_flag) ? 0 : 2 * CONTROLS_BORDER_WIDTH;
int x1 = Width() - off - 3 * (CONTROLS_BUTTON_SIZE + CONTROLS_DIALOG_BUTTON_OFF);
int y1 = off + CONTROLS_DIALOG_BUTTON_OFF;
int x2 = x1 + CONTROLS_BUTTON_SIZE;
int y2 = y1 + CONTROLS_BUTTON_SIZE;
if(!m_button_truemax.Create(m_chart_id, m_name + "TrueMax", m_subwin, x1, y1, x2, y2)) return false;
if(!m_button_truemax.BmpNames("::res\\Expand2.bmp", "::res\\Restore.bmp")) return false;
if(!CWndContainer::Add(m_button_truemax)) return false;
m_button_truemax.Locking(true);
m_button_truemax.Alignment(WND_ALIGN_RIGHT, 0, 0, off + 2 * CONTROLS_BUTTON_SIZE + 2 * CONTROLS_DIALOG_BUTTON_OFF, 0);
CaptionAlignment(WND_ALIGN_WIDTH, off, 0, off + 3 * (CONTROLS_BUTTON_SIZE + CONTROLS_DIALOG_BUTTON_OFF), 0);
return true;
}
bool MaximizableAppDialog::CreateButtonSize(void)
{
int off = (m_panel_flag) ? 0 : 2 * CONTROLS_BORDER_WIDTH;
int x1 = Width() - CONTROLS_BUTTON_SIZE + 1;
int y1 = Height() - CONTROLS_BUTTON_SIZE + 1;
int x2 = x1 + CONTROLS_BUTTON_SIZE - 1;
int y2 = y1 + CONTROLS_BUTTON_SIZE - 1;
if(!m_button_size.Create(m_chart_id, m_name + "Size", m_subwin, x1, y1, x2, y2)) return false;
if(!m_button_size.BmpNames("::res\\size6.bmp", "::res\\size10.bmp")) return false;
if(!CWndContainer::Add(m_button_size)) return false;
m_button_size.Alignment(WND_ALIGN_RIGHT|WND_ALIGN_BOTTOM, 0, 0, 0, 0);
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
return true;
}
void MaximizableAppDialog::OnClickButtonTrueMax(void)
{
if(m_button_truemax.Pressed())
Expand();
else
Restore();
SubwinOff();
}
// This is a hack. It's required because in minimized state sizing button somehow "overlaps"
// the close button and intercepts clicks on it (which prevents exit from minimized app).
// This happens despite the fact that the sizing button is hidden, disabled and assigned
// with minimal Z-order (checked out, then removed).
// Looks like a bug in the standard control library, specifically:
// In CWnd::OnMouseEvent there must be a line:
//
// if(!IS_ENABLED || !IS_VISIBLE) return false;
//
// but it's not there, so invisible, disabled and even background objects are processed
// in the same manner as all other objects. Specifically in CWndContainer::OnMouseEvent
// there is a reverse loop through all objects (it does _not_ respect Z-order anyhow).
void MaximizableAppDialog::OnClickButtonSizeFixMe(void)
{
if(m_minimized)
{
Destroy();
}
}
void MaximizableAppDialog::Expand(void)
{
m_maximized = true;
m_minimized = false;
m_button_minmax.Pressed(false);
Rebound(m_max_rect);
m_button_size.Hide();
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
if(!m_panel_flag)
{
m_caption.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
}
ClientAreaVisible(true);
SelfAdjustment();
}
//+------------------------------------------------------------------+
//| Restore dialog window |
//+------------------------------------------------------------------+
void MaximizableAppDialog::Restore(void)
{
m_maximized = false;
m_minimized = false;
m_button_minmax.Pressed(false);
m_button_size.Show();
m_button_size.StateFlagsSet(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
CAppDialog::Maximize();
if(!m_panel_flag)
{
m_caption.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
}
SelfAdjustment();
}
void MaximizableAppDialog::Minimize()
{
CAppDialog::Minimize();
m_button_size.Hide();
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
}
bool MaximizableAppDialog::OnChartChange(const long &lparam, const double &dparam, const string &sparam)
{
m_max_rect.SetBound(0, 0,
(int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) - 0 * CONTROLS_BORDER_WIDTH,
(int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS) - 1 * CONTROLS_BORDER_WIDTH);
if(m_maximized)
{
if(m_rect.Width() != m_max_rect.Width() || m_rect.Height() != m_max_rect.Height())
{
Rebound(m_max_rect);
SelfAdjustment();
m_chart.Redraw();
}
return true;
}
return false;
}
void MaximizableAppDialog::OnClickButtonMinMax(void)
{
CAppDialog::OnClickButtonMinMax();
m_button_truemax.Pressed(false);
m_maximized = false;
if(m_minimized)
{
m_button_size.Hide();
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
}
else
{
m_button_size.Show();
m_button_size.StateFlagsSet(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
}
if(!m_panel_flag)
{
m_caption.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
}
SelfAdjustment(m_minimized);
}
bool MaximizableAppDialog::OnDialogSizeStart(void)
{
if(m_drag_object == NULL)
{
m_drag_object = new CDragWnd;
if(m_drag_object == NULL) return false;
}
int x1 = m_button_size.Left() - CONTROLS_DRAG_SPACING;
int y1 = m_button_size.Top() - CONTROLS_DRAG_SPACING;
int x2 = m_button_size.Right() + CONTROLS_DRAG_SPACING;
int y2 = m_button_size.Bottom() + CONTROLS_DRAG_SPACING;
m_drag_object.Create(m_chart_id, "", m_subwin, x1, y1, x2, y2);
m_drag_object.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
CChart chart;
chart.Attach(m_chart_id);
m_drag_object.Limits(-CONTROLS_DRAG_SPACING, -CONTROLS_DRAG_SPACING,
chart.WidthInPixels() + CONTROLS_DRAG_SPACING,
chart.HeightInPixels(m_subwin) + CONTROLS_DRAG_SPACING);
chart.Detach();
m_drag_object.MouseX(m_button_size.MouseX());
m_drag_object.MouseY(m_button_size.MouseY());
m_drag_object.MouseFlags(m_button_size.MouseFlags());
m_sizing = true;
return true;
}
bool MaximizableAppDialog::OnDialogDragStart(void)
{
if(m_maximized) return false;
return CAppDialog::OnDialogDragStart();
}
//+------------------------------------------------------------------+
//| Continue dragging the dialog box |
//+------------------------------------------------------------------+
bool MaximizableAppDialog::OnDialogDragProcess(void)
{
if(!m_sizing) return CDialog::OnDialogDragProcess();
if(m_drag_object == NULL) return false;
int x = m_drag_object.Right() - Right() - CONTROLS_DRAG_SPACING;
int y = m_drag_object.Bottom() - Bottom() - CONTROLS_DRAG_SPACING;
// resize dialog
CRect r = Rect();
r.right += x;
r.bottom += y;
if(r.Width() < m_size_limit.cx) r.right = r.left + m_size_limit.cx;
if(r.Height() < m_size_limit.cy) r.bottom = r.top + m_size_limit.cy;
Rebound(r);
SelfAdjustment();
return true;
}
//+------------------------------------------------------------------+
//| End dragging the dialog box |
//+------------------------------------------------------------------+
bool MaximizableAppDialog::OnDialogDragEnd(void)
{
if(!m_sizing) return CDialog::OnDialogDragEnd();
if(m_drag_object != NULL)
{
m_button_size.MouseFlags(m_drag_object.MouseFlags());
delete m_drag_object;
m_drag_object = NULL;
}
m_norm_rect.SetBound(m_rect);
m_sizing = false;
SelfAdjustment();
return true;
}
+27
View File
@@ -0,0 +1,27 @@
//+------------------------------------------------------------------+
//| SpinEditResizable.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//+------------------------------------------------------------------+
#include <Controls/SpinEdit.mqh>
class SpinEditResizable: public CSpinEdit
{
public:
virtual bool OnResize(void) override
{
m_edit.Width(Width());
m_edit.Height(Height());
int x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_SPIN_BUTTON_X_OFF);
int y1 = (Height() - 2 * CONTROLS_SPIN_BUTTON_SIZE) / 2;
m_inc.Move(Left() + x1, Top() + y1);
x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_SPIN_BUTTON_X_OFF);
y1 = (Height() - 2 * CONTROLS_SPIN_BUTTON_SIZE) / 2 + CONTROLS_SPIN_BUTTON_SIZE;
m_dec.Move(Left() + x1, Top() + y1);
return CWndContainer::OnResize();
}
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB