//--- 连接控制元素的程序库
#include <ChartObjects\ChartObjectsTxtControls.mqh>
//--- 预定义常量
#define X_PROPERTY_NAME_1 10 //第一列属性名的x坐标
#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[]; // 属性数据类型(整型,双精度,字符串)
uint ExtGroupTypes[]; // 存储有关属性归属于一个组的数据的数组
uchar ExtDrawTypes[]; // 存储有关属性显示类型的数据的数组
double ExtMaxValue[]; // 面板工作时最大可能的属性值
double ExtMinValue[]; // 面板工作时最小可能的属性值
double ExtStep[]; // 更改属性的步骤
int ExtCount; // 所有属性的总数
color ExtColors[2]; // 用于显示行的颜色的数组
string ExtComments[2]; // 评论数组 (用于CHART_COMMENT 属性)
//+------------------------------------------------------------------+
//| 自定义指标初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 在图表上显示评论
Comment("SomeComment");
//--- 数组中存储颜色以便过后能够在它们之间切换
ExtColors[0]=InpFirstColor;
ExtColors[1]=InpSecondColor;
//--- 数组中存储评论以便过后在它们之间切换
ExtComments[0]="FirstComment";
ExtComments[1]="SecondComment";
//--- 准备并显示管理图表属性的控制面板
if(!PrepareControls())
return(INIT_FAILED);
//--- 成功执行
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| EA的去初始化函数 |
//+------------------------------------------------------------------+
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 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;
}
}
|