Обсуждение статьи "Улучшаем работу с Панелями: добавляем прозрачность, меняем цвет фона и наследуемся от CAppDialog/CWndClient"

 

Опубликована статья Улучшаем работу с Панелями: добавляем прозрачность, меняем цвет фона и наследуемся от CAppDialog/CWndClient:

Продолжаем изучать работу с CAppDialog. Теперь мы научимся задавать цвета фона, рамки и заголовка для графической панели. По шагам рассмотрим, как добавить прозрачность окна приложения при перемещении его на графике. Далее мы рассмотрим создание потомков от CAppDialog или CWndClient и увидим новые тонкости в работе с контролами. Наконец, посмотрим с новой точки зрения на новые Проекты.

Теперь в коде "Live panel and transparent Button.mq5" полностью реализовано изменение цвета панели и кнопки при перемещении панели:

Live panel and transparent Button


Автор: Vladimir Karputov

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Обсуждение статьи "Как создать графическую панель любой сложности и как это работает"

Rashid Umarov, 2018.04.23 10:30

Двойной клик - это два клика, между которыми совсем малый промежуток времени. Значит, обрабатываться может так же, как и обычный клик - нужно только добавить статическую переменную в OnChartEvent. Посмотрите пример в https://www.mql5.com/ru/docs/constants/chartconstants/enum_chartevents и сделайте примерно так:

....

Покажем на примере, как добавить обработку двойного клика на панели. Внесем правки в класс CMyWndClient



1. Переопределим виртуальный метод OnDblClick, который тянется еще из предка CWnd

class CMyWndClient : public CWndClient
  {
private:
   CButton           m_button1;                       // the button object
   CButton           m_button2;                       // the button object
   //--- scroll size
   int               m_scroll_size;                   // scroll_size
   //--- храним владельца
   CAppDialog        m_owner;                         // owner
   //--- скрывать невидимое
   bool              m_hide_invisble;
   //---
   bool              AddButton1(void);
   bool              AddButton2(void);
protected:
   //--- handlers of the dependent controls events
   void              OnClickButton1(void);
   void              OnClickButton2(void);
   void              OnShowScrollH(void);
   virtual bool      OnScrollLineRight(void);
   virtual bool      OnScrollLineLeft(void);
   virtual bool      OnDblClick(void);
.....
//+------------------------------------------------------------------+
//|  переопределим обработку события OnDblClick                      |
//+------------------------------------------------------------------+
bool CMyWndClient::OnDblClick(void)
  {
   Print(__FUNCTION__);
   return ColorBackground(GetRandomColor());
  }

2. Добавим обработку этого события

//+------------------------------------------------------------------+
//| Event Handling                                                   |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CMyWndClient)
ON_EVENT(ON_CLICK,m_button1,OnClickButton1)
ON_EVENT(ON_CLICK,m_button2,OnClickButton2)
ON_EVENT(ON_DBL_CLICK,this,OnDblClick)
ON_EVENT(ON_SHOW,m_scroll_h,OnShowScrollH)
EVENT_MAP_END(CWndClient)

3. В файле приложения  MyWndClient.mq5  добавим строки по отлову события DoubleClick

//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // event ID  
                  const long& lparam,   // event parameter of the long type
                  const double& dparam, // event parameter of the double type
                  const string& sparam) // event parameter of the string type
  {
//--- время последнего клика мышки
   static uint last_click=0;
//--- нажатие левой кнопкой мышки на графике
   if(id==CHARTEVENT_OBJECT_CLICK)   
     {
      uint click_time=GetTickCount();
      //Print("click_time=",click_time);
      //Print("Координаты щелчка мышки на графике: x = ",lparam,"  y = ",dparam);
      if(click_time-last_click<dbl_click_time)
        {
         PrintFormat("DoubleClick! time=%d msec",click_time-last_click);
         // отправим событие ON_DBL_CLICK клиентской области - пусть обработает 
         EventChartCustom(CONTROLS_SELF_MESSAGE,ON_DBL_CLICK,ClientArea.Id(),dparam,ClientArea.Name());       
        }
      last_click=click_time;
      //---
     }
   AppWindow.ChartEvent(id,lparam,dparam,sparam);
  }

Добавим во внешний параметр приложения время между кликами в миллисекундах - если оно меньше указанного, будет генерироваться событие DoubleClick

//+------------------------------------------------------------------+
//|                                                  MyWndClient.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.001"
#property description "Приложение MyWndClient на основе класса CMyWndClient"
#property description "Добавлены кнопки для установки цвета фона и заголовка"
#include "MyWndClient.mqh"
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
//--- input parameter
input bool InpTwoButtonsVisible=false; // ширина панели
input bool HideInvisble=false;         // скрыть невидимое
input uint dbl_click_time=500;         // период между кликами в msec

Файлы приложены. Можно смотреть как по отдельности, так и распаковать архив в папку MQL5\Experts

Файлы:
 

На видео показано, что событие двойного клика отрабатывает только на панели. Вне панели событие не перехватывается.

Файлы:
 
Интересно, можно ли сделать панель непрозрачной для мыши. При перетаскивании и даже редактировании в поле Edit  цепляются объекты на графике, стопы перетаскиваются.
 
Photic:
Интересно, можно ли сделать панель непрозрачной для мыши. При перетаскивании и даже редактировании в поле Edit  цепляются объекты на графике, стопы перетаскиваются.

Плюсую. Очень часто стопы и тейки задеваются таким образом. 

Можно пробовать решать это изменением их вида на виртуальные - если линии не выбраны для редактирования, перенос панели их не цепляет.

И еще ...было бы классно узнать, как сделать вывод текущей информации (например, профит по открытым Buy или Sell или любую изменяющуюся текущую информацию) в само окно панели?

Может, кто-то делал что-либо подобное. МТ4.

 
Vyacheslav Nekipelov:

***

И еще ...было бы классно узнать, как сделать вывод текущей информации (например, профит по открытым Buy или Sell или любую изменяющуюся текущую информацию) в само окно панели?

Может, кто-то делал что-либо подобное. МТ4.

Выводить в панель можно что угодно - необходимо только прописать новые методы ответственные за вывод.

Но для старого терминала неинтересно.

Вот пример панели, которая выводит информацию о позициях: https://www.mql5.com/ru/code/16931
 
Vladimir Karputov:
Вот пример панели, которая выводит информацию о позициях: https://www.mql5.com/ru/code/16931

Спасибо большое) Нужно будет как-то посмотреть эту тему.

 

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

У Вас не получилось увидеть, почему первый раз заголовок закрашивается вместе с кнопками закрытия, а после сворачивания/разворачивания изменения цветов уже не влияют на элементы управления?


 
Vasiliy Pushkaryov:

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

У Вас не получилось увидеть, почему первый раз заголовок закрашивается вместе с кнопками закрытия, а после сворачивания/разворачивания изменения цветов уже не влияют на элементы управления?


Я обнаружил причину. Посмотрите на ширину заголовка после первого запуска и после сворачивания/разворачивания:

Ширина заголовка после первого запуска

Рис. 1. Ширина заголовка после первого запуска


Ширина заголовка после сворачивания/разворачивания

Рис. 2. Ширина заголовка после сворачивания/разворачивания


 
Vladimir Karputov:

Я обнаружил причину. Посмотрите на ширину заголовка после первого запуска и после сворачивания/разворачивания:


Отлично, спасибо. Добавил в код одну строку и нажатие по кнопке стало закрашивать заголовок полностью.

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CLivePaneButtonClicks::OnClickButton2(void)
  {
   string prefix=Name();
   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Caption")
        {
         CEdit *edit=(CEdit*) obj;
         color clr=(color)GETRGB(XRGB(rand()%255,rand()%255,rand()%255));
         edit.ColorBackground(clr);
         edit.Width(336);
         ChartRedraw();
         return;
        }
     }
  }

Теперь можно просто переопределить этот момент в функциях

    virtual void    Minimize(void);
    virtual void    Maximize(void);

И все будет в порядке.

Но я с Вашего позволения напомню пару раз в ветках с новыми билдами об этой особенности. Может поправят.

 

Владимир, спасибо за статьи, очень полезный материал. У меня может быть ламерский вопрос...

Есть объект типа CBmpButton - кнопка с изображением. Так вот, само изображение кнопки выступает тут в качестве ресурса. Как получить доступ к его свойствам? Или нельзя?

Пример из Документации. 

Там я поиграл с методом CControlsDialog::CreateBmpButton1():

//+------------------------------------------------------------------+
//| Create the "BmpButton1" button                                   |
//+------------------------------------------------------------------+
bool CControlsDialog::CreateBmpButton1(void)
  {
//--- coordinates
   int x1 = INDENT_LEFT;
   int y1 = INDENT_TOP + (EDIT_HEIGHT + CONTROLS_GAP_Y);
   int x2 = x1 + BUTTON_WIDTH;
   int y2 = y1 + BUTTON_HEIGHT;
//--- create
   if(!m_bmpbutton1.Create(m_chart_id, m_name + "BmpButton1", m_subwin, x1, y1, x2, y2))
      return(false);
//--- sets the name of bmp files of the control CBmpButton
   string name1, name2;
   name1 = "\\Images\\euro.bmp";
   name2 = "\\Images\\dollar.bmp";
   m_bmpbutton1.BmpNames(name1, name2);
   if(!Add(m_bmpbutton1))
      return(false);
   m_chart.Redraw();
   if(ObjectFind(m_chart_id, name1) >= 0)
     {
      DebugBreak();
     }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+

Объект самого изображения на панели не находится с помощью функции ObjectFind(), что вполне ест-но. А как его найти, если это вообще возможно?

Спасибо.

Причина обращения: