본문 바로가기
Delphi Tip/유닛

메인폼과 Application 전역객체

by MonoSoft 2024. 4. 7.
728x90
반응형

메인폼과 Application 전역객체

 

728x90

 

 

 

델파이에서 메인폼은 일반폼과는 상당히 다르게 동작한다.

 

간혹 이를 잘못 이해해서 오류를 내는 경우가 있다.

지난번 예제에서 나도 이런 차이를 간과하여 실수를 저질렀는데,

사실 이런 에러는 VCL의 별별 기능을 파헤쳐서 응용하는 고수들일 수록 많이 부닥칠 수 있다.

 

그런 예를 들어보자.

다음은 첨부한 예제의 폼의 메인 폼 소스이다.

 

// MainFm.pas 메인폼 소스 {중략}

 

var MainFrm: TMainFrm;

 

// 전역 폼 변수

 

implementation

 

{$R *.dfm}

 

uses SubFm;

 

procedure TMainFrm.FormCreate(Sender: TObject);

begin

if assigned(Application.MainForm) then

ShowMessage(Application.MainForm.Caption)

else

ShowMessage('not assigned');

end;

 

procedure TMainFrm.FormDestroy(Sender: TObject);

begin

ShowMessage('Main Form is Destroyed');

end;

 

procedure TMainFrm.Button1Click(Sender: TObject);

begin

TSubFrm.Create(Self).Show;

end;

 

procedure TSubFrm.FormDestroy(Sender: TObject);

begin

ShowMessage('SubFrm is Destroyed');

end;

 

procedure TSubFrm.FormClose(Sender: TObject; var Action: TCloseAction);

begin

Action := caFree;

end;

 

다음은 메인폼에서 사용하는 작업 폼 소스의 내용이다.

 

// SubFm.pas 작업폼 소스

 

{중략}

 

procedure TSubFrm.FormDestroy(Sender: TObject);

begin

ShowMessage('SubFrm is Destroyed');

end;

 

procedure TSubFrm.FormClose(Sender: TObject; var Action: TCloseAction);

begin

Action := caFree;

end;

 

첫번째 문제로, 예제를 실행해보면 알수 있지만,

먼저 Application 객체의 MainForm 속성값은

메인폼의 OnCreate 이벤트 내에서는 NIL인 상태라는 것이다.

 

다시 말해서 Main폼이 완전히 생성되기 전까지는

Application.MainForm 속성을 참조하면 안된다는 것이다.

 

나는 전역 폼 변수를 사용하지 않기 때문에,

메인폼을 참조할 때 Application.MainForm으로 주로 참조한다.

 

그런데, 이 속성이 메인폼의 OnCreate 이벤트에서는

참조해서는 안된다는 사실을 깨닫고, 메인폼에 의존하는

싱글턴 패턴 클래스 상당수를 어떻게 고쳐야 하는가 딜레마에 빠져 있다.

 

두번째 문제로, 이 예제를 실행한 뒤 즉각 프로그램을 종료하면,

메인폼의 OnDestroy 이벤트에 들어있는 ShowMessage가 제대로 동작하지 않는다는 것이다.

 

개발환경에서 브레이크 포인트를 ShowMessage에 걸어두면,

브레이크 포인터는 걸리지만, 제대로 실행은 되지 않는다.

 

이는 개발환경 외부에서 실행하면 참으로 분명해 질 것이다.

원칙적으로 친다면, 메인폼을 종료할 때, "Main form is Destroyed"라는

메시지 박스가 표시되어야 하지만, 표시되지 않는다.

 

이는 ShowMessage가 Forms 유닛과 밀접하게 관련이 있기 때문에,

Application 객체의 상태와 아주 관계가 깊기 때문이다.

 

즉 ShowMessage는 Application 객체가 온전할때만 동작하는데,

Application이 이미 파괴된 상태, 즉 메인폼이 파괴된 상태에서는

ShowMessage가 정상 동작하지 않는다는 것이다.

 

이에 대한 증거로, 메인폼에 있는 버튼을 클릭하여

작업폼을 화면에 나타나게 한 후, 작업폼을 종료해보라.

작업폼의 OnDestroy 이벤트에 있는 ShowMessage는 정상 동작할 것이다.

 

메인폼과 작업폼이 동시에 표시 있는 상태에서 메인폼을 종료 해보라.

VCL의 자동 파괴 메커니즘 때문에 작업폼과 메인폼 모두 파괴될 것이지만,

OnDestroy에 있는 어느 ShowMessage도 제대로 동작하지 않음을 볼 수 있을 것이다.

 

결론인즉, Application 객체의 상태에 의존하거나

Forms 유닛에 의존하는 클래스나 메서드를,

폼의 OnDestroy에서 사용할 때 주의가 필요하다는 것이다.

 

최근 나의 경험에 의하면, 이런 에러를 피하려면,

메인폼이 종료되기 전에 모든 작업폼을 닫고 파괴하는 코드를

먼저 실행토록 하고, 메인폼의 OnDestroy 이벤트에서

Application 객체에 의존하는 부분의 코드를 다음과 같이 처리하는 것이다.

 

if Application.Active then

// Application이 아직 유효한 상태의 코드

else

// Application이 아직 유효하지 않은 상태의 코드

 

728x90
반응형

댓글