//--- подключим библиотеку элементов управления
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//--- предопределенные константы
#define X_PROPERTY_NAME_1 10 // х-координата имени свойства в первом столбце
#define X_PROPERTY_VALUE_1 225 // x-координата значения свойства в первом столбце
#define X_PROPERTY_NAME_2 345 // x-координата имени свойства во втором и третьем столбцах
#define X_PROPERTY_VALUE_2 550 // x-координата значения свойства во втором и третьем столбце
#define X_BUTTON_1 285 // x-координата кнопки в первом столбце
#define X_BUTTON_2 700 // x-координата кнопки во втором столбце
#define Y_PROPERTY_1 30 // y-координата начала первого и второго столбца
#define Y_PROPERTY_2 286 // y-координата начала третьего столбца
#define Y_DISTANCE 16 // расстояние по оси y между строками
#define LAST_PROPERTY_NUMBER 111 // номер последнего графического свойства
//--- входные параметры
input color InpFirstColor=clrDodgerBlue; // Цвет нечетных строк
input color InpSecondColor=clrGoldenrod; // Цвет четных строк
//--- переменные и массивы
CChartObjectLabel ExtLabelsName[]; // надписи для отображения имен свойств
CChartObjectLabel ExtLabelsValue[]; // надписи для отображения значений свойств
CChartObjectButton ExtButtons[]; // кнопки
int ExtNumbers[]; // индексы свойств
string ExtNames[]; // имена свойств
uchar ExtDataTypes[]; // типы данных свойств (integer, double, string)
uint ExtGroupTypes[]; // массив, который хранит данные о принадлежности свойств к одной из групп
uchar ExtDrawTypes[]; // массив, который хранит данные о способе отображения свойств
double ExtMaxValue[]; // максимальные значения свойств, которые они могут принимать в процессе работы с данной панелью
double ExtMinValue[]; // минимальные значения свойств, которые они могут принимать в процессе работы с данной панелью
double ExtStep[]; // шаги для изменений свойств
int ExtCount; // общее количество всех свойств
color ExtColors[2]; // массив цветов для отображения строк
string ExtComments[2]; // массив комментариев (для свойства CHART_COMMENT)
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- выведем комментарий на график
Comment("SomeComment");
//--- сохраним цвета в массив для дальнейшего переключения между ними
ExtColors[0]=InpFirstColor;
ExtColors[1]=InpSecondColor;
//--- сохраним комментарии в массив для дальнейшего переключения между ними
ExtComments[0]="FirstComment";
ExtComments[1]="SecondComment";
//--- подготовим и отобразим панель управления свойствами графика
if(!PrepareControls())
return(INIT_FAILED);
//--- успешное выполнение
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Deinitialization function of the expert |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- очищаем текст комментария на графике
Comment("");
}
//+------------------------------------------------------------------+
//| Обработчик событий графика |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- проверка события нажатия на объект графика
if(id==CHARTEVENT_OBJECT_CLICK)
{
//--- разобьем имя объекта по разделителю
string obj_name[];
StringSplit(sparam,'_',obj_name);
//--- проверка, является ли объект кнопкой
if(obj_name[0]=="Button")
{
//--- получаем индекс кнопки
int index=(int)StringToInteger(obj_name[1]);
//--- установим кнопку в ненажатое состояние
ExtButtons[index].State(false);
//--- установим новое значения свойства в зависимости от его типа
if(ExtDataTypes[index]=='I')
ChangeIntegerProperty(index);
if(ExtDataTypes[index]=='D')
ChangeDoubleProperty(index);
if(ExtDataTypes[index]=='S')
ChangeStringProperty(index);
}
}
//--- перерисовка значений свойств
RedrawProperties();
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Изменение целочисленного свойства графика |
//+------------------------------------------------------------------+
void ChangeIntegerProperty(const int index)
{
//--- получаем текущее значение свойства
long value=ChartGetInteger(0,(ENUM_CHART_PROPERTY_INTEGER)ExtNumbers[index]);
//--- определяем следующее значение свойства
switch(ExtDrawTypes[index])
{
case 'C':
value=GetNextColor((color)value);
break;
default:
value=(long)GetNextValue((double)value,index);
break;
}
//--- устанавливаем новое значение свойства
ChartSetInteger(0,(ENUM_CHART_PROPERTY_INTEGER)ExtNumbers[index],0,value);
}
//+------------------------------------------------------------------+
//| Изменение вещественного свойства графика |
//+------------------------------------------------------------------+
void ChangeDoubleProperty(const int index)
{
//--- получаем текущее значение свойства
double value=ChartGetDouble(0,(ENUM_CHART_PROPERTY_DOUBLE)ExtNumbers[index]);
//--- определяем следующее значение свойства
value=GetNextValue(value,index);
//--- устанавливаем новое значение свойства
ChartSetDouble(0,(ENUM_CHART_PROPERTY_DOUBLE)ExtNumbers[index],value);
}
//+------------------------------------------------------------------+
//| Изменение строкового свойства графика |
//+------------------------------------------------------------------+
void ChangeStringProperty(const int index)
{
//--- статическая переменная для переключения внутри массива комментариев ExtComments
static uint comment_index=1;
//--- меняем индекс для получения другого комментария
comment_index=1-comment_index;
//--- устанавливаем новое значение свойства
ChartSetString(0,(ENUM_CHART_PROPERTY_STRING)ExtNumbers[index],ExtComments[comment_index]);
}
//+------------------------------------------------------------------+
//| Определение следующего значения свойства |
//+------------------------------------------------------------------+
double GetNextValue(const double value,const int index)
{
if(value+ExtStep[index]<=ExtMaxValue[index])
return(value+ExtStep[index]);
else
return(ExtMinValue[index]);
}
//+------------------------------------------------------------------+
//| Получение следующего цвета для свойства типа color |
//+------------------------------------------------------------------+
color GetNextColor(const color clr)
{
//--- вернем следующее значение цвета
switch(clr)
{
case clrWhite: return(clrRed);
case clrRed: return(clrGreen);
case clrGreen: return(clrBlue);
case clrBlue: return(clrBlack);
default: return(clrWhite);
}
}
//+------------------------------------------------------------------+
//| Перерисовка значений свойств |
//+------------------------------------------------------------------+
void RedrawProperties(void)
{
//--- текст значения свойства
string text;
long value;
//--- цикл по количеству свойств
for(int i=0;i<ExtCount;i++)
{
text="";
switch(ExtDataTypes[i])
{
case 'I':
//--- получаем текущее значение свойства
if(!ChartGetInteger(0,(ENUM_CHART_PROPERTY_INTEGER)ExtNumbers[i],0,value))
break;
//--- текст целочисленного свойства
switch(ExtDrawTypes[i])
{
//--- свойство цвета
case 'C':
text=(string)((color)value);
break;
//--- булевое свойство
case 'B':
text=(string)((bool)value);
break;
//--- свойство перечисления ENUM_CHART_MODE
case 'M':
text=EnumToString((ENUM_CHART_MODE)value);
break;
//--- свойство перечисления ENUM_CHART_VOLUME_MODE
case 'V':
text=EnumToString((ENUM_CHART_VOLUME_MODE)value);
break;
//--- число типа int
default:
text=IntegerToString(value);
break;
}
break;
case 'D':
//--- текст вещественного свойства
text=DoubleToString(ChartGetDouble(0,(ENUM_CHART_PROPERTY_DOUBLE)ExtNumbers[i]),4);
break;
case 'S':
//--- текст строкового свойства
text=ChartGetString(0,(ENUM_CHART_PROPERTY_STRING)ExtNumbers[i]);
break;
}
//--- отобразим значение свойства
ExtLabelsValue[i].Description(text);
}
}
//+------------------------------------------------------------------+
//| Создание панели для управления свойствами графика |
//+------------------------------------------------------------------+
bool PrepareControls(void)
{
//--- выделим память под массивы с запасом
MemoryAllocation(LAST_PROPERTY_NUMBER+1);
//--- переменные
int i=0; // переменная цикла
int col_1=0; // количество свойств в первом столбце
int col_2=0; // количество свойств во втором столбце
int col_3=0; // количество свойств в третьем столбце
//--- текущее количество свойств - 0
ExtCount=0;
//--- ищем свойства в цикле
while(i<=LAST_PROPERTY_NUMBER)
{
//--- запомним текущий номер свойства
ExtNumbers[ExtCount]=i;
//--- увеличим значение переменной цикла
i++;
//--- проверим, есть ли свойство с таким номером
if(CheckNumber(ExtNumbers[ExtCount],ExtNames[ExtCount],ExtDataTypes[ExtCount],ExtGroupTypes[ExtCount],ExtDrawTypes[ExtCount]))
{
//--- создаем элементы управления для свойства
switch(ExtGroupTypes[ExtCount])
{
case 1:
//--- создаем надписи и кнопку для свойства
if(!ShowProperty(ExtCount,0,X_PROPERTY_NAME_1,X_PROPERTY_VALUE_1,X_BUTTON_1,Y_PROPERTY_1+col_1*Y_DISTANCE,true))
return(false);
//--- количество элементов в первом столбце увеличилось
col_1++;
break;
case 2:
//--- создаем надписи и кнопку для свойства
if(!ShowProperty(ExtCount,1,X_PROPERTY_NAME_2,X_PROPERTY_VALUE_2,X_BUTTON_2,Y_PROPERTY_1+col_2*Y_DISTANCE,true))
return(false);
//--- количество элементов во втором столбце увеличилось
col_2++;
break;
case 3:
//--- создаем только надписи для свойства
if(!ShowProperty(ExtCount,2,X_PROPERTY_NAME_2,X_PROPERTY_VALUE_2,0,Y_PROPERTY_2+col_3*Y_DISTANCE,false))
return(false);
//--- количество элементов в третьем столбце увеличилось
col_3++;
break;
}
//--- определим максимальное, минимальное значение свойства и шаг
GetMaxMinStep(ExtNumbers[ExtCount],ExtMaxValue[ExtCount],ExtMinValue[ExtCount],ExtStep[ExtCount]);
//--- увеличим количество свойств
ExtCount++;
}
}
//--- освободим память, которая не используется массивами
MemoryAllocation(ExtCount);
//--- перерисуем значения свойств
RedrawProperties();
ChartRedraw();
//--- успешное выполнение
return(true);
}
//+------------------------------------------------------------------+
//| Выделение памяти для массивов |
//+------------------------------------------------------------------+
void MemoryAllocation(const int size)
{
ArrayResize(ExtLabelsName,size);
ArrayResize(ExtLabelsValue,size);
ArrayResize(ExtButtons,size);
ArrayResize(ExtNumbers,size);
ArrayResize(ExtNames,size);
ArrayResize(ExtDataTypes,size);
ArrayResize(ExtGroupTypes,size);
ArrayResize(ExtDrawTypes,size);
ArrayResize(ExtMaxValue,size);
ArrayResize(ExtMinValue,size);
ArrayResize(ExtStep,size);
}
//+------------------------------------------------------------------+
//| Проверяем индекс свойства на принадлежность к одному из |
//| перечислений ENUM_CHART_PROPERTIES |
//+------------------------------------------------------------------+
bool CheckNumber(const int ind,string &name,uchar &data_type,uint &group_type,uchar &draw_type)
{
//--- проверяем, является ли свойство целочисленным
ResetLastError();
name=EnumToString((ENUM_CHART_PROPERTY_INTEGER)ind);
if(_LastError==0)
{
data_type='I'; // свойство из перечисления ENUM_CHART_PROPERTY_INTEGER
GetTypes(ind,group_type,draw_type); // определим параметры отображения свойства
return(true);
}
//--- проверяем, является ли свойство вещественным
ResetLastError();
name=EnumToString((ENUM_CHART_PROPERTY_DOUBLE)ind);
if(_LastError==0)
{
data_type='D'; // свойство из перечисления ENUM_CHART_PROPERTY_DOUBLE
GetTypes(ind,group_type,draw_type); // определим параметры отображения свойства
return(true);
}
//--- проверяем, является ли свойство строковым
ResetLastError();
name=EnumToString((ENUM_CHART_PROPERTY_STRING)ind);
if(_LastError==0)
{
data_type='S'; // свойство из перечисления ENUM_CHART_PROPERTY_STRING
GetTypes(ind,group_type,draw_type); // определим параметры отображения свойства
return(true);
}
//--- свойство не принадлежит ни одному перечислению
return(false);
}
//+------------------------------------------------------------------+
//| Определение того, в какой группе должно находиться свойство, |
//| и его тип отображения |
//+------------------------------------------------------------------+
void GetTypes(const int property_number,uint &group_type,uchar &draw_type)
{
//--- проверим на принадлежность свойства к третьей группе
//--- свойства третьей группы отображаются во втором столбце, начиная с CHART_BRING_TO_TOP
if(CheckThirdGroup(property_number,group_type,draw_type))
return;
//--- проверим на принадлежность свойства ко второй группе
//--- свойства второй группы отображаются во втором столбце с начала
if(CheckSecondGroup(property_number,group_type,draw_type))
return;
//--- если попали сюда, значит свойство принадлежит первой группе (первый столбец)
CheckFirstGroup(property_number,group_type,draw_type);
}
//+------------------------------------------------------------------+
//| Функция проверяет, принадлежит ли свойство третьей группе, и |
//| если да, то определяет его тип отображения |
//+------------------------------------------------------------------+
bool CheckThirdGroup(const int property_number,uint &group_type,uchar &draw_type)
{
//--- проверим свойство на принадлежность к третьей группе
switch(property_number)
{
//--- булевые свойства
case CHART_IS_OBJECT:
case CHART_WINDOW_IS_VISIBLE:
draw_type='B';
break;
//--- целочисленные свойства
case CHART_VISIBLE_BARS:
case CHART_WINDOWS_TOTAL:
case CHART_WINDOW_HANDLE:
case CHART_WINDOW_YDISTANCE:
case CHART_FIRST_VISIBLE_BAR:
case CHART_WIDTH_IN_BARS:
case CHART_WIDTH_IN_PIXELS:
draw_type='I';
break;
//--- вещественные свойства
case CHART_PRICE_MIN:
case CHART_PRICE_MAX:
draw_type='D';
break;
//--- по сути, это свойство является командой показа графика поверх всех других
//--- для данной панели в его применении нет необходимости, так как окно всегда
//--- будет становиться поверх всех других раньше, чем мы используем его
case CHART_BRING_TO_TOP:
draw_type=' ';
break;
//--- свойство не принадлежит к третьей группе
default:
return(false);
}
//--- свойство принадлежит к третьей группе
group_type=3;
return(true);
}
//+------------------------------------------------------------------+
//| Функция проверяет, принадлежит ли свойство второй группе, и если |
//| да, то определяет его тип отображения |
//+------------------------------------------------------------------+
bool CheckSecondGroup(const int property_number,uint &group_type,uchar &draw_type)
{
//--- проверим свойство на принадлежность ко второй группе
switch(property_number)
{
//--- свойство типа ENUM_CHART_MODE
case CHART_MODE:
draw_type='M';
break;
//--- свойство типа ENUM_CHART_VOLUME_MODE
case CHART_SHOW_VOLUMES:
draw_type='V';
break;
//--- строковое свойство
case CHART_COMMENT:
draw_type='S';
break;
//--- свойство цвета
case CHART_COLOR_BACKGROUND:
case CHART_COLOR_FOREGROUND:
case CHART_COLOR_GRID:
case CHART_COLOR_VOLUME:
case CHART_COLOR_CHART_UP:
case CHART_COLOR_CHART_DOWN:
case CHART_COLOR_CHART_LINE:
case CHART_COLOR_CANDLE_BULL:
case CHART_COLOR_CANDLE_BEAR:
case CHART_COLOR_BID:
case CHART_COLOR_ASK:
case CHART_COLOR_LAST:
case CHART_COLOR_STOP_LEVEL:
draw_type='C';
break;
//--- свойство не принадлежит ко второй группе
default:
return(false);
}
//--- свойство принадлежит ко второй группе
group_type=2;
return(true);
}
//+------------------------------------------------------------------+
//| Эта функция вызывается только в том случае, если уже известно, |
//| что свойство не принадлежит второй и третьей группам свойств |
//+------------------------------------------------------------------+
void CheckFirstGroup(const int property_number,uint &group_type,uchar &draw_type)
{
//--- свойство принадлежит первой группе
group_type=1;
//--- определим тип отображения свойства
switch(property_number)
{
//--- целочисленные свойства
case CHART_SCALE:
case CHART_HEIGHT_IN_PIXELS:
draw_type='I';
return;
//--- вещественные свойства
case CHART_SHIFT_SIZE:
case CHART_FIXED_POSITION:
case CHART_FIXED_MAX:
case CHART_FIXED_MIN:
case CHART_POINTS_PER_BAR:
draw_type='D';
return;
//--- остались только булевые свойства
default:
draw_type='B';
return;
}
}
//+------------------------------------------------------------------+
//| Создание надписи и кнопки для свойства |
//+------------------------------------------------------------------+
bool ShowProperty(const int ind,const int type,const int x1,const int x2,
const int xb,const int y,const bool btn)
{
//--- статический массив для переключения внутри массива цвета ExtColors
static uint color_index[3]={1,1,1};
//--- меняем индекс для получения другого цвета
color_index[type]=1-color_index[type];
//--- выведем надписи и кнопку (если btn=true) для свойства
if(!LabelCreate(ExtLabelsName[ind],"name_"+(string)ind,ExtNames[ind],ExtColors[color_index[type]],x1,y))
return(false);
if(!LabelCreate(ExtLabelsValue[ind],"value_"+(string)ind,"",ExtColors[color_index[type]],x2,y))
return(false);
if(btn && !ButtonCreate(ExtButtons[ind],(string)ind,xb,y+1))
return(false);
//--- успешное выполнение
return(true);
}
//+------------------------------------------------------------------+
//| Создание надписи |
//+------------------------------------------------------------------+
bool LabelCreate(CChartObjectLabel &lbl,const string name,const string text,
const color clr,const int x,const int y)
{
if(!lbl.Create(0,"Label_"+name,0,x,y))
return(false);
if(!lbl.Description(text))
return(false);
if(!lbl.FontSize(10))
return(false);
if(!lbl.Color(clr))
return(false);
//--- успешное выполнение
return(true);
}
//+------------------------------------------------------------------+
//| Создание кнопки |
//+------------------------------------------------------------------+
bool ButtonCreate(CChartObjectButton &btn,const string name,
const int x,const int y)
{
if(!btn.Create(0,"Button_"+name,0,x,y,50,15))
return(false);
if(!btn.Description("Next"))
return(false);
if(!btn.FontSize(10))
return(false);
if(!btn.Color(clrBlack))
return(false);
if(!btn.BackColor(clrWhite))
return(false);
if(!btn.BorderColor(clrBlack))
return(false);
//--- успешное выполнение
return(true);
}
//+------------------------------------------------------------------+
//| Устанавливаем максимальное, минимальное значение свойства и шаг |
//+------------------------------------------------------------------+
void GetMaxMinStep(const int property_number,double &max,double &min,double &step)
{
double value;
//--- установим значения в зависимости от типа свойства
switch(property_number)
{
case CHART_SCALE:
max=5;
min=0;
step=1;
break;
case CHART_MODE:
case CHART_SHOW_VOLUMES:
max=2;
min=0;
step=1;
break;
case CHART_SHIFT_SIZE:
max=50;
min=10;
step=2.5;
break;
case CHART_FIXED_POSITION:
max=90;
min=0;
step=15;
break;
case CHART_POINTS_PER_BAR:
max=19;
min=1;
step=3;
break;
case CHART_FIXED_MAX:
value=ChartGetDouble(0,CHART_FIXED_MAX);
max=value*1.25;
min=value;
step=value/32;
break;
case CHART_FIXED_MIN:
value=ChartGetDouble(0,CHART_FIXED_MIN);
max=value;
min=value*0.75;
step=value/32;
break;
case CHART_HEIGHT_IN_PIXELS:
max=700;
min=520;
step=30;
break;
//--- значения по умолчанию
default:
max=1;
min=0;
step=1;
}
}
|