English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
사용자 정의 그래픽 컨트롤. 파트 3. 양식

사용자 정의 그래픽 컨트롤. 파트 3. 양식

MetaTrader 5 | 5 7월 2021, 10:54
55 0
Dmitry Fedoseev
Dmitry Fedoseev

 

소개

첫 번째 글 "Creating a Simple Control"에서는 그래픽 컨트롤 생성 원칙을 다루고 간단한 컨트롤 생성을 보여주는 단계별 예제를 제공했습니다. 이어지는 글 "컨트롤 라이브러리"는 미리 만들어진 컨트롤 세트를 설명합니다. 또 다른 매우 중요한 그래픽 인터페이스 구성 요소인 양식이 있습니다.

양식은 컨트롤이 표시되는 화면에서 특별히 지정된 직사각형 부분을 나타냅니다. 게다가, 해당 양식은 포함된 모든 컨트롤을 동시에 관리 할 수있는 컨테이너가 되기도 합니다 : 모두 함께 숨기고, 표시하고, 이동할 수 있습니다.

마지막 글에서는 양식 생성 및 컨트롤과 함께 사용하는 방법에 대해 설명합니다.

양식 작업을 위한 클래스가 이전 글에서 사용된 IncGUI.mqh 파일에 추가되었습니다 (새 파일 이름은 IncGUI_v3.mqh 임). 양식 작업을 위한 클래스 외에도 일부 클래스가 파일에 추가되었으며 CHMenu (수평 메뉴) 및 CVMenu (수직 메뉴) 클래스가 업데이트 되었으며 몇 가지 오류가 수정되었습니다.

추가된 클래스:

  • CFrame 클래스 - 프레임. 클래스는 CWorkPiece 클래스의 Frame 메소드로 생성된 프레임과 동일합니다.
  • CButton 클래스 - 버튼. 일반 버튼 (OBJ_BUTTON).
  • CLabel 클래스 - 레이블. 그래픽 개체 "레이블 (Label)" (OBJ_LABEL) 에 의해 수행되는대로 레이블을 표시하는 것 외에도 이 클래스는 줄이 "\n" 기호로 구분되는 몇 줄의 텍스트 표시를 허용합니다.

새 클래스를 추가한 결과 CColorSchemes 클래스가 다음과 같이 수정되었습니다. 새 컨트롤의 색상이 추가되었습니다.

CHMenu 및 CVMenu 클래스의 변경 사항: 적용된 변경 사항을 통해 드롭 다운 탭이 있는 2 단계 메뉴를 만들 수 있습니다. 이에 대해서는 아래의 "주 메뉴 만들기" 섹션에서 자세히 설명합니다.

오류: CWorkPiece 클래스의 Frame() 메소드 수정 - 사각형 레이블의 하위 창 번호를 설정할 수 없습니다. CListMS 클래스 - Selected() 및 SetSelected() 메소드 - 이제 배열 크기가 확인됩니다. 그렇지 않으면 빈 목록을 사용할 수 없습니다.

 

1. 양식

이 양식은 여러 버튼 OBJ_BUTTON을 사용하는 그래픽 개체 "Rectangle Label" OBJ_RECTANGLE_LABEL을 기반으로 합니다. 시각적으로 양식은 양식 이름과 컨트롤 단추가 표시되는 양식의 상단 부분에 바가있는 사각형 (그림 1) 을 나타냅니다.

양식을 이동하는 버튼 (손 이미지 포함)이 왼쪽에 있으며 최소화 버튼 (사각형 이미지 포함)과 닫기 버튼 (십자 이미지 포함)이 오른쪽에 있습니다.

그림 1. 형태

그림 1. 형태

양식을 이동하려면 이동 버튼 (버튼이 눌린 위치로 이동)을 누르고 양식을 이동할 차트의 아무 곳이나 클릭합니다. 결과적으로 이동 버튼이 해제되고 양식이 표시된 위치로 이동합니다 (왼쪽 상단 모서리가 클릭 한 지점에 위치합니다).

표시된 위치가 차트의 가장자리에 있고 양식이 차트 테두리 외부에 배치되어야 하는 경우 양식 위치가 조정되어 차트에서 완전히 표시됩니다.

여러 유형의 양식을 작성할 수 있습니다.

  • 유형 0 (그림 1);
  • 유형 1 - 추가 "취소" 및 "적용" 버튼 포함 (그림 2);
  • 유형 2 - 추가 "닫기" 버튼 포함 (그림 3);

그림 2. 유형 1의 형식 ("취소" 및 "적용" 단추 포함)

그림 2. 유형 1의 형식 ("취소" 및 "적용" 단추 포함)

그림 3. 유형 2의 형태 ( "닫기" 버튼 사용)

그림 3. 유형 2의 형태 ( "닫기" 버튼 사용)

