-
V tΘto kapitole se budeme zab²vat postupn²m v²vojem aplikace jednoduchΘho
sprßvce soubor∙. V²voj naÜi aplikace budeme provßd∞t v t∞chto krocφch:
Navrhneme formulß° sprßvce soubor∙, propojφme ovladaΦe (aplikace pou₧φvß
t°i r∙znΘ ovladaΦe k zobrazenφ p°φpustn²ch diskov²ch jednotek, adresß°∙
a soubor∙), vytvo°φme vlastnφ zobrazovacφ ovladaΦ, zajistφme prßci se soubory
a vytvo°φme alternativnφ zp∙sob prßce se soubory pomocφ myÜi. Nejprve provedeme
nßvrh formulß°e aplikace sprßvce soubor∙. ZaΦneme vytvo°enφm novΘho projektu.
Pou₧itφm Inspektora objekt∙ nastavφme nßsledujφcφ vlastnosti pro hlavnφ
formulß° projektu: Caption nastavφme na Sprßvce soubor∙,
Name
na FMForm a Position na poDefault. Nynφ p°idßme na
formulß° ovladaΦe. Proto₧e umφst∞nφ ka₧dΘho z nich zßvisφ na umφst∞nφ ostatnφch
je nutno jejich umφst∞nφ a nastavenφ jejich vlastnostφ zadßvat v po°adφ
uvedenΘm v nßsledujφcφ tabulce. Komponenty DirectoryPanel a FilePanel
jsou umφst∞ny na StatusBar:
Komponenta |
Vlastnost |
Hodnota |
Panel |
Align |
alBottom |
|
Caption |
nechßme prßzdn² |
|
Name |
StatusBar |
|
BevelOuter |
bvNone |
Panel |
Align |
alLeft |
|
Caption |
nechßme prßzdn² |
|
Name |
DirectoryPanel |
|
BevelInner |
bvLowered |
|
BevelWidth |
2 |
Panel |
Align |
alClient |
|
Caption |
nechßme prßzdn² |
|
Name |
FilePanel |
|
BevelInner |
bvLowered |
|
BevelWidth |
2 |
TabSet |
Align |
alBottom |
|
Name |
DriveTabSet |
CDirectoryOutline |
Name |
DirectoryOutline |
|
Align |
alLeft |
FileListBox |
Align |
alClient |
|
Name |
FileList |
|
ShowGlyphs |
true |
Kdy₧ mßme p°idßny vÜechny komponenty a nastaveny jejich vlastnosti,
je vhodnΘ projekt ulo₧it. Unit1 ulo₧φme pod jmΘnem FMXWin
a
Project1 pod FilManEx. K projektu dßle p°idßme nßsledujφcφ
programovou jednotku (nazveme ji FMXUtils). Obsahuje r∙znΘ pomocnΘ
funkce pro prßci se soubory (prostudujte si je a zjist∞te co a jak d∞lajφ).
Jsou zde takΘ pou₧ity deklarace t°φd v²jimek. Nejprve je uveden hlaviΦkov²
soubor a nßsleduje jeho programovß jednotka:
#ifndef FmxUtilsHPP
#define FmxUtilsHPP
#include <consts.hpp>
#include <Classes.hpp>
#include <Windows.hpp>
#include <SysUtils.hpp>
#include <System.hpp>
class __declspec(delphiclass)
EInvalidDest;
class __declspec(pascalimplementation)
EInvalidDest:public EStreamError
{
typedef EStreamError
inherited;
public:
__fastcall
EInvalidDest(const AnsiString Msg) : EStreamError(Msg) { }
__fastcall
EInvalidDest(const AnsiString Msg, const TVarRec *Args,
const int Args_Size) : EStreamError(Msg, Args, Args_Size) { }
__fastcall
EInvalidDest(int Ident) : EStreamError(Ident) { }
__fastcall
EInvalidDest(int Ident, const TVarRec *Args,
const int Args_Size) : EStreamError(Ident, Args, Args_Size) { }
__fastcall
EInvalidDest(const AnsiString Msg, int AHelpContext) :
EStreamError(Msg, AHelpContext) { }
__fastcall
EInvalidDest(const AnsiString Msg, const TVarRec *Args,
const int Args_Size, int AHelpContext) : EStreamError(Msg, Args,
Args_Size, AHelpContext) { }
__fastcall
EInvalidDest(int Ident, int AHelpContext) :
EStreamError(Ident, AHelpContext) { }
__fastcall
EInvalidDest(int Ident, const TVarRec *Args,
const int Args_Size, int AHelpContext) : EStreamError(Ident,
Args, Args_Size, AHelpContext) { }
public:
__fastcall
virtual ~EInvalidDest(void) { }
};
class EFCantMove
: public EStreamError
{
typedef EStreamError
inherited;
public:
__fastcall
EFCantMove(const AnsiString Msg) : EStreamError(Msg) { }
__fastcall
EFCantMove(const AnsiString Msg, const TVarRec *Args,
const int Args_Size) : EStreamError(Msg, Args, Args_Size) { }
__fastcall
EFCantMove(int Ident) : EStreamError(Ident) { }
__fastcall
EFCantMove(int Ident, const TVarRec *Args,
const int Args_Size) : EStreamError(Ident, Args, Args_Size) { }
__fastcall
EFCantMove(const AnsiString Msg, int AHelpContext) :
EStreamError(Msg, AHelpContext) { }
__fastcall
EFCantMove(const AnsiString Msg, const TVarRec *Args,
const int Args_Size, int AHelpContext) : EStreamError(Msg, Args,
Args_Size, AHelpContext) { }
__fastcall
EFCantMove(int Ident, int AHelpContext) :
EStreamError(Ident, AHelpContext) { }
__fastcall
EFCantMove(int Ident, const TVarRec *Args,
const int Args_Size, int AHelpContext) : EStreamError(Ident,
Args, Args_Size, AHelpContext) { }
public:
__fastcall
virtual ~EFCantMove(void) { }
};
extern void __fastcall
CopyFile(const AnsiString FileName,
const AnsiString
DestName);
extern void __fastcall
MoveFile(const AnsiString FileName,
const AnsiString
DestName);
extern long __fastcall
GetFileSize(const AnsiString FileName);
extern TDateTime
__fastcall FileDateTime(const AnsiString FileName);
extern bool __fastcall
HasAttr(const AnsiString FileName,
unsigned short
Attr);
extern int __fastcall
ExecuteFile(const AnsiString FileName,
const AnsiString
Params, const AnsiString DefaultDir, int ShowCmd);
#endif
#include <vcl.h>
#pragma hdrstop
#include <shellapi.h>
#include <stdio.h>
#include "FmxUtils.h"
TDateTime __fastcall
FileDateTime(const AnsiString FileName)
{
return (FileDateToDateTime(FileAge(FileName)));
}
long __fastcall GetFileSize(const
AnsiString FileName)
{
TSearchRec
SearchRec;
if(FindFirst(ExpandFileName(FileName),
faAnyFile, SearchRec)==0)
return SearchRec.Size;
else
return -1;
}
void __fastcall MoveFile(const
AnsiString FileName,
const AnsiString
DestName)
{
AnsiString
Destination;
char FName[255];
bool ckmove;
Destination=ExpandFileName(DestName);
GetFileTitle(FileName.c_str(),FName,255);
if(HasAttr(FileName,
faReadOnly)) {
char buffer[255];
sprintf(buffer, "Error: Can not move the file '%s'.",
FileName.c_str());
throw EFCantMove(buffer);
}
if (HasAttr(Destination,faDirectory))
Destination=Destination+AnsiString(FName);
ckmove= MoveFile(FileName.c_str(),
Destination.c_str());
if(!ckmove)
ShowMessage("Please give the destination filename");
}
void __fastcall CopyFile(AnsiString
FileName,AnsiString DestName)
{
bool
ckcopy;
AnsiString
Destination;
char
FName[255];
GetFileTitle(FileName.c_str(),FName,255);
Destination
= ExpandFileName(DestName);
if(HasAttr(Destination,faDirectory))
Destination=Destination+FName;
ckcopy= CopyFile(FileName.c_str(),Destination.c_str(),false);
if(!ckcopy)
ShowMessage("Please give the destination filename");
}
bool __fastcall HasAttr(const
AnsiString FileName,
const unsigned
short Attr)
{
int attribtest;
attribtest=FileGetAttr(FileName);
if(attribtest
& Attr)
return true;
else
return false;
}
int __fastcall ExecuteFile(const
AnsiString FileName,
const AnsiString
Params, const AnsiString DefaultDir, int ShowCmd)
{
char zFileName[79],
zParams[79], zDir[79];
return (int)
ShellExecute(Application->MainForm->Handle, NULL,
strcpy(zFileName, FileName.c_str()),
strcpy(zParams, Params.c_str()),
strcpy(zDir, DefaultDir.c_str()), ShowCmd);
}
K naÜemu formulß°i p°idßme i nabφdku. Na formulß° p°idßme komponentu
MainMenu
a pomocφ Nßvrhß°e nabφdky vytvo°φme nabφdku podle nßsledujφcφ tabulky (jsou
zde uvedeny i zkracovacφ klßvesy):
&File
&Open
&Move...
F7
&Copy...
F8
&Delete...
Del
&Rename...
&Properties...
------------
&Exit
Nynφ ji₧ m∙₧eme vytvo°it obsluhu udßlosti OnClick pro volbu
File
| Exit, kterß uzavφrß hlavnφ formulß° aplikace. Vytvo°te ji sami.
-
Po p°idßnφ komponenty TabSet na formulß°, se m∙₧eme zab²vat zprovozn∞nφm
tohoto ovladaΦe. Tato komponenta vytvß°φ zßlo₧ky pro ka₧d² prvek v jeho
seznamu zßlo₧ek v zßvislosti na vlastnosti Tabs. Implicitn∞ tento
seznam je prßzdn². Seznam sice m∙₧eme editovat b∞hem nßvrhu, ale budeme
jej vytvß°et a₧ p°i b∞hu aplikace. Po zprovozn∞nφ tohoto ovladaΦe jej musφme
propojit s ovladaΦem DirectoryOutline a nßsledn∞ s FileList.
API Windows poskytuje funkci GetDriveType, kterß vracφ informaci
o typu specifikovanΘ jednotky. K urΦenφ zda jednotka je p°φpustnß, p°edßme
nulou ukonΦen² °et∞zec obsahujφcφ ko°enov² adresß° jednotky, funkci GetDriveType.
Vrßcenß hodnota indikuje typ jednotky: hodnota v∞tÜφ ne₧ 1 indikuje p°φpustnou
jednotku; jinß hodnota indikuje nep°φpustnou jednotku. Nßsledujφcφ k≤d
tvo°φ obsluhu udßlosti OnCreate formulß°e a slou₧φ k vytvo°enφ seznamu
zßlo₧ek p°i vytvo°enφ formulß°e. Seznam zßlo₧ek obsahuje p°φpustnΘ jednotky
v systΘmu.
static char * Drive_Letter[]={"a:\\","b:\\","c:\\","d:\\","e:\\","f:\\",
"g:\\","h:\\","i:\\","j:\\","k:\\","l:\\","m:\\","n:\\","o:\\","p:\\",
"q:\\","r:\\","s:\\","t:\\","u:\\","v:\\","w:\\","x:\\","y:\\","z:\\"};
int AddedIndex;
for(int x =0; x <=
25; x++ ) {
if(GetDriveType(Drive_Letter[x])
> 1) {
AddedIndex=DriveTabSet->Tabs->Add(String(Drive_Letter[x]));
if (toupper(*Drive_Letter[x]) == FileList->Drive)
DriveTabSet->TabIndex = AddedIndex;
}
}
Tato obsluha vlo₧φ pφsmena p°φpustn²ch jednotek na zßlo₧ky. Pozd∞ji
se jeÜt∞ budeme zab²vat zobrazenφm typu jednotky. Nynφ, kdy₧ mßme ovladaΦe
reprezentujφcφ diskovΘ jednotky, adresß°e a soubory, je nutno je propojit.
Kdy₧ zvolφme jinou diskovou jednotku, chceme zobrazit jejφ adresß°ovou
strukturu a seznam soubor∙ vybranΘho adresß°e. K propojenφ ovladaΦ∙, musφme
vytvo°it obsluhy udßlostφ reagujφcφ na v²b∞r zßlo₧ky a zm∞nu adresß°e.
Kdy₧ u₧ivatel kliknutφm (nebo pomocφ klßvesnice) vybere zßlo₧ku komponenty
TabSet,
komponenta generuje udßlost OnClick. V naÜem p°φpad∞ TabSet
obsahuje zßlo₧ky pro p°φpustnΘ diskovΘ jednotky a kliknutφ na n∞kterΘ zßlo₧ce
znamenß zm∞nu jednotky. Vytvo°φme tedy nßsledujφcφ obsluhu udßlosti
OnClick
pro komponentu nazvanou DriveTabSet, kterß nastavφ vlastnost Drive
v ovladaΦi DirectoryOutline na prvnφ pφsmeno pou₧itΘ zßlo₧ky:
DirectoryOutline->Drive=
*((DriveTabSet->Tabs->Strings
[DriveTabSet->TabIndex]).c_str());
Jestli₧e nynφ vybereme zßlo₧ku diskovΘ jednotky, pak DirectoryOutline
zobrazφ adresß°ovou strukturu specifikovanΘ jednotky. Kdy₧ u₧ivatel vybere
prvek v komponent∞ DirectoryOutline (kliknutφm nebo pomocφ kurzorov²ch
klßves), pak komponenta generuje udßlost OnClick. Mnohem praktiΦt∞jÜφ
je ale vyu₧φvat udßlost OnChange, kterß indikuje, ₧e n∞co v komponent∞
DirectoryOutline
bylo zm∞n∞no. Reakci na tuto udßlost m∙₧eme vyu₧φt k aktualizaci seznamu
soubor∙. Nßsledujφcφ k≤d aktualizuje jak seznam soubor∙ tak i stavov² °ßdek
a to v₧dy p°i zm∞n∞ adresß°e:
FileList->Directory
= DirectoryOutline->Directory;
DirectoryPanel->Caption=DirectoryOutline->Directory;
JakΘkoli zm∞ny v adresß°ovΘm stromu se projevφ jednak zobrazenφm seznamu
soubor∙ vybranΘho adresß°e a v²pisem adresß°ovΘ cesty k aktußlnφmu adresß°i
na panelu stavovΘho °ßdku. Kdy₧ u₧ivatel klikne na prvek v seznamu soubor∙,
pak okno seznamu generuje udßlost OnChange. V naÜem p°φpad∞ vyu₧ijeme
tuto udßlost k zobrazenφ informacφ o vybranΘm souboru (na druhΘm panelu
stavovΘho °ßdku). Vytvo°φme tedy tuto obsluhu udßlosti:
AnsiString TheFileName;
if(FileList->ItemIndex>=0){
char buffer[255];
TheFileName
=FileList->Items->Strings[FileList->ItemIndex];
sprintf(buffer,"%s
%d bytes",TheFileName,GetFileSize(TheFileName));
FilePanel->Caption
= buffer;
if (GetFileAttributes(TheFileName.c_str())
& FILE_ATTRIBUTE_DIRECTORY)
FileSelected = false;
else
FileSelected = true;
}
else {
FilePanel->Caption="";
FileSelected
= false;
}
Funkce GetFileSize je deklarovßna v programovΘ jednotce FMXUnit.
Do soukromΘ Φßsti deklarace formulß°e umφstφme:
bool FileSelected;
Zm∞na vybranΘho souboru v seznamu soubor∙ zp∙sobφ v²pis jmΘna a velikosti
vybranΘho souboru na stavovΘm °ßdku.
-
Ka₧d² ovladaΦ, kter² mß vlastnφ variantu zobrazovßnφ mß vlastnost nazvanou
Style.
V naÜi aplikaci nastavφme vlastnost Style komponenty
TabSet
na tsOwnerDraw. Ka₧d² seznam °et∞zc∙ C++ Builderu m∙₧e obsahovat
seznam objekt∙. Do sprßvce soubor∙ p°idßme bitovΘ mapy indikujφcφ typ diskovΘ
jednotky. Po₧adovanΘ obrßzky bitov²ch map musφme p°idat k aplikaci, a potom
tyto obrßzky lze umφs¥ovat do seznamu °et∞zc∙. OvladaΦ Image je
ovladaΦ obsahujφcφ grafick² obrßzek, nap°. bitovou mapu. Komponentu
Image
lze pou₧φt k zobrazenφ grafickΘho obrßzku na formulß°i, ale m∙₧eme ji takΘ
pou₧φt pro dr₧enφ skryt²ch obrßzk∙, kterΘ pak v aplikaci budeme pou₧φvat.
Lze je nap°. pou₧φt k ulo₧enφ bitov²ch map pro vlastnφ zobrazovacφ ovladaΦ.
V naÜi aplikaci p°idßme na hlavnφ formulß° t°i komponenty
Image,
nastavφme jejich jmΘna na Floppy,
Fixed a Network,
vlastnosti Visible u vÜech t°φ komponent nastavφme na false
a vlastnosti Picture p°i°adφme odpovφdajφcφ bitovΘ mapy (m∙₧eme
je stßhnout). Kdy₧ ji₧ mßme grafickΘ obrßzky
v aplikaci, m∙₧eme je p°i°adit k °et∞zc∙m v seznamu °et∞zc∙. V naÜi aplikaci
zjistφme existujφcφ diskovß za°φzenφ a pro ka₧dΘ existujφcφ za°φzenφ do
seznamu p°idßme °et∞zec souΦasn∞ s obrßzkem reprezentujφcφm typ za°φzenφ.
Zm∞nφme tedy ji₧ existujφcφ obsluhu udßlosti
OnCreate pro formulß°
a to takto:
static char * Drive_Letter[]={"a:\\","b:\\","c:\\","d:\\","e:\\","f:\\",
"g:\\","h:\\","i:\\","j:\\","k:\\","l:\\","m:\\","n:\\","o:\\","p:\\",
"q:\\","r:\\","s:\\","t:\\","u:\\","v:\\","w:\\","x:\\","y:\\","z:\\"};
int AddedIndex;
for(int x =0; x <=
25; x++ ) {
switch(GetDriveType(Drive_Letter[x]))
{
case DRIVE_REMOVABLE:
AddedIndex=DriveTabSet->Tabs->AddObject(String(Drive_Letter[x]),
Floppy->Picture->Graphic);
break;
case DRIVE_FIXED:
AddedIndex=DriveTabSet->Tabs->AddObject(String(Drive_Letter[x]),
Fixed->Picture->Graphic);
break;
case DRIVE_REMOTE:
AddedIndex=DriveTabSet->Tabs->AddObject(String(Drive_Letter[x]),
Network->Picture->Graphic);
break;
case DRIVE_CDROM:
AddedIndex=DriveTabSet->Tabs->AddObject(Drive_Letter[x],
Floppy->Picture->Graphic);
break;
case DRIVE_RAMDISK:
AddedIndex=DriveTabSet->Tabs->AddObject(Drive_Letter[x],
Floppy->Picture->Graphic);
break;
}
if (toupper(*Drive_Letter[x])
== FileList->Drive)
DriveTabSet->TabIndex = AddedIndex;
}
Kdy₧ nastavφme styl ovladaΦe na vlastnφ kreslenφ, Windows ji₧ dßle
nezobrazuje ovladaΦ na obrazovku. Mφsto toho generuje udßlosti pro ka₧d²
viditeln² prvek v ovladaΦi. NaÜe aplikace tyto udßlosti zpracuje pro nakreslenφ
prvk∙. P°ed vlastnφm zobrazenφm prvk∙ v prom∞nnΘm vlastnφm kreslφcφm ovladaΦi,
Windows generuje udßlost OnMeasureItem. Windows urΦujφ, jakß plocha
bude pot°ebnß k zobrazenφ prvku (obecn∞ plocha, na kterΘ bude zobrazen
text prvku aktußlnφm pφsmem). NaÜe aplikace m∙₧e zpracovat tuto udßlost
a zm∞nit navr₧enou plochu. K zm∞n∞ velikosti prvku pro vlastnφ kreslenφ,
vytvo°φme obsluhu udßlosti OnMeasureItem. Tato udßlost mß dva d∙le₧itΘ
parametry: index prvku a velikost tohoto prvku. Velikost je parametr volan²
odkazem a aplikace m∙₧e jeho hodnotu zmenÜovat nebo zv∞tÜovat. Pozice nßsledujφcφho
prvku zßvisφ na velikosti p°edchozφho prvku. Zm∞nu velikosti prvku lze
vyu₧φvat v komponentßch seznamu, kombinovanΘho okna a TabSet (zde
se pou₧φvß udßlost OnMeasureTab). V naÜφ aplikaci vytvo°φme obsluhu
udßlosti OnMeasureTab pro komponentu TabSet, kterß zv∞tÜφ
p∙vodnφ Üφ°ku zßlo₧ky o Üφ°ku bitovΘ mapy + 2:
int BitmapWidth;
BitmapWidth = ((Graphics::TBitmap
*)
(DriveTabSet->Tabs->Objects[Index]))->Width;
TabWidth=TabWidth+2+BitmapWidth;
Prvek z vlastnostφ Objects v seznamu °et∞zc∙ musφme p°etypovat.
Objects
je vlastnost typu TObject a m∙₧e tak obsahovat libovolnΘho potomka
TObject.
Kdy₧ zφskßvßme objekty z pole, je pot°eba je p°evΘst zp∞t na aktußlnφ typ
prvk∙. Jestli₧e aplikace po₧aduje kreslenφ nebo p°ekreslenφ ovladaΦe pomocφ
vlastnφho kreslenφ, Windows generuje kreslφcφ udßlost pro ka₧d² viditeln²
prvek v ovladaΦi. JmΘna t∞chto udßlostφ zaΦφnajφ v₧dy OnDraw, nap°.
OnDrawItem,
OnDrawTab
nebo OnDrawCell. Tato udßlost obsahuje parametry indikujφcφ index
kreslenΘho prvku, obdΘlnφk, ve kterΘm bude zobrazen a obvykle n∞kterΘ informace
o stavu prvku. Pro naÜi aplikaci tedy vytvo°φme obsluhu udßlosti OnDrawTab
pro komponentu
TabSet:
Graphics::TBitmap
*Bitmap;
Bitmap = (Graphics::TBitmap
*) (DriveTabSet->Tabs->Objects[Index]);
TabCanvas->Draw(R.Left,
R.Top + 4, Bitmap);
TabCanvas->TextOut(R.Left
+ 2 + Bitmap->Width, R.Top + 2,
DriveTabSet->Tabs->Strings[Index].SubString(1,1));
V∞tÜina kreslφcφch udßlostφ nep°edßvß jako parametr plßtno objektu;
b∞₧n∞ se p°i kreslenφ pou₧φvß plßtno ovladaΦe. Proto₧e TabSet mß
mezi prvky vlo₧en odd∞lovaΦ zßlo₧ek, je p°edßno pro kreslen² prvek specißlnφ
plßtno jako parametr.
-
V knihovn∞ b∞hu programu Builderu je zabudovßno n∞kolik souborov²ch operacφ.
Funkce pro prßci se soubory vy₧adujφ zadßnφ jmΘna souboru, se kter²m chceme
pracovat. Mimo t∞chto knihovnφch funkcφ budeme v naÜφ aplikaci pou₧φvat
n∞kterΘ dalÜφ; jsou uvedeny v programovΘ jednotce FMXUtils. Prßci
se soubory budeme provßd∞t jako reakci na volbu v nabφdce. N∞kterΘ prvky
nabφdky, je vhodnΘ zp°φstupnit pouze v p°φpad∞ vybranΘho souboru. Pro povolovßnφ
a zakazovßnφ prvk∙ v nabφdce vytvo°φme obsluhu udßlosti OnClick
pro nabφdku File:
Open1->Enabled =
FileSelected;
Delete1->Enabled
= FileSelected;
Copy1->Enabled =
FileSelected;
Move1->Enabled =
FileSelected;
Rename1->Enabled
= FileSelected;
Properties1->Enabled
= FileSelected;
Nynφ, kdy₧ u₧ivatel otev°e nabφdku File, aplikace povoluje nebo
zakazuje vÜechny prvky tΘto nabφdky (mimo Exit) v zßvislosti na
tom, zda mßme v seznamu soubor∙ vybran² soubor.
ZruÜenφ souboru odstranφ soubor z disku a zruÜφ p°φsluÜnou polo₧ku
v seznamu soubor∙. Pro zruÜenφ souboru, p°edßme jmΘno souboru funkci DeleteFile.
DeleteFile
vracφ true, jestli₧e soubor byl zruÜen, nebo false, pokud
jej nelze zruÜit (jednß se nap°. o soubor urΦen² pouze pro Φtenφ). Nßsledujφcφ
k≤d zpracovßvß volbu File | Delete:
if(MessageDlg("Delete"
+ FileList->FileName + "?", mtConfirmation,
TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes){
if(DeleteFile(FileList->FileName.c_str()))
FileList->Items->Delete(FileList->ItemIndex);
}
Ka₧d² soubor mß n∞kolik atribut∙ ulo₧en²ch operaΦnφm systΘmem jako
bitovΘ p°φznaky. Zm∞na atributu souboru se provßdφ v t∞chto krocφch: p°eΦteme
atributy souboru, zm∞nφme po₧adovan² atribut a ulo₧φme atributy souboru.
Pro p°eΦtenφ atribut∙ souboru, p°edßme jmΘno souboru funkci FileGetAttr.
Vrßcenß hodnota typu unsigned short popisuje nastavenΘ atributy.
V naÜem p°φklad∞ volbou File | Properties otev°eme dialogovΘ okno,
ve kterΘm u₧ivatel zjistφ informace o souboru a kde takΘ m∙₧e atributy
souboru m∞nit. P°idßme tedy k projektu nov² formulß°, p°i°azenou programovou
jednotku ulo₧φme pod jmΘnem FAttrDlg a vlastnosti novΘho formulß°e
nastavφme podle nßsledujφcφ tabulky:
Vlastnost |
Hodnota |
Name |
FileAttrDlg |
Caption |
File Attributes |
Position |
poScreenCenter |
BorderIcons |
[biSystemMenu] |
BorderStyle |
bsDialog |
Podle nßsledujφcφho obrßzku na formulß° p°idßme dalÜφ ovladaΦe (jmΘna
t°φ komponent Label jsou uvedena na obrßzku a znaΦky nazveme ReadOnly,
Archive,
System
a Hidden):
Pro nastavenφ souborov²ch atribut∙, p°edßme jmΘno souboru a atributy
funkci FileSetAttr. Nßsledujφcφ k≤d Φte souborovΘ atributy do prom∞nnΘ,
nastavφ znaΦky v dialogovΘm okn∞ na souΦasnΘ hodnoty atribut∙ a dialogovΘ
okno provede. Jestli₧e u₧ivatel n∞kter² z atribut∙ zm∞nφ, pak v p°φpad∞
uzav°enφ dialogovΘho okna pomocφ tlaΦφtka OK, jsou jejich hodnoty
p°edßny souboru (nßsledujφcφ p°φkazy tvo°φ obsluhu volby File | Properties):
unsigned short
Attributes, NewAttributes;
FileAttrDlg->FileDirName->Caption
=
FileList->Items->Strings[FileList->ItemIndex];
FileAttrDlg->FilePathName->Caption
= FileList->Directory;
FileAttrDlg->ChangeDate->Caption
=
DateTimeToStr(FileDateTime(FileList->FileName));
Attributes = FileGetAttr(FileList->Items->Strings[FileList->ItemIndex]);
FileAttrDlg->ReadOnly->Checked
= Attributes & faReadOnly;
FileAttrDlg->Archive->Checked
= Attributes & faArchive;
FileAttrDlg->System->Checked
= Attributes & faSysFile;
FileAttrDlg->Hidden->Checked
= Attributes & faHidden;
if (FileAttrDlg->ShowModal()!=
mrCancel){
NewAttributes
= Attributes;
if (FileAttrDlg->ReadOnly->Checked)
NewAttributes = NewAttributes | faReadOnly;
else NewAttributes
= NewAttributes & ~faReadOnly;
if(FileAttrDlg->Archive->Checked)
NewAttributes=NewAttributes|faArchive;
else NewAttributes
= NewAttributes & ~faArchive;
if(FileAttrDlg->System->Checked)NewAttributes=NewAttributes|faSysFile;
else NewAttributes
= NewAttributes & ~faSysFile;
if(FileAttrDlg->Hidden->Checked)NewAttributes=NewAttributes|faHidden;
else NewAttributes
= NewAttributes & ~faHidden;
if (NewAttributes
!= Attributes)
FileSetAttr(FileAttrDlg->FileDirName->Caption, NewAttributes);
}
P°esun, kopφrovßnφ a p°ejmenovßnφ soubor∙ jsou podobnΘ operace, vÜechny
vytvß°ejφ soubor z jinΘho souboru. LiÜφ se pouze tφm, co zbude z p∙vodnφho
souboru. Knihovna b∞hu programu poskytuje funkci RenameFile, kterß
provßdφ p°ejmenovßnφ. Programovß jednotka FMXUtils poskytuje podobnΘ
funkce nazvanΘ MoveFile a CopyFile pro dalÜφ operace. VÜechny
tyto funkce p°ebφrajφ dva °et∞zce jako svΘ parametry: jmΘno p∙vodnφho souboru
a jmΘno cφlovΘho souboru. Nßsledujφcφ k≤d zobrazuje soukromou metodu nazvanou
ConfirmChange,
kterß zobrazφ potvrzovacφ dialogovΘ okno:
void __fastcall TFMForm::ConfirmChange(const
AnsiString ACaption,
AnsiString FromFile, AnsiString ToFile)
{
char buffer[700];
sprintf(buffer,"%s
%s to %s?",ACaption, FromFile, ToFile);
if(MessageDlg(buffer,
mtConfirmation,
TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes){
if (ACaption == "Move") MoveFile(FromFile, ToFile);
else if (ACaption == "Copy") CopyFile(FromFile, ToFile);
else if (ACaption =="Rename") RenameFile(FromFile, ToFile);
FileList->Update();
}
}
Proto₧e vÜechny t°i operace jsou si podobnΘ, m∙₧e aplikace sprßvce
soubor∙ sdφlet v∞tÜinu pou₧itΘho k≤du. Vytvo°φme dialogovΘ okno, ve kterΘm
u₧ivatel zadß p∙vodnφ jmΘno a cφlovΘ jmΘno a pou₧ijeme jej v t∞chto operacφch.
Na obrßzku je toto okno zobrazeno (hornφ editaΦnφ ovladaΦ nazveme FromFileName
a spodnφ ToFileName).
Formulß° dialogovΘho okna nazveme ChangeDlg a jeho jednotku
ulo₧φme do souboru FChngDlg.CPP. Po vytvo°enφ dialogovΘho okna jej
m∙₧eme otevφrat z obsluhy udßlosti sdφlenΘ prvky nabφdky Move, Copy
a Rename (nazveme ji FileChange). Tato obsluha je tvo°ena
p°φkazy (funkce _c_exit je definovßna v hlaviΦkovΘm souboru Process.h):
if (dynamic_cast<TMenuItem
*>(Sender) == Move1 )
ChangeDlg->Caption
= "Move" ;
else if (dynamic_cast<TMenuItem
*>(Sender) == Copy1)
ChangeDlg->Caption
= "Copy";
else if (dynamic_cast<TMenuItem
*>(Sender) == Rename1)
ChangeDlg->Caption
= "Rename";
else _c_exit();
ChangeDlg->CurrentDir->Caption
= DirectoryOutline->Directory;
ChangeDlg->FromFileName->Text
= FileList->FileName;
ChangeDlg->ToFileName->Text
= "";
if((ChangeDlg->ShowModal()!=mrCancel)&&(ChangeDlg->ToFileName->Text!=""))
ConfirmChange(ChangeDlg->Caption,
ChangeDlg->FromFileName->Text,
ChangeDlg->ToFileName->Text);
Aplikace nynφ zobrazuje dialogovΘ okno se sprßvn²m titulkem a provßdφ
po₧adovanou operaci. Aplikace n∞kdy pot°ebuje provΘst jinou aplikaci. API
Windows poskytuje funkci ShellExecute, kterß provßdφ aplikaci, ale
tato funkce vy₧aduje n∞kolik parametr∙. Programovß jednotka FMXUtils
obsahuje jejφ snadn∞ji pou₧itelnou alternativu, nazvanou ExecuteFile.
ExecuteFile
pracuje dv∞ma zp∙soby. Je-li ji p°edßno jmΘno proveditelnΘho souboru, ExecuteFile
spustφ tuto aplikaci. Je-li ji p°edßno jmΘno dokumentu p°i°azenΘho aplikaci,
ExecuteFile
spustφ aplikaci a automaticky otev°e tento dokument.
ExecuteFile
p°ebφrß t°i parametry typu AnsiString a Φtvrt² parametr indikujφcφ
zp∙sob zobrazenφ okna aplikace. T°i °et∞zce reprezentujφ jmΘno souboru,
parametry p°edanΘ aplikaci a adresß° pou₧it² jako pracovnφ adresß° aplikace.
Poslednφ parametr m∙₧e b²t jedna z konstant pou₧φvanß API funkcφ ShowWindow.
Nap°. SW_SHOW zobrazφ okno normßln∞,
SW_SHOWMINIMIZED zobrazφ
okno minimalizovanΘ apod. Okno seznamu soubor∙ obsahuje vÜechny informace
pot°ebnΘ k provedenφ souboru. StejnΘ p°φkazy m∙₧eme p°ipojit k udßlosti
OnDblClk
okna seznamu soubor∙, co₧ umo₧nφ spouÜt∞t programy dvojit²m kliknutφm na
jejich jmΘnu v seznamu. Jestli₧e ale vybran² prvek je adresß°, potom pravd∞podobn∞
chceme tento adresß° otev°φt (p°ejφt na tento adresß°). Obsluha udßlosti
volby
File | Open bude vypadat takto:
if (HasAttr(FileList->FileName,
faDirectory))
DirectoryOutline->Directory
= FileList->FileName;
else ExecuteFile(FileList->FileName,"
", DirectoryOutline->Directory, SW_SHOW);
a obsluha dvojitΘho kliknutφ na seznamu soubor∙ je tvo°ena p°φkazem:
Open1Click(Sender);
HasAttr je funkce typu bool z FMXUtils, kterß
vracφ true, kdy₧ soubor uveden² jako jejφ prvnφ parametr mß atribut
urΦen² druh²m parametrem; jinak vracφ false. Nastavenφ vlastnosti
Directory
seznamu adresß°∙, zp∙sobφ zm∞nu adresß°e. Dvojit²m kliknutφm na adresß°i
v seznamu soubor∙ lze nynφ m∞nit adresß°. V²voj aplikace dokonΦφme v nßsledujφcφ
kapitole.