안녕하세요 따랑님
잠간 짬을내세 참고하실만한 샘플을 만들었습니다.
저번 게시글에서도 말씀 드렸는데
게시물
http://delphi.borlandforum.com/impboard/impboard.dll?action=read&db=del_tip&no=304 은 삭제 해주세요.
동적 버튼 생성 / 파괴
동적 버튼 검색
동적 버튼 캡션 할당
을 포함하고요, 작성 환경은 Delphi XE3 입니다.
그럼 즐코하세요 :)
unit _fmMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TfmMain = class(TForm)
ButtonCreate: TButton;
GridPanel: TGridPanel;
ButtonDestroy: TButton;
ComboBoxButtons: TComboBox;
EditButtonCaption: TEdit;
ButtonChangeCaptionFindComponent: TButton;
ButtonChangeCaptionComponents: TButton;
procedure FormCreate(Sender: TObject);
procedure ButtonCreateClick(Sender: TObject);
procedure ComboBoxButtonsChange(Sender: TObject);
procedure ButtonChangeCaptionFindComponentClick(Sender: TObject);
procedure ButtonDestroyClick(Sender: TObject);
procedure ButtonChangeCaptionComponentsClick(Sender: TObject);
private
function NewButtonNameExists: Boolean;
procedure OnNewButtonClick(Sender: TObject);
public
end;
var
fmMain: TfmMain;
implementation
{$R *.dfm}
const
NAME_NEW_BUTTON = 'NewButton';
procedure TfmMain.ButtonChangeCaptionComponentsClick(Sender: TObject);
var
i: Integer;
LName: String;
begin
if not NewButtonNameExists then
Exit;
for i := 0 to ComponentCount - 1 do
if Components[i] is TButton then
begin
LName := Components[i].Name;
if LName.Contains(NAME_NEW_BUTTON) and LName.Equals(ComboBoxButtons.Text) then
begin
TButton(Components[i]).Caption := EditButtonCaption.Text;
Break;
end;
end;
end;
procedure TfmMain.ButtonChangeCaptionFindComponentClick(Sender: TObject);
var
LButton: TButton;
begin
if not NewButtonNameExists then
Exit;
LButton := TButton(FindComponent(ComboBoxButtons.Text));
if Assigned(LButton) then
LButton.Caption := EditButtonCaption.Text;
end;
procedure TfmMain.ButtonCreateClick(Sender: TObject);
var
LCnt, i: Integer;
LButton: TButton;
begin
LCnt := GridPanel.ColumnCollection.Count * GridPanel.RowCollection.Count;
for i := 0 to LCnt - 1 do
begin
LButton := TButton.Create(Self);
LButton.Parent := GridPanel;
LButton.Name := Format('%s%d', [NAME_NEW_BUTTON, i]);
LButton.OnClick := OnNewButtonClick;
LButton.Caption := LButton.Name;
ComboBoxButtons.Items.Add(LButton.Name);
end;
ComboBoxButtons.DropDownCount := LCnt;
ComboBoxButtons.ItemIndex := -1;
end;
procedure TfmMain.ButtonDestroyClick(Sender: TObject);
var
i: Integer;
begin
for i := ComponentCount - 1 downto 0 do
if Components[i] is TButton then
if String(TButton(Components[i]).Name).Contains(NAME_NEW_BUTTON) then
TButton(Components[i]).Free;
end;
function TfmMain.NewButtonNameExists: Boolean;
begin
Result := (ComboBoxButtons.ItemIndex > -1) and
not String(EditButtonCaption.Text).IsEmpty;
end;
procedure TfmMain.ComboBoxButtonsChange(Sender: TObject);
var
LButtonCanChange: Boolean;
begin
if ComboBoxButtons.ItemIndex = -1 then
EditButtonCaption.Text := EmptyStr
else
EditButtonCaption.Text := ComboBoxButtons.Text;
LButtonCanChange := EditButtonCaption.Text <> EmptyStr;
ButtonChangeCaptionFindComponent.Enabled := LButtonCanChange;
ButtonChangeCaptionComponents.Enabled := LButtonCanChange;
end;
procedure TfmMain.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown := True;
end;
procedure TfmMain.OnNewButtonClick(Sender: TObject);
begin
ShowMessage(TButton(Sender).Caption);
end;
end.
따랑 님이 쓰신 글 :
: 답변감사드림니다 바쁜신데
: 1.답변은 하신말씀데로 그대로 작성하였습니다.
: 2.대소문자 구분은 정확히 하고 uppercase명렬을 사용도 해보았습니다.
: 3.형 비교는 안해보았습니다.
: 해보고 결과를 말씀 드리겠습니다.
:
: 질문입니다:
: aEdit:= TEdit.Create(Self); // 이렇게 되어 있어야 합니다.
: With aEditt Do Begin
: Name:=_'aEdit_'+A_PK_ID.Text;
: Text:='축하합니다.';
: End;
: 예를 들어 a_PK_ID.Text:='13'이면
:
: 이미 생성된 Edit를 aEdit_13를 찾아서
: 이미들어있는 Text를 변경할려고 합니다.
: 축하합니다를 또 당첨됬습니다.로 변경할려고요
: 제가 할려고 하는 작성은 에러가 발생합니다.
: 부탁드립니다.
:
:
:
: 별을보라 님이 쓰신 글 :
: : 먼저 델파이는 OwnerShip 기반으로 객체의 소멸을 관리하므로 특별한 경우가 아니면 일부러 Components 를 찾아
: : 메모리를 해제할 필요가 없다는건 아실 거라 생각하겠습니다.
: :
: : 전체 소스가 없으니 점검하실 부분만 말씀드릴게요.
: :
: : 1. 버튼, 에디트, 메모, 라벨, 쉐이프, 이미지를 동적으로 만드실 때
: : TButton.Create(여기에 어떤 인자를 넘기는지요?)
: : 일반적으로 Self 또는 폼변수를 넘기고 있나요? 아니라면 당연히 님이 제시한 코드가 실행되지 않을 겁니다.
: : 예를 들어 님 코드에
: : aSend_Btn_1:= TButton.Create(Self); // 이렇게 되어 있어야 합니다.
: :
: : 2. Pos 함수는 대소문자를 구분합니다. 혹시 Name 부여시 대소문자가 정확한지 확인해 보세요.
: :
: : 3. 마지막으로 이건 직접적인 영향이 없을 수도 있지만 중요한 거라 말씀드리고 싶네요.
: : 제시한 코드는 형검사를 안하고 형변환을 수행하고 있습니다.
: : i) 꼭 이름으로 찾아서 메모리 해제를 하시려면
: : for i := ComponentCount - 1 down 0 do begin
: : if ((Components[i] is TButton) and
: : ((Pos('aSend_' ,TButton(Self.Components[i]).Name)<>0) Or
: : (Pos('aDelete' ,TButton(Self.Components[i]).Name)<>0))) Then TButton(Self.Components[i]).Free
: : Else If ((Components[i] is TEdit) and
: : (Pos('aEdit_' ,TEdit (Self.Components[i]).Name)<>0)) Then TEdit (Self.Components[i]).Free
: : ........
: : end;
: : 이렇게 하면 SCE(boolean short circuit evaluation) 에 따라 오류가 발생하지 않습니다.
: :
: : ii) 이름이 아니고 형검사만으로 해제하려면
: :
: : for i := ComponentCount - 1 down 0 do begin
: : if (Components[i] is TButton) then TButton(Components[i]).Free
: : else if (Components[i] is TEdit) then TEdit(Components[i]).Free
: : ....
: : end;
: : 이렇게 하시면 좀 보기 쉽겠죠.
: :
: : 그럼.
: :
: :
: : 따랑 님이 쓰신 글 :
: : : 답변 감사드립니다.
: : : 아래와 같이도 작성해보았는데 해제작업이 안되요
: : : 감사합니다.
: : :
: : : for i := ComponentCount - 1 down 0 do
: : : beign
: : : // Do destory Instance
: : : end;
: : : gomsun2 님이 쓰신 글 :
: : : : 안녕하세요 따랑님 :) 오늘 두번이나 뵙네요.
: : : :
: : : : 팁, 트릭 란에 올리신 질문은 삭제 해주시고요,
: : : :
: : : : 답변입니다.
: : : :
: : : : 파괴를 하는 루틴에서는 looping 할 때 역순으로 해야 합니다.
: : : : 5개의 컴포넌트를 찾아 파괴하는 시나리오를 생각해 보면
: : : :
: : : : 각각의 인덱스가 아래와 같이 있다고 가정하고,
: : : : 0, 1, 2, 3, 4
: : : :
: : : : 파괴를 위한 루핑을 시작합니다.
: : : : i 는 0 일때 1번 돌면
: : : : 0, 1, 2, 3
: : : :
: : : : i 는 1 일때 2번 돌면
: : : : 0, 1, 2
: : : :
: : : : i 는 2 일때 3번 돌면
: : : : 0, 1
: : : : 문제가 발생합니다.
: : : :
: : : : 때문에 리스트(Components)에 담긴 인스턴스를 파괴할려면
: : : :
: : : : for i := ComponentCount - 1 down 0 do
: : : : beign
: : : : // Do destory Instance
: : : : end;
: : : :
: : : : 와 같이 작업하셔야 합니다.
: : : :
: : : : 즐코하세요 :)
: : : :
: : : : 따랑 님이 쓰신 글 :
: : : : : 안녕하셔요
: : : : : 컴포넌트를 Button,Edit,Label등을 반목하여 생성하여 ㅅ해제후 또 생성하는 작업입니다
: : : : : 생성과 해제가 반복되는 작업입니다.
: : : : : 그런데 같은 컴포넌트를 찾아서 해제하는 작업에 문제가 있습니다.
: : : : : 부탁드립니다.
: : : : : 소스는 아래와 같습니다.
: : : : :
: : : : : For i:=0 to Self.ComponentCount-1 Do Begin
: : : : : If (Pos('aSend_' ,TButton(Self.Components[i]).Name)<>0) Or
: : : : : (Pos('aDelete' ,TButton(Self.Components[i]).Name)<>0) Then TButton(Self.Components[i]).Free
: : : : : Else If (Pos('aEdit_' ,TEdit (Self.Components[i]).Name)<>0) Then TEdit (Self.Components[i]).Free
: : : : : Else If (Pos('aMemo_' ,TMemo (Self.Components[i]).Name)<>0) Then TMemo (Self.Components[i]).Free
: : : : : Else If (Pos('aLabel_' ,TLabel (Self.Components[i]).Name)<>0) Then TLabel (Self.Components[i]).Free
: : : : : Else If (Pos('aShape_' ,TShape (Self.Components[i]).Name)<>0) Then TShape (Self.Components[i]).Free
: : : : : Else If (Pos('aImage_' ,Timage (Self.Components[i]).Name)<>0) Then Timage (Self.Components[i]).Free;
: : : : : End;
: : : : :