English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
사용자 정의 그래픽 컨트롤. 1 부: 간단한 컨트롤 만들기

사용자 정의 그래픽 컨트롤. 1 부: 간단한 컨트롤 만들기

MetaTrader 5 | 5 7월 2021, 10:50
206 0
Dmitry Fedoseev
Dmitry Fedoseev

소개

MQL5 언어는 개발자에게 프로그래밍 방식으로 컨트롤되는 다양한 그래픽 개체를 제공합니다. 버튼, 텍스트 레이블, 편집 필드, 비트 맵 레이블 (그림 1), 분석을위한 그래픽 도구 (그림 2)와 같은 것들 말이죠.


그림 1. 그래픽 개체: 버튼, 텍스트 레이블, 편집 필드, 비트 맵 레이블


그림 2. 분석을 위한 그래픽 객체 : 타원, 피보나치 팬, 피보나치 확장

MetaTrader 5 클라이언트 터미널에는 총 40 개 이상의 그래픽 개체가 있습니다. 이러한 모든 개체는 개별적으로 사용할 수 있지만 더 자주 상호 연결된 개체의 체인에 사용됩니다. 예를 들어 편집 필드 (OBJ_EDIT)를 사용하는 경우 비트 맵 레이블 (OBJ_LABEL)이 함께 사용되어 편집 필드의 기능을 나타냅니다.

편집 필드를 사용하는 경우 사용자가 입력 한 데이터의 정확성을 확인하고 소수점 구분 기호로 점과 쉼표를 모두 사용할 수있는 가능성을 제공해야 하는 경우가 많습니다.

프로그래밍 방식의 데이터 출력을 사용하는 경우 데이터 형식을 지정해야 합니다. 예를 들어 불필요한 0을 삭제해야 하는 부분들이죠. 따라서 편집 필드, 비트 맵 레이블 및 기타 기능적 특징을 포함하는 단일 객체를 갖는 것이 더 쉬울 것입니다.

현재 프로그래밍 세계에는 거의 모든 응용 프로그램에서 사용되는 특정 그래픽 컨트롤 집합이 있습니다. 양식 (모든 컨트롤 요소가 있는 응용 프로그램 인터페이스의 기본), 프레임 (그룹화 및 하나의 기능적 목적을 가진 요소 세트 분리, 버튼, 편집 필드, 레이블, 확인란, 라디오 버튼, 수직 및 수평 스크롤 바, 목록, 드롭 다운 목록, 메뉴 행, 메뉴 탭 (그림 . 3)과 같은 것들 말이죠. 

 
그림 3. 가장 일반적인 표준 컨트롤이 있는 양식

위에서 언급한 요소가 MQL5에서 표현되는 방식은 다른 프로그래밍 언어 (단추 및 편집 필드)와 유사합니다. 당신의 무기고에 다른 광범위한 컨트롤을 갖는 것이 편리 할 것입니다.

여러 개발 환경은 프로그래머에게 사용자 지정 컨트롤을 만들기 위한 특수 도구를 제공합니다. MQL5는 이러한 기능을 제공하지 않습니다. 그러나 MQL5는 객체 지향 언어이기 때문에 필요하지 않습니다. 별도의 프로그래밍된 개체의 형태로 모든 작업을 수행 할 수 있습니다.

사용자 지정 컨트롤을 만드는 원리와 방법론은 이 글에서 자세히 설명합니다. 이를 기반으로 프로그래밍에 능숙한 모든 사람은 애플리케이션에서 반복적으로 사용할 수있는 필요한 컨트롤 세트를 만들 수 있습니다.


1. 그래픽 컨트롤이 되어야 하는 것

1.1. 일반 요구 사항 및 원칙

유용하게 사용하려면 그래픽 컨트롤이 응용 프로그램 개발을 더 쉽게 만들어야 합니다. 그러기 위해서는 다음 요구 사항을 충족해야 합니다.

  1. 개발 중에 컨트롤을 빠르게 생성 할 수 있어야 합니다. 이 문제는 프로그래밍에 대한 객체 지향 접근 방식을 사용하여 해결됩니다. 하나의 그래픽 컨트롤이 하나의 프로그래밍된 개체로 표시됩니다.
     
  2. 컨트롤은 유연해야 합니다. 즉, 크기, 위치, 색상 등 속성을 변경할 수 있어야 합니다.
     
  3. 컨트롤은 사용하기 쉬워야 합니다. 요소의 목적과 메소드 이름에서 목적을 이해할 수 있는 필수 속성과 메소드만 있어야 합니다. 이제 컨트롤의 속성을 카테고리로 나누겠습니다.
     
    1. 컨트롤되지 않는 속성. 이러한 속성에는 색 구성표가 포함됩니다. 응용 프로그램에서 사용되는 모든 컨트롤에는 일반적인 스타일이 있어야 합니다. 그렇기 때문에 각 컨트롤에 대해 개별적으로 색상을 설정하는 것이 힘들 것입니다.
      또한 일부 컨트롤의 색상을 검색하는 것은 시간을 낭비하고 싶지 않은 매우 어려운 작업입니다. 예를 들어 스크롤 바입니다. 일부 웹 개발자는이 흥미로운 작업에 직면했을 수 있습니다.
       
    2. 컨트롤 생성 단계에서 설정되는 속성 또는 거의 변경되지 않는 속성. 예 : 컨트롤의 크기. 응용 프로그램에서 사용되는 모든 컨트롤의 균형 있고 편리한 위치는 인터페이스를 만드는 단계에서 해결되는 특별하고 어려운 작업입니다.
      이와 관련하여 컨트롤의 크기는 일반적으로 프로그램 작동 중에 변경되지 않습니다. 그러나 때때로 이러한 속성을 변경해야 할 수도 있습니다. 그렇기 때문에 프로그램 작동 중에 이러한 속성을 변경할 수있는 가능성을 제공해야 합니다.
       
    3. 주요 작동 속성. 프로그램에서 자주 변경되는 속성입니다. 컨트롤의 목적을 형성하는 속성입니다. 이러한 속성은 두 가지 범주로 나눌 수 있습니다.
       
      1. 컨트롤 표시를 자동으로 업데이트하는 속성 예 : 편집. 프로그램에 의해 값이 설정되면 변경 사항이 화면에 표시되어야 합니다. 프로그래밍에서는 한 줄의 코드를 사용하여 수행해야 합니다.
         
      2. 필수 새로 고침이 필요한 속성 예 : 목록. 목록은 데이터 배열 작업을 의미하므로 목록의 단일 요소로 작업한 후 목록을 새로 고치면 안됩니다. 여기서는 목록의 모든 요소를 ​​사용하여 마지막에 강제 업데이트를 수행하는 것이 좋습니다. 이 접근 방식은 애플리케이션 성능을 크게 향상시킵니다.
         
  4. 컨트롤을 빠르고 간단하게 숨기고 표시할 수 있습니다. 컨트롤을 표시하려면 표시 속성을 반복적으로 설정할 필요가 없습니다. 개체 속성에 대한 액세스는 이 컨트롤의 그래픽 개체의 가시성과 상관 없이 독립적이어야 합니다. 즉, 프로그래밍된 개체는 컨트롤의 모든 속성을 포함해야하며 그래픽 개체의 속성을 사용해서는 안됩니다.
      
  5. 컨트롤에 해당하는 이벤트를 출력하려면 컨트롤에 포함된 개별 그래픽 개체의 이벤트를 처리해야 합니다.

1.2. 컨트롤 및 필수 방법 사용 방법 

위에서 언급한 요구 사항을 고려하여 그래픽 인터페이스를 생성하는 다음과 같은 체계와 프로그래밍된 개체의 필수 속성 및 메소드 집합이 있습니다.

  1. 거의 변경되지 않는 속성의 컨트롤 및 병렬 설정 초기화. 이 메소드는 Init()이라 불리며, 이는 여러 매개 변수를 갖고 있습니다. 첫 번째 필수 항목 - 컨트롤의 이름. 이 매개 변수는 컨트롤에 포함된 모든 그래픽 개체의 이름에서 접두사로 사용됩니다. 또한 컨트롤의 크기를 설정하는 매개 변수 및 기타 매개 변수를 포함 할 수 있습니다 (컨트롤 목적에 따라 다름).
     
  2. 컨트롤은 차트에서 고정된 위치를 가질 수 있을 뿐만 아니라 이동할 가능성을 요할 수 있습니다. 따라서 좌표를 결정하기 위해 별도의 방법을 사용할 것입니다 : SetPosLeft() - X 좌표 설정, SetPosTop() - Y 좌표 설정. 이러한 각 메소드에는 하나의 매개 변수가 있어야 합니다. 매우 자주 두 좌표를 모두 변경해야하므로 X 및 Y 좌표를 동시에 변경하는 두 개의 매개 변수가 있는 SetPos 메소드를 사용하는 것이 좋습니다.
    컨트롤의 위치를 ​​계산하려면 다른 컨트롤의 크기와 위치에 대한 정보를 얻어야 할 수 있습니다. 이를 위해 다음 메소드를 사용할 것입니다. Width() - width, Height() - height, Left() - X 좌표, Top() - Y 좌표. 이 작업 단계에서 컨트롤 좌표를 계산하고 설정 방법을 호출합니다.
     
  3. 생성 직후 또는 애플리케이션의 다른 작업 단계에서 컨트롤을 표시해야 합니다. 이를 위해 Show() 메소드가 사용됩니다. 컨트롤을 숨기려면 Hide() 메소드가 사용됩니다.
     
  4. 앞서 언급했듯이 프로그램 작동 중에 컨트롤의 크기를 변경해야 할 수도 있습니다. 그렇기 때문에 프로그래밍된 개체는 크기를 설정하는 별도의 메소드 인 SetWidth() 및 / 또는 SetHeght()를 가져야 합니다. 속성은 거의 변경되지 않으므로 변경 사항을 적용하려면 표시를 업데이트하는 Refresh() 메소드를 호출해야 합니다.

  5. 개별 그래픽 개체의 이벤트는 컨트롤의 특정 이벤트에 해당하는 값을 반환하는 Event() 메소드에서 처리됩니다. Event() 메소드는 OnChartEvent() 함수에서 호출해야 합니다. OnChartEvent() 함수와 동일한 매개 변수 세트를 갖습니다.

따라서 저희는 프로그래밍된 객체의 필수 메소드 세트를 얻습니다.

  • void Init(string aName ...) - 컨트롤의 초기화;
  • void SetPosLeft(int aLeft) - X 좌표 설정;
  • void SetPosTop(int aTop) - Y 좌표 설정;
  • void SetPos(int aLeft, int aTop) - X 및 Y 좌표 동시 설정;
  • void SetWidth(int aWidth) - 너비 설정;
  • void SetHeght(int aHeight) - 높이 설정;
  • int Width() - 너비 얻기;
  • int Height() - 높이 얻기;
  • int Left() - X 좌표 얻기;
  • int Top() - Y 좌표 얻기;
  • void Refresh() - 표시의 완전 새로 고침;
  • void Show() - 전시;
  • void Hide() - 숨김;
  • int Event(const int id, const long & lparam, const double & dparam, const string & sparam) - 차트 이벤트 처리;

다른 방법의 존재 여부 (또는 나열된 방법 중 일부 없음)는 컨트롤 자체와 그 목적에 따라 다릅니다.

이 글의 뒷부분에서 위에서 설명한 원칙을 구현하려고 합니다. 사용자가 텍스트나 숫자를 입력 할 수 있는 컨트롤을 만들 것입니다.

그 전에 그래픽 개체를 빠르고 편리하게 사용할 수 있는 도구를 제공해야 합니다.


2. 빠르고 편리하게 그래픽 개체로 작업하는 방법

그래픽 객체 작업을 위해 MQL5는 ObjectCreate(), ObjectDelete(), ObjectSetDouble(), ObjectSetInteger(), ObjectSetString(), ObjectGetDouble(), ObjectGetInteger(), ObjectGetString() 와 같은 기본 기능을 제공합니다. 이러한 기능을 직접 사용할 수 있지만 프로그래밍 과정은 매우 힘들고 길 것입니다. 함수에는 긴 이름이 있습니다. 긴 이름을 가진 많은 인디케이터가 함수에 전달되어야 합니다.

그래픽 객체 작업을 보다 편리하게하기 위해 MetaTrader 5 클라이언트 터미널 패키지 (MQL5/의 CChartObject 클래스)에 포함된 기성 클래스를 사용할 수 있습니다. Include/ChartObjects/ChartObject.mqh 파일) 또는 자체 클래스를 작성하고 필요한 모든 메소드를 제공 할 수 있습니다.

농담으로, 프로그래밍에 대한 이러한 접근 방식은 뒤에 점이 있는 키 하나를 누르는 것으로 구성됩니다. 객체의 이름을 지정한 후 점을 입력하면 해당 속성 및 메소드 목록이 열립니다. 목록에서 필요한 항목을 선택하기 만하면 됩니다 (그림 4).


그림 4. CWorkPiece 클래스의 모든 메소드 목록이 글에 첨부되어 있습니다.

보조 클래스를 사용하여 그래픽 개체를 관리하는 두 가지 변형이 있습니다.

  1. 각 그래픽 객체에 대해 개별 클래스 인스턴스가 생성됩니다. 메모리 소모량 관점에서 볼 때 매우 편리하지만 경제적이지 않은 방법입니다. 이 변형의 경우 각 그래픽 개체 유형에 대한 특수 클래스를 작성하는 것이 좋습니다. 그러나 이 접근 방식은 매우 힘들기 때문에 최적의 방법은 아닙니다. Expert Advisors의 프로그래밍과 달리 사용자 인터페이스를 만들 때 최대 성능에 대한 엄격한 요구 사항이 없습니다.
  2. 하나의 클래스 인스턴스를 사용하십시오. 그래픽 개체를 관리해야하는 경우 개체가 클래스에 추가됩니다. 두 번째 변형을 사용할 것입니다.

두 번째 유형의 그래픽 개체 관리에 가장 적합한 범용 클래스를 만들어 보겠습니다.


3. 그래픽 객체 관리를위한 유니버설 클래스

프로그래밍하는 동안 각 그래픽 개체의 작업은 생성, 속성 읽기 / 설정, 응용 프로그램 작동 종료시 삭제의 세 단계로 구성됩니다.

따라서 먼저 그래픽 객체를 관리하는 클래스에는이를 생성하는 메소드가 포함되어야 합니다. 그래픽 객체 생성을위한 필수 매개 변수는 이름입니다. 따라서 객체 생성 방법에는 생성된 객체의 이름을 지정하기 위한 하나의 필수 매개 변수가 있습니다.

일반적으로 그래픽 개체는 프로그램 (Expert Advisor, 인디케이터 또는 스크립트)이 실행되는 차트에 생성됩니다. 더 드문 경우는 하위 창이고 더 드문 경우는 터미널의 또 다른 차트 창입니다. 따라서 두 번째 선택적 매개 변수는 하위 창의 수를 지정하는 매개 변수가됩니다. 세 번째는 차트의 인디케이터입니다.

기본적으로 두 선택적 매개 변수는 모두 0입니다 (가격 차트는 "자체"차트에 있음). 글에서 그래픽 개체 유형 목록을 찾아보세요. 각 유형에 대해 Create 메소드를 추가하십시오.

그 전에 파일을 만들어야 합니다. 이를 수행하려면 MetaEditor를 열고 새 포함 파일을 만들고 이름을 IncGUI.mqh라고합니다. 열린 파일에서 보호된 섹션과 public 섹션을 사용하여 CGraphicObjectShell 클래스를 생성합니다. 보호 섹션에서 개체 이름 및 차트 인디케이터에 대한 변수를 선언합니다.

객체 생성 방법에서 이러한 변수는 이름과 차트 인디케이터를 지정하지 않고 객체 생성 후 관리 할 수 ​​있도록 메소드에서 전달한 값을 매개 변수로 할당합니다. 따라서 그래픽 객체를 관리하는 첫 번째 변형에도 클래스를 사용할 수 있습니다.

두 번째 변형 (그래픽 객체 관리)에 클래스를 사용하려면 그래픽 객체를 첨부하는 메소드 (Attach() 메소드)를 제공합니다. 이 메소드에는 하나의 필수 매개 변수 (그래픽 개체의 이름)와 하나의 선택적 매개 변수 (차트 인디케이터)가 있습니다. 첨부된 그래픽 개체의 이름과 인디케이터를 알아야 할 수도 있습니다. 이를 수행하려면 개체에 Name() 및 ChartID() 메소드를 추가합니다.

결과적으로 저희는 클래스의 다음 "워크 피스"를 얻습니다. 

class CGraphicObjectShell
  {
protected:
   string            m_name;
   long              m_id;
public:
   void Attach(string aName,long aChartID=0)
     {
      m_name=aName;
      m_id=aChartID;
     }
   string Name()
     {
      return(m_name);
     }    
   long ChartID()
     {
      return(m_id);
     }
  };

위에서 언급한 그래픽 개체 생성 방법을 추가합니다. 이러한 메소드의 이름은 "Create"로 시작합니다.

독자는 이를 건너 뛸 수 있으며, 글에 첨부된 IncGUI.mqh 파일에는 미리 만들어진 클래스인 CGraphicObjectShell이 ​​포함되어 있습니다.

예를 들어, 다음은 수직선 그래픽 객체 (OBJ_VLINE)를 생성하는 한 가지 방법입니다.

void CreateVLine(string aName,int aSubWindow=0,long aChartID=0)
  {
   ObjectCreate(m_id,m_name,OBJ_VLINE,aSubWindow,0,0);
   Attach(aName,aChartID);
  }

이제 사용자 가이드에서 그래픽 개체 속성 목록을 엽니다. ObjectSetDouble(), ObjectSetInteger() 및 ObjectSetString() 함수를 사용하여 각 속성의 값을 설정하는 메소드를 작성합니다. 메소드 이름은 "Set"으로 시작합니다. 다음으로 ObjectGetDouble() 및 ObjectGetInteger() 함수를 사용하여 속성을 읽는 메소드를 작성합니다. ObjectGetString().

예를 들어, 다음은 색상을 설정하고 가져 오는 방법입니다.

void SetColor(color aColor)
  {
   ObjectSetInteger(m_id,m_name,OBJPROP_COLOR,aColor);
  }
color Color()
  {
   return(ObjectGetInteger(m_id,m_name,OBJPROP_COLOR));
  }

글쎄, 이제 저희는 그래픽 객체 작업에 필요한 최소한의 도구를 가지고 있는 것 같지만 아직 다 갖추진 못했습니다.

그래픽 개체로 작업 할 때 개체에 대해 하나의 작업만 수행해야 하는 경우가 있습니다. 이 경우 객체에 대해 Attach() 메소드를 실행한 다음 주 객체로 돌아가서 Attach()를 다시 실행해야 하기 때문에 그닥 편리하지 않습니다.

클래스에 속성을 설정 / 가져 오는 모든 메소드의 두 가지 변형을 더 추가해 보겠습니다.

첫 번째 - "자체 (own)" 차트의 이름:

void SetColor(string aName,color aColor)
  {
   ObjectSetInteger(0,aName,OBJPROP_COLOR,aColor);
  }
color Color(string aName)
  {
   return(ObjectGetInteger(0,aName,OBJPROP_COLOR));
  }

두 번째 - 차트의 이름 및 인디케이터:

void SetColor(long aChartID,string aName,color aColor)
  {
   ObjectSetInteger(aChartID,aName,OBJPROP_COLOR,aColor);
  }
color Color(long aChartID,string aName)
  {
   return(ObjectGetInteger(aChartID,aName,OBJPROP_COLOR));
  }

ObjectGet ... 및 ObjectSet ... 함수 외에도 그래픽 객체 작업을위 한 다른 함수가 있습니다 : ObjectDelete(), ObjectMove(), ObjectFind(), ObjectGetTimeByValue(), ObjectGetValueByTime(), ObjectsTotal(). 그들은 또한 각각의 호출의 세 가지 변형으로 클래스에 추가 될 수 있습니다.

마지막으로 이 파일에서 간단하고 짧은 이름 "g"로 CGraphicObjectShell 클래스를 선언합니다. 

CGraphicObjectShell g;

이제 그래픽 개체 작업을 시작하려면 IncGUI.mqh 파일을 연결하는 것으로 충분합니다. 따라서 작업 할 "g" 클래스를 갖게됩니다. 이를 사용하면 사용 가능한 모든 그래픽 개체를 쉽게 관리 할 수 ​​있습니다.


4. 컨트롤 용 공작물

그래픽 개체로 빠르게 작업 할 수 있는 클래스가 있지만 더 쉬운 방법으로 컨트롤을 만들 수 있습니다. 모든 컨트롤은 네 가지 그래픽 개체를 기반으로 만들 수 있습니다.

  1. 직사각형 레이블 (OBJ_RECTANGLE_LABEL),
  2. 텍스트 라벨 (OBJ_LABEL),
  3. 필드 수정 (OBJ_EDIT),
  4. 버튼 (OBJ_BUTTON).

그래픽 객체 생성 후 좌표, 크기, 색상, 글꼴 크기 등 많은 속성을 설정해야 합니다. 프로세스를 서두르기 위해 다른 클래스를 만들고 이름을 CWorkPiece (workpieces)로 지정하고 매개 변수에 전달된 속성을 사용하여 그래픽 개체를 만드는 메소드를 제공합니다. 

