全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4095
推到 Plurk!
推到 Facebook!

假設在panel1上動態產生3個button,這時如可取得某個button的caption值?

答題得分者是:pedro
mitchellhu
一般會員


發表:23
回覆:53
積分:15
註冊:2007-06-12

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-08-09 15:10:02 IP:59.125.xxx.xxx 訂閱
假設在panel1上動態產生3個button,這時如可取得某個button的caption值?
我曾試著先用panel1.Controlcount 取得目前panel1上已有幾個元件(因為panel1上的元件只有button,所以直接計算元件數)。若目前動態產生了3個button(應該是panel1.contorls[0],panel1.contorls[1],panel1.contorls[2],分別代表button1,button2,button3)。接著我又設定一個string變數BName想來取得第一個Button的Caption.
在設件期部份code如下:
var
Bname : string;

begin
Banme := panel1.Controls[0].caption;
end;

這段code在設計期ok,但編譯時報錯[DCC Error] Unit1.pas(59): E2362 Cannot access protected symbol TControl.Caption
按f1查hlep, Caption真的是TContol的一項protected porperty。
因為pane1上的button都是動態產生的,設計期無得知確實的button數量,所以只能用panel1來間接取得這些button的訊息,但從錯訊息看來好像無法不去處理TControl的porteced member的問題,請教前輩們這當如何處理,才不會違反這個原則?
另要讓其它元件的Caption設定成第一個buttn的Caption,該如何處理?
我原本直覺想法是
panel2.Control[0].caption := panel1.Controls[0].caption
看起是完全不可能了,請問如何解決呢?


編輯記錄
mitchellhu 重新編輯於 2007-08-09 15:13:23, 註解 無‧
mitchellhu 重新編輯於 2007-08-09 15:16:12, 註解 無‧
pedro
尊榮會員


發表:152
回覆:1187
積分:892
註冊:2002-06-12

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-08-09 15:23:50 IP:60.248.xxx.xxx 未訂閱
善用IS及AS,即可做到
for i:=0 to panel.componentcount-1 do
if panel.components[i] is TButton then
begin
caption:=(panel.components[i] as TButton).Caption;
end
Coffee
版主


發表:31
回覆:878
積分:561
註冊:2006-11-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-08-09 15:28:06 IP:220.130.xxx.xxx 訂閱
騙它就好了..:P
Type TZControl=class(TControl);//繼承它,就開放
//反正那些Button也是繼承來的
然後typecast TZControl就可以得到caption
------
不論是否我發的文,在能力範圍皆很樂意為大家回答問題。
為了補我的能力不足之處,以及讓答案可以被重複的使用,希望大家能儘量以公開的方式問問題。
在引述到我的文時自然會儘量替各位想辦法,謝謝大家!
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-08-09 15:44:17 IP:61.222.xxx.xxx 訂閱
uses Typinfo;


begin
Showmessage(GetStrProp(Controls[0],'Caption'))
end;
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-08-09 20:05:15 IP:210.66.xxx.xxx 訂閱
你只要自己Keep TButton Array 就可以直接存取它.

<textarea class="delphi" rows="10" cols="60" name="code"> unit TestMain; interface uses Windows, Forms, Controls, StdCtrls, Classes, Dialogs, ExtCtrls; type TButtons = array of TButton; TForm1 = class(TForm) Panel1: TPanel; CreateBtns: TButton; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure CreateBtnsClick(Sender: TObject); procedure Panel1Resize(Sender: TObject); private Buttons: TButtons; procedure DO_BUTTON_CLICK(Sender: TObject); function GET_BTN_BOUNDSRECT(Index: Integer): TRect; public function CreateButtons(var A: TButtons; Count: Integer): Boolean; procedure DestroyButtons(var A: TButtons); end; var Form1: TForm1; implementation {$R *.dfm} uses SysUtils, Math; { TForm1 } function TForm1.CreateButtons(var A: TButtons; Count: Integer): Boolean; var I: Integer; begin DestroyButtons(A); SetLength(A, Count); for I := 0 to Count-1 do begin A[I] := TButton.Create(nil); with A[I] do begin A[I].Tag := I; A[I].Caption := 'Btn' IntToStr(I); A[I].OnClick := DO_BUTTON_CLICK; A[I].Parent := Panel1; with GET_BTN_BOUNDSRECT(I) do A[I].SetBounds(Left, Top, Right, Bottom); A[I].Visible := True; end; end; Result := Length(A) = Count; end; procedure TForm1.DestroyButtons(var A: TButtons); var I: Integer; begin if A <> nil then begin for I := 0 to Length(A)-1 do if A[I] <> nil then FreeAndNil(A[I]); A := nil; end; end; procedure TForm1.DO_BUTTON_CLICK(Sender: TObject); begin if Sender is TButton then ShowMessage(TButton(Sender).Caption); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin DestroyButtons(Buttons); end; procedure TForm1.CreateBtnsClick(Sender: TObject); begin if CreateButtons(Buttons, 100) then Panel1Resize(Panel1); CreateBtns.Enabled := False; end; function TForm1.GET_BTN_BOUNDSRECT(Index: Integer): TRect; const BW = 70; BH = 20; var CC, C, R: Integer; begin CC := Max(1,Panel1.ClientWidth div BW); C := Index mod CC; R := Index div CC; Result := Rect(C*BW 5,R*BH 5,BW,BH); end; procedure TForm1.Panel1Resize(Sender: TObject); var I: Integer; begin CreateBtns.Left := ClientWidth - CreateBtns.Width - 10; Panel1.Width := ClientWidth - CreateBtns.Width - 20; if Buttons <> nil then for I := 0 to Length(Buttons)-1 do with GET_BTN_BOUNDSRECT(I) do Buttons[I].SetBounds(Left, Top, Right, Bottom); end; end. </textarea>
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-08-10 15:02:38 IP:61.64.xxx.xxx 訂閱

pedro756901 的方法,可以適用絕大部分的狀況,也不易有 bug

===================引 用 mitchellhu 文 章===================
假設在panel1上動態產生3個button,這時如可取得某個button的caption值?
我曾試著先用panel1.Controlcount 取得目前panel1上已有幾個元件(因為panel1上的元件只有button,所以直接計算元件數)。若目前動態產生了3個button(應該是panel1.contorls[0],panel1.contorls[1],panel1.contorls[2],分別代表button1,button2,button3)。接著我又設定一個string變數BName想來取得第一個Button的Caption.
在設件期部份code如下:
var
Bname : string;

begin
Banme := panel1.Controls[0].caption;
end;

這段code在設計期ok,但編譯時報錯[DCC Error] Unit1.pas(59): E2362 Cannot access protected symbol TControl.Caption
按f1查hlep, Caption真的是TContol的一項protected porperty。
因為pane1上的button都是動態產生的,設計期無得知確實的button數量,所以只能用panel1來間接取得這些button的訊息,但從錯訊息看來好像無法不去處理TControl的porteced member的問題,請教前輩們這當如何處理,才不會違反這個原則?
另要讓其它元件的Caption設定成第一個buttn的Caption,該如何處理?
我原本直覺想法是
panel2.Control[0].caption := panel1.Controls[0].caption
看起是完全不可能了,請問如何解決呢?


mitchellhu
一般會員


發表:23
回覆:53
積分:15
註冊:2007-06-12

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-08-13 11:25:32 IP:59.125.xxx.xxx 訂閱
Jow 大:
您所附的程式碼看起來考慮很完整。但我能力有限,看不太懂。
我也將你的code實作後,產生一個錯誤[DCC Error] TestMain.pas(50): E2003 Undeclared identifier: 'forbidden'
請問這是為什麼?
另一個問題想請教,因為元件是動態產生的,若使用者又再次按下CreateBtns,則一定會產生問題,因不應再產生第二次相同的Buttons。
我曾試在動態產生buttons前,檢查panel生是否有button存在,若存在則free button,但遇到了一個問題,已free的button,的name仍會存在,系統無法產生同name的button,請問free後之元件,是仍然存在記憶體中嗎?後來我用destory也是同樣的情況?請問該如何處理?
謝謝你!
編輯記錄
mitchellhu 重新編輯於 2007-08-13 11:51:19, 註解 無‧
danny
版主


發表:100
回覆:522
積分:595
註冊:2002-03-11

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-08-13 11:54:03 IP:203.79.xxx.xxx 訂閱
那是使用 Delphi RTTI 的方式取得, 但是缺點就是不保證每一個版本的 Delphi RTTI 都一樣
你可以使用 pedro756901 的方式, 只要改 TButton 部份就可以適用其他元件, pedro756901 的方式也可以寫成如下
for i:=0 to Panel.ComponentCount-1 do
if Panel.Components[i] is TButton then
begin
TButton(Panel.Components[i]).Caption := '123';
end

另外以上方式的順序是依元件的 TabOrder (就是你放上元件的順序), 不過 TabOrder 可以隨你高興改順序
還有 FindComponent 也可以依你指定的元件名稱, 找到你的元件
TButton(FindComponent('Button1')).Caption := '123';

===================引 用 mitchellhu 文 章===================
Jow?大:
您所附的程式碼看起來考慮很完整。但我能力有限,看不太懂。
我也將你的code實作後,產生一個錯誤[DCC Error] TestMain.pas(50): E2003 Undeclared identifier: 'forbidden'
請問這是為什麼?
另一個問題想請教,因為元件是動態產生的,若使用者又再次按下CreateBtns,則一定會產生問題,因不應再產生第二次相同的Buttons。
我曾試先寫了一段在動態產生buttons前,檢查panel生是否有button存在,若存在則free button,但遇到了一個問題,已free的button,的name仍會存在,系統無法產生同name的button,請問free後之元件,是仍然存在記憶體中嗎?後來我用destory也是同樣的情況?請問該如何處理?
謝謝你!
------
將問題盡快結案也是一種禮貌!
mitchellhu
一般會員


發表:23
回覆:53
積分:15
註冊:2007-06-12

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-08-13 14:23:50 IP:59.125.xxx.xxx 訂閱
danny版主及各位回復我的各位大老,真的很感謝您們。 基本上我是新手,所以對於問題的描述真的能力不足。我初始想像動態產生Button這件事是不會太困難的,但當我真實實作時卻遇到不少問題。我覺得有必要把我的真正問題講清楚一下。 嗯故事是這樣的: 我的需求是有2個panel(panel1,panel2),在panel1是作為各項功能button的container. panel上的button是動態產生的(主要的原因buttn的數量會因為使用者需求而改變),button的caption也是動態定義的。而panel2上的button 也是根據panel1上的button動態的對應ColorButton. Colorbun.caption也是對應panel1.button.caption。 本來我的認知是cpation值的取得和傳遞是主要的問題,所以才提出了本項問題。哈哈,結果連剛開始的動態產生panel1就過不了關了。真是有愧於各位的回復。 目前我程式已可在panel上動態生成5個button了。code如下: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, ColorButton ; type TForm1 = class(TForm) Button1: TButton; Panel1: TPanel; Edit1: TEdit; Panel2: TPanel; ColorButton1: TColorButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var ButtonArray:array[0..4] of TButton; ColorBtnArray:array[0..4] of TColorButton; CaptionArray:array[0..4] of String; i,j:integer; begin //訂義新增panel1 上新增button的caption CaptionArray[0] := '作業一'; CaptionArray[1] := '作業二'; CaptionArray[2] := '作業三'; CaptionArray[3] := '作業四'; CaptionArray[4] := '作業五'; for i := 0 to 4 do begin //產生panel1的button ButtonArray[i] := TButton.Create(Self); j := Round(((panel1.Width -20)-(75*5))/4); Edit1.Text := IntToStr(ButtonArray[i].Width); ButtonArray[i].Name := 'fmPan1Btn' IntToStr(i); ButtonArray[i].Caption := CaptionArray[i]; ButtonArray[i].Visible := true; ButtonArray[i].Top:= Round(panel1.Height *0.5) - Round(ButtonArray[i].Height * 0.5); ButtonArray[i].Left := 10 ((ButtonArray[i].Width j) * i); ButtonArray[i].parent := panel1; //產生panle2的ColorButon ColorBtnArray[i] := TColorButton; end; end; 所以我的問題就比較單純了:當使用者已按下Button1在panel1上產生5個button後,使用再按Button1就會產生問題,因為重複產生了。我試過在產生pnael上的button前,先檢查是否有button存在,若有則button.free。但無論是free或destory後,再按Butoon時仍有原有button.name重複問題。請問應如何解決? PS:danny版主,我之會想學習自已處理原件,係拜讀您的大作Delphi 元件設計初步(一)後,才開始產生的。您所寫出的文件真的可以引領delphi初學者,真的很感激您。
系統時間:2024-04-28 15:25:15
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!