Rozdział 5.
Model komponentów
wizualnych
W rozdziale tym mam zamiar przedstawić model komponentów wizualnych oraz bi-
bliotekę VCL – Visual Component Library. Zanim jednak do tego przystąpię, chciałbym
powiedzieć kilka słów o bibliotekach klas. W rozdziale tym przedstawię następujące
zagadnienia:
υ
podstawowe wiadomości o bibliotekach
υ
przegląd biblioteki VCL – Visual Component Library
υ
Klasy biblioteki VCL – formularze, aplikacje oraz klasy związane z komponentami
(component classes)
Podstawowe wiadomości
o bibliotekach klas
Często mówi się, że „Na początku było C ...” – nie jest to jednak do końca prawdą. Jeśli
jednak wziąć pod uwagę programowanie w systemie Windows, nie można temu zaprzeczyć.
Na początku ogromną większość programów dla Windows pisano w C. W rzeczywistości
Windows API (ang. Application Programmer’s Interface – Interfejs Programisty) jest
ogromną kolekcją funkcji napisanych w języku C. Nie podlega wątpliwości fakt, że tysiące
programistów nadal pisze programy dla Windows w języku C. Nagle ludzie z Borlanda
powiedzieli, „Wszystko to można zrobić łatwiej.” (W rzeczywistości rewolucja związana
ze bibliotekami klas mogła rozpocząć się na różnych frontach, ale Borland był niekwe-
stionowanym liderem.) Nie podlegało wątpliwości, że programowanie w Windows jest
świetnie przystosowane do techniki programowania obiektowo-zorientowanego. Dzięki
stworzeniu klas, które ukrywały w sobie podstawowe zadania programistyczne doty-
czące Windows, programista mógł być bardziej produktywny. Po stworzeniu klasy, aby
180
Część I
180
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
np. reprezentowała sobą różne zachowania okienka, klasę tą można było powtórnie wy-
korzystywać. Rozpoczęła się rewolucja związana z zastosowaniem bibliotek klas. Nie
wytłumaczyłem Ci jednak jeszcze, co to jest biblioteka klas.
Biblioteka klas jest kolekcją klas, która upraszcza programowanie
w Windows, poprzez hermetyzację często używanych zadań programi-
stycznych. Hermetyzacja ma za zadanie ukrycie złożonej budowy funkcji
udostępniając je jedynie w uproszczonej formie (w postaci interfejsu klasy –
przyp. tłum.).
Popularne biblioteki klas składają się z klas, które hermetyzują okna, pola edycyjne, listy
wyboru, operacje graficzne, bitmapy, paski przewijania, okienka dialogowe i podobne
elementy.
Dlaczego powinniśmy się zajmować bibliotekami klas?
To dobre pytanie. Z podsumowania wynika, że dzięki bibliotekom klas programowanie
w Windows staje się dużo prostsze niż w czystym C, asemblerze, czy też oryginalnym
Pascalu (mam na myśli czystego Pascala, a nie Object Pascala). Pozwól, że przedstawię to
na przykładzie. Listing 5.1 zawiera kawałek programu dla systemu Windows napisanego
w języku C++. Kawałek ten wczytuje z pliku bitmapę, a następnie wyświetla ją na środ-
ku ekranu. Mimo, że kod ten może być dla Ciebie trochę niezrozumiały i bezsensowny,
proszę Cię o cierpliwość.
Listing 5.1. Kawałek kodu w C++, którego zadaniem jest wczytanie i wyświetlenie bitmapy
HPALETTE hPal;
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
LBITMAPINFO lpbi = 0;
HFILE hFile;
DWORD nClrUsed, nSize;
HDC hDC;
HBITMAP hBitmap;
void *bits;
do {
if ((hFile = _lopen(data.FileName, OF_READ)) == HFILE_ERROR) break;
if (_hread(hFile, &bfh, sizeof(bfh)) != sizeof(bfh)) break;
if (bfh.bfType != 'BM') break;
if (_hread(hFile, &bih, sizeof(bih)) != sizeof(bih)) break;
nClrUsed = (bih.biClrUsed) ? bih.biClrUsed : 1 << bih.biBitCount;
nSize = sizeof(BITMAPINFOHEADER) + nClrUsed * sizeof(RGBQUAD);
lpbi = (LPBITMAPINFO) GlobalAllocPtr(GHND, nSize);
if (!lpbi) break;
MoveMemory(lpbi, &bih, sizeof(bih));
nSize = nClrUsed * sizeof(RGBQUAD);
if (_hread(hFile, &lpbi->bmiColors, nSize) != nSize) break;
if (_llseek(hFile, bfh.bfOffBits, 0) == HFILE_ERROR) break;
nSize = bfh.bfSize-bfh.bfOffBits;
if ((bits = GlobalAllocPtr(GHND, nSize)) == NULL) break;
if (_hread(hFile, bits, nSize) != nSize) break;
hDC = GetDC(hWnd);
hBitmap = CreateDIBitmap(hDC, &(lpbi->bmiHeader), CBM_INIT,
Rozdzia³ 5.
♦ Model komponentów wizualnych
181
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
181
bits, lpbi, DIB_RGB_COLORS);
if (hBitmap) {
LPLOGPALETTE lppal;
DWORD nsize = sizeof(LOGPALETTE) + (nClrUsed-1) = sizeof(PALETTEENTRY);
lppal = (LPLOGPALETTE) GlobalAllocPtr(GHND, nSize);
if (lppal) {
lppal->palVersion = 0x0300;
lppal->palNumEntries = (WORD) nClrUsed;
MoveMemory(lppal->palPalEntry, lpbi->bmiColors,
nClrUsed * sizeof(PALETTEENTRY));
hPal = CreatePalette(lppal);
(void) GlobalFreePtr(lppal);
}
}
} while (FALSE);
if (hFile != HFILE_ERROR) _lclose(hFile);
HPALETTE oldPal = SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);
HDC hMemDC = CreateCompatibleDC(hDC);
HBITMAP oldBitmap = (HBITMAP) SelectObject(hMemDC, hBitmap);
BitBlt(hDC, 0, 0, (WORD)bih.biWidth, (WORD)bih.biHeight, hMemDC, 0, 0,
SRCCOPY);
SelectObject(hMemDC, oldBitmap);
DeleteDC(hMemDC);
SelectPalette(hDC, oldPal, FALSE);
ReleaseDC(hWnd, hDC);
if (bits) (void) GlobalFreePtr(bits);
if (lpbi) (void) GlobalFreePtr(lpbi);
Czyż nie jest to trochę przerażające? Spójrz teraz na równoważny kod wykorzystujący
bibliotekę VCL, która została stworzona przez firmę Borland :
Image.LoadFromFile('winnt.bmp');
Powiedz mi zatem, którą z wersji wolałbyś używać? Myślę, że, aby podjąć tą decyzję,
nie musisz nawet wiedzieć, jak działają powyższe fragmenty kodu. Nie będąc znawcą,
łatwo zauważyć, że wersja VCL jest o wiele krótsza i o wiele bardziej czytelna.
Powyższe przykłady same mówią za siebie. Biblioteki klas ukrywają przed Tobą detale,
których znajomość przestaje być konieczna. W przypadku wersji wykorzystującej VCL,
wszystko zawarte w listingu 5.1 jest wykonywane jakby poza twoją wiedzą – wewnątrz
biblioteki klasy (z tą różnicą, że nie jest to napisane C++, lecz w Pascalu). Kiedy VCL
wykonuje za Ciebie “czarną robotę”, nie musisz znać każdego szczegółu będącego tłem
dla Twojego kodu. Wszystko czego Ci potrzeba to wybranie odpowiednich obiektów,
które tworzą bibliotekę klas, a następnie wykorzystanie ich w twoich programach.
Dobrze zbudowana biblioteka klas w pełni wykorzystuje zalety OOP – niektóre są pod ty
względem lepsze, inne mniej. Stworzona przez firmę Borland biblioteka OWL
(dostarcza-
na zarówno w wersji dla języka Pascal, jak i C++) oraz biblioteka VCL są wspaniałymi
1
OWL (ang. Object Windows Library) – biblioteka firmy Borland służąca do pisania zorientowanych
obiektowo programów w systemie Windows (przyp. tłum.)
182
Część I
182
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
przykładami programowania zorientowanego obiektowo. Dostarczają one odpowiedniego
poziomu abstrakcji, aby wygrzebać się z bałaganu i zabrać się do prawdziwej pracy.
W czym tkwi słaby punkt?
Czy nie nabrałeś przypadkiem trochę sceptycyzmu? Rozumiem. Na pewno jesteś na
tyle spostrzegawczy, aby zauważyć, że ta niesamowita wręcz prostota użycia musi wy-
magać pewnych wyrzeczeń. Masz całkowitą rację. Może myślisz sobie, że program
wykorzystujący biblioteki klas jest większy i wolniejszy niż jego odpowiednik napisany
w języku niskiego poziomu. Częściowo to prawda. Jednakże aplikacje napisane przy
użyciu bibliotek klas, niekoniecznie muszą być wolniejsze od innych programów. Na pewno
w przypadku języka obiektowo-zorientowanego istnieje pewna wrodzona nadmiarowość,
ale dla większości typowych programów dla Windows jest ona praktycznie niezauważalna.
Faktem jest, że programy napisane w Delphi z reguły posiadają większe rozmiary, niż
równoważne programy napisane w językach typu C. Jeśli na przykład prosty program
napisany w C zajmuje 75 KB, to jego odpowiednik napisany w Delphi może zajmować
nawet 250KB. Różnica ta może wydawać się znaczna, jednak powyższy przykład poka-
zuje najgorszy przypadek. Różnica w końcowym rozmiarze programu napisanego w C
i w Delphi przy użyciu bibliotek klas jest najbardziej zauważalna w przypadku małych
programów. Gdy tylko twoje programy zaczną stawać się większe i bardziej wyszukane,
różnica w rozmiarach praktycznie zaniknie.
Jednym z powodów różnicy w rozmiarach jest po prostu różnica pomiędzy językiem
proceduralnym, a zorientowanym obiektowo. Języki zorientowane obiektowo niosą ze
sobą dodatkową nadmiarowość związaną z takimi cechami jak obsługa wyjątków,
i innymi zaletami techniki OOP. Myślę, że różnica w rozmiarach kodu znaczy
niewiele w stosunku do możliwości, których dostarcza Object Pascal.
Przed określeniem mnie mianem „promotora nadmiarowości”, pozwól mi wyjaśnić, że
jeśli chodzi o dodatkowy balast, jestem tak skrupulatny jak nikt inny. Uważam, że
wszyscy powinniśmy pisać programy tak małe, jakie są możliwe do osiągnięcia przy
pomocy narzędzi, których używamy. Jestem jednak realistą i wiem, że czas wprowadzenia
produktu na rynek jest wiodącą siłą w przemyśle związanym z produkcją oprogramo-
wania. Jestem skłonny do pewnych wyrzeczeń w zamian za siłę, jaką daje mi Object
Pascal oraz VCL. Nie mam zamiaru tracić miesiąca na napisanie programu dla Win-
dows, który po skompilowaniu zajmie 100KB, gdy przy pomocy Delphi tą samą rzecz
mogę zrealizować w dwa dni otrzymując przy tym 400KB kodu wynikowego. Rozmiar ko-
du wynikowego staje się mało znaczący kiedy porówna się go z zaoszczędzonym czasem.
Biblioteka Komponentów Wizualnych (VCL)
Na pewno zdążyłeś zauważyć, że w tytule tej książki zostało zawarte słowo „Delphi 4”.
O Delphi dużo się mówiło i pisało. Kiedy w 1995 roku wprowadzono Delphi 1, szybko
2
RTTI (ang. run time type information) – informacja o typach upublicznionych (published) wła-
ściwości i metod klasy, dostępna dla programu w trakcie jego wykonywania (przyp. tłum.)
Rozdzia³ 5.
♦ Model komponentów wizualnych
183
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
183
stało się ono hitem. Delphi miało do zaoferowania technologie szybkiego tworzenia
Dzięki bibliotekom klas możesz poznać zasady projektowania i pro-
gramowania zorientowanego obiektowo
Jeśli na poważnie zajmiesz się tak szaloną rzeczą, jaką jest programowanie
w Windows, możesz w końcu zajrzeć do kodu źródłowego twojej ulubionej
biblioteki klas. Wcześniej czy później będziesz chciał się dowiedzieć, jak
tworzą kod profesjonaliści. Kod źródłowy VCL jest wspaniałym źródłem
tego rodzaju wiedzy.
Pewnego weekendu, gdy liście zostaną zagrabione, płot wymalowany, pra-
nie zrobione, dzieci będą u babci, a ty zabierzesz się za Delphi, poświęć
trochę czasu na przyjrzenie się kodowi źródłowemu VCL (wersje Pro-
fessional i Client/Server są dostarczane wraz z kodem źródłowym VCL.).
Na początku zapewne trudno Ci będzie wszystko zrozumieć, ale po chwili
zrozumiesz, o co chodzi twórcom. Nie wysilaj się nadmiernie. Spróbuj zro-
zumieć tylko rzeczy, które mieszczą się w granicach twojej wiedzy doty-
czącej Object Pascala. Pozostaw bardziej skomplikowany materiał na po-
tem.
Zwróć uwagę na to, jak twórcy VCL używają prywatnego, chronionego
oraz publicznego dostępu do elementów klas. Zauważ, że rzeczy, które po-
winny być ukryte przed użytkownikiem, nie są dostępne publicznie. Studiując
źródła VCL możesz naprawdę wiele nauczyć się o Object Pascalu oraz o
zasadach projektowania obiektowo-zorientowanego.
aplikacji (RAD) za pomocą czegoś, co nazwano komponentami (ang. components).
Komponenty to obiekty, które mogą być osadzane na formularzu, a następnie zręcznie
przekształcane poprzez wykorzystanie ich właściwości, metod oraz zdarzeń. Można to
nazwać programowaniem wizualnym.
Koncepcja programowania opartego na formularzach została po raz pierwszy wprowadzona
przez firmę Microsoft w Visual Basicu. W przeciwieństwie jednak do Visual Basica,
w Delphi jako język programowania wprowadzono pochodną Pascala. Ten nowy język,
nazwany Object Pascal, włączył technologie OOP do języka Pascal. Delphi oraz Object
Pascal reprezentowały związek programowania obiektowo-zorientowanego z progra-
mowaniem opartym na formularzach. Dodatkowo, Delphi tworzyło samodzielne pliki
wykonywalne (ang. executables). Prawdziwe programy. Programy, które do pracy nie
wymagały działających równocześnie bibliotek DLL; programy, które były skompilowane,
a nie interpretowane; programy, które wykonywały się dziesiątki razy szybciej niż aplikacje
Visual Basica. Świat programistów był pod wrażeniem.
Delphi nie było tylko czystym Object Pascalem, dając tym samym wolną rękę w zgłębianiu
jego zawiłości, lecz wprowadzało także VCL (Bibliotekę Komponentów Wizualnych).
Jak już wcześniej wspomniałem, VCL daje szkielet aplikacji Windows dostosowany do
Object Pascala. Chyba najbardziej znamienną cechą VCL jest jej budowa oparta o koncepcje
właściwości, metod oraz zdarzeń – czyli modelu komponentów wizualnych. Przyjrzyjmy
się bliżej temu modelowi.
184
Część I
184
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
Komponenty
Jak już powiedziałem w rozdziale 1, komponenty VCL są obiektami, które wykonują
pewne specyficzne predefiniowane funkcje. Komponenty VCL są zawarte w klasach
Object Pascala. Od tej chwili komponenty w tej książce będą dla Ciebie „chlebem po-
wszednim”. Nie mam zamiaru wyjaśniać Ci teraz każdego ich detalu, gdyż w dalszej
części książki poznasz dokładnie ich działanie na przykładach. Bardziej szczegółowo
postaram się opisać komponenty w rozdziale 7.
Właściwości, Metody, Zdarzenia
W rozdziale 1. zrobiłem krótki wstęp na temat modelu właściwości, metod i zdarzeń. Te trzy
składniki tworzą publiczny interfejs komponentów biblioteki VCL (część komponentu
widoczną dla użytkownika). Przyjrzyjmy się teraz osobno każdemu z nich.
Właściwości
Właściwości są elementami komponentu, które odpowiadają za jego zachowanie. Wiele
komponentów ma wspólne (tego samego typu) właściwości. Na przykład, wszystkie
komponenty wizualne posiadają właściwości
Top
oraz
Left
. Te dwie właściwości określają
miejsce na formularzu, w którym zostanie umieszczony komponent – zarówno w fazie pro-
jektowania jak i wykonywania programu. Wszystkie komponenty mają właściwość
Owner
.
Właściwość ta jest wykorzystywana do określenia właściciela danego komponentu
Właściwości i Inspektor Obiektów
Mówi się, że obraz może zastąpić tysiące słów. Uruchommy zatem ponownie Delphi
i przyjrzyjmy się komponentom w akcji. Kiedy uruchomisz Delphi zostajesz przywitany
pustym formularzem oraz Inspektorem Obiektów (Object Inspector).
Jeśli masz tak skonfigurowane Delphi, że podczas jego zamykania jest za-
pisywany Pulpit, to po uruchomieniu Delphi może się pokazać projekt, nad
którym ostatnio pracowałeś. W takim przypadku w celu otrzymania puste-
go formularza z menu głównego wybierz
File | New Application
.
Na rysunku 5.1 przedstawiono Inspektor Obiektów. (Delphi dopasowuje rozmiary In-
spektora Obiektów do aktualnej rozdzielczości ekranu, tak że Twój Inspektor Obiektów
może być dłuższy lub krótszy od przedstawionego na rysunku 5.1) Jeśli to konieczne,
kliknij na zakładce Inspektora Obiektów
Properties
, tak aby zostały wyświetlone właści-
wości formularza. Jeśli na raz nie mogą być wyświetlone wszystkie właściwości, Inspektor
Obiektów wyświetla pasek przewijania, dzięki któremu możesz zobaczyć dodatkowe
3
Dany komponent może być właścicielem innych komponentów. Przykładem może być formularz,
który w Delphi jest właścicielem znajdujących się na nim komponentów. Właścicielem formularza jest
aplikacja. Właściwość Owner pozwala na określenie tych zależności. Wraz ze zwolnieniem pamięci
komponentu właściciela zostaje także zwolniona pamięć posiadanych przez niego obiektów.
Rozdzia³ 5.
♦ Model komponentów wizualnych
185
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
185
Rysunek 5.1.
Inspektor Obiektów
właściwości. Zarówno rozmiar, jak i położenie okna Inspektora Obiektów może być
zmieniane. Osobiście wolę, gdy Inspektor Obiektów jest tak wysoki jak tylko na to pozwa-
lają rozmiary ekranu. W takim przypadku mogę widzieć maksymalną liczbę właściwości
w jednej chwili. Odszukaj wśród właściwości formularza właściwość
Left
, a następnie
kliknij na niej. Zmień teraz jej wartość (dowolna wartość pomiędzy 0 i 600) i naciśnij
ENTER
. Zauważ, że gdy tylko zmieniłeś tę wartość, formularz zmienił swe położenie.
Powyżej został ukazany ważny aspekt właściwości: są one czymś więcej niż tylko zwy-
kłymi, prostymi polami klasy. Co prawda każda właściwość jest związana z pewnym
polem danych, jednakże właściwość sama w sobie nie jest polem danych klasy. Zmieniając
bowiem wartość właściwość, często prowadzimy do wykonania poza naszą wiedzą ja-
kiegoś kawałka kodu.
Właściwości często są powiązane z metodami dostępowymi, które są wy-
konywane, gdy właściwość zostanie zmodyfikowana lub odczytana.
Zmiana wartości właściwości
Właściwości mogą być modyfikowane zarówno w fazie projektowania (gdy projektu-
jesz swój formularz), jak i w fazie wykonywania (kiedy program jest wykonywany
zgodnie z kodem, który stworzyłeś). W każdym przypadku właściwość posiada metodę
dostępu, która zostaje wykonana, gdy tylko właściwość ta ulegnie zmianie. Z przykła-
dem zmiany wartości właściwości w fazie projektowania miałeś już do czynienia, kiedy
zmieniłeś właściwość
Left
, czego wynikiem było przesunięcie formularza na ekranie.
Jedną z zalet VCL, która bardzo dobrze jest wykorzystywana przez Delphi, jest to, że
już podczas fazy projektowania możesz na ekranie zobaczyć efekt zmiany właściwości.
Nie wszystkie jednak właściwości powodują widoczną zmianę formularza w trakcie
projektowania. Mimo wszystko, jeśli istnieje tylko taka możliwość, wynik zmiany
wartości właściwości ma natychmiastowe odzwierciedlenie w wyglądzie formularza.
186
Część I
186
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
Aby zmienić właściwość w fazie wykonywania programu, przypisujesz jej po prostu
nową wartość. Gdy to zrobisz, VCL wykona jakby „za kulisami” (bez Twojej wiedzy)
metodę dostępową odpowiadającą tej właściwości. Aby w trakcie wykonywania zmienić
właściwość
Left
, użyj następującego kodu:
Left := 200;
W przypadku właściwości
Left
(a także
Top
) VCL przesuwa oraz powtórnie rysuje
formularz. (Jeśli jesteś programistą Windows API, możesz się domyślać, że powyższy
kod jest ostatecznie odpowiedzialny za wykonanie następujących funkcji Windows API
:
SetWindowPos
oraz
InvalidateRect
.)
Specyfikatory dostępu do właściwości (Property Access Specifiers) Wła-
ściwości posiadają dwa specyfikatory dostępu (access specifiers), które są
wykorzystywane, gdy właściwości są odczytywane lub modyfikowane. Są
nimi specyfikator odczytu (ang. read specifier) oraz specyfikator zapisu
(ang. write specifier).
Wystarczy powiedzieć, że specyfikatory dostępu wiążą metody odczytu i zapisu z właści-
wością. Kiedy właściwość jest odczytywana lub zapisywana, automatycznie wykonują
się związane z nią metody dostępowe. Kiedy wykonujesz przypisanie takie jak w po-
przednim przykładzie, odwołujesz się do specyfikatora zapisu. W efekcie VCL sprawdza,
czy istnieje odpowiednia metoda dostępu dla specyfikatora zapisu. Jeśli tak, metoda ta
zostaje wykonana. Jeśli taka metoda nie istnieje, VCL przypisuje tylko nową wartość do
pola danych związanych z właściwością.
Kiedy odwołujesz się do właściwości (to znaczy – używasz jej po prawej stronie operatora
przypisania), odwołujesz się wtedy do specyfikatora odczytu:
X := Left;
W tym wypadku VCL odwołuje się do specyfikatora odczytu w celu odczytu wartości
właściwości
Left
. W wielu wypadkach specyfikator odczytu nie wykonuje nic więcej
poza podaniem aktualnej wartości właściwości.
Atrybuty Właściwości (Property Attributes)
Atrybuty właściwości są zdeterminowane przez twórcę komponentu. Właściwość może
być tylko do odczytu – może ona zostać tylko odczytana, jednak nie można zmienić jej
wartości. Właściwość może również zostać określona jako „tylko do zapisu” (write-only)
– spotyka się to jednak dość rzadko.
Wreszcie, niektóre właściwości mogą być wyspecyfikowane jako dostępne tylko w fa-
zie wykonywania programu (runtime-only). Tego typu właściwość może być dostępna
tylko podczas wykonywania programu, a nie w fazie projektowej. Ponieważ właściwość
ta nie jest wykorzystywana w fazie projektowania, nie jest ona wyświetlana w Inspektorze
Obiektów.
Rozdzia³ 5.
♦ Model komponentów wizualnych
187
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
187
Typy Właściwości (Property Types)
Niektóre właściwości (same będące klasami – przyp. red.) wykorzystują instancje in-
nych klas biblioteki VCL w charakterze swoich właściwości. Aby to przyjrzeć się temu
dokładniej, wstawmy do naszego pustego formularza komponent
Memo
:
1.
W Palecie Komponentów wybierz przycisk
Memo
(znajduje się on na stronie
Standard
) (gdy będziesz nad przyciskiem
Memo
, pokaże się wskazówka z nazwą
komponentu.)
2.
Przesuń teraz kursor myszki nad formularz i kliknij w miejscu, gdzie ma znaj-
dować się lewy górny róg komponentu
Memo
.
Komponent pojawi się na formularzu, zaś Inspektor Obiektów pokaże jego
właściwości.
3.
Zlokalizuj właściwość
Lines
i kliknij ją. Zwróć uwagę na to, że wartością wła-
ściwości jest tekst (
TStrings
) i że na prawo od wartości właściwości widnieje
mały przycisk z wielokropkiem (…) .
Przycisk z wielokropkiem oznacza, że właściwość może podlegać edycji za
pomocą odpowiedniego edytora. Na przykład – dla tablicy łańcuchów poka-
że się okienko dialogowe, w którym będziesz mógł edytować łańcuchy tek-
stowe. W przypadku właściwości
Font
, naciśnięcie przycisku (…) wywoła
okno dialogowe wyboru czcionki. Dokładny typ edytora zależy od specyfiki
właściwości, chociaż pewne właściwości mogą współużytkować wspólne
edytory. Edytor można wywołać klikając na przycisku (…) lub przez po-
dwójne kliknięcie na wartości właściwości.
Właściwość
Lines
jest dla komponentu
Memo
instancją klasy
TStrings
. Kiedy dwukrot-
nie klikniesz na polu wartości, pokaże się edytor łańcuchów, w którym będziesz mógł
wpisać łańcuchy tekstowe, które pojawią się w komponencie
Memo
po uruchomieniu
programu. Jeśli chcesz, aby komponent
Memo
pozostał pusty po uruchomieniu, musisz
całkowicie wyczyścić zawartość łańcuchów w edytorze łańcuchów.
Właściwość
Font
jest jeszcze jednym przykładem właściwości, która jest instancją klasy
VCL. Określa ona poszczególne aspekty czcionki, jak krój pisma (typeface), kolor, rozmiar
itd. Zlokalizuj teraz właściwość
Font
w Inspektorze Obiektów (nieważne czy wcześniej
wybrałeś
Memo
, czy formularz.)
Zauważ, że przed słowem
Font
widnieje znak plusa. Oznacza to, że w zakresie tej wła-
ściwości istnieją indywidualne właściwości, które można ustawić. Gdy dwukrotnie
klikniesz nazwę wartości, Inspektor Obiektów rozciągnie się, ukazując indywidualne
elementy właściwości. Możesz teraz poddać te elementy samodzielnej edycji (tzn.
ustawić każdy z osobna). W przypadku właściwości
Font
te same właściwości mogą
być ustawione przy pomocy edytora. Możesz stosować obydwie metody z takim samym
skutkiem.
188
Część I
188
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
Niektóre właściwości to mają charakter zbiorowy (o zbiorach – ang. sets – wspomina-
łem w rozdziale 3). Dobrym przykładem właściwości zbiorowej zbioru jest właściwość
Style
zawarta wewnątrz obiektu
Font
. Zwróć uwagę, że z przodu właściwości
Style
widnieje znak plusa. Gdy dwukrotnie klikniesz na właściwości
Style
, rozwinie się ona,
ujawniając elementy zbioru. W tym przypadku zbiór składa się z różnych stylów fon-
tów: pogrubienie (bold), pochylenie (italic), podkreślenie (underline) oraz przekreślenie
(strikeout). Klikając dwukrotnie na danym rodzaju stylu włączasz go do zbioru lub z niego
wyłączasz
Niektóre właściwości mogą być typu wyliczeniowego (tzn. mogą być listą
możliwych wyborów).
Wyliczenie (enumeration) jest listą możliwych do wyboru wartości dla danej właściwo-
ści. Kiedy w Inspektorze Obiektów klikniesz na właściwość wyliczeniową, na prawo od
wartości pokaże się strzałka listy rozwijanej. Aby zobaczyć możliwe do wyboru warto-
ści, naciśnij przycisk ze strzałką, a ukaże się rozwijana lista wyboru. Możesz także
dwukrotnie kliknąć na wartości właściwości. Po każdej takiej operacji, Inspektor
Obiektów cyklicznie zmienia wartość właściwości zgodnie z kolejnością elementów na
liście wyboru. Dobrym przykładem właściwości wyliczeniowej jest właściwość
Cursor
.
Odszukaj ją, a następnie kliknij przycisk ze strzałką w celu wyświetlenia możliwych do
wyboru rodzajów kursora.
Podstawowa różnica pomiędzy właściwościami zbiorowymi, a wyliczeniowymi jest taka,
że w przypadku tych ostatnich może zostać wybrana tylko jedna z wartości (przykładowo
– tylko jeden rodzaj kursora może być ustawiony w danym momencie). Z kolei zbiór
może być pusty albo może zawierać dowolną liczbę elementów (przykładowo – czcionka
może nie mieć ustawionego żadnego stylu lub może równocześnie być pogrubiona,
podkreślona oraz pochylona).
Tak długo, jak masz uruchomione Delphi wraz z pustym formularzem, możesz poświęcić
trochę czasu, aby zbadać różne komponenty i ich właściwości. W takim razie zaczynaj.
Ja mogę poczekać.
Metody
Metody przedstawiłem w rozdziale 3 dlatego nie zamierzam tutaj ponownie opisywać
ich w najmniejszych szczegółach. Metody komponentów VCL są funkcjami i procedurami,
które mogą być wywołane po to, aby komponent wykonał pewną akcję. Na przykład
wszystkie komponenty wizualne mają metodę
Show
, która wyświetla komponent, oraz
metodę
Hide
, która komponent ukrywa:
MyWindow.Show;
…
{ tutaj coś się 'wykonuje – jakiś kawałek kodu}
…
MyWindow.Hide;
Metody w VCL mogą być zadeklarowane jako publiczne (
public
), chronione (
protected
)
oraz prywatne (
private
). Do metod publicznych mają dostęp użytkownicy komponentu.
W tym przykładzie zarówno metody
Show
jak i
Hide
są metodami publicznymi. Do
Rozdzia³ 5.
♦ Model komponentów wizualnych
189
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
189
Podstawowe zasady: Właściwości
υ
Właściwości wyglądają jak pola klas oraz posiadają podobne do
nich zasady dostępu.
υ
Właściwości nie są jednak polami klas. Są specjalną kategorią
składników klasy.
υ
Często (lecz nie zawsze) podczas przypisywania właściwości warto-
ści, jest wykonywana odpowiednia metoda dostępowa. Wszystko
zależy od tego, jak dana właściwość została zdefiniowana.
υ
Właściwości upublicznione (
published
) posiadają często wartości
domyślne. Wartość domyślna to wartość, która pojawia się w In-
spektorze Obiektów zaraz po tym jak komponent jest po raz pierw-
szy wykorzystywany. Jest to także wartość, która zostanie użyta,
gdy nie przypisze się właściwości żadnej wartości.
υ
Właściwości mogą być zaprojektowane jako tylko do odczytu, tylko
do zapisu lub zarówno do zapisu i odczytu.
υ
Właściwości działające tylko w czasie wykonywania programu
(runtime-only properties) nie są uwidaczniane w Inspektorze
Obiektów i mogą być modyfikowane tylko w fazie wykonywania
programu.
υ
Właściwości mogą stanowić:
υ
Proste typy danych
υ
Łańcuchy tekstowe
υ
Tablice
υ
Zbiory
υ
Typy wyliczeniowe
υ
Obiekty klas VCL
metod chronionych danego komponentu nie mają dostępu jego użytkownicy, a jedynie
jego komponenty pochodne. Metody prywatne mogą oczywiście być tylko wykorzy-
stywane w zasięgu klasy.
Niektóre metody pobierają parametry i zwracają wartości. Inne z kolei tego nie czynią.
Zależy to całkowicie od tego, jak metoda została napisana przez autora komponentu. Na
przykład metoda
GetTextBuf
podaje tekst zawarty w komponencie
TEdit
. Metoda ta
może posłużyć do otrzymania tekstu z pola edycji (komponentu
EditControl
) :
var
Buff
: array [0..255] of Char;
NumChars
: Integer;
begin
NumChars := EditControl.GettextBuf(Buff, SizeOf(Buff));
end;
190
Część I
190
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
Podstawowe zasady: Metody
υ
Metody mogą być prywatne (
private
), chronione (
protected
)
lub publiczne (
public
).
υ
Metody mogą pobierać parametry oraz zwracać wartości.
υ
Niektóre metody nie pobierają żadnych parametrów oraz nic nie
zwracają.
υ
Użytkownicy komponentu mogą wywoływać tylko metody pu-
bliczne.
Jak można zauważyć, ta szczególna metoda pobiera dwa parametry oraz zwraca liczbę
całkowitą (
integer
). Kiedy zostanie wywołana powyższa metoda, zawartość pola edycji
zostanie umieszczona w zmiennej
Buff
oraz zwrócona zostanie liczba znaków uzyskanych
z pola edycji.
Na razie to wszystko, co musisz wiedzieć o metodach. Więcej o nich opowiem w roz-
dziale 20.
Zdarzenia
Mówi się, ze system Windows jest środowiskiem sterowanym zdarzenia-
mi (event-driven). Sterowanie zdarzeniami oznacza tutaj, że programem
kierują zdarzenia, które występują w ramach środowiska Windows. Za zda-
rzenie możemy tutaj uznać m.in. ruchy myszy, naciśnięcie przycisków my-
szy oraz wciśnięcie klawisza klawiatury.
Dla programistów, którzy zajmowali się programowaniem pod DOS-em, czy też progra-
mowaniem komputerów mainframe, koncepcja czegoś, co jest kierowane zdarzeniami
może wydać się trochę trudna. Program dla Windows, odwołując się do systemu, nie-
ustannie sprawdza, czy w środowisku Windows nie nastąpiło jakieś zdarzenie. W skład
zdarzeń Windows zaliczamy m.in. aktywacje menu, naciśnięcie przycisku, przesunięcie
okienka, potrzebę odświeżenia wyglądu okienka, aktywację okienka i wiele innych.
Windows zawiadamia program o zdarzeniu wysyłając odpowiedni komunikat (message).
Istnieje ponad 200 możliwych komunikatów, które Windows może wysłać do aplikacji.
Jest więc tego sporo. Na szczęście programując w Delphi nie musisz ich wszystkich
znać; w zasadzie najczęściej używa się tylko około 20 z nich.
Zdarzenia VCL
W przypadku VCL za zdarzenie uznaje się wszystko, co zdarzy się w komponencie, a co
może być ważne dla użytkownika. Każdy komponent jest tak projektowany, aby mógł
odpowiadać na pewne zdarzenia. Najczęściej jest to zdarzenie systemu Windows, ale
równie dobrze może to być zupełnie inna rzecz. Na przykład komponent typu przycisk
jest tak zaprojektowany, aby na kliknięcie myszy odpowiadał w sposób wyspecyfiko-
wany przez użytkownika. Jednak w przypadku komponentu niewidzialnego takiego jak
Rozdzia³ 5.
♦ Model komponentów wizualnych
191
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
191
np. komponent obsługi baz danych, może on odpowiadać na zdarzenie nie generowane
przez Windows, na przykład oznaczającego osiągnięcie przez użytkownika końca tabeli
danych.
Obsługa zdarzeń (Handling Events). Odpowiedź na zdarzenie można na-
zwać obsługą zdarzenia.
Zdarzenia są obsługiwane przez metody zwane procedurami obsługi zdarzeń (event
handlers). Procedur tych używałeś dość intensywnie przechodząc przez pierwsze trzy
rozdziały książki. Typowy program dla Windows przez większość swojego czasu pozo-
staje bezczynny (idle), a jedynym jego zadaniem jest oczekiwanie na jakieś zdarzenie.
Dzięki VCL obsługa zdarzeń staje się dziecinnie prosta. Zdarzenia, które może obsłużyć
dany komponent są przedstawione w Inspektorze Obiektów pod zakładką zdarzeń
(Events). Nazwy zdarzeń są opisem zdarzenia, na które odpowiadają. Na przykład, zda-
rzenie obsługi kliknięcie myszą ma nazwę
OnClick
(czyli „przypadku kliknięcia”).
Nie musisz obsługiwać każdego zdarzenia, na obsługę którego pozwala dany
komponent. Tak naprawdę raczej rzadko będziesz to robił. Jeśli nie odpo-
wiesz na dane zdarzenie, komunikat dotyczący tego zdarzenia albo zostanie
odrzucony, albo obsłużony w standardowy, zdefiniowany przez VCL (lub
sam komponent) sposób. Powinieneś obsługiwać tylko zdarzenia, które
chcesz wykorzystać, a resztę ignorować.
Wszystkie te stwierdzenia będą miały większy sens, gdy wykorzystasz je w praktyce.
Tworząc nową aplikację zacznijmy nasze ćwiczenia. Z menu głównego wybierz opcję
File | New Application
. Jeśli zostaniesz zapytany o zapisanie obecnego projektu,
odpowiedz przecząco. Teraz powtórnie będziesz miał czysty formularz. Po pierwsze za-
projektuj główny formularz:
1.
Zmień właściwość
Name
na
PMEForm
(ang. PME – properties, methods, events,
czyli „właściwości, metody, zdarzenia”).
2.
Zmień właściwość
Caption
na
PME Test Program
.
Następnym krokiem będzie dodanie komponentu
Memo
:
1.
W palecie komponentów wybierz zakładkę
Standard
, a następnie kliknij przycisk
Memo
.
2.
Kliknij gdziekolwiek na formularzu, aby umieścić tam komponent
Memo
.
3.
Zmień wartość
Name
na
Memo
. Wcześniej upewnij się, czy komponent
Memo
jest
rzeczywiście aktualnie wybranym komponentem, w przeciwnym bowiem
przypadku mógłbyś niechcący zmienić nazwę formularza.
4.
Dwukrotnie kliknij na właściwości
Lines
w kolumnie wartości. Pokaże się
edytor listy łańcuchów tekstowych.
192
Część I
192
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
5.
Wykasuj słowo
Memo
i wpisz tam tekst postaci „A test program using proper-
ties, methods and events”. W celu zamknięcia edytora łańcuchów kliknij OK.
6.
Zmień rozmiary komponentu
Memo
, tak aby zajmował większą część formularza.
Na dole pozostaw miejsce na przyciski.
Twój formularz powinien przypominać rysunek 5.2.
Rysunek 5.2.
Formularz wraz
z komponentem
Memo
Możesz teraz na formularzu umieścić przycisk:
1.
Na palecie komponentów wybierz zakładkę
Standard
, a następnie wybierz
komponent
Button
.
2.
Kliknij na formularzu poniżej komponentu
Memo
, aby umieścić w tym miejscu
przycisk.
3.
Ustaw właściwość
Name
na
Button
.
4.
Zmień
Caption
na
Pokaż / Ukryj
.
5.
Wyśrodkuj przycisk w poziomie.
Komponenty możesz wyśrodkować w sposób „ręczny”, ale dokładniejszą
metodą jest użycie Palety Wyrównywania (Alignment Palette). Z menu
głównego wybierz
View | Alignment palette
. W oknie, które się po-
jawi, kliknij następnie przycisk
Center horizontally in window
w
celu poziomego wyśrodkowania komponentu w stosunku do formularza.
Przycisku
Button
będziesz używał do naprzemiennego pokazywania oraz ukrywania
komponentu
Memo
. Teraz musisz napisać trochę kodu, aby po kliknięciu twojego przyci-
sku coś się działo. Najpierw upewnij się, że przycisk jest wybrany, a następnie kliknij
na zakładce
Events
Inspektora Obiektów.
Rozdzia³ 5.
♦ Model komponentów wizualnych
193
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
193
Pojawi się lista zdarzeń obsługiwanych przez komponent
Button
. Pierwszym od góry
zdarzeniem powinno być
OnClick
. Kliknij dwukrotnie na kolumnie jego wartości; to co
się teraz stało, jest jedną z najwspanialszych rzeczy związanych z programowaniem wi-
zualnym. Na wierzchu pojawił się Edytor Kodu, w którym zostało przygotowane miejsce
na wpisanie kodu procedury
OnClick
. Rysunek 5.3 przedstawia Edytor Kodu wraz
z podprogramem obsługi zdarzenia
OnClick
.
Rysunek 5.3.
Edytor Kodu Delphi
zawierający
podprogram obsługi
zdarzenia OnClick
Twój Edytor Kodu może nieco się różnić od tego przedstawionego na ry-
sunku. Usunąłem z niego Eksplorator Modułów (Module Explorer), aby
ukazać więcej kodu. Jedną ze wspanialszych właściwości Delphi IDE jest
jego pełna elastyczność oraz możliwość dowolnej konfiguracji. Jeśli nie
podoba Ci się standardowy układ, możesz zawsze go zmienić.
Dodawanie kodu do podprogramu obsługi
Zwróć uwagę, że główny szkielet podprogramu obsługi zdarzenia został już za Ciebie
stworzony. Wszystko co musisz wykonać, to wpisanie odpowiedniego kodu. Jeśli dokład-
nie przyjrzysz się podprogramowi obsługi zdarzenia, zauważysz, że jest to procedura,
której nadano nazwę
ButtonClick
, która jest składnikiem klasy
TPMEForm
, i która jako
parametr pobiera wskaźnik do obiektu typu
TObject
nazwanego
Sender
. (O parametrze
Sender
powiem teraz tylko kilka słów.) Jedyną rzeczą, która pozostała do zrobienia, jest
napisanie kodu, który po każdym naciśnięciu przycisku chowałby lub pokazywał kompo-
nent
Memo
. Pożyczymy sobie trochę kodu z naszych poprzednich rozważań nad metodami.
Zredaguj metodę
ButtonClick
, tak aby miała następującą postać:
procedure TPMEForm.ButtonClick(Sender: TObject);
const
IsVisible : Boolean = False;
begin
IsVisible := not IsVisible;
194
Część I
194
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
if IsVisible
then
Memo.Hide
else
Memo.Show;
end;
Na początku zostaje zadeklarowana stała, którą nazwano
IsVisible
.
Stała, która ma określony typ, użyta w ten sposób jest w istocie zmienną
statyczną, która dzięki temu że istnieje nawet gdy procedura jest nieaktyw-
na, zachowuje swoją wartość pomiędzy wywołaniami procedury lub funk-
cji.
Pierwsza linia kodu powyższej metody zmienia wartość logiczną zmiennej na
True
, jeśli
wcześniej było
False
– i vice versa. Działa to mniej więcej w ten sposób :
1.
Na początek zmienna statyczna ma wartość
False
. Podczas pierwszego wywoła-
nia metody obsługi zdarzenia, wartości zostaje przypisana wartość
NOT False
,
czyli
True
.
2.
Podczas następnego wywołania metody, zmiennej
IsVisible
zostaje przypisa-
na wartość
NOT True
.
3.
Podczas każdego wywołania metody zmienna
IsVisible
zawiera wartość
przeciwną do tej, którą posiadała podczas wcześniejszego wywołania. Instrukcja
warunkowa
if…then…else
wywołuje – w zależności od wartości
IsVisible
–
odpowiednio procedurę
Show
lub
Hide
.
To wszystko. Czy to jednak naprawdę działa? Przekonajmy się. Naciśnij przycisk
Run
znajdujący się na pasku przycisków. Po skompilowaniu, program zostaje uruchomiony
i komponent
Memo
pojawia się na ekranie. Tak, to chwila prawdy. Kliknij przycisk –
komponent
Memo
zniknął. Kliknij ponownie przycisk – komponent
Memo
znowu się pojawił.
Hurra, działa!
Gdy już pobawisz się programem, zamknij go (naciśnij przycisk zamknięcia programu,
który znajdziesz w prawym górnym rogu paska tytułowego) i wróć do Edytora Kodu.
Przed dalszą pracą zapisz projekt. Z menu głównego wybierz
File | Save All
. Pierw-
szą rzeczą, o którą zostaniesz zapytany, będzie nazwa modułu (pliku źródłowego).
Wpisz tutaj
PMEMain
, a następnie wciśnij
OK
. Następnie zostaniesz poproszony o wpisanie
nazwy projektu. Wpisz tutaj
PMETest
, a następnie naciśnij przycisk
OK
.
Używanie właściwości Visible
Praca ze zmienną
IsVisible
jest trochę niewygodna. Powróćmy do rozważań nad wła-
ściwościami. Czyż nie byłoby miło, gdyby komponent
Memo
miał właściwość określającą,
czy jest on aktualnie widoczny, czy też ukryty. Czy coś takiego istnieje ? Oczywiście.
Jak łatwo możemy się domyślić, właściwość tę nazwano
Visible
. Spróbujmy ją wykorzy-
Rozdzia³ 5.
♦ Model komponentów wizualnych
195
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
195
stać. Zredaguj powtórnie podprogram obsługi zdarzenia, aby wyglądał jak na poniższym
wydruku :
procedure TPMEForm.ButtonClick(Sender: TObject);
begin
if Memo.Visible
then
Memo.Hide
else
Memo.Show;
end;
Naciśnij teraz ponownie przycisk
Run
. Pojawił się program, który dokładnie wykonuje
twoje zamierzenia. W jednym przykładzie opanowałeś właściwości, metody oraz zdarzenia.
Nie gorączkuj się tak. Spokojnie. Będzie tego trochę więcej.
Parametr Sender
Jak mogłeś zauważyć, metoda
ButtonClick
otrzymuje wskaźnik do obiektu typu
TObject
o nazwie
Sender
(wszystkie zmienne reprezentujące obiekty są w Delphi wskaźnikami).
Każdy podprogram obsługi zdarzenia w Delphi posiada przynajmniej parametr
Sender
.
W zależności od zdarzenia podprogram obsługi może mieć także jeden lub więcej pa-
rametrów dodatkowych. Na przykład, podprogram obsługi zdarzenia
OnMouseDown
ma
postać typu:
procedure TPMEForm.FormMouseDown(Sender: Tobject;
Button: TmouseButton; Shift: TShiftState; X, Y: Integer);
begin
end;
W powyższej procedurze dowiadujesz się, który przycisk został wciśnięty, które klawi-
sze na klawiaturze były wciśnięte w momencie, gdy naciśnięto klawisz myszy – oraz
otrzymujesz współrzędne kursora podczas tego zdarzenia. Programowi obsługi zdarzenia
zostaje dostarczona pełna informacja, która jest niezbędna do właściwej obsługi tegoż
zdarzenia.
Po co w takim razie jest parametr
Sender
? Otóż jest on wskaźnikiem do komponentu,
który wysyła komunikat do procedury obsługi zdarzenia. W tym akurat przykładzie, para-
metr
Sender
nie jest specjalnie użyteczny, gdyż wiemy , że nadawcą komunikatu jest
przycisk
Pokaż/Ukryj
. Istnienie parametru
Sender
pozwala na użycie tej samej procedury
obsługi zdarzenia przez więcej niż jeden komponent.
Aby to zobrazować, stwórzmy drugi przycisk. Jeden przycisk będzie odpowiedzialny za
ukrywanie komponentu
Memo
(nadajmy mu nazwę
Ukryj
), a drugi będzie służył do po-
kazywania komponentu
Memo
:
1.
Jeśli aktualnie jesteś w Edytorze Kodu, naciśnij F12, aby przełączyć się do
Projektanta Formularzy.
2.
Klikając na przycisku
Show / Hide
wybierz go. Ustaw właściwość
Name
na
Show
, a
Caption
na
Show
.
196
Część I
196
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
3.
Na prawo od przycisku
Show
dodaj nowy przycisk. Aby nadać formularzowi
równomierny wygląd, uporządkuj przyciski.
4.
Ustaw właściwość
Name
nowego przycisku na
Hide
. Właściwość
Caption
zmieni się automatycznie również na
Hide
.
5.
Naciśnij teraz przycisk
Show
, a następnie w Inspektorze Obiektów wybierz
kartę
Events
. Zwróć uwagę, że zdarzenie
OnClick
, ma teraz nazwę
ShowClick
.
Zmień ją ponownie na
ButtonClick
(Początkowa nazwa procedury obsługi zda-
rzenia, jest nazwą domyślną, jeśli chcesz, możesz ją zmienić na dowolną inną).
6.
Kliknij przycisk
Hide
, a następnie w Inspektorze Obiektów odszukaj zdarzenie
OnClick
. Kliknij przycisk ze strzałką i wybierz listy
ButtonClick
( tak naprawdę,
będzie tam tylko jedna pozycja do wybrania).
7.
Kliknij dwukrotnie na
ButtonClick
. Znajdziesz się w Edytorze Kodu z kursorem
w metodzie
ButtonClick
; zmodyfikuj teraz jej kod :
procedure TPMEForm.ButtonClick(Sender: TObject);
begin
if Sender = Hide
then
Memo.Hide
else
Memo.Show;
end;
Twój formularz powinien przypominać rysunek 5.4. Skompiluj i uruchom program.
Kliknij na każdym z przycisków, aby upewnić się, czy program działa poprawnie.
Rysunek 5.4.
Formularz,
do którego dodano
wszystkie
komponenty
Właśnie stworzyłeś pojedynczą metodę obsługi zdarzenia, która obsługuje zdarzenia dla
dwóch przycisków. Wykorzystujesz tutaj parametr
Sender
, aby zdecydować, od którego
przycisku pochodzi zdarzenie
OnClick
, w wyniku czego ukrywasz lub pokazujesz kompo-
nent
Memo
. Mógłbyś oczywiście stworzyć osobną procedurę obsługi zdarzenia
OnClick
dla każdego z przycisków, ale forma kodu przedstawiona tutaj jest bardziej zwięzła. Poza
tym jest to świetna ilustracja wykorzystania parametru
Sender
.
Rozdzia³ 5.
♦ Model komponentów wizualnych
197
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
197
Podstawowe zasady : Zdarzenia
υ
Jeśli trzeba, możesz obsłużyć dowolne zdarzenie komponentu
υ
Nie musisz odpowiadać na wszystkie zdarzenia definiowane przez
komponent
υ
Zdarzenia są obsługiwane przez metody obsługi zdarzeń, zwane pro-
cedurami zdarzeniowymi
υ
Wiele komponentów może współdzielić tą samą wspólną procedurę
obsługi zdarzenia
υ
Nazwy procedur obsługi zdarzeń stworzone przez Delphi są nazwami
domyślnymi i mogą zostać zmienione według upodobań programisty
υ
Nazwę procedury obsługi zdarzenia zmieniaj tylko w Inspektorze
Obiektów
υ
Parametr
Sender
zawarty w procedurze obsługi zdarzenia może zo-
stać wykorzystany do określenia komponentu, który wygenerował ob-
sługiwane zdarzenie
υ
Podwójne kliknięcie na nazwie procedury obsługi zdarzenia
w Inspektorze Obiektów przenosi Cię do Edytora Kodu w miejsce,
gdzie znajduje się sekcja dotycząca procedury obsługi zdarzenia. Je-
śli takiej procedury nie będzie, Delphi utworzy szkielet procedury.
υ
Każda procedura obsługi zdarzenia zawiera wszystkie parametry, któ-
re są niezbędne do właściwej obsługi tego zdarzenia
Zwróć uwagę na porównanie wartości zmiennej
Sender
z właściwością
Name
komponentu.
Ponieważ oba są wskaźnikami, porównanie ma na celu stwierdzenie, czy wskazują one
ten sam adres.Krok 6 poprzedniego ćwiczenia pokazuje ważną rzecz. Po stworzeniu
procedury obsługi zdarzenia
OnClick
dla konkretnego komponentu, ta sama procedura
może stać się procedurą obsługi zdarzenia
OnClick
generowanego przez inny kompo-
nent formularza. Pozwala to na wykorzystanie tej samej procedury obsługi zdarzenia
w stosunku do wielu komponentów. Dokładniej opiszę zdarzenia w dalszych rozdziałach
tej książki.
Odkrywanie VCL
Biblioteka VCL jest świetnie zaprojektowaną biblioteką klas. Jak większość dobrych
bibliotek klas wykorzystuje ona do maksimum dziedziczenie klas. Większość biblioteki
VCL jest złożona z klas, które reprezentują komponenty. Inne klasy VCL nie mają po-
wiązania z komponentami. Klasy te wykonują nieprzyjemne zadania porządkowe (tzw.
„czarną robotę”), są klasami pomocniczymi oraz dostarczają różnych użytecznych
usług.
198
Część I
198
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
Hierarchia klas VCL związana z komponentami jest dosyć złożona. Na szczęście, aby
zacząć programować w Delphi nie musisz znać każdego detalu VCL. Na szczycie
struktury VCL znajdziesz klasę
TObject
. Rysunek 5.5 przedstawia kilka głównych klas
bazowych VCL wraz z ich klasami potomnymi.
Rysunek 5.5.
Hierarchia klas VCL
TObject
jest praprzodkiem wszystkich klas VCL reprezentujących komponenty (Pamiętaj
– wszystkie klasy w Object Pascalu są wyprowadzone z
TObject
.). Poniżej
TObject
znajduje się klasa
TPersistent
. Komponent ten jest odpowiedzialny za zdolność kompo-
nentu do zapisywania samego siebie do pliku lub pamięci, jak również za wiele innych
detali, których nie musisz znać. Jestem wdzięczny (ty także powinieneś być) za to, że
aby tworzyć większość aplikacji w systemie Delphi, nie muszę zbyt wiele wiedzieć na
temat działania
TPersistent
.
Klasa
TComponent
funkcjonuje jako bardziej bezpośrednia klasa bazowa dla większości
komponentów. Dostarcza wszelkich funkcji, które są wymagane dla poprawnej funkcjonal-
ności podstawowego komponentu. Komponenty niewidoczne (nonvisual) są bezpośrednimi
potomkami
TComponent
. Komponenty wizualne (visual) wywodzą się z klasy
TControl
,
która (jak to zostało przedstawione na rysunku 5.5) została wyprowadzona z
TComponent
.
TControl
dostarcza dodatkowych funkcji wymaganych przez komponenty wizualne.
Poszczególne komponenty są następnie potomkami
TGraphicControl
lub
TWinControl
.
Kiedy na formularzu umieścisz komponent, w deklaracji klasy formularza zostaje utworzo-
ny wskaźnik do tego komponentu, dzięki czemu masz do niego dostęp w swoim kodzie.
Jako nazwa tego wskaźnika zostaje użyta właściwość
Name
komponentu. Kiedy w przy-
kładowej aplikacji umieściłeś komponent
Memo
na formularzu, Delphi automatycznie
stworzyło pole
TMemo
i nadał jej nazwę
Memo
.
Rozdzia³ 5.
♦ Model komponentów wizualnych
199
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
199
Podobnie, kiedy na formularzu utworzyłeś przycisk, Delphi stworzył zmienną typu
TButton
, której zadaniem było reprezentowanie twojego przycisku. Przed tym jak któ-
rekolwiek z powyżej opisanych zdarzeń miało miejsce, Delphi wyprowadził nową klasę
z
TForm
oraz oczywiście stworzył na jej podstawie obiekt, który reprezentował formularz.
Pewne zrozumienie klas i komponentów VCL jest oczywiście konieczne przed dalszą
pracą z tą biblioteką. Chociaż nie mogę zrobić przeglądu wszystkich klas VCL, spróbuję
wskazać główne punkty. Przypatrzmy się zatem klasom, których będziesz najczęściej
używał.
Klasy formularzy i aplikacji
Klasy formularza i aplikacji reprezentują w VCL formularze oraz obiekt aplikacji. Klasy
te są potomkami
TComponent
i same są też komponentami. Zostały wymienione osobno,
tak aby można je było odróżnić od elementów kontrolnych (kontrolek), które umieszczasz
na formularzu.
Klasa TApplication
Klasa
TApplication
zawiera w sobie podstawowe operacje programu Windows. Klasa
ta jest odpowiedzialna za takie sprawy jak zarządzanie ikoną aplikacji, dostarczanie
pomocy kontekstowej oraz obsługa komunikatów (message handling). Każda aplikacja
w Delphi posiada wskaźnik do obiektu typu
TApplication
o nazwie
Application
. Kla-
sa
TApplication
jest głównie używana do wyświetlania okienek informacyjnych
(message boxes), zarządzania pomocą kontekstową oraz ustawiania treści podpowiedzi
dla przycisków i linii statusowej.
TApplication
jest pewnego rodzaju osobliwością
w bibliotece VCL, jako że pewne jej właściwości (
Icon
,
HelpFile
,
Title
) mogą zostać
ustawione na karcie
Application
w opcjach projektu (
Project|Options
).
Klasa TForm
Klasa
TForm
reprezentuje formularze w ramach VCL. Formularze są wykorzystywane
jako okna główne, okienka dialogowe, okna podrzędne, a także jako dowolne inne
okno, jakie tylko możesz sobie wyobrazić. Można powiedzieć, że
TForm
jest „koniem
roboczym” VCL. Ma prawie 60 właściwości, 45 metod i 20 zdarzeń. Formularze przed-
stawiłem w szczegółach w rozdziale 4.
Klasy komponentów
Ta grupa zawiera szeroki zakres klas i może być następnie podzielona na osobne kategorie,
które przedstawiam w następnych sekcjach.
Standardowe klasy komponentów
Komponenty standardowe są najbardziej popularnymi elementami sterującymi interfejsu
Windows. W ich skład wchodzą :
TButton
,
TEdit
,
TListBox
,
TMemo
,
TMainMenu
,
200
Część I
200
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
TScrollBar
,
TPopupmenu
,
TCheckBox
,
TRadioButton
,
TRadioGroup
,
TGroupBox
,
TPanel
oraz
TActionList
.
O większości tych klas nie będę tutaj pisał, gdyż hermetyzują one najbardziej powszechne
kontrolki Windows. Komponent
TMainMenu
hermetyzuje menu główne formularza. W trak-
cie projektowania dwukrotne kliknięcie na ikonie komponentu
MainMenu
wywołuje
Projektant Menu (Menu Designer).
TMainMenu
zawiera właściwości, które kontrolują
m.in. czy element menu jest w kolorze nieaktywny (jest wtedy w kolorze szarym), czy
jest zaznaczony, określają identyfikator (ID) pomocy kontekstowej, tekst podpowiedzi
elementu i inne. Każdy element menu posiada pojedyncze zdarzenie –
OnClick
, dzięki
któremu każdemu wybranemu elementowi menu możesz przypisać odpowiednią procedurę
obsługi zdarzenia. W następnym rozdziale przedstawię więcej szczegółów dotyczących
menu oraz Projektanta Menu.
Komponent TPanel
Kolejnym godnym zainteresowania komponentem standardowym jest
TPanel
.
Panel jest prostokątnym obszarem na formularzu, który wraz z własnymi
komponentami może być traktowany jako pojedyncza jednostka.
Panel
jest komponentem grupującym. Z tego powodu może on zawierać inne komponenty.
Panele posiadają właściwości, które kontrolują jego typ krawędzi (panel wypukły, wklę-
sły, płaski) oraz grubość ramki. Kombinacje tych właściwości dają dużą różnorodność form
paneli.
Komponent TActionList
Nowością w Delphi 4 jest komponent
TActionList
. Komponent ten może zostać wykorzy-
stany do łatwej aktywacji wielu komponentów za jednym razem. Na przykład aplikacja,
która używa Schowka (Clipboard), może posiadać pozycje
Wytnij
,
Kopiuj
,
Wklej
zarówno
w menu programu, menu kontekstowym jak i na pasku narzędzi. Jeśli w Schowku znajdą
się jakieś dane, zarówno przycisk
Wklej
na pasku narzędzi, jak i elementy menu powin-
ny zostać odblokowane. Jeśli w schowku nie ma danych, przycisk oraz elementy menu
powinny zostać zablokowane. Wszystkie te elementy kontrolne (pasek narzędzi oraz
elementy menu) mogą zostać zablokowane lub odblokowane jednocześnie dzięki kom-
ponentowi
TActionList
.
Komponenty na karcie Additional
Delphi posiada pewna grupę komponentów, którą przedstawię razem z komponentami
standardowymi. Elementy te znajdują się na karcie
Additional
Palety Komponentów
i obejmują następujące klasy:
TBitBtn
,
TSpeedButton
,
TMaskEdit
,
TStringGrid
,
TDrawGrid
,
TImage
,
TShape
,
TBevel
,
TScrollBox
,
TCheckListBox
,
TSplitter
,
TStatic-
Text
oraz
TChart
. Klasa
TBitBtn
reprezentuje przycisk, który może zostać pokryty grafiką.
Innym przyciskiem posiadającym grafikę jest
TSpeedButton
, ale tak naprawdę nie jest
on prawdziwym przyciskiem. Jest on graficznym opisem przycisku. Dzięki temu mo-
Rozdzia³ 5.
♦ Model komponentów wizualnych
201
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
201
żesz używać dużej liczby tego typu komponentów nie konsumując tym samym zasobów
Windows na każdy przycisk.
Komponent
TImage
pozwala na umieszczenie wybranego z pliku obrazka na formularzu.
TBevel
umożliwia na stworzenie ramek i linii, które mogą być wypukłe lub wklęsłe.
Bevel
może zostać użyty do podzielenia formularza na pewne regiony oraz nadania
formularzowi estetycznej formy. Komponenty
TStringGrid
oraz
TDrawGrid
dostarczają
środków do prezentacji informacji w formie tabel.
Standardowe kontrolki Win32
Część z komponentów VCL hermetyzuje podstawowe kontrolki Win32. Do komponentów
tych należą m.in. :
TListView
,
TTreeView
,
TTrackBar
,
TProgressBar
,
TTabControl
,
TPageControl
,
TRichEdit
,
TImageList
,
TStatusBar
,
TAnimate
,
TDateTimePicker
,
TToolBar
,
TCoolBar
oraz kilka innych. Niektóre z nich są z natury skomplikowane,
dlatego reprezentujące je komponenty również są skomplikowane.
Możesz mi wierzyć albo nie, ale VCL znacznie upraszcza pracę z tymi pospolitymi
kontrolkami. Aby jednak dobrze zrozumieć działanie owych klas, musisz spędzić nad
nimi trochę czasu. W rozdziale 13 omówię komponenty
TToolBar
,
TCoolBar
,
TImageList
oraz
TStatusBar
.
Klasy komponentów bazodanowych
VCL zawiera mnóstwo komponentów do obsługi baz danych. W ich skład wchodzą za-
równo komponenty wizualne (visual) jak i niewidoczne (nonvisual). Niewidocznymi
komponentami są
TDataSource
,
TDatabase
,
TTable
oraz
TQuery
. Klasy te są związane
z operacjami wykonywanymi jakby „za kulisami” (bez wiedzy aplikacji).
Elementami widzialnymi, są elementy obsługi baz danych, które użytkownik może zoba-
czyć oraz na które użytkownik może interaktywnie oddziaływać. Na przykład komponent
TDBGrid
służy do wyświetlenia zawartość tablicy danych w formie tabeli (ang. grid). W ten
sposób
TDBGrid
jest pewnego rodzaju interfejsem pomiędzy użytkownikiem i bazą da-
nych. Używając
TDBGrid
użytkownik może bezpośrednio zobaczyć oraz zredagować dane
w tabeli bazy danych znajdujące się na dysku.
TDBNavigator
dostarcza przycisków, które pozwalają użytkownikowi na poruszanie się
po tabeli danych. Klasa ta zawiera m.in. przyciski typu „następny rekord”, „poprzedni
rekord”, „pierwszy rekord”, „ostatni rekord”, „anuluj edycję”, „akceptuj edycję” itp.
Inne komponenty stanowią bazodanowe mutacje standardowych kontrolek Windows,
przystosowane do współpracy z polami rekordów. Mowa tu m.in. o komponentach
TDBText
,
TDBEdit
,
TDBListBox
,
TDBImage
itp.
Grupą komponentów związaną zwykle z programowaniem baz danych są komponenty
typu
QuickReport
. Grupa ta pozwala na łatwe i przejrzyste tworzenie raportów, zwłaszcza
gdy ich źródłem jest baza danych. Komponenty tego typu opiszę w rozdziałach 16, 17 i 18.
202
Część I
202
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
Klasy reprezentujące standardowe dialogi
Windows posiada standardowe okna dialogowe służące m.in. do otwierania plików, zapisu
plików, wyboru czcionki oraz wyboru kolorów. VCL posiada odpowiednie klasy, które
reprezentują kolejne typy tych dialogów. Klasami tymi są
TOpenDialog
,
TSaveDialog
,
TOpenPictureDialog
,
TSavePictureDialog
,
TFontDialog
,
TColorDialog
,
TPrintDialog
,
TPrinterSetupDialog
,
TFindDialog
oraz
TReplaceDialog
. Wszystkie komponenty w tej
grupie są niewidoczne w tym sensie, że nie posiadają widocznego interfejsu w trakcie
projektowania. W trakcie wykonywania programu stają się one widoczne poprzez użycie
metody
Execute
.
Komponenty systemowe
Karta
System
w Palecie Komponentów zawiera mieszaninę komponentów niewidzial-
nych i komponentów widzialnych. Do reprezentacji zegara systemowego służy klasa
TTimer
.
Posiada ona jedyne zdarzenie
OnTimer
, które jest wywoływane za każdym ra-
zem, gdy minie pewna określona ilość czasu. Odstęp czasu, który musi upłynąć między
wywołaniami zdarzenia
OnTime
jest ustawiany jako właściwość
Interval
.
TTimer
jest
komponentem niewidzialnym.
Do grupy komponentów systemowych należy również klasa
TMediaPlayer
. Umożliwia
ona na odgrywanie plików medialnych takich jak np. audio WAV, video AVI, audio
MIDI. Nośnik taki może być odgrywany, zatrzymany, ustawiony w konkretnym miej-
scu pliku. Można na nim wykonywać jeszcze wiele innych, różnych operacji. Klasa ta
zawiera wiele właściwości i zdarzeń, które w znacznym stopniu upraszczają złożoność
świata MCI (ang. Media Control Interface – interfejs kontroli i dostępu do mediów).
Klasa
TpaintBox
wykorzystuje swoiste „płótno” (ang. canvas), na którym możesz rysować
cokolwiek zechcesz. Ma on wiele potencjalnych zastosowań. Grupa komponentów sys-
temowych zawiera ponadto klasy odpowiedzialne za OLE oraz dynamiczną wymianę
danych DDE.
Grupa komponentów Win 3.1
Nie bądź nierozsądny, automatycznie odrzucając tę grupę komponentów i to tylko
z powodu jej nazwy. Grupa ta zawiera kilka świetnych komponentów (Karta Win 3.1
ma swe korzenie w Delphi 1). Osobiście szczególnie lubię komponenty
TTabSet
oraz
TNotebook
. Grupa ta zawiera również sporo klas, które umożliwią Ci budowę własnych
dialogów typu
File Open
oraz
File Save
. Klasami tymi są
TFileListBox
,
TDirectoryListBox
,
TDriveComboBox
oraz
TFilterComboBox
.
Komponenty związane z Internetem
W zależności od tego, którą wersję Delphi (Standard, Professional, Client/Server) po-
siadasz, możesz mieć (ale nie musisz) kartę
Internet
. Zawiera ona komponenty służące
do obsługi Internetu. Można do nich m.in. zaliczyć komponenty typu
HTML
,
FTP
,
SMTP
,
POP3
oraz
HTTP
. Zawiera ona również komponenty służące do pisania aplikacji korzy-
stających z sieci przy pomocy interfejsu Winsock API. Większość tych komponentów to
rdzenne komponenty biblioteki VCL, chociaż przynajmniej jeden –
THTML
– jest elementem
typu ActiveX.
Rozdzia³ 5.
♦ Model komponentów wizualnych
203
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
203
Komponenty przykładowe
Karta
Samples
zawiera komponenty, które mogą zostać wykorzystane do lepszego
zrozumienia ogólnych zasad tworzenia komponentów. Ponieważ kod źródłowy tych
komponentów został dołączony do Delphi, możesz łatwo przyglądnąć się jak one działają.
W skład przykładowych komponentów wchodzą
TGauge
,
TColorButton
,
TSpinButton
,
TSpinEdit
,
TDirectoryOutline
oraz
TCalendar
.
Kontrolki ActiveX
Karta
ActiveX
zawiera kontrolki ActiveX, które możesz wykorzystać we własnych
aplikacjach. W ich skład wchodzą m.in.
ChartFX
(autorstwa Software FX),
Visual
Speller
(autorstwa Visual Components Inc.),
Formula One Spreadsheet
,
Formula One
VtChart
oraz
Graph
(trzy ostatnie stworzone przez Bits Per Second, Ltd.).
Klasy GDI
GDI (ang. Graphics Device Interface) ma spory udział w aplikacjach Windows typu
GUI. Klasy te hermetyzują m.in. bitmapy, fonty, konteksty urządzeń (DC), pędzle, pióra.
Właśnie dzięki tym obiektom GDI jest możliwe wyświetlanie tekstu oraz grafiki. Klasy
GDI nie są skojarzone z żadnym specyficznym komponentem, ale wiele komponentów
wykorzystuje instancje tych klas jako swoje właściwości. Na przykład kontrolka edycyjna
posiada właściwość
Font
, która jest instancją klasy
TFont
.
Kontekst urządzenia
(device context) jest dobrze znanym terminem dla programistów piszą-
cych programy w Windows. Jednakże w VCL termin ten nie jest zbyt często używany.
Wynika to z faktu, że VCL ukrywa konteksty urządzeń systemu Windows w klasie
TCanvas
. W VCL użyto terminu canvas (płótno) w odniesieniu do kontekstu urządzenia.
Canvas
dostarcza powierzchni, na której możesz rysować, używając metod takich jak np.
MoveTo
,
LineTo
oraz
TextOut
. Metody
Draw
i
StretchDraw
pozwalają na wyświetlanie
bitmap. Nie uważasz, że koncepcja płócien, na których możesz rysować, ma więcej sensu
niż archaiczny termin kontekst urządzenia (device context)? Operacje dotyczące grafiki
omówię dokładnie w rozdziale 12. Przedstawię teraz listę najpowszechniej używanych
klas GDI:
υ
Klasa
TCanvas
zawiera instancje innych klas GDI. Kiedy, na przykład, wykonujesz
sekwencje
MoveTo
/
LineTo
, zostaje narysowana linia przy pomocy aktualnego
koloru pióra. Właściwość
Pen
jest wykorzystywana do określenia aktualnego
koloru pióra. Jest ona instancją klasy
TPen
.
TPen
posiada właściwości, które
określają m.in. grubość linii, styl linii (ciągła, przerywana, kropkowana, itd.)
oraz tryb rysowania linii.
υ
Klasa
TBrush
reprezentuje pędzel (brush), który jest wykorzystywany podczas
operacji związanych z wypełnianiem. Jest on używany jako wzór wypełnienia
w operacjach takich jak
FillRect
,
Polygon
,
Ellipse
. W skład właściwości
TBrush
wchodzą
Color
,
Style
,
Bitmap
. Właściwość
Style
pozwala na ustale-
nie standardowego, z góry ustalonego wzoru wypełnienia. Właściwość
Bitmap
określa bitmapę wykorzystywaną jako wzór wypełnienia.
204
Część I
204
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
υ
Operacje związane z obsługą bitmap w VCL są wykonywane przez klasę
TBitmap
. Jej właściwości to m.in.
Palette
,
Height
,
Width
oraz
Transparent-
Color
. Metody to m.in.
LoadFromFile
,
LoadFromResourceID
,
SaveToFile
.
Klasa
TBitmap
jest wykorzystywana również przez inne klasy, takie jak np.
TImage
,
TBitBtn
,
TSpeedButton
. Obiekt typu
TBitmap
może zostać również
wykorzystany do operacji na bitmapach znajdujących się aktualnie nie na ekranie,
ale np. w pamięci komputera. Tego typu bitmapy są często wykorzystywane
przez aplikacje intensywnie korzystające z grafiki. Wykorzystują je one w celu
likwidacji efektu migotania (flickering) oraz poprawienia wydajności.
υ
Klasa
TFont
zajmuje się operacjami związanymi z obsługą czcionek. Jej wła-
ściwości to m.in.
Color
,
Height
,
Style
(tekst pogrubiony, tekst pochylony,
tekst normalny, itd.) Klasa
TFont
jest właściwością, którą posiadają wszystkie
komponenty wyświetlające tekst.
Oprócz wymienionych tutaj klas, istnieje jeszcze wiele innych, które są wykorzystywa-
ne jako tzw. klasy pomocnicze lub rozszerzenia klasy bazowej w celu zwiększenia jej
funkcjonalności. Podczas dalszej pracy z Delphi dowiesz się więcej o tych klasach,
a także o ich wykorzystaniu. Rysunek 5.6 przedstawia hierarchie klas VCL, które her-
metyzują operacje GDI.
Rysunek 5.6.
Hierarchia klas VCL
związanych z GDI
Klasy użytkowe
VCL zawiera wiele użytecznych klas, które możesz wykorzystywać w swoich aplikacjach.
Klasy tego typu upraszczają pewne zadania związane z programowaniem w Windows.
Na przykład klasa
TIniFile
upraszcza obsługę, zapis oraz odczyt plików konfiguracyj-
nych systemu Windows (pliki typu
.INI
). Powszechnie wiadomo, że pliki typu
.INI
są
anachronizmem. Zostały one wyparte przez Rejestr systemowy (System Registry). Aby
ułatwić obsługę Rejestru, VCL dostarcza klas
TRegistry
oraz
TRegkeyInfo
.
Klasa
TStringList
pozwala na używanie tablic łańcuchów tekstowych. Klasa ta jest
wykorzystywana przez wiele innych komponentów do przechowywania łańcuchów tek-
stowych. Na przykład, klasa
TMemo
wykorzystuje klasę
TStringList
jako właściwość
Lines
.
TStringList
posiada metody
LoadFromFile
oraz
SaveToFile
, które pozwalają
na zapis lub odczyt listy łańcuchów tekstowych z pliku. Klasę
TStringList
można
również wykorzystać do odczytu oraz zapisu plików tekstowych.
Inną użyteczną klasą VCL jest klasa
TList
. Klasa ta pozwala na tworzenie tablic
obiektów dowolnego typu. Klasa ta po prostu przechowuje listę wskaźników do obiektów.
Rozdzia³ 5.
♦ Model komponentów wizualnych
205
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
205
Główną zaletą tej klasy jest jej zdolność do dynamicznej zmiany rozmiarów tablicy,
w miarę jak nowe obiekty są dodawane lub usuwane.
VCL dostarcza również klas związanych z obsługą strumieni (strumień to w rzeczywistości
blok danych). Klasy
TStream
,
TFileStream
,
TMemoryStream
oraz
TResourceStream
po-
zwalają na odczyt i zapis danych z i do strumieni. Klasą bazową dla wszystkich tych
klas jest klasa
TStream
. Klasy
TFileStream
używa się podczas operacji związanych
z obsługą plików na dysku, klasy
TMemoryStream
do manipulacji danymi w pamięci,
TResourceStream
do wczytywania zasobów binarnych (binary resources) z plików typu
EXE i DLL. Klasy te co prawda są przeznaczone dla bardziej doświadczonych użyt-
kowników, ale stają się nieocenioną pomocą jeśli chodzi o konkretną funkcję, której
dostarczają. Aby dowiedzieć się czegoś więcej o tych klasach, zajrzyj do Pomocy Delphi
VCL (VCL Help).
To nie wszystko …
Na pewno nie przedstawiłem tutaj wszystkich klas VCL. Starałem się jednak wspo-
mnieć o klasach, które prawdopodobnie najczęściej będziesz wykorzystywał w swoich
aplikacjach.
Przewróć teraz kilka kartek do tyłu i przyjrzyj się listingowi 5.1. Pokazałem Ci tam, jak
łatwo przy pomocy Delphi załadować bitmapę z pliku, a następnie ją wyświetlić. Zrób-
my ćwiczenie, które potwierdzi ta tezę. Po pierwsze, stwórz nową aplikację. Masz teraz
przed sobą czysty formularz. Wykonaj następujące kroki:
1.
Ustaw właściwość formularza
Caption
na
Bitmap Test Program
.
2.
Kliknij na zakładkę
Additional
, która znajduje się w Palecie Komponentów.
Wybierz komponent Image i umieść go na formularzu.
3.
Odszukaj właściwość
Align
i ustaw ją na
alClient
. W następstwie tego kompo-
nent Image wypełni całą powierzchnię formularza.
4.
Odszukaj właściwość
Stretch
i ustaw ją na
True
.
5.
Odszukaj właściwość
Picture
, a następnie kliknij dwukrotnie na kolumnie
wartości.
6.
Pojawi się okienko dialogowe Edytora Rysunków (Picture Editor). Kliknij przy-
cisk
Load
. Pojawi się okno dialogowe wyboru pliku do załadowania (File Open).
7.
Wejdź do katalogu
\Program Files\Common Files\Borland Shared Files\
Images\Splash\256Color
a następnie wybierz któryś z obrazków znajdujących
się w tym katalogu (mnie spodobał się HANDSHAKE.BMP). Kliknij OK.
8.
Powróciłeś do okna dialogowego Edytora Rysunków. Bitmapa, którą wybrałeś,
jest wyświetlona w oknie podglądu. Kliknij OK. (Jeśli chcesz wybrać inny obra-
zek, naciśnij ponownie przycisk OK.). Bitmapa wypełni cały obszar formularza.
206
Część I
206
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
9.
Kliknij teraz przycisk Run. Kiedy uruchomisz aplikację, będziesz mógł dowolnie
zmieniać rozmiary okna. Pomimo zmian rozmiarów, bitmapa zawsze będzie
wypełniała cały obszar formularza.
Prawda, że to łatwe? Gdyby nie zależało Ci, aby obrazek wypełniał zawsze cały formularz,
zadanie to byłoby jeszcze prostsze. Na rysunku 5.7 został przedstawiony kompletny
program w fazie wykonywania.
Rysunek 5.7.
Program
wykorzystujący
bitmapę
Podsumowanie
W niniejszym rozdziale zdobyłeś wiedzę na temat bibliotek klas oraz sposobu, w jaki
VCL wkomponowuje się w ich strukturę. Omówiłem właściwości, metody, zdarzenia
oraz dostarczyłem Ci możliwości zdobycia pewnego doświadczenia. W rozdziale tym
zawarłem przegląd klas VCL, które najprawdopodobniej napotkasz programując w Delphi.
Nie omówiłem ich wszystkich, ale krótko wspomniałem o najczęściej używanych.
W którym kierunku podąża rynek rozwoju oprogramowania? Wygląda na to, że przy-
szłością są komponenty. Zaletą VCL jest fakt, że jeśli zechcesz (lub będziesz zmuszony)
przesiąść się na C++, nadal będziesz mógł używać tej biblioteki. Może zdziwi Cię fakt,
że prawie taki sam VCL, jaki jest wykorzystywany przez Delphi, jest również wykorzysty-
wany przez C++ Buildera. Czas, który poświęcisz na poznawanie Delphi, może na-
tychmiast zostać wykorzystany podczas programowania w C++. Niczego nie musisz
uczyć się na nowo, gdyż nadal jest to takie samo VCL.
Rozdzia³ 5.
♦ Model komponentów wizualnych
207
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
207
Warsztat
Warsztat składa się z pytań kontrolnych oraz ćwiczeń utrwalających i pogłębiających
zdobytą wiedzę. Odpowiedzi do pytań możesz znaleźć w dodatku A.
Pytania i odpowiedzi
υ
Co to jest biblioteka klas?
Biblioteka klas jest zbiorem klas, które upraszczają programowanie w Windows.
W dobrze zbudowanej bibliotece klas zawarte są założenia projektowe oraz
programowania obiektowo-zorientowanego, dając możliwość obiektowo-zoriento-
wanego podejścia do programowania w Windows.
υ
Czy VCL jest biblioteką klas?
Tak, VCL jest biblioteką klas. VCL zostało napisane w Object Pascalu, ale
współpracuje zarówno z Delphi, jak i z C++ Builderem.
υ
Wygląda na to, że najlepszym podejściem do programowania jest używanie
komponentów. Czy to prawda?
Generalnie tak. VCL jest świetnym wyborem dla aplikacji, które używają mnóstwo
okienek dialogowych oraz dla aplikacji korzystających z baz danych. Nie istnieje
prawie taka rzecz, której nie dałoby się wykonać w Delphi. Jedno jest pewne –
Delphi jest liderem wśród narzędzi typu RAD.
υ
Czy właściwości to pola danych klas?
Nie. Właściwości to szczególne twory. Niektóre właściwości po prostu ustawiają
wartości pól danych klasy. Inne, po zmodyfikowaniu, wywołują metodę, która
wykonuje specjalne operacje związane z daną właściwością. W tym przypadku
właściwość wykonuje więcej, niż tylko ustawianie wartości pola danych klasy.
υ
Czy muszę odpowiadać na każde zdarzenie, które zostało zdefiniowane w
komponencie?
Nie. Możesz obsłużyć tyle zdarzeń, ile wymaga twoja aplikacja. Jeśli chcesz,
możesz nie obsługiwać żadnego.
υ
Czy komponenty na karcie Win 3.1 są przestarzałe?
Nie wszystkie! Komponenty te były bardzo ważne w Delphi 1, gdyż Delphi 1
było 16-bitowym środowiskiem programistycznym (stąd nazwa karty – Win 3.1).
Nie oznacza to jednak, że komponenty te są przestarzałe.
υ
Widzę, że istnieje mnóstwo klas VCL. Wydawało mi się, że programowanie
w Delphi będzie łatwe.
208
Część I
208
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
Programowanie w Delphi jest o wiele łatwiejsze niż programowanie w Windows
przy użyciu narzędzi tradycyjnych. Niezależnie jednak od użytego narzędzia
programistycznego, programowanie w Windows wymaga od programisty dużego
doświadczenia i wiedzy.
Quiz
1.
Czy wszystkie komponenty są widoczne w fazie projektowania?
2.
Czy
OpenDialog
jest komponentem widocznym czy niewidocznym?
3.
Jak nazywa się klasa VCL, która reprezentuje formularz?
4.
Czy wszystkie wersje Delphi są dostarczane z tym samym zestawem kompo-
nentów?
5.
Czy ostatecznym przodkiem wszystkich klas VCL jest
TObject
?
6.
Podaj przykład komponentu niewidocznego.
7.
Czy wszystkie komponenty współdzielą pewne powszechne właściwości?
8.
Wymień dwie wspólne właściwości, które posiadają wszystkie komponenty
wizualne.
9.
Czy dwa lub więcej komponentów może współdzielić tą samą procedurę obsługi
zdarzenia?
10.
Jakim terminem określa się w VCL kontekst urządzenia? Jak nazywa się klasa,
która hermetyzuje kontekst urządzenia?
Ćwiczenia
1.
Opisz, czym różnią się właściwości i pola danych w klasach.
2.
Stwórz w Delphi aplikację, która po naciśnięciu przycisku wyświetla na głównym
formularzu bitmapę.
3.
Stwórz w Delphi aplikację, która po kliknięciu na głównym formularzu wy-
świetla napis
Hello, Bubba!
.
4.
Umieść kilka wybranych przez Ciebie komponentów na formularzu. Kliknij na
komponencie, a następnie z pomocą Inspektora Obiektów przyjrzyj się jego
właściwościom. Powtórz tę czynność z każdym komponentem.
5.
Włącz kartę
Events
, która znajduje się w Inspektorze Obiektów, a następnie
przestudiuj zdarzenia dostępne dla każdego komponentu, który umieściłeś
w punkcie 4.
Rozdzia³ 5.
♦ Model komponentów wizualnych
209
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\05.doc
209