VCL - pierwsze kroki


Więcej właściwości

Kolejne niezbędne właściwości są przeznaczone do przechowywania danych. Dotyczy to zarówno danych wyjściowych - rezultatów działania, jak i wejściowych - potrzebnych do wykonania wybranej operacji.

Te dane to lokalizacje plików. Typem właściwości będzie AnsiString. Pojedyncza zmienna tego typu przechowa jednak nazwę tylko jednej ścieżki. Do zachowania nazw wielu ścieżek potrzebny nam będzie typ TStringList, który jest wykorzystywany m.in. w komponentach TMemo i TListBox (właściwości Lines i Items). Typ TStringList dostarcza metod zapisu i odczytu danych z listy w prosty i szybki sposób.

Dodatkowa korzyść związana z wykorzystaniem typu TStringList polega na tym, że gdy pracujemy w środowisku C++Buildera, dwukrotne kliknięcie właściwości spowoduje wyświetlenie listy, która umożliwi zadeklarowanie początkowych wartości elementów.

Nazwy obu wspomnianych właściwości w naszym komponencie to ListaWejsciowa i ListaWyjsciowa, a ich deklaracja wygląda następująco:

// zmienne przechowujące wartości:

TStringList *ListaWej, *ListaWyj;

...

// metody realizujące dostęp do

// zmiennych za pomocą właściwości:

TStringList* __fastcall CzytajWej(void);

void __fastcall ZapisujWej(TStrings* w);

TStringList* __fastcall CzytajWyj(void);

void __fastcall ZapisujWyj(TStrings* w);

...

// deklaracja właściwości:

public:

__published:

__property TStrings* ListaWejsciowa = {read=CzytajWej, write=ZapisujWej};

__property TStrings* ListaWyjsciowa = {read=CzytajWyj, write=ZapisujWyj};

...

// ciała metod

TStringList* __fastcall

TFilesExplorer::CzytajWej(void) {

return ListaWej;

}

void __fastcall

TFilesExplorer::ZapisujWej(Lista* w) {

ListaWej->Assign(w);

}

TStringList* __fastcall

TFilesExplorer::CzytajWyj(void) {

return ListaWyj;

}

void __fastcall

TFilesExplorer::ZapisujWyj(Lista* w) {

ListaWyj->Assign(w);

}

Musimy pamiętać, że zmienne ListaWej i ListaWyj przechowujące listy to zmienne typu wskaźnikowego i należy zainicjować je w obrębie konstruktora komponentu, a następnie uwolnić w destruktorze. Ostatnia właściwość komponentu będzie miała nazwę Opcje i będzie przechowywać szczegółowe ustawienia komponentu. Utworzymy dla niej nowy typ - nową klasę. Jak widać, deklaracja właściwości komponentów jest dość elastyczna. Dzięki temu możemy tworzyć kod jednocześnie prosty i funkcjonalny. Oto klasa przechowująca opcje:

class __declspec(delphiclass) opcje :

public TPersistent

{

bool KDKosza, TPliki, KMDoc, NPotwierdzaj, NPTKatalogu, ZNazwy, OPostepu, NPlikow, PKatalogi;

AnsiString NOPostepu;

public:

// konstruktor klasy opcje

__fastcall opcje(void);

// metoda zwraca wartość, która informuje

// pole fFlags struktury SHFILEOPSTRUCT

// o sposobie wykonania działania

FILEOP_FLAGS __fastcall OdczytajFlagi(void);

// metoda zwraca nazwę okna postępu w polu

// lpszProgressTitle struktury SHFILEOPSTRUCT

LPCSTR __fastcall OdczytajNazweOkna(void);

__published:

__property bool KasowanieDoKosza = {read=KDKosza, write=KDKosza, default=true};

__property bool TylkoPliki = {read=TPliki, write=TPliki};

__property bool KilkaMiejscDoc = {read=KMDoc, write=KMDoc};

__property bool NiePotwierdzaj = {read=NPotwierdzaj, write=NPotwierdzaj};

__property bool NiePotwTworzKatalogu = {read=NPTKatalogu, write=NPTKatalogu};

__property bool ZmianaNazwy = {read=ZNazwy, write=ZNazwy, default=true};

__property bool WylOknoPostepu = {read=OPostepu, write=OPostepu};

__property bool WylNazwyPlikow = {read=NPlikow, write=NPlikow};

__property AnsiString NazwaOknaPost = {read=NOPostepu, write=NOPostepu};

__property bool PszeszukujKatalogi = {read=PKatalogi, write=PKatalogi};

};

Klasa opcje ma również właściwości (property), co powoduje ich wyświetlanie w oknie Object Inspector jako podopcje właściwości Opcje komponentu. Należy zwrócić uwagę na sposób deklaracji klasy. Musi on dziedziczyć po klasie TPersistent, która dostarcza niezbędne mechanizmy do pracy z komponentami. Drugą ważną czynnością jest umieszczenie klauzuli __declspec(delphiclass). Teraz przejdźmy do klasy głównej komponentu. Klasa komponentu, która wykorzystuje inne klasy zadeklarowane wcześniej, musi zawierać przed nazwą klauzulę PACKAGE. Uwzględniając wszystkie wcześniejsze deklaracje, fragment pliku nagłówkowego FileExplorer.h zawierający deklarację klasy komponentu powinien wyglądać następująco:

class PACKAGE TFilesExplorer :

public TComponent

{

private:

ROperacji operacja;

TStringList *ListaWej, *ListaWyj;

opcje *o;

// metody umożliwiające

// współpracę z właściwościami

TStringList* __fastcall CzytajWej(void);

void __fastcall ZapisujWej(TStrings* w);

TStringList* __fastcall CzytajWyj(void);

void __fastcall ZapisujWyj(TStrings* w);

public:

// konstruktor

__fastcall TFilesExplorer(TComponent* Owner);

// destruktor

__fastcall ~TFilesExplorer(void);

__published:

__property ROperacji Operacja = {read=operacja, write=operacja};

__property TStrings* ListaWejsciowa = {read=CzytajWej, write=ZapisujWej};

__property TStrings* ListaWyjsciowa = {read=CzytajWyj, write=ZapisujWyj};

__property opcje* Opcje = {read=o, write=o};

};