델파이 컴포넌트(Component) 2편
생성(Create)과 해제(Destroy)
솔직해 컴포넌트는 이 두가지만 잘 해주면 거의 끝난것이라고 할수 있습니다.
많은 분들이 이 두가지를 잘못해서 컴포넌트와의
싸움에서 쓴잔을 마시고 계신줄 알고 있습니다.
가령 폼위에 컴포를 올려놓기는 했는데 삭제하려면
엑세스가 바이얼레이션한다는 보기싫은 메시지를 토해놓는다던지,
델파이가 종료가 안된다던지, 혹은 아주 보기 드믈게 윈도우가 다운된다던지 하는 일의 대부분은
Create와 Destroy를 잘못해서 생기는 일입니다.
하지만 절대 어려운 일이 아닙을 미리 밝혀드립니다.
먼저 강좌에서 만든 'MyButton.pas'를 봅시다. 많이 보던 코드들이 나와 있죠?
처음 보는 함수가 하나 만들어져 있음을 볼수 있습니다.
바로 'Register'라는 함수인데 설명이 구지 필요하지는 않겠죠?
그럼 TMyButton에 Create와 Destroy를 추가해 봅시다.
public
{ Public declarations }
constructor Create( AOwner : TComponent ); override; <<=
destructor Destroy; override; <<= 우선 선언부에 위와 같이 선언을 해 주고요..
그 다음 구현부에서는
constructor TMyButton.Create( AOwner : TComponent );
begin
inherited Create(AOwner);
// 생성시에 할일...
end;
destructor TMyButton.Destroy;
begin
// 해제시에 할일...
inherited Destroy;
end;
무척 쉽죠? 이렇게 간단한데 왜 실패를 하게 될까요?
열쇠는 바로 'inherited'에 있습니다.
아빠인 TButton의 Create를 호출하는 것이지요..
우리가 만든 TMyButton의 아빠인 TButton의 Create를 보면
다음과 같이 선언되어 있습니다.
constructor Create(AOwner: TComponent); override;
'override'라고 표시가 되어 있죠?
TComponent에서부터 상속을 받아서 내려오는 녀석이지요..
TComponent의 Create는 'override'라는 표시가 보이지 않을겁니다.
대신 'virtual'이라는 지시어가 붙어있죠!!!!
다음은 TComponent의 선언부에 있는 것입니다.
constructor Create(AOwner: TComponent); virtual;
virtual과 override의 차이는 다들 아시겠죠?
둘의 차이를 모르신다면 OOP부분부터 다시 공부를 하시고
다음으로 넘어가실것을 강력히 권해드리고 싶군요..
컴포넌트의 생성은 TComponent로부터 시작한다는 말이 됩니다.
그럼 간단히 우리의 TMyButton의 족보를 살펴보기로 합시다.
TObject
|
TPersistent |
TComponent <<--------- 생성을 시작 | |
TControl | | |
TWinControl | | |
TButtonControl | | |
TButton | | |
TMyButton <<--------- 우리의 자랑스런 컴포넌트 휴우~ 생각보다 복잡하군요..
TComponent부터
컴포의 생성에 관여한다고 했는데
그럼 TComponent부터 TButton까지 Create부분을 살펴보도록 합시다.
공통점을 한번 찾아보세요.
constructor TComponent.Create(AOwner: TComponent);
begin
FComponentStyle := [csInheritable];
if AOwner <> nil then AOwner.InsertComponent(Self);
end;
컴포넌트의 시작부분입니다.
InsertComponent로 자신을 컴포넌트로서 등록을 해주는 군요..
아직까지는 눈에 보이지 않은 컴포넌트입니다.
constructor TControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWindowProc := WndProc;
FControlStyle := [csCaptureMouse, csClickEvents, csSetCaption, csDoubleClicks];
FFont := TFont.Create;
FFont.OnChange := FontChanged;
FColor := clWindow;
FVisible := True;
FEnabled := True;
FParentFont := True;
FParentColor := True;
FParentShowHint := True;
FIsControl := False;
FDragCursor := crDrag;
end;
FFont, FColor, FVisible 등등을 보니
이제부터 눈에 보이는 컴포넌트가 되는것 같군요..
WndProc을 보면 메시지도 처리를 할수가 있겠구요..
constructor TWinControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FObjectInstance := MakeObjectInstance(MainWndProc);
FBrush := TBrush.Create;
FBrush.Color := FColor;
FParentCtl3D := True;
FTabOrder := -1;
FImeMode := imDontCare;
FImeName := Screen.DefaultIme;
end;
FBrush가 보이기 시작하는 것은 보니 아마도 그림도 그릴수 있게되겠군요.
앗! FTabOrder가 있다면 드뎌 핸들을 갖는
정상적인 윈도우-컨트롤로 변신을 하는군요..
이름도 'TWinControl' 이군요 // TButtonControl.Create는 없습니다.
constructor TButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := [csSetCaption, csOpaque, csDoubleClicks];
Width := 75; Height := 25; TabStop := True;
end;
여기서는 자신의 Width, Height를 정해주는 군요..
버튼을 폼에 올려놓으면 기본적으로 크기가 정해지죠?
여기서 그걸 처리하는 군요..
차례대로 한번 살펴보셨나요?
위의 코드를 발췌한 파일과 줄번호를 써놓았으니 참고하시구요..
우리가 만든 TMyButton의 아버지들은
생성시에 위와 같이 많은 일들을 하게 됩니다.
위에서 혹시 공통점들을 발견하셨는지 모르겠네요..
각 함수의 첫머리에서 'inherited Create(AOwner);'가
있는것을 발견할수 있을 겁니다.
즉. 자신의 아버지가 해 놓은 일을 고스란히 물려받으면서
거기에 내가 할일을 덧붙인다는 말이 되겠지요
그런데 우리가 만든 컴포넌트에서 조상들의 빛나는 업적(?)을 모두 무시하고,
즉 inherited를 하지 않고 Create함수를 작성한다면 어떻게 될까요?
굳이 권해드리고 싶지는 않지만 시험삼아서 inherited를 빼먹구
컴포넌트를 만들면 어떻게 되는지를 확인해보는 것도 좋을듯합니다.
억세스가 어드레스0000에서 바이얼레이션한다는
메시지를 보실수 있을 겁니다.
제경우 시험삼아서 몇번 해보았더니 시스템이 다운되더군요.
(WinNT 4.0, IE4.01에서 테스트 했습니다.) 항상 다운되는 것은 아니니
너무 걱정은 안하셔도 될듯.. *^^*
이렇게 장황하게 설명을 드리는 것은 작은 실수가 얼마나
큰 화를 부르는 가를 보여드리기 위해서입니다.
명심하십시요!!!!
조상을 져버리고 잘되기를 바라는 것이 얼마나 어리석은 짓인가를... ^^;
여러분이 만든 컴포넌트가 만약 설치가 안되거나 삭제할때 에러가 난다면
'Create'나 'Destroy'함수를 꼭한번 확인해 보세요..
열에 아홉은 조상을 무시한 경우, 즉 inherited를 빼먹었을 경우입니다.
그럼 두 함수를 다시 한번 살펴봅시다.
----------------------------------------------------------------
constructor TMyButton.Create( AOwner : TComponent );
begin
inherited Create(AOwner); // 생성시에 할일...
end;
destructor TMyButton.Destroy;
begin
// 해제시에 할일...
inherited Destroy;
end;
----------------------------------------------------------------
조금 다른점을 발견하셨으리라 봅니다.
바로 inherited의 위치인데요..
Create의 경우 함수의 제일 위에서 inherited를 해주지요..
Destroy의 경우는 함수의 맨 끝에서 inherited를 해주고요..
함수의 실행 순서를 생각하시면 쉽게 이해가 되지요?
'Create'함수에서 inherited를 하기전에는 컴포넌트는
생성이 되지 않았다고 생각하시면 됩니다.
그러니 자신이 생성도 되지 않았는데
무슨일을 한다는 것은 말도 안되는 것이지요..
마찬가지로 Destroy에서 inherited를 하면
자신은 이미 해제된 것입니다.
자신이 이미 없어졌는데
무슨일을 한다는 것도 우수운 일이지요..
따라서 생성시에는
맨처음에 inehrited를 해제시에는 맨 끝 inehrited!!!
3편계속...
'Delphi Tip > 컴포넌트' 카테고리의 다른 글
델파이 컴포넌트(Component) 4편 (0) | 2023.07.19 |
---|---|
델파이 컴포넌트(Component) 3편 (0) | 2023.07.18 |
델파이 컴포넌트(Component) 1편 (0) | 2023.07.14 |
델파이 DSPack MP4 (0) | 2021.11.11 |
델파이 콤보박스 key 값 설정 (0) | 2021.11.10 |
댓글