Newsgroup: it.comp.lang.delphi
Titolo: Ancora sul componente che monitora una cartella

Eccomi ancora qui... riporto brevemente per completezza il codice del 
componente a cui faccio riferimento:
TMyComp = class (TComponent)
  private
    FPath: String;
    FStrings: TStrings;
    procedure FindFiles;
  protected
    procedure SetPath (Value: String);
    procedure SetStrings (Value: TStrings);
  public
    constructor Create (aOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Path: String read FPath write SetPath;
    property Strings: TStrings read FStrings write SetStrings;
  end;
procedure TMyComp.FindFiles;
var
  aPath: String;
  SearchRec: TSearchRec;
begin
  if DirectoryEsists (FPath) then
    aPath := FPath
  else
    aPath := ExtractFilePath (Application.ExeName) + FPath;
  if aPath[Length (aPath)] <> '\' then
    aPath := aPath + '\';
  FStrings.Clear;
  if FindFirst (aPath + '*.*', faAnyFile, SearchRec) = 0 then
    begin
      repeat
        FStrings.Append (SearchRec.Name);
      until FindNext (SearchRec) <> 0;
      FindClose (SearchRec);
    end;
  (FStrings as TStringList).Sort;
end;
procedure TMyComp.SetPath (Value: String);
begin
  if FPath <> Value then
    begin
      FPath := Value;
      FindFiles;
    end
end;
procedure TMyComp.SetStrings (Value: TStrings);
begin
  { Lascio in bianco per aggirare il problema di readonly }
  { che ho discusso in un altro thread }
end;
constructor TMyComp.Create (AOwner: TComponent);
begin
  inherited Create(AOwner);
  FStrings := TStringList.Create;
  FindFiles;
end;
destructor TMyComp.Destroy;
begin
  FStrings.Free;
  inherited Destroy;
end;
Risolto il problema della proprietà readonly (vedi altro thread), ora mi 
aspetterei che avendo messo una copia di TMyComp in una form, a runtime io 
possa andare a leggere immediatamente la lista di file nella cartella 
corrente... e invece, benchè abbia esplicitamente chiamato FindFiles nel 
costructor, a runtime Strings è vuota.
Preso dallo sconforto, ho provato ad aggiungere al componente un metodo 
Loaded o AfterConstruction in cui richiamavo FindFiles, ma a runtime Strings 
è sempre vuota...
Chiaramente, se intervengo su FPath, innesco un meccanismo che mi aggiorna 
FStrings, ma come faccio ad avere Strings sia già pronta a runtime, qualora 
non debba cambiare FPath?
Si può fare? Se si, dove sbaglio?
Un grazie mai abbastanza grande per il tempo che mi dedicate,
   Stefano 





Puntualizzo una cosa:
so che dichiarando una procedura Initializa public che richiama FindFiles (o 
dichiarando direttamente FindFiles come public) potrei rispolvere il 
problema richiamando nell'OnCreate del mio progetto TMyComp1.Initialize, ma 
c'è un modo per farlo in automatico?
Grazie ancora,
   Stefano 

> Si può fare? Se si, dove sbaglio?
1) dichiari una property boolean come published
Nel metodo che assegna il valore, se metti true, chiami la findfiles, se 
metti false, azzeri la tstringlist;
2) assegni un path di default nel costruttore *prima* di chiamare findfiles
Infine, imho, stai inventando la ruota: hai visto IShellApi?
AS

Ok, do un occhio alle cose che mi hai suggerito...
Cmq immagino ci sia qualcosa che fa quanto esposto meglio e piů in fretta, 
ma quello che ho portato č solo un esempio semplice di una cosa un po' piů 
complicata su cui sto lavorando...
Se avessi messo il listatone originale lunghissimo, qualcuno di sicuro 
m'avrebbe ucciso!
Ciao e ancora grazie,
  Stefano 

 findfiles
Non credo che risolva... nella funzione FindFiles che ho riportato, se FPath 
non č inizializzata, il componente ci mette autonomamente ExtractFilePath 
(Application.ExeName)... Dunque non dovrebbe essere un problema di 
inizializzazione di questo tipo...
Stefano 

non debba cambiare FPath?
Appunto! Quando chiami il costruttore, FPath viene posto a stringa vuota!
Da specifiche, il costruttore azzera tutti i campi.
Quindi FindFiles non trova nessun path da leggere e non riempe un bel
nulla. Dovresti impostare tu un path nel costruttore prima di chiamare
FindFiles. 
Attenzione però che a design time avere un componente che appena posto sul
form si legge un disco da 200GB non è proprio il massimo... l'utente
rischia di aspettare parecchi minuti prima poter fare qualsiasi cosa!
Devi piuttosto chiederti se la lista dei file a design time è necessaria
oppure no - anche perché il contenuto dipenderà da quello che c'è a
run-time...
Luigi D. Sandon - D&amp;D Support Team
--- posted by geoForum on 
http://www.delphiedintorni.it

No no no... calma... che sennò mi perdo...
Quando arriva il suo turno, viene inizializzato il componente, ovvero viene 
avviato il suo costruttore:
constructor TMyComp.Create (AOwner: TComponent);
begin
  inherited Create(AOwner);
  FStrings := TStringList.Create;
  FindFiles;
end;
Viene avviato il costruttore di TComponent da cui il mio componente è erede, 
quindi viene inizializzato FStrings. Non ho esplicitamente espresso FPath := 
'' perchè è ridondante, se lo avessi fatto, non sarebbe cambiato nulla...
Quindi viene richiamato FindFiles, record d'attivazione nello stack ecc. 
ecc., e vediamo cosa succede...
procedure TMyComp.FindFiles;
var
  aPath: String;
  SearchRec: TSearchRec;
begin
  if DirectoryEsists (FPath) then
    aPath := FPath
  else
    aPath := ExtractFilePath (Application.ExeName) + FPath;
  if aPath[Length (aPath)] <> '\' then
    aPath := aPath + '\';
  FStrings.Clear;
  if FindFirst (aPath + '*.*', faAnyFile, SearchRec) = 0 then
    begin
      repeat
        FStrings.Append (SearchRec.Name);
      until FindNext (SearchRec) <> 0;
      FindClose (SearchRec);
    end;
  (FStrings as TStringList).Sort;
end;
Per prima cosa controlla se il valore contenuto in FPath è un valore valido 
per una directory... visto che FPath è nullo, e non è un valore valido, 
viene eseguito l'assegnamento che mette in aPath (una nuova variabile) il 
valore ExtractFilePath (Application.ExeName), ovvero la cartella in cui si 
trova l'eseguibile che si sta eseguendo.
A questo valore va aggiunto FPath, perchè in FPath potrei aver salvato un 
percorso relativo... tuttavia, visto che in questo caso FPath è nullo, in 
aPath rimane il percorso all'eseguibile e basta.
Prima di procedere controllo se in aPath c'è bisogno di aggiungere il 
carattere separatore di cartelle "\": in questo caso non ce n'è bisogno...
Dopodichè, inizia la ricerca dei file nella cartella aPath, che è valida e 
diversa da zero...
Ebbene, a questo punto io mi aspetterei di avere dentro a FStrings tutti i 
file della cartella d'avvio del programma, e invece è vuoto...
Sapete spiegarmi il perchè di questo comportamento?
Stefano 

 ha scritto nel messaggio 
news:aOe8d.15389$eb....@tornado.fastwebnet.it...


 come fare...
[...]
Da' un'occhiata a TComponent.Loaded.
E quota, per favore.
Saluti
Paolo Arosio
--
"La dimostrazione dell'esistenza di specie intelligenti nell'universo e'
che non ci vengono a trovare" [Calvin & Hobbes]

 Da' un'occhiata a TComponent.Loaded.
Qualche messaggio sopra accennavo al fatto che avevo provato questa cosa 
senza successo... se mi dici cosě probabilmente ho commesso qualche altro 
bug... verificherň...
perň perchč se metto un break-point subito all'inizio di questa procedura 
l'esecuzione non mi si ferma mai lě? premo F9, F8, F7 ma non arrivo mai lě 
dentro...
hoi dichiarato cosě:
type
  TMmyComp = class(TComponent)
    [...]
    public Loaded; virtual;
    [...]
  end;
[...]
procedure TMyComp.Loaded;
begin
  inherited Loaded;
  // mio codice qui
end;
[...]
dove sbaglio?
grazie,
   Stefano 


A quel che leggo dall'help, TComponent.Loaded non fa altro che cambiare lo
stato del componente, resettando il flag csLoading. Non credo dovresti
metterlo all'inizio.
In ogni caso, se il campo FPath == '', sei assolutamente certo di quel che
ritorna DirectoryExists(FPath)?
Infine, oltre che l'esecuzione passo-passo, un utile strumento di debug e'
la funzione OutputDebugString(pchar) che scrive nella finestra di log.


Soccia grazie mille!
M'hai aperto gli occhi!
E poi mi faccio piccolopiccolo e mi vergogno perchè mi sa che ho fatto su un 
gran casino per niente perchè mi sa che copiaincollando da create ho 
dichiarato gli altri eventi virtual invece che ovveride... che fesso!
ciao,
  Ste