양식 작업을 위한 프로그래밍 방식은 CFormBase와 CFormTemplate의 두 클래스로 표시됩니다.

CFormBase 클래스는 기본 클래스이고 CFormTemplate은 CFormBase 클래스의 하위 클래스입니다. 효과 및 원칙 (응용 원칙 포함)에서 CFormBase 클래스는 이전에 설명한 다른 컨트롤과 정확히 동일한 컨트롤입니다.

CFormBase 클래스에는 컨트롤 준비를 위한 Init() 메소드, 양식 표시를 위한 SetPos() 및 Show() 메소드 (양식을 나타내는 그래픽 개체 생성), 숨기기를 위한 Hide() 메소드, 디스플레이 새로 고침을 위한 Refresh() 메소드가 있습니다. , Event() 메소드는 다른 모든 컨트롤에서와 같이 이벤트 처리 및 기타 메소드에 사용됩니다.

양식의 적용과 컨트롤 사용은 Init() 메소드의 호출로 시작하여 SetPos() 메소드를 사용하여 위치를 설정하고 Show() 메소드 또는 다른 방법으로 표시를 활성화합니다. 디스플레이는 매개 변수가 있는 Show() 메소드를 사용하여 활성화 할 수 있으며, 양식은 Hide() 메소드를 사용하여 숨길 수 있습니다.

Event() 메소드 호출이 OnChartEvent() 함수에 추가 되어 양식 컨트롤 기능 (이동, 최소화, 닫기 등)을 보장합니다. 서브 윈도우에서 양식의 동작을 확인하기 위해 필요한 경우에는 CHARTEVENT_CHART_CHANGE 이벤트 상에서의 OnChartEvent() 함수뿐만 아니라 Init() 메소드 호출 직후 호출되는 SetSubWindow() 메소드를 사용합니다. 모든 것이 다른 컨트롤과 동일합니다.

표준 컨트롤은 독립적이지만 (다른 컨트롤과 연결될 필요는 없음), 양식의 숨김/표시와 함께 배치된 컨트롤의 동시 표시/숨김을 보장하고자 해당 양식은 다른 컨트롤과의 필수 연결의 존재를 암시합니다. . 따라서 양식 및 관련 컨트롤의 Init(), Show() 및 Hide() 메소드의 동기화된 작업이 보장되어야 합니다.

하나는 확실히 양식과 관련된 모든 컨트롤의 Show() 메소드를 호출 할 수 있습니다 (예 : 형식의 Show() 메소드를 호출 할 때). 해당 컨트롤은 양식과 관련이 있죠. 그러나 프로그램에 몇 가지 양식이 사용될 때 그러한 접근법은 구조화되지 않고 이해, 디버깅 및 업데이트에 불편한 코드를 초래할 것입니다.

각 양식에 대한 양식 클래스의 복사본을 만들고 컨트롤이 있는 작업 코드를 추가 할 수 있습니다. 그러나 이는 다시 구조화되지 않은 코드(양식의 코드가 컨트롤 작업과 관련된 코드와 분리되지 않음) 및 양식의 설계와 기능을 담당하는 코드 부분만 복제되는 코드의 과도한 중복의 발생을 초래합니다; 이 모든 것은 모든 클래스 사본에서 변경을 수행해야 하기 때문에 모든 양식 기능에 대한 수정 적용을 복잡하게 합니다.

기본 클래스와 하위 클래스로의 분할은 여러 양식 작성, 양식 및 관련 컨트롤의 표시 동기화 및 다른 양식과 관련된 코드의 명확한 분리 문제를 해결하는 데 도움이 됩니다. 기본 문제를 해결하는 것 외에도 클래스 및 하위 클래스를 사용하면 이미 완료된 작업을 변경하지 않고도 기본 클래스를 향후 업그레이드 할 수 있습니다.

컨트롤과 양식의 Init(), Show() 및 Hide() 메소드 호출을 동기화하기 위해 CFormBase 클래스는 표준 컨트롤 클래스와 약간의 차이가 있습니다. 몇 가지 가상 메소드 보호된 섹션 :

virtual void MainProperties() {}
virtual void OnInitEvent() {}
virtual void OnShowEvent() {}
virtual void OnHideEvent() {}
virtual void EventsHandler(const int id, const long& lparam, const double& dparam, const string& sparam){}
virtual void OnWindowChangeEvent(int aSubWindow) {}
virtual bool OnCancelEvent() {return(true);}
virtual bool OnApplyEvent()  {return(true);} 

이러한 메소드는 가상이므로 CFormTemplate 하위 클래스의 해당하는 실제 메소드로의 리디렉션이 이를 통해 수행됩니다.

CFormTemplate 하위 클래스는 자체적으로 사용되지 않으며 템플릿입니다. 새 양식을 만들려면 고유 한 이름으로 CFormTemplate 클래스의 복사본을 만듭니다 (CFormTemplate 클래스의 코드를 복사하고 이름을 바꾸고 모든 양식에 대해 동일하게 반복). 서브 클래스를 복사하면 다른 형식과 관련된 코드를 분리 할 수 ​​있습니다.

가상 메소드는 protected 섹션에 있으며 따라서 다른 양식 이벤트에 대해 메소드가 기본 클래스에서 이미 호출 되었기 때문에 필요하지 않은 호출에는 액세스 할 수 없습니다. 이러한 이벤트에 해당하는 컨트롤의 작동을위한 코드만 추가해야 합니다.

아래 그래프는 Expert Advisor 기능과 표준 컨트롤 클래스 방법 간의 상호 작용을 보여줍니다. (그림 4) 그리고 양식 클래스 메소드와의 상호 작용을 비교합니다 (그림 5).

그림 4. Expert Advisor 기능과 컨트롤 방법 간의 상호 작용
그림 4. Expert Advisor 기능과 컨트롤 방법 간의 상호 작용

그림 5. Expert Advisor 기능과 양식 클래스 메소드 간의 상호 작용
그림 5. Expert Advisor 기능과 양식 클래스 메소드 간의 상호 작용

각 방법의 목적을 자세히 살펴 보겠습니다.

  • MainProperties() 및 OnInitEvent() 메소드는 양식의 Init() 메소드에서 호출됩니다. MainProperties() 메소드는 양식의 모양 (양식 유형, 이동 유무, 최소화 및 닫기 단추)을 설정합니다. OnInitEvent() 메소드는 모든 컨트롤의 Init() 메소드를 호출하고 컨트롤에 기본값을 설정합니다.

  • OnShowEvent() 메소드는 Show() 메소드에서 호출됩니다. 모든 컨트롤의 Show() 메소드 호출 코드가 여기에 추가됩니다.

  • OnHideEvent() 메소드는 Hide() 메소드에서 호출됩니다. 모든 컨트롤의 Hide() 메소드 호출 코드가 여기에 추가됩니다.

  • The EventsHandler() method is equivalent to the Expert Advisor's OnChartEvent() function. 양식의 Event() 메소드는 Expert Advisor의 OnChartEvent() 함수에서 호출되며 모든 차트 이벤트는 이 메소드로 리디렉션됩니다. 모든 컨트롤의 Event() 메소드의 호출 코드와 해당 이벤트 처리가 EventsHandler()에 추가됩니다.

  • OnWindowChangeEvent() 메소드는 하위 창을 변경할 때 SetSubWindow() 메소드에서 호출됩니다. 모든 컨트롤의 SetSubWindow() 메소드의 호출 코드가 여기에 추가됩니다. 이 메소드에는 모든 컨트롤에 설정할 새 하위 창 번호를 전달하는 매개 변수가 있습니다.

  • OnCancelEvent() 메소드는 양식을 닫을 때 실행됩니다 (십자 이미지, "취소" 또는 "닫기" 단추가 있는 단추를 클릭 할 때). 양식을 닫을 때 확인 코드를 추가 할 수 있습니다 (예 : 양식을 실제로 닫아야하는지 확인하기 위한 확인 창 호출). 메소드가 true를 반환하면 양식을 닫는 코드가 완료되고 양식이 닫힙니다. 메소드가 false를 반환하면 양식을 닫는 코드 실행이 중단되고 양식은 열린 상태로 유지됩니다.

  • OnApplyEvent() 메소드는 양식의 "Apply "버튼을 클릭하면 실행됩니다. 여기에서 (OnCancelEvent() 메소드에서와 같이) 몇 가지 검사를 실행하고 메소드가 true 또는 false를 반환하여 양식을 닫을 수 있는지 여부를 확인할 수 있습니다. 이 방법은 또한 Expert Advisor의 다음 시작시 컨트롤 값이 프로그램이 종료되기 전과 동일하도록 컨트롤 값을 저장하는 코드를 포함 할 수 있습니다. 이를 위해 저장된 값을 OnInitEvent() 메소드에 로드하고 컨트롤에 설정해야 합니다.

 

2. 새 양식을 만드는 단계별 절차

따라서 새 양식을 만드는 단계별 절차는 다음과 같습니다.

1. IncGUI_v3.mqh 파일을 포함합니다.

#include <IncGUI_v3.mqh>
2. IncGUI_v3.mqh 파일에서 CFormTemplate 클래스의 코드를 Expert Advisor의 파일로 복사하고 (하위 클래스는 파일의 끝에 있음) 이름을 바꿉니다 (라이브러리 사용 예제에서 하위 클래스는 CForm으로 명명 됨). 

 

class CFormTemplate: public CFormBase{
   public:
   protected      void MainProperties()
     {
        m_Name        = "Form";       // Form name. The names of all the controls of this form should start with it.
        m_Width       = 200;           // Form width
        m_Height      = 150;           // Form height
        m_Type        = 1;             // Form type: 0 - without buttons, 1 - with "Apply" and "Cancel" buttons, 2 - with the "Close" button
        m_Caption     = "FormCaption"; // Form caption
        m_Movable     = true;          // Movable form (the button with a hand image is displayed in the top left corner)
        m_Resizable   =  true;         // Form minimizing/maximizing allowed (the button with a rectangle image 
                                           // is displayed in the top right corner)
        m_CloseButton = true;          // Form closing allowed (the button with a cross image is displayed in the top right corner)
     }
      void OnInitEvent() {} 
      void OnShowEvent(int aLeft, int aTop) {}
      void OnHideEvent() {}
      void OnWindowChangeEvent(int aSubWindow) {}
      void EventsHandler(const int id,const long& lparam,const double& dparam,const string& sparam){}
      bool OnApplyEvent()  {return(true);}
      bool OnCancelEvent() {return(true);}
};

양식 코드에 대한 별도의 포함 파일을 만들고 Expert Advisor에 포함하고 CFormTemplate 하위 클래스의 코드를 여기에 복사하고 이 파일에서 양식 작업과 관련된 나머지 코딩을 수행 할 수 있습니다.

시각적 편집기를 사용하여 비유하면 이 단계는 버튼을 클릭하여 다양한 양식 이벤트의 기능이 있는 새 양식 파일이 프로젝트에 나타나는 새 양식을 만드는 것과 매우 유사합니다.

3. 양식의 주요 속성을 설정합니다. 이 단계는 기본 클래스에 선언된 변수에 값을 할당하여 MainProperties() 메소드에서 실행됩니다. 모든 변수의 용도에 대한 자세한 설명은 템플릿에 제공됩니다. 비주얼 편집기 (예 : Excel의 VBA)에서 양식 속성 창을 사용하는 것과 이 단계의 유사점을 확인할 수 있습니다.

void MainProperties()
{
   m_Name         =  "Form";        // Form name. The names of all the controls of this form should start with this one.
   m_Width        =  200;           // Form width
   m_Height       =  150;           // Form height
   m_Type         =  1;             // Form type: 0 - without buttons, 1 - with "Apply" and "Cancel" buttons, 2 - with the "Close" button
   m_Caption      =  "FormCaption";   // Form caption
   m_Movable      =  true;          // Movable form (the button with a hand image is displayed in the top left corner)
   m_Resizable    =  true;          // Form minimizing/maximizing allowed (the button with a rectangle image 
                                    // is displayed in the top right corner)
   m_CloseButton = true;            // Form closing allowed (the button with a cross image is displayed in the top right corner)
}

다른 컨트롤과 양식의 또 다른 차이점을 알 수 있습니다. 양식 이름은 Init() 메소드 매개 변수로 전송되는 대신 MainProperties() 메소드에서 설정됩니다.

양식에 대한 주요 작업은 하위 클래스에서 수행됩니다. 양식의 모든 하위 클래스는 한 번만 선언되므로 양식의 한 하위 클래스의 Init() 메소드를 호출 할 때 다른 이름을 지정할 필요가 없습니다.

Init() 메소드로 전송할 수있는 유일한 매개 변수는 State 매개 변수이지만 이 매개 변수도 필수는 아닙니다. State 매개 변수의 값은 표시 될 때 양식의 초기 상태(최대화 또는 최소화)를 결정합니다. 값이 1이면 양식이 최대화되고 (그림 1, 2, 3) 값이 2이면 양식이 최소화됩니다 (그림 6).

그림 6. 최소화된 형태

그림 6. 최소화된 형태

4. 클래스를 선언하십시오.

CForm frm;

5. 컨트롤을 사용하는 표준 단계를 만듭니다. Expert Advisor의 OnInit() 함수에서 양식의 Init() 메소드를 호출하고, OnDeinit() 함수에서 Deinit() 메소드를 호출하고, OnChartEvent()에서 Event() 메소드를 호출합니다. 함수를 사용하고 필요한 경우 CHARTEVENT_CHART_CHANGE 이벤트시 SetSubWindow() 메소드를 호출합니다.

양식은 나중에 차트에 표시되고 이동, 최소화, 닫기 버튼 등을 클릭하는 데 응답해야 합니다.

그런 다음 양식에 컨트롤을 추가합니다.

 

3. 양식에 컨트롤을 추가하는 단계별 절차

  1. 컨트롤 선언. 양식 외부의 컨트롤 메소드에 대한 액세스를 보장해야 하는 경우 컨트롤 클래스는 public 섹션에서 선언해야 합니다. 모든 작업이 양식 클래스 내에서 수행 될 수있는 경우 컨트롤 클래스는 protected 섹션에서 선언되어야 합니다.

  2. 컨트롤 값을 복원하기위한 변수 선언 선택적 단계. "취소" 및 "적용" 버튼이 있는 양식을 사용하려는 경우 사용자가 컨트롤을 변경하면 값을 복원하기 위해 양식을 열 때 컨트롤이 가졌던 값을 저장하기 위해 모든 컨트롤에 변수를 추가해야 합니다. "취소" 버튼을 누릅니다.

  3. 모든 컨트롤의 Int() 메소드 호출 OnInitEvent() 메소드에서 실행됩니다.

  4. 저장된 데이터를 로드합니다. 선택적 단계입니다. OnInitEvent() 메소드에서 실행됩니다. 이 단계는 Expert Advisor, Terminal 또는 컴퓨터를 다시 시작한 후 컨트롤이 값을 유지해야 하는 경우에 사용됩니다. 데이터 저장은 12 단계에서 수행됩니다.

  5. 기본값 설정이 단계에서 모든 컨트롤은 Expert Advisor를 시작한 후 양식을 처음 열 때 컨트롤에 표시되는 값으로 설정됩니다 (해당 값이 사용자). 4 단계에서 데이터가 로드된 경우 로드된 데이터가 사용됩니다. 컨트롤의 추가 준비도 이 단계에서 수행됩니다. 예를 들어 목록 및 메뉴 항목도 여기에 추가됩니다.

  6. 모든 컨트롤에 대해 Show() 메소드 (매개 변수가있는 버전) 호출은 OnShowEvent() 메소드에서 실행됩니다. OnShowEvent() 메소드에는 양식 작업 공간의 왼쪽 상단 모서리 좌표를 전달하는 두 개의 매개 변수 (int aLeft, int aTop)가 있습니다. 컨트롤 위치는 이러한 변수의 값에 따라 설정됩니다 (값을 추가해야 함).

  7. 양식의 모든 컨트롤에 대한 Hide() 메소드 호출은 OnHideEvent() 메소드에서 실행됩니다.

  8. SetSubWindow() 메소드 호출 선택적 단계. 하위 창에 양식을 표시해야 하는 경우 모든 컨트롤에 대해 SetSubWindow 메소드가 호출됩니다. 새 하위 창 번호를 전달하는 매개 변수 (int aSubWindow)가있는 OnWindowChangeEvent() 메소드에서 실행됩니다.

  9. 모든 컨트롤의 Event() 메소드 호출. 이것은 EventsHandler() 메소드에서 실행됩니다.

  10. 컨트롤 이벤트 처리. 선택적 단계. 이벤트 시 컨트롤 간의 상호 작용을 보장해야 하는 경우 이 단계에서 이벤트가 처리되고 적절한 작업이 실행됩니다. 이것은 EventsHandler() 메소드에서 실행됩니다.

  11. 새 값 적용 "적용" 버튼을 사용하여 실행되는 선택적 단계입니다. OnApplyEvent() 메소드에서 실행됩니다. 이 단계에서는 컨트롤 값의 정확성을 확인합니다. 잘못된 값이 발견되면 사용자에게 알려야하며 메소드는 false를 반환하고 양식은 열린 상태로 유지됩니다. 값이 정확하다면 양식을 닫기 위해 true가 반환되어야 합니다.

  12. 데이터 저장. 선택적 단계. "Apply" 버튼을 사용하여 OnApplyEvent() 메소드에서 실행됩니다. 데이터는 파일, 전역 변수, 차트의 보이지 않는 개체 등에 저장할 수 있습니다 (목표 및 목적에 따라 다름).

  13. OnCancelEvent() 메소드를 확인합니다. 선택적 단계. OnCancelEvent() 메소드에서 false가 반환되면 양식이 열린 상태로 유지됩니다. 즉, 닫기 버튼이 응답하지 않습니다. 양식을 닫으려면 메소드에서 true를 반환해야 합니다.

양식 작업의 예는 첨부된 eIncGUI_v3_Test_Form.mq5 파일에서 찾을 수 있습니다. 다른 컨트롤이 있는 기본 양식은 시작할 때 열립니다 (그림 7).

양식에는 닫기 버튼이 없습니다. 이것은 기본 양식이며 차트에서 사라지지 않도록 해야 합니다. 그렇지 않으면 양식이 다시 나타나려면 Expert Advisor를 다시 시작해야 합니다.

그림 7. 열린 기본 메뉴 탭이 있는 eIncGUI_v3_Test_Form.mq5 예제의 기본 양식

그림 7. 열린 기본 메뉴 탭이 있는 eIncGUI_v3_Test_Form.mq5 예제의 기본 양식

주 메뉴 명령을 사용하여 양식의 다른 두 가지 변형을 열 수 있습니다.

주 메뉴 - 양식 유형 - 유형 1은 유형 1의 양식을 엽니다 ("취소" 및 "적용" 버튼 포함).
주 메뉴 - 양식 유형 - 유형 2는 유형 2의 양식을 엽니다("닫기" 버튼 사용).

두 양식 모두 닫을 때 확인이 필요합니다 (MessageBox() 함수를 사용하여 수행됨). 유형 1 양식에는 입력 상자가 있습니다. "적용" 버튼을 클릭하여 입력 값을 확인합니다. 유형 2 양식에는 새 컨트롤 "Label" (CLabel 클래스)과 이를 테스트 할 몇 개의 단추 (CButton 클래스)가 있습니다.

이제 소개에서 언급했듯이 주 메뉴를 생성하여 예시 한대로 CHMenu 및 CVMenu 클래스의 변경 사항을 검토해 보겠습니다.

 

우선, 가로 바 (CHMenu 클래스 기반)와 탭 (CVMenu 클래스 기반)의 2 단계 메뉴 만 만들 수 있다고 말하고 싶습니다. 원칙적으로 더 많은 레벨을 생성 할 수 있지만 프로세스가 매우 복잡하고 힘들기 때문에 권장되지 않으며 더 이상 고려되지 않습니다.

사실, 양식에 대한 메인 메뉴의 생성은 계획조차 없었고, CHMenu와 CVMenu 클래스는 다양한 기능과 도구를 활성화/비활성화하기 위해 개별적으로 그리고 서로 독립적으로 사용되어야 했습니다. 그러나 CHMenu 및 CVMenu 클래스의 약간의 개선으로 대부분의 경우에 충분한 주 메뉴를 얻을 수 있습니다.

본격적인 다단계 메뉴를 만들려면 다소 다른 접근 방식이 적용되어야 합니다(나무와 같은 데이터 구조의 생성). 이 방식은 전체 개별 글에 대한 주제를 제공할 수 있기 때문에 이제 기존 수단으로 자신을 제한할 것입니다.

먼저 CHMenu 및 CVMenu 클래스에 적용된 모든 변경 사항과 수정 사항을 검토하겠습니다.

CVMenu 클래스에서 틱 기호를 표시하는 데 사용되는 그래픽 개체 "Label"을 클릭하는 것에 대한 응답이 수정되었습니다. 이에 따라 LastClickedX(), LastClickedY() 및 LastClickedQuarter() 메소드의 동작이 변경되었습니다. 레이블을 클릭하면 이제 텍스트 상자의 경우와 같이 값이 반환됩니다. 유사한 수정 사항이 CHMenu 클래스 및 LastClickedX(), LastClickedY(), LastClickedQuarter() 및 LastClickedW() 메소드에 적용되었습니다.

두 클래스 모두 메뉴 명령에 표시되는 그래픽 객체의 좌표를 계산하기 위한 SolvePosX() 및 SolvePosY() 메소드를 추가하여 업데이트되었습니다. 표시된 객체의 너비는 SolvePosX() 메소드로 전달되고 표시된 객체의 높이는 표시된 객체의 X 좌표 또는 Y 좌표를 각각 반환하는 SolvePosY() 메소드로 전달됩니다. 이제 더 이상 LastClickedX(), LastClickedY(), LastClickedQuarter() 및 LastClickedW() 메소드를 사용할 필요가 없습니다.

LastClickedName1() 및 LastClickedName2() 메소드를 추가하여 두 클래스가 모두 업데이트되었습니다. 이러한 메소드는 마지막으로 클릭한 메뉴 항목을 형성하는 그래픽 개체의 이름을 반환합니다. LastClickedName1() 은 텍스트 상자의 이름을 반환하고 LastClickedName2()는 틱 기호의 레이블 이름을 반환합니다.

ToggleNameAdd() 및 ToggleNamesClear() 메소드가 CVMenu에 추가되었습니다. ToggleNameAdd() 메소드는 "toggle" 이름 목록을 만드는 데 사용되며 ToggleNamesClear() 메소드는 이 목록을 지우는 데 사용됩니다. ToggleNameAdd() 메소드를 사용하는 경우 (목록에 이름 추가) 메뉴를 구성하는 그래픽 개체의 이벤트와 ToggleNameAdd() 메소드에 의해 이름이 추가된 그래픽 개체의 이벤트를 제외하고 모든 차트 이벤트에서 메뉴가 자동으로 닫힙니다. ToggleNamesClear() 메소드로 목록을 지우면 메뉴가 정상 작동 모드로 돌아갑니다.