컨트롤이 작동하려면 차트 이벤트를 처리해야 합니다. 다른 차트의 이벤트는 사용할 수 없으므로 자체 차트로만 작업 할 것입니다. CWorkPiece 클래스의 메소드 매개 변수에는 차트 인디케이터가 없습니다. 0 (자체 차트)이 모든 곳에서 사용됩니다.

하위 창 번호를 지정하는 매개 변수는 가격 차트와 하위 창 모두에서 컨트롤을 생성 할 수 있는 가능성을 제공하는 데 사용됩니다. 그래픽 개체는 왼쪽 상단 모서리에만 바인딩됩니다. 컨트롤을 다른 모서리에 상대적으로 재배치해야 하는 경우 차트 크기를 고려하여 전체 컨트롤의 좌표를 다시 계산하는 것이 훨씬 쉽습니다. 차트 크기 변경을 컨트롤하기 위해 CHARTEVENT_CHART_CHANGE 이벤트를 처리 할 수 ​​있습니다.

많은 컨트롤의 기본으로 "Rectangle label" 개체를 사용합니다. 이 개체의 생성 방법을 CWorkPiece 클래스에 추가합니다. 이 메소드는 Canvas() 라고 합니다.

void Canvas(string aName="Canvas",
             int aSubWindow=0,
             int aLeft=100,
             int aTop=100,
             int aWidth=300,
             int aHeight=150,
             color aColorBg=clrIvory,
             int aColorBorder=clrDimGray)
  {
   g.CreateRectangleLabel(aName,aSubWindow); // Creation of rectangle label
   g.SetXDistance(aLeft);                    // Setting of the X coordinate
   g.SetYDistanse(aTop);                        // Setting of the Y coordinate
   g.SetXSize(aWidth);                          // Setting of width
   g.SetYSize(aHeight);                         // Setting of height
   g.SetBgColor(aColorBg);                   // Setting of background color
   g.SetColor(aColorBorder);                 // Setting of border color
   g.SetCorner(CORNER_LEFT_UPPER);             // Setting of a anchor point
   g.SetBorderType(BORDER_FLAT);             // Setting of border type
   g.SetTimeFrames(OBJ_ALL_PERIODS);            // Setting visibility at all timeframes
   g.SetSelected(false);                        // Disabling selection
   g.SetSelectable(false);                   // Disabling of selection possibility
   g.SetWidth(1);                               // Setting of border width
   g.SetStyle(STYLE_SOLID);                  // Setting of border style
  }

주의: 이 메소드는 14 줄의 코드로 구성됩니다. 이 개체를 만들 때마다 모두 작성하는 것은 매우 답답할 것입니다. 이제 한 줄만 작성하면 충분합니다. 메소드의 모든 매개 변수는 선택 사항이며 사용 빈도 (위치, 크기, 색상 등) 순서대로 나열됩니다.

Canvas() 메소드와 유사하게 텍스트 레이블, 버튼 및 편집 필드를 만드는 메소드인 Label(), Button() 및 Edit()을 작성합니다. 미리 만들어진 클래스 CWorkPiece는 IncGUI.mqh 파일의 글에 첨부됩니다. 위에서 언급한 메소드 외에도 이 클래스에는 프레임을 만들고 삭제하는 메소드인 Frame 및 DeleteFrame과 같은 몇 가지 다른 메소드가 포함되어 있습니다 (그림 5). 프레임은 왼쪽 상단 모서리에 캡션이 있는 사각형 레이블입니다.

프레임은 양식에서 컨트롤을 그룹화 할 때 사용하도록 계획되어 있습니다.


그림 5. 캡션이 있는 프레임.

CWorkPiece 클래스의 모든 메소드 목록이 글에 첨부되어 있습니다.

CGraphicObjectShell 클래스와 유사하게 IncGUI.mqh 파일을 연결한 후 바로 사용할 수 있도록 짧은 이름 "w"로 CWorkPiece 클래스를 선언합니다.

CWorkPiece w;

모든 보조 도구가 준비되었으므로 이 글의 주제인 사용자 지정 컨트롤 생성을 계속할 수 있습니다.


5. "편집" 컨트롤 생성

먼저, 용어를 혼동하지 않도록 그래픽 개체 OBJ_EDIT를 텍스트 필드로, OBJ_LABEL 개체를 레이블로, 생성된 컨트롤을 편집 필드로 부릅니다. 생성된 컨트롤은 편집 필드 (OBJ_EDIT)와 텍스트 레이블 (OBJ_LABEL)이라는 두 개의 그래픽 개체로 구성됩니다.

Te control은 텍스트 데이터 입력과 숫자 데이터 입력의 두 가지 작동 모드를 지원합니다. 숫자 데이터 입력 모드에서는 입력 값의 범위에 제한이 있으며 쉼표와 점 모두 소수점 구분 기호로 허용됩니다. 편집 필드에 있는 값의 프로그래밍된 출력에서 ​​지정된 소수 자릿수에 따라 형식이 지정됩니다.

따라서 컨트롤을 초기화 할 때 작동 모드 (텍스트 또는 숫자)를 지정해야 합니다. 모드는 aDigits 매개 변수를 사용하여 지정됩니다. 0보다 큰 값은 지정된 소수 자릿수로 숫자 모드를 설정하고 음수 값은 텍스트 모드를 설정합니다.

기본적으로 허용되는 값의 범위는 -DBL_MAX에서 DBL_MAX (double 변수 값의 전체 범위)입니다. 필요한 경우 SetMin() 및 SetMax() 메소드를 호출하여 다른 범위를 설정할 수 있습니다. 크기 매개 변수 중 너비만 컨트롤에 설정됩니다. 편집 필드가 균형을 이루도록 하려면 해당 높이와 너비를 설정해야 합니다.

글꼴 크기를 변경하려면 그래픽 개체의 높이를 변경해야 합니다. 그리고 다른 모든 컨트롤의 위치를 ​​변경해야 합니다. 아무도 이것을 하지 않을 것입니다. 모든 컨트롤과 해당 편집 필드에 일정한 글꼴 크기를 사용한다고 가정합니다. 그러나 컨트롤의 클래스에는 다른 요소의 좌표 계산의 편의를 위해 높이를 반환하는 메소드가 있습니다.

4 가지 색상 매개 변수가 있습니다 : 배경색, 텍스트 색상, 캡션 색상 및 경고 색상 (예 : 잘못된 값을 입력하는 경우 텍스트 필드의 배경색을 변경하여 사용자의 주의를 끌 수 있음).

앞에서 언급했듯이 하위 창의 컨트롤이 지원됩니다. 컨트롤이 작동하는 데 필요한 주요 매개 변수 외에도 다른 매개 변수 태그를 사용할 것입니다. 클래스의 인스턴스에 저장되는 간단한 텍스트 값입니다. 태그는 편리한 보조 도구입니다.

클래스는 CInputBox라고합니다. 따라서 다음과 같은 클래스의 변수 세트가 있습니다 (private 섹션에 있음).

string m_NameEdit;    // Name of the Edit object
string m_NameLabel;   // Name of the Label object
int m_Left;           // X coordinate
int m_Top;            // Y coordinate
int m_Width;           // Width
int m_Height;          // Height
bool m_Visible;        // Visibility flag of the control
int m_Digits;          // Number of decimal places for the double number; -1 set the text mode
string m_Caption;      // Caption
string m_Value;        // Value
double m_ValueMin;     // Minimum value
double m_ValueMax;     // Maximum value
color m_BgColor;       // Background color
color m_TxtColor;     // Text color
color m_LblColor;      // Caption color
color m_WarningColor; // Warning font color
bool m_Warning;        // Flag of warning
int m_SubWindow;       // Subwindow
string m_Tag;           // Tag

컨트롤을 사용할 때 호출되는 첫 번째 메소드는 Init()입니다.

이 방법에서는 이전에 결정된 모든 매개 변수의 값을 준비합니다.

// The initialization method
void Init(string aName="CInputBox",
           int aWidth=50,
           int aDigits=-1,
           string aCaption="CInputBox")
 { 
   m_NameEdit=aName+"_E";  // Preparing the name of the text field
   m_NameLabel=aName+"_L"; // Preparing the caption name
   m_Left=0;                 // X coordinate
   m_Top=0;                  // Y coordinate
   m_Width=aWidth;          // Width
   m_Height=15;             // Height
   m_Visible=false;         // Visibility
   m_Digits=aDigits;       // The mode of operation and the number of decimal places
   m_Caption=aCaption;     // Caption text
   m_Value="";              // Value in the text mode
   if(aDigits>=0)m_Value=DoubleToString(0,m_Digits); // Value in the numeric mode
   m_ValueMin=-DBL_MAX;                   // Minimal value
   m_ValueMax=DBL_MAX;                  // Maximal value
   m_BgColor=ClrScheme.Color(0);       // Background color of the text field
   m_TxtColor=ClrScheme.Color(1);      // Color of text and frame of the text field
   m_LblColor=ClrScheme.Color(2);      // Caption color
   m_WarningColor=ClrScheme.Color(3); // Warning color
   m_Warning=false;                      // Mode: warning, normal
   m_SubWindow=0; // Number of subwindow
   m_Tag=""; // Tag
 }

컨트롤이 텍스트 모드에서 작동하는 경우 숫자 모드에서 작동하는 경우 m_Value 변수에 값 ""이 할당됩니다 (지정된 소수 자릿수를 가진 0). 색상 매개 변수는 기본값으로 설정됩니다. 마지막 단계에서 색 구성표를 다룰 것입니다.

컨트롤이 아직 표시되지 않기 때문에 컨트롤의 좌표를 결정하는 변수는 0으로 설정됩니다. Init() 메소드를 호출한 후 (컨트롤이 차트에서 고정된 위치를 가질 계획이라면) SetPos() 메소드를 사용하여 좌표를 설정할 수 있습니다.

// Setting the X and Y coordinates
void SetPos(int aLeft,int aTop)
{ 
   m_Left=aLeft;
   m_Top=aTop;
}

그 후에 컨트롤을 표시 할 수 있습니다 (Show() 메소드).

// Enable visibility on the previously specified position
void Show()
{ 
   m_Visible=true; // Registration of visibility
   Create();       // Creation of graphical objects
   ChartRedraw();   // Refreshing of the chart
}

Create() 함수는 Show() 메소드에서 호출됩니다. 그래픽 개체 (private 섹션에 있음)를 만든 다음 차트를 새로 고칩니다 (ChartRedraw()). Create() 함수의 코드는 다음과 같습니다.

// The function of creation of graphical objects
void Create(){ 
   color m_ctmp=m_BgColor;  // Normal background color
      if(m_Warning){ // The warning method is set
         m_ctmp=m_WarningColor; // The text field will be color in the warning color
      }
    // Creation of the text field
   w.Edit(m_NameEdit,m_SubWindow,m_Left,m_Top,m_Width,m_Height,m_Value,m_ctmp,m_TxtColor,7,"Arial"); 
      if(m_Caption!=""){ // There is a caption
          // Creation of caption
         w.Label(m_NameLabel,m_SubWindow,m_Left+m_Width+1,m_Top+2,m_Caption,m_LblColor,7,"Arial"); 
      } 
}   

m_Warning 값에 따라 Create() 함수에서 그래픽 객체를 생성 할 때 텍스트 필드에 해당 배경색이 할당됩니다. m_Caption 변수에 값이 있으면 캡션이 만들어집니다 (캡션없이 컨트롤을 만들 수 있음).

이동 가능한 컨트롤을 만들 계획이라면 좌표 지정과 함께 Show() 메소드의 두 번째 변형을 사용하십시오. 이 메소드에서 좌표가 설정되고 Show() 메소드의 첫 번째 변형이 호출됩니다.

// Setting the X and Y coordinates
void SetPos(int aLeft,int aTop){ 
   m_Left=aLeft;
   m_Top=aTop;
}

컨트롤이 표시되면 잠시 숨겨야 합니다.

Hide() 메소드는 이러한 목적으로 사용됩니다.

// Hiding (deletion of graphical objects)
void Hide()
{ 
   m_Visible=false; // Registration of the invisible state
   Delete();        // Deletion of graphical objects
   ChartRedraw();    // Refreshing of the chart
}  

Hide() 메소드는 그래픽 개체를 삭제하는 Delete() 함수를 호출 한 다음 ChartRedraw() 함수를 호출하여 차트를 새로 고칩니다. Delete() 함수는 private 섹션에 있습니다.

// The function of deletion of graphical objects
void Delete()
{ 
   ObjectDelete(0,m_NameEdit);  // Deletion of the text field
   ObjectDelete(0,m_NameLabel); // Deletion of caption
}   

컨트롤 표시를 변경하지 않고 속성 값만 설정하는 메소드 (SetPos() 메소드)를 이미 만났으므로 컨트롤의 강제 새로 고침을위한 메소드 인 Refresh() 메소드를 만드는 것이 논리적입니다. 

// Refreshing of displaying (deletion and creation)
void Refresh()
{ 
   if(m_Visible)
   {   // Visibility enabled
      Delete();     // Deletion of graphical object
      Create();     // Creation of graphical objects
      ChartRedraw(); // Redrawing of the chart 
   }            
}   

컨트롤은 매우 간단하기 때문에 삭제 및 생성이라는 간단한 새로 고침 방법을 사용합니다. 많은 편집 필드로 구성된 목록과 같이 더 복잡한 컨트롤이라면 더 스마트 한 접근 방식을 선택할 것입니다.

그래서 저희는 컨트롤 배치를 마쳤습니다. 이제 값 설정인 SetValue() 메소드를 진행하겠습니다. 컨트롤은 두 가지 모드로 작동 할 수 있으므로 SetValue() 메소드에는 문자열 및 이중 유형의 두 가지 변형이 있습니다. 텍스트 모드에서 값은 그대로 사용됩니다.

// Setting a text value
void SetValue(string aValue)
{ 
   m_Value=aValue; // Assigning a value to variable to store it
      if(m_Visible)
      { // The visibility of the control is enabled
          // Assigning the text field to the object for managing graphical objects
         g.Attach(m_NameEdit); 
         g.SetText(m_Value); // Setting the value for the text field
         ChartRedraw();        // Redrawing the chart
      }
} 

