Setting properties on new components

My problems is about setting componentproperties as runtime.

I have made 2 test components to show my problem, TMyEdit and TMyGroupBox.
TMyEdit.Enable will (in this test) set its background to red.
MyGroupBox.Enable will iterate all components in it and set the Enable property on them.

Here are snips from my code:

  TMyEdit = class(TEdit)
  private
    Function GetEnabled: Boolean;
    Procedure SetEnabled(ABoolean: Boolean);
  protected
  public
  published
    Property Enabled: Boolean Read GetEnabled Write SetEnabled;
  end;

Function TMyEdit.GetEnabled: Boolean;
begin
  Result := Inherited Enabled;
end;

Procedure TMyEdit.SetEnabled(ABoolean: Boolean);
begin
  if ABoolean <> Enabled then
  begin
    if ABoolean then
      Color := clWindow
    else
      Color := clRed;
    Inherited Enabled := ABoolean;
  end;
end;



  TMyGroupBox = class(TGroupBox)
  private
    Function GetEnabled: Boolean;
    Procedure SetEnabled(ABoolean: Boolean);
  protected
  public
  published
    Property Enabled: Boolean Read GetEnabled Write SetEnabled;
  end;

Function TMyGroupBox.GetEnabled: Boolean;
begin
  Result := Inherited Enabled;
end;

Procedure TMyGroupBox.SetEnabled(ABoolean: Boolean);
Var
  i: Integer;
begin
  if ABoolean <> Enabled then
  begin
    for i := 0 to ControlCount-1 do
      Controls[i].Enabled := ABoolean;
    Inherited Enabled := ABoolean;
  end;
end;


What I do is that I put a MyGroupBox on a form and drops a MyEdit in it. Now, if I at runtime change the Enabled value of MyEdit, the background will change accordingly.
If I change Enabled for MyGroupBox, it will not call (Set)Enabled for MyEdit but instead it calls it on TEdit (the parent component).
Now, if I change the For loop to read

    for i := 0 to ControlCount-1 do
      if (Controls[i] is TMyListBox) then
      (Controls[i] As TMyListBox).Enabled := ABoolean
      else
        Controls[i].Enabled := ABoolean;

it will work. But I don't want MyGroupBox to know all possible components that I will drop in it.

Anyone has a clue?
LVL 7
BlackManAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

BlackManAuthor Commented:
Edited text of question
0
vladikaCommented:
Here is Delphi source

procedure TControl.SetEnabled(Value: Boolean);
begin
  if FEnabled <> Value then
  begin
    FEnabled := Value;
    Perform(CM_ENABLEDCHANGED, 0, 0);
  end;
end;

So you can process CM_ENABLEDCHANGED message as

  TMyEdit = class(TEdit)
  private
    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  end;

  TMyGroupBox = class(TGroupBox)
  private
    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  end;


procedure TMyEdit.CMEnabledChanged(var Message: TMessage);
begin
 if Enabled then Color := clWindow else Color := clRed;
end;

procedure TMyGroupBox.CMEnabledChanged(var Message: TMessage);
var I: Integer;
begin
  for I := 0 to ControlCount-1 do
    Controls[I].Enabled := Enabled;
end;


0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
BlackManAuthor Commented:
That one works, but can you explain why MyEdit.Enabled is not called in my component?
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

BlackManAuthor Commented:
Oops, I was to quick to send the other comment :-)
Your code works fine for Enabled but what if it was another property, like one I made myself?
0
vladikaCommented:
The problem is that GetEnabled and SetEnabled in TControl is not virtual.
If it were virtual you simple override it and all.
Suppose exists two class
type
  TClass1 = class
  public
    procedure Print;
  end;

  TClass2 = class(TClass1)
  public
    procedure Print;
  end;

procedure TClass1.Print;
begin
  // print 'Class 111'
end;

procedure TClass2.Print;
begin
  // print 'Class 222'
end;

 and procedure ..
procedure Test(C: TClass1);
begin
  C.Print;
end;

 and you have two variables
var C1: TClass1;
     C2: TClass2;

C1 := TClass1.Create;  // Type of C1 is Class1
C2 := TClass2.Create;  // Type of C2 is Class2

if you call Test(C1) you see 'Class 111'
if you call Test(C2) you as well as see 'Class 111' becouse Print is not virtual

if Print was virtual you see in first case 'Class 111' and 'Class 222' in second case

It is reason.

So, Delphi does not allow you override property Enabled but
notify you about its changing.

If it was another property and Get/Set not virtual and no notify message
I am afraid it is impossible

So, If you write components yourself make Get/Set protected and virtual.


0
BlackManAuthor Commented:
Thanks
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.