This is a hack but...
 
type
  TInternalControl = class (TControl);
  TInternalGraphicsObject = class (TGraphicsObject);
 
procedure setObjectColour (obj: TObject; newColour: TColor);
begin
  if obj is TControl then
    TInternalControl (obj).Color := newColour
  else if obj is TGraphicsObject then
    TInternalGraphicsObject (obj).Color := newColour;
end;
The other ways are the interface / typinfo ways as suggested in previous emails.  I would however, implement the interfaces using the adapter pattern instead of using inheritance:
 
type
  IColourable = interface
  // Interface GUID
    procedure SetColour (Value: TColor);
    function GetColour: TColor;
    property Colour: TColor read GetColour write SetColour;
  end;
 
  TColourableControlAdapter = class (TInterfacedObject, IColourable)
  private
    FControl: TControl;
    procedure SetColour (Value: TColor);
    function GetColour: TColor;
   
  public
    constructor Create (AControl: TControl);
  end;
 
  TColourableGraphicsObject = class (TInterfacedObject, IColourable)
  ... similar to TColourableControlAdapter
 
constructor TColourableControlAdapter.Create (AControl: TControl);
begin
  inherited Create;
  FControl := AControl;
end;
 
procedure TColourableControlAdapter.SetColour (Value: TColor);
begin
  // using the hack above...
  TInternalControl (FControl).Color := Value;
end;
 
Then instead of a TList, you use TInterfaceList:
 
var
  list: IInterfaceList;
 
begin
  list := TInterfaceList.Create;
 
To add objects to the list:
 
list.Add (TColourableControlAdapter.Create (MyForm));
list.Add (TColourableGraphicsObject.Create (MyFont));
 
To set the colour:
 
  (list.Items[Index] as IColourable).Colour := newColour;
 
You don't need to free the list or any of the interfaces in the list because as the list goes out of scope it will automatically be freed via reference counting.
 
Dennis.
 
----- Original Message -----
From: "Moretti, Giovanni" <[EMAIL PROTECTED]>
To: "Multiple recipients of list delphi" <[EMAIL PROTECTED]>
Sent: Wednesday, October 23, 2002 6:23 PM
Subject: [DUG]: Polymorphic assignment to Color - How? (sometime it's a Property, sometimes not)

> Hi
>
> I'm building a list of objects that can be coloured and want to be able to get/set their colour.
>
> The object properties are all going to be stored in a Tlist so the types will probably need to be stored along with them. I'm happy to store the Object type (eg Tform ...) along with the reference to the object but I can't see a general way to do this and get/set the color.
>
> ========= ATTEMPT #1 ===========================================
>  
> In the olden days, before properties, I'd have just passed a pointer to the Tcolor value:
>
>    procedure setObjectColour (Color     : ^TColor ;
>                               newColour : TColor);
>      begin
>        Color^ := newColour;
>      end;
>
>   setObjectColour(@Label3.Color, clRed);
>
> I tried this, but it's unpredictable as sometimes an object's color is just a TColor (a glorified integer) but other times it's a property with get/set methods.
>
> ========= ATTEMPT #2 ===========================================
>
> Figuring the run-time type information should be able to handle this, I tried:
>
>   Type  TControlClass = Class of Tcontrol;
>
>   procedure setObjectColour ( obj       : TObject;
>                               whatClass : TControlClass;
>                               newColour : TColor);
>   begin
>     (obj as whatClass).color := newColour;
>                            ^-------------- ERROR - COLOR not declared
> // OR
>
>     whatClass(object).color  := newColour;  
>               ^----------------------------Missing Operator or ;
>   end;
>
>   setObjectColour(Label3, Tlabel, clRed);  // To Recolour something 
>
> But neither will compile without errors.
>
> ========= FINALLY ===========================================
>
> It's not elegant but has the great virtue that it actually works:
>
>   procedure setObjectColour ( obj       : TObject;
>                               newColour : TColor);
>   begin
>     if      (obj is TForm)  then (obj as TForm) .color := newColour
>     else if (obj is TLabel) then (obj as TLabel).color := newColour
>     else if (obj is TFont ) then (obj as TFont) .color := newColour
>     else if (obj is TBrush) then (obj as TBrush).color := newColour
>     else if (obj is TPen)   then (obj as TPen)  .color := newColour
>     else showMessage('setObjectColour: Don''t know how');
>   end;
>
>   setObjectColour(Form1, clRed);
>
> Except this means that adding new types of things will require adding of extra "if .." statements which with polymorphism should be necessary. Unfortunately you can't do the more general:
>
>    (obj as Tcontrol).color := newColour;
>
> As Tcontrol's "color" is protected (and can't be seen this won't compile). Only Tcontrol's descendents expose some way of getting/setting color.
>
> I want to be able to recolour anything that has a colour but there must be a better way than tests for explicit types/classes ...
>
> Any Ideas?
>
> Thanks
> Giovanni
> ========================================================================
> Giovanni Moretti  |  Institute of Information Sciences and Technology
> Senior Lecturer   |  Massey University, Palmerston North, New Zealand
> Computer Science  |  Ph 64-6-3505799x2474 == Fax 64-6-3502259 == ZL2BOI
> ------------------------------------------------------------------------
>
http://www-ist.massey.ac.nz/moretti        mailto:[EMAIL PROTECTED]
> ---------------------------------------------------------------------------
>     New Zealand Delphi Users group - Delphi List -
[EMAIL PROTECTED]
>                   Website: http://www.delphi.org.nz
> To UnSub, send email to: [EMAIL PROTECTED]
> with body of "unsubscribe delphi"
> Web Archive at:
http://www.mail-archive.com/delphi%40delphi.org.nz/
>

Reply via email to