2013-05-27 1 views
1

단락 : 이벤트 및/또는 위젯에 대해 "정적으로"선언 된 ID가 중형 및 대형 프로젝트간에 충돌하지 않는지 확인하는 방법은 무엇입니까? WxWidget ID 문제

... 그리고 긴 : wxWidgets에있는 ID를 다루는

한 가지 방법은 위젯의 소스 파일에서 컴파일 단위, 즉 당 열거에 의해를 선언하는 것입니다. 그러나 ID가 WxWidgets의 이벤트 처리에 사용될 때는 전역 적으로 고유해야합니다. 일부는 전 세계적으로 고유 할 필요는 없지만 모든 것이 안전하다면 런타임에 잠재적 인 가능성이 있습니다. "충돌"은 경고를 유발하지 않습니다. 이벤트는 단순히 다른 위젯에 의해 처리됩니다. 불행히도, 나는이 문제를 두 번이나 보았습니다. (상속 된 코드베이스) - 뭔가를 놓치지 않는 한 추적하기가 어렵고 짜증납니다. 어쨌든, 이것을 한 번에 정렬하고 싶습니다. :-)

나는 WxWidgets도 동적 바인딩을 지원하며, 우리는 이것을 일부 장소에서 사용합니다. 그러나 모든 "정적으로"선언 된 ID에 대한 코드를 변경하는 것은 너무 많은 노력입니다. 따라서 본질적으로 wxID_HIGHEST에서 열거 된 열거 형 (겉으로보기에) 임의의 오프셋이있는 많은 개별 소스 파일 (> 60)이 있습니다. 오프셋이 임의적이라고 생각합니다. 위의 ID 충돌 문제에 대한 단일 사례를 수정하기 위해 추가 된 것 같습니다. 어쨌든 모든 열거 형을 하나의 파일/열거 형에 넣는 것은 믿을 수 없을 정도로 긴 목록이므로 약간 추한 것 같습니다.

여기 제가 생각해 봤습니다. 하나의 열거 형을 사용하여 하나의 헤더 파일에 여러 위젯의 MIN/MAX-ID를 유지 관리하고 주어진 ID 열거 형을 시작하고 끝내는 두 개의 매크로를 제공합니다. END-macro는 선언 된 MAX-ID가 초과되지 않았는지 확인해야합니다. 그게 합리적이라고 생각하니? ID 충돌 문제를 해결하는 일반적인 방법은 무엇입니까?

내 솔루션은 다음과 같습니다. 동적 바인딩을위한 ID를 처리하는 함수를 추가 할 계획입니다. WxWindows는 ID 참조 계산 기능과 관련된 기능을 제공하지만, 필자가 생각한 바로는 ... 가능한 한 플랫폼 독립적 인 것으로 생각됩니다.

#include <wx/defs.h> 
#define NUM_OF_DYNAMIC_AUTO_IDS 500 

namespace WxWidgetIdHelper { 

    enum WxWidgetIDsEnum { 
    MIN_DYNAMIC_AUTO_ID = wxID_HIGHEST + 1, 
    MAX_DYNAMIC_AUTO_ID = MIN_DYNAMIC_AUTO_ID + NUM_OF_DYNAMIC_AUTO_IDS, 
    STATIC_ID_OFFSET = MAX_DYNAMIC_AUTO_ID + 1, 

    Widget1_MIN_ID = STATIC_ID_OFFSET + 1, 
    Widget1_MAX_ID = Widget1_MIN_ID + 20, 

    Widget2_MIN_ID = Widget1_MAX_ID + 1, 
    Widget2_MAX_ID = Widget2_MIN_ID + 20, 
    ... 
    }; 

    template<bool> struct MaxIdCheck; 
    template<> struct MaxIdCheck<false> {}; 
} 

#define BEGIN_WXWIDGET_ID_ENUM(CLASSNAME) \ 
    enum CLASSNAME##_##WXWIDGET_IDs { \ 
    CLASSNAME##_##MIN_ID = WxWidgetIdHelper##::##CLASSNAME##_##MIN_ID, 

#define END_WXWIDGET_ID_ENUM(CLASSNAME) CLASSNAME##_##MAX_ID }; \ 
    WxWidgetIdHelper::MaxIdCheck< \ 
    (CLASSNAME##_##MAX_ID>WxWidgetIdHelper::CLASSNAME##_##MAX_ID) > \ 
    INCREASE##_##CLASSNAME##_##MAX_ID_in_WxWidgetIdHelper_h; 

답변

0

가 보편적 인 대답은 없습니다하지만 난 당신이 다음 사항에 유의해야한다고 생각 :

  • IDS는 전 세계적으로 고유 할 필요가 없습니다, 그들은 각 상단 내부에 고유합니다 레벨 창. 일반적인 프로그램에서 각 대화 상자는 자체 클래스로 표시되므로이 대화 상자의 모든 ID는이 클래스에서만 제어되므로 나머지 모든 프로그램에서 신경 쓰지 않아도됩니다.
  • IMHO는 모든 컨트롤에 대해 ID를 완전히 사용하지 않아야합니다. ID를 보관하기에 너무 편리한 유일한 장소는 연관된 객체가 없으므로 메뉴 항목뿐입니다 (wxMenuItem에 바인딩 할 수 없음). 그러나 모든 컨트롤에 대해 control->Bind()을 호출하는 것이 더 낫습니다.이 컨트롤은 이벤트를 자체적으로 얻으려고하기 때문에 ID를 전혀 지정할 필요가 없습니다. 이벤트 테이블 매크로를 Bind()을 호출하는 것으로 바꾸는 것은 정말 간단하지만, ID 충돌이 없으므로 기존 이벤트 테이블에 대해 수행 할 필요조차 없습니다. 아마도 그렇게해야합니다. 새 이벤트 핸들러에 Bind()을 사용하는 것입니다.
  • XRC를 사용하는 경우 IMHO를 사용하면 모든 ID가 XRC 파일에 지정된 문자열이고 문자열을 구별하는 것이 물론 정수 ID를 구별하는 것보다 훨씬 간단합니다. 그래서이 문제는 전혀 발생하지 않습니다. 특히, XRC에서 메뉴를 정의하면 ID를 사용하는 것이 정말 편리합니다.

TL; DR 당신이 그들을 사용하는 경우 XRC에서 그들을 정의 메뉴 항목을 제외한 모든에서 ID를 사용하지 마십시오.

+0

감사합니다. 비록 합리적으로 빠르고 우아한 방식으로 (상속받은) 난장판을 해결할 필요가 있긴하지만 내가 다루고있다. 하나의 최상위 창 아래에 모든 것이 "살아"있으므로 전 세계적으로 고유 한 ID가 더 안전합니다. IMHO. 이 모든 것들이 함께 어울리는 방식은 다소 차선책이며, 부분적으로 아프고, 잘 성장하지 못하고, 잘 유지되지 않습니다. 지금은 적절한 정리 및 재구성을 할 시간이 없습니다. ID-To-Bind()는 간단합니다. ID가 OnCommandEvent() 또는 유사한 메소드의 전환 명령문에서 사용되거나 컨트롤을 찾는 데 사용되거나, (?) 무엇인가 빠졌습니까? –

+0

하나의 메소드에서 여러 컨트롤의 이벤트를 처리해야하는 경우'wxEvent :: GetEventObject() '를 사용하여 이벤트를 구분할 수 있습니다. 이것은 기본적으로 (반드시 고유 한) 제어 포인터를 ID로 재사용합니다. –

+0

ID를 사용하지 않고 메뉴 항목에 바인딩하는 방법을 찾을 때이 답변을 발견했습니다 (나는 싫어합니다). 가장 논리적 인 해결책은 (1) 'wxCommantEvent' 객체에서 이벤트 핸들러 내의 메뉴 항목에 대한 포인터를 얻거나 (2)'wxMenuItem'에 직접 바인드 할 수있는 것입니다. 적어도 왜 wxWidgets 3.1에서는 가능하지 않은지 궁금합니다. 아니면 내가 틀렸어? –