얻은 인수는 m_Value 변수에 할당되며 컨트롤이 표시되면 텍스트 필드에 표시됩니다.

숫자 모드에서는 획득 한 인수를 m_Digits 값에 따라 정규화 한 다음 최대값과 최소값 (m_MaxValue, m_MinValue)에 따라 수정하고 문자열로 변환 한 다음 첫 번째 메소드 인 SetValue()를 호출합니다.

// Setting a number value
void SetValue(double aValue)
{ 
   if(m_Digits>=0)
   {  // In the numeric mode
       // Normalization of the number according to the specified accuracy
      aValue=NormalizeDouble(aValue,m_Digits);
      // "Alignment" of the value according to the minimal acceptable value
      aValue=MathMax(aValue,m_ValueMin); 
       // "Alignment" of the value according to the maximal acceptable value
      aValue=MathMin(aValue,m_ValueMax); 
       // Setting the obtained value as a string
      SetValue(DoubleToString(aValue,m_Digits)); 
   }
   else
   { // In the text mode
      SetValue((string)aValue); // Assigning the value to the variable to store it as is
   }            
}

값을 가져 오는 두 가지 방법을 작성해 보겠습니다. 하나는 문자열 값을 가져 오는 방법이고 다른 하나는 이중 값을 가져 오는 방법입니다.

// Getting a text value
string ValueStrind()
{ 
   return(m_Value);
}

// Getting a numeric value
double ValueDouble()
{ 
   return(StringToDouble(m_Value));
}

컨트롤에 대해 설정된 값은 최대 및 최소 허용 값에 ​​따라 수정됩니다. 가져오기 및 설정 방법을 추가해 보겠습니다.

// Setting the maximal acceptable value
void SetMaxValue(double aValue)
{ 
   m_ValueMax=aValue; // Registration of the new maximal accepted value
      if(m_Digits>=0)
     { // The control works in the numeric mode
         if(StringToDouble(m_Value)>m_ValueMax)
         { /* The current value of the control is greater than the new maximal acceptable value*/
            SetValue(m_ValueMax); // Setting the new value that is equal to the maximal accepted value
         }
      }         
}

// Setting the minimal acceptable value
void SetMinValue(double aValue)
{ 
   m_ValueMin=aValue; // Registration of the new minimal acceptable value     
      if(m_Digits>=0)
      { // The control works in the numeric mode
         if(StringToDouble(m_Value)<m_ValueMin)
         { /* The current value of the control is less than the new minimal acceptable value*/
            SetValue(m_ValueMin); // Setting the new value that is equal to the minimum acceptable value
         }
      }
}

// Getting the maximal accepted value
double MaxValue()
{ 
   return(m_ValueMax); 
}

// Getting the minimal accepted value
double MinValue()
{ 
   return(m_ValueMin);
}

컨트롤이 숫자 모드에서 작동하는 경우 새로운 최대 및 최소 허용 값을 설정할 때 현재 값의 확인 및 수정 (필요한 경우)이 수행됩니다.

이제 사용자가 입력 한 값인 Event 메소드를 살펴 보겠습니다. 사용자가 입력 한 데이터 확인은 CHARTEVENT_OBJECT_ENDEDIT 이벤트를 사용하여 수행됩니다. 텍스트 모드에서 작업 할 때 사용자가 지정한 값이 m_Value와 같지 않으면 새 값이 m_Value에 할당되고 값 1이 Event() 메소드에서 반환된 m_event 변수에 할당됩니다.

숫자 모드에서 작업 할 때 m_OldValue 변수에 m_Value의 이전 값을 기억하고 쉼표를 점으로 바꾸고 문자열을 숫자로 변환 한 다음 SetValue() 함수에 전달합니다. 그런 다음 m_Value와 m_OldValue가 같지 않으면 이벤트를 "생성"합니다 (값 1을 m_event 변수로 설정).

// Handling of events
int Event(const int id,
           const long & lparam,
           const double & dparam,
           const string & sparam)
{ 
   bool m_event=0; // Variable for an event of this control
      if(id==CHARTEVENT_OBJECT_ENDEDIT)
      { // There has been an event of end of editing the text field
         if(sparam==m_NameEdit)
         { // The text field with the name m_NameEdit has been modified
            if(m_Digits<0)
            { // In the text mode
               g.Attach(m_NameEdit); // Assigning the text field for controlling it
                  if(g.Text()!=m_Value)
                  { // New value in the text field
                     m_Value=g.Text(); // Assigning the value to the variable to store it
                     m_event=1;         // There has been an event
                  }
            }
            else
            { // In the numeric mode
               string m_OldValue=m_Value; // The variable with the previous value of the control
               g.Attach(m_NameEdit);      // Attaching the text field for controlling it
               string m_stmp=g.Text();     // Getting text specified by a user in the text field
               StringReplace(m_stmp,",",".");       // Replacing comma with a dot
               double m_dtmp=StringToDouble(m_stmp); // Conversion to a number
               SetValue(m_dtmp);                     // Setting the new numeric value
                     // Comparing the new value with the previous one
                  if(StringToDouble(m_Value)!=StringToDouble(m_OldValue))
                  { 
                     m_event=1; // There has been an event 
                  }
            }
         }
      }               
   return(m_event); // Return the event. 0 - there is no event, 1 - there is an event
}

하위 창에서 컨트롤 작업 지원. 이를 제공하려면 CHARTEVENT_CHART_CHANGE 이벤트 발생시 OnChartEvent() 함수에서 호출해야 하는 SetSubWindow() 메소드를 추가합니다. 가격 차트에서만 컨트롤을 사용하려는 경우이 메소드를 호출 할 필요가 없습니다. 

m_SubWindow 변수는 이미 선언되어 있으며 기본적으로 0과 같으며 컨트롤의 그래픽 개체를 만들 때 "w"클래스의 Edit() 및 Label() 메소드에 전달됩니다. 하위 창의 번호는 SetSubWindowName() 메소드에 전달됩니다. 숫자가 변경되면 m_SubWindow 변수의 값을 변경하고 Refresh() 메소드를 실행합니다.

// Setting a subwindow by number
void SetSubWindow(int aNumber)
{ 
   int m_itmp=(int)MathMax(aNumber,0); /* If the number is negative, 0 will be used - the price chart*/
      if(m_itmp!=m_SubWindow)
      { /* The specified number doesn't correspond the number where the control is located*/
         m_SubWindow=m_itmp; // Registration of the new number of subwindow
         Refresh(); // Recreation of the graphical objects
      }
} 

아마도 함수에 번호 대신 하위 창의 이름을 전달하는 것이 더 편리 할 것입니다. SetSubWindow() 메소드의 다른 변형을 추가합니다.

// Setting a subwindow by name
void SetSubWindow(string aName)
{ 
   SetSubWindow(ChartWindowFind(0,aName)); // Determination of the number of the subwindow by its name and setting the subwindow by number
}

글의 시작 부분에 명시된 개념에 따라 다른 누락된 메소드와 함께 컨트롤 클래스를 제공합니다.

