2009-06-17 39 views

Trả lời

58

Nó phụ thuộc nếu nó là một thành phần trực quan hoặc không trực quan. Nguyên tắc là như nhau, nhưng có một số cân nhắc bổ sung cho từng loại thành phần.

Đối với các thành phần không nhìn

var 
    C: TMyComponent; 
begin 
    C := TMyComponent.Create(nil); 
    try 
    C.MyProperty := MyValue; 
    //... 
    finally 
    C.Free; 
    end; 
end; 

Đối với các thành phần hình ảnh:

Về bản chất các thành phần thị giác được tạo ra trong cùng một cách như các thành phần không nhìn. Nhưng bạn phải đặt một số thuộc tính bổ sung để hiển thị chúng.

var 
    C: TMyVisualComponent; 
begin 
    C := TMyVisualComponent.Create(Self); 
    C.Left := 100; 
    C.Top := 100; 
    C.Width := 400; 
    C.Height := 300; 
    C.Visible := True; 
    C.Parent := Self; //Any container: form, panel, ... 

    C.MyProperty := MyValue, 
    //... 
end; 

Một vài giải thích cho đoạn code trên:

  • Bằng cách đặt các chủ sở hữu của các thành phần (các tham số của các nhà xây dựng) các thành phần bị phá hủy khi các hình thức sở hữu bị phá hủy.
  • Đặt thuộc tính Parent làm cho thành phần hiển thị. Nếu bạn quên nó, thành phần của bạn sẽ không được hiển thị. (Thật dễ dàng để bỏ lỡ một :))

Nếu bạn muốn nhiều thành phần bạn có thể làm tương tự như trên nhưng trong một vòng lặp:

var 
    B: TButton; 
    i: Integer; 
begin 
    for i := 0 to 9 do 
    begin 
    B := TButton.Create(Self); 
    B.Caption := Format('Button %d', [i]); 
    B.Parent := Self; 
    B.Height := 23; 
    B.Width := 100; 
    B.Left := 10; 
    B.Top := 10 + i * 25; 
    end; 
end; 

này sẽ bổ sung thêm 10 nút ở bên trái đường viền của biểu mẫu. Nếu bạn muốn sửa đổi các nút sau này, bạn có thể lưu chúng trong một danh sách. (TComponentList ist tốt nhất phù hợp, nhưng cũng hãy nhìn vào các đề xuất từ ​​các ý kiến ​​để câu trả lời này)

Làm thế nào để gán xử lý sự kiện:

Bạn cần phải tạo ra một phương pháp xử lý sự kiện và gán nó vào thuộc tính sự kiện.

procedure TForm1.MyButtonClick(Sender: TObject); 
var 
    Button: TButton; 
begin 
    Button := Sender as TButton; 
    ShowMessage(Button.Caption + ' clicked'); 
end; 

B := TButton.Create; 
//... 
B.OnClick := MyButtonClick; 
+1

Nhưng nếu tôi không chắc chắn có bao nhiêu thành phần tôi muốn tạo, ví dụ: nếu nó phụ thuộc vào quyết định của người dùng. Vậy làm thế nào tôi có thể khai báo các thành phần động? –

+0

Sự khác biệt có nên truyền nil hay một thành phần khác vì chủ sở hữu không có gì liên quan đến thành phần đang hiển thị hay không, chỉ với tuổi thọ của đối tượng. Một thành phần vô hình không được giải phóng trong cùng một phương thức có thể được tạo giống như trong đoạn thứ hai của bạn và được chủ sở hữu tự động giải phóng. – mghie

+0

s/visible/visual/g – mghie

0

Rất dễ dàng. Gọi Tạo. Ví dụ:

procedure test 
var 
    b : TButton; 
begin 
    b:=TButton.Create(nil); 
    b.visible:=false; 
end; 

Điều này tạo thành phần (TButton là một thành phần) trong thời gian chạy và đặt thuộc tính hiển thị.


Đối với nhà xây dựng: vượt qua nếu bạn muốn tự quản lý bộ nhớ. Vượt qua một con trỏ khác thành phần nếu bạn muốn có nó bị phá hủy khi các thành phần khác bị phá hủy.

+1

Cần chuyển con trỏ đến chủ sở hữu phần tử. TButton.Create (chủ sở hữu); –

+3

Mã này không biên dịch –

+0

> cần cho chủ sở hữu Không nhất thiết. TButton.Create (nil); là mã hợp lệ. nhưng bây giờ bạn cần phải tiêu diệt nó một cách rõ ràng. Tạo các thành phần trực quan với một chủ sở hữu nil đôi khi hữu ích. – Despatcher

23

Để đơn giản hóa quá trình tạo thành phần thời gian chạy, bạn có thể sử dụng GExperts.

  1. Tạo thành phần (hoặc nhiều thành phần) trực quan và đặt thuộc tính của nó.
  2. Chọn một hoặc nhiều thành phần và thực thi GExperts, Components thành Code.
  3. Dán mã được tạo vào ứng dụng của bạn.
  4. Xóa (các) thành phần khỏi trình thiết kế biểu mẫu trực quan.
(mã TButton sáng tạo được tạo ra theo cách này)

Ví dụ:

var 
    btnTest: TButton; 

btnTest := TButton.Create(Self); 
with btnTest do 
begin 
    Name := 'btnTest'; 
    Parent := Self; 
    Left := 272; 
    Top := 120; 
    Width := 161; 
    Height := 41; 
    Caption := 'Component creation test'; 
    Default := True; 
    ParentFont := False; 
    TabOrder := 0; 
end; 
+0

Mẹo hay! Đó là chính xác những gì tôi đã đề nghị. GExperts là một công cụ tuyệt vời để sử dụng với Delphi. –

+0

... hoặc bạn có thể thiết kế nó trong trình chỉnh sửa trực quan và sau đó lấy một đỉnh vào tệp .dfm. Về cơ bản, điều tương tự cũng có trong văn bản – Earlz

+0

Gracias. Tôi thích viết tất cả mọi thứ một mình (tôi biết đó có thể là phát minh lại bánh xe nhưng tôi cảm thấy có nhiều kiểm soát hơn) dù sao dường như công cụ GExpert không thay đổi trong mã thuần và âm thanh tốt. Cảm ơn một lần nữa để được tư vấn. – QMaster

1

Nhưng nếu tôi không chắc chắn biết có bao nhiêu thành phần tôi muốn tạo, ví dụ nếu nó phụ thuộc vào quyết định của người dùng. Vậy làm thế nào tôi có thể khai báo các thành phần động?

Câu trả lời đã được đề xuất - cách dễ nhất là Danh sách đối tượng (thành phần). TObjectList là đơn giản nhất để sử dụng (trong đơn vị contnrs). Danh sách rất tuyệt!

In Form1 Public 
    MyList: TObjectList; 
    procedure AnyButtonClick(Sender: TObject); 

// Bạn có thể tinh vi hơn và khai báo // TNotifyevents và chỉ định chúng nhưng hãy để đơn giản :) . . .

procedure Tform1.AnyButtonClick(Sender: TObject); 
begin 
    If Sender is TButton then 
    begin 
    Case Tbutton(Sender).Tag of 
    . 
    . 
    . 
// Or You can use the index in the list or some other property 
// you have to decide what to do  
// Or similar :) 
    end; 
end; 

procedure TForm1.BtnAddComponent(Sender: TObJect) 
var 
    AButton: TButton; 
begin 
    AButton := TButton.Create(self); 
    Abutton. Parent := [Self], [Panel1] [AnOther Visual Control]; 
    AButton.OnClick := AnyButtonClick; 
// Set Height and width and caption ect. 
    . 
    . 
    . 
    AButton.Tag := MyList.Add(AButton); 
end; 

Danh sách đối tượng có thể chứa bất kỳ đối tượng nào - tốt hơn để có danh sách liên quan nếu bạn muốn nhiều điều khiển động trên các bảng tương tự chẳng hạn.

Lưu ý: giống như những người nhận xét khác, tôi có thể đã đơn giản hóa quá mức cho ngắn gọn nhưng tôi hy vọng bạn định vị ý tưởng đó. Bạn cần một cơ chế để quản lý các đối tượng khi chúng được tạo ra và danh sách là tuyệt vời cho công cụ này.

0

Một số thành phần ghi đè phương thức 'Đã tải'. Phương thức này sẽ không được gọi tự động nếu bạn tạo một cá thể khi chạy. Nó sẽ được gọi bởi Delphi khi tải từ tệp biểu mẫu (DFM) hoàn tất.

