i have a little problem. I'm trying to create in Delphi7 a list of components at run-time and to resize them with form's .OnResize event but no use... i can't figure out how to do it.
Here's my code:
procedure TForm1.Button1Click(Sender: TObject);
var
//ExtCtrls
panel: TPanel;
memo: TMemo;
splitter: TSplitter;
list: TListBox;
begin
panel := TPanel.Create(Self);
list := TListBox.Create(Self);
splitter := TSplitter.Create(Self);
memo := TMemo.Create(Self);
with panel do
begin
Parent := Form1;
BevelOuter := bvNone;
Top := 12;
Left := 12;
Height := Form1.Clientheight - 24;
Width := Form1.Clientwidth - 24;
end;
with list do
begin
Parent := panel;
Align := alClient;
Top := 0;
Height := panel.Height;
end;
with splitter do
begin
Parent := panel;
Top := 0;
Width := 12;
Align := alLeft;
end;
with memo do
begin
Parent := panel;
Top := 0;
Left := 0;
Width := round(panel.Width / 4) * 3;
Height := panel.Height;
Align := alLeft;
end;
end;
Do i have to somehow register their names in order to use them in form's event? Or maybe, to create a class and include them?
Any kind of help is really appreciated! Thank you in advance.
Your variables are local to the procedure where they are created so you can't refer to them using those variables when outside that procedure. The solution is to make them fields of the form class.
type
TForm1 = class(TForm)
procedure FormResize(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
FPanel: TPanel;
FMemo: TMemo;
FSplitter: TSplitter;
FList: TListBox;
end;
Then your FormResize
event handler can refer to them.
procedure TForm1.FormResize(Sender: TObject);
begin
if Assigned(FPanel) then
begin
...
end;
end;
Don't forget to remove the local variables from Button1Click
and use the fields instead.
procedure TForm1.Button1Click(Sender: TObject);
begin
FPanel := TPanel.Create(Self);
...
end;
Although David's answer is also very correct, I thought I would take a moment and go into some more detail. By the looks of it, you seem to be very new with Delphi. There is a very common issue with beginners, which David doesn't address in his answer, pertaining to creating and freeing these objects. Any and every time you ever call 'Create' on a class, at some point, when you're done with it, you have to also 'Free' that class. Failure to free anything will result in a memory leak, and no one wants that. Freeing is just as simple as creating - until you get into the subject of keeping a list of objects (which you don't need right now).
Let's say you wanted to create a text box (TEdit
) control and place it in the center of your form. Now first of all, the Delphi IDE allows you to simply drop these controls in your form, just making sure you know. You don't necessarily need to create/free them yourself, unless there's some special scenario. But doing this is dangerous. For the sake of this example, we're assuming that this TEdit
control will be there for the entire duration of your application.
First, you need to declare a variable somewhere for this control. The most reasonable place for this is inside the class where it will be used (in this case, your form which we'll call Form1
). When working with variables (aka Fields) in your form, make sure you do not put anything above the private
section. Everything above private
is intended for auto-generated code by Delphi for anything which has been dropped (and is visual) in your form. Otherwise, any manually created things must go under either private
or under public
. The public
area would be a good place for your control...
type
TForm1 = class(TForm)
private
public
MyEdit: TEdit;
end;
Now that it's declared, we have to create (and free) it. It's a good practice that any and every time you ever create something, that you immediately put the code to also free it before you continue working. Make an event handler for your form's OnCreate
and OnDestroy
events...
procedure TForm1.FormCreate(Sender: TObject);
begin
MyEdit:= TMyEdit.Create(nil);
MyEdit.Parent:= Self;
MyEdit.Left:= (ClientWidth div 2) - (Width div 2);
MyEdit.Top:= (ClientHeight div 2) - (Height div 2);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if assigned(MyEdit) then MyEdit.Free;
end;
If this object is not created (before creation or after destruction), then you will get an "Access Violation" when trying to use it. This is because your application tries to access an area of the computer's memory which is not allocated or not matching with the type you meant to get.
Well, that's the basics to fix your scenario. However one more thing to show you. Suppose you need to just create an object for a short time, for the duration of a procedure. There's a different approach for this. In your code above, you declared your variable directly within the procedure. This example will show you when it is necessary to do this...
procedure TForm1.Button1Click(Sender: TObject);
var
MyObject: TMyObject;
begin
MyObject:= TMyObject.Create;
try
MyObject.DoSomething;
Caption:= MyObject.GetSomething;
finally
MyObject.Free;
end;
end;
You see, as long as MyObject
will only be used in this one call to this procedure, then you can declare it here. But if the object is expected to stay in memory after this procedure is over and done with, then things get more complicated. Again, in your case, stick with putting this in the form's class until you're more familiar with dynamically creating objects.
A final note, as mentioned above, you do have the ability to place the TEdit
control directly on your form in design-time without writing your own code. If you do this, you need to remember NOT to try to create or free these ones. This is also the case when Delphi will automatically put the code above the private
section - is when there's something which you're not supposed to play with.
I don't think I am eligible to "comment", so I'm phrasing this as an "answer". If you want to resize your runtime components when their parent changes size, take a good look at the Anchors property. It can save you a lot of work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With