Recent

Author Topic: access element's in form  (Read 6057 times)

ali-libre

  • New Member
  • *
  • Posts: 40
access element's in form
« on: March 30, 2017, 03:47:30 pm »
how to access all (ie:)tlist create constly in the form?
like:
Code: Pascal  [Select][+][-]
  1. with List* do
  2.   font.color := clclack;
  3. end;
i must be mention the object's not created in an array.
« Last Edit: March 30, 2017, 03:53:56 pm by ali-libre »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: access element's in form
« Reply #1 on: March 30, 2017, 10:10:07 pm »
I am not entirely clear what you are asking, but it may be you are looking for a procedure something like this:
Code: Pascal  [Select][+][-]
  1. implementation
  2.  
  3. uses typinfo, Controls;
  4.  
  5. procedure ChangeFontColorOf(aForm: TForm; const aControlName: string;
  6.   aNewColor: TColor);
  7. var
  8.   c: TControl;
  9.   i: Integer;
  10. begin
  11.   if Assigned(aForm) then begin
  12.     for i:=0 to aForm.ControlCount-1 do begin
  13.       c:=aForm.Controls[i];
  14.       if c.ClassNameIs(aControlName) and IsPublishedProp(c, 'Font') then
  15.         c.Font.Color:=aNewColor;
  16.     end;
  17.   end;
  18. end;

To change the Font.Color of all buttons on your form you might call it like this:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   ChangeFontColorOf(Self, 'TButton', clBlue);
  4. end;

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1572
    • Lebeau Software
Re: access element's in form
« Reply #2 on: March 31, 2017, 06:44:44 am »
Code: [Select]
c.Font.Color:=aNewColor;

The Font property is protected in TControl, you can't access it directly without a type-cast:

Code: [Select]
type
  TControlAccess = class(TControl)
  end;

procedure ChangeFontColorOf(aForm: TForm; const aControlName: string; aNewColor: TColor);
var
  c: TControl;
  i: Integer;
begin
  if Assigned(aForm) then begin
    for i:=0 to aForm.ControlCount-1 do begin
      c:=aForm.Controls[i];
      if c.ClassNameIs(aControlName) and IsPublishedProp(c, 'Font') then
        TControlAccess(c).Font.Color:=aNewColor;
    end;
  end;
end;

Or, use RTTI (since you are using it anyway):

Code: [Select]
procedure ChangeFontColorOf(aForm: TForm; const aControlName: string; aNewColor: TColor);
var
  c: TControl;
  i: Integer;
begin
  if Assigned(aForm) then begin
    for i:=0 to aForm.ControlCount-1 do begin
      c:=aForm.Controls[i];
      if c.ClassNameIs(aControlName) and IsPublishedProp(c, 'Font') then
        TFont(GetObjectProp(c, 'Font')).Color:=aNewColor;
    end;
  end;
end;

Either way, note that the Controls[] list only contains *immediate child controls*.  If you have nested controls more than 1 level deep and want to change their colors, you will have to change the aForm parameter to a TWinControl and then drill down the parent/child hierarchy calling ChangeFontColorOf() recursively:

Code: [Select]
type
  TControlAccess = class(TControl)
  end;

procedure ChangeFontColorOf(aParent: TWinControl; const aControlName: string; aNewColor: TColor);
var
  c: TControl;
  i: Integer;
begin
  if Assigned(aParent) then begin
    for i:=0 to aParent.ControlCount-1 do begin
      c:=aParent.Controls[i];
      if c.ClassNameIs(aControlName) and IsPublishedProp(c, 'Font') then
        TControlAccess(c).Font.Color:=aNewColor;
      if c is TWinControl then
        ChangeFontColorOf(TWinControl(c), aControlName, aNewColor);
    end;
  end;
end;

Otherwise, if you are just interested in controls created at design-time, use the form's Components[] list instead of the Controls[] list.
« Last Edit: March 31, 2017, 06:47:10 am by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: access element's in form
« Reply #3 on: March 31, 2017, 11:42:43 am »
@Remy
Your point about accessing nested controls is well made. Thank you demonstrating how to extend to nested controls.

Although Font is a protected property of TControl, the code I showed does work without need of
a cracker class (at least on Linux where I tested it), since the c.Font property is accessed only after a  check to make sure c has a published Font property.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1572
    • Lebeau Software
Re: access element's in form
« Reply #4 on: March 31, 2017, 04:39:01 pm »
Although Font is a protected property of TControl, the code I showed does work without need of
a cracker class (at least on Linux where I tested it), since the c.Font property is accessed only after a  check to make sure c has a published Font property.

You are accessing the Font property through a pointer to TControl itself.  The property is NOT publicly accessible in TControl itself. Regardless of whether a derived class publishes the property, you should NOT be able to access the property from TControl itself. Your code is not in the same unit that declares TControl itself, so you don't have direct access to TControl's non-public members. The code should NOT have compiled as you showed it. If it is, that would be a compiler bug.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: access element's in form
« Reply #5 on: March 31, 2017, 06:23:46 pm »
I can't disagree with the theory you present. Since the code I showed compiles and runs on both Linux and Windows, and changes the font colour of any top-level control of the specified control class (though not for nested sub controls), I presume this is a (minor) FPC bug, for not respecting the protected visibility of TControl.Font.

I double checked.

TControl.Font is a public property in the LCL. I don't know about the VCL.
So no FPC bug.
« Last Edit: March 31, 2017, 06:31:06 pm by howardpc »

ASerge

  • Hero Member
  • *****
  • Posts: 2475
Re: access element's in form
« Reply #6 on: March 31, 2017, 07:21:10 pm »
TControl.Font is a public property in the LCL. I don't know about the VCL.
In VCL it is protected.
Your code is working, but I am confused by the following
Code: Pascal  [Select][+][-]
  1. const aControlName: string
+
Code: Pascal  [Select][+][-]
  1. c.ClassNameIs(aControlName)
I think either that
Code: Pascal  [Select][+][-]
  1. const AControlClassName: string
or so
Code: Pascal  [Select][+][-]
  1. SameText(c.Name, aControlName)

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: access element's in form
« Reply #7 on: March 31, 2017, 08:12:36 pm »
@ASerge
You're right. I chose the parameter name carelessly, and your suggestion is much better, and accurately self-descriptive.
I tell others to improve their naming, and then pick a confusing name myself.

avra

  • Hero Member
  • *****
  • Posts: 2582
    • Additional info
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

ali-libre

  • New Member
  • *
  • Posts: 40
Re: access element's in form
« Reply #9 on: April 01, 2017, 11:58:33 am »
Yes.
I was searched for wrong key-word...!

Thank's

 

TinyPortal © 2005-2018