착한아이 님이 쓰신 글 :
: 델파이 폼의 시작 이벤트 순서는 대략 아래와 같습니다.
:
: OnCreate
: OnShow
: ...
: OnActivate
:
:
:
:
: 그런데 컴포넌트를 추가하다보면 이 순서가 가끔 바뀝니다.
:
: OnActivate
: OnCreate
: OnShow
: 혹은
: OnCreate
: OnActivate
: OnShow
:
:
:
: 첨부파일 예는 Frame에 CoolBar를 넣은 후,
: ComboBox를 넣고 안 넣고에 따라 Form의 이벤트 순서가 바뀜을 보여줍니다.
:
: 원인은 무엇이며 원래 순서를 유지하는 방법이 있는지 궁금합니다.
: 감사합니다.
답변:
Create, Activate, Show 이벤트는...
OnCreate -> OnShow -> OnActivate 순서로 라우팅 되는 게 정상적인 순서임에도 불구하고
첨부되어 있는 소스코드 실행시 아래와 같이 순서가 바뀌는 것은 VCL 라이브러리가 엉터리로
만들어져 있어서 그래요.
<문제점>
TComboBox는 Edit 콘트롤과 List 콘트롤이 내부적으로 결합되어 있는 Composition 구조로 SubClassing 되어 있어요.
다시 말해서... 이 컴포넌트는 EditWndProc()와 ListWndProc() 로 서브클래싱 되어 있는 복수의 윈도우 핸들을 갖고있는
Composition 구조의 컴포넌트 인데...
TCoolBar 클래스에서 Band를 Update() 할 때... Band의 Child인...
Composition 구조로 서브클래싱 되어 있는 TComboBox 로 부터 ActiveControl, FocusedControl을
setup 하는 과정이... VCL 라이브러리가 엉터리로 만들어져 있어서 conflict 가 일어나고 있는 겁니다.
VCL 라이브러리 수정하지 않고 해결 하려면...
간단하게 아래와 같이 Unit2.pas 소스에서...
TComboBox.Focused() 메소드를 오버라이드 해서 처리하면 됍니다.
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ToolWin, ComCtrls;
type
TComboBox = class(StdCtrls.TComboBox)
function Focused: Boolean; override;
end;
TFrame2 = class(TFrame)
CoolBar1: TCoolBar;
ComboBox1: TComboBox;
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
function TComboBox.Focused: Boolean;
var
FocusedWnd: HWND;
begin
Result := False;
if HandleAllocated then
begin
FocusedWnd := GetFocus;
if FocusedWnd = 0 then Exit;
Result := (FocusedWnd = FEditHandle) or (FocusedWnd = FListHandle) or (FocusedWnd = Handle);
end;
end;
end.
위와 같이 수정한 후에 실행하면...
다음과 같이 이벤트가 정상적으로 라우팅 되게 될 겁니다.
rad 10.3.1 소스코드와 컴파일한 바이너리 첨부해서 올립니다.
<해결후>
VCL 라이브러리...
엉터리로 만들어져 있는 부분들 많아요. 아마추어가 만들어 놓은 것 처럼...
IDE, 디버거도 마찬가지.