Обсуждение статьи "Рецепты MQL5 - Элементы управления в подокне индикатора - Кнопки" - страница 7

 
TheXpert:
Вы так уверены что в вашей статье все идеально?

Очень приятно, что Вы её читали.

С удовольствием отвечу на все вопросы в соответствующей ветке.

===

Чтоб не было лишних заблуждений, я против Анатолия ни чего не имею! За статью ему респект! Но на вопросы ответить надо...

 
DC2008:

Извините, а я Вас случайно не отвлекаю от написания очередного учебного пособия или рецепта?

Если нет, то давайте продолжим обсуждение Вашей статьи про управление в подокне индикатора. Итак, Вы предлагаете массовое решение (или идею) как сделать удобное меню в индикаторе. Хорошо, цель статьи очень достойна! Но как "начинающему" программисту воспользоваться всем этим арсеналом? Куда разместить пользовательские функции? Продемонстрируйте на примере. А заодно объясните, что нужно исправить в коде чтобы использовать например, 5 кнопок? Считайте это вопрос начинающего.

Нет, не отвлекаете. Я пока ничего не пишу. Надо же иногда отдыхать хотя бы один день в году. Просто отдыхать не интересно, тем более долго. )

Это не массовое решение и я об этом не писал. Давайте Вы не будете приписывать то, чего не было. В начале обсуждения уже было озвучено, что это не универсальное решение, а частный случай. На мой взгляд хороший пример, чтобы попрактиковаться начинающему. А не получить готовое решение на халяву и побежать, разинув рот в широкой улыбке, на встречу солнцу. ) Понимаете? Мне бы такой простой и понятный пример в самом начале изучения программирования. Особенно, когда это первый язык программирования в жизни и до этого род деятельности всю жизнь был в абсолютно другой области, никак с этим не связанный. 

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

Массив состояний кнопок есть, поэтому по такому же принципу можно производить проверку, какая кнопка нажата и вместо простого изменения цвета кнопки, производить какое-то другое (нужное пользователю) действие. Это могут быть например торговые функции (и не только): удаление всех отложенных ордеров, закрытие всех позиций и т.д. Идей бесконечное множество. А если нет идей, то выбран не тот род деятельности. )

Для того, чтобы это реализовать нужно создать ещё один массив, который будет проинициализирован идентификаторами пользовательского перечисления (которое тоже нужно создать), например, с названием ENUM_SCRIPT. А идентификаторы тогда будут называться, например: SCRIPT_01 =0, SCRIPT_02 =2 и т.д. Также в цикле, при проверке нажата ли кнопка на панели, нужно будет определить, какой идентификатор привязан к нажатой кнопке и текущее состояние кнопки, а далее передать на исполнение программе соответствующую функцию.

Пример кода показывать специально не буду. Для начинающих пусть это будет домашним заданием. )

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров - Документация по MQL5
 

Внёс изменения, как Вы и сказали:

//--- Отображаемый текст в кнопках
string button_texts[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"Button 01","Button 02","Button 03","Button 04"},
     {"Button 05"}
  };
//--- Названия объектов
string button_object_names[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"button_01","button_02","button_03","button_04"},
     {"button_05"}
  };
....
bool button_states[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {true,false,false,false},
     {false}
  };

И вот что получил на экране:

 

Как исправить? (я новичёк)

 
DC2008:

Внёс изменения, как Вы и сказали:

И вот что получил на экране:

 

Как исправить? (я новичёк)

Вот так:

#define BUTTON_COLUMNS 5 // Количество кнопок по ширине
#define BUTTON_ROWS    1 // Количество кнопок по высоте
...
//--- Отображаемый текст в кнопках
string button_texts[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"Button 01","Button 02","Button 03","Button 04","Button 05"}
  };
//--- Названия объектов
string button_object_names[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"button_01","button_02","button_03","button_04","button_05"}
  };
...
//--- Состояния кнопок
bool button_states[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {true,false,false,false,false}
  };
 

Отлично! Заработало.

Но вот как мои функции подцепить к кнопкам я не понял. Покажите на примере.

 
DC2008:

Отлично! Заработало.

Но вот как мои функции подцепить к кнопкам я не понял. Покажите на примере.

Хорошо, давайте продолжим начатую Вами игру в "новичка". )

На каком моменте застряли? Покажите попытку того, как поняли на текущий момент. Создайте перечисление с пятью идентификаторами и массив, элементам которого нужно назначить эти идентификаторы.

 
bool fun_states[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {true,false,false,false,false}
  };
enum ENUM_SCRIPT
  {
   SCRIPT_01 =0,
   SCRIPT_02 =1,
   SCRIPT_03 =2,
   SCRIPT_04 =3,
   SCRIPT_05 =4,
  };
void F1()
  {Print("F1");}
bool F2()
  {Print("F2");return(false);}
int F3()
  {Print("F3");return(0);}
double F4()
  {Print("F4");return(0.1);}
color F5()
  {Print("F5");return(clrAliceBlue);}

И что делать дальше?

 
DC2008:

И что делать дальше?

Вот такой массив нужен:

//--- Скрипты
ENUM_SCRIPT buttons_scripts[NUMBER_BUTTONS_HEIGHT][NUMBER_BUTTONS_WIDTH]=
  {
     {SCRIPT_01,SCRIPT_02,SCRIPT_03,SCRIPT_04,SCRIPT_05}
  };

Затем нужно написать примерно вот такую функцию:

//+------------------------------------------------------------------+
//| Исполнение скриптов                                              |
//+------------------------------------------------------------------+
void ScriptOn()
  {
   for(int i=0; i<NUMBER_BUTTONS_WIDTH; i++)
     {
      for(int j=0; j<NUMBER_BUTTONS_HEIGHT; j++)
        {
         //--- Если эта кнопка нажата, запустим соответствующий скрипт
         if(buttons_state[j][i])
           {
            if(buttons_scripts[j][i]==SCRIPT_01)
              {
               F1();
               return;
              }
            //---
            if(buttons_scripts[j][i]==SCRIPT_02)
              {
               F2();
               return;
              }
            //---
            if(buttons_scripts[j][i]==SCRIPT_03)
              {
               F3();
               return;
              }
            //---
            if(buttons_scripts[j][i]==SCRIPT_04)
              {
               F4();
               return;
              }
            //---
            if(buttons_scripts[j][i]==SCRIPT_05)
              {
               F5();
               return;
              }
           }
        }
     }
  }

...и расположить эту функцию вот в этой части кода:

//--- Отслеживание нажатий на графическом объекте левой кнопкой мыши
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Если кликнули по кнопке
      if(InitializeButtonStates(sparam))
        {
         //--- Установим цвета для кнопок
         ChangeButtonColorOnClick();
         //--- Запустить скрипт
         ScriptOn();
        }
      //--- Обновим график
      ChartRedraw();
      return;
     }

А дальше можно подумать, как оптимизировать код, если в этом есть необходимость. :)

 
tol64:

Так у меня так и сделано.

Программа, в которой включается при запуске отслеживание, выключает его при выгрузке. А программа, которая осталась на графике и которой нужно отслеживание, проверяет, включено ли оно, и если отключено, то включает.

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

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

Может, предложить разработчикам генерировать CHARTEVENT_CHART_CHANGE при изменении CHART_EVENT_MOUSE_MOVE? Тогда вообще можно будет элегантно восстанавливать необходимую настройку при работающем советнике.

 

А пока у меня получился вот такой вариант:

#property copyright "Copyright 2013, komposter"
#property link      "http://www.komposter.me/"
#property version   "1.00"
#property indicator_chart_window

input   bool    EnableMouseDetect = false; // true - работать с отслеживанием мыши, false - без

bool PrevState = false;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
        if ( EnableMouseDetect )
        {
                //--- Получим текущее состояние
                PrevState = (bool)ChartGetInteger(0,CHART_EVENT_MOUSE_MOVE);
                //--- Включим слежение за событиями мыши
                if ( PrevState == false ) ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
        }

        return(0);
}

//+------------------------------------------------------------------+
//| Deinitialization function of the expert                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        if ( EnableMouseDetect )
        {
                //--- Отключим слежение за событиями мыши
                if ( PrevState == false )
                {
                        ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,false);
                        ChartRedraw(); // Без этой строки отслеживание отключается только с приходом тика. Так задумано?..
                }
        }
}

//+------------------------------------------------------------------+
//| OnTick                                                           |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                     const int prev_calculated,
                     const datetime& time[],
                     const double& open[],
                     const double& high[],
                     const double& low[],
                     const double& close[],
                     const long& tick_volume[],
                     const long& volume[],
                     const int& spread[])
       {
        
        return(rates_total);
       }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int    id,
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- Отслеживание движения мыши и нажатия левой кнопки мыши
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      static int count=1;
      Print("CHARTEVENT_MOUSE_MOVE; EXPERT; ",count);
      count++;
     }
  }
//+------------------------------------------------------------------+

 

Сделал один индикатор, но с параметром: запускаем с EnableMouseDetect = true - управляет отслеживанием, false - просто принтит количество событий, если отслеживание включено.


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

А в свете проведенных тут исследований (про нагрузку на процессор) в таких костылях нет необходимости.

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

 
ChartRedraw(); // Без этой строки отслеживание отключается только с приходом тика. Так задумано?..
В МТ5 асинхронное обновление свойств чарта. Т.е. то что мы установили свойство, еще не говорит о том, что терминал его тут же подобрал. Для того, что бы все свойства перечитались терминалом заново и используется функция ChartRedraw(). Также можно использовать функции ChartGet... ObjectGet, в этом случае свойства также будут перечитаны.
Документация по MQL5: Операции с графиками / ChartRedraw
Документация по MQL5: Операции с графиками / ChartRedraw
  • www.mql5.com
Операции с графиками / ChartRedraw - Документация по MQL5
Причина обращения: