처음부터 그래픽 라이브러리 만들기 - 페이지 9

 
Aliaksandr Hryshyn :

더:

창의 영역을 마우스 오른쪽 버튼으로 클릭하면 메뉴가 나타납니다. 마우스를 이동하고 왼쪽 클릭합니다. 결과적으로 창이 움직입니다.

아마도. 어떻게 이해하시겠어요? 스스로 개발하고 테스트하기 때문에 작업 과정에서 실수로 버그를 만나기 전까지는 일부 버그에 대해 전혀 모릅니다. 나 혼자 다 해...

 

여기 내 예가 있습니다. 첨부 파일에는 서로 겹쳐진 세 개의 창이 있습니다.

하위 창이 있는 단일 창을 만드는 것은 추가 코드 없이 엔진을 사용하는 것입니다. 상단 버튼 을 누르는 이벤트를 처리하는 것 외에도.

cStrategy_viewer::cStrategy_viewer()
  {
   int width_type= 126 ;
   int height_type= 30 ;
   int width_object= 170 ;
   int height_object= 22 ;

   my_handler.md= GetPointer ( this );
   int obj_types_count=(ER_NODE_TYPE_COUNT- 1 );
//Основное окно
   _main_window= new cV_object_rectangle();
   _main_window.Set_property_info(vop_position_x, 10 );
   _main_window.Set_property_info(vop_position_y, 50 );
   _main_window.Set_property_info(vop_size_x,width_type*obj_types_count);
   _main_window.Set_property_info(vop_size_y, 700 );
   _main_window.Set_property_info(vop_is_zorder_top_on_click, true );
   _main_window.Create(cV_object_base::global_parent_object);
//Заголовок
   cV_object_rectangle *caption= new cV_object_rectangle();
   caption.Set_property_info(vop_position_x,- 1 );
   caption.Set_property_info(vop_position_y,- 1 );
   caption.Set_property_info(vop_size_x,_main_window.Get_property(vop_size_x).data_long);
   caption.Set_property_info(vop_size_y, 20 );
   caption.Create(_main_window);
//Текст заголовка.Будет отображаться полное имя файла стратегии
   _caption_text= new cV_object_label();
   _caption_text.Set_property_info(vop_position_x,- 1 );
   _caption_text.Set_property_info(vop_position_y,- 1 );
   _caption_text.Set_property_info(vop_size_x,caption.Get_property(vop_size_x).data_long);
   _caption_text.Set_property_info(vop_text, "Стратегия ...." );
   _caption_text.Set_property_info(vop_text_anchor, TA_CENTER );
   _caption_text.Set_property_info(vop_font_size, 20 );
   _caption_text.Set_property_info(vop_is_movable, true );
   _caption_text.Set_property_info(vop_moving_parent_index, 2 );
   _caption_text.Set_property_info(vop_is_position_fixing_parent_x, true );
   _caption_text.Set_property_info(vop_is_position_fixing_parent_y, true );
   _caption_text.Set_property_info(vop_position_fixing_parent_index_x, 2 );
   _caption_text.Set_property_info(vop_position_fixing_parent_index_y, 2 );
   _caption_text.Create(caption);
//Контейнер для типов объектов
   _object_types= new cV_object_base();
   _object_types.Set_property_info(vop_position_x, 0 );
   _object_types.Set_property_info(vop_position_y, 20 );
   _object_types.Set_property_info(vop_size_x,obj_types_count*width_type);
   _object_types.Set_property_info(vop_size_y,height_type);
   _object_types.Create(_main_window);
//Типы объектов
   cV_object_rectangle *obje_type;
   cV_object_label *obje_type_text;
   for ( int i1= 0 ; i1<obj_types_count; i1++)
     {
      obje_type= new cV_object_rectangle();
      obje_type.Set_property_info(vop_position_x,i1*width_type);
      obje_type.Set_property_info(vop_position_y, 0 );
      obje_type.Set_property_info(vop_size_x,width_type);
      obje_type.Set_property_info(vop_size_y,height_type);
      obje_type.Set_property_info(vop_border_line_width, 3 );
      obje_type.Set_property_info(vop_color_borders_mouse_moving, clrLightBlue );
      obje_type.Set_property_info(vop_color_borders_selected, clrYellow );
      obje_type.Set_property_info(vop_is_change_color_borders_on_mouse_move, true );
      obje_type.Set_property_info(vop_is_change_color_borders_on_select, true );
      obje_type.Set_property_info(vop_is_selected, false );
      obje_type.Set_property_info(vop_is_my_event_MOUSE_DOWN_UP_CLICK_LEFT, true );
       color clr= 0 ;
       switch (eNode_type(i1+ 1 ))
        {
         case nt_function:
           {
            clr= clrDimGray ;
             break ;
           }
         case nt_indicator_data:
           {
            clr= clrNavy ;
             break ;
           }
         case nt_indicator:
           {
            clr= clrMaroon ;
             break ;
           }
         case nt_if:
           {
            clr= clrBlack ;
             break ;
           }
         case nt_const:
           {
            clr= clrGreen ;
             break ;
           }
         case nt_buffer:
           {
            clr= clrBlue ;
             break ;
           }
         case nt_node_top:
           {
            clr= clrIndigo ;
             break ;
           }
        }
      obje_type.Set_property_info(vop_color_borders,clr);
      obje_type.Set_property_info(vop_color_back,clr);
      obje_type.Create(_object_types);
      obje_type.Add_event_handler( GetPointer (my_handler));
      obje_type_text= new cV_object_label();
      obje_type_text.Set_property_info(vop_text, StringSubstr ( EnumToString (eNode_type(i1+ 1 )), 3 ));
      obje_type_text.Set_property_info(vop_color_back, clrWhite );
      obje_type_text.Set_property_info(vop_size_x,width_type- 1 );
      obje_type_text.Set_property_info(vop_position_x,- 3 );
      obje_type_text.Set_property_info(vop_position_y, 5 - 3 );
      obje_type_text.Set_property_info(vop_text_anchor, TA_CENTER );
      obje_type_text.Set_property_info(vop_font_size, 18 );
      obje_type_text.Create(obje_type);
     }
   _object_types.Get_child( 0 ).Set_property(vop_is_selected, true );
//Окно отображения объектов
   cV_object_rectangle *objects_viever= new cV_object_rectangle();
   objects_viever.Set_property_info(vop_position_x, 0 );
   objects_viever.Set_property_info(vop_position_y,height_type+_object_types.Get_property(vop_position_y).data_long);
   objects_viever.Set_property_info(vop_size_x,width_object);
   objects_viever.Set_property_info(vop_size_y, 30 *height_object);
   objects_viever.Create(_main_window);
//Контейнер объектов
   int functions_count=cRules::Get_object_count(nt_function);
   _objects= new cV_object_base();
   _objects.Set_property_info(vop_position_x, 0 );
   _objects.Set_property_info(vop_position_y, 0 );
   _objects.Set_property_info(vop_size_x,width_object);
   _objects.Set_property_info(vop_size_y,functions_count*height_object);
   _objects.Set_property_info(vop_color_back, clrOlive );
//_objects.Set_property_info(vop_is_position_fixing_parent_x,true);
//_objects.Set_property_info(vop_is_position_fixing_parent_y,true);
   _objects.Create(objects_viever);
//Объекты
   for ( int i1= 0 ; i1<functions_count; i1++)
     {
      cV_object_label *object= new cV_object_label();
      object.Set_property_info(vop_size_x,width_object- 2 );
      object.Set_property_info(vop_position_x, 1 );
      object.Set_property_info(vop_position_y,i1*height_object);
      object.Set_property_info(vop_color_back, clrWhite );
      object.Set_property_info(vop_text,cRules::Get_object_name(nt_function,i1));
      object.Set_property_info(vop_text_anchor, TA_LEFT );
      object.Set_property_info(vop_font_size,height_object- 2 );
      object.Create(_objects);
     }
  }

상단의 버튼 클릭 이벤트 처리:

 void cStrategy_viewer::cMy_handler::On_event(sEvent & event )
  {
   cV_object_base *obj=GetPointer( event . object );
   switch ( event .id)
     {
       case CHARTEVENT_CLICK_:
        {
         if (obj.Get_parent()==GetPointer(md._object_types))
           {
            obj.Set_property(vop_is_selected, true );
           }
         break ;
        }
     }
  }

버튼은 여러 개이지만 부모 창은 하나만 있음

파일:
 
Реter Konow :

그런 버그가 있었습니다. 수정했습니다. 이벤트 자체는 순서대로 고정되지만 코드가 진화함에 따라 피할 수 없는 다양한 변경으로 버그가 발생합니다.

예, 쉽지 않습니다

데모 사진:


 
그런 경우에는 우선 이벤트와 창 제어를 잘 처리해야 하고 나머지는 훨씬 더 많은 작업이 필요하지만 나머지는 이미 더 간단합니다.
 
처음부터 비주얼 요소 라이브러리를 만들고 싶은 분들이 계시죠 :) ?
 
Aliaksandr Hryshyn :
그런 경우에는 우선 이벤트와 창 제어를 잘 처리해야 하고 나머지는 훨씬 더 많은 작업이 필요하지만 나머지는 이미 더 간단합니다.

백로그가 이미 있습니다.

1: Windows에는 닫기 및 최소화 버튼이 있어야 합니다(최소한).

2: 창은 클릭할 때 서로의 위에 다시 그려야 합니다.

3: 창은 마우스로 움직여야 합니다.

4. 윈도우는 커서가 움직일 때 차트에서 "발견"(포커스가 됨)되어야 합니다( 포인트 이벤트).

5. 모든 창 요소는 창의 공통 "지도"에 있어야 하며 마우스를 가져가면 찾을 수 있습니다(지정된 이벤트).

 

가장 간단한 요소:

1. 정적이며 크기가 변경되지 않고 축소되지 않은 창입니다.

2. 버튼.

3. 체크박스.

4. 라디오 버튼.

5. 탭.

6. 선, 프레임, 구분선, 직사각형.


중간 난이도의 요소:

1. 슬라이더.

2. 진행률 표시줄.

3. 필드를 입력합니다.

4. 스크롤 가능한 필드.

5. 단순 목록 항목.


고도의 복잡성 요소.

1. 드롭다운 목록(매우 복잡한 요소).

2. 동적(신축성) 창. 슈퍼 하드.


총 50가지 종류의 컨트롤이 있습니다. 각각은 엔진의 해당 기능에서 지원하는 공통적이고 고유한 속성 집합을 가져야 합니다. 최소 100개의 속성이 있습니다. 그렇지 않으면 요소의 작업이 심각하게 제한됩니다.

단순한 모양과 선에는 많은 속성이 필요하지 않지만 요소가 복잡할수록 더 많이 필요합니다.
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
  • www.mql5.com
Все объекты, используемые в техническом анализе, имеют привязку на графиках по координатам цены и времени – трендовая линия, каналы, инструменты Фибоначчи и т.д.  Но есть ряд вспомогательных объектов, предназначенных для улучшения интерфейса, которые имеют привязку к видимой всегда части графика (основное окно графика или подокна индикаторов...
 

쓰레기! 테이블을 잊어 버렸습니다! 거기 정글...

그리고 나무 모양의 목록 과 다양한 줄무늬의 모든 종류의 폴더 ...

 
각 대화형 컨트롤에는 자체 속성 집합으로 관리하는 매개 변수가 있습니다. 예를 들어, 버튼은 bool 유형(1 또는 0)의 매개변수이고, 입력 필드에는 문자열(문자열) 유형 의 매개변수가 있고, 슬라이더는 범위(범위)입니다. 버튼이 있는 입력 필드에는 다음 매개변수가 있습니다. 속성 current_value, last_value, min, max, step, value_type 및 기타. 각 속성은 기능으로 뒷받침됩니다.

각 대화형 요소(좋은 의미)에는 서로 다른 이벤트에 따라 변경되는 8개의 서로 다른 상태가 있어야 합니다.

예: 중립, neutral_pointed,activated_neutral,activated_pointed,neutral_highlighted,activated_highlighted,neutral_locked,activated_locked.

각 상태는 고유한 요소 속성 값 집합을 사용하여 고려되며 특수 기능으로 수정되는 고유한 이벤트에 영향을 미칩니다.
 
Реter Konow :

쓰레기! 테이블을 잊어 버렸습니다! 거기 정글...

그리고 나무 모양의 목록과 다양한 줄무늬의 모든 종류의 폴더 ...

제 경우에는 "정글"이 평균보다 더 복잡하지 않게 만들어졌습니다. 표시 창(표의 가시 영역), 모든 셀이 맞아야 하는 전체 크기 창, 내부로 이동합니다. 기본 창, 행 및 셀 창, 스크롤링(슬라이더, 밴드 제한). 상대적 배치 구속은 속성에 의해 결정됩니다. 슬라이더의 경우에만 개체 이동 이벤트 를 가로채고 " 전체 크기 창"의 위치를 이미 조정해야 합니다. 이것은 모두 가상 창으로 수행되며 시각적 부분을 첨부해야 합니다. 시각적 부분이 없으면 선 창과 전체 크기 창이 있습니다. 글쎄, 편집된 셀에 대해 입력 필드를 만들고(이것은 이미 스스로 수행함) 나머지 모든 상호 작용은 엔진에 의해 구현됩니다. 각 셀에 대한 올바른 이벤트가 도착합니다(마우스 이벤트, 다시 그리기, 이동) .. .. 이러한 기회, 많은 창(큰 목록, 테이블, 수천 개의 창)이 있을 때 성능을 높일 수 있는 몇 가지 아이디어가 더 있습니다.