EasyAndFastMod/WndEvents.mqh
2026-01-15 07:23:17 -05:00

1786 lines
142 KiB
MQL5

//+------------------------------------------------------------------+
//| WndEvents.mqh |
//| Copyright 2015, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "Defines.mqh"
#include "WndContainer.mqh"
//+------------------------------------------------------------------+
//| Класс для обработки событий |
//+------------------------------------------------------------------+
class CWndEvents : public CWndContainer {
protected:
//--- Экземпляр класса для управления графиком
CChart m_chart;
//--- Идентификатор и номер окна графика
long m_chart_id;
int m_subwin;
//--- Имя программы
string m_program_name;
//--- Короткое имя индикатора
string m_indicator_shortname;
//--- Индекс активного окна
int m_active_window_index;
//--- Хэндл подокна эксперта
int m_subwindow_handle;
//--- Имя подокна эксперта
string m_subwindow_shortname;
//--- Количество подокон на графике после установки подокна эксперта
int m_subwindows_total;
//---
private:
//--- Параметры событий
int m_id;
long m_lparam;
double m_dparam;
string m_sparam;
//---
public:
CWndEvents(void);
~CWndEvents(void);
//--- Виртуальный обработчик события графика
virtual void OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {}
//--- Таймер
void OnTimerEvent(void);
//---
public:
//--- Обработчики событий графика
void ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
//---
public:
//--- Возвращает индекс активированного окна
int GetActiveWindowIndex(void) {
return(m_active_window_index);
}
//---
private:
void ChartEventCustom(void);
void ChartEventClick(void);
void ChartEventMouseMove(void);
void ChartEventObjectClick(void);
void ChartEventEndEdit(void);
void ChartEventChartChange(void);
//--- Проверка событий в элементах управления
void CheckElementsEvents(void);
//--- Определение номера подокна
void DetermineSubwindow(void);
//--- Удалить подокно эксперта
void DeleteExpertSubwindow(void);
//--- Проверка и обновление номера окна эксперта
void CheckExpertSubwindowNumber(void);
//--- Проверка и обновление номера окна индикатора
void CheckSubwindowNumber(void);
//--- Изменение размеров заблокированной главной формы
void ResizeLockedWindow(void);
//--- Инициализация параметров событий
void InitChartEventsParams(const int id, const long lparam, const double dparam, const string sparam);
//--- Перемещение окна
void MovingWindow(const bool moving_mode = false);
//--- Проверка событий всех элементов по таймеру
void CheckElementsEventsTimer(void);
//--- Установка состояния графика
void SetChartState(void);
//---
protected:
//--- Удаление интерфейса
void Destroy(void);
//--- Перерисовка окна
void ResetWindow(void);
//---
public:
//--- Инициализация ядра
void InitializeCore(void);
//--- Завершение создания GUI
void CompletedGUI(void);
//--- Обновление положения элементов
void Moving(void);
//---
protected:
//--- Скрытие всех элементов
void Hide(void);
//--- Показ элементов указанного окна
void Show(const uint window_index);
//--- Восстановление приоритетов на нажатие левой кнопкой мыши
void SetZorders(void);
//--- Перерисовка элементов
void Update(const bool redraw = false);
//--- Перемещает всплывающие подсказки на верхний слой
void ResetTooltips(void);
//--- Показывает элементы только выделенных вкладок
void ShowTabElements(const uint window_index);
//--- Устанавливает состояние доступности элементов
void SetAvailable(const uint window_index, const bool state);
//--- Формирует массив элементов с таймером
void FormTimerElementsArray(void);
//--- Формирует массив доступных элементов
void FormAvailableElementsArray(void);
//--- Формирует массив элементов с авто-ресайзом (X)
void FormAutoXResizeElementsArray(void);
//--- Формирует массив элементов с авто-ресайзом (Y)
void FormAutoYResizeElementsArray(void);
//---
private:
//--- Перетаскивание формы завершено
bool OnWindowEndDrag(void);
//--- Сворачивание/разворачивание формы
bool OnWindowCollapse(void);
bool OnWindowExpand(void);
//--- Обработка изменения размеров окна
bool OnWindowChangeXSize(void);
bool OnWindowChangeYSize(void);
//--- Включение/отключение всплывающих подсказок
bool OnWindowTooltips(void);
//--- Скрытие всех контекстных меню от пункта инициатора
bool OnHideBackContextMenus(void);
//--- Скрытие всех контекстных меню
bool OnHideContextMenus(void);
//--- Открытие диалогового окна
bool OnOpenDialogBox(void);
//--- Закрытие диалогового окна
bool OnCloseDialogBox(void);
//--- Определение доступных элементов
bool OnSetAvailable(void);
//--- Определение заблокированных элементов
bool OnSetLocked(void);
//--- Изменения в графическом интерфейсе
bool OnChangeGUI(void);
//---
private:
//--- Возвращает индекс активированного окна
int ActivatedWindowIndex(void);
//--- Возвращает индекс активированного главного меню
int ActivatedMenuBarIndex(void);
//--- Возвращает индекс активированного пункта меню
int ActivatedMenuItemIndex(void);
//--- Возвращает индекс активированной сдвоенной кнопки
int ActivatedSplitButtonIndex(void);
//--- Возвращает индекс активированного комбо-бокса
int ActivatedComboBoxIndex(void);
//--- Возвращает индекс активированного выпадающего календаря
int ActivatedDropCalendarIndex(void);
//--- Возвращает индекс активированной полосы прокрутки
int ActivatedScrollIndex(void);
//--- Возвращает индекс активированной таблицы
int ActivatedTableIndex(void);
//--- Возвращает индекс активированного слайдера
int ActivatedSliderIndex(void);
//--- Возвращает индекс активированного древовидного списка
int ActivatedTreeViewIndex(void);
//--- Возвращает индекс активированного стандартного графика
int ActivatedSubChartIndex(void);
//--- Проверяет и делает контекстное меню доступным
void CheckContextMenu(CMenuItem &object);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CWndEvents::CWndEvents(void) : m_chart_id(::ChartID()),
m_subwin(0),
m_active_window_index(0),
m_indicator_shortname(""),
m_program_name(PROGRAM_NAME),
m_subwindow_handle(INVALID_HANDLE),
m_subwindow_shortname(""),
m_subwindows_total(1) {
//--- Выйти, если это не реал-тайм
if(::MQLInfoInteger(MQL_TESTER) || ::MQLInfoInteger(MQL_FRAME_MODE))
return;
//--- Инициализация ядра
InitializeCore();
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CWndEvents::~CWndEvents(void) {
//--- Выйти, если это не реал-тайм
if(::MQLInfoInteger(MQL_TESTER))
return;
//--- Удалить таймер
::EventKillTimer();
//--- Включим управление
m_chart.MouseScroll(true);
m_chart.SetInteger(CHART_DRAG_TRADE_LEVELS, true);
//--- Отключим слежение за событиями мыши
m_chart.EventMouseMove(false);
//--- Включим вызов командной строки для клавиш Space и Enter
m_chart.SetInteger(CHART_QUICK_NAVIGATION, true);
//--- Отсоединиться от графика
m_chart.Detach();
//--- Удалим подокно индикатора
DeleteExpertSubwindow();
//--- Стереть коммент
::Comment("");
}
//+------------------------------------------------------------------+
//| Инициализация ядра |
//+------------------------------------------------------------------+
void CWndEvents::InitializeCore(void) {
//--- Включим таймер, если вне тестера
if(!::MQLInfoInteger(MQL_TESTER)) {
::ResetLastError();
bool is_timer =::EventSetMillisecondTimer(TIMER_STEP_MSC);
}
//--- Получим ID текущего графика
m_chart.Attach();
//--- Включим слежение за событиями мыши
m_chart.EventMouseMove(true);
//--- Отключим вызов командной строки для клавиш Space и Enter
m_chart.SetInteger(CHART_QUICK_NAVIGATION, false);
//--- Определение номера подокна
DetermineSubwindow();
}
//+------------------------------------------------------------------+
//| Инициализация событийных переменных |
//+------------------------------------------------------------------+
void CWndEvents::InitChartEventsParams(const int id, const long lparam, const double dparam, const string sparam) {
m_id = id;
m_lparam = lparam;
m_dparam = dparam;
m_sparam = sparam;
//--- Получим параметры мыши
m_mouse.OnEvent(id, lparam, dparam, sparam);
}
//+------------------------------------------------------------------+
//| Обработка событий программы |
//+------------------------------------------------------------------+
void CWndEvents::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {
//--- Если массив пуст, выйдем
if(CWndContainer::WindowsTotal() < 1) {
//--- Направление события в файл приложения
OnEvent(id, lparam, dparam, sparam);
return;
}
//--- Инициализация полей параметров событий
InitChartEventsParams(id, lparam, dparam, sparam);
//--- Пользовательские события
ChartEventCustom();
//--- Проверка событий элементов интерфейса
CheckElementsEvents();
//--- Событие перемещения мыши
ChartEventMouseMove();
//--- Событие изменения свойств графика
ChartEventChartChange();
}
//+------------------------------------------------------------------+
//| Проверка событий элементов управления |
//+------------------------------------------------------------------+
void CWndEvents::CheckElementsEvents(void) {
//--- Обработка события перемещения курсора мыши
if(m_id == CHARTEVENT_MOUSE_MOVE) {
//--- Выйти, если форма находится в другом подокне графика
if(!m_windows[m_active_window_index].CheckSubwindowNumber())
return;
//--- Проверяем только доступные элементы
int available_elements_total = CWndContainer::AvailableElementsTotal(m_active_window_index);
for(int e = 0; e < available_elements_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_available_elements[e];
//--- Проверка фокуса над элементами
el.CheckMouseFocus();
//--- Обработка события
el.OnEvent(m_id, m_lparam, m_dparam, m_sparam);
}
}
//--- Все события, кроме перемещения курсора мыши
else {
int elements_total = CWndContainer::ElementsTotal(m_active_window_index);
for(int e = 0; e < elements_total; e++) {
//--- Проверяем только доступные элементы
CElement *el = m_wnd[m_active_window_index].m_elements[e];
if(!el.IsVisible() || !el.CElementBase::IsAvailable() || el.CElementBase::IsLocked())
continue;
//--- Обработка события в обработчике элемента
el.OnEvent(m_id, m_lparam, m_dparam, m_sparam);
}
}
//--- Направление события в файл приложения
OnEvent(m_id, m_lparam, m_dparam, m_sparam);
}
//+------------------------------------------------------------------+
//| Проверка пользовательских событий (CHARTEVENT_CUSTOM) |
//+------------------------------------------------------------------+
void CWndEvents::ChartEventCustom(void) {
//--- Если сигнал на определение доступных элементов
if(OnSetAvailable())
return;
//--- Если сигнал об изменении в графическом интерфейсе
if(OnChangeGUI())
return;
//--- Если сигнал на определение заблокированных элементов
if(OnSetLocked())
return;
//--- Если сигнал об окончании перетаскивания формы
if(OnWindowEndDrag())
return;
//--- Если сигнал свернуть форму
if(OnWindowCollapse())
return;
//--- Если сигнал развернуть форму
if(OnWindowExpand())
return;
//--- Если сигнал изменить размер элементов по оси X
if(OnWindowChangeXSize())
return;
//--- Если сигнал изменить размер элементов по оси Y
if(OnWindowChangeYSize())
return;
//--- Если сигнал включить/выключить всплывающие подсказки
if(OnWindowTooltips())
return;
//--- Если сигнал на скрытие контекстных меню от пункта инициатора
if(OnHideBackContextMenus())
return;
//--- Если сигнал на скрытие всех контекстных меню
if(OnHideContextMenus())
return;
//--- Если сигнал на открытие диалогового окна
if(OnOpenDialogBox())
return;
//--- Если сигнал на закрытие диалогового окна
if(OnCloseDialogBox())
return;
}
//+------------------------------------------------------------------+
//| Событие CHARTEVENT CLICK |
//+------------------------------------------------------------------+
void CWndEvents::ChartEventClick(void) {
}
//+------------------------------------------------------------------+
//| Событие CHARTEVENT MOUSE MOVE |
//+------------------------------------------------------------------+
void CWndEvents::ChartEventMouseMove(void) {
//--- Выйти, если это не событие перемещения курсора
if(m_id != CHARTEVENT_MOUSE_MOVE)
return;
//--- Перемещение окна
MovingWindow();
//--- Установка состояния графика
SetChartState();
}
//+------------------------------------------------------------------+
//| Событие CHARTEVENT OBJECT CLICK |
//+------------------------------------------------------------------+
void CWndEvents::ChartEventObjectClick(void) {
}
//+------------------------------------------------------------------+
//| Событие CHARTEVENT OBJECT ENDEDIT |
//+------------------------------------------------------------------+
void CWndEvents::ChartEventEndEdit(void) {
}
//+------------------------------------------------------------------+
//| Событие CHARTEVENT CHART CHANGE |
//+------------------------------------------------------------------+
void CWndEvents::ChartEventChartChange(void) {
//--- Событие изменения свойств графика
if(m_id != CHARTEVENT_CHART_CHANGE)
return;
//--- Проверка и обновление номера окна эксперта
CheckExpertSubwindowNumber();
//--- Проверка и обновление номера окна индикатора
CheckSubwindowNumber();
//--- Перемещение окна
MovingWindow(true);
//--- Изменение размеров заблокированного главного окна
ResizeLockedWindow();
//--- Перерисуем график
m_chart.Redraw();
}
//+------------------------------------------------------------------+
//| Таймер |
//+------------------------------------------------------------------+
void CWndEvents::OnTimerEvent(void) {
//--- Выйти, если курсор мыши в состоянии покоя (разница между вызовами > 300 ms) и левая кнопка мыши отжата
if(m_mouse.GapBetweenCalls() > 300 && !m_mouse.LeftButtonState()) {
int text_boxes_total = CWndContainer::ElementsTotal(m_active_window_index, E_TEXT_BOX);
for(int e = 0; e < text_boxes_total; e++)
m_wnd[m_active_window_index].m_text_boxes[e].OnEventTimer();
//---
return;
}
//--- Если массив пуст, выйдем
if(CWndContainer::WindowsTotal() < 1)
return;
//--- Проверка событий всех элементов по таймеру
CheckElementsEventsTimer();
//--- Перерисуем график, если окно в режиме перемещения
if(m_windows[m_active_window_index].ClampingAreaMouse() == PRESSED_INSIDE_HEADER)
m_chart.Redraw();
}
//+------------------------------------------------------------------+
//| Событие окончания перетаскивания формы |
//+------------------------------------------------------------------+
bool CWndEvents::OnWindowEndDrag(void) {
//--- Если сигнал свернуть форму
if(m_id != CHARTEVENT_CUSTOM + ON_WINDOW_DRAG_END)
return(false);
//--- Если идентификатор окна и номер подокна совпадают
if(m_lparam == m_windows[0].Id() && (int)m_dparam == m_subwin) {
//--- Установить режим показа во всех главных элементах
int main_total = MainElementsTotal(m_active_window_index);
for(int e = 0; e < main_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_main_elements[e];
el.Moving(false);
}
}
//--- Обновить расположение всех элементов
m_chart.Redraw();
return(true);
}
//+------------------------------------------------------------------+
//| Событие свёртывания формы |
//+------------------------------------------------------------------+
bool CWndEvents::OnWindowCollapse(void) {
//--- Если сигнал свернуть форму
if(m_id != CHARTEVENT_CUSTOM + ON_WINDOW_COLLAPSE)
return(false);
//--- Если идентификатор окна и номер подокна совпадают
if(m_lparam == m_windows[0].Id() && (int)m_dparam == m_subwin) {
int elements_total = CWndContainer::ElementsTotal(0);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[0].m_elements[e];
//--- Скрыть все элементы кроме формы
if(el.Id() > 0)
el.Hide();
}
//--- Сбросить цвета формы
m_windows[0].ResetColors();
}
//--- Обновить расположение всех элементов
m_chart.Redraw();
return(true);
}
//+------------------------------------------------------------------+
//| Событие развёртывания формы |
//+------------------------------------------------------------------+
bool CWndEvents::OnWindowExpand(void) {
//--- Если сигнал "Развернуть форму"
if(m_id != CHARTEVENT_CUSTOM + ON_WINDOW_EXPAND)
return(false);
//--- Индекс активного окна
int awi = m_active_window_index;
//--- Если идентификатор окна и номер подокна совпадают
if(m_lparam != m_windows[awi].Id() || (int)m_dparam != m_subwin)
return(true);
//--- Изменить высоту окна, если включен режим
if(m_windows[awi].AutoYResizeMode())
m_windows[awi].ChangeWindowHeight(m_chart.HeightInPixels(m_subwin) - 3);
//---
int y_resize_total = CWndContainer::AutoYResizeElementsTotal(awi);
for(int e = 0; e < y_resize_total; e++) {
CElement *el = m_wnd[awi].m_auto_y_resize_elements[e];
//--- Если включен режим, то подогнать высоту
if(el.AutoYResizeMode()) {
el.ChangeHeightByBottomWindowSide();
el.Update();
}
}
//--- Показать элементы
Show(awi);
//--- Показать элементы только выделенных вкладок
ShowTabElements(awi);
//--- Обновить для отображения всех изменений
int elements_total = CWndContainer::ElementsTotal(awi);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[awi].m_elements[e];
if(el.IsVisible())
el.Update();
}
//--- Обновить расположение всех элементов
m_chart.Redraw();
return(true);
}
//+------------------------------------------------------------------+
//| Событие изменения размеров элементов по оси X |
//+------------------------------------------------------------------+
bool CWndEvents::OnWindowChangeXSize(void) {
//--- Если сигнал "Изменить размер элементов"
if(m_id != CHARTEVENT_CUSTOM + ON_WINDOW_CHANGE_XSIZE)
return(false);
//--- Выйти, если идентификаторы окна не совпадают
if(m_lparam != m_windows[m_active_window_index].Id())
return(true);
//--- Обновить положение элементов
Moving();
//--- Обновить окно
m_windows[m_active_window_index].Update();
//--- Изменить ширину
int x_resize_total = CWndContainer::AutoXResizeElementsTotal(m_active_window_index);
for(int e = 0; e < x_resize_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_auto_x_resize_elements[e];
el.ChangeWidthByRightWindowSide();
//el.Update();
}
//--- Обновить положение элементов
Moving();
//---
for(int e = 0; e < x_resize_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_auto_x_resize_elements[e];
el.Moving(false);
}
m_chart.Redraw();
for(int e = 0; e < x_resize_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_auto_x_resize_elements[e];
el.Update();
}
//--- Обновить для отображения всех изменений в древовидных списках
int treeviews_total = ElementsTotal(m_active_window_index, E_TREE_VIEW);
for(int t = 0; t < treeviews_total; t++) {
CTreeView *tv = m_wnd[m_active_window_index].m_treeview_lists[t];
tv.RedrawContentList();
tv.UpdateContentList();
}
//--- Показать указатель курсора, если в режиме ручного изменения ширины
if(m_windows[m_active_window_index].ResizeState())
m_windows[m_active_window_index].GetResizePointer().Reset();
//--- Обновить расположение всех элементов
m_chart.Redraw();
return(true);
}
//+------------------------------------------------------------------+
//| Событие изменения размеров элементов по оси Y |
//+------------------------------------------------------------------+
bool CWndEvents::OnWindowChangeYSize(void) {
//--- Если сигнал "Изменить размер элементов"
if(m_id != CHARTEVENT_CUSTOM + ON_WINDOW_CHANGE_YSIZE)
return(false);
//--- Выйти, если идентификаторы окна не совпадают
if(m_lparam != m_windows[m_active_window_index].Id())
return(true);
//--- Обновить положение элементов
Moving();
//--- Обновить окно
m_windows[m_active_window_index].Update();
//--- Изменить высоту
int y_resize_total = CWndContainer::AutoYResizeElementsTotal(m_active_window_index);
for(int e = 0; e < y_resize_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_auto_y_resize_elements[e];
el.ChangeHeightByBottomWindowSide();
//el.Update();
}
//--- Обновить положение элементов
Moving();
//---
for(int e = 0; e < y_resize_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_auto_y_resize_elements[e];
el.Moving(false);
}
m_chart.Redraw();
for(int e = 0; e < y_resize_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_auto_y_resize_elements[e];
el.Update();
}
//--- Показать указатель курсора, если в режиме ручного изменения высоты
if(m_windows[m_active_window_index].ResizeState())
m_windows[m_active_window_index].GetResizePointer().Reset();
//--- Обновить расположение всех элементов
m_chart.Redraw();
return(true);
}
//+------------------------------------------------------------------+
//| Событие включения/отключения всплывающих подсказок |
//+------------------------------------------------------------------+
bool CWndEvents::OnWindowTooltips(void) {
//--- Если сигнал "Включить/отключить всплывающие подсказки"
if(m_id != CHARTEVENT_CUSTOM + ON_WINDOW_TOOLTIPS)
return(false);
//--- Вытий, если идентификаторы окна не совпадают
if(m_lparam != m_windows[0].Id())
return(true);
//--- Синхронизировать режим всплывающих подсказок между всеми окнами
int windows_total = WindowsTotal();
for(int w = 0; w < windows_total; w++) {
bool state = m_windows[0].TooltipButtonState();
m_windows[w].IsTooltip(state);
//--- Показать всплывающие подсказки в кнопках окон
int window_elements_total = m_windows[w].ElementsTotal();
for(int e = 0; e < window_elements_total; e++) {
CElement *el = m_windows[w].Element(e);
el.ShowTooltip(state);
}
//--- Установить режим показа во всех элементах
int elements_total = ElementsTotal(w);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[w].m_elements[e];
el.ShowTooltip(state);
}
}
//--- Переместить всплывающие подсказки на верхний слой
ResetTooltips();
return(true);
}
//+------------------------------------------------------------------+
//| Событие скрытия контектсных меню от пункта инициатора |
//+------------------------------------------------------------------+
bool CWndEvents::OnHideBackContextMenus(void) {
//--- Если сигнал на скрытие контекстных меню от пункта инициатора
if(m_id != CHARTEVENT_CUSTOM + ON_HIDE_BACK_CONTEXTMENUS)
return(false);
//--- Пройдём по всем меню от последнего вызванного
int awi = m_active_window_index;
int context_menus_total = CWndContainer::ElementsTotal(awi, E_CONTEXT_MENU);
for(int i = context_menus_total - 1; i >= 0; i--) {
//--- Указатели контекстного меню и его предыдущего узла
CContextMenu *cm = m_wnd[awi].m_context_menus[i];
CMenuItem *mi = cm.PrevNodePointer();
//--- Если дальше этого пункта больше ничего нет, то...
if(::CheckPointer(mi) == POINTER_INVALID)
continue;
//--- Если дошли до пункта инициатора сигнала, то...
if(mi.Id() == m_lparam) {
//--- ...в случае, если его контекстное меню без фокуса, скроем его
if(!cm.MouseFocus()) {
cm.Hide();
mi.IsPressed(false);
mi.Update(true);
}
//--- Завершим цикл
break;
} else {
cm.Hide();
mi.IsPressed(false);
mi.Update(true);
}
}
return(true);
}
//+------------------------------------------------------------------+
//| Событие скрытия всех контекстных меню |
//+------------------------------------------------------------------+
bool CWndEvents::OnHideContextMenus(void) {
//--- Если сигнал на скрытие всех контекстных меню
if(m_id != CHARTEVENT_CUSTOM + ON_HIDE_CONTEXTMENUS)
return(false);
//--- Скрыть все контекстные меню
int awi = m_active_window_index;
int cm_total = CWndContainer::ElementsTotal(awi, E_CONTEXT_MENU);
for(int i = 0; i < cm_total; i++) {
m_wnd[awi].m_context_menus[i].Hide();
//---
if(CheckPointer(m_wnd[awi].m_context_menus[i].PrevNodePointer()) != POINTER_INVALID) {
CMenuItem *mi = m_wnd[awi].m_context_menus[i].PrevNodePointer();
mi.IsPressed(false);
mi.Update(true);
}
}
//--- Отключить главные меню
int menu_bars_total = CWndContainer::ElementsTotal(awi, E_MENU_BAR);
for(int i = 0; i < menu_bars_total; i++)
m_wnd[awi].m_menu_bars[i].State(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Событие открытия диалогового окна |
//+------------------------------------------------------------------+
bool CWndEvents::OnOpenDialogBox(void) {
//--- Если сигнал на открытие диалогового окна
if(m_id != CHARTEVENT_CUSTOM + ON_OPEN_DIALOG_BOX)
return(false);
//--- Выйти, если сообщение от другой программы
if(m_sparam != m_program_name)
return(true);
//--- Пройдёмся по массиву окон
int window_total = CWndContainer::WindowsTotal();
for(int w = 0; w < window_total; w++) {
//--- Если идентификатор открытого окна
if(m_windows[w].Id() == m_lparam) {
//--- Запомним в этой форме индекс окна, с которого она была вызвана
m_windows[w].PrevActiveWindowIndex(m_active_window_index);
//--- Активируем форму
m_windows[w].State(true);
//--- Восстановим объектам формы приоритеты на нажатие левой кнопкой мыши
m_windows[w].SetZorders();
//--- Запомним индекс активированного окна
m_active_window_index = w;
//--- Показать окно
Show(m_active_window_index);
}
//--- Другие формы будут заблокированы, пока не закроется активированное окно
else {
//--- Заблокируем форму
m_windows[w].State(false);
//--- Обнулим приоритеты элементов формы на нажатие левой кнопкой мыши
int elements_total = CWndContainer::ElementsTotal(w);
for(int e = 0; e < elements_total; e++)
m_wnd[w].m_elements[e].ResetZorders();
}
}
//--- Скрытие всплывающих подсказок в предыдущем окне
int prev_window_index = m_windows[m_active_window_index].PrevActiveWindowIndex();
int tooltips_total = CWndContainer::ElementsTotal(prev_window_index, E_TOOLTIP);
for(int t = 0; t < tooltips_total; t++)
m_wnd[prev_window_index].m_tooltips[t].FadeOutTooltip();
//--- Показать элементы только выделенных вкладок
ShowTabElements(m_active_window_index);
//--- Сформируем массив видимых и при этом доступных элементов
FormAvailableElementsArray();
//--- Восстановление приоритетов на нажатие левой кнопкой мыши у активированного окна
SetZorders();
//--- Переместить всплывающие подсказки на верхний слой
ResetTooltips();
return(true);
}
//+------------------------------------------------------------------+
//| Событие закрытия диалогового окна |
//+------------------------------------------------------------------+
bool CWndEvents::OnCloseDialogBox(void) {
//--- Если сигнал на закрытие диалогового окна
if(m_id != CHARTEVENT_CUSTOM + ON_CLOSE_DIALOG_BOX)
return(false);
//--- Пройдёмся по массиву окон
int window_total = CWndContainer::WindowsTotal();
for(int w = 0; w < window_total; w++) {
//--- Если идентификатор открытого окна
if(m_windows[w].Id() == m_lparam) {
//--- Заблокируем форму
m_windows[w].State(false);
//--- Спрячем форму
int elements_total = CWndContainer::ElementsTotal(w);
for(int e = 0; e < elements_total; e++)
m_wnd[w].m_elements[e].Hide();
//--- Активируем предыдущую форму
m_windows[int(m_dparam)].State(true);
//--- Перерисовка графика
m_chart.Redraw();
break;
}
}
//--- Установка индекса предыдущего окна
m_active_window_index = int(m_dparam);
//--- Восстановление приоритетов на нажатие левой кнопкой мыши у активированного окна
SetZorders();
return(true);
}
//+------------------------------------------------------------------+
//| Событие для определения доступных элементов управления |
//+------------------------------------------------------------------+
bool CWndEvents::OnSetAvailable(void) {
//--- Если сигнал об изменении доступности элементов
if(m_id != CHARTEVENT_CUSTOM + ON_SET_AVAILABLE)
return(false);
//--- Сигнал на установку/восстановление
bool is_restore = (bool)m_dparam;
//--- Определим активные элементы
int ww_index = ActivatedWindowIndex();
int mb_index = ActivatedMenuBarIndex();
int mi_index = ActivatedMenuItemIndex();
int sb_index = ActivatedSplitButtonIndex();
int cb_index = ActivatedComboBoxIndex();
int dc_index = ActivatedDropCalendarIndex();
int sc_index = ActivatedScrollIndex();
int tl_index = ActivatedTableIndex();
int sd_index = ActivatedSliderIndex();
int tv_index = ActivatedTreeViewIndex();
int ch_index = ActivatedSubChartIndex();
//--- Если сигнал на определение доступных элементов, сначала отключаем доступ
if(!is_restore)
SetAvailable(m_active_window_index, false);
//--- Восстанавливаем, только если нет активированных элементов
else {
if(ww_index == WRONG_VALUE && mb_index == WRONG_VALUE && mi_index == WRONG_VALUE &&
sb_index == WRONG_VALUE && dc_index == WRONG_VALUE && cb_index == WRONG_VALUE &&
sc_index == WRONG_VALUE && tl_index == WRONG_VALUE && sd_index == WRONG_VALUE &&
tv_index == WRONG_VALUE && ch_index == WRONG_VALUE) {
SetAvailable(m_active_window_index, true);
return(true);
}
}
//--- Если (1) сигнал на определение доступных элементов или (2) на восстановление для выпадающего календаря
if(!is_restore || (is_restore && dc_index != WRONG_VALUE)) {
CElement *el = NULL;
//--- Окно
if(ww_index != WRONG_VALUE) {
el = m_windows[m_active_window_index];
}
//--- Главное меню
else if(mb_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_menu_bars[mb_index];
}
//--- Пункт меню
else if(mi_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_menu_items[mi_index];
}
//--- Сдвоенная кнопка
else if(sb_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_split_buttons[sb_index];
}
//--- Выпадающий календарь без выпадающего списка
else if(dc_index != WRONG_VALUE && cb_index == WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_drop_calendars[dc_index];
}
//--- Выпадающий список
else if(cb_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_combo_boxes[cb_index];
}
//--- Полоса прокрутки
else if(sc_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_scrolls[sc_index];
}
//--- Таблица
else if(tl_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_tables[tl_index];
}
//--- Слайдер
else if(sd_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_sliders[sd_index];
}
//--- Древовидный список
else if(tv_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_treeview_lists[tv_index];
}
//--- Стандартный график
else if(ch_index != WRONG_VALUE) {
el = m_wnd[m_active_window_index].m_sub_charts[ch_index];
}
//--- Выйти, если указатель на элемент не получен
if(::CheckPointer(el) == POINTER_INVALID) {
return(true);
}
//--- Блок для главного меню
if(mb_index != WRONG_VALUE) {
//--- Сделать доступными главное меню и его видимые контекстные меню
el.IsAvailable(true);
//---
CMenuBar *mb = dynamic_cast<CMenuBar*>(el);
int items_total = mb.ItemsTotal();
for(int i = 0; i < items_total; i++) {
CMenuItem *mi = mb.GetItemPointer(i);
mi.IsAvailable(true);
//--- Проверяет и делает контекстное меню доступным
CheckContextMenu(mi);
}
}
//--- Блок для пункта меню
if(mi_index != WRONG_VALUE) {
CMenuItem *mi = dynamic_cast<CMenuItem*>(el);
mi.IsAvailable(true);
//--- Проверяет и делает контекстное меню доступным
CheckContextMenu(mi);
}
//--- Блок для полос прокрутки
else if(sc_index != WRONG_VALUE) {
//--- Сделать доступным начиная от главного узла
el.MainPointer().IsAvailable(true);
}
//--- Блок для древовидного списка
else if(tv_index != WRONG_VALUE) {
//--- Заблокировать все элементы, кроме главного
CTreeView *tv = dynamic_cast<CTreeView*>(el);
tv.IsAvailable(true, true);
int total = tv.ElementsTotal();
for(int i = 0; i < total; i++)
tv.Element(i).IsAvailable(false);
} else {
//--- Сделать элемент доступным
el.IsAvailable(true);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Событие ON_SET_LOCKED |
//+------------------------------------------------------------------+
bool CWndEvents::OnSetLocked(void) {
//--- Если сигнал о блокировке элементов
if(m_id != CHARTEVENT_CUSTOM + ON_SET_LOCKED)
return(false);
//---
bool find_flag = false;
//---
int elements_total = CWndContainer::MainElementsTotal(m_active_window_index);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_main_elements[e];
//---
if(m_lparam != el.Id()) {
if(find_flag)
break;
//---
continue;
}
//---
find_flag = true;
//---
int total = el.ElementsTotal();
for(int i = 0; i < total; i++)
el.Element(i).Update(true);
//---
el.Update(true);
}
return(true);
}
//+------------------------------------------------------------------+
//| Событие изменений в графическом интерфейсе |
//+------------------------------------------------------------------+
bool CWndEvents::OnChangeGUI(void) {
//--- Если сигнал об изменении в графическом интерфейсе
if(m_id != CHARTEVENT_CUSTOM + ON_CHANGE_GUI)
return(false);
//--- Сформируем массив видимых и при этом доступных элементов
FormAvailableElementsArray();
//--- Переместить всплывающие подсказки на верхний слой
ResetTooltips();
//--- Перерисовать график
m_chart.Redraw();
return(true);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированного окна |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedWindowIndex(void) {
int index = WRONG_VALUE;
//---
int total = WindowsTotal();
for(int i = 0; i < total; i++) {
if(m_windows[i].ResizeState()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированного главного меню |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedMenuBarIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_MENU_BAR);
for(int i = 0; i < total; i++) {
CMenuBar *el = m_wnd[m_active_window_index].m_menu_bars[i];
if(el.State()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированного пункта меню |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedMenuItemIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_MENU_ITEM);
for(int i = 0; i < total; i++) {
CMenuItem *el = m_wnd[m_active_window_index].m_menu_items[i];
if(el.GetContextMenuPointer().IsVisible()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированной сдвоенной кнопки |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedSplitButtonIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_SPLIT_BUTTON);
for(int i = 0; i < total; i++) {
CSplitButton *el = m_wnd[m_active_window_index].m_split_buttons[i];
if(el.GetContextMenuPointer().IsVisible()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированного комбо-бокса |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedComboBoxIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_COMBO_BOX);
for(int i = 0; i < total; i++) {
CComboBox *el = m_wnd[m_active_window_index].m_combo_boxes[i];
if(el.GetListViewPointer().IsVisible()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированного выпадающего календаря |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedDropCalendarIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_DROP_CALENDAR);
for(int i = 0; i < total; i++) {
CDropCalendar *el = m_wnd[m_active_window_index].m_drop_calendars[i];
if(el.GetCalendarPointer().IsVisible()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированной полосы прокрутки |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedScrollIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_SCROLL);
for(int i = 0; i < total; i++) {
CScroll *el = m_wnd[m_active_window_index].m_scrolls[i];
if(el.State()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированной таблицы |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedTableIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_TABLE);
for(int i = 0; i < total; i++) {
CTable *el = m_wnd[m_active_window_index].m_tables[i];
if(el.ColumnResizeControl()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированного слайдера |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedSliderIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_SLIDER);
for(int i = 0; i < total; i++) {
CSlider *el = m_wnd[m_active_window_index].m_sliders[i];
if(el.State()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированного древовидного списка |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedTreeViewIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_TREE_VIEW);
for(int i = 0; i < total; i++) {
CTreeView *el = m_wnd[m_active_window_index].m_treeview_lists[i];
//--- Перейти к следующему, если включен режим вкладок
if(el.TabItemsMode())
continue;
//--- Если процесс изменения ширины списков
if(el.GetMousePointer().State()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Возвращает индекс активированного стандартного графика |
//+------------------------------------------------------------------+
int CWndEvents::ActivatedSubChartIndex(void) {
int index = WRONG_VALUE;
//---
int total = ElementsTotal(m_active_window_index, E_SUB_CHART);
for(int i = 0; i < total; i++) {
CStandardChart *el = m_wnd[m_active_window_index].m_sub_charts[i];
if(el.GetMousePointer().IsVisible()) {
index = i;
break;
}
}
return(index);
}
//+------------------------------------------------------------------+
//| Рекурсивно проверяет и делает контекстные меню доступными |
//+------------------------------------------------------------------+
void CWndEvents::CheckContextMenu(CMenuItem &object) {
//--- Получим указатель контекстного меню
CContextMenu *cm = object.GetContextMenuPointer();
//--- Выйти, если контекстного меню нет в пункте
if(::CheckPointer(cm) == POINTER_INVALID)
return;
//--- Выйти, если контекстное меню есть, но скрыто
if(!cm.IsVisible())
return;
//--- Установить признаки доступного элемента
cm.IsAvailable(true);
//---
int items_total = cm.ItemsTotal();
for(int i = 0; i < items_total; i++) {
//--- Установить признаки доступного элемента
CMenuItem *mi = cm.GetItemPointer(i);
mi.IsAvailable(true);
//--- Проверим, есть ли в этом пункте контекстное меню
CheckContextMenu(mi);
}
}
//+------------------------------------------------------------------+
//| Перемещение окна |
//+------------------------------------------------------------------+
void CWndEvents::MovingWindow(const bool moving_mode = false) {
//--- Если управление передано окну, определим его положение
if(!moving_mode)
if(m_windows[m_active_window_index].ClampingAreaMouse() != PRESSED_INSIDE_HEADER)
return;
//--- Перемещение окна
int x = m_windows[m_active_window_index].X();
int y = m_windows[m_active_window_index].Y();
m_windows[m_active_window_index].Moving(x, y);
//--- Перемещение элементов управления
int main_total = MainElementsTotal(m_active_window_index);
for(int e = 0; e < main_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_main_elements[e];
el.Moving();
}
}
//+------------------------------------------------------------------+
//| Проверка событий всех элементов по таймеру |
//+------------------------------------------------------------------+
void CWndEvents::CheckElementsEventsTimer(void) {
int awi = m_active_window_index;
int timer_elements_total = CWndContainer::TimerElementsTotal(awi);
for(int e = 0; e < timer_elements_total; e++) {
CElement *el = m_wnd[awi].m_timer_elements[e];
if(el.IsVisible())
el.OnEventTimer();
}
}
//+------------------------------------------------------------------+
//| Определение номера подокна |
//+------------------------------------------------------------------+
void CWndEvents::DetermineSubwindow(void) {
//--- Выйдем, если тип программы "Скрипт"
if(PROGRAM_TYPE == PROGRAM_SCRIPT)
return;
//--- Сброс последней ошибки
::ResetLastError();
//--- Если тип программы эксперт
if(PROGRAM_TYPE == PROGRAM_EXPERT) {
//--- Выйти, если графический интерфейс эксперта нужен в главном окне
if(!EXPERT_IN_SUBWINDOW)
return;
//--- Получим хэндл индикатора-пустышки (пустое подокно)
m_subwindow_handle = iCustom(::Symbol(), ::Period(), "::Indicators\\SubWindow.ex5");
//--- Если такого индикатор нет, сообщить об ошибке в журнал
if(m_subwindow_handle == INVALID_HANDLE)
::Print(__FUNCTION__, " > Ошибка при получении хэндла индикатора в директории ::Indicators\\SubWindow.ex5 !");
//--- Если хэндл получен, значит индикатор есть, подключен к приложению в качестве ресурса,
// а это значит, что графический интерфейс приложения нужно поместить в подокно
else {
//--- Получим количество подокон на графике
int subwindows_total = (int)::ChartGetInteger(m_chart_id, CHART_WINDOWS_TOTAL);
//--- Установим подокно для графического интерфейса эксперта
if(::ChartIndicatorAdd(m_chart_id, subwindows_total, m_subwindow_handle)) {
//--- Сохраним номер подокна и текущее количество подокон на графике
m_subwin = subwindows_total;
m_subwindows_total = subwindows_total + 1;
//--- Получим и сохраним короткое имя подокна эксперта
m_subwindow_shortname =::ChartIndicatorName(m_chart_id, m_subwin, 0);
}
//--- Если подокно не установилось
else
::Print(__FUNCTION__, " > Ошибка при установке подокна эксперта! Номер ошибки: ", ::GetLastError());
}
//---
return;
}
//--- Определение номера окна индикатора
m_subwin =::ChartWindowFind();
//--- Если не получилось определить номер, выйдем
if(m_subwin < 0) {
::Print(__FUNCTION__, " > Ошибка при определении номера подокна: ", ::GetLastError());
return;
}
//--- Если это не главное окно графика
if(m_subwin > 0) {
//--- Получим общее количество индикаторов в указанном подокне
int total =::ChartIndicatorsTotal(m_chart_id, m_subwin);
//--- Получим короткое имя последнего индикатора в списке
string indicator_name =::ChartIndicatorName(m_chart_id, m_subwin, total - 1);
//--- Если в подокне уже есть индикатор, то удалить программу с графика
if(total != 1) {
::Print(__FUNCTION__, " > В этом подокне уже есть индикатор.");
::ChartIndicatorDelete(m_chart_id, m_subwin, indicator_name);
return;
}
}
}
//+------------------------------------------------------------------+
//| Удаляет подокно эксперта |
//+------------------------------------------------------------------+
void CWndEvents::DeleteExpertSubwindow(void) {
//--- Выйти, если это не эксперт
if(PROGRAM_TYPE != PROGRAM_EXPERT)
return;
//--- Выйти, если хэндл невалиден
if(m_subwindow_handle == INVALID_HANDLE)
return;
//--- Получим количество окон на графике
int windows_total = (int)::ChartGetInteger(m_chart_id, CHART_WINDOWS_TOTAL);
//--- Найдём подокно эксперта
for(int w = 0; w < windows_total; w++) {
//--- Получим короткое имя подокна эксперта (индикатор SubWindow.ex5)
string indicator_name =::ChartIndicatorName(m_chart_id, w, 0);
//--- Перейти к следующему, если это не подокно эксперта
if(indicator_name != m_subwindow_shortname || w != m_subwin)
continue;
//--- Удалить подокно эксперта
if(!::ChartIndicatorDelete(m_chart_id, m_subwin, indicator_name))
::Print(__FUNCTION__, " > Ошибка при удалении подокна эксперта! Номер ошибки: ", ::GetLastError());
}
}
//+------------------------------------------------------------------+
//| Проверка и обновление номера окна эксперта |
//+------------------------------------------------------------------+
void CWndEvents::CheckExpertSubwindowNumber(void) {
//--- Выйти, если (1) это не эксперт или (2) графический интерфейс эксперта в главном окне
if(PROGRAM_TYPE != PROGRAM_EXPERT || !EXPERT_IN_SUBWINDOW)
return;
//--- Получим количество подокон на графике
int subwindows_total = (int)::ChartGetInteger(m_chart_id, CHART_WINDOWS_TOTAL);
//--- Выйти, если количество подокон и количество индикаторов не изменилось
if(subwindows_total == m_subwindows_total)
return;
//--- Сохраним текущее количество подокон
m_subwindows_total = subwindows_total;
//--- Для проверки наличия подокна эксперта
bool is_subwindow = false;
//--- Найдём подокно эксперта
for(int sw = 0; sw < subwindows_total; sw++) {
//--- Остановить цикл, если подокно эксперта есть
if(is_subwindow)
break;
//--- Сколько индикаторов в данном окне/подокне
int indicators_total =::ChartIndicatorsTotal(m_chart_id, sw);
//--- Переберём все индикаторы в окне
for(int i = 0; i < indicators_total; i++) {
//--- Получим короткое имя индикатора
string indicator_name =::ChartIndicatorName(m_chart_id, sw, i);
//--- Если это не подокно эксперта, перейти к следующему
if(indicator_name != m_subwindow_shortname)
continue;
//--- Отметим, что подокно эксперта есть
is_subwindow = true;
//--- Если номер подокна изменился, то
// нужно сохранить новый номер во всех элементах главной формы
if(sw != m_subwin) {
//--- Сохраним номер подокна
m_subwin = sw;
//--- Сохраним его также во всех элементах главной формы интерфейса
int elements_total = CWndContainer::ElementsTotal(0);
for(int e = 0; e < elements_total; e++)
m_wnd[0].m_elements[e].SubwindowNumber(m_subwin);
}
//---
break;
}
}
//--- Если подокно эксперта не обнаружено, удалим эксперта
if(!is_subwindow) {
::Print(__FUNCTION__, " > Удаление подокна эксперта приводит к удалению эксперта!");
//--- Удаление эксперта с графика
::ExpertRemove();
}
}
//+------------------------------------------------------------------+
//| Проверка и обновление номера окна программы |
//+------------------------------------------------------------------+
void CWndEvents::CheckSubwindowNumber(void) {
//--- Выйти, если это не индикатор
if(PROGRAM_TYPE != PROGRAM_INDICATOR)
return;
//--- Если программа в подокне и номера не совпадают
if(m_subwin != 0 && m_subwin !=::ChartWindowFind()) {
//--- Определить номер подокна
DetermineSubwindow();
//--- Сохранить во всех элементах
int windows_total = CWndContainer::WindowsTotal();
for(int w = 0; w < windows_total; w++) {
int elements_total = CWndContainer::ElementsTotal(w);
for(int e = 0; e < elements_total; e++)
m_wnd[w].m_elements[e].SubwindowNumber(m_subwin);
}
}
}
//+------------------------------------------------------------------+
//| Изменение размеров заблокированного главного окна |
//+------------------------------------------------------------------+
void CWndEvents::ResizeLockedWindow(void) {
//--- Сохранить во всех элементах
int windows_total = CWndContainer::WindowsTotal();
//--- Выйти, если интерфейс не создан
if(windows_total < 1)
return;
//--- Изменить размер всех элементов заблокированной формы, если включен один из режимов
if(m_windows[0].CElementBase::IsLocked() && (m_windows[0].AutoXResizeMode() || m_windows[0].AutoXResizeMode())) {
int elements_total = CWndContainer::ElementsTotal(0);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[0].m_elements[e];
//--- Если это форма
if(dynamic_cast<CWindow*>(el) != NULL) {
el.OnEvent(m_id, m_lparam, m_dparam, m_sparam);
continue;
}
//--- Изменить ширину элементов, где включен такой режим
if(el.AutoXResizeMode())
el.ChangeWidthByRightWindowSide();
//--- Изменить ширину элементов, где включен такой режим
if(el.AutoYResizeMode())
el.ChangeHeightByBottomWindowSide();
//--- Обновить положение объектов
el.Moving();
}
//--- Обновим (сохраним) свойства графика у других форм
for(int w = 1; w < windows_total; w++)
m_windows[w].SetWindowProperties();
//--- Перерисовка активированного окна
ResetWindow();
//--- Обновить
Update();
}
}
//+------------------------------------------------------------------+
//| Перерисовка окна |
//+------------------------------------------------------------------+
void CWndEvents::ResetWindow(void) {
//--- Выйти, если ещё нет ни одного окна
if(CWndContainer::WindowsTotal() < 1)
return;
//--- Перерисовка окна и его элементов
Hide();
Show(m_active_window_index);
}
//+------------------------------------------------------------------+
//| Удаление всех объектов |
//+------------------------------------------------------------------+
void CWndEvents::Destroy(void) {
//--- Установим индекс главного окна
m_active_window_index = 0;
//--- Получим количество окон
int window_total = CWndContainer::WindowsTotal();
//--- Пройдёмся по массиву окон
for(int w = 0; w < window_total; w++) {
//--- Активируем главное окно
if(m_windows[w].WindowType() == W_MAIN)
m_windows[w].State(true);
//--- Заблокируем диалоговые окна
else
m_windows[w].State(false);
}
//--- Освободим массивы элементов
for(int w = 0; w < window_total; w++) {
int elements_total = CWndContainer::ElementsTotal(w);
for(int e = 0; e < elements_total; e++) {
//--- Если указатель невалидный, перейти к следующему
if(::CheckPointer(m_wnd[w].m_elements[e]) == POINTER_INVALID)
continue;
//--- Удалить объекты элемента
m_wnd[w].m_elements[e].Delete();
m_wnd[w].m_elements[e].Id(WRONG_VALUE);
}
//--- Освободить массивы элементов
::ArrayFree(m_wnd[w].m_elements);
::ArrayFree(m_wnd[w].m_main_elements);
::ArrayFree(m_wnd[w].m_timer_elements);
::ArrayFree(m_wnd[w].m_auto_x_resize_elements);
::ArrayFree(m_wnd[w].m_auto_y_resize_elements);
::ArrayFree(m_wnd[w].m_available_elements);
::ArrayFree(m_wnd[w].m_menu_bars);
::ArrayFree(m_wnd[w].m_menu_items);
::ArrayFree(m_wnd[w].m_context_menus);
::ArrayFree(m_wnd[w].m_combo_boxes);
::ArrayFree(m_wnd[w].m_split_buttons);
::ArrayFree(m_wnd[w].m_drop_lists);
::ArrayFree(m_wnd[w].m_scrolls);
::ArrayFree(m_wnd[w].m_tables);
::ArrayFree(m_wnd[w].m_tabs);
::ArrayFree(m_wnd[w].m_calendars);
::ArrayFree(m_wnd[w].m_drop_calendars);
::ArrayFree(m_wnd[w].m_sub_charts);
::ArrayFree(m_wnd[w].m_pictures_slider);
::ArrayFree(m_wnd[w].m_time_edits);
::ArrayFree(m_wnd[w].m_text_boxes);
::ArrayFree(m_wnd[w].m_tooltips);
::ArrayFree(m_wnd[w].m_treeview_lists);
::ArrayFree(m_wnd[w].m_file_navigators);
::ArrayFree(m_wnd[w].m_frames);
}
//--- Освободить массивы форм
::ArrayFree(m_wnd);
::ArrayFree(m_windows);
}
//+------------------------------------------------------------------+
//| Завершение создания GUI |
//+------------------------------------------------------------------+
void CWndEvents::CompletedGUI(void) {
//--- Выйти, если ещё нет ни одного окна
int windows_total = CWndContainer::WindowsTotal();
if(windows_total < 1) {
return;
}
//--- Показать комментарий информирующий пользователя
::Comment("Update. Please wait...");
//--- Скрыть элементы
Hide();
//--- Нарисовать элементы
Update(true);
//--- Показать элементы активированного окна
Show(m_active_window_index);
//--- Сформируем массив элементов с таймером
FormTimerElementsArray();
//--- Сформируем массив видимых и при этом доступных элементов
FormAvailableElementsArray();
//--- Сформируем массивы элементов с авто-ресайзом
FormAutoXResizeElementsArray();
FormAutoYResizeElementsArray();
//--- Перерисовать график
m_chart.Redraw();
//--- Очистить комментарий
::Comment("");
//--- Отправим событие завершения создания GUI
::EventChartCustom(m_chart_id, ON_END_CREATE_GUI, 0, 0.0, "");
//CWndEvents::PrintContainer();
}
//+------------------------------------------------------------------+
//| Перемещение элементов |
//+------------------------------------------------------------------+
void CWndEvents::Moving(void) {
//--- Обновить положение элементов
int main_total = MainElementsTotal(m_active_window_index);
for(int e = 0; e < main_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_main_elements[e];
el.Moving(false);
}
}
//+------------------------------------------------------------------+
//| Скрытие элементов |
//+------------------------------------------------------------------+
void CWndEvents::Hide(void) {
int windows_total = CWndContainer::WindowsTotal();
for(int w = 0; w < windows_total; w++) {
m_windows[w].Hide();
int main_total = MainElementsTotal(w);
for(int e = 0; e < main_total; e++) {
CElement *el = m_wnd[w].m_main_elements[e];
el.Hide();
}
}
}
//+------------------------------------------------------------------+
//| Показ элементов указанного окна |
//+------------------------------------------------------------------+
void CWndEvents::Show(const uint window_index) {
//--- Показать элементы указанного окна
m_windows[window_index].Show();
//--- Если окно не свёрнуто
if(!m_windows[window_index].IsMinimized()) {
int main_total = MainElementsTotal(window_index);
for(int e = 0; e < main_total; e++) {
CElement *el = m_wnd[window_index].m_main_elements[e];
//--- Показать элемент, если он (1) не выпадающий и (2) его главный элемент не вкладки
if(!el.IsDropdown() && dynamic_cast<CTabs*>(el.MainPointer()) == NULL)
el.Show();
}
//--- Показать элементы только выделенных вкладок
ShowTabElements(window_index);
}
}
//+------------------------------------------------------------------+
//| Восстановление приоритетов на нажатие левой кнопкой мыши |
//| у активного окна |
//+------------------------------------------------------------------+
void CWndEvents::SetZorders(void) {
int elements_total = CWndContainer::ElementsTotal(m_active_window_index);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[m_active_window_index].m_elements[e];
//---
if(el.ClassName() != "CGraph")
el.SetZorders();
else {
CGraph *graph = dynamic_cast<CGraph*>(el);
graph.SetZorders();
}
}
}
//+------------------------------------------------------------------+
//| Перерисовка элементов |
//+------------------------------------------------------------------+
void CWndEvents::Update(const bool redraw = false) {
int windows_total = CWndContainer::WindowsTotal();
for(int w = 0; w < windows_total; w++) {
//--- Перерисовка элементов
int elements_total = CWndContainer::ElementsTotal(w);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[w].m_elements[e];
el.Update(redraw);
}
}
}
//+------------------------------------------------------------------+
//| Перемещает всплывающие подсказки на верхний слой |
//+------------------------------------------------------------------+
void CWndEvents::ResetTooltips(void) {
//--- Переместить всплывающие подсказки на верхний слой
int window_total = CWndContainer::WindowsTotal();
for(int w = 0; w < window_total; w++) {
int tooltips_total = CWndContainer::ElementsTotal(w, E_TOOLTIP);
for(int t = 0; t < tooltips_total; t++)
m_wnd[w].m_tooltips[t].Reset();
}
}
//+------------------------------------------------------------------+
//| Устанавливает состояние доступности элементов |
//+------------------------------------------------------------------+
void CWndEvents::SetAvailable(const uint window_index, const bool state) {
//--- Получим количество главных элементов
int main_total = MainElementsTotal(window_index);
//--- Если нужно сделать элементы недоступными
if(!state) {
m_windows[window_index].IsAvailable(state);
for(int e = 0; e < main_total; e++) {
CElement *el = m_wnd[window_index].m_main_elements[e];
el.IsAvailable(state);
}
} else {
m_windows[window_index].IsAvailable(state);
for(int e = 0; e < main_total; e++) {
CElement *el = m_wnd[window_index].m_main_elements[e];
//--- Если это древовидный список
if(dynamic_cast<CTreeView*>(el) != NULL) {
CTreeView *tv = dynamic_cast<CTreeView*>(el);
tv.IsAvailable(true);
continue;
}
//--- Если это файловый навигатор
if(dynamic_cast<CFileNavigator*>(el) != NULL) {
CFileNavigator *fn = dynamic_cast<CFileNavigator*>(el);
CTreeView *tv = fn.GetTreeViewPointer();
fn.IsAvailable(state);
tv.IsAvailable(state);
continue;
}
//--- Сделать элемент доступным
el.IsAvailable(state);
}
}
}
//+------------------------------------------------------------------+
//| Показывает элементы только выделенных вкладок |
//+------------------------------------------------------------------+
void CWndEvents::ShowTabElements(const uint window_index) {
//--- Простые вкладки
int tabs_total = CWndContainer::ElementsTotal(window_index, E_TABS);
for(int t = 0; t < tabs_total; t++) {
CTabs *el = m_wnd[window_index].m_tabs[t];
if(el.IsVisible())
el.ShowTabElements();
}
//--- Вкладки древовидных списков
int treeview_total = CWndContainer::ElementsTotal(window_index, E_TREE_VIEW);
for(int tv = 0; tv < treeview_total; tv++)
m_wnd[window_index].m_treeview_lists[tv].ShowTabElements();
}
//+------------------------------------------------------------------+
//| Формирует массив элементов с таймером |
//+------------------------------------------------------------------+
void CWndEvents::FormTimerElementsArray(void) {
int windows_total = CWndContainer::WindowsTotal();
for(int w = 0; w < windows_total; w++) {
int elements_total = CWndContainer::ElementsTotal(w);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[w].m_elements[e];
//---
if(dynamic_cast<CCalendar *>(el) != NULL ||
dynamic_cast<CColorPicker *>(el) != NULL ||
dynamic_cast<CListView *>(el) != NULL ||
dynamic_cast<CTable *>(el) != NULL ||
dynamic_cast<CTextBox *>(el) != NULL ||
dynamic_cast<CTextEdit *>(el) != NULL ||
dynamic_cast<CTreeView *>(el) != NULL) {
CWndContainer::AddTimerElement(w, el);
}
}
}
}
//+------------------------------------------------------------------+
//| Формирует массив доступных элементов |
//+------------------------------------------------------------------+
void CWndEvents::FormAvailableElementsArray(void) {
//--- Индекс окна
int awi = m_active_window_index;
//--- Общее количество элементов
int elements_total = CWndContainer::ElementsTotal(awi);
//--- Очистим массив
::ArrayFree(m_wnd[awi].m_available_elements);
//---
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[awi].m_elements[e];
//--- Добавляем только видимые и доступные для обработки элементы
if(!el.IsVisible() || !el.CElementBase::IsAvailable() || el.CElementBase::IsLocked())
continue;
//--- Исключить элементы не требующие обработки по наведению курсора мыши
if(dynamic_cast<CButtonsGroup *>(el) == NULL &&
dynamic_cast<CFileNavigator *>(el) == NULL &&
dynamic_cast<CPicture *>(el) == NULL &&
dynamic_cast<CPicturesSlider *>(el) == NULL &&
dynamic_cast<CProgressBar *>(el) == NULL &&
dynamic_cast<CSeparateLine *>(el) == NULL &&
dynamic_cast<CStatusBar *>(el) == NULL &&
dynamic_cast<CTabs *>(el) == NULL &&
dynamic_cast<CTextLabel *>(el) == NULL) {
AddAvailableElement(awi, el);
//Print(__FUNCTION__," > class: ",el.ClassName(),"; id: ",el.Id());
}
}
}
//+------------------------------------------------------------------+
//| Формирует массив элементов с авто-ресайзом (X) |
//+------------------------------------------------------------------+
void CWndEvents::FormAutoXResizeElementsArray(void) {
int windows_total = CWndContainer::WindowsTotal();
for(int w = 0; w < windows_total; w++) {
int elements_total = CWndContainer::ElementsTotal(w);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[w].m_elements[e];
//--- Добавляем только те, у которых включен режим авто-ресайза
if(!el.AutoXResizeMode())
continue;
//---
if(dynamic_cast<CButton *>(el) != NULL ||
dynamic_cast<CFileNavigator *>(el) != NULL ||
dynamic_cast<CGraph *>(el) != NULL ||
dynamic_cast<CListView *>(el) != NULL ||
dynamic_cast<CMenuBar *>(el) != NULL ||
dynamic_cast<CProgressBar *>(el) != NULL ||
dynamic_cast<CStandardChart *>(el) != NULL ||
dynamic_cast<CStatusBar *>(el) != NULL ||
dynamic_cast<CTable *>(el) != NULL ||
dynamic_cast<CTabs *>(el) != NULL ||
dynamic_cast<CTextBox *>(el) != NULL ||
dynamic_cast<CTextEdit *>(el) != NULL ||
dynamic_cast<CTreeView *>(el) != NULL ||
dynamic_cast<CFrame *>(el) != NULL) {
CWndContainer::AddAutoXResizeElement(w, el);
}
}
}
}
//+------------------------------------------------------------------+
//| Формирует массив элементов с авто-ресайзом (Y) |
//+------------------------------------------------------------------+
void CWndEvents::FormAutoYResizeElementsArray(void) {
int windows_total = CWndContainer::WindowsTotal();
for(int w = 0; w < windows_total; w++) {
int elements_total = CWndContainer::ElementsTotal(w);
for(int e = 0; e < elements_total; e++) {
CElement *el = m_wnd[w].m_elements[e];
//--- Добавляем только те, у которых включен режим авто-ресайза
if(!el.AutoYResizeMode())
continue;
//---
if (dynamic_cast<CGraph *>(el) != NULL ||
dynamic_cast<CListView *>(el) != NULL ||
dynamic_cast<CStandardChart *>(el) != NULL ||
dynamic_cast<CTable *>(el) != NULL ||
dynamic_cast<CTabs *>(el) != NULL ||
dynamic_cast<CTextBox *>(el) != NULL ||
dynamic_cast<CFrame *>(el) != NULL) {
CWndContainer::AddAutoYResizeElement(w, el);
}
}
}
}
//+------------------------------------------------------------------+
//| Устанавливает состояние графика |
//+------------------------------------------------------------------+
void CWndEvents::SetChartState(void) {
int awi = m_active_window_index;
//--- Для определения события, когда нужно отключить управление
bool condition = false;
//--- Проверим окна
int windows_total = CWndContainer::WindowsTotal();
for(int i = 0; i < windows_total; i++) {
//--- Перейти к следующей, если эта форма скрыта
if(!m_windows[i].IsVisible())
continue;
//--- Проверить условия во внутреннем обработчике формы
m_windows[i].OnEvent(m_id, m_lparam, m_dparam, m_sparam);
//--- Если есть фокус, отметим это
if(m_windows[i].MouseFocus())
condition = true;
}
//--- Проверим фокус выпадающих списков
if(!condition) {
//--- Получим общее количество выпадающих списков
int drop_lists_total = CWndContainer::ElementsTotal(awi, E_DROP_LIST);
for(int i = 0; i < drop_lists_total; i++) {
//--- Получим указатель на выпадающий список
CListView *lv = m_wnd[awi].m_drop_lists[i];
//--- Если список активирован (открыт)
if(lv.IsVisible()) {
//--- Проверим фокус над списком и состояние его полосы прокрутки
if(m_wnd[awi].m_drop_lists[i].MouseFocus() || lv.ScrollState()) {
condition = true;
break;
}
}
}
}
//--- Проверим фокус выпадающих календарей
if(!condition) {
int drop_calendars_total = CWndContainer::ElementsTotal(awi, E_DROP_CALENDAR);
for(int i = 0; i < drop_calendars_total; i++) {
if(m_wnd[awi].m_drop_calendars[i].GetCalendarPointer().MouseFocus()) {
condition = true;
break;
}
}
}
//--- Проверим фокус контекстных меню
if(!condition) {
//--- Получим общее количество выпадающих контекстных меню
int context_menus_total = CWndContainer::ElementsTotal(awi, E_CONTEXT_MENU);
for(int i = 0; i < context_menus_total; i++) {
//--- Если фокус над контексным меню
if(m_wnd[awi].m_context_menus[i].MouseFocus()) {
condition = true;
break;
}
}
}
//--- Проверим состояние полос прокрутки
if(!condition) {
int scrolls_total = CWndContainer::ElementsTotal(awi, E_SCROLL);
for(int i = 0; i < scrolls_total; i++) {
if(((CScroll*)m_wnd[awi].m_scrolls[i]).State()) {
condition = true;
break;
}
}
}
//--- Устанавливаем состояние графика во всех формах
for(int i = 0; i < windows_total; i++)
m_windows[i].CustomEventChartState(condition);
}
//+------------------------------------------------------------------+