Обсуждение статьи "Применение контейнеров для компоновки графического интерфейса: класс CBox"

 

Опубликована статья Применение контейнеров для компоновки графического интерфейса: класс CBox:

В данной статье описан альтернативный метод создания графического интерфейса на основе схем компоновки и контейнеров при помощи менеджера компоновки, а именно класса CBox. Класс CBox представляет собой вспомогательное средство управления, которое действует как контейнер основных элементов управления графического интерфейса. Он упрощает составление графических панелей, а иногда и сокращает время написания кода.

Самым простым способом создания графического интерфейса для какого-либо приложения является абсолютное расположение элементов управления внутри его диалогового окна. Тем не менее, иногда подобный подход к проектированию графического пользовательского интерфейса может быть неудобным и даже практически нецелесообразным. В данной статье описан альтернативный метод создания графического интерфейса на основе схем компоновки и контейнеров при помощи менеджера компоновки, а именно класса CBox.

Реализованный и используемый в данной статье класс менеджера компоновки в общих чертах схож с классами, применяемыми в некоторых широко распространенных языках программирования, например BoxLayout (Java) и Pack geometry manager (Python/Tkinter).


3.1. Стили компоновки

CBox предлагает два стиля компоновки: вертикальный и горизонтальный.

Базовая компоновка горизонтального стиля выглядит следующим образом:

Горизонтальный стиль класса CBox

Рис. 2. Горизонтальный стиль (центрированный)

Базовая компоновка вертикального стиля выглядит следующим образом:

Вертикальный стиль класса CBox

Рис. 3. Вертикальный стиль (центрированный)

По умолчанию CBox применяет горизонтальный стиль.

Комбинация данных типов компоновки (возможно, с использованием нескольких контейнеров) позволяет воссоздать практически любой вариант графического интерфейса. Более того, размещение элементов внутри контейнеров допускает сегментированное проектирование. Иными словами, вы можете изменять размер и расположение элементов управления в одном контейнере без воздействия на элементы других контейнеров.

Автор: Enrico Lambino

 

такой класс нужно в стандартные  внести разработчиками!

супер!!!

 

Столкнулся с проблемой в данной полезной надстройке.

Прошу совета у тех, кто разбирается в стандартных контролах.

Поскольку данная надстройка с панелями использует стандартные классы CWnd, CWndClient, я предполагаю, что знаний их внутреннего устройства может оказаться достаточно, чтобы понять, где "собака порылась".

Суть проблемы. Берем программу Controls2.mq5 из статьи (для компиляции нужны также ControlsDialog2.mqh и Box.mqh), компилируем, запускаем.

Почти всё работает нормально кроме "дейтпикера". Он только открывается и закрывается, но в открытом состоянии не реагирует на нажатия, пропуская события в нижележащие контролы.

Исходная аналогичная демка от MQ (Experts/Examples/Controls.mq5) работает с "дейтпикером" нормально.

 
Stanislav Korotky:

Почти всё работает нормально кроме "дейтпикера". Он только открывается и закрывается, но в открытом состоянии не реагирует на нажатия, пропуская события в нижележащие контролы.

Исходная аналогичная демка от MQ (Experts/Examples/Controls.mq5) работает с "дейтпикером" нормально.

Вопрос снимается. В CDatePicker отсутствует вызов BringToTop в момент раскрытия выпадающей части, как сделано в CComboBox, например. В стандартном примере дейтпикер работает за счет того, что его инициализацию подвинули (намеренно или случайно) после создания "листбокса", который оказывается топологически под ним. А контролы в CWndContainer::OnMouseEvent обходятся от последних добавленных к первым.

Чтобы нормально пофиксить, надо было бы переопределить CDatePicker::ListShow, но он не виртуальный. Приходится переопределять CDatePicker::OnClickButton и добавлять туда BringToTop. Однако корректно это сделать не получается как и с любым виртуальным методом в стандартной библиотеке, потому что все переменные члены объявлены private. В частности нельзя написать:

bool MyDatePicker::OnClickButton(void) // override
{
    return ((m_drop.Pressed()) ? BringToTop() && ListShow() : ListHide());
}

потому что m_drop недоступен. Приходится вызывать BringToTop и при раскрытии, и при схлопывании.

#include <Controls/DatePicker.mqh>

class CDatePickerFixed: public CDatePicker
{
  protected:
    virtual bool OnClickButton() override
    {
      BringToTop();
      return CDatePicker::OnClickButton();
    }
};