|
최상천 님이 쓰신 글 :
: Timer컴포넌트를 만들었는데요.
:
: TTimer컴포넌트를 보면 OnTimer 이벤트 핸들러가 있죠.
: 저두 내가만든 타이머 컴포넌트에 OnTimer 이벤트 핸들러를 만들고 싶거든요......
:
: 이벤트 핸들러를 만들려면 내가만든 컴포넌트에 이벤트를 생성해 주어야 하잖아요.
: 그 방법을 잘 모르겠습니다.
:
: 아시는분 있으시면 갈켜주세요.
: bye.
임펠리테리입니다.
이벤트를 만들려면, 가장 먼저 그 이벤트의 핸들러가 리턴할 파라미터의 리스트를 결정해야 합니다. 예를 들어 OnMouseDown 이벤트에는 마우스의 어떤 버튼인지를 나타내는 Button, 시프트나 컨트롤키 등의 상태를 알려주는 Shift, 그리고 x, y 위치 파라미터가 있지요? 이와 같이, 해당 핸들러에서 필요할 것같은 정보를 넘겨주어야 하는데, 어떤어떤 정보를 넘겨줄까를 결정해야 합니다.
결정되었다면 그 인자리스트로 이벤트의 형(type)을 선언해야 합니다. 가장 흔히 사용하는 이벤트형인 TNotifyEvent 형의 경우 classes.hpp 헤더파일에 다음과 같이 선언되어 있습니다.
typedef void __fastcall (__closure *TNotifyEvent)(System::TObject* Sender);
보시다시피 이 TNotifyEvent 형의 경우 단하나의 인자인 Sender만을 가지고 있습니다. 사실 이 Sender 인자는 그 이벤트 자체에 대한 정보를 넘겨주지는 않지만, 이벤트가 발생한 컴퍼넌트로부터 추가적인 정보가 필요할 때 꼭 필요한 경우가 있으므로 모든 이벤트에 기본적으로 반드시 포함되어 있어야 한다고 생각하는 것이 좋습니다.
만약 지금 만드려고 하는 이벤트에 Sender 외에 다른 인자가 필요없다면 새로운 이벤트 형을 만드는 대신 그냥 일반적으로 사용되는 TNotifyEvent로 선언하면 됩니다. TNotifyEvent가 아니더라도 만들려는 이벤트형과 동일한 형이 이미 있다면 그걸 그대로 사용하시면 됩니다.
선언하는 방법은 대충 위의 TNotifyEvent 형과 비슷하게 하면 됩니다.
그다음으로 할 작업은 일반적인 프로퍼티를 선언하는 방법과 거의 동일합니다. 사실 이벤트도 프로퍼티니까요. 예를 들어, 다음과 같이 TMyTimerEvent라는 이벤트형을 선언할 수 있습니다.
typedef void __fastcall (__closure *TMyTimerEvent)(System::TObject* Sender, int Second);
컴퍼넌트 클래스의 private 섹션에 다음과 같은 선언을 추가합니다.
TMyTimerEvent FOnMyTimer;
그리고 __published 섹션에는 다음과 같은 선언을 추가하구요.
__property TMyTimerEvent OnMyTimer = {read=FOnMyTimer, write=FOnMyTimer};
일반적인 이벤트를 선언하는 방법과 거의 똑같죠?
그리고 남은 일은 단 하나, 내 컴퍼넌트의 코드 중 실제로 이벤트가 발생해야 할 부분에서 다음과 같은 코드를 추가하면 됩니다.
if(FOnMyTimer)
FOnMyTimer(this, Second);
이제 완벽하게 동작하죠.
이제 잠깐 이벤트가 동작하는 방법을 생각해봅시다.
이벤트란 사실상 함수의 포인터입니다. 그리고 핸들러가 연결되지 않았을 경우에는 null값을 가지게 되므로 위의 마지막에서 추가한
if(FOnMyTimer)
FOnMyTimer(this, Second);
이 코드에서는 그냥 아무 일도 하지 않고 지나가게 됩니다. 만약 핸들러가 연결되어 있을 경우라면 this, Second 인자를 그 핸들러에 넘겨주면서 핸들러를 실행하게 되겠지요?
VCL을 설계한 볼랜드의 엔지니어들이 이벤트를 프로퍼티로 만들어놓은 이유는 디자인타임에 이벤트에 핸들러를 연결해줄 수 있게 하기 위해서입니다. 이점을 제외하면 이벤트란 사실 동적으로 사용하는 함수의 포인터에 지나지 않죠.
그럼 참고하시길...
|