Newsgroup: it.comp.lang.delphi
Titolo: TRinoStaticText :)

Morde, ho preferito discutere prima in privato con Rino… Troppi post.
Ora che abbiamo finito postiamo la soluzione… :)
Rispondo alla richiesta fatta da Rino qualche giorno fa circa la
creazione di un componente.
A Rino serviva un componente ereditato da TstaticText con una proprietà
in più.
Una proprietà che rappresentasse una lista di riferimenti a n controlli
presenti sulla form owner del componente stesso.
L’ostacolo di Rino e stato principalmente il “come gestire la cosa con
un Property Editor custom”.
In sintesi il risultato doveva essere:
Rino mette il Componente TRinoStaticText sulla form. Nell’Object
Inspector seleziona la proprietà StoredControls ed appare un editor.
All’interno di tale editor Rino vuole riempire una ListBox i cui
elementi siano dei controlli presenti sulla form. Tali controlli non li
inserisce a mano ma spostati da un altro box che li contiene tutti
(ovviamente sta anch’esso sull’editor).
Dunque, la dichiarazione del componente si presenta in questo modo:
  TRinoStaticText = class(TStaticText)
  private
    { Private declarations }
    FStoredControls: TStrings;
    procedure SetStoredControls(const Value: TStrings);
    procedure UpdateControlsList(FromForm: Boolean);
  protected
    { Protected declarations }
    procedure Loaded; override;
    procedure WriteState(Writer: TWriter); override;
    procedure Notification(AComponent: TComponent; Operation:
TOperation); override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SetNotification;
  published
    { Published declarations }
    property StoredControls: TStrings read FStoredControls write
SetStoredControls;
  end;
Create e Destroy…
constructor TRinoStaticText.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FStoredControls := TStringList.Create;
end;
destructor TRinoStaticText.Destroy;
begin
  FreeAndNil(FStoredControls);
  inherited;
end;
FstoredControls è di tipo TStrings. Tale classe gestisce items composti
da una stringa più un eventuale puntatore.
È il componente adatto in quanto per ogni controllo che andremo ad
aggiungere alla nostra lista ci serve tenere traccia sia del suo nome
(per il salvataggio nel .dfm) che del suo indirizzo di memoria (per
localizzarlo a runtime)…
procedure TRinoStaticText.Loaded;
begin
  inherited Loaded; // comportamento di default
  UpdateControlsList(True);
end;
procedure TRinoStaticText.WriteState(Writer: TWriter);
begin
  UpdateControlsList(False);
  inherited WriteState(Writer); // comportamento di default
end;
procedure TRinoStaticText.UpdateControlsList(FromForm: Boolean);
var
  I: Integer;
  Component: TComponent;
begin
  if (FStoredControls = nil) or (Owner = nil) then
    Exit;
  for I := FStoredControls.Count - 1 downto 0 do
  begin
    if FromForm then
    begin
      Component := Owner.FindComponent(FStoredControls[I]);
      if Component = nil then
        FStoredControls.Delete(I)
      else
        FStoredControls.Objects[I] := Component;
    end
    else
    begin
      Component := TComponent(FStoredControls.Objects[I]);
      if Component <> nil then
        FStoredControls[I] := Component.Name
      else
        FStoredControls.Delete(I);
    end;
  end;
end;
Supponiamo che la lista contenga già le info su alcuni controlli
(ovviamente solo i nome) e che è già salvata all’interno del dfm. Appare
nel seguente modo:
  object RinoStaticText1: TRinoStaticText
    Left = 136
    Top = 48
    Width = 80
    Height = 17
    Caption = 'RinoStaticText1'
    TabOrder = 0
    StoredControls.Strings = (
      'CheckBox1'
      'Edit2'
      'RinoStaticText2')
  end
Ovviamente, quando viene creato il componente e lette le proprie info
sul dfm StoredControls conterrà la sola lista dei nomi. Mancano i
puntatori ai relativi controlli.
L’override del metodo Loaded serve proprio a questo: dopo aver
recuperato la lista dei nomi dal dfm associo ad ogni nome il puntatore
del relativo controllo…
      Component := Owner.FindComponent(FStoredControls[I]);
      if Component = nil then
        FStoredControls.Delete(I)
      else
        FStoredControls.Objects[I] := Component;
Quando invece vengono salvate le info nel dfm mi assicuro che il
controllo puntato dall’elemento n di StoredControls abbia associato il
giusto nome (l’utente potrebbe cambiarlo). Inoltre se tale controllo non
esiste più cancello l’elemento dalla lista.
      Component := TComponent(FStoredControls.Objects[I]);
      if Component <> nil then
        FStoredControls[I] := Component.Name
      else
        FStoredControls.Delete(I);
Ora, supponiamo che dopo aver aggiunto alla lista un riferimento a un
controllo cancelliamo tale controllo. Sarebbe comodo cancellare anche
automaticamente il suo riferimento da FStoredControls del controllo
TrinoStaticText.
Per questo ci viene incontro il metoto protetto Notification che ci
avvisa della creazione o distruzione di componenti all’interno di una
form.
 
 procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
procedure TRinoStaticText.Notification(AComponent: TComponent;
  Operation: TOperation);
var
  I: Integer;
  Component: TComponent;
begin
  // If a component is removed the reference will be deleted
  inherited Notification(AComponent, Operation);
  if not (csDestroying in ComponentState) and (Operation = opRemove) and
    (FStoredControls <> nil) then
    for I := FStoredControls.Count - 1 downto 0 do
    begin
      Component := TComponent(FStoredControls.Objects[I]);
      if Component = AComponent then
        FStoredControls.Delete(I); 
    end;
end;
SetNotification è il metodo di scrittura per la proprietà StoredControls
che farà scatenare Notification
procedure TRinoStaticText.SetNotification;
var
  I: Integer;
  Component: TComponent;
begin
  if Assigned(FStoredControls) then
    for I := FStoredControls.Count - 1 downto 0 do
    begin
      Component := TComponent(FStoredControls.Objects[I]);
      if Component <> nil then
        Component.FreeNotification(Self);
    end;
end;
Se volete scaricate pure da
http://www.salexander.supereva.it/Rino%20components.zip
Acqua
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Ora che abbiamo finito postiamo la soluzione… :)
E vi ringrazio per questo!
Ciao Ale, e salutami RINO! (anche il mio babbo si chiama cosi', solo che lui
non mi parla mai di delphi!!! ;)
^_____^
-- 
Morde. 
(
mo...@despammed.com
)

 Acqua
Non si scarica, scarica solo uno zip da 4kb illeggibile
Grazie

L'ho riaggirnato... riprova pure:
http://www.salexander.supereva.it/Rino%20components.zip
http://www.salexander.supereva.it/Rino%20Components.zip
http://www.salexander.supereva.it/rinocomp.zip
--
Acqua

 non mi parla mai di delphi!!! ;)
LOL!!!
--
Acqua

 L'ho riaggirnato... riprova pure:
Era un problema del mio browser ie 5.5, sul pc di un collega con il 6 sono
riuscito a scaricare.
Grazie

Ragazzi il componente va una bomba....ma non ne avevo DUBBI!!!
Se tutti fossero così altruisti bè.........(inutile continuare).
Cmq ringranzio ancora Acqua per la sua disponibilità.
A buon rendere amico!!!
Ciao
Rino.
p.s. grazie al NG che rende possibile tutto questo!!!
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/