Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to know Width when creating New component

Status
Not open for further replies.

GeppoDarkson

Programmer
Oct 9, 2002
74
IT
Hi to all,
I have to make a new component based on a TPanel with some controls over it.

I need to know the Width and Height to set the position of the child controls (for example, a label in the middle of the panel).

When the component is creating I can't find how to know the "final" width (it gives me 185 as when you put it on the form with no drag).

If I call my method "ArrangeAllTheChildControls" at runtime it works.

I can't override OnShow, OnActivate etc to make the call.

I think that a Timer can handle this by activating the procedure after the creation, but it seems to be not so elegant, so maybe there are some better ways.

Any suggestions?

Thank you,
Ciao,
Geppo Darkson.
 
Use the anchoring.

Set the child controls "Anchor" properties to have them keeping their positions when the panel is rezised.

buho (A).
 
Hi buho,
my problem is not on resizing, but on create:
I have to put 10 labels spaced equally, so I need to let the component create, and only after he have the final dimensions I can calculate the space between the labels.

Unfortunally until the creation is complete the width and height are not set properly, and I can't find an event fired after the creation to override.

Ciao,
Geppo Darkson.
 
Not sure I'm getting your meaning right.

a) You can assign the default Width and Height in the component constructor. Override it, call the inherited one and set your panel size when it returns.

b) You design your component based on some "default size" (the same you are setting in the constructor) and place your labels accordingly. When the component is dropped they will appear in the due places. After the dropping the user can resize the component, but it is a normal resize operation, so anchors should work.

Anyway, you can intercept the WM_SIZE and WM_WINDOWSPOSCHANGING Windows messages, but most VCL components explicitly don't act in the WM_SIZE if the component state is csLoading (same for WM_WINDOWPOSCHANGING).

May be you can call your "ArrangeAllTheChildControls" method in your constructor too, or in the AfterConstruction method... or may be not, depends on what your are actually doing in it.

NOTE : TDBNavigator is a control with a handfull of buttons, may be taking a look at the source will help you.

buho (A).
 
Override the component's Loaded procedure.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Interesting, lets see how TPanel works: it is using TCustomPanel.Create where the panel default size is defined assigning the Height and Width. After the creation TControl.Loaded is called, and it calls UpdateAnchorRules.

I've never resorted to Loaded overriding... something I'm missing here? Some situation where setting the default sizes in the constructor will not work? I never base a component in a Txxxx but in a TCustomXXXX if it exists, may be basing in TPanel (and not in TCustomPanel) affects some things?

buho (A).
 
This is a proof of concept. I'm only checking the horizontal alignment.

It works. You can drop it in a form and the labels appears centered; after that you can resize it and the labels keeps the horizontal centering (labels width vary and they are not vertically anchored).

Of course you can run the test app too :).

Code:
{------------------------------}
unit PWL; // Panel With Labels
{------------------------------}

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, ExtCtrls,
  StdCtrls, Graphics;

{------------------------------}
{Internal definitions}
const
  PWLMaxLabels = 3;
type
  TPWLArray = array of TLabel;

{------------------------------}
{The component}
type
  TPWL = class(TCustomPanel)
  private
    pwlArray : TPWLArray;
  public
    constructor Create(AOwner : TComponent); override;
  end;

{------------------------------}
procedure Register;

{==============================}
implementation

constructor TPWL.Create(AOwner : TComponent);
  procedure StartLabel(i : integer);
    const
      WL = 200;       // Default label width
    var
      Lbl : TLabel;   // Debug - To have it in the Local Variables pane
    begin
      pwlArray[i] := TLabel.Create(Self);
      Lbl := pwlArray[i];
      Lbl.Parent := Self;
      Lbl.AutoSize := False;
      Lbl.Width := WL;
      Lbl.Left := (Width - WL) div 2;
      Lbl.Top := 4 + Height * i div PWLMaxLabels;
      Lbl.Anchors := [akRight, akLeft];
      Lbl.Caption := IntToStr(i);
      Lbl.Color := clHotLight;
    end;
  var
    i : integer;
  begin
    inherited Create(AOwner);
    Width := 300;       // Default - initial
    Height := 300;      // Default - initial
    SetLength(pwlArray, PWLMaxLabels);
    for i := 0 to PWLMaxLabels - 1 do StartLabel(i);
  end;

{------------------------------}
procedure Register;
begin
  RegisterComponents('Samples', [TPWL]);
end;

{==============================}
end.
 
Thank you all,
now everithings works well.

Ciao,
Geppo Darkson.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top