إنشاء المكونات في وقت التشغيل - دلفي
-
05-07-2019 - |
سؤال
كيف يمكنني إنشاء مكون في وقت التشغيل ثم العمل معه (تغيير الخصائص، وما إلى ذلك)؟
المحلول
يعتمد ذلك على ما إذا كان مكونًا مرئيًا أو غير مرئي.المبدأ هو نفسه، ولكن هناك بعض الاعتبارات الإضافية لكل نوع من المكونات.
للمكونات غير المرئية
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 أزرار على الحد الأيسر للنموذج.إذا كنت تريد تعديل الأزرار لاحقًا، فيمكنك تخزينها في القائمة.(قائمة المكونات هو الأنسب، ولكن قم أيضًا بإلقاء نظرة على المقترحات الواردة من التعليقات على هذه الإجابة)
كيفية تعيين معالجات الأحداث:
يجب عليك إنشاء طريقة معالج الحدث وتعيينها إلى خاصية الحدث.
procedure TForm1.MyButtonClick(Sender: TObject);
var
Button: TButton;
begin
Button := Sender as TButton;
ShowMessage(Button.Caption + ' clicked');
end;
B := TButton.Create;
//...
B.OnClick := MyButtonClick;
نصائح أخرى
لتبسيط عملية إنشاء مكون وقت التشغيل، يمكنك استخدام خبراء.
- قم بإنشاء مكون (أو المزيد من المكونات) بشكل مرئي وقم بتعيين خصائصه.
- حدد مكونًا واحدًا أو أكثر وقم بتنفيذ GExperts، Components to Code.
- الصق الكود الذي تم إنشاؤه في التطبيق الخاص بك.
- قم بإزالة المكون (المكونات) من مصمم النموذج المرئي.
مثال (رمز إنشاء 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;
وأود فقط أن أضيف أن عند إضافة عناصر تحكم حيوي ... انها فكرة جيدة لإضافتها إلى قائمة الكائنات (TObjectList) كما هو مقترح في <1> من جانب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 'الى قائمة استخدامات الخاصة بك. م> أي بمعنى 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;
ولكن اذا كنت لا تعرف بالتأكيد كم مكونات أريد إنشاء، على سبيل المثال إذا كان يعتمد على قرار المستخدم. فكيف أعلن مكونات حيوي؟
اقتباس فقرة>تم اقترح الجواب - أسهل طريقة هي قائمة الكائنات (مكونات). TObjectList هو أبسط لاستخدام (في contnrs وحدة). قوائم كبيرة!
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;
ويمكن أن تحتوي قائمة كائن أي كائن البصرية أم لا ولكن التي تمنحك النفقات المضافة لفرز العناصر التي هي التي - الأفضل أن يكون القوائم ذات الصلة إذا كنت تريد متعددة التحكم الديناميكي على لوحات مماثلة على سبيل المثال
ملحوظة: مثل المعلقين الآخرين ربما أكون قد الإفراط في تبسيط الإيجاز ولكن أرجو أن شركة جنرال الكتريك هذه الفكرة. كنت في حاجة الى آلية لإدارة كائنات أخرى يتم إنشاؤها وقوائم ممتازة لهذه الاشياء.
وخلال البحث على "إنشاء نموذج دلفي باستخدام قالب يستند إلى XML"، وأجد شيئا لافتا مفيدة من RTTI واستخدام أدوات مفتوحة API (ToolsApi.pas على ما أظن). إلقاء نظرة على واجهات في الوحدة.
وتخفيف جدا. استدعاء إنشاء. مثال:
procedure test
var
b : TButton;
begin
b:=TButton.Create(nil);
b.visible:=false;
end;
وهذا يخلق عنصر (TButton هو عنصر) في وقت التشغيل وبتعيين الخاصية مرئية.
لالمنشئ: تمرير شيء إذا كنت ترغب في إدارة الذاكرة نفسك. تمرير مؤشر مكون آخر إذا كنت تريد أن يكون دمرت عندما يتم تدمير العنصر الآخر.
وبعض مكونات تجاوز أسلوب "المحملة. لن يتم استدعاء هذا الأسلوب تلقائيا إذا قمت بإنشاء مثيل في وقت التشغيل. وسوف يطلق عليه دلفي عند تحميل من ملف النموذج (DFM) غير كاملة.
إذا يحتوي على طريقة رمز التهيئة، التطبيق الخاص بك قد تظهر سلوك غير متوقع عندما تم إنشاؤها في وقت التشغيل. في هذه الحالة، معرفة ما اذا كان قد استخدم الكاتب مكون هذا الأسلوب.
إذا كنت عش الفوز التحكم في صناديق المجموعة / صفحة التحكم / الخ ...، وأعتقد أنه من المفيد أن يكون مربع المجموعة الأم أيضا أن يكون المالك. لقد لاحظت انخفاضا حادا في أوقات قريبة النافذة عند القيام بذلك، بدلا من الاضطرار المالك يكون دائما هو النموذج الرئيسي.
هذا مثال على كيفية محاكاة علامة الزر على 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.