VCL - pierwsze kroki

W pierwszej części artykułu przedstawimy podstawowe zasady działania i budowy komponentów VCL w środowisku C++Builder. Zdefiniujemy też właściwości nowego komponentu do obsługi plików i rozpoczniemy implementacjęjego najważniejszych metod.

W pierwszej części artykułu przedstawimy podstawowe zasady działania i budowy komponentów VCL w środowisku C++Builder. Zdefiniujemy też właściwości nowego komponentu do obsługi plików i rozpoczniemy implementacjęjego najważniejszych metod.

Zbudowanie komponentu opakowującego często wykorzystywane funkcje API, pozwala zapomnieć o skomplikowanych szczegółach związanych z wywoływaniem poszczególnych funkcji i zamiast tego korzystać z ujednoliconego interfejsu udostępnianego przez komponent. Drugą ważną zaletą jest też możliwość wielokrotnego wykorzystania komponentu w różnych projektach - także przez inne osoby.

Budowany przez nas komponent nie będzie widoczny po uruchomieniu naszej aplikacji. Natomiast w fazie projektowania będzie reprezentowany przez ikonę umieszczoną w formularzu naszej aplikacji. Podobnie funkcjonują komponenty znajdujące się na karcie Dialogs, np. OpenDialog. Tego typu komponenty (niewidoczne) są tworzone na podstawie klasy TComponent.

Jak zacząć?

Aby rozpocząć tworzenie komponentu, wybieramy z menu C++Buildera opcję File | New | Other a następnie Component. Pojawi się okno, w którym musimy umieścić następujące informacje:

  • Ancestor type - nazwa klasy bazowej naszego komponentu (po jakim komponencie nasz komponent będzie dziedziczył metody i właściwości).
  • Class Name - nazwa klasy.
  • Pallete Page - nazwa palety, na której ma być umiejscowiony komponent.
  • Unit file name - nazwa i miejsce modułu źródłowego komponentu.
  • Search path - ścieżka poszukiwań plików.
Po zatwierdzeniu podanych informacji zostanie wygenerowany szablon komponentu, w którym będziemy mogli umieszczać nasze metody.

Ogólnie o budowie

Nasz komponent będzie nosił nazwę TFilesExplorer i będzie umożliwiał wykonywanie operacji opisanych w poprzednim numerze w artykule "Do pliku przez API". Dostarczy też informacji o plikach, takich jak typ, czas utworzenia itp.

Każdy komponent ma kilka charakterystycznych cech: właściwości (properties), zdarzenia (events) oraz wyjątki (exceptions). Właściwości upraszczają operowanie zmiennymi komponentu oraz jego metodami, a ponadto zapewniają komunikację z komponentem w fazie projektowania. Do ich edycji w środowisku C++Buildera służy okno Object Inspector. A oto przykład typowej definicji właściwości:

AnsiString Czytaj;

void Zapisz(AnsiString CoZapisac);

public:

__published:

__property AnsiString NazwaWłaściwości = {read=Czytaj, write=Zapisz};

Podczas odczytywania właściwości jej wartość jest pobierana bezpośrednio ze zmiennej przypisanej do read lub wywoływana jest przypisana funkcja. Podobnie rzecz się ma przy zapisywaniu właściwości za pomocą write. Ważne jest miejsce deklaracji właściwości. Jeżeli deklaracja wystąpi po słowie public, to będzie ogólnodostępna, ale zmiany jej wartości będzie można dokonać tylko w obrębie kodu programu. Jeżeli dodatkowo daną właściwość opublikujemy, czyli umieścimy w obrębie słowa kluczowego published, to będziemy mieli do niej pełny dostęp nawet w środowisku C++Buildera.

Kolejny element to zdarzenia. Najczęściej spotyka się następującą deklarację:

TNotifyEvent *zdarzenie;

__property TNotifyEvent OnZdarzenie = {read=zdarzenie, write=zdarzenie};

void PrzykładowaMetoda(void)

{

...

// wywołanie zdarzenia

if(zdarzenie) zdarzenie(this);

...

}

Jak widać powyżej, zdarzenia można deklarować tak samo, jak właściwości. Takie podejście stosowane jest wówczas, gdy nie potrzebujemy przekazywać żadnych dodatkowych wartości przy wywołaniu zdarzenia. Wywoływanie zdarzeń z przekazywaniem parametrów omówimy dokładniej w drugiej części artykułu. Tworząc komponent, zetkniemy się też z wyjątkami. Aby utworzyć wyjątek, deklarujemy nową klasę oznaczającą określony wyjątek, a następnie już w komponencie zamieszczamy jego wywołanie. Oto przykład:

class NaszWyjatek : public Exception

{

public:

__fastcall NaszWyjatek(const AnsiString wiadomosc) : Exception(wiadomosc){}

}

Pierwsze kroki

Tworząc nowy komponent, musimy wskazać jego klasę bazową.

Tworząc nowy komponent, musimy wskazać jego klasę bazową.

Po tym krótkim ogólnym wstępie powróćmy do naszego komponentu. Do tej pory utworzyliśmy tylko szablon. Teraz należy zastanowić się, jakie właściwości musi mieć komponent. Jedną z nich na pewno będzie właściwość oznaczająca czynność, którą chcemy wykonać. Nazwiemy ją operacja. Pozostaje tylko określić jej rodzaj. W naszym przykładzie dobrym rozwiązaniem będzie zastosowanie typu wyliczeniowego, ponieważ właściwość operacja może przyjąć tylko kilka wartości. Dzięki temu w oknie Object Inspector wyświetli się pełna lista dostępnych wartości danej właściwości. Oto deklaracja typu wyliczeniowego i właściwości:

enum ROperacji { OpFind, OpCreate, OpRename, OpCopy, OpMove, OpDelete};

ROperacji operacja;

public:

__published:

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


Zobacz również