2009-06-17 4 views

ответ

58

Это зависит от того, является ли это визуальным или не визуальным компонентом. Принцип тот же, но есть некоторые дополнительные соображения для каждого вида компонента.

Для невизуальных компонентов

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

Для визуальных компонентов:

В сущности визуальные компоненты созданы в том же образом, как и не-визуальных компонентов. Но вы должны установить некоторые дополнительные свойства, чтобы сделать их видимыми.

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; 

Несколько объяснений кода выше:

  • путем установки владельца компонента (параметр конструктора) компонент разрушается, когда форма владеющее разрушается.
  • Установка свойства Parent делает компонент видимым. Если вы забудете, ваш компонент не будет отображаться. (Это легко пропустить что один :))

Если вы хотите много компонентов вы можете сделать то же самое, что и выше, но в цикле:

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; 

Это добавит 10 кнопок слева границы формы. Если вы хотите изменить кнопки позже, вы можете сохранить их в списке. (TComponentList IST лучше всего подходит, но и взглянуть на предложения, от комментариев к этому ответу)

Как назначить обработчики событий:

Вы должны создать метод обработчика событий и назначить его на свойство события.

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

Но если я не знаю, сколько компонентов я хочу создать, например. если это зависит от решения пользователя. Итак, как я могу объявить компоненты динамически? –

+0

Различие в том, следует ли передавать ниль или другой компонент в качестве владельца, не имеет ничего общего с видимым компонентом или только с временем жизни объекта. Невидимый компонент, который не освобождается в том же методе, может быть создан так же, как и во втором фрагменте, и автоматически освобождается владельцем. – mghie

+0

s/visible/visual/g – mghie

0

Очень легко. Вызовите Создать. Пример:

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

Это создает компонент (TButton является компонентом) во время выполнения и отображает свойство.


Для конструктора: передайте nil, если вы хотите самостоятельно управлять памятью. Передайте указатель другому компоненту, если вы хотите его уничтожить, когда другой компонент будет уничтожен.

+1

Необходимо передать указатель владельцу элемента. TButton.Create (владелец); –

+3

Этот код не компилируется –

+0

> необходимо владельцу Не обязательно. TButton.Create (ноль); действительный код. но теперь вам нужно явно уничтожить его. Создание визуальных компонентов с владельцем nil иногда полезно. – Despatcher

23

Чтобы упростить процесс создания компонента времени выполнения, вы можете использовать GExperts.

  1. Визуально создайте компонент (или несколько компонентов) и задайте его свойства.
  2. Выберите один или несколько компонентов и выполните команду GExperts, Components to Code.
  3. Вставьте сгенерированный код в ваше приложение.
  4. Удалить компонент (ы) из конструктора визуальной формы.

Пример (TButton-создание кода, генерируемого таким образом):

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

Отличный совет! Это именно то, что я бы предложил. GExperts - отличный инструмент для работы с Delphi. –

+0

... или вы можете создать его в визуальном редакторе, а затем взять пик в файл .dfm. В основном то же самое есть в тексте – Earlz

+0

Gracias. Я предпочитаю писать все сам по себе (я знаю, что это, может быть, изобретать колесо, но я чувствую больше контроля над ним), так или иначе, похоже, что инструмент GExpert не изменяется в чистом коде, и это звучит хорошо. Еще раз спасибо за консультацию. – QMaster

1

Но если я не знаю, конечно, сколько компонентов я хочу создать, например, если это зависит от решения пользователя. Итак, как я могу объявить компоненты динамически?

Ответ был предложен - самым простым способом является Список объектов (компонентов). TObjectList является самым простым в использовании (в условных обозначениях). Списки великолепны!

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

// Вы можете получить более изощренными и объявить // TNotifyevents и назначить их, но позволяет сохранить его простым :) . . .

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; 

список объектов может содержать любой объект, визуальный или нет, но это дает дополнительную нагрузку сортировки, какие элементы которых - лучше иметь связанные списки, если вы хотите использовать несколько динамических элементов управления на подобных панелей, например.

Примечание: как и другие комментаторы, я, возможно, слишком упрощен для краткости, но надеюсь, что вы идете. Вам нужен механизм для управления объектами, когда они созданы, и списки отлично подходят для этого материала.

0

Некоторые компоненты переопределяют метод «Loaded». Этот метод не будет вызываться автоматически, если вы создадите экземпляр во время выполнения. Он будет вызываться Delphi при загрузке из файла формы (DFM).

Если метод содержит код инициализации, ваше приложение может проявлять неожиданное поведение при создании во время выполнения. В этом случае проверьте, использовал ли этот компонент этот метод.

0

Если вы устанавливаете элементы управления победой в групповых ящиках/элементах управления страницами/Etc ..., я думаю, что поле родительской группы также является владельцем. Я заметил резкое уменьшение времени закрытия окна при выполнении этого, в отличие от того, что владелец всегда был основной формой.

1

Во время исследования «создание формы delphi с использованием шаблона на основе xml» я нахожу что-то полезное, указывающее RTTI и использующее открытые инструменты api (ToolsApi.pas, я думаю). Посмотрите на интерфейсы в блоке.

4

Я хотел бы добавить, что при динамическом добавлении элементов управления ... это хорошая идея добавить их в список объектов (TObjectList), как предложено в < 1> by @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; 

Вы должны добавить блок 'Contnrs' в список Uses. I.e System.Contnrs.pas базовый блок контейнеров И у вас может быть много списков объектов. Я предлагаю использовать TObjectList для каждого типа управления, который вы используете , например.

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 

Это позволяет легко манипулировать и управлять каждым элементом управления, так как вы будете знать, какой тип управления он, например.

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; 

Это позволяет затем использовать методы и свойства этого элемента управления Не забудьте создать TObjectLists, возможно, в форме создания события ...

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

Это пример как эмулировать тег кнопки на 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. 
Смежные вопросы