tags:

views:

83

answers:

3

Hi. I has a piece of code where I override TStringGrid's inplace editor and the hint window. For this, I created my own string grid based on TStringGrid and use a TEdit for inplace editor and a TPanel for tool tips. In TMyStringGrid.Create constructor I initialize them like this:

Constructor TMyStringGrid.Create();
Begin
  inherited Create(AOwner);
  MyEditor:= TEdit.Create(Self);  
  MyEditor.Parent  := Self;
End;

In this case the owner (the main form) is freeing the controls. I used this for years and it worked. The thing is that other people argue that the programmer should use NIL instead the Self when instantiation the child controls and later to manually free them in the Destroy destructor. It seems that the second alternative has gigantic advantage over the first one, especially when you dynamically create lots of child controls (not my case). Other problem with my code, they say, is that the child controls may be freed after an Application.ProcessMessages call while the application may still want to use them.

So, I should let my code unchanged or should I manually create and free the child controls? There is a any Borland example of compound controls?


Delphi 7, Win XP
Reference: http://delphi.about.com/od/kbcurt/ss/dynamiccreateno.htm

+3  A: 

Yes you can use your code without changing it.

There is a any Borland example of compound controls?

Best example is to check the implementation of TLabeledEdit.

It was creating the label in constructor

  if Assigned(FEditLabel) then exit;
  FEditLabel := TBoundLabel.Create(Self);
  FEditLabel.FreeNotification(Self);
  FEditLabel.FocusControl := Self;
Bharat
Thanks. +1. Right TLabeledEdit! I totally forgot about TLabeledEdit at the moment I asked the question :)
Altar
+2  A: 

There's no good reason to pass nil instead of Self in this situation. That AOwner parameter is there specifically for that reason. Take advantage of it.

There's a reason to pass nil when creating a control and manually destroy it, but for a completely different situation: if you're creating a control (typically a form) inside a function. This is a pretty common pattern, for example:

MyDialog := TMyDialog.Create(nil);
try
  result := MyDialog.ShowModal;
finally
  MyDialog.Free;
end;

There, you want to free it immediately instead of waiting around until the current form gets destroyed, which could be much later. But when it comes to sub-components, you usually want them to be destroyed at the same time as the parent component, not later, so pass Self to AOwner and let the VCL take care of it for you.

Mason Wheeler
Thanks. +1. Which is the name of the pattern?
Altar
+1  A: 

Considering that constructor, the grid instance is owned by Aowner (which is tipically a TForm or a TFrame). The inplace editor is owned and parented by the grid instance. I don't see how ProcessMessages would cause destruction of the child objects, since they will be destroyed in the destroying loop of TMyStringGrid. That's nothing I can see of wrong on that implementation - and I use that same design for the components I create. Ownership is there on VCL to easy our lifes when managing objects' lifetime. And is not the case where nil is recomended as owner, which is shown in Mason' answer.

In the pattern shown by Mason , the reason for the NIL is that, without a owner, the object destruction will not enter in a Notification loop. If you create a lot of components which destruction you handle manually, you want to make sure the owner is NIL, otherwise a lot of code get executed (without need) in each component construction/destruction. Many moons ago, there was an excelent white paper on the web archive of (now defunct) eagle-software.com

Fabricio Araujo
Hi. I think that article originates from About.com http://delphi.about.com/od/kbcurt/ss/dynamiccreateno.htm
Altar
Sincerely, I don't know what article came first. Actually, they are the same article - but about.com doesn't include the date where the article was released - the eagle-software one is from 1999.
Fabricio Araujo