Обсуждение статьи "Графические интерфейсы II: Элементы "Разделительная линия" и "Контекстное меню" (Глава 2)"

 

Опубликована статья Графические интерфейсы II: Элементы "Разделительная линия" и "Контекстное меню" (Глава 2):

В этой статье мы создадим элемент «Разделительная линия». Его, как и класс для создания меню, описанный в предыдущей главе, тоже можно будет использовать не только как независимый элемент интерфейса, но и как часть многих других элементов. После этого у нас будет всё необходимое для разработки класса контекстного меню, которое тоже будет подробно рассмотрено в этой статье. Кроме этого, вносятся необходимые дополнения в класс, который является базой для хранения указателей на все элементы графического интерфейса приложения.

О том, для чего предназначена эта библиотека, более подробно можно прочитать в первой статье серии: Графические интерфейсы I: Подготовка структуры библиотеки (Глава 1).  

Разработка класса для создания разделительной линии

В контекстном меню, помимо различных типов пунктов меню, часто можно увидеть ещё один элемент интерфейса — разделительную линию. Этот элемент встречается не только в контекстных меню. Например, в статусной строке торгового терминала MetaTrader и редактора кода MetaEditor тоже можно увидеть вертикальные разделительные линии. Поэтому для этого объекта мы создадим отдельный класс, чтобы его можно было применить в любом другом элементе управления или даже просто использовать как отдельный элемент дизайна графического интерфейса.

Чтобы имитировать рельефность, разделительная линия должна состоять минимум из двух частей. Если одну линию сделать светлее фона, а другую — темнее, то визуально мы получим своеобразную канавку на поверхности. Есть два варианта для создания разделительной линии: (1) из двух объектов-примитивов типа CRectLabel, который у нас уже есть в файле Objects.mqh, или (2) создать объект типа OBJ_BITMAP_LABEL и использовать его как холст для рисования. Воспользуемся вторым вариантом. Для рисования стандартная библиотека предлагает класс CCanvas. В этом классе уже есть все необходимые методы для рисования простых геометрических фигур, что существенно облегчит реализацию задуманного и сэкономит много времени. 

Класс CCanvas нужно внедрить в нашу разрабатываемую библиотеку таким образом, чтобы была возможность использовать его подобно тем объектам-примитивам, которые сейчас содержатся в файле Objects.mqh. Этого легко можно добиться, сделав класс CCanvas производным от класса CChartObjectBmpLabel. Но придётся внести маленькое изменение в код класса CCanvas, чтобы впоследствии не возникло ошибок или предупреждений при компиляции программы. Дело в том, что и в классе CCanvas, и в классе CChartObject, который является базовым для класса CChartObjectBmpLabel, есть поле (переменная) m_chart_id. В результате компилятор выдаст предупреждение о том, что переменная с таким именем уже существует:

Рис. 1. Предупреждение компилятора о том, что переменная с таким именем уже существует.

Рис. 1. Предупреждение компилятора


Автор: Anatoli Kazharski

 
А предусматривается использование механизма привязки/делегирования действий/команд к разным контролам? Например к кнопке в тулбаре и пункте контекстного меню? Для этого подошел бы паттерн "команда". Заодно, можно реализовывать механизм Undo/Redo через хранение в истории выполненных команд сохраняя исходные значения получателя.

Также неплохо ввести понятие модели, которую слушает тот или иной контрол (паттерн наблюдатель). Это позволит прозрачно реагировать всем котролам в интерфейсе на изменения в модели.

Например, пока у модели чарта пользователь не проинициализировал все параметры, все контролы связанные с управлением чарта имеют disable вид. Это избавляет от обращений непосредственно к контролам и логики отвечающей за их поведение в тех или иных случаях.
 
Igor Volodin:
А предусматривается использование механизма привязки/делегирования действий/команд к разным контролам? Например к кнопке в тулбаре и пункте контекстного меню? Для этого подошел бы паттерн "команда". Заодно, можно реализовывать механизм Undo/Redo через хранение в истории выполненных команд сохраняя исходные значения получателя.

Также неплохо ввести понятие модели, которую слушает тот или иной контрол (паттерн наблюдатель). Это позволит прозрачно реагировать всем котролам в интерфейсе на изменения в модели.

Например, пока у модели чарта пользователь не проинициализировал все параметры, все контролы связанные с управлением чарта имеют disable вид. Это избавляет от обращений непосредственно к контролам и логики отвечающей за их поведение в тех или иных случаях.

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

Что касается дополнительных механизмов, то всё это обсуждаемо. После публикации всей серии можно будет пройтись по всем пунктам схемы и составить список того, что нужно изменить или добавить, при наличии аргументов, почему так будет лучше/надёжней/удобней и т.д.

Возможно я неправильно понял вопрос. Тогда нужны уточнения, что именно нужно получить и как это должно выглядеть.

 
А зачем массив переменных ?
color             m_area_color_array[];
И в конструкторе CContextMenu() нужно переменную m_item_Ysize задать размер большим нуля по умолчанию.
Причина обращения: