Скачать MetaTrader 5

Нужен пример использования ComboBox

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Нет компьютера под рукой? Переписывайся с друзьями с помощью телефона!
Andy
564
Andy 2013.06.14 07:32 

Привет,

Есть ли у кого ссылки на то как правильно создавать, заполнять и реагировать на события CComboBox.

Создаю его так :

class CCurrencyBox : public CComboBox
{
    bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
    {
        return true;
    }
};

CCurrencyBox * CurrencyBox;
CurrencyBox = new CCurrencyBox();

    CurrencyBox.ListViewItems(5);
    CurrencyBox.AddItem("Demo1");
    CurrencyBox.ItemAdd("Demo2");
    CurrencyBox.ItemInsert(0, "Demo3");
    CurrencyBox.Activate();
    CurrencyBox.Enable();
    CurrencyBox.Show();
    CurrencyBox.Size(200, 30);
    CurrencyBox.Create(ChartID(), "Demo", Chart, 10, 10, 100, 30);
    /*
    CurrencyBox.ListViewItems(5);
    CurrencyBox.AddItem("Demo1");
    CurrencyBox.ItemAdd("Demo2");
    CurrencyBox.ItemInsert(0, "Demo3");
    CurrencyBox.Activate();
    CurrencyBox.Enable();
    CurrencyBox.Show();
    CurrencyBox.Size(200, 30);
    */

Он появляется, но заполнить данными не получается - он всегда пустой, при этом даже Width / Height не меняются.

В результате вижк такую картину :


Спасибо, Артем

Rashid Umarov
Админ
11836
Rashid Umarov 2013.06.14 09:10  

Попробуйте сначала через поиск в MetaEditor


Andy
564
Andy 2013.06.15 11:11  

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

Переписал один в один из примера :

CurrencyBox = new CCurrencyBox();

    CurrencyBox.Create(ChartID(), "Demo", ChartWindow, selectorX, selectorY, selectorX + selectorWidth, selectorY + selectorHeight);
    int total=SymbolsTotal(true);
    for (int i=0;i<total;i++)
        if (!CurrencyBox.ItemAdd(SymbolName(i,true)))
        {
            Print("Error");
        }
    CurrencyBox.SelectByText(Symbol());
    CurrencyBox.Alignment(WND_ALIGN_RIGHT, 0,0,11,0);

После добавления вызова метода SelectByText() в комбо боксе появилась одна валюта, но выпадающий список так и не появляется по клику. Suggestions?

И тогда вопрос вдогонку - можно ли размещать выпадающий список прямо на графике или обязательно делать его приватным свойством диалога?

Только что поробовал создать ListView - элементы добавляются, похоже просто не раотают события ... точки останова внутри обработчиков событий ComboBox не срабатывают, т.е. сообщения о том, что я кликнул на комбо-боксе просто не посылаются. Почему?

Andrey Khatimlianskii
56199
Andrey Khatimlianskii 2013.06.16 02:57  

Покажите код (в т.ч. обработчика событий).

А вообще - готовьтесь к долгим увлекательным часам изучения особенностей стандартной библиотеки ;)

Примеров к ней - минимум, документация, в основном, формальная. Поэтому постоянно приходится изучать внутренности и догадываться о возможном поведении.

Документация по MQL5: Стандартная библиотека
Документация по MQL5: Стандартная библиотека
  • www.mql5.com
Стандартная библиотека - Документация по MQL5
Andy
564
Andy 2013.06.16 11:06  

Спасибо за интерес к теме. Да, я примерно так и понял ... долгие увлекательные часы ...

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

Вобщем, данный индикатор - это корреляция валют, кол-во валют задаете в виде строки с разделителем во входных параметрах, пока что кол-во буферов ограничено 9ю. Вас могут заинтересовать функции Synchronize() и GetBarByTime() - это собственно синхронизация.

Теперь, что касается моего вопроса - я хотел сделать выбор валюты для которой будет считаться корреляция с другими с помощью комбо бокса, сначала попытался отнаследоваться от базового класса создав свой CCurrencyBox, но решил, что слишком много головняка + в примерах метаквотов они CComboBox используют без наследования от него, просто создают инстанс базового класса, поэтьому я убрал свой класс и создаю инстанс базового CComboBox - НИЧЕГО не меняется, айтемы добавляются, но событие клика не посылается.

Т.е. сейчас я просто использую стандартный класс CComboBox и его стандартные обработчики событий, все равно не работает, что дебажить, в какую сторону копать - понятия не имею и как продебажить отправление сообщений о событии если дебагер даже не попадает внутрь обработчика - я не знаю. Вот что используется сейчас в методе PrepareControls()  (создание инстанса и все, обработчики - не перекрываются, используются станартные метаквотовские) :

CComboBox * CurrencyBox;

void PrepareControls()
{
    long chartWidth = ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS, ChartWindow);
    double chartShift = chartWidth * ChartGetDouble(ChartID(), CHART_SHIFT_SIZE, ChartWindow) / 100;
    int selectorX = int(chartWidth - chartShift + 115);
    int selectorY = 12;
    int selectorWidth = 100;
    int selectorHeight = 20;
   
    CurrencyBox = new CComboBox();
    CurrencyBox.Create(ChartID(), "Demo", ChartWindow, selectorX, selectorY, selectorX + selectorWidth, selectorY + selectorHeight);

    for (int i = 0; i < Currencies.Total(); i++)
    {
        CurrencyBox.ItemAdd(SymbolName(i,true));
    }
}

Как видите, инстанс создается на основе CComboBox, а значит и обработчики должны срабатывать из файла Controls\ComboBox.mqh - но НЕ срабатывают - по клику стрелочка выпадающего списка меняется, но сам список не появляется, даже если принудительно вызвать CurrencyBox.Show()

Обработчики - стандартные, НЕ мои :

EVENT_MAP_BEGIN(CComboBox)
   ON_EVENT(ON_CLICK,m_edit,OnClickEdit)
   ON_EVENT(ON_CLICK,m_drop,OnClickButton)
   ON_EVENT(ON_CHANGE,m_list,OnChangeList) CheckListHide(id,(int)lparam,(int)dparam);

EVENT_MAP_END(CWndContainer)

bool CComboBox::OnClickEdit(void)
  {
//--- change button state
   if(!m_drop.Pressed(!m_drop.Pressed()))
      return(false);
//--- call the click on button handler
   return(OnClickButton());
  }
//+------------------------------------------------------------------+
//| Handler of click on button                                       |
//+------------------------------------------------------------------+
bool CComboBox::OnClickButton(void)
  {
//--- show or hide the drop-down list depending on the button state
   return((m_drop.Pressed()) ? ListShow() : ListHide());
  }
//+------------------------------------------------------------------+
//| Handler of click on drop-down list                               |
//+------------------------------------------------------------------+
bool CComboBox::OnChangeList(void)
  {
   string text=m_list.Select();
//--- hide the list, depress the button
   ListHide();
   m_drop.Pressed(false);
//--- set text in the main entry field
   m_edit.Text(text);
//--- send notification
   EventChartCustom(m_chart_id,ON_CHANGE,m_id,0.0,m_name);
//--- handled
   return(true);
  }

Если будете открывать в терминале индикатор, то подключаемый файл статистики можно взять отсюда - https://www.mql5.com/ru/articles/387

Документация по MQL5: Стандартная библиотека / Классы для создания панелей и диалогов / CComboBox
Документация по MQL5: Стандартная библиотека / Классы для создания панелей и диалогов / CComboBox
  • www.mql5.com
Стандартная библиотека / Классы для создания панелей и диалогов / CComboBox - Документация по MQL5
Файлы:
Andrey Khatimlianskii
56199
Andrey Khatimlianskii 2013.06.16 14:34  

Я не пробовал создавать комбобокс без родителя, он у меня является частью панели, как и в метаквотовском примере (ControlsDialog.mqh).

А тогда обработчик выбора другого варианта выглядит так:

EVENT_MAP_BEGIN(CControlsDialog)
   ON_EVENT(ON_CHANGE,m_combo_box,OnChangeComboBox)
EVENT_MAP_END(CAppDialog)
void CControlsDialog::OnChangeComboBox(void)
  {
   Alert(__FUNCTION__+" \""+m_combo_box.Select()+"\"");
  }

 

Попробуйте оттолкнуться от готового (как-бы работающего) примера метаквотов, и удаляйте все лишнее, пока не перестанет работать. 

Andy
564
Andy 2013.06.16 19:31  

причина найдена - сюрприз - это нельзя реализовать без диалогового окна :)

1. моей первой ошибкой было то, что я не добавил в индикатор основной обработчик событий чарта - оно транслирует событие клика по графику на выбранные дочерние элементы, в моем случае demo.OnEvent() - событие выпадалки

void OnChartEvent(
    const int id,
    const long &lparam,
    const double &dparam,
    const string &sparam)
{
    //CurrencyBox.OnEvent(id, lparam, dparam, sparam);
    demo.OnEvent(id, lparam, dparam, sparam);
}

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

#define ON_EVENT(event,control,handler)  if(id==(event+CHARTEVENT_CUSTOM) && lparam==control.Id()) { handler(); return(true); }

Это означает, что событие сработает только если в эотй проверке параметр lparam будет равен реальному ID контрола, который это событие вызвал ... но есть одна проблема ... у контрола есть метод control.Id() который всегда возвращает -1 ... до тех пор пока он не станет дочерним, т.е. пока не будет добавлен методом Add() к диалоговому окну.

Я попытался отнаследоваться от класса CComboBox и создать свой макрос, который не будет проверять ID контрола, а просто молча вызывать событие для него ... и о чудо - выпадалка наконец-то выпала ... НО ... теперь уже не работает клик по выпавшему списку, т.е. чтобы такая система работала без наличия диалогового окна необходимо перекрывать каждый из классов используемых в классе CComboBox ... проще все же использовать Диалог

И последнее - ответ на мой предыдущий вопрос : И тогда вопрос вдогонку - можно ли размещать выпадающий список прямо на графике или обязательно делать его приватным свойством диалога?

Нет, нельзя, контролы, которые не были добавлены внутрь какого-либо диалогового окна работать НЕ будут. Тему можно закрывать.

Andrey Khatimlianskii
56199
Andrey Khatimlianskii 2013.06.18 05:01  
artemiusgreat:

Тему можно закрывать.

И открывать заявку в сервис-деск, чтоб убрали это искусственное ограничение.

Не поленитесь, они действительно воплощают толковые предложения.

Pavel Tsatsenko
842
Pavel Tsatsenko 2013.06.18 05:24  
artemiusgreat:
 Тему можно закрывать.
Вы еще не размещали на чарте два одинаковых индикатора с библиотечными контролами? Попробуйте.
Victor Kirillin
491
Victor Kirillin 2013.06.18 11:03  

Все контролы должны быть добавлены в CAppDialog ("дети", "внуки", "внучатые племянники" и т.д.).

После вызова CAppDialog::Run(), контролам раздаются идентификаторы. Дальше события будут работать.

Serhiy Dotsenko
919
Serhiy Dotsenko 2015.02.08 14:36  
komposter:

А вообще - готовьтесь к долгим увлекательным часам изучения особенностей стандартной библиотеки ;)

зато интересно )) в учебный целях самое оно ))

 

в справке нужно дописать, что метод Select, может не только bool возвращать, но и string. хорошо что Alt + G есть, а то часы могут в сутки превращатся ))

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий