I want to disable all objects in a form, how can I do that? Thanks in
advance for your help!
( I think it should be iterate thru' all objects on the form but I don't
know what function to do that)
Rgds,
scchui
I would do something like this:
for i := 0 to Form1.ComponentCount -1 do
if (Form1.Components[i] is TControl) then
TControl(Form1.Components[i]).Enabled := false;
Hope this helps,
David
"scchui" <nospam> wrote in message news:44fafe25$1...@newsgroups.borland.com...
That needs to be a recursive function call.
~ JD
Thanks!
David
"JD" <nos...@nospam.com> wrote in message
news:44fb0954$1...@newsgroups.borland.com...
Disabling a control necessarily makes all of its children inaccessible,
too. Scchui needs to explain more about what the purpose of the code is.
Is it to make everything *look* disabled (grayed out)? Or is it just to
disallow the user from operating the form?
If the latter, then it's a simple matter of disabling the form itself:
Self.Enabled := False;
--
Rob
My purpose is to disable some controls according to user access level.
I've use the following code to do my job and it works fine. There is many
controls on the form and ususally only some of them need to be enabled. So I
first disable all and then enable the ones granted to user access :
var i:integer;
ChildControl: TControl;
begin
for I:= 0 to self.ControlCount -1 do
begin
ChildControl := self.Controls[I];
childcontrol.enabled:=false;
end;
// and then enable some specific controls according to user access rights
Currently this is only one level of controls on a form and not require
recursive method yet. Though I think that it may be needed to recursively
disable some sub-level child control, if any.
Rgds,
scchui
Grega
"JD" <nos...@nospam.com> wrote in message
news:44fb0954$1...@newsgroups.borland.com...
>
Another top-poster!! Why are the delphi groups the only place
where I see top-posters ?!?
> What do you mean exactly?
Components is an array of objects owned by that component
which can include components that own other components which
can include more components that own still other components
ad infinitum.
To guarantee that all components are itterated, you need a
recursive function (function that calls itself) on each and
component in the top-level component's Components array.
~ JD
You're wrong.
> If he used ControlCount, that needs to be recursive.
You're wrong again. If he used ControlCount, he'd be lucky not
to get an AV because ControlCount is for the Controls array
and may be more or less than the ComponentCount.
> But he uses ComponentCount and that doesn't need to be
> recursive.
Oh? Perhaps then you might tell me what happens to the
Components array for the form if I dynamically allocate
an object and assign say a TPanel as the Owner? I'll tell
you ... nothing. However, something does happen to the
Panels Components array. In addition, if I set the new
control's Parent to the form, the form's Controls array
increases while it's Components remains unchanged as does
the Panel's Control array.
To be clear, Controls is an array of objects that that control
*directly* parents while the Components array is for objects
that that control ownes and any control may have a different
Owner and Parent.
You're wrong again. A recursive function is the only guaranteed
way to get to all Components (and Controls).
~ JD
Not to sound dense, but from what I am reading in these messages I need to
learn something on this topic.
I assume the implication that I need to write a recursive function implies
that I need to not only look at the components owned by the form, but also
any components owned by those components. I was operating under the
assumption that if a component's parent was disabled, it would be as well.
Or maybe you are referring to components that may not be owned by the form
itself?
I would appreciate a code snippet for disabling all components recursively.
Thanks!
Dave
"JD" <nos...@nospam.com> wrote in message
news:44fc7154$1...@newsgroups.borland.com...
More top-posting and no trimming!
> I assume the implication that I need to write a recursive
> function implies that I need to not only look at the
> components owned by the form, but also any components owned
> by those components.
That is correct. However, if (and you as the programmer know
this) you never dynamically (at run-time) allocate a new object,
then your example will work and no recursion is needed. However,
while the native VCL behaves in a predictable way, all bets
are off when you use a 3rd party component.
> I was operating under the assumption that if a component's
> parent was disabled, it would be as well.
That is correct unless, as Rob Kennedy noted, you require the
object to also *look* like it's disabled.
Drop a TPanel on a form and add a TEdit to the TPanel and
disable the TPanel. The TEdit will also be disabled but it
won't look disabled unless you explicitly disable the TEdit.
> Or maybe you are referring to components that may not be
> owned by the form itself?
No. The Owner (Components) is responsible for memory
management (which also includes streaming) and the Parent
(Controls) is responsible for screen-IO. You can itterate
eigther array depending on your needs. The thing to remember
is that the Owner and the Parent are 2 different things
and any given object may have a different Owner and Parent.
In fact, a component can have an Owner and no Parent but not
the reverse.
Any object that derives from TComponent (or later) requires
an Owner and when specified (not nil) will add that object
to the specified owner's Components array.
If that object (the new object) also descends from TWinContol,
it requires a Parent as well and when you set the Parent, you
will add it to the Parent's Controls Array.
For the most part, all of this is quite transparent to most
because few dynamically allocate objects on the fly and even
fewer have a need for a different Owner/Parent pair but it's a
distinction that needs to be made.
Now, the Owner (being responsible for memory management) will
automatically destroy any objects that it ownes when it is
destroyed which means that if any of it's owned objects also
own other objects, they too will also be destroyed ad infinitum.
This means that you can allocate a new object (that descends
from TComponent) and forget about it (not maintain a pointer
to the allocated object) because when the Owner is destroyed,
it will be destroyed.
(I'm really carrying on huh?)
Another useful but poorly documented feature of the VCL is that
the Parent will also destroy anything in it's Controls array
when it is destroyed. IOW, you can allocate a TPanel and a
group of other controls where you set their Parent to the
TPanel and to correctly release memory, all you have to do is
free the TPanel and that's only if you want to free that
memory before the application closes because when it closes,
everything in all component's Components array and everything
in all controls Controls array will automatically be destroyed.
> I would appreciate a code snippet for disabling all
> components recursively.
After all of what I had to say, you're going to hate me
because I (still) don't do delphi. Sure I can read it and
for simple things, I can post samples but I couldn't google
a good sample that I could convert. You'll just have to
translate (it's pure C++ between begin and and):
DisableComponents( Form1 );
procedure TForm1.DisableSComponents(AComponent : TComponent);
begin
// declare x as integer and initialize to zero
// while x < AComponent.ComponentCount do the body of the loop and then increment x
for( int x = 0; x < AComponent->ComponentCount; ++x )
{
// test Components[x] to see if it's a TControl
if( dynamic_cast<TControl*>( AComponent->Components[x] )
{
AComponent->Components[x]->Enabled = false;
}
DisableComponents( AComponent );
}
end;
~ JD
You seem to know a lot, and I appreciate the insight.
My only question, and once again ignore the ignorance, but how does your
code (albeit in C++) differ from my answer?
Your explanation was good, and I am learning, but your code looks strikingly
like mine...
Or have I missed something again?
DisableComponents( AComponent );
Thang
"Dave" <Dayto...@dslextreme.com> wrote in message
news:44fd2fed$1...@newsgroups.borland.com...
Dave.
You have missed the most important part. it is recursive. Here's JD's
procedure converted to Pascal:
procedure TfrmMain.DisableComponents(AComponent : TComponent);
var
x : integer;
begin
for x := 0 to AComponent.ComponentCount - 1 do
begin
if AComponent.Components[x] is TControl then
TControl(AComponent.Components[x]).Enabled := false;
DisableComponents( AComponent );
end;
end;
You would call it something like:
for i := 0 to frmMain.ComponentCount - 1 do
DisableComponents(frmMain.Components[i]);
As Vu points out, note the call to DisableComponents from WITHIN
DisableComponents - this is recursion, see
http://en.wikipedia.org/wiki/Recursion for reference.
Dave
Note the deliberate error ;-)
Recursive call should be DisableComponents(AComponent.Components[x])
Easier would be:
DisableComponents(self);
The looping will be done within the function.
>> As Vu points out, note the call to DisableComponents from WITHIN
>> DisableComponents - this is recursion, see
>> http://en.wikipedia.org/wiki/Recursion for reference.
>>
> Note the deliberate error ;-)
>
> Recursive call should be DisableComponents(AComponent.Components[x])
Also I guess there's a difference between using:
(1) Components & ComponentCount
(2) Controls & ControlCount.
The form owns all components, so in case (1) all components
on the form will be found and no recursion is needed. Of
course you can mess this up be supplying a different owner
when dynamically creating components. In case (2), only
the controls will be listed for wich the form (or control)
is parent. So you have to use recursion in that case. So I
guess the 2 versions are something along these lines:
(1)
procedure TfrmMain.DisableComponents;
var
i: integer;
begin
for i:=0 to ComponentCount-1 do
if Components[i] is TControl then
TControl(Components[i]).Enabled := false;
end;
(2)
procedure TfrmMain.DisableControls(ctl: TControl);
var
i: integer;
wc: TWinControl;
begin
if ctl is TWinControl then
begin
wc := TWinControl(ctl);
for i:=0 to wc.ControlCount-1 do
DisableControls(wc.Controls[i]);
end;
ctl.Enabled := false;
end;
and call
DisableControls(self);
(in this case also the form will be disabled, which you
probably don't want). So I guess you will usually call this
function with a panel or tabsheet...
Take care,
Herre
"Vu Quang Thang" <thangvqATgmail.com> wrote in message
news:44fd...@newsgroups.borland.com...