//--- 제어 요소 라이브러리를 연결
#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[]; // 속성 데이터 유형 (integer, double, string)
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);
}
//+------------------------------------------------------------------+
//| 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);
}
//+------------------------------------------------------------------+
//| 차트 double 속성 변경 |
//+------------------------------------------------------------------+
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;
//--- boolean 속성
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':
//--- double 속성 텍스트
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);
}
//--- 속성이 double 타입인지 확인
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)
{
//--- boolean 속성
case CHART_IS_OBJECT:
case CHART_WINDOW_IS_VISIBLE:
draw_type='B';
break;
//--- integer 속성
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;
//--- double 속성
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;
//--- string 속성
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)
{
//--- integer 속성
case CHART_SCALE:
case CHART_HEIGHT_IN_PIXELS:
draw_type='I';
return;
//--- double 속성
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;
}
}
|