(?) Вопрос - возможно ли ЛИ "онлайн" обновление позиции объекта ?! (МТ-5)

 

Здравия, Уважаемые! 

Вопрос  такой:
а можно ли ЛИ сделать "онлайн обновление" положения объекта ?! (в МТ-5)

у меня суть такая:
на графике есть 2 объекта:
1) вертикальная линия со свободным перемещением <<-->> , 
2) прямоугольник OBJ_RECTANGLE с жёсткой привязкой левой стороной к вертикальной линии!

Суть:
при перемещении вертикальной линии <<-->>, чтобы прямоугольник обновлял свою позицию "мгновенно", при малейшем изменении положения вертикальной линии так, будто я двигаю НЕ вертикальную линию, а сам Прямоугольник за левый нижний или верхний угол ?!

Сейчас у меня этот момент реализован вот так:

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   
   // Обработка перетаскивания и отпускания мыши для вертикальной линии
   if(id == CHARTEVENT_OBJECT_DRAG  && sparam == INP_VLINE_NAME)
   {
      datetime d_time = (datetime)ObjectGetInteger(0, INP_VLINE_NAME, OBJPROP_TIME);
      if(d_time <= 0) return;

       // Устанавливаем левый край прямоугольника на вертикальную линию
    ObjectSetInteger(0, INP_RECT_NAME, OBJPROP_TIME, 1, (long)d_time);

    // Правый край прямоугольника на бар 0
    datetime t_right = (datetime)iTime(_Symbol, _Period, 0);
    ObjectSetInteger(0, INP_RECT_NAME, OBJPROP_TIME, 2, (long)t_right);

в итоге: переместив вертикалку - после отпускания ЛКМ и происходит обновление положения прямоугольника !
Соль в том, что обновления положения прямоугольника происходит ИМЕННО В МОМЕНТ ОТПУСКАНИЯ ЛКМ (!!!)
а хотелось-бы чтобы он обновлялся сразу-же, как-только я (с зажатой ЛКМ на вертикалке) перемещаю вертикалку <<-->> хоть на 1 пиксель !

Возможно ли такое ??

(...та и такая ^ формулировка кода почему-то НЕ ОБНОВЛЯЕТ правую сторону прямоугольника на Баре-0 (!) ... а вместо бара-0 -->> правый край прямоугольника прыгает на ТОТ бар, который был "назначен" для ЛЕВОЙ стороны прямоугольника в момент старта индикатора ... я поначалу думал что всё дело в не-приходе новых тиков из-за дисконнекта с "брокером", но Левая ж сторона ОБНОВЛЯЕТСЯ вслед за вертикалкой, а вот правая сторона - увы "глючит" ... и как временный вариант ==>> было принято решение стартовать рисование объектов на 1-м и 0-м барах, а потом двигать вертикалку куда понадобится ... только этот момент и спасает...)

я тогда (с помощью ИИ) сделал такой "костыль":

/*
 ... ниже - проба ИИ создать код, который бы отслеживал "НАЖАТИЕ ЛКМ + ПЕРЕМЕЩЕНИЕ" чтобы мгновенно обновлять 
левую сторону Прямоугольника, ... по этая функция увы неработает вообще (!) :(
*/

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
        // Начало перетаскивания — нажата ЛКМ на вертикальной линии
   if(id == CHARTEVENT_OBJECT_CLICK && sparam == INP_VLINE_NAME)
   {
      g_drag_active = true;
   }

   // Завершение перетаскивания — отпускание ЛКМ после drag
   if(id == CHARTEVENT_OBJECT_DRAG && sparam == INP_VLINE_NAME)
   {
      g_drag_active = false;
   }

   // Во время перетаскивания: движение мыши с зажатой ЛКМ
   if(id == CHARTEVENT_MOUSE_MOVE && g_drag_active)
   {
      int x = (int)lparam;
      int y = (int)dparam;
      int window = 0;
      datetime dt = 0;
      double price = 0;

      if(ChartXYToTimePrice(0, x, y, window, dt, price))
      {
         if(dt > 0 && price > 0)
         {
            // Обновляем левую границу прямоугольника (время)
            ObjectSetInteger(0, INP_RECT_NAME, OBJPROP_TIME, 1, (long)dt);

            // Правый край остаётся на баре 0
            datetime t_right = (datetime)iTime(_Symbol, _Period, 0);
            ObjectSetInteger(0, INP_RECT_NAME, OBJPROP_TIME, 2, (long)t_right);

            ChartRedraw();
         }
      }
      else
      {
         PrintFormat("ChartXYToTimePrice failed, error: %d", GetLastError());
      }
   }
}
/* вот только СЕЙЧАС заметил, что в коде от ИИ - есть какое-то ОБЪЯВЛЕНИЕ переменных Х и Y, но нету их "обработки" 
с отслеживанием координат курсора мышки в момент зажатия ЛКМ (начало флага g_drag_active = false;),
... видать поэтому этот модуль в коде и неработает ...
*/


ЧТО можете подсказать Вы из своего опыта - можно ли ЛИ всё-же сделать "мгновенное" обновление положения прямоугольника (без задержек) при перемещении вертикальной линии ?!

Документация по MQL5: Типы объектов / Константы, перечисления и структуры
Документация по MQL5: Типы объектов / Константы, перечисления и структуры
  • www.mql5.com
При создании графического объекта функцией ObjectCreate() необходимо указать тип создаваемого объекта, который может принимать одно из значений...
[Удален]  
Это абсолютно реально! 
 
Temirgali Orazbayev #:
Это абсолютно реально! 
ок, какой план действий нужен для этого ?!
(как вы это делаете на практике ?!)
 

Запустите таймер. Добавьте функцию OnTimer(), для контроля изменений во времени.

OnChartEvent() контролирует "нажатия", срабатывает на кнопки.
Справочник MQL5 / Основы языка / Функции / Функции обработки событий
 

На ИИ лучше не оглядываться, а брать инфу из документации - иначе ничего не заработает, т.к. ИИ требует такого же знания предмета для исправления его ошибок, как и самостоятельное написание кода. Даже если код ИИ откомпилируется, он почти на 100% не заработает правильно, а такие ошибки еще сложнее искать.

Могу порекомендовать в качестве отправной точки вот этот индикатор в блоге (описание на английском). Суть решения - включает сообщения мыши в OnInit с помощью вызова ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true). Тогда в OnCalculate можно перемещать нужные объекты в ответ на событие CHARTEVENT_MOUSE_MOVE - иначе оно не генерируется.

Но все такие решения будут сильно жрать CPU во время перемещения. В зависимости от назначения исходной задачи возможно всё можно реализовать проще - например, включив надписи у объектов (текст будет выводиться рядом с линией автоматически).

Instant estimation of profit, margin level, drawdown on MetaTrader charts
Instant estimation of profit, margin level, drawdown on MetaTrader charts
  • 2018.07.16
  • www.mql5.com
I'm sure all of you use the crosshair tool on MetaTrader's charts. It's very useful to measure distance in bars or points between 2 spots. Yet I was always wondering, why it does not provide an option
 

можно, но немного больше кода добавить придётся

ключ в комментарии

            //sparam == 1 левая кнопка нажата, 2 правая кнопка нажата, 16 средняя, 0 просто mouse move

а идея такая - event mouse move генерится в том числе и при нажатии (mouse_down)  на кнопку мыши, определяем это по sparam, далее получаем координаты мыши по паре дата цена, только один раз при обнаружении что кнопка мыши нажата, постоянно вызывать ChartTimePricetoXY и т.п. будет слишком тормозить работу терминала, а потом просто проверяем, что клик был именно по вертикальной линии. Далее пока генерится событие mouse move и не сработало событие OBJECT_CLICK таскаем свою линию и связанный с ней прямоугольник. После этого ещё и сработает событие OBJECT_DRAG где можно зафикировать статус кво произошедших изменений.

PS в моём примере кода еще надо будет определить и за какой угол прямоугольника идет перетаскивание FindByCorner()



          
         case CHARTEVENT_MOUSE_MOVE: {
         
           // if(id==CHARTEVENT_MOUSE_MOVE)      Comment("POINT: ",(int)lparam,",",(int)dparam,"\n",MouseState((uint)sparam));
         
            //Print(sparam);
            
            //тут надо получить положения мыши в виде координат
            //GetMousePos(lparam, dparam);
            if(state.Get() == STATE_SET_POINT_2) {
               GetMousePos(lparam, dparam);
               gObj.Track(mousePos.x, mousePos.y);
               //это redraw нужен при использовании без smart5i, что странно, так как в s5i данное событие не обрабатывается...
               ChartRedraw(0);
            }
            else  if(state.Get() == STATE_LIVE_NIKOVOLUME) {
               Print("move NV corner");
            
            }
            
            //sparam == 1 левая кнопка нажата, 2 правая кнопка нажата, 16 средняя, 0 просто mouse move
            if((int)sparam == 1) {
               
               //Print("LMB pressed");
               if(!isLMBPressed) {
                  GetMousePos(lparam, dparam);
                  //Print("LMB pressed ", mousePos.x, " - " , mousePos.y);
                  //find NV for find corner
                  nvLive = nvf.FindByCorner(mousePos.x, mousePos.y);
                  //Print("LMB pressed ", nvLive);
               
               }  else {
............... дальше код уже другой идёт