안녕하세요. 델파이 동호회원 홍진혁입니다.
제가 구사하려는 것은 다음과 같습니다.
TPanel, TButton, TBitBtn 등등 50가지 정도의 VCL중 임의의 것을 Click하여
그 Click한 것과 똑같은 것을 동적으로 생성하려면 아래와 같이 Class Reference로
하는 것이 가장 적절하더군요.
type
CRefType = class of TControl;
var
ClassRef: CRefType;
procedure ObjectClick(Sender : TObject);
begin
if Sender is TPanel then ClassRef := TPanel
else if Sender is TButton then ClassRef := TButton
{ 등등등 }
end;
위의 procedure를 각 VCL의 OnClick Event Handler에 대입하면 Click하는 Sender의 Class Type을 알수가 있습니다. 그래서 Click한 Object와 똑같은 Object를 동적으로 생성하려면
ClassRef.Create(Application);
와 같이 간단하게 구현할 수가 있습니다.
그러나, 문제는 그 Class Type (ClassRef.ClassName)을 알더라도 Sender에 따라 어떤 속성을 바꾸어 주려면 아래의 예제와 같이 일일이 Sender = Txxx 및 with(Sender)로 하여 장황하게 코딩을 해주어야만 합니다. (방법이 있는지 몰라 저의 경우는 일일이 case by case로 코딩을 하고 있습니다.) 그래서, 코딩하는 라인이 기하급수적으로 늘어납니다.
if Sender is TPanel then begin
with TPanel(Sender) do
begin
if x < 5 then begin
if y < 5 then begin
Cursor := crSizeNWSE; SC_COMMAND := SC_LEFT_TOP;
end else if y > height-5 then begin
Cursor := crSizeNESW; SC_COMMAND := SC_LEFT_BOTTOM;
end else begin
Cursor := crSizeWE; SC_COMMAND := SC_LEFT;
end;
end else if x > width-5 then begin
if y < 5 then begin
Cursor := crSizeNESW; SC_COMMAND := SC_RIGHT_TOP;
end else if y > height-5 then begin
Cursor := crSizeNWSE; SC_COMMAND := SC_RIGHT_BOTTOM;
end else begin
Cursor := crSizeWE; SC_COMMAND := SC_RIGHT;
end;
end else begin
if y < 5 then begin
Cursor := crSizeNS; SC_COMMAND := SC_TOP;
end else if y > height-5 then begin
Cursor := crSizeNS; SC_COMMAND := SC_BOTTOM;
end else begin
Cursor := crDefault; SC_COMMAND := SC_DRAGMOVE;
end;
end;
end;
TPanel(Sender).Perform(WM_SysCommand, SC_Command, 0);
end
else if Sender is TButton then begin
with TButton(Sender) do
begin
if x < 5 then begin
if y < 5 then begin
Cursor := crSizeNWSE; SC_COMMAND := SC_LEFT_TOP;
end else if y > height-5 then begin
Cursor := crSizeNESW; SC_COMMAND := SC_LEFT_BOTTOM;
end else begin
Cursor := crSizeWE; SC_COMMAND := SC_LEFT;
end;
end else if x > width-5 then begin
if y < 5 then begin
Cursor := crSizeNESW; SC_COMMAND := SC_RIGHT_TOP;
end else if y > height-5 then begin
Cursor := crSizeNWSE; SC_COMMAND := SC_RIGHT_BOTTOM;
end else begin
Cursor := crSizeWE; SC_COMMAND := SC_RIGHT;
end;
end else begin
if y < 5 then begin
Cursor := crSizeNS; SC_COMMAND := SC_TOP;
end else if y > height-5 then begin
Cursor := crSizeNS; SC_COMMAND := SC_BOTTOM;
end else begin
Cursor := crDefault; SC_COMMAND := SC_DRAGMOVE;
end;
end;
end;
TButton(Sender).Perform(WM_SysCommand, SC_Command, 0);
end
{등등등}
제 생각에는 ClassRef.Create()와 같이 Class Reference의 개념과 유사한 방법으로 위의 문제를 간단히 한번만 코딩할수 있을 것 같은데 그게 잘 안되더군요.
이런 문제를 해결하기 위해서는 어떻게 해야 하는지 알고계신 전문가가 계시면 답변 부탁드립니다.
> 안녕하세요. 델파이 동호회원 홍진혁입니다.
>
> 제가 구사하려는 것은 다음과 같습니다.
> TPanel, TButton, TBitBtn 등등 50가지 정도의 VCL중 임의의 것을 Click하여
> 그 Click한 것과 똑같은 것을 동적으로 생성하려면 아래와 같이 Class Reference로
> 하는 것이 가장 적절하더군요.
>
> type
> CRefType = class of TControl;
>
> var
> ClassRef: CRefType;
>
> procedure ObjectClick(Sender : TObject);
> begin
> if Sender is TPanel then ClassRef := TPanel
> else if Sender is TButton then ClassRef := TButton
> { 등등등 }
> end;
>
> 위의 procedure를 각 VCL의 OnClick Event Handler에 대입하면 Click하는 Sender의 Class Type을 알수가 있습니다. 그래서 Click한 Object와 똑같은 Object를 동적으로 생성하려면
> ClassRef.Create(Application);
> 와 같이 간단하게 구현할 수가 있습니다.
>
> 그러나, 문제는 그 Class Type (ClassRef.ClassName)을 알더라도 Sender에 따라 어떤 속성을 바꾸어 주려면 아래의 예제와 같이 일일이 Sender = Txxx 및 with(Sender)로 하여 장황하게 코딩을 해주어야만 합니다. (방법이 있는지 몰라 저의 경우는 일일이 case by case로 코딩을 하고 있습니다.) 그래서, 코딩하는 라인이 기하급수적으로 늘어납니다.
>
> if Sender is TPanel then begin
> with TPanel(Sender) do
> begin
> if x < 5 then begin
> if y < 5 then begin
> Cursor := crSizeNWSE; SC_COMMAND := SC_LEFT_TOP;
> end else if y > height-5 then begin
> Cursor := crSizeNESW; SC_COMMAND := SC_LEFT_BOTTOM;
> end else begin
> Cursor := crSizeWE; SC_COMMAND := SC_LEFT;
> end;
> end else if x > width-5 then begin
> if y < 5 then begin
> Cursor := crSizeNESW; SC_COMMAND := SC_RIGHT_TOP;
> end else if y > height-5 then begin
> Cursor := crSizeNWSE; SC_COMMAND := SC_RIGHT_BOTTOM;
> end else begin
> Cursor := crSizeWE; SC_COMMAND := SC_RIGHT;
> end;
> end else begin
> if y < 5 then begin
> Cursor := crSizeNS; SC_COMMAND := SC_TOP;
> end else if y > height-5 then begin
> Cursor := crSizeNS; SC_COMMAND := SC_BOTTOM;
> end else begin
> Cursor := crDefault; SC_COMMAND := SC_DRAGMOVE;
> end;
> end;
> end;
> TPanel(Sender).Perform(WM_SysCommand, SC_Command, 0);
> end
> else if Sender is TButton then begin
> with TButton(Sender) do
> begin
> if x < 5 then begin
> if y < 5 then begin
> Cursor := crSizeNWSE; SC_COMMAND := SC_LEFT_TOP;
> end else if y > height-5 then begin
> Cursor := crSizeNESW; SC_COMMAND := SC_LEFT_BOTTOM;
> end else begin
> Cursor := crSizeWE; SC_COMMAND := SC_LEFT;
> end;
> end else if x > width-5 then begin
> if y < 5 then begin
> Cursor := crSizeNESW; SC_COMMAND := SC_RIGHT_TOP;
> end else if y > height-5 then begin
> Cursor := crSizeNWSE; SC_COMMAND := SC_RIGHT_BOTTOM;
> end else begin
> Cursor := crSizeWE; SC_COMMAND := SC_RIGHT;
> end;
> end else begin
> if y < 5 then begin
> Cursor := crSizeNS; SC_COMMAND := SC_TOP;
> end else if y > height-5 then begin
> Cursor := crSizeNS; SC_COMMAND := SC_BOTTOM;
> end else begin
> Cursor := crDefault; SC_COMMAND := SC_DRAGMOVE;
> end;
> end;
> end;
> TButton(Sender).Perform(WM_SysCommand, SC_Command, 0);
> end
> {등등등}
>
> 제 생각에는 ClassRef.Create()와 같이 Class Reference의 개념과 유사한 방법으로 위의 문제를 간단히 한번만 코딩할수 있을 것 같은데 그게 잘 안되더군요.
> 이런 문제를 해결하기 위해서는 어떻게 해야 하는지 알고계신 전문가가 계시면 답변 부탁드립니다.
>
클레스 참조자의 활용이 그렇게 자유로움을 준다고 생각진 않습니다.
다만 델파이가 VCL을 다루는것을 보면 임의의 컴포넌트를 생성했을때 그 객체를
조작하기위해 RTTI를 문자열로 접근하는것을 발견할수 있습니다.
사실 델파이가 표준 VCL을 조작할때는 published 프로퍼티만이 조작됩니다.
기타 public이나 메소드등은 접근조차 하지 않습니다.
RTTI는 그 객체가 무슨타입인지 몰라도 published 프로퍼티를 접근할수 있게 합니다.
또한 프로퍼티를 문자열명으로 접근할수 있도록 해줍니다.
그와 관련된 함수는 typinfo.pas 유닛에 있습니다.