Nếu phương pháp chứa mã khởi tạo, ứng dụng của bạn có thể hiển thị hành vi không mong muốn khi được tạo khi chạy. Trong trường hợp này, hãy kiểm tra xem nhà văn thành phần đã sử dụng phương pháp này chưa.

0

Nếu bạn lồng điều khiển thắng trong Hộp nhóm/Điều khiển trang/v.v ..., tôi nghĩ có lợi khi có hộp nhóm chính cũng là chủ sở hữu. Tôi đã nhận thấy một sự sụt giảm mạnh trong thời gian đóng cửa sổ khi làm điều này, trái với việc chủ sở hữu luôn là hình thức chính.

1

Trong một nghiên cứu về "tạo biểu mẫu delphi sử dụng mẫu dựa trên xml", tôi tìm thấy điều gì đó hữu ích chỉ ra RTTI và sử dụng các công cụ mở api (ToolsApi.pas tôi nghĩ). Có một cái nhìn tại các giao diện trong đơn vị.

4

Tôi chỉ muốn thêm điều đó khi tự động thêm điều khiển ... làm ý tưởng tốt để thêm chúng vào danh sách đối tượng (TObjectList) như được đề xuất trong < 1> bởi @Despatcher.

procedure Tform1.AnyButtonClick(Sender: TObject); 
begin 
    If Sender is TButton then 
    begin 
    Case Tbutton(Sender).Tag of 
    . 
    . 
    . 
// Or You can use the index in the list or some other property 
// you have to decide what to do  
// Or similar :) 
    end; 
end; 

procedure TForm1.BtnAddComponent(Sender: TObJect) 
var 
    AButton: TButton; 
begin 
    AButton := TButton.Create(self); 
    Abutton. Parent := [Self], [Panel1] [AnOther Visual Control]; 
    AButton.OnClick := AnyButtonClick; 
// Set Height and width and caption ect. 
    . 
    . 
    . 
    AButton.Tag := MyList.Add(AButton); 
end; 

Bạn cần thêm đơn vị 'Contnrs' vào danh sách Sử dụng. I.e System.Contnrs.pas Vùng chứa Đơn vị cơ sở Và bạn có thể có nhiều danh sách đối tượng. Tôi khuyên bạn nên sử dụng TObjectList cho từng loại điều khiển mà bạn sử dụng ví dụ:

Interface 
Uses Contnrs; 
Type 
TMyForm = class(TForm) 
private 
    { Private declarations } 
public 
    { Public declarations } 
end; 
Var 
    MyForm: TMyForm; 
    checkBoxCntrlsList: TObjectList; //a list for the checkBoxes I will createin a TPanel 
    comboboxCntrlsList: TObjectList; //a list of comboBoxes that I will create in some Form Container 

điều này cho phép bạn dễ dàng thao tác/quản lý từng điều khiển vì bạn sẽ biết loại điều khiển nào, ví dụ:

Var comboBox: TComboBox; 
I: Integer; 

begin 
For I = 0 to comboboxCntrlsList.Count -1 do // or however you like to identify the control you are accessing such as using the tag property as @Despatcher said 
    Begin 
    comboBox := comboboxCntrlsList.Items[I] as TComboBox; 
    ...... your code here 
    End; 
end; 

này cho phép bạn sau đó sử dụng các phương pháp và thuộc tính của điều khiển mà Đừng quên để tạo ra các TObjectLists, có lẽ trong các hình thức tạo sự kiện ...

checkBoxCntrlsList := TObjectList.Create; 
comboboxCntrlsList := TObjectList.Create; 
-1

Đây là ví dụ cách mô phỏng thẻ nút trên Evernote

unit Unit7; 

interface 

uses 
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,Vcl.Graphics, 
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, CHButton, Vcl.ExtCtrls, RzPanel, CHPanel, RzCommon,RzBmpBtn, Vcl.StdCtrls; 

type 
    // This is panel Button 
    TButtonClose = class (TRzPanel) 
    CloseButton : TRzBmpButton; 
    procedure CloseButtonClick(Sender: TObject); 
    procedure CloseButtonMouseEnter(Sender: TObject); 
    procedure MouseDown(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
    procedure MouseUp(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
end; 

TForm7 = class(TForm) 
    CHButton1: TCHButton; 
    RzPanel1: TRzPanel; 
    RzBmpButton1: TRzBmpButton; 
    procedure CHButton1Click(Sender: TObject); 
    procedure RzBmpButton1Click(Sender: TObject); 
    procedure RzPanel1MouseDown(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
    procedure RzPanel1MouseUp(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
    procedure RzPanel1MouseEnter(Sender: TObject); 
    procedure RzBmpButton1MouseEnter(Sender: TObject); 
    procedure FormMouseEnter(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
private 
    { Private declarations } 
public 
    { Public declarations } 
end; 

var 
    Form7: TForm7; 
    MyCloseButton : TButtonClose; 

implementation 

{$R *.dfm} 

// constructor for on the fly component created 
constructor TButtonClose.Create(AOwner: TComponent); 
begin 
    inherited Create(AOwner); 

    // Set Events for the component 
    Self.OnMouseEnter := Self.CloseButtonMouseEnter; 
    Self.OnMouseDown := Self.MouseDown; 
    Self.OnMouseUp := Self.MouseUp; 
    Self.Height := 25; 

    // Close button on top panel Button 
    // Inherited from Raize Bitmap Button 
    CloseButton := TRzBmpButton.Create(self); 
    // Set On Click Event for Close Button 
    CloseButton.OnClick := Self.CloseButtonClick; 
    // Place Close Button on Panel Button 
    CloseButton.Parent := self; 
    CloseButton.Left := 10; 
    CloseButton.Top := 5; 
    CloseButton.Visible := False; 
    // Setting the image for the button 
    CloseButton.Bitmaps.Up.LoadFromFile(ExtractFilePath(Application.ExeName)+'\close.bmp'); 
end; 

procedure TButtonClose.CloseButtonClick(Sender: TObject); 
begin 
    // Free the parent (Panel Button) 
    TControl(Sender).Parent.Free; 
end; 

procedure TButtonClose.CloseButtonMouseEnter(Sender: TObject); 
begin 
    // Show the Close button 
    CloseButton.Visible := True; 
end; 

procedure TButtonClose.MouseDown(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
begin 
    // Emulate Button down state, since it is panel 
    TRzPanel(Sender).BorderOuter := fsLowered; 
end; 

procedure TButtonClose.MouseUp(Sender: TObject; Button: TMouseButton; 
Shift: TShiftState; X, Y: Integer); 
begin 
    // Emulate Button up state, since it is panel 
    TRzPanel(Sender).BorderOuter := fsRaised; 
end; 

destructor TButtonClose.Destroy; 
begin 
    inherited Destroy; 
end; 

procedure TForm7.FormCreate(Sender: TObject); 
begin 
    // Create Panel Button on the fly 
    MyCloseButton := TButtonClose.Create(self); 
    MyCloseButton.Caption := 'My Button'; 
    MyCloseButton.Left := 10; 
    MyCloseButton.Top := 10; 
    // Don't forget to place component on the form 
    MyCloseButton.Parent := self; 
end; 

procedure TForm7.FormMouseEnter(Sender: TObject); 
begin 
    if Assigned(RzBmpButton1) then 
     RzBmpButton1.Visible := False; 

    // Hide when mouse leave the button 
    // Check first if myCloseButton Assigned or not before set visible property 
    if Assigned(MyCloseButton.CloseButton) then 
     MyCloseButton.CloseButton.Visible := False; 
end; 

procedure TForm7.RzBmpButton1Click(Sender: TObject); 
begin 
    TControl(Sender).Parent.Free; 
end; 

procedure TForm7.RzBmpButton1MouseEnter(Sender: TObject); 
begin 
    RzBmpButton1.Visible := True; 
end; 

procedure TForm7.RzPanel1MouseDown(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
begin 
    TRzPanel(Sender).BorderOuter := fsLowered; 
end; 

procedure TForm7.RzPanel1MouseEnter(Sender: TObject); 
begin 
    RzBmpButton1.Visible := True; 
end; 

procedure TForm7.RzPanel1MouseUp(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
begin 
    TRzPanel(Sender).BorderOuter := fsRaised; 
end; 

procedure TForm7.CHButton1Click(Sender: TObject); 
begin 
    FreeAndNil(Sender); 
end; 

end. 
Các vấn đề liên quan