2 단계 메뉴의 동작은 다음과 같습니다. 가로 메뉴 항목을 클릭하는 이벤트가 LastClickedName1() 및 LastClickedName2() 메소드에 의해 정의되면 이 항목의 개체 이름을 수직 메뉴의 ToggleNameAdd()로 가져와 추가로 전송합니다.

이 후 세로 메뉴 이벤트와 가로 메뉴 항목 1개(세로 메뉴가 열림)의 이벤트를 제외하고 차트에서 세로 메뉴가 숨겨집니다.

사용자가 세로 메뉴 항목을 선택했다면 세로 메뉴를 닫고 이 항목에 해당하는 동작을 실행해야 합니다. 사용자가 동일한 가로 메뉴 항목 (세로 메뉴가 열림)을 반복적으로 클릭하면 세로 메뉴가 숨겨져야 합니다.

t/phe 메뉴 생성의 예를 살펴 보겠습니다.

메인 메뉴에는 세 가지 항목이 있으므로 세 개의 수직 메뉴가 필요합니다. 양식 하위 클래스의 public 섹션에서 가로 메뉴 클래스와 세 개의 세로 메뉴 클래스를 선언합니다 (아래 예제는 eIncGUI_v3_Test_Form.mq5 예제에서와 똑같은 방식으로 보여줍니다).

class CForm: public CFormBase{
public:
   CHMenu m_hm;
   CVMenu m_vm1;
   CVMenu m_vm2;
   CVMenu m_vm3; 

OnInitEvent() 메소드에서 메뉴 클래스를 초기화하고 메뉴 항목을 추가합니다.

// Horizontal menu
m_hm.Init(m_Name+"_HM",m_Width,2);
// Adding horizontal menu items
m_hm.AddItem("Form types");
m_hm.AddItem("Item-2");
m_hm.AddItem("Item-3");
// Vertical menu 1
m_vm1.Init(m_Name+"_VM1",70,10); 
// Adding items to vertical menu 1
m_vm1.AddItem("Type-1");
m_vm1.AddItem("Type-2");
// Vertical menu 2
m_vm2.Init(m_Name+"_VM2",70,3);
// Adding items to vertical menu 2
m_vm2.AddItem("Item-2-1");
m_vm2.AddItem("Item-2-2");
m_vm2.AddItem("Item-2-3"); 
m_vm2.AddItem("Item-2-4");
m_vm2.AddItem("Item-2-5"); 
// Vertical menu 3
m_vm3.Init(m_Name+"_VM3",70,3);
// Adding items to vertical menu 3
m_vm3.AddItem("Item-3-1");
m_vm3.AddItem("Item-3-2");
m_vm3.AddItem("Item-3-3"); 
m_vm3.AddItem("Item-3-4");
m_vm3.AddItem("Item-3-5"); 

OnHideEvent() 메소드에서 메뉴를 숨깁니다.

void OnHideEvent()
{
   m_hm.Hide(); 
   m_vm1.Hide(); 
   m_vm2.Hide(); 
   m_vm3.Hide(); 
}

OnShowEvent() 메소드에서 가로 메뉴를 표시합니다.

void OnShowEvent(int aLeft,int aTop)
{
    m_hm.Show(aLeft,aTop); 
}

마지막으로 EventsHandler() 메소드의 주요 작업입니다.

모든 메뉴의 Event() 메소드를 호출합니다.

void EventsHandler(const int id,const long& lparam,const double& dparam,const string& sparam)
{
    int m_event0=m_hm.Event(id,lparam,dparam,sparam);
    int m_event1=m_vm1.Event(id,lparam,dparam,sparam);
    int m_event2=m_vm2.Event(id,lparam,dparam,sparam);
    int m_event3=m_vm3.Event(id,lparam,dparam,sparam); 

m_event0 값 (가로 메뉴 항목 인덱스)에 따라 적절한 세로 메뉴 (예 : 항목 0 및 세로 메뉴 1)로 작업합니다.

if(m_event0==0)
{ // Clicking item 0
   if(m_vm1.Visible())
   { 
      m_vm1.Hide(); // If the vertical menu is open, close it
   }
   else{ // If the vertical menu is closed
      m_vm1.ToggleNamesClear(); // Clear the list of "toggle" names
      // Add to the list the names of the graphical objects forming the item 
      // of the horizontal menu which led to the last event 
      // of the horizontal menu 
      m_vm1.ToggleNameAdd(m_hm.LastClickedName1()); 
      m_vm1.ToggleNameAdd(m_hm.LastClickedName2());
      // Display the vertical menu
      m_vm1.Show(m_hm.SolvePosLeft(m_vm1.Width()),m_hm.SolvePosTop(m_vm1.Height())); 
   }
}

이러한 작업은 수직 메뉴를 여는 모든 수평 메뉴 항목에 대해 수행되어야 합니다. 수직 메뉴 이벤트가 발생하면 메뉴를 닫습니다.

클릭 한 항목의 인덱스에 따라 다음과 같이하십시오.

if(m_event1>=0)
{ // Vertical menu event 1
   m_vm1.Hide(); // Hide the menu
      if(m_event1==0)
      { // Clicking item 0
        //...
      }
      if(m_event1==1)
      { // Clicking item 1
        //...
      }
}

모든 수직 메뉴와 모든 항목에 대해 이러한 작업을 수행해야 합니다.

이제 메인 메뉴 생성이 완료되었습니다.

 

결론

이 글는 그래픽 인터페이스 작성에 관한 일련의 글를 마무리합니다.

저희 작업의 결과로, 저희는 다기능적이고 사용하기 쉬운 그래픽 인터페이스를 빠르게 생성 할 수있는 상당한 수단을 보유하고 있습니다. 이는 그래픽 인터페이스에 대한 기존 요구 사항과 매우 일치합니다.

  • 프레임 워크를 캡션 형태와 최소화/최대화, 이동이 가능한 형태로 사용;
  • 한 양식 또는 다른 양식과 관련하여 명확하게 지정된 코드 영역;
  • 컨트롤의 표시/숨기기는 양식의 표시/숨기기와 동기화됩니다.

모든 컨트롤과 양식에는 빠르게 변경할 수있는 공통 디자인과 색 구성표가 있습니다.

양식을 만드는 절차를 반복하겠습니다.

양식을 만드는 간단한 절차:

  1. IncGUI_v3.mqh 파일을 포함합니다.

  2. 고유한 이름으로 CFormTemplate 클래스의 복사본을 만들고 이 클래스를 선언합니다.

  3. 하위 클래스 복사본의 MainProperties() 메소드에서 양식 속성을 설정합니다.

  4. Expert Advisor의 OnInit(), OnDeinit()OnChartEvent() 함수에서 양식의 Init(), Hide() 및 Event() 메소드를 각각 호출합니다. Expert Advisor의 OnInit() 함수에서 또는 필요에 따라 Show() 메소드를 호출합니다.

  5. 컨트롤로 작업하십시오. 서브 클래스 사본에서 컨트롤 클래스를 선언하십시오. 하위 클래스 복사본의 OnInitEvent(), OnShowEvent(), OnHideEvent() 및 EventHandler() 메소드에서 컨트롤의 Init(), Show(), Hide() 및 Event() 메소드를 호출합니다.

 

부록

첨부 파일 목록:

  • IncGUI_v3.mqh -그래픽 인터페이스를 생성하기위한 모든 클래스를 포함하는 포함 파일. 파일은 터미널 데이터 디렉토리의 MQL5 / Include 디렉토리에 있어야 합니다.
  • eIncGUI_v3_Test_Form.mq5 - 양식 작업의 예. 파일은 터미널 데이터 디렉토리의 MQL5 / Experts 디렉토리에 있어야 합니다.
  • IncGUIv3mqh.chm - IncGUI_v3.mqh 파일에 대한 문서.

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

MQL5 클라우드 네트워크로 계산 속도 향상 MQL5 클라우드 네트워크로 계산 속도 향상
가정용 컴퓨터에 몇 개의 코어가 있습니까? 거래 전략을 최적화하기 위해 몇 대의 컴퓨터를 사용할 수 있습니까? 여기에서는 MQL5 클라우드 네트워크를 사용하여 마우스 클릭으로 전 세계의 컴퓨팅 성능을 받아 계산을 가속화하는 방법을 보여줍니다. "시간은 돈이다"라는 표현은 해가 갈수록 더욱 화제를 불러 일으키며 수십 시간 또는 며칠 동안 중요한 계산을 기다릴 여유가 없습니다.
사용자 정의 그래픽 컨트롤. 파트 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 프로그램의 유용성은 풍부한 기능과 정교한 그래픽 사용자 인터페이스에 의해 결정됩니다. 빠르고 안정적인 작동보다 시각적인식이 때때로 더 중요합니다. 다음은 표준 라이브러리 클래스를 기반으로 디스플레이 패널을 만드는 방법에 대한 단계별 가이드입니다.
사용자 정의 그래픽 컨트롤. 1 부: 간단한 컨트롤 만들기 사용자 정의 그래픽 컨트롤. 1 부: 간단한 컨트롤 만들기
이 글에서는 그래픽 컨트롤 개발의 일반 원칙을 다룹니다. 그래픽 개체로 빠르고 편리한 작업을 위한 도구를 준비하고 텍스트 또는 숫자 데이터를 입력하기위한 간단한 컨트롤 생성의 예와 사용 방법을 분석 할 것입니다.