04 Rozdział 03


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 zró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 zródłowych aplikacji, same także mają postać tekstu zró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ć.
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},
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 zró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 zró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ę
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 wskaznik.
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 zródłowego projektu.
Application.Run
Wywołanie Application.Run powoduje wejście do głównej pętli aplikacji,
czyli faktyczne uruchomienie programu.
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 zró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.
78 Część I
Każdemu formularzowi, dodawanemu do projektu, towarzyszy oddzielny plik
zró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 zródłowy prostego modułu.
Listing 3.3. Tekst zró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;
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 zró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 zró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).
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ózniej odwoływać się do zmiennej, mając
gwarancję, że ta została już poprawnie zainicjowana.
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
i 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
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
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 zródłowe (ang. include files)
Podobnie, jak większość narzędzi programistycznych, kompilator Delphi
umożliwia dołączanie zewnętrznych plików zródłowych (tzw. include files) na
etapie kompilacji. Mechanizm ten umożliwia wykorzystywanie tych samych
fragmentów programu zró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 zródłowego, kompiluje ten plik. Dlatego też należy
ograniczać stosowanie dołączanych plików zródłowych, a zamiast nich
wykorzystywać moduły (units).
W praktyce dołączane pliki zró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
zródłowy do wszystkich modułów. Po jego zmianie, czyli zmianie dyrektyw dla
kompilatora, wszystkie moduły są poddawane rekompilacji. Poniższy listing
84 Część I
przedstawia przykład takiego pliku z dyrektywami, zaczerpnięty z tekstu
zró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 zró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
zró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
z 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.
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 zródłowy prostego komponentu.
Listing 3.5. Tekst zró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]);
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ę znalezć nowy komponent.
Delphi automatycznie generuje odpowiedni fragment programu.
UWAGA:
Należy zwrócić uwagę, że - choć nie widać tego wprost w tekście zródłowym
TArrayTable - korzystanie z atrybutu Records zawsze powoduje fizyczne
przesunięcie wskaznika 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ózniejsze odtwarzanie stanu wskaznika wewnątrz
komponentu nie rozwiązuje problemu, gdyż atrybut Fields komponentu
TTable odwołuje się zawsze do bieżącego rekordu. Dlatego zapamiętywanie
wskaznika 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ę znalezć 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).


Wyszukiwarka

Podobne podstrony:
04 rozdział 03 wtcjpb3t4i6ahedwpeqbi526b4gndq3qkbqtbaq
04 Rozdział III Od wojennego chaosu do papieża matematyka
04 Rozdzial 2
monter systemow rurociagowychq3[04] z1 03 n
05 Rozdział 03 Wzór Taylora i ekstrema funkcji
Nauka swiatowa i polska[1] Rozdzial 03
monter systemow rurociagowychq3[04] z1 03 u
03 Rozdział 03
04 Rozdzial 2
opiekun w domu pomocy spolecznej46[04] z2 03 n
opiekun w domu pomocy spolecznej46[04] o1 03 u
04 ROZDZIA 4 Zegarek, a co to takiego , czyli poznawanie i oswajanie si z tym, co nieuniknione
04 Rozdział 04

więcej podobnych podstron