[C++Builder] About Property 를 추가한 TMyComponent

볼랜드포럼에 올렸던 글을 블로그에 재게시 합니다.
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tutorial&no=131

가끔 Third Party Component 를 설치하다 보면 Object Inspector 에 About Property 가 있는 것을 알 수 있습니다.



이것을 C++Builder 에서 어떻게 구현하는지 알아봅시다.

이것을 구현하려면 먼저 Property Editor 에 대해서 알아야 합니다. Property Editor 란 Property 의 type 에 맞는 값을
입력할 수 있도록 된 Editor 입니다.


여기저기 자료를 찾다보니 아크로에디트를 만드신 김성동님께서 공개하신 강좌가 있네요.

Property Editor 만들기

델파이강좌이지만 빌더도 마찬가지이므로 기본적인 방법은 같습니다. 자세한 내용은 위 강좌를 참고하시고,

여기서는 Property Editor 중에서 대화형 상자를 이용한 Property Editor 를 만들어 보겠습니다.

이전의 Component Editor 제작에서와 마찬가지로 일반적인 Application 제작으로 시작합니다.
그리고 Property Editor 를 상속받은 class 를 만들고 멤버 함수를 만들면 되는 것입니다.

이번에 만들려고 하는 폼은 다음과 같습니다.



적당한 그림을 보여주고 정보를 얻을 수 있는 URL 을 표시합니다.

이제 만들어야 하는 파일은 모두 9개입니다.

MyComponent.cpp          //TComponent 상속받아 About property 추가
MyComponent.h             //TMyCompoent 헤더
aboutproperty.cpp          //About property Editor
aboutproperty.h             //class 정의한 헤더
aboutproperty.dfm          //폼의 정보를 저장한 파일
MyComponent_bcb6.cpp  //엔트리 소스
MyComponent_bcb6.res  //리소스 파일
MyComponent_bcb6.bpk  //패키지 파일
MyComponent_reg.cpp   //등록을 위한 register 함수가 있는 파일



이제 하려는 것은 TComponent 를 상속받아서 TMyComponent 를 만들고 여기에 About property 를 추가하는 것입니다.
TMyComponent 의 class 는 다음과 같습니다.
class PACKAGE TMyComponent : public TComponent
 {
 private:
   AnsiString __fastcall GetAbout(void);
   void __fastcall SetAbout(const AnsiString Value);
 public:
   __fastcall TMyComponent(TComponent* Owner);
 __published:
   __property AnsiString About = { read = GetAbout, write = SetAbout, stored = false};
 };

stored 는 About property 상태를 dfm 파일에 저장할 것인가를 지정하는 것입니다. 저장할 필요가 없으므로 false 입니다.
시험삼아서 stored 를 지워보시면 그 효과를 확실히 알 수 있습니다.

그럼 SetAbout, GetAbout 함수를 봅시다.
AnsiString __fastcall TMyComponent::GetAbout(void)
 {
   return VERSION;
 }

 void __fastcall TMyComponent::SetAbout(const AnsiString Value)
 {
 }

GetAbout 은 Object Inspector 의 Value 에 어떤 값이 표시되는 지를 나타내는 것입니다.
VERSION 이라는 문자열 상수를 지정합니다.
const AnsiString VERSION = "Ver 1.0";

SetAbout은 필요가 없으므로 빈칸으로 만듭니다.


그럼 Property Editor 를 구현하기 위한 class 를 살펴봅시다.
class PACKAGE TAboutProperty : public TStringProperty
 {
 public:
   void __fastcall Edit(void);
   TPropertyAttributes __fastcall GetAttributes(void);
 };

TStringProperty 를 상속받았습니다. 이것은 Object Inspector 를 통해서 직접 문자열을 입력받는 property editor입니다.
그리고 Edit , GettAttributes 함수를 오버라이딩합니다.


Edit 함수는 Component Editor 에서와 마찬가지로 더블 클릭하면 실행하는 것입니다.
void __fastcall TAboutProperty::Edit(void)
 {
    TAboutForm* AboutForm = new TAboutForm(NULL); //AboutForm 생성

    try
    {
      AboutForm->ShowModal(); //AboutForm 을 화면에 보여준다.
    }
    __finally
    {
      delete AboutForm; //AboutForm 파괴한다.
    }
 }

GetAttributes 함수는 Property Editor 의 속성을 얻는 것입니다. 대화형으로 하려면 paDialog , 읽기전용으로 하려면
paReadOnly 를 반환합니다.
TPropertyAttributes __fastcall TAboutProperty::GetAttributes(void)
 {
   return TPropertyAttributes() << paDialog << paReadOnly; //대화형 , 읽기전용 설정
 }

여기서 잠깐 델파이는 위 함수를 어떻게 표현하는지 알아봅시다.
function TAboutProperty.GetAttributes : TPropertyAttributes;
 begin
   Result := [ paDialog, paReadOnly ];
 end;

TPropertyAttributes 타입은 집합형입니다. 집합형에 두개의 원소를 추가하여 반환하는 방법을 델파이와 비교해 보세요.
델파이 예제는 많은데 빌더 예제가 부족해서 난감한 경우가 많죠.

그럼 등록에 필요한 register 함수를 알아봅시다.
사실 이 부분이 제일 난감합니다. Property Editor 를 등록하기 위한 부분입니다.
AnsiString 타입일 경우 다음과 같이 좀 복잡한 방법을 사용해야 합니다.
PPropInfo PropInfo = ::GetPropInfo(__typeinfo(TMyComponent), "About");
RegisterPropertyEditor(*(PropInfo->PropType),__classid(TMyComponent),"About", __classid(TAboutProperty));

뉴스그룹을 계속 뒤져본 결과 위의 방식이 가장 일반적인 방식인것 같습니다. property 의 type 을 알려주기 위한
부분이 제일 어렵죠. 이런 방법 저런 방법들이 있지만 모범답안은 없는것 같습니다.

델파이라면 다음과 같이 간단하게 해결됩니다.
RegisterPropertyEditor(TypeInfo(string), TMyComponent, 'About', TAboutProperty);

4개의 인수중 첫번째는 property 의 type , 두번째는 연결시키려는 컴포넌트 , 세번째는 property 의 이름 , 네번째는
property editor 입니다.

설치하면 다음과 같이 Object Inspector 에 나타납니다.