views:

116

answers:

1

Hello, I want to create an custom control (descendant of TRichEdit). I simply want add some text above the editfield.

I've created my own control and I override the constructor to create a TLabel for the caption. It works, but my problem: How is it possible to move the label above the richedit? When I set Top := -5 the label begins to disappaer.

Here's the code of the constructor:

constructor TDBRichEditExt.Create(AOwner: TComponent);
begin
  inherited;
  lblCaption := TLabel.Create(self);
  lblCaption.Parent := parent;
  lblCaption.Caption := 'Header';
  lblCaption.Top := -5;
end;

I think it's logic that the label disappaers since the richedit is the parent. I've tried

lblCaption.Parent := self.parent;

To make the form which owns the richedit the parent - but this dosn't work...

How could I achieve this? Thank you all!

+9  A: 

I think it's logic that the label disappaers since the richedit is the parent

This is wrong. In your code, the parent of the TLabel is the parent of the TDBRichEditExt, as it should be. Notice that, in a method of TDBRichEditExt, Parent and Self.Parent is the same thing. If you would like the parent of the TLabel to be the TDBRichEditExt itself - which you do not - then you should set lblCaption.Parent := self;.

Now, if the parent of the TLabel is the parent of the TDBRichEditExt, then the Top property of the TLabel refers to the parent of TDBRichEditExt, not to the TDBRichEditExt itself. Hence, if the parent of the TDBRichEditExt is a TForm, then Top := -5 means that the TLabel will be positioned five pixels above the form's upper edge. You mean

lblCaption.Top := Self.Top - 5;

But -5 is a far too small number. What you really should use is

lblCaption.Top := Self.Top - lblCaption.Height - 5;

which in addition makes a 5 px space between the label and the Rich Edit.

Also, you would like

lblCaption.Left := Self.Left;

Another issue

But this will not work, because at the time the component is created, I do not think that the Parent has been set yet. So what you will need is to do the positioning of the label at a more appropriate time. In addition, this will move the label each time your component is moved, which is very important!

TDBRichEditExt = class(TRichEdit)
private
  FLabel: TLabel;
  FLabelCaption: string;
  procedure SetLabelCaption(LabelCaption: string);
public
  constructor Create(AOwner: TComponent); override;
  procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override;
published
  LabelCaption: string read FLabelCaption write SetLabelCaption;
end;

procedure TDBRichEditExt.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;
  if not assigned(Parent) then
    Exit;
  FLabel.Parent := self.Parent;
  FLabel.Top := self.Top - FLabel.Height - 5;
  FLabel.Left := self.Left;
end;

Details

In addition, when you hide the TDBRichEditExt, you want to hide the label as well. Thus you need

protected
  procedure CMVisiblechanged(var Message: TMessage); message CM_VISIBLECHANGED;

where

procedure TDBRichEditExt.CMVisiblechanged(var Message: TMessage);
begin
  inherited;
  if assigned(FLabel) then
    FLabel.Visible := Visible;
end;

And similarly for the Enabled property, and you also need to update the parent of the TLabel each time the parent of the TDBRichEditExt is changed:

protected
  procedure SetParent(AParent: TWinControl); override;

with

procedure TDBRichEditExt.SetParent(AParent: TWinControl);
begin
  inherited;
  if not assigned(FLabel) then Exit;
  FLabel.Parent := AParent;
end;
Andreas Rejbrand
Great answer, thank you very much for this detailed information and your effort to explain it!
doubleu
There are more to it than Andreas has explained (very well, must be said +1 for it), see TLabeledEdit source in ExtCtrls.pas. For example, form notification handling.
Fabricio Araujo