컨트롤의 두 좌표를 동시에 설정할 수있는 SetPos() 메소드가있는 즉시 별도의 좌표 설정을위한 메소드를 추가합니다.

// Setting the X coordinate
void SetPosLeft(int aLeft)
{ 
   m_Left=aLeft;
}      

// Setting the Y coordinate
void SetPosTop(int aTop)
{ 
   m_Top=aTop;
}  

너비 설정 방법:

// Setting the width
void SetWidth(int aWidth)
{ 
   m_Width=aWidth;
}

좌표와 크기를 얻는 방법:

// Getting the X coordinate
int Left()
{ 
   return(m_Left);
}

// Getting the Y coordinate
int Top()
{ 
   return(m_Top);
}

// Getting the width
int Width()
{ 
   return(m_Width);
}

// Getting the height
int Height()
{
   return(m_Height); 
}

태그 작업 방법:

// Setting the tag
void SetTag(string aValue)
{ 
   m_Tag=aValue;
}

// Getting the tag
string Tag()
{ 
   return(m_Tag);
}  

경고 방법:

// Setting the warning mode
void SetWarning(bool aValue)
{ 
      if(m_Visible)
      { // Visibility is enabled
         if(aValue)
         { // We need to turn on the warning mode
            if(!m_Warning)
            { // The warning mode has not been enabled
               g.Attach(m_NameEdit);         // Attaching the text field for controlling
               g.SetBgColor(m_WarningColor); // Setting the warning color of text in the text field
            }
         }
         else
         { // We need to disable the warning mode
            if(m_Warning)
            { // The warning mode is enabled
               g.Attach(m_NameEdit);    // Attach the text field for controlling 
               g.SetBgColor(m_BgColor); // Setting the normal font color                
            }
         }
      }
   m_Warning=aValue; // Registration of the current mode
}

// Getting the warning mode
bool Warning()
{ 
   return(m_Warning);
}

경고 모드를 설정할 때 컨트롤이 표시되면 SetWarning 메소드에 전달된 매개 변수 값이 확인됩니다. 해당 값이 컨트롤의 현재 상태와 일치하지 않으면 텍스트 필드의 배경색이 변경됩니다.

어쨌든 설정 모드가 등록되어 있으며 컨트롤이 보이지 않을 경우 텍스트 필드에 해당 색상을 설정하지 않습니다.

남은 속성은 m_Digits입니다. 값을 가져오고 설정하는 방법을 추가해보겠습니다. 

// Setting the number of decimal places
void SetDigits(int aValue)
{ 
   m_Digits=aValue; // Registration of the new value
      if(m_Digits>=0)
      { // The numeric mode
         SetValue(ValueDouble()); // Resetting of the current value
      }
}  

// Getting the m_Digits value
int Digits()
{ 
   return(m_Digits);
}  

글쎄, 저희는 가장 흥미로운 부분에서 끝을 맺게 됐습니다. 이제 가장 아름다운 시간을 맞이할 때입니다.


6. 색 구성표

색 구성표는 CСolorSchemes 클래스의 변수에 저장됩니다.

클래스는 ClrScheme이라는 이름으로 IncGUI.mqh 파일에서 미리 선언됩니다. 색 구성표를 설정하기 위해 매개 변수로 지정된 색 구성표 번호를 사용하여 SetScheme() 메소드를 호출합니다. SetScheme() 메소드가 호출되지 않으면 숫자 0의 색 구성표가 사용됩니다.

색을 얻으려면 색 구성표에서 지정된 수의 색으로 Color 메소드를 사용합니다. private 섹션과 public 섹션으로 COLoror Schemes 클래스를 작성하겠습니다. private 섹션에서 색 구성표의 인덱스를 저장하기위한 m_ShemeIndex 변수를 선언합니다. public 섹션에서 SetScheme() 메소드를 작성합니다:

// Setting the color scheme number
void SetScheme(int aShemeIndex)
{ 
   m_ShemeIndex=aShemeIndex;
}

Color 메소드. 2 차원 배열이 메소드에서 선언됩니다. 첫 번째 차원은 색 구성표 번호입니다. 두 번째는 구성표의 색상 번호입니다. 지정된 색 구성표 수에 따라 메소드 매개 변수에 지정된 번호로 색을 반환합니다.

color Color(int aColorIndex)
{
   color m_Color[3][4];  // The first dimension - the color scheme number, the second one - the number of the color in the color scheme
   // default
   m_Color[0][0]=clrSnow;
   m_Color[0][1]=clrDimGray;
   m_Color[0][2]=clrDimGray;
   m_Color[0][3]=clrPink;
   // yellow-black
   m_Color[1][0]=clrLightYellow;
   m_Color[1][1]=clrBrown;
   m_Color[1][2]=clrBrown;
   m_Color[1][3]=clrPink;
   // blue
   m_Color[2][0]=clrAliceBlue;
   m_Color[2][1]=clrNavy;
   m_Color[2][2]=clrNavy;
   m_Color[2][3]=clrPink;
   return(m_Color[m_ShemeIndex][aColorIndex]); // Returning a value according to the scheme number and the number of color in the scheme
}

지금은 색 구성표에 각각 4 가지 색상이 포함됩니다. 그 두 가지는 같은 값을 가지고 있습니다. 또한 다른 컨트롤을 만들 때 더 많은 색상이 필요할 수 있습니다.

체계에서 적절한 색상을 쉽게 찾거나 새 색상을 추가하기 위해 클래스에는 색상을 볼 수있는 메소드 인 Show() 메소드가 포함되어 있습니다 (그림 6). 또한 차트에서 색상 예제를 삭제하는 역방향 메소드 Hide가 있습니다.


그림 6. Show() 메소드를 사용하여 색 구성표보기

이 글에는 ColorSchemesView.mq5가 첨부되어 있습니다. 색 구성표 (ColorSchemesView.mq5)를 보기 위한 Expert Advisor입니다.

CInputBox 클래스의 Init 메소드를 약간 수정해보겠습니다. 색상을 ClrScheme 클래스의 색상으로 바꿉니다.

m_BgColor=ClrScheme.Color(0);       // Background color of the text field
m_TxtColor=ClrScheme.Color(1);      // Font color and frame color of the text field
m_LblColor=ClrScheme.Color(2);     // Caption color
m_WarningColor=ClrScheme.Color(3); // Warning color

이것은 하나의 컨트롤 생성의 끝입니다. 이제 다른 컨트롤을 개발할 수 있는 기반이 생겼습니다.


7. 컨트롤 사용

Expert Advisor를 생성하고 이름을 GUITest로 지정합니다. IncGUI.mqh 파일을 연결하십시오.  

#include <IncGUI.mqh>
ib라는 이름으로 CInputBox 클래스를 선언합니다.
CInputBox ib;

EA의 OnInit()에서 ib 객체의 Init() 메소드를 호출합니다.

ib.Init("InpytBox",50,4,"input");

컨트롤을 표시하고 위치를 설정합니다.

ib.Show(10,20);

EA의 OnDeinit() 함수에서 컨트롤을 삭제합니다.

ib.Hide(); 

Expert Advisor를 컴파일하여 차트에 연결합니다. 컨트롤이 표시됩니다 (그림 7).


그림 7. InputBox 컨트롤

Expert Advisor에 색 구성표 변경 가능성을 추가합니다.

현재 세 가지 색 구성표가 있습니다. 색 구성표를 선택하기 위해 열거와 외부 변수를 만들어 보겠습니다. 

enum eColorScheme
  {
   DefaultScheme=0,
   YellowBrownScheme=1,
   BlueScheme=2
  };

input eColorScheme ColorScheme=DefaultScheme;

Expert Advisor의 OnInit() 함수 맨 처음에 색 구성표 설정을 추가합니다.

ClrScheme.SetScheme(ColorScheme);

이제 EA 속성 창에서 세 가지 색 구성표 중 하나를 선택할 수 있습니다 (그림 8).




그림 8. 다른 색 구성표

새 값을 지정하는 이벤트를 처리하려면 EA의 OnChartEvent() 함수에 다음 코드를 추가합니다.

if(ib.Event(id,lparam,dparam,sparam)==1)
  {
   Alert("Entered value "+ib.ValueStrind());
  }

이제 편집 필드에 새 값이 지정되면 지정된 값을 알리는 메시지 창이 열립니다.

Expert Advisor에게 하위 창에서 컨트롤 생성 가능성을 제공합니다.

먼저 테스트 인디케이터 TestSubWindow (TestSubWindow.mq5 파일에 첨부 됨)를 만듭니다. MQL5 마법사에서 인디케이터를 만들 때 별도의 하위 창에서 작동하도록 지정합니다. EA의 OnChartEvent() 함수에 다음 코드를 추가합니다.

if(CHARTEVENT_CHART_CHANGE)
  {
   ip.SetSubWindow("TestSubWindow");
  }

이제 지표가 차트에 없으면 가격 차트에 컨트롤이 생성됩니다. 지표를 차트에 연결하면 컨트롤이 하위 창으로 이동합니다 (그림 9). 지표를 삭제하면 컨트롤이 가격 차트로 돌아갑니다.

 
그림 9. 하위 창의 컨트롤

결론

작업의 결과로 다음 클래스가 포함된 IncGUI.mqh 포함 파일이 있습니다. CGraphicObjectShell (그래픽 객체 생성 및 관리), CWorkPiece (매개 변수를 사용하여 속성을 설정하여 여러 그래픽 객체의 빠른 생성), CColorSchemes (설정 색 구성표 및 현재 색 구성표의 색 가져 오기) 및 컨트롤의 한 클래스인 CInputBox.

CGraphicObjectShell, CWorkPiece 및 CColorSchemes 클래스는 이름이 "g", "w" 및 "ClrScheme"인 파일에 이미 선언되어 있습니다. 즉, IncGUI.mqh 파일을 연결한 후 바로 사용할 수 있습니다.

CInputBox 클래스 사용 방법을 반복해보겠습니다.

  1. IncGUI.mqh 파일을 연결합니다.
  2. CInputBox 유형의 클래스를 선언하십시오.
  3. Init() 메소드를 호출합니다.
  4. SetPos() 메소드를 사용하여 좌표를 설정합니다. 필요한 경우 Show()를 사용하여 가시성을 켭니다. 두 번째 변형 : 좌표 지정과 함께 Show()를 사용하여 가시성을 켭니다.
  5. 필요한 경우 또는 Expert Advisor의 작업이 끝날 때 Hide() 메소드를 사용하여 컨트롤을 숨 깁니다.
  6. OnChartEvent() 함수에 Event() 메소드 호출을 추가합니다.
  7. 하위 창에 컨트롤을 만들어야 하는 경우 CHARTEVENT_CHART_CHANGE 이벤트가 발생할 때 SetSubWindow 메소드를 호출하여 OnChartEvent() 함수를 제공합니다.
  8. 색 구성표를 사용하려면 Init() 메소드를 호출하기 전에 ClrScheme 클래스의 SetScheme() 메소드를 호출하십시오. 


첨부 파일

  • IncGUI.mqh - 기본 포함 파일. 파일은 클라이언트 터미널 데이터 폴더의 MQL5/Include 폴더에 있어야 합니다.
  • GUITest.mq5 - CInputBox 컨트롤의 예제가 있는 Expert Advisor. 파일은 클라이언트 터미널 데이터 폴더의 MQL5/Experts 폴더에 있어야 합니다.
  • TestSubWindow.mq5 - 하위 창에 컨트롤을 표시하는 기능을 테스트하기 위한 인디케이터입니다. 파일은 클라이언트 터미널 데이터 폴더의 MQL5/Indicators 폴더에 있어야 합니다.
  • ColorSchemesView.mq5 - 색 구성표를 보기 위한 Expert Advisor. 컨트롤 생성을 위한 보조 도구입니다. 파일은 클라이언트 터미널 데이터 폴더의 MQL5/Experts 폴더에 있어야 합니다.
  • IncGUImqh.chm - documentation for the IncGUI.mqh file.  

MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/310

사용자 정의 그래픽 컨트롤. 파트 2. 컨트롤 라이브러리 사용자 정의 그래픽 컨트롤. 파트 2. 컨트롤 라이브러리
"Custom Graphical Controls"시리즈의 두 번째 글에서는 프로그램 (Expert Advisor, 스크립트, 인디케이터)과 사용자 간의 상호 작용에서 발생하는 주요 문제를 처리하기 위한 컨트롤 라이브러리를 소개합니다. 라이브러리에는 수많은 클래스 (CInputBox, CSpinInputBox, CCheckBox, CRadioGroup, CVSсrollBar, CHSсrollBar, CList, CListMS, CComBox, CHMenu, CVMenu, CHProgress, CDialer, CDialerInputBox, CTable) 및 사용 예제가 포함되어 있습니다.
MQL5 마법사 : 새 버전 MQL5 마법사 : 새 버전
이 문서에는 업데이트된 MQL5 마법사에서 사용할 수있는 새로운 기능에 대한 설명이 포함되어 있습니다. 수정된 신호 아키텍처를 통해 다양한 시장 패턴의 조합을 기반으로 거래 로봇을 만들 수 있습니다. 이 글에 포함된 예제는 Expert Advisor의 대화 형 생성 절차를 설명합니다.
사용자 정의 그래픽 컨트롤. 파트 3. 양식 사용자 정의 그래픽 컨트롤. 파트 3. 양식
이것은 그래픽 컨트롤에 관한 세 가지 글 중 마지막입니다. 주요 그래픽 인터페이스 구성 요소 (양식)의 생성과 다른 컨트롤과 함께 사용하는 방법을 다룹니다. 양식 클래스 외에도 CFrame, CButton, CLabel 클래스가 컨트롤 라이브러리에 추가되었습니다.
MQL5에서 리소스 사용 MQL5에서 리소스 사용
MQL5 프로그램은 일상적인 계산을 자동화 할 뿐만 아니라 완전한 기능을 갖춘 그래픽 환경을 만들어 주기도 합니다. 진정한 인터랙티브 컨트롤을 만드는 기능은 이제 고전적인 프로그래밍 언어의 기능과 거의 동일합니다. MQL5에서 본격적인 독립 실행형 프로그램을 작성하려면 리소스를 사용하십시오. 리소스가 있는 프로그램은 유지 관리 및 배포가 더 쉽습니다.