background image

Rozdział 3 

Elementy składowe aplikacji 

Książka niniejsza nie jest przeznaczona dla początkujących, autor uznał jednak za 
stosowne zamieścić tutaj zwięzłe omówienie elementów, z których składa się 
każda aplikacja Delphi. Czytelnicy mogą dysponować doświadczeniami 
wyniesionymi z kontaktów z innymi narzędziami programistycznymi, znacząco 
różniącymi się od Delphi. W takim przypadku zbiór podstawowych informacji 
o języku i środowisku Delphi pozwoli im lepiej przyswoić dalsze części książki. 
Czytelnicy, którzy znają już Delphi i samodzielnie tworzyli aplikacje w tym 
środowisku, mogą pominąć niniejszy rozdział i od razu przejść do rozdziału 4, 
„Konwencje”. 

Bieżący rozdział prezentuje koncepcję projektów i bibliotek Delphi. Zaznajamia 
ponadto z elementami języka Object Pascal: modułami (ang. unit), formularzami, 
modułami danych i dołączanymi plikami źródłowymi (ang. include files). Ponadto 
zawarto w nim omówienie komponentów Delphi, stanowiących kluczowy element 
każdej aplikacji Delphi. 

Czym są projekty? 

Termin „projekt” może mieć różne znaczenia, w zależności od używanego 
narzędzia programistycznego. Zazwyczaj projektem nazywa się nadrzędną 
strukturę, grupującą wszystkie obiekty tworzące aplikację. Główną funkcją takiej 
struktury jest ustanawianie wzajemnych relacji między tymi obiektami. 
Pojedynczy projekt służy z reguły za „magazyn” obiektów, należących do jednej 
aplikacji. Oczywiście występują wyjątki od tej reguły. Czasami na aplikację składa 
się kilka projektów. Może się również zdarzyć,  że jeden projekt obejmuje kilka 
aplikacji. Jednak w przypadku większości narzędzi programistycznych z pojedyn-
czego projektu generowany jest jeden wynikowy plik wykonywalny. 

Projekty Delphi 

W przypadku Delphi projekt zawiera listę wszystkich plików, które składają się na 
jedną aplikację. Projekty Delphi wyróżniają się tym, że poza wyszczególnieniem 
w nich  plików  źródłowych aplikacji, same także mają postać tekstu źródłowego 
programu. Oznacza to, iż projekt Delphi jest programem napisanym w języku 
Object Pascal, dającym się w razie potrzeby przeglądać i modyfikować. 

background image

74 

Część I 

UWAGA: 

Możliwe jest wprawdzie ręczne modyfikowanie projektów Delphi, należy jednak 
zdecydowanie unikać samodzielnego wprowadzania zmian. Delphi w trakcie pracy 
nad aplikacją modyfikuje części pliku, dlatego użytkownik nie powinien zmieniać 
go niezależnie, na własną rękę. Wprowadzona zmiana może zmylić Delphi; z kolei 
Delphi może zamazać zmiany wpisane przez użytkownika. 

Projekty Delphi mają postać tekstu programu i przechowywane są przez system 
operacyjny jako pliki. Dlatego też ograniczenia co do nazw projektów, pokrywają 
się z ograniczeniami nazw wszelkich identyfikatorów w języku Object Pascal. 
Nazwy projektów i modułów muszą rozpoczynać się literą i mogą zawierać litery, 
cyfry i znaki podkreślenia. Nie są dozwolone spacje i kropki. Listing 3.1 
przedstawia niewielki plik projektu Delphi. 

UWAGA: 

Oczywiście maksymalna długość nazwy pliku projektu ograniczona jest z drugiej 
strony przez system operacyjny. Niektóre sieciowe systemy operacyjne, 
w szczególności NetWare 3.x, nie dopuszczają stosowania długich nazw plików. 
To samo ograniczenie obowiązuje w niektórych systemach kontroli wersji. Przy 
nadawaniu nazw plikom należy zatem brać pod uwagę również takie zewnętrzne 
ograniczenia. 

Listing 3.1. Plik projektu RENTMAN. 

Program RENTMAN 
uses 

Forms 
RETDATA in ‘RENTDATA.pas’ {dmRENTMAN: TDataModule}, 
ANYFORM in ‘..\..\CH09\CODE\ANYFORM.pas’{fmAnyForm}, 
DBFORM in ‘..\..\CH09\CODE\DBFORM.pas’ {fmDatabaseForm}, 
EDITFORM in ‘..\..\CH09\CODE\EDITFORM.pas’ {fmEditForm}, 
REMPENT0 in ‘REMPENT0.pas’ {fmREMPENT0}, 
RSYSMAN0 in ‘RSYSMAN0.pas’ {fmRSYSMAN0}, 
RWKTENT0 in ‘RWKTENT0.pas’ {fmRWKTENT0}, 
CGRDFORM in ‘..\..\CH09\CODE\CGRDFORM.pas’ 

{fmControlGridForm}, 

RTENCGD0 in ‘RTENCGD0.pas’ {fmRTENCGD0}, 
RPROCGD0 in ‘RPROCGD0.pas’ {fmRPROCGD0}, 
RLEACGD0 in ‘RLEACGD0.pas’ {fmRLEACGD0}, 
MSTRFORM in ‘MSTRFORM.pas’ {fmMasterDetailForm} 
GRIDFORM in ‘GRIDFORM.pas’ {fmGridForm}, 
RWORGRD0 in ‘RWORGRD0.pas’ {fmRWORGRD0}, 
RWORMDE0 in ‘RWORMDE0.pas’ {fmRWORMDE0}, 
RCALGRD0 in ‘RCALGRD0.pas’ {fmRCALGRD0}, 
RCALEDT0 in ‘RCALEDT0.pas’ {fmRCALEDT0}, 
RPROLST0 in ‘RPROLST0.pas’ {fmRPROLST0}, 

background image

 

Błąd! Nie zdefiniowano stylu. Elementy składowe aplikacji 

75

 

{$ *.RES} 
begin 

Application.Initialize; 
Application.HelpFile := ‘C:\Data\Word\CSD\CH13  

 \code\Rentman.hlp’; 

Application.CreateForm(TfRSYSMAN0, fmRSYSMAN0); 
Application.CreateForm(TdmRENTMAN, dmRENTMAN); 
Application.CreateForm(TfmREMPENT0, fmREMPENT0); 
Application.CreateForm(TfmRWKTENT0, fmRWKTENT0); 
Application.CreateForm(TfmRTENCGD0, fmRTENCGD0); 
Application.CreateForm(TfmRPROCGD0, fmRPROCGD0); 
Application.CreateForm(TfmRLEACGD0, fmRLEACGD0); 
Application.CreateForm(TfmRWORGRD0, fmRWORGRD0); 
Application.CreateForm(TfmRWORMDE0, fmRWORMDE0); 
Application.CreateForm(TfmRCALGRD0, fmRCALGRD0); 
Application.CreateForm(TfmRCALEDT0, fmRCALEDT0); 
Application.CreateForm(TfmRPROLST0, fmRPROLST0); 
Application.Run; 

end. 

Słowo kluczowe program 

Słowo kluczowe 

program

, rozpoczynające listing 3.1, informuje kompilator, że 

na podstawie tego pliku źródłowego ma być wygenerowany osobny plik 
wykonywalny. W przypadku biblioteki dołączanej dynamicznie (DLL) albo 
modułu, słowo 

program

 zastępowane jest odpowiednio przez słowo 

library

 

albo 

unit

Polecenie uses 

W ramach polecenia 

uses

 wymienione są wszystkie moduły, napisane w języku 

Object Pascal, które Delphi skonsoliduje (połączy), tworząc plik wykonywalny. 
Moduły (ang. units) są elementami, składającymi się na aplikację Delphi. Gdy 
użytkownik zleca skompilowanie lub uruchomienie pliku projektu, Delphi 
automatycznie rekompiluje każdy moduł, którego kod wynikowy jest starszy niż 
aktualny tekst źródłowy. W niektórych środowiskach programowania za proces ten 
odpowiada program (lub funkcja) make. 

Moduł 

Forms

, wymieniony na listingu 3.1, stanowi część biblioteki Visual 

Component Library, wchodzącej w skład pakietu Delphi. Pozostałe moduły, 
wymienione na listingu, odpowiadają formularzom, dodanym do projektu przez 
autora aplikacji. W każdym wierszu wymienione są kolejno: nazwa modułu, 
ścieżka dostępu do pliku, w którym ten moduł jest przechowywany oraz nazwa 
formularza, zawartego w module. Nazwy formularzy odpowiadają identyfikatorom 
wpisywanym w 

polu atrybutu 

Name

, w 

oknie Object Inspector. Wraz 

z wprowadzeniem  w Delphi  obsługi długich nazw plików, możliwe stało się 

background image

76 

Część I 

nadawanie plikom nazw identycznych z nazwami modułów. Oczywiście nazwa 
modułu nie zawiera rozszerzenia. Jeśli podczas kompilacji Delphi nie jest w stanie 
zlokalizować modułu, korzystając z 

jego długiej nazwy, podejmuje próbę 

odszukania go na podstawie nazwy skróconej. 

Dyrektywa $R 

Dyrektywa kompilatora 

$R

 interpretowana jest jako polecenie dołączenia do 

projektu wskazanego pliku zasobów Windows. Gwiazdka oznacza, że główna 
część nazwy pliku zasobów jest identyczna z 

nazwą projektu. W 

trakcie 

budowania projektu Delphi tworzy plik zasobów dla samego projektu oraz dla 
każdego z zawartych w nim formularzy. Jeśli któryś z plików zasobów nie jest 
dostępny podczas konsolidacji programu, Delphi generuje komunikat „

File not 

found: xxx.RES

”.  

Application.CreateForm

 

Polecenia 

Application.CreateForm

    wczytują formularze, należące do 

projektu, do pamięci operacyjnej. Na ogół wymienione są w ten sposób wszystkie 
formularze, zawarte w projekcie. Korzystając z opcji menu 

Options\Project

, można 

zdecydować, które formularze mają być tworzone automatycznie. Każdy 
utworzony formularz przechowywany jest w zmiennej. Zmienna taka - na przykład 

fmRSYSMAN0

 - zdefiniowana jest w sekcji 

interface

 modułu formularza. 

Ponieważ projekt wykorzystuje moduły a one z kolei definiują powyższe zmienne, 
na poziomie projektu „widać” te zmienne i można przekazać je jako argument 
wywołania procedury 

Application.CreateForm

. Procedura ta tworzy 

wskazany formularz w pamięci i zwraca w zmiennej do niego wskaźnik. 

Kolejność, w 

jakiej formularze wymienione są w 

ciągu wywołań 

Application. CreateForm

, określa kolejność tworzenia formularzy. 

Pierwszy formularz, utworzony przez 

Application. CreateForm

, staje się 

głównym formularzem aplikacji. Chcąc zmienić kolejność tworzenia formularzy, 
należy skorzystać z opcji menu 

Options\Application

; nie należy natomiast zmieniać 

tekstu źródłowego projektu. 

Application.Run 

Wywołanie 

Application.Run

 powoduje wejście do głównej pętli aplikacji, 

czyli faktyczne uruchomienie programu. 

background image

 

Błąd! Nie zdefiniowano stylu. Elementy składowe aplikacji 

77

 

Biblioteki Delphi 

Delphi oferuje wygodny mechanizm tworzenia bibliotek dołączanych dynamicznie 
(ang.  dynamic link libraries, DLL). W przeciwieństwie do większości innych 
języków programowania w Windows, Delphi dysponuje specjalnymi elementami 
składni, wspomagającymi generowanie bibliotek DLL. Należą do nich dwa słowa 
kluczowe: 

library

 i 

export

. Słowo kluczowe 

library

 zastępuje słowo 

program

, obecne w 

poprzednim przykładzie. Informuje kompilator, że 

generowana ma być biblioteka DLL, a nie plik EXE. Użycie słowa kluczowego 

export

 powoduje wyeksportowanie wskazanych funkcji z biblioteki DLL; 

eksportowane funkcje biblioteczne mogą być wywoływane z innych modułów 
wykonywalnych. Na Listingu 3.2 przedstawiono tekst źródłowy niewielkiej 
biblioteki. 

Listing 3.2. Biblioteka StrUtil. 

library StrUtil; 
Uses 

SysUtils; 

function Pad(InString: String; Len: Integer): String; 
begin 

Result:=Format(‘%-*s’,[Len, InString]); 

end; 
function LPad(InString: String; Len: Integer): String; 
begin 

Result:=Format(‘%*s’,[Len, InString]); 

end; 
exports 

Pad index 1, 
LPad index 2; 

begin 
end. 

Biblioteki mają formę bardzo zbliżoną do programów. Należy jedynie zwrócić 
uwagę na słowo 

library

, zastępujące słowo 

Program

 (zob. początek Listingu 

3.2). Polecenie 

exports

 nakazuje wyeksportowanie funkcji 

Pad

 i 

LPad

 

z biblioteki DLL. Funkcje te będzie można wywoływać z innych modułów 
wykonywalnych. 

Moduły (ang. units) w Delphi 

Moduły stanowią - obok formularzy - elementarne bloki, składające się na 
aplikację Delphi. W 

modułach przechowywane są definicje formularzy, 

decydujących o 

graficznej postaci aplikacji. Moduły zawierają ponadto 

dodatkowe, dopisywane przez autora programu, fragmenty kodu, wspomagające 
funkcje aplikacji.  

background image

78 

Część I 

Każdemu formularzowi, dodawanemu do projektu, towarzyszy oddzielny plik 
źródłowy modułu. Plik taki zawiera definicję klasy, która odpowiada wizualnej 
reprezentacji formularza. Gdy autor doda do formularza jakikolwiek komponent, 
Delphi automatycznie modyfikuje definicję klasy, tak aby obejmowała ona ten 
nowy komponent. Również każdy dodany do formularza podprogram obsługi 
zdarzenia przechowywany jest w pliku modułu. Zdecydowana większość tekstu 
programu, dopisywana samodzielnie przez autora aplikacji, trafia właśnie do 
plików modułów. Listing 3.3 przedstawia tekst źródłowy prostego modułu. 

Listing 3.3. Tekst źródłowy modułu Delphi.

 

Unit RTENCGD0; 
interface 
uses 

Windows, Messages, SysUtils, Classes, Graphics, Controls, 
Forms, Dialogs, CGRDFORM, Buttons, DBCtrls, StdCtrls, 
ExtCtrls, Mask, DBNavSch, DBCGrids; 

type 
 TfmRTENCGD0 = class(TfmControlGridForm) 

teTenantNo: TDBText; 
deName: TDBEdit; 
deEmployer: TDBEdit; 
deEmpAddress: TDBEdit; 
deEmpCity: TDBEdit; 
deEmpState: TDBEdit; 
deEmpZip: TDBEdit; 
deHomePhone: TDBEdit; 
deWorkPhone: TDBEdit; 
deICEPhone: TDBEdit; 
deLeaseBeginDate: TDBEdit; 
deLeaseEndDate: TDBEdit; 
deMovedInDate: TDBEdit; 
deMovedOutDate: TDBEdit; 
deRentDueDay: TDBEdit; 
dePetDeposit: TDBEdit; 
deComments: TDBEdit; 
Label1: TLabel; 
dkLawnService: TDBCheckBox; 
Label2: TLabel; 
Label3: TLabel; 
Label4: TLabel; 
Label5: TLabel; 
Label6: TLabel; 
Label7: TLabel; 
Label8: TLabel; 
Label9: TLabel; 
Label10: TLabel; 
LaName: TLabel; 
Label12: TLabel; 
Label13: TLabel; 
Label14: TLabel; 
Label15: TLabel; 

background image

 

Błąd! Nie zdefiniowano stylu. Elementy składowe aplikacji 

79

 

Label16: TLabel; 
Label17: TLabel; 

private 

{ Private declarations } 

public 

( Public declarations } 

end; 

var 

fmRTENCGD0: TfmRTENCGD0; 
DefaultPetDeposit : Integer; 

implementation 

uses rentdata; 

{$R *.DFM} 

initialization 
 DefaultPetDeposit:=150; 
end. 

Sekcja interface 

Przede wszystkim należy zwrócić uwagę na podział modułu na sekcje 

interface

implementation

 i 

initialization

. Sekcja 

interface

 

zawiera informacje nagłówkowe modułu. Obejmują one deklaracje funkcji 
i procedur oraz definicje zmiennych, stałych i typów, które mają być widoczne na 
zewnątrz modułu. Sekcja ta odpowiada plikowi nagłówkowemu programu 
w języku C. Inaczej niż w języku C, informacji nagłówkowych modułów Delphi 
nie trzeba przechowywać w osobnym pliku źródłowym, który musiałby być 
dołączany do wszystkich innych modułów dyrektywą 

include

 lub jej 

odpowiednikiem. Informacje nagłówkowe przechowywane są w skompilowanym 
pliku modułu. Gdy jakiś inny moduł odwołuje się do niego poprzez polecenie 

Uses

, Delphi - chcąc pobrać informacje o deklaracjach i definicjach - odczytuje 

nagłówek skompilowanego modułu, a nie jego tekst źródłowy. 

Powyższe rozwiązanie umożliwia dystrybucję modułów w postaci skompilowanej, 
bez konieczności dodawania do nich jakichkolwiek plików nagłówkowych. 
Eliminuje ponadto każdorazową rekompilację pliku nagłówkowego, towarzysząca 
kompilacji zawierającego go modułu (ten ostatni problem rozwiązują tzw. 
prekompilowane pliki nagłówkowe - ang. precompiled headers - które jednak nie 
są dostępne we wszystkich kompilatorach języka C). 

background image

80 

Część I 

Sekcja implementation 

Sekcja 

implementation

 zawiera właściwy tekst podprogramów, zawartych 

w module. Wszystkie obiekty programu, umieszczone w tej sekcji, nie będą 
widoczne poza modułem, o ile nie zostały wymienione w sekcji 

interface

W typowym module deklaracje funkcji umieszczane są w sekcji 

interface

natomiast ich treść w sekcji 

implementation

Zmienna identyfikująca formularz 

Wśród definicji zmiennych (po słowie 

var

) w sekcji 

interface

 występuje 

zmienna, identyfikująca egzemplarz formularza: 

var 

 fmRTENCGD0: TfmRTENCGD0; 

Zdefiniowano w 

ten sposób zmienną o 

nazwie 

fmRTENCGD0

, typu 

TfmRTENCGD0

.

 TfmRTENCGD0 

jest typem potomnym w stosunku do 

TForm

 

i został automatycznie zdefiniowany podczas interaktywnego tworzenia formularza 
w środowisku Delphi. Zmienna 

fmRTENCGD0

 jest inicjowana w pliku projektu, 

podczas wywołania 

Application.CreateForm

. Ponieważ zmienna ta jest 

zdefiniowana w 

sekcji 

interface

 modułu, jest widoczna i 

może być 

modyfikowana we wszystkich innych modułach, odwołujących się do niego 
w swoich klauzulach 

Uses

, w tym także w pliku projektu.  

Sekcja initialization 

W sekcji tej należy umieszczać fragmenty programu, które mają być wykonane 
bezpośrednio po pierwszym załadowaniu modułu. Kod sekcji 

initialization

 

wykonywany jest zatem po załadowaniu aplikacji. Kolejność wykonywania sekcji 

initialization

 poszczególnych modułów odpowiada kolejności w jakiej 

moduły te są wymienione w poleceniu 

Uses

 pliku projektu. Na Listingu 3.3 

sekcja 

initialization

 obejmuje wiersze pomiędzy słowem 

initialization

, a końcem modułu: 

initialization 

 DefaultPetDeposit:=150; 

end. 

Po załadowaniu aplikacji, zmienna 

DefaultPetDeposit

 jest inicjowana 

wartością  150. Aplikacja może później odwoływać się do zmiennej, mając 
gwarancję, że ta została już poprawnie zainicjowana. 

background image

 

Błąd! Nie zdefiniowano stylu. Elementy składowe aplikacji 

81

 

Sekcja finalization 

W module można dodatkowo umieścić sekcję 

finalization

. Program, zawarty 

w tej sekcji, wykonywany jest przy zamykaniu aplikacji. Typowe czynności, 
wykonywane w sekcji 

finalization

, obejmują zamykanie otwartych plików 

zwalnianie wszelkich innych zasobów, z 

których moduł mógł korzystać. 

Omawiana sekcja musi występować po sekcji 

initialization

, ale przed 

ostatnim słowem kluczowym 

end.

 modułu. 

Formularze Delphi 

Formularze Delphi są elementami, odpowiadającymi za wizualną postać aplikacji. 
Większość operacji, wykonywanych w trakcie interaktywnego projektowania 
formularzy w środowisku Delphi, znajduje swoje odbicie w pliku formularza. 
Zmiana atrybutu albo przesunięcie komponentu sprowadza się w istocie do zmiany 
wybranych ustawień, przechowywanych w pliku formularza. 

Ponieważ narzędzia programistyczne Delphi dynamicznie łączą mechanizmy 
programowania wizualnego z tradycyjnym pisaniem kodu, możliwa jest edycja 
formularza w postaci tekstowej. Po jego zapisaniu można obejrzeć efekty 
poczynionych zmian w postaci graficznej. Listing 3.4. przedstawia tekstową 
wersję niewielkiego formularza. 

Listing 3.4. Reprezentacja tekstowa prostego formularza 

inherited fmDatabaseForm: TfmDatabaseForm 

Left = 75 
Top = 124 
Width = 554 
Caption = ‘fmDatabaseForm’ 
PixelsPerInch = 96 
TextHeight = 13 
inherited paTop: TPanel 

Width = 546 

end 
inherited paMiddle: TPanel 

Width = 546 

end 
inherited paBottom: TPanel 

Width =546 
object paRight: TPanel 

Left = 385 
Top = 1 
Width = 160 
Height = 37 
Align = alRight 
BevelOuter = bvNone 
TabOrder = 0 
object bbok: TBitBtn 

background image

82 

Część I 

Left = 4 
Top = 8 
Width = 75 
Height =25 
TabOrder = 0 
Kind = bkOK 

end 
object bbCancel: TBitBtn 

Left = 82 
Top = 8 
Width = 75 
Height = 25 
TabOrder = 1 
Kind = bkCancel 

end 

end 
object bbPrintForm: TBitBtn 

Left = 280 
Top = 8 
Width = 75 
Height = 25 
Caption = ‘Print Form’ 
TabOrder = 1 
OnClick = bbPrintFormClick 
Glyph.Data = { 

76010000424D760100000000000076000000280000002000000

0100000000100 

04000000000000010000130B0000130B0000000000000000000

0000000000000 

800000800000008080008000000080008000808000007F7F7F0

0BFBFBF000000 

FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF0

0300000000000 

00033FFFFFFFFFFFFFFF0888888888888880777777777777777

F088888888888 

8880777777777777777F0000000000000000FFFFFFFFFFFFFFF 

F0F8F8F8F8F8F 

8F80777777777777777F08F8F8F8F8F8F9F0777777777777777 

F0F8F8F8F8F8F 

8F807777777777777F7F0000000000000000777777777777777

F3330FFFFFFFF 

03333337F3FFFF3F7F333330F0000F0F03333337F77773737F3

33330FFFFFFFF 

03333337F3FF3FFF7F333330F00F000003333337F7737777733

33330FFFF0FF0 

33333337F3FF7F3733333330F08F0F0333333337F7737F73333

33330FFFF0033 

background image

 

Błąd! Nie zdefiniowano stylu. Elementy składowe aplikacji 

83

 

33333337FFFF773333333330000003333333333777777333333

3} 

NumGlyphs = 2 

end 
object DBNavigator1: TDBNavSearch 

Left = 8 
Top = 8 
Width = 253 
Height = 25 
TabOrder =2 

end 

end 

end 

Moduły danych 

Delphi umożliwia korzystanie ze specjalnych formularzy, zwanych modułami 
danych
 (ang. data modules). Tworzy się je przy pomocy polecenia 

New Data

 

Module

 z menu 

File

. Moduły danych umożliwiają grupowanie kontrolek nie 

posiadających reprezentacji graficznej - zwykle komponentów obsługujących bazy 
danych - na pojedynczym, centralnym formularzu. Pozostałe formularze, chcąc 
uzyskać dostęp do komponentów obsługujących bazę danych, odwołują się do 
modułów danych. Moduły danych można także umieszczać w składnicy obiektów 
Delphi (Object Repository) i tworzyć na ich podstawie formularze potomne, 
kopiować je i wykorzystywać, tak jak wszelkie inne obiekty, przechowywane 
w składnicy. Należy zwrócić uwagę,  że na module danych nie można umieścić 
kontrolki graficznej. 

Dołączane pliki źródłowe (ang. include files) 

Podobnie, jak większość narzędzi programistycznych, kompilator Delphi 
umożliwia dołączanie zewnętrznych plików źródłowych (tzw. include files) na 
etapie kompilacji. Mechanizm ten umożliwia wykorzystywanie tych samych 
fragmentów programu źródłowego w różnych częściach aplikacji. Należy jednak 
pamiętać,  że Delphi każdorazowo po napotkaniu dyrektywy dołączenia w danym 
miejscu zewnętrznego pliku źródłowego, kompiluje ten plik. Dlatego też należy 
ograniczać stosowanie dołączanych plików źródłowych, a 

zamiast nich 

wykorzystywać moduły (units). 

W praktyce dołączane pliki źródłowe zawierają na ogół szereg dyrektyw dla 
kompilatora; dyrektywy te mają być zastosowane do wszystkich modułów, 
należących do projektu. Plik z dyrektywami dołączany jest jako zewnętrzny plik 
źródłowy do wszystkich modułów. Po jego zmianie, czyli zmianie dyrektyw dla 
kompilatora, wszystkie moduły są poddawane rekompilacji. Poniższy listing 

background image

84 

Część I 

przedstawia przykład takiego pliku z 

dyrektywami, zaczerpnięty z 

tekstu 

źródłowego programu WinMac32 Windows Macro Engine: 

{$B-,F-,G+,I-,K+,N-,P+,Q-,R-,S+,T-,V+,W-,X+} 
{$IFNDEF DEBUG} 
{$D-} 
{$ELSE} 
{$D+,L+,Y+} 
{$ENDIF} 

UWAGA: 

Kompletny tekst źródłowy WinMac32 znajduje się na płycie CD-ROM dołączonej 
do książki. 

Powyższy plik umożliwia  łatwe uaktywnianie i wyłączanie opcji kompilatora, 
kontrolujących poziom wspomagania programu uruchomieniowego (debuggera). 
Należy zwrócić uwagę na wiersz 

{$IFNDEF DEBUG}

. Informuje on kompilator, 

że jeśli użytkownik nie zdefiniował  o nazwy symbolicznej 

DEBUG

, to trzy opcje 

związane z programem uruchomieniowym - 

$D

$L

 i 

$Y

 - mają być wyłączone. 

Wyłączenie opcji 

$D

 automatycznie wyłącza również dwie pozostałe. 

Analogicznie, jeżeli użytkownik zdefiniował 

DEBUG

, trzy opcje są uaktywnianie. 

Jeśli wszystkie moduły aplikacji będą zawierały dyrektywę dołączenia tego pliku, 
będzie można bardzo łatwo decydować, czy mają być kompilowane z aktywnymi 
przełącznikami dotyczącymi  debuggera, czy też nie - wystarczy zdefiniować lub 
usunąć definicję nazwy symbolicznej 

DEBUG

. Rozwiązanie to wydaje się 

wygodniejsze niż przełączanie trzech opcji w polu dialogowym 

Options\Project

Po utworzeniu pliku z dyrektywami, dołącza się go do odpowiednich plików 
źródłowych modułów, korzystając z dyrektywy 

$I

, na przykład: 

{$I WINMAC32.INC} 

UWAGA: 

Warunkowe dyrektywy kompilatora nie są przenoszone między poszczególnymi 
modułami, mimo że można byłoby tego oczekiwać. Rozpoczynając kompilację 
nowego modułu, Delphi zawsze ustala stan dyrektyw warunkowych zgodnie 

ustawieniami, wpisanymi w 

polu dialogowym 

Project\Options

 albo 

w parametrach wywołania kompilatora. 

Komponenty Delphi 

Jeśli formularze porównamy do cząsteczek, składających się na aplikację Delphi, 
to komponenty wypadałoby nazwać atomami, tworzącymi te cząsteczki. 
Formularze składają się zatem z komponentów. 

background image

 

Błąd! Nie zdefiniowano stylu. Elementy składowe aplikacji 

85

 

Za reprezentacją graficzną komponentów, widoczną w środowisku programowania 
wizualnego Delphi, kryją się fragmenty programu w języku Object Pascal. Listing 
3.5 przedstawia tekst źródłowy prostego komponentu. 

Listing 3.5. Tekst źródłowy nowego komponentu 

- TArrayTable 


Komponent Delphi ArrayTable 

Umożliwia dostęp do tabeli w

 sposób typowy dla tablic. 

Aby uzyskać dostęp do wartości poszczególnych pól

 

należy użyć składni:

 

Records[RecNum].Fields[FieldNum].AsType 
Autor: Ken Henderson. 
Copyright (C) 1995 by Ken Henderson. 

unit ArrayTable; 
 
interface 
 
uses 

Windows, Messages, SysUtils, Classes, Graphics, Controls, 
Forms, Dialogs, Db, DBTables; 
 

type 

TArrayTable = class(TTable) 
private 

{Private declarations} 
function GetRecords(RecNum : Longint) : TDataSet; 

protected 

{Protected declarations} 

public 

{Public declarations} 
property Records{RecNum : Longint} : TDataSet read  

 GetRecords; 

published 

{Published declarations} 

end; 
 
procedure Register; 
 
implementation 
 
function TArrayTable.GetRecords(RecNum : Longint) : TDataSet; 
begin 

First 
MoveBy(RecNum); 
Result:=Self; 

end; 
 
procedure Register; 
begin 
RegisterComponents( ‘Data Access’, [TArrayTable]); 

background image

86 

Część I 

end; 
 
end. 

Powyższy komponent zdefiniowano jako klasę pochodną standardowej tabeli 
Table, dodając tylko jeden publiczny atrybut: 

Records

. Dzięki niemu możliwe 

jest traktowanie tabeli tak, jak jednej dużej tablicy. Na przykład, poniższy zapis 
zwróci - w postaci łańcucha znaków - zawartość trzeciego pola z piątego rekordu 
(zarówno nowy atrybut 

Records

, jak i własny atrybut 

Fields

 klasy 

TTable

 

wymagają indeksów liczonych od zera): 

TArrayTable1.Records[4].Fields[2].AsString; 

Jak nietrudno zauważyć, rozszerzenie funkcji istniejącego komponentu nie 
wymagało dużego nakładu pracy. Cały proces był nawet prostszy niż tworzenie 
nowego komponentu przy użyciu polecenia 

New

 

Component

 z menu 

Component

Po wywołaniu tego polecenia, użytkownik musi wskazać klasę - przodka 
(w naszym  przypadku  będzie to 

TTable

), wprowadzić nazwę nowej klasy 

i wybrać stronę palety komponentów, na której ma się znaleźć nowy komponent. 
Delphi automatycznie generuje odpowiedni fragment programu. 

UWAGA: 

Należy zwrócić uwagę,  że - choć nie widać tego wprost w tekście  źródłowym 

TArrayTable

 - korzystanie z atrybutu 

Records

 zawsze powoduje fizyczne 

przesunięcie wskaźnika bieżącego rekordu. Nie ma sposobu obejścia tego 
ograniczenia, które wynika z właściwości mechanizmów dostępu do baz danych 
w Delphi.  Zapamiętanie i późniejsze odtwarzanie stanu wskaźnika wewnątrz 
komponentu nie rozwiązuje problemu, gdyż atrybut 

Fields

 komponentu 

TTable

 odwołuje się zawsze do bieżącego rekordu. Dlatego zapamiętywanie 

wskaźnika bieżącego rekordu w  powinno odbywać się przed odwołaniem do 
atrybutu 

Records

, a odtwarzanie - po skorzystaniu z tego atrybutu. 

Należy również zwrócić uwagę na wywołanie procedury 

RegisterComponent

umieszczone na końcu listingu 3.5. Procedura ta dodaje komponent Delphi do 
palety paska narzędzi. Pierwszy argument procedury wskazuje na stronę palety, na 
której ma się znaleźć nowy komponent. Drugi argument zawiera listę 
komponentów, które mają zostać zarejestrowane. Nazwy komponentów należy 
oddzielać przecinkami (wewnątrz nawiasów kwadratowych).