Hrajeme si na Explorer - 5. díl - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



Delphi

Hrajeme si na Explorer - 5. díl

12. října 2001, 00.00 | V tomto dílu se podíváme na třídění výpisu souborů podle velikosti, typu souboru a data poslední změny.

Dnes do programu přidáme možnosti třídění souborů podle zbylých kriterií.

Třídění

Třídění výpisu podle velikosti, typu souboru a data poslední změny implementujeme v proceduře TForm1.FileViewCompare. Připomínám, že tato procedura je zavolána při porovnávání dvou položek seznamu souborů a rozhoduje, která z nich je v seznamu dřív. Výsledek je předán pomocí výstupního parametru Compare (blíže viz minulý díl seriálu). Tady je klíčová část kódu procedury:

case SortCriteria of
  scName:
    if DirectoryExists(FileName1)and(FileExists(FileName2)) then
      Compare := -1
    else if FileExists(FileName1)and(DirectoryExists(FileName2)) then
      Compare := 1
    else
      Compare := AnsiCompareText(FileName1, FileName2);
  scSize:
    if DirectoryExists(FileName1)and(FileExists(FileName2)) then
      Compare := -1
    else if FileExists(FileName1)and(DirectoryExists(FileName2)) then
      Compare := 1
    else
      if PSearchRec(Item1.Data)^.Size < PSearchRec(Item2.Data)^.Size then
        Compare := -1
      else
        Compare := 1;
  scType:
    Compare := AnsiCompareText(Item1.SubItems[1], Item2.SubItems[1]);
  scDate:
    if DirectoryExists(FileName1)and(FileExists(FileName2)) then
      Compare := -1
    else if FileExists(FileName1)and(DirectoryExists(FileName2)) then
      Compare := 1
    else
      if Cardinal(PSearchRec(Item1.Data)^.Time)
       > Cardinal(PSearchRec(Item2.Data)^.Time) then
        Compare := -1
      else
        Compare := 1;
end;

Kód potřebuje vysvětlení: O třídění podle jména jsme se bavili v minulém dílu seriálu, tady není co řešit. U třídění podle velikosti je aplikována podobná logika jako u třídění podle jména - je-li jedna z porovnávaných položek adresář, automaticky se posouvá dopředu; pouze jsou-li obě položky soubory (nebo obě adresáře, prostě jsou-li stejného typu), rozhoduje se pomocí porovnávání jejich velikosti. Tu získáme ze struktury TSearchRec (obsahuje základní data o každém souboru), na kterou ukazuje vlastnost Data příslušné položky (připomínám, že tuto vlastnost jsme nastavovali při vytváření seznamu souborů).

Třídění podle typu obstará funkce AnsiCompareText, která vrací hodnotu ve stejném formátu, jako ji potřebujeme zapsat do Compare. V tomto případě si povšimněte vynechání logiky "adresáře nejdřív".

Poslední třídění je podle data. Kód je velmi podobný třídění podle velikosti (o obou se porovnávají dvě čísla, zjištěná ze struktury TSearchRec). Rozdíly jsou dva:

  1. Nejnovější soubory (tedy ty s největší hodnotou položky TSearchRec.Time) patří na začátek seznamu. U velikostí to bylo naopak - na začátek jsme umisťovali nejmenší soubory. Proto je nutné v podmínce obrátit znaménko.
  2. Oba časy je nutné před porovnáváním převést na typ Cardinal, což je 32bitové celé číslo bez znaménka. U času souboru by totiž použití Integeru (tedy celočíselného typu se znaménkem) vedlo k tomu, že při porovnávání by některé položky mohly být přeházené.
Optimalizace

Vypadá to, že kód je v pořádku a funkční, ale já zde vidím prostor pro malou optimalizaci. Při porovnávání velikostí a časů souborů totiž není potřeba používat podmínku, stačí obě porovnávané hodnoty od sebe odečíst. Výsledkem bude buď kladné nebo záporné číslo, případně 0, pokud budou porovnávané hodnoty stejné. Toto číslo můžeme rovnou použít jako hodnotu proměnné Compare. Upravené části kódu budou vypadat takhle:

scSize:
  if DirectoryExists(FileName1)and(FileExists(FileName2)) then
    Compare := -1
  else if FileExists(FileName1)and(DirectoryExists(FileName2)) then
    Compare := 1
  else
    Compare := PSearchRec(Item1.Data)^.Size
      - PSearchRec(Item2.Data)^.Size;

...

scDate:
  if DirectoryExists(FileName1)and(FileExists(FileName2)) then
    Compare := -1
  else if FileExists(FileName1)and(DirectoryExists(FileName2)) then
    Compare := 1
  else
    Compare := Cardinal(PSearchRec(Item2.Data)^.Time)
      - Cardinal(PSearchRec(Item1.Data)^.Time);

V tomto případě není optimalizace nijak klíčová (na rychlosti porovnání nám tady zas tak nezáleží), ale v některých případech se podobné "triky" hodí, protože ušetří drahocenný čas při výpočtech.

Drobná úprava

Na závěr článku ještě opravíme jednu drobnou chybičku v napodobování Exploreru. V něm se totiž u složek nezobrazuje jejich velikost, zatímco v našem programu se objevuje velikost 1 kB. Chybu odstraníme záměnou tohoto řádku v proceduře TForm1.ShowBtnClick

SubItems.Add(IntToFileSize(SearchRec.Size));

za následující podmínku:

if DirectoryExists(DirEdit.Text + '\' + SearchRec.Name) then
  SubItems.Add('')
else
  SubItems.Add(IntToFileSize(SearchRec.Size));

Význam kódu je snad jasný, prostě od sebe odlišíme případy souborů a adresářů - a velikost vypíšeme pouze u souborů.

Příště

Třídění podle jednotlivých kritérií máme tedy hotové. Příště se podíváme na to, jak soubory spouštět v asociované aplikaci, doděláme možnost výběru více souborů a procházení adresáři.

Aplikaci ve stavu vývoje po dnešním článku si můžete stáhnout zde.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Delphi  

 » Rubriky  » Windows  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: