События с графическими объектами
Для графических объектов, находящихся на графике, терминал генерирует несколько специализированных событий. Большинство из них относится к объектам любых типов. Событие окончания редактирования текста в поле ввода — CHARTEVENT_OBJECT_ENDEDIT — генерируется только для объектов типа OBJ_EDIT.
События щелчка мышью на объекте (CHARTEVENT_OBJECT_CLICK), буксировки мышью (CHARTEVENT_OBJECT_DRAG) и изменения свойств объека (CHARTEVENT_OBJECT_CHANGE) активны всегда, в то время как события создания объекта CHARTEVENT_OBJECT_CREATE и удаления объекта CHARTEVENT_OBJECT_DELETE требуют явного включения путем установки свойств графика: CHART_EVENT_OBJECT_CREATE и CHART_EVENT_OBJECT_DELETE.
При переименовании объекта вручную (из диалога свойств) терминал генерирует последовательность событий CHARTEVENT_OBJECT_DELETE, CHARTEVENT_OBJECT_CREATE, CHARTEVENT_OBJECT_CHANGE. При программном переименовании объекта эти события не генерируются.
Все события в объектах несут имя связанного объекта в параметре sparam функции OnChartEvent.
Кроме того, для CHARTEVENT_OBJECT_CLICK передаются координаты щелчка: X в параметре lparam и Y в параметре dparam. Координаты являются общими для всего графика, включая подокна.
Щелчок мышью на объектах работает по-разному в зависимости от типа объекта. Для некоторых, таких как эллипс, курсор должен находиться над любой точкой привязки. Для других (треугольник, прямоугольник, линии) курсор может быть над периметром объекта, а не только над точкой. Во всех таких случаях при наведении курсора мыши на интерактивный участок объекта появляется всплывающая подсказка с названием объекта.
Объекты с привязкой к экранным координатам, позволяющие формировать графический интерфейс программы, в частности, кнопка, поле ввода, прямоугольная панель, — генерируют события при щелчке мышью в любом месте внутри объекта.
При наличии нескольких объектов под курсором, событие генерируется для объекта с наибольшим Z-приоритетом. Если приоритеты объектов равны, событие приписывается тому, который был создан позднее (это соответствует их визуальному отображению, то есть более поздний перекрывает более ранний).
Проверить события в объектах поможет новая версия индикатора EventAllObjects.mq5. Мы в ней создадим и настроим с помощью уже известного класса ObjectSelector несколько объектов, а затем перехватим в обработчике OnChartEvent их характерные события.
#include <MQL5Book/ObjectMonitor.mqh>
|
Изначально в OnInit создается объект-кнопка и вертикальная линия. Для линии будем отслеживать событие перемещения (буксировки), а по нажатию кнопки — создадим поле ввода, для которого будем проверять введенный текст.
const string ObjNamePrefix = "EventShow-";
|
Попутно не забываем установить свойства графика CHART_EVENT_OBJECT_CREATE и CHART_EVENT_OBJECT_DELETE в true, чтобы получать уведомления об изменении набора объектов.
В функции OnChartEvent обеспечим дополнительную реакцию на требуемые события: по завершении буксировки выведем в журнал новую позицию линии, а по завершении редактирования текста в поле ввода — его содержимое.
void OnChartEvent(const int id,
|
Обратите внимание, что когда кнопка нажимается первый раз, её состояние меняется с отжатого на нажатое, и в ответ на это мы создаем поле ввода. Если же щелкнуть кнопку еще раз, она сменит состояние обратно, в результате чего поле ввода будет удалено с графика.
Ниже приведено изображение графика в процессе работы индикатора.
Объекты, контролируемые обработчиком событий OnChartEvent
Сразу после запуска индикатора в журнале появляются такие строки:
CHARTEVENT_OBJECT_CREATE 0 0.000000 'EventShow-Button'
|
Если затем перетащить линию мышью, увидим примерно следующее:
CHARTEVENT_OBJECT_DRAG 0 0.000000 'EventShow-VLine'
|
Далее можно нажать кнопку и отредактировать текст в только что созданном поле ввода (по завершении редактирования нажмите Enter или щелкните мышью за пределами поля ввода). Это приведет к появлению таких записей в журнале (координаты и текст сообщения могут отличаться — здесь был введен текст "new message"):
CHARTEVENT_OBJECT_CLICK 181 113.000000 'EventShow-Button'
|
Если после этого отжать кнопку, поле ввода удалится.
CHARTEVENT_OBJECT_CLICK 162 109.000000 'EventShow-Button'
|
Стоит отметить, что кнопка работает по умолчанию как двухпозиционный переключатель, то есть "залипает" попеременно в нажатом или отжатом состоянии в результате клика мышью. Для обычной кнопки такое поведение излишне: чтобы просто отслеживать нажатия кнопки, следует при обработке события возвращать её в отжатое состояние вызовом ObjectSetInteger(0, ButtonName, OBJPROP_STATE, false).