Обсуждение статьи "Делаем информационную панель для отображения данных в индикаторах и советниках" - страница 4

 
Denis Kirichenko #:
Move(int x, int y)

Где-то тут есть недоработка. Нужно принтовать (или в отладчике глядеть, но он часто не работает) значения координат и размеров.

Вот логика в комментариях:

   //--- Если панель по высоте не больше размера окна по высоте
   if(!this.m_higher_wnd)
     {
      if(y+h>this.m_chart_h-2)
         y=this.m_chart_h-h-2;
      if(y<1)
         y=1;
     }
   //--- Если панель по высоте не входит в размер окна по высоте
   else
     {
      //--- Не даём панели опускаться ниже верхней грани окна с зазором в 1 пиксель
      if(y>1)
         y=1;
      //--- Не даём панели провалиться ниже нижней грани окна с зазором в 1 пиксель
      if(y<this.m_chart_h-h-2)
         y=this.m_chart_h-h-2;
     }
 
Denis Kirichenko #:
При попытке сдвинуть панель после изменений размера графика, он постоянно корректирует координаты и не даёт свободно перемещать окно панели...

Скорее всего значение переменной this.m_higher_wnd не актуально в методе Move(). Эти значения устанавливаются в обработчике событий:

//+------------------------------------------------------------------+
//| Обработчик событий                                               |
//+------------------------------------------------------------------+
void CDashboard::OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Если создан графический  объект
   if(id==CHARTEVENT_OBJECT_CREATE)
     {
      this.BringToTop();
      ::ObjectSetInteger(this.m_chart_id,sparam,OBJPROP_SELECTED,true);
     }
//--- Если график изменён
   if(id==CHARTEVENT_CHART_CHANGE)
     {
      //--- Получаем номер подокна графика, если это не главное окно (номер может измениться при удалении окна какого-либо индикатора)
      if(this.m_wnd!=0)
         this.m_wnd=this.GetSubWindow();
      //--- Получаем новые размеры графика
      int w=(int)::ChartGetInteger(this.m_chart_id,CHART_WIDTH_IN_PIXELS,this.m_wnd);
      int h=(int)::ChartGetInteger(this.m_chart_id,CHART_HEIGHT_IN_PIXELS,this.m_wnd);
      //--- Определяем выход размеров панели за пределы окна графика
      this.m_higher_wnd=this.HigherWnd();
      this.m_wider_wnd=this.WiderWnd();
      //--- Если высота графика изменилась - корректируем расположение панели по вертикали
      if(this.m_chart_h!=h)
        {
         this.m_chart_h=h;
         int y=this.m_y;
         if(this.m_y+this.m_h>h-1)
            y=h-this.m_h-1;
         if(y<1)
            y=1;
         this.Move(this.m_x,y);
        }
      //--- Если ширина графика изменилась - корректируем расположение панели по горизонтали
      if(this.m_chart_w!=w)
        {
         this.m_chart_w=w;
         int x=this.m_x;
         if(this.m_x+this.m_w>w-1)
            x=w-this.m_w-1;
         if(x<1)
            x=1;
         this.Move(x,this.m_y);
        }
     }

Вполне возможно, что где-то здесь не правильно выставляются флаги превышения размеров при разворачивании окна графика.

Если вписать эти строчки

this.m_higher_wnd=this.HigherWnd();
this.m_wider_wnd=this.WiderWnd();

в самом начале метода Move() - чтобы принудительно устанавливать корректные значения при каждом движении мышки, баг пропадёт? Если пропадёт - значит дело в значениях этих переменных, и нужно в обработчике событий смотреть почему они не получают своих значений при разворачивании окна. Ну, а если там всё нормально, значит нужно принтовать метод Move() для поиска ошибки.

 

Баг пропал. В метод CDashboard::OnChartEvent() внёс такие изменения:


//--- Если график изменён
   if(id == CHARTEVENT_CHART_CHANGE)
     {
      //--- Получаем номер подокна графика, если это не главное окно (номер может измениться при удалении окна какого-либо индикатора)
      if(m_wnd != 0)
         m_wnd = GetSubWindow();
      //
      long value;
      // сбросим значение ошибки
      ::ResetLastError();
      // получим значение свойства
      if(!::ChartGetInteger(m_chart_id, CHART_BRING_TO_TOP, m_wnd, value))
        {
         //--- выведем сообщение об ошибке в журнал "Эксперты"
         Print(__FUNCTION__ + ", Error Code = ", ::GetLastError());
         return;
        }
      // если это не показ графика поверх всех других - выходим
      if(value == 0)
         return;
      //--- Получаем новые размеры графика
      int w = (int)::ChartGetInteger(m_chart_id, CHART_WIDTH_IN_PIXELS, m_wnd);
      int h = (int)::ChartGetInteger(m_chart_id, CHART_HEIGHT_IN_PIXELS, m_wnd);
      //--- Определяем выход размеров панели за пределы окна графика
      //m_higher_wnd = HigherWnd();
      //m_wider_wnd = WiderWnd();
      //--- Если высота графика изменилась - корректируем расположение панели по вертикали
      if(m_chart_h != h)
        {
         m_chart_h = h;
         m_higher_wnd = HigherWnd(); // added
         int y = m_y;
         if(m_y + m_h > h - 1)
            y = h - m_h - 1;
         if(y < 1)
            y = 1;
         Move(m_x, y);
        }
      //--- Если ширина графика изменилась - корректируем расположение панели по горизонтали
      if(m_chart_w != w)
        {
         m_chart_w = w; 
         m_wider_wnd = WiderWnd(); // added
         int x = m_x;
         if(m_x + m_w > w - 1)
            x = w - m_w - 1;
         if(x < 1)
            x = 1;
         Move(x, m_y);
        }
     }


Чтобы постоянно не нагружать метод CDashboard::Move(), добавил проверку флагов превышения размеров в те блоки, где непосредственно меняются ширина и высота окна графика.


 
Denis Kirichenko #:

Баг пропал. В метод CDashboard::OnChartEvent() внёс такие изменения:

Чтобы постоянно не нагружать метод CDashboard::Move(), добавил проверку флагов превышения размеров в те блоки, где непосредственно меняются ширина и высота окна графика.

Спасибо. Впишу себе.