//+------------------------------------------------------------------+ //| Dialog.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include #include #include #include #include #include //+------------------------------------------------------------------+ //| Resources | //+------------------------------------------------------------------+ #resource "/Include/Controls/res/Close.bmp" #resource "/Include/Controls/res/Restore.bmp" #resource "/Include/Controls/res/Turn.bmp" //#define CAPTION_TEXT_COLOR clrWhite //#define CAPTION_COLOR C'0,120,215' // #define CAPTION_TEXT_COLOR C'0x28,0x29,0x3B' // #define CAPTION_COLOR C'225,225,225' #define CAPTION_TEXT_COLOR C'0x28,0x4b,0x63' #define CAPTION_COLOR C'0xe2,0xec,0xf3' //+------------------------------------------------------------------+ //| Class CDialog1 | //| Usage: base class to create dialog boxes | //| and indicator panels | //+------------------------------------------------------------------+ class CDialog1 : public CWndContainer { private: //--- dependent controls //CPanel m_white_border; // the "white border" object CPanel m_background; // the background object CEdit m_caption; // the window title object //CCanvas m_caption; // Объект холста для вывода текста CBmpButton m_button_close; // the "Close" button object CWndClient m_client_area; // the client area object protected: //--- flags bool m_panel_flag; // the "panel in a separate window" flag //--- flags bool m_minimized; // "create in minimized state" flag //--- additional areas CRect m_min_rect; // minimal area coordinates CRect m_norm_rect; // normal area coordinates public: CDialog1(void); ~CDialog1(void); //--- 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); //--- chart event handler virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam); //--- set up string Caption(void) const { return(m_caption.Text()); } bool Caption(const string text) { return(m_caption.Text(text)); } //--- fill bool Add(CWnd *control); bool Add(CWnd &control); //--- methods for working with files virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); protected: //--- create dependent controls virtual bool CreateBackground(void); virtual bool CreateCaption(void); virtual bool CreateButtonClose(void); virtual bool CreateClientArea(void); //--- handlers of the dependent controls events virtual void OnClickCaption(void); virtual void OnClickButtonClose(void); //--- access properties of caption void CaptionAlignment(const int flags, const int left, const int top, const int right, const int bottom) { m_caption.Alignment(flags, left, top, right, bottom); } //--- access properties of client area bool ClientAreaVisible(const bool visible) { return(m_client_area.Visible(visible)); } int ClientAreaLeft(void) const { return(m_client_area.Left()); } int ClientAreaTop(void) const { return(m_client_area.Top()); } int ClientAreaRight(void) const { return(m_client_area.Right()); } int ClientAreaBottom(void) const { return(m_client_area.Bottom()); } int ClientAreaWidth(void) const { return(m_client_area.Width()); } int ClientAreaHeight(void) const { return(m_client_area.Height()); } //--- handlers of drag virtual bool OnDialogDragStart(void); virtual bool OnDialogDragProcess(void); virtual bool OnDialogDragEnd(void); }; //+------------------------------------------------------------------+ //| Common handler of events | //+------------------------------------------------------------------+ EVENT_MAP_BEGIN(CDialog1) ON_EVENT(ON_CLICK, m_button_close, OnClickButtonClose) //ON_EVENT(ON_CLICK, m_caption, OnClickCaption) //ON_EVENT(ON_DRAG_START, m_caption, OnDialogDragStart) //ON_EVENT_PTR(ON_DRAG_PROCESS, m_drag_object, OnDialogDragProcess) //ON_EVENT_PTR(ON_DRAG_END, m_drag_object, OnDialogDragEnd) EVENT_MAP_END(CWndContainer) //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CDialog1::CDialog1(void) : m_panel_flag(false), m_minimized(false) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CDialog1::~CDialog1(void) { } //+------------------------------------------------------------------+ //| Create a control | //+------------------------------------------------------------------+ bool CDialog1::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) { //--- call method of parent class if(!CWndContainer::Create(chart, name, subwin, x1, y1, x2, y2)) return(false); //--- create dependent controls if(!CreateBackground()) return(false); if(!CreateCaption()) return(false); if(!CreateButtonClose()) return(false); if(!CreateClientArea()) return(false); //--- set up additional areas m_norm_rect.SetBound(m_rect); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Add control to the client area (by pointer) | //+------------------------------------------------------------------+ bool CDialog1::Add(CWnd *control) { return(m_client_area.Add(control)); } //+------------------------------------------------------------------+ //| Add control to the client area (by reference) | //+------------------------------------------------------------------+ bool CDialog1::Add(CWnd &control) { return(m_client_area.Add(control)); } //+------------------------------------------------------------------+ //| Save | //+------------------------------------------------------------------+ bool CDialog1::Save(const int file_handle) { //--- check if(file_handle == INVALID_HANDLE) return(false); //--- save FileWriteStruct(file_handle, m_norm_rect); FileWriteInteger(file_handle, m_min_rect.left); FileWriteInteger(file_handle, m_min_rect.top); FileWriteInteger(file_handle, m_minimized); //--- result return(CWndContainer::Save(file_handle)); } //+------------------------------------------------------------------+ //| Load | //+------------------------------------------------------------------+ bool CDialog1::Load(const int file_handle) { if(file_handle == INVALID_HANDLE) return(false); //--- load if(!FileIsEnding(file_handle)) { FileReadStruct(file_handle, m_norm_rect); int left = FileReadInteger(file_handle); int top = FileReadInteger(file_handle); m_min_rect.Move(left, top); m_minimized = FileReadInteger(file_handle); } //--- result return(CWndContainer::Load(file_handle)); } //+------------------------------------------------------------------+ //| Create background | //+------------------------------------------------------------------+ bool CDialog1::CreateBackground(void) { int off = 0; //--- coordinates int x1 = off; int y1 = off; int x2 = Width() - off; int y2 = Height() - off; //--- create if(!m_background.Create(m_chart_id, m_name + "Back", m_subwin, x1, y1, x2, y2)) return(false); if(!m_background.ColorBackground(CAPTION_COLOR)) return(false); color border = CAPTION_COLOR; if(!m_background.ColorBorder(border)) return(false); if(!CWndContainer::Add(m_background)) return(false); m_background.Alignment(WND_ALIGN_CLIENT, off, off, off, off); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Create window title | //+------------------------------------------------------------------+ bool CDialog1::CreateCaption(void) { int off = 2; //--- coordinates int x1 = off; int y1 = off; int x2 = Width() - off; int y2 = y1 + CONTROLS_DIALOG_CAPTION_HEIGHT; //--- create if(!m_caption.Create(m_chart_id, m_name + "Caption", m_subwin, x1, y1, x2, y2)) return(false); if(!m_caption.Color(CAPTION_TEXT_COLOR)) return(false); if(!m_caption.ColorBackground(CAPTION_COLOR)) return(false); if(!m_caption.ColorBorder(CAPTION_COLOR)) return(false); //if(!m_caption.Font("Segoe UI")) // return(false); if(!m_caption.FontSize(10)) return(false); if(!m_caption.ReadOnly(true)) return(false); if(!m_caption.Text(m_name)) return(false); if(!CWndContainer::Add(m_caption)) return(false); m_caption.Alignment(WND_ALIGN_WIDTH, off, 0, off, 0); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Create the "Close" button | //+------------------------------------------------------------------+ bool CDialog1::CreateButtonClose(void) { int off = 2; //--- coordinates int x1 = Width() - off - (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; //--- create if(!m_button_close.Create(m_chart_id, m_name + "Close", m_subwin, x1, y1, x2, y2)) return(false); if(!m_button_close.BmpNames("/Include/Controls/res/Close.bmp")) return(false); if(!CWndContainer::Add(m_button_close)) return(false); m_button_close.Alignment(WND_ALIGN_RIGHT, 0, 0, off + CONTROLS_DIALOG_BUTTON_OFF, 0); //--- change caption //CaptionAlignment(WND_ALIGN_WIDTH, off, 0, off + (CONTROLS_BUTTON_SIZE + CONTROLS_DIALOG_BUTTON_OFF), 0); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Create client area | //+------------------------------------------------------------------+ bool CDialog1::CreateClientArea(void) { int off = 0; //--- coordinates int x1 = off; int y1 = off + CONTROLS_DIALOG_CAPTION_HEIGHT + 3; int x2 = Width() - (off); int y2 = Height() - (off); //--- create if(!m_client_area.Create(m_chart_id, m_name + "Client", m_subwin, x1, y1, x2, y2)) return(false); if(!m_client_area.ColorBackground(C'0xFA,0xFA,0xFA')) return(false); if(!m_client_area.ColorBorder(C'0xF7,0xF7,0xF7')) return(false); CWndContainer::Add(m_client_area); m_client_area.Alignment(WND_ALIGN_CLIENT, x1, y1, x1, x1); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Handler of click on the window title | //+------------------------------------------------------------------+ void CDialog1::OnClickCaption(void) { } //+------------------------------------------------------------------+ //| Handler of click on the "Close" button | //+------------------------------------------------------------------+ void CDialog1::OnClickButtonClose(void) { Visible(false); } //+------------------------------------------------------------------+ //| Start dragging the dialog box | //+------------------------------------------------------------------+ bool CDialog1::OnDialogDragStart(void) { if(m_drag_object == NULL) { m_drag_object = new CDragWnd; if(m_drag_object == NULL) return(false); } //--- calculate coordinates int x1 = Left() - CONTROLS_DRAG_SPACING; int y1 = Top() - CONTROLS_DRAG_SPACING; int x2 = Right() + CONTROLS_DRAG_SPACING; int y2 = Bottom() + CONTROLS_DRAG_SPACING; //--- create m_drag_object.Create(m_chart_id, "", m_subwin, x1, y1, x2, y2); m_drag_object.PropFlags(WND_PROP_FLAG_CAN_DRAG); //--- constraints 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(); //--- set mouse params m_drag_object.MouseX(m_caption.MouseX()); m_drag_object.MouseY(m_caption.MouseY()); m_drag_object.MouseFlags(m_caption.MouseFlags()); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Continue dragging the dialog box | //+------------------------------------------------------------------+ bool CDialog1::OnDialogDragProcess(void) { //--- checking if(m_drag_object == NULL) return(false); //--- calculate coordinates int x = m_drag_object.Left() + 50; int y = m_drag_object.Top() + 50; //--- move dialog Move(x, y); //--- succeed return(true); } //+------------------------------------------------------------------+ //| End dragging the dialog box | //+------------------------------------------------------------------+ bool CDialog1::OnDialogDragEnd(void) { if(m_drag_object != NULL) { m_caption.MouseFlags(m_drag_object.MouseFlags()); delete m_drag_object; m_drag_object = NULL; } //--- set up additional areas //if(m_minimized) // m_min_rect.SetBound(m_rect); //else m_norm_rect.SetBound(m_rect); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Class CAppDialog1 | //| Usage: main dialog box of MQL5 application | //+------------------------------------------------------------------+ class CAppDialog1 : public CDialog1 { private: //--- dependent controls CBmpButton m_button_minmax; // the "Minimize/Maximize" button object //--- variables string m_program_name; // name of program string m_instance_id; // unique string ID ENUM_PROGRAM_TYPE m_program_type; // type of program string m_indicator_name; int m_deinit_reason; //--- for mouse int m_subwin_Yoff; // subwindow Y offset CWnd* m_focused_wnd; // pointer to object that has mouse focus CWnd* m_top_wnd; // pointer to object that has priority over mouse events handling protected: CChart m_chart; // object to access chart public: CAppDialog1(void); ~CAppDialog1(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); virtual void Destroy(const int reason = REASON_PROGRAM); //--- chart event handler virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam); //--- dialog run bool Run(void); //--- chart events processing void ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam); //--- set up void Minimized(const bool flag) { m_minimized = flag; } //--- to save/restore state void IniFileSave(void); void IniFileLoad(void); virtual string IniFileName(void) const; virtual string IniFileExt(void) const { return(".dat"); } virtual bool Load(const int file_handle); virtual bool Save(const int file_handle); private: bool CreateCommon(const long chart, const string name, const int subwin); bool CreateExpert(const int x1, const int y1, const int x2, const int y2); bool CreateIndicator(const int x1, const int y1, const int x2, const int y2); protected: //--- create dependent controls virtual bool CreateButtonMinMax(void); //--- handlers of the dependent controls events virtual void OnClickButtonClose(void); virtual void OnClickButtonMinMax(void); //--- external event handlers virtual void OnAnotherApplicationClose(const long &lparam, const double &dparam, const string &sparam); //--- methods virtual bool Rebound(const CRect &rect); virtual void Minimize(void); virtual void Maximize(void); string CreateInstanceId(void); string ProgramName(void) const { return(m_program_name); } void SubwinOff(void); }; //+------------------------------------------------------------------+ //| Common handler of events | //+------------------------------------------------------------------+ EVENT_MAP_BEGIN(CAppDialog1) ON_EVENT(ON_CLICK, m_button_minmax, OnClickButtonMinMax) ON_EXTERNAL_EVENT(ON_APP_CLOSE, OnAnotherApplicationClose) EVENT_MAP_END(CDialog1) //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CAppDialog1::CAppDialog1(void) : m_program_type(WRONG_VALUE), m_deinit_reason(WRONG_VALUE), m_subwin_Yoff(0), m_focused_wnd(NULL), m_top_wnd(NULL) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CAppDialog1::~CAppDialog1(void) { } //+------------------------------------------------------------------+ //| Application dialog initialization function | //+------------------------------------------------------------------+ bool CAppDialog1::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) { if(!CreateCommon(chart, name, subwin)) return(false); //--- switch(m_program_type) { case PROGRAM_EXPERT: if(!CreateExpert(x1, y1, x2, y2)) return(false); break; case PROGRAM_INDICATOR: if(!CreateIndicator(x1, y1, x2, y2)) return(false); break; default: Print("CAppDialog1: invalid program type"); return(false); } //--- Title of dialog window if(!Caption(m_program_name)) return(false); //--- create dependent controls if(!CreateButtonMinMax()) return(false); //--- get subwindow offset SubwinOff(); //--- if flag is set, minimize the dialog if(m_minimized) Minimize(); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Initialize common area | //+------------------------------------------------------------------+ bool CAppDialog1::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; m_deinit_reason = WRONG_VALUE; //--- get unique ID m_instance_id = CreateInstanceId(); //--- initialize chart object m_chart.Attach(chart); //--- determine type of program m_program_type = (ENUM_PROGRAM_TYPE)MQLInfoInteger(MQL_PROGRAM_TYPE); //--- specify object and mouse events if(!m_chart.EventObjectCreate() || !m_chart.EventObjectDelete() || !m_chart.EventMouseMove()) { Print("CAppDialog1: object events specify error"); m_chart.Detach(); return(false); } //--- succeed return(true); } //+------------------------------------------------------------------+ //| Initialize in Expert Advisor | //+------------------------------------------------------------------+ bool CAppDialog1::CreateExpert(const int x1, const int y1, const int x2, const int y2) { //--- EA works only in main window m_subwin = 0; //--- geometry for the minimized state m_min_rect.SetBound(CONTROLS_DIALOG_MINIMIZE_LEFT, CONTROLS_DIALOG_MINIMIZE_TOP, CONTROLS_DIALOG_MINIMIZE_LEFT + CONTROLS_DIALOG_MINIMIZE_WIDTH, CONTROLS_DIALOG_MINIMIZE_TOP + CONTROLS_DIALOG_MINIMIZE_HEIGHT); //--- call method of the parent class if(!CDialog1::Create(m_chart.ChartId(), m_instance_id, m_subwin, x1, y1, x2, y2)) { Print("CAppDialog1: expert dialog create error"); m_chart.Detach(); return(false); } //--- succeed return(true); } //+------------------------------------------------------------------+ //| Initialize in Indicator | //+------------------------------------------------------------------+ bool CAppDialog1::CreateIndicator(const int x1, const int y1, const int x2, const int y2) { int width = m_chart.WidthInPixels(); //--- geometry for the minimized state m_min_rect.LeftTop(0, 0); m_min_rect.Width(width); m_min_rect.Height(CONTROLS_DIALOG_MINIMIZE_HEIGHT - 2 * CONTROLS_BORDER_WIDTH); //--- determine subwindow m_subwin = ChartWindowFind(); if(m_subwin == -1) { Print("CAppDialog1: find subwindow error"); m_chart.Detach(); return(false); } //--- int total = ChartIndicatorsTotal(m_chart.ChartId(), m_subwin); m_indicator_name = ChartIndicatorName(m_chart.ChartId(), m_subwin, total - 1); //--- if subwindow number is 0 (main window), then our program is //--- not an indicator panel, but is an indicator with built-in settings dialog //--- dialog of such an indicator should behave as an Expert Advisor dialog if(m_subwin == 0) return(CreateExpert(x1, y1, x2, y2)); //--- if subwindow number is not 0, then our program is an indicator panel //--- check if subwindow is not occupied by other indicators if(total != 1) { Print("CAppDialog1: subwindow busy"); ChartIndicatorDelete(m_chart.ChartId(), m_subwin, ChartIndicatorName(m_chart.ChartId(), m_subwin, total - 1)); m_chart.Detach(); return(false); } //--- resize subwindow by dialog height if(!IndicatorSetInteger(INDICATOR_HEIGHT, (y2 - y1) + 1)) { Print("CAppDialog1: subwindow resize error"); ChartIndicatorDelete(m_chart.ChartId(), m_subwin, ChartIndicatorName(m_chart.ChartId(), m_subwin, total - 1)); m_chart.Detach(); return(false); } //--- indicator short name m_indicator_name = m_program_name + IntegerToString(m_subwin); if(!IndicatorSetString(INDICATOR_SHORTNAME, m_indicator_name)) { Print("CAppDialog1: shortname error"); ChartIndicatorDelete(m_chart.ChartId(), m_subwin, ChartIndicatorName(m_chart.ChartId(), m_subwin, total - 1)); m_chart.Detach(); return(false); } //--- set flag m_panel_flag = true; //--- call method of the parent class if(!CDialog1::Create(m_chart.ChartId(), m_instance_id, m_subwin, 0, 0, width, y2 - y1)) { Print("CAppDialog1: indicator dialog create error"); ChartIndicatorDelete(m_chart.ChartId(), m_subwin, ChartIndicatorName(m_chart.ChartId(), m_subwin, total - 1)); m_chart.Detach(); return(false); } //--- succeed return(true); } //+------------------------------------------------------------------+ //| Application dialog deinitialization function | //+------------------------------------------------------------------+ void CAppDialog1::Destroy(const int reason) { //--- destroyed already? if(m_deinit_reason != WRONG_VALUE) return; //--- m_deinit_reason = reason; IniFileSave(); //--- detach chart object from chart m_chart.Detach(); //--- call parent destroy CDialog1::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(CONTROLS_SELF_MESSAGE, ON_APP_CLOSE, m_subwin, 0.0, m_program_name); } //+------------------------------------------------------------------+ //| Calculate subwindow offset | //+------------------------------------------------------------------+ void CAppDialog1::SubwinOff(void) { m_subwin_Yoff = m_chart.SubwindowY(m_subwin); } //+------------------------------------------------------------------+ //| Create the "Minimize/Maximize" button | //+------------------------------------------------------------------+ bool CAppDialog1::CreateButtonMinMax(void) { //--- succeed return(true); } //+------------------------------------------------------------------+ //| Charts event processing | //+------------------------------------------------------------------+ void CAppDialog1::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { int mouse_x = (int)lparam; int mouse_y = (int)dparam - m_subwin_Yoff; //--- separate mouse events from others switch(id) { case CHARTEVENT_CHART_CHANGE: //--- assumed that the CHARTEVENT_CHART_CHANGE event can handle only the application dialog break; case CHARTEVENT_OBJECT_CLICK: //--- we won't handle the CHARTEVENT_OBJECT_CLICK event, as we are working with the CHARTEVENT_MOUSE_MOVE events return; case CHARTEVENT_CUSTOM+ON_MOUSE_FOCUS_SET: //--- the CHARTEVENT_CUSTOM + ON_MOUSE_FOCUS_SET event if(CheckPointer(m_focused_wnd) != POINTER_INVALID) { //--- if there is an element with focus, try to take its focus away if(!m_focused_wnd.MouseFocusKill(lparam)) return; } m_focused_wnd = ControlFind(lparam); return; case CHARTEVENT_CUSTOM+ON_BRING_TO_TOP: m_top_wnd = ControlFind(lparam); return; case CHARTEVENT_MOUSE_MOVE: //--- the CHARTEVENT_MOUSE_MOVE event if(CheckPointer(m_top_wnd) != POINTER_INVALID) { //--- if a priority element already exists, pass control to it if(m_top_wnd.OnMouseEvent(mouse_x, mouse_y, (int)StringToInteger(sparam))) { //--- event handled m_chart.Redraw(); return; } } if(OnMouseEvent(mouse_x, mouse_y, (int)StringToInteger(sparam))) m_chart.Redraw(); return; default: //--- call event processing and redraw chart if event handled if(OnEvent(id, lparam, dparam, sparam)) m_chart.Redraw(); return; } //--- if event was not handled, try to handle the CHARTEVENT_CHART_CHANGE event if(id == CHARTEVENT_CHART_CHANGE) { //--- if subwindow number is not 0, and dialog subwindow has changed its number, then restart if(m_subwin != 0 && m_subwin != ChartWindowFind()) { long fiction = 1; OnAnotherApplicationClose(fiction, dparam, sparam); } //--- if chart width is less that dialog width, and subwindow number is not 0, try to modify dialog width if(m_chart.WidthInPixels() != Width() && m_subwin != 0) { Width(m_chart.WidthInPixels()); m_chart.Redraw(); } //--- get subwindow offset SubwinOff(); return; } } //+------------------------------------------------------------------+ //| Run application | //+------------------------------------------------------------------+ bool CAppDialog1::Run(void) { //--- redraw chart for dialog invalidate m_chart.Redraw(); //--- here we begin to assign IDs to controls if(Id(m_subwin * CONTROLS_MAXIMUM_ID) > CONTROLS_MAXIMUM_ID) { Print("CAppDialog1: too many objects"); return(false); } //--- succeed return(true); } //+------------------------------------------------------------------+ //| Stop application | //+------------------------------------------------------------------+ void CAppDialog1::OnClickButtonClose(void) { //--- destroy application Destroy(); } //+------------------------------------------------------------------+ //| Handler of click on the "Minimize/Maximize" button | //+------------------------------------------------------------------+ void CAppDialog1::OnClickButtonMinMax(void) { if(m_button_minmax.Pressed()) Minimize(); else Maximize(); //--- get subwindow offset SubwinOff(); } //+------------------------------------------------------------------+ //| Resize | //+------------------------------------------------------------------+ bool CAppDialog1::Rebound(const CRect &rect) { if(!Move(rect.LeftTop())) return(false); if(!Size(rect.Size())) return(false); //--- resize subwindow if(m_program_type == PROGRAM_INDICATOR && !IndicatorSetInteger(INDICATOR_HEIGHT, rect.Height() + 1)) { Print("CAppDialog1: subwindow resize error"); return(false); } //--- succeed return(true); } //+------------------------------------------------------------------+ //| Minimize dialog window | //+------------------------------------------------------------------+ void CAppDialog1::Minimize(void) { //--- set flag m_minimized = true; //--- resize Rebound(m_min_rect); //--- hide client area ClientAreaVisible(false); } //+------------------------------------------------------------------+ //| Restore dialog window | //+------------------------------------------------------------------+ void CAppDialog1::Maximize(void) { //--- reset flag m_minimized = false; //--- resize Rebound(m_norm_rect); //--- show client area ClientAreaVisible(true); } //+------------------------------------------------------------------+ //| Create unique prefix for object names | //+------------------------------------------------------------------+ string CAppDialog1::CreateInstanceId(void) { return(IntegerToString(rand(), 5, '0')); } //+------------------------------------------------------------------+ //| Handler of the ON_APP_CLOSE external event | //+------------------------------------------------------------------+ void CAppDialog1::OnAnotherApplicationClose(const long &lparam, const double &dparam, const string &sparam) { //--- exit if we are in the main window if(m_subwin == 0) return; //--- exit if external program was closed in main window if(lparam == 0) return; //--- get subwindow offset SubwinOff(); //--- exit if external program was closed in subwindow with greater number if(lparam >= m_subwin) return; //--- after all the checks we must change the subwindow //--- get the new number of subwindow m_subwin = ChartWindowFind(); //--- change short name m_indicator_name = m_program_name + IntegerToString(m_subwin); IndicatorSetString(INDICATOR_SHORTNAME, m_indicator_name); //--- change dialog title Caption(m_program_name); //--- reassign IDs Run(); } //+------------------------------------------------------------------+ //| Save the current state of the program | //+------------------------------------------------------------------+ void CAppDialog1::IniFileSave(void) { string filename = IniFileName() + IniFileExt(); int handle = FileOpen(filename, FILE_WRITE | FILE_BIN | FILE_ANSI); //--- if(handle != INVALID_HANDLE) { Save(handle); FileClose(handle); } } //+------------------------------------------------------------------+ //| Read the previous state of the program | //+------------------------------------------------------------------+ void CAppDialog1::IniFileLoad(void) { string filename = IniFileName() + IniFileExt(); int handle = FileOpen(filename, FILE_READ | FILE_BIN | FILE_ANSI); //--- if(handle != INVALID_HANDLE) { Load(handle); FileClose(handle); } } //+------------------------------------------------------------------+ //| Generate the filename | //+------------------------------------------------------------------+ string CAppDialog1::IniFileName(void) const { string name; //--- name = (m_indicator_name != NULL) ? m_indicator_name : m_program_name; //--- name += "_" + Symbol(); name += "_Ini"; //--- return(name); } //+------------------------------------------------------------------+ //| Load data | //+------------------------------------------------------------------+ bool CAppDialog1::Load(const int file_handle) { if(CDialog1::Load(file_handle)) { if(m_minimized) { m_button_minmax.Pressed(true); Minimize(); } else { m_button_minmax.Pressed(false); Maximize(); } int prev_deinit_reason = FileReadInteger(file_handle); if(prev_deinit_reason == REASON_CHARTCLOSE || prev_deinit_reason == REASON_CLOSE) { //--- if the previous time program ended after closing the chart window, //--- delete object left since the last start of the program string prev_instance_id = IntegerToString(FileReadInteger(file_handle), 5, '0'); if(prev_instance_id != m_instance_id) { long chart_id = m_chart.ChartId(); int total = ObjectsTotal(chart_id, m_subwin); for(int i = total - 1; i >= 0; i--) { string obj_name = ObjectName(chart_id, i, m_subwin); if(StringFind(obj_name, prev_instance_id) == 0) ObjectDelete(chart_id, obj_name); } } } return(true); } //--- failure return(false); } //+------------------------------------------------------------------+ //| Save data | //+------------------------------------------------------------------+ bool CAppDialog1::Save(const int file_handle) { if(CDialog1::Save(file_handle)) { FileWriteInteger(file_handle, m_deinit_reason); FileWriteInteger(file_handle, (int)StringToInteger(m_instance_id)); return(true); } //--- failure return(false); } //+------------------------------------------------------------------+