Board index » cppbuilder » Owner/Parent

Owner/Parent


2007-10-13 04:50:54 PM
cppbuilder5
I have just succeeded in creating a new control (a TMemo) at run time. I never did that before; so should I set both the Parent and Owner? Or will at least one come by default?
George
 
 

Re:Owner/Parent

Hi George
In article <471086ee$ XXXX@XXXXX.COM >,
XXXX@XXXXX.COM says...
Quote

I have just succeeded in creating a new control
(a TMemo) at run time. I never did that before;
so should I set both the Parent and Owner?
Or will at least one come by default?
None comes by default.
example:
in the h file:
TMemo* MyMemo;
in the Cpp file
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
, MyMemo(0)
{
}
void __fastcall CreateMemoClick(TObject* Sender)
{
if(MyMemo)delete MyMemo;
MyMemo = new TMemo(this);
MyMemo->Visible = false;
MyMemo->Parent = Form1;
MyMemo->Align = alNone;
MyMemo->SetBounds(20,20, Width-40, ClientHeight-40);
MyMemo->Visible = true;
}
TMemo(this);
TMemo(Form1);
TMemo(Panel1);
TMemo(NULL); // Remember to delete if You use NULL
MyMemo->Parent = Form1; //show on Form1
MyMemo->Parent = Panel1; //show on Panel1
The parent decide where the panel will be shown
MyMemo->Visible = false;
Make it possible to make all the changes to the
Memo without repainting the control each time.
MyMemo->Visible = true;
Makes the control visible.
You can also use
MyMemo->Hide();
MyMemo->Show();
instead of MyMemo->Visible
Kind regards
Asger
 

Re:Owner/Parent

Well, up to a point.
If none come by default. How can I get a TMemo showing without setting both? Also I put nothing in the .h file.
It is now apparent to me that the line
TMemo*Memo2=new TMemo(Form1);
actually sets the owner as Form1.
I don't see the need for your line
, MyMemo(0)
I never did understand what "this" means; I tried moving the initiating button off form background into a panel and I expect either the owner or parent of the TMemo to change as well, but it doesn't. I don't understand why not.
George.
Quote

=?utf-8?Q?Asger_J=C3=B8rgensen?= < XXXX@XXXXX.COM >wrote:
Quote

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
, MyMemo(0)

 

{smallsort}

Re:Owner/Parent

=?utf-8?Q?Asger_J=C3=B8rgensen?= < XXXX@XXXXX.COM >wrote:
Quote

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
, MyMemo(0)
Since TForm descends from TObject, all of it's members are
automatically initialized to NULL so that's not needed.
Quote
MyMemo = new TMemo(this);
MyMemo->Visible = false;
MyMemo->Parent = Form1;
MyMemo->Align = alNone;
MyMemo->SetBounds(20,20, Width-40, ClientHeight-40);
MyMemo->Visible = true;
There is no need to set Visible to false and then back to true
and Align is alNone by default.
Quote
TMemo(NULL); // Remember to delete if You use NULL
Since all TWinControl descendents require that the Parent be
set, it's not required to explicitly delete the control because
in terms of destruction, the Parent behaves exactly the same
as the Owner does.
When an object is destroyed, any objects that it ownes are
also destroyed and any objects that they own are destroyed
ad infinitum. In addition, when an object is destroed, any
objects that it parents will also be destroyed.
Quote
MyMemo->Visible = false;
Make it possible to make all the changes to the
Memo without repainting the control each time.
While that might work, it's not good advice. With any
TWinControl, if it doesn't have a BeginUpdate method,
use the win32 API SendMessage to send it a WM_SETREDRAW
message (which is all BeginUpdate does).
In the case of a TMemo, you can call Begin/EndUpdate on it's
Lines property.
~ JD
 

Re:Owner/Parent

"george" < XXXX@XXXXX.COM >wrote:
Quote

Please wrap your lines when you post. If using a reader,
locate and set an option for line length/limit/width.
Thanks!
Quote
If none come by default. How can I get a TMemo showing
without setting both?
You *must* pass an Owner in as you allocate but that *can*
be NULL (kinda dumb if you ask me because I;ve never seen a
good reason for it except for special cases with a TForm).
As for the Parent, that must be explicitly set because the
Parent is responsible for forwarding paint message. Without
a Parent, the control will never be seen.
Quote
Also I put nothing in the .h file.
You can do it without it being defined as a member of the
class. You just didn't explain enough so Asger put it there
just as I would have.
Quote
It is now apparent to me that the line
TMemo*Memo2=new TMemo(Form1);
actually sets the owner as Form1.
Correct. It also declares Memo2 as a local variable which
means that as the block finished execution, Memo2 will be
out of scope and no longer accessable.
Quote
I don't see the need for your line
, MyMemo(0)
That is one way to initialize members. He could have just as
well explicitly set the member to NULL in the ctor but since
TForm descends from TObject and TObject automatically
initializes it's members to NULL, it wasn't needed in any event.
Quote
I never did understand what "this" means
I won't get too technical with you and try to keep it simple.
It's a hidden pointer that points to the class in which it's
used. If used inside Form1, it means 'Form1'. If used inside
a component, it means 'this particulare component'.
Quote
I tried moving the initiating button off form background
into a panel and I expect either the owner or parent of the
TMemo to change as well, but it doesn't.
It wouldn't. You showed the allocation where you used the form
as the Owner. If you moved that to a different form, the Owner
would not change because TForm1 is explicit. However, if you
has used 'this' as the Owner, TForm2 would be the Owner.
As for the Parent, you didn't show that code and you haven't
explained what it is that you're trying to accomplish.
~ JD
 

Re:Owner/Parent

Hi JD
In article <471133b5$ XXXX@XXXXX.COM >,
XXXX@XXXXX.COM says...
Quote

Since TForm descends from TObject, all of it's members are
automatically initialized to NULL so that's not needed.
Thanks for that information, had I known, i could
have saved a lot of initialzing lists over the years.<g>
Quote
>MyMemo->Visible = true;

There is no need to set Visible to false and then back to true
and Align is alNone by default.

>TMemo(NULL); // Remember to delete if You use NULL

Since all TWinControl descendents require that the Parent be
set, it's not required to explicitly delete the control because
in terms of destruction, the Parent behaves exactly the same
as the Owner does.
Nice to know, but sometimes its a TSpeedButton or
a TImage so if its only tru for TWinControl's I thin
I'll keep on doing it, that is if I use NULL, which
usually I don't.
Quote
>MyMemo->Visible = false;
>Make it possible to make all the changes to the
>Memo without repainting the control each time.

While that might work,
Ooh it works especially when You create a bunch of
buttons where You have to: set the size, the caption
and the glyph. Saves a lot of repainting.
Quote
it's not good advice. With any TWinControl,
if it doesn't have a BeginUpdate method,
use the win32 API SendMessage to send it a WM_SETREDRAW
message (which is all BeginUpdate does).
And why wasn't it good advice ?
It's easy and it's logic..
Quote
In the case of a TMemo, you can call Begin/EndUpdate on it's
Lines property.
Yaaa, but there is no lines in a new TMemo.<g>
Kind regards
Asger
 

Re:Owner/Parent

Hi George
In article <47112f55$ XXXX@XXXXX.COM >,
XXXX@XXXXX.COM says...
Quote

Well, up to a point.

If none come by default. How can I get a TMemo showing without
setting both? Also I put nothing in the .h file.
Could You show the code where You do that ??
I sure would like to see that.
Kind regards
asger
 

Re:Owner/Parent

On or about 13 Oct 2007 01:50:54 -0700 did "george"
< XXXX@XXXXX.COM >dribble thusly:
Quote

I have just succeeded in creating a new control (a TMemo) at run time. I never did that before; so should I set both the Parent and Owner? Or will at least one come by default?
If you did something like this:
TMemo *memo = new TMemo(this);
Then you've already set the owner to the form you're working with. All
that does is make the form responsible for freeing that memory (you
can still free it yourself without causing trouble).
To display the control, you need to give it a parent:
memo->Parent=this;
memo->Left=0;
memo->Top;
memo->Width=100;
memo->Height=50;
That will display it on the current form, at the upper left corner,
and set its dimensions to 100x50.
 

Re:Owner/Parent

=?utf-8?Q?Asger_J=C3=B8rgensen?= < XXXX@XXXXX.COM >wrote:
Quote

[...] but sometimes its a TSpeedButton or a TImage so if its
only tru for TWinControl's I thin I'll keep on doing it,
that is if I use NULL, which usually I don't.
You missed the point that it has to be parented and only
TWinControls can Parent. Of course, there are times when
one needs to dynamically create objects only under certain
conditions and destroy them under other conditions but the
truth is that even if not destroyed, when the application
exits, Windows will recover that memory irrespective if
your application deleted that object or not.
The only real question is if not propperly managed, will the
application eat memory as long as it's running.
Quote
>>MyMemo->Visible = false;
>>Make it possible to make all the changes to the
>>Memo without repainting the control each time.
>
>While that might work,

Ooh it works especially when You create a bunch of
buttons where You have to: set the size, the caption
and the glyph. Saves a lot of repainting.
It doesn't work that way. Messages are only processed when the
application idles (unless you explicitly process them). That
means that one can allocate multiple controls and set all of
the required properties before a single WM_PAINT is processed.
Now, some controls do work differently (like a TMemo and
a TStringGrid) where when they detect a change, they use
SendMessage to cause an immediate repaint which in essence
gets inserted into your block of code so that's when one
needs to disable refresh to prevent that. But ... those
controls are few and buttons (any button) are not one of
them.
If you're really concerned about the amount of painting,
using Visible generates two repaints (once to erase and
once to paint). Not only does that induce flicker, it
causes twice as much painting as needed.
You can accomplish everything that you're insisting on without
the flicker and with half as much painting by changing 2 lines
of code and adding a third. For example:
instead of:
// paints twice
Memo1->Visible = false;
// add lines
Memo1->Visible = true;
use:
// paints once
Memo1->Lines->BeginUpdate();
// add lines
Memo1->Lines->EndUpdate();
Memo1->Invalidate();
Quote
>it's not good advice. [...]
And why wasn't it good advice ?
All setting Visible does is introduce a programmer-caused
flicker and it paints twices as much as needed.
Quote
It's easy and it's logic..
Easy is not always good. I see disabling refresh just as
easy and even more logical because it does not introduce
undesirable behavior and it's twice as efficeient. Not
only that, it's the most efficient method available. Now
that's logical!
Quote
>In the case of a TMemo, you can call Begin/EndUpdate on it's
>Lines property.

Yaaa, but there is no lines in a new TMemo.<g>
With a newly allocated TMemo, it would be correct to say
that it has zero lines (that Memo::Lines::Count is zero)
but it would be incorrect to say that it's Lines does not
exist (is not valid).
Test it for yourself. Start a new application and add this to
the main form's ctor:
TMemo *pMemo = new TMemo( this );
pMemo->Parent = this;
pMemo->Left = 10;
pMemo->Top = 10;
pMemo->Lines->BeginUpdate(); // if you're correct, AV here
// add lines
pMemo->Lines->EndUpdate();
~ JD