Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: How to get ClientHeight during constructor?

44 views
Skip to first unread message

Remy Lebeau (TeamB)

unread,
Jul 1, 2008, 2:06:45 PM7/1/08
to

"Ian Boyd" <ian.borla...@avatopia.com> wrote in message
news:486a713b$1...@newsgroups.borland.com...

> How can i get my control's client height during it's constructor.

You don't. That is too soon in the creation process.

> i need to position controls inside the client area.

Just create the controls and set their Left/Top and/or Align properties
normally. They will position themselves for you when the TThing's HWND
becomes valid.


Gambit


Ian Boyd

unread,
Jul 1, 2008, 2:02:36 PM7/1/08
to
How can i get my control's client height during it's constructor.

type
TTestingThing = class(TEdit)
public
constructor Create(AOwner: TComponent); override;
end;

constructor TThing.Create(AOwner: TComponent);
var
ch: Integer;
begin
inherited Create(AOwner);
ch := Self.ClientHeight;
end;

EInvalidOperation: Control '' has no parent window

Ian Boyd

unread,
Jul 1, 2008, 2:12:35 PM7/1/08
to
> Just create the controls and set their Left/Top and/or Align properties
> normally. They will position themselves for you when the TThing's HWND
> becomes valid.

i can calculate top and left without problems, but the child controls are
not visually aligned.


Remy Lebeau (TeamB)

unread,
Jul 1, 2008, 3:10:26 PM7/1/08
to

"Ian Boyd" <ian.borla...@avatopia.com> wrote in message
news:486a7392$1...@newsgroups.borland.com...

> i can calculate top and left without problems, but the
> child controls are not visually aligned.

Then you are not setting them up correctly. Please show your actual code.


Gambit


Ian Boyd

unread,
Jul 1, 2008, 3:54:13 PM7/1/08
to
>> i can calculate top and left without problems, but the
>> child controls are not visually aligned.
>
> Then you are not setting them up correctly. Please show your actual code.

i'll show pseudo-code, to demonstrate what i'm trying to achieve - since
there's a lot of fluff that would just confuse things.

type
TDemoThing = class(TCustomEdit)
private
FimgButton: TPaintBox;
protected
procedure Resize; override;


public
constructor Create(AOwner: TComponent); override;
end;

constructor TDemoThing .Create(AOwner: TComponent);
begin
inherited Create(AOwner);

Self.Text := '';
Self.Width := 210;

FimgButton := TPaintBox.Create(AOwner);
FimgButton.Parent := Self;

AdjustButtonLocation;
end;

procedure TDemoThing .Resize;
begin
inherited Resize;

AdjustButtonLocation;
end;

procedure TDemoThing .AdjustButtonLocation;
var
padding: Integer;
begin
//Position and size the button with 10% margin from the top, bottom and
left.
//Make it's width 26/20 the ratio of it's height

padding := Round(Self.ClientHeight* 0.10);

FimgButton .Top := padding; //10% from top
FimgButton .Height := Self.ClientHeight - 2*padding; //10% off bottom
and top
FimgButton .Width := MulDiv(FpnlButton.Height, 26, 20); //this is the
size ratio it needs to be, with height determinted
FimgButton .Left := Self.ClientWidth - FimgButton.Width - padding;

Self.Invalidate;
end;


Remy Lebeau (TeamB)

unread,
Jul 1, 2008, 8:26:07 PM7/1/08
to

"Ian Boyd" <ian.borla...@avatopia.com> wrote in message
news:486a8b64$1...@newsgroups.borland.com...

> i'll show pseudo-code, to demonstrate what i'm trying to achieve -
> since there's a lot of fluff that would just confuse things.

TPaintBox is a TGraphicControl descendant, not a TWinControl descendant.
Graphical controls cannot appear on top of a TCustomEdit like you are
attempting. They are drawn behind the TCustomEdit. You are positioning
your TPaintBox such that the TCustomEdit completely covers it. That is why
you do not see it visually.

To do what you are attempting, you will have to stop using the TPaintBox
altogether, and intercept the WM_PAINT and WM_ERASEBKGND messages to draw
directly on the TCustomEdit itself instead.


Gambit


Ian Boyd

unread,
Jul 3, 2008, 10:42:15 AM7/3/08
to
> TPaintBox is a TGraphicControl descendant, not a TWinControl descendant.
> Graphical controls cannot appear on top of a TCustomEdit like you are
> attempting. They are drawn behind the TCustomEdit. You are positioning
> your TPaintBox such that the TCustomEdit completely covers it. That is
> why you do not see it visually.

i see it visually, and i have my nice custom code drawing done.

i just gave up trying to find the client height of an edit box, and assume
that it's always 2 pixels.


Back to my original question: How does one get the ClientHeight of a control
during it's constructor?

Sample code to reproduce the error:
type
TTestingThing = class(TEdit)


public
constructor Create(AOwner: TComponent); override;
end;

constructor TThing.Create(AOwner: TComponent);


var
ch: Integer;
begin
inherited Create(AOwner);
ch := Self.ClientHeight;
end;

The call to ClientHeight, which internally calls HandleNeeded, throws the
error:
"EInvalidOperation: Control '' has no parent window."
Well of course it does, it's AOwner.

Note: It's okay to say that Delphi just cannot do it, and it's a limitation
of Delphi's mechanism of wrapping visual controls in object based wrapper.

This is why i try to avoid posting code - people try to answer a question
that wasn't asked. If i'm asking for a device that can be used to put a
bullet through my foot: give me a gun.


Mark Tiede

unread,
Jul 3, 2008, 11:42:46 AM7/3/08
to
Ian,

Maybe you can override the CreateWnd method. I think at that point in
time things may be defined.


"Ian Boyd" <ian.borla...@avatopia.com> wrote in message

news:486a713b$1...@newsgroups.borland.com...

Marc Rohloff [TeamB]

unread,
Jul 3, 2008, 1:16:48 PM7/3/08
to
On Thu, 3 Jul 2008 10:42:15 -0400, Ian Boyd wrote:

> Back to my original question: How does one get the ClientHeight of a control
> during it's constructor?

As Remy said you can't.

Some alternatives would be to override TControl.SetParent (although I
would recommend against this) or to trap one of the Window's messages.
However why not just use the Height property?

--
Marc Rohloff [TeamB]
marc -at- marc rohloff -dot- com

Remy Lebeau (TeamB)

unread,
Jul 3, 2008, 2:16:25 PM7/3/08
to

"Ian Boyd" <ian.borla...@avatopia.com> wrote in message
news:486ce547$1...@newsgroups.borland.com...

> i just gave up trying to find the client height of an edit box,
> and assume that it's always 2 pixels.

That is a bad assumption to make, not to mention a wrong assumption anyway.

> Back to my original question: How does one get the ClientHeight
> of a control during it's constructor?

For a TWinControl descendant, querying the ClientHeight (or the ClientWidth
or ClientRect) property requires a valid Handle. That, in turn, requires a
valid Parent. The Parent has not been assigned yet whle you are still
inside the constructor, hense the error message you were seeing before. You
must wait for the Parent hierarchy to be set up first before you can access
anything that requires the Handle property. If you must use a Handle-based
value during the construction process, then you will have to override either
the SetParent() or Loaded() method for that, ie:

type
TTestingThing = class(TEdit)
protected
void SetParent(AParent: TWinControl); override;
end;

void TTestingThing.SetParent(AParent: TWinControl);
var
ch: Integer;
begin
inherited;
if HasParent then
begin
ch := Self.ClientHeight;
...
end;
end;

> The call to ClientHeight, which internally calls HandleNeeded,
> throws the error:

As it should be, because the Parent property is not assigned yet.

> "EInvalidOperation: Control '' has no parent window."
> Well of course it does, it's AOwner.

No. Owner and Parent are two completely different things.


Gambit


Christian Klopfer

unread,
Jul 4, 2008, 3:24:59 AM7/4/08
to
I had also some problems within the Constructor.

I solved my problem by transfering the initialization to an timer event
that is started at the end of the constructor.

So the construction is finished and a couple of miliseconds later the
timer fires to initialize it ;-)

A bit of work but ok I think. Maybe also a solution for you...


Ian Boyd schrieb:

Frederick C. Wilt

unread,
Jul 5, 2008, 1:47:27 PM7/5/08
to

"Christian Klopfer" <No-...@Your-Site.be.os> wrote in message
news:486dd04a$1...@newsgroups.borland.com...

>I had also some problems within the Constructor.
>
> I solved my problem by transfering the initialization to an timer event
> that is started at the end of the constructor.

Did you try using OnPaint with a "first time" boolean variable so the
desired code is only executed on the first OnPaint event?


Finn Tolderlund

unread,
Jul 6, 2008, 1:21:05 PM7/6/08
to

"Frederick C. Wilt" <fcw...@mindspring.com> skrev i meddelelsen
news:486fb3b1$1...@newsgroups.borland.com...

I prefer to post a user message in the constructor. It then gets handled
when the form creation is done, the first time the application begins
processing messages. Just like using a timer, but without the extra resource
used by the timer.
--
Finn Tolderlund


Ian Boyd

unread,
Jul 14, 2008, 11:54:52 AM7/14/08
to
> Why not just use the Height property?

Well i could, but Height > ClientHeight, and i want the ClientHeight.


Ian Boyd

unread,
Jul 14, 2008, 12:00:58 PM7/14/08
to
> I solved my problem by transfering the initialization to an timer event
> that is started at the end of the constructor.

Which really is the same as you posting a message to yourself, except in
this case the message is WM_TIMER.


Ian Boyd

unread,
Jul 14, 2008, 11:59:40 AM7/14/08
to
>> i just gave up trying to find the client height of an edit box,
>> and assume that it's always 2 pixels.

> That is a bad assumption to make, not to mention a wrong assumption
> anyway.

i know that on 2000 it is 2 pixels (the sunken border is 2 pixels).

On XP and Vista it's a one pixel visual border, plus a one pixel margin,
giving two pixels.

i suppose it could be different in Seven, but i really don't care that much.
:)

This doesn't seem too bad. Why would someone (Marc Rohloff) recommend
against it, "Some alternatives would be to override TControl.SetParent

(although I
would recommend against this)"

What's the down-side?


0 new messages