Darmowy fragment publikacji:
IDZ DO
IDZ DO
PRZYK£ADOWY ROZDZIA£
PRZYK£ADOWY ROZDZIA£
SPIS TREŒCI
SPIS TREŒCI
KATALOG KSI¥¯EK
KATALOG KSI¥¯EK
KATALOG ONLINE
KATALOG ONLINE
ZAMÓW DRUKOWANY KATALOG
ZAMÓW DRUKOWANY KATALOG
TWÓJ KOSZYK
TWÓJ KOSZYK
DODAJ DO KOSZYKA
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
CENNIK I INFORMACJE
ZAMÓW INFORMACJE
ZAMÓW INFORMACJE
O NOWOŒCIACH
O NOWOŒCIACH
ZAMÓW CENNIK
ZAMÓW CENNIK
CZYTELNIA
CZYTELNIA
FRAGMENTY KSI¥¯EK ONLINE
FRAGMENTY KSI¥¯EK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Delphi 2005
Autor: Elmar Warken
T³umaczenie: Wojciech Moch
ISBN: 83-7361-993-3
Tytu³ orygina³u: Delphi 2005
Format: B5, stron: 810
Œrodowisko programistyczne Delphi jest od dawna jednym z najpopularniejszych
narzêdzi stosowanych przez twórców aplikacji. Ka¿da z jego wersji wnosi³a wiele
nowoœci, jednak wersja oznaczona symbolem 2005 to prawdziwy prze³om. Umo¿liwia
ona bowiem projektowanie aplikacji przeznaczonych dla platformy .NET, co otwiera
przez programistami tysi¹ce nowych mo¿liwoœci. Mog¹ wykorzystywaæ bibliotekê klas
FCL, tworzyæ aplikacje nie tylko w znanym z poprzednich wersji Delphi jêzyku Object
Pascal, ale równie¿ w zyskuj¹cym coraz wiêksz¹ popularnoœæ jêzyku C#, a tak¿e
stosowaæ w swoich programach klasy i obiekty napisane w dowolnym jêzyku zgodnym
z platform¹ .NET. Delphi 2005 to prawdziwa rewolucja.
Ksi¹¿ka „Delphi 2005” wyczerpuj¹co omawia najnowsz¹ wersjê tego œrodowiska
programistycznego. Przedstawia jego mo¿liwoœci i ich praktyczne zastosowanie
praktyczne. Szczegó³owo opisuje zagadnienia podstawowe, takie jak praca
z interfejsem u¿ytkownika i stosowanie komponentów oraz tematy zaawansowane
zwi¹zane z tworzeniem aplikacji bazodanowych, korzystaniem z klas i obiektów
specyficznych dla platformy .NET oraz pisaniem w³asnych komponentów.
(cid:129) Korzystanie z elementów interfejsu u¿ytkownika
(cid:129) Zarz¹dzanie plikami projektu
(cid:129) Biblioteka klas .NET
(cid:129) Przetwarzanie plików XML
(cid:129) Zasady programowania obiektowego w Object Pascal
(cid:129) Tworzenie aplikacji z wykorzystaniem biblioteki VCL.NET
(cid:129) Po³¹czenia z baz¹ danych za pomoc¹ ADO.NET
(cid:129) Zasady tworzenia w³asnych komponentów
Dziêki tej ksi¹¿ce poznasz wszystkie mo¿liwoœci najnowszej wersji Delphi
Spis treści
Przedmowa ....................................................................................... 9
Rozdział 1. Praca w IDE ................................................................................... 15
1.1. Konstrukcja komponentów ...................................................................................... 15
1.1.1. Elementy sterujące, narzędzia i komponenty ................................................ 16
1.1.2. Formularze i okna ......................................................................................... 18
1.2. Orientacja na zdarzenia ........................................................................................... 19
1.2.1. Zdarzenie na każdą okazję ............................................................................ 19
1.2.2. Zdarzenia w Delphi ....................................................................................... 21
1.3. Cykl rozwoju aplikacji ............................................................................................ 23
1.3.1. Cykl rozwoju aplikacji w IDE Delphi ........................................................... 23
1.3.2. Program przykładowy ................................................................................... 24
1.4. IDE i narzędzia wizualne ......................................................................................... 25
1.4.1. Budowa IDE ................................................................................................. 25
1.4.2. Pomoc w IDE i opis języka ........................................................................... 29
1.4.3. Projektowanie formularzy ............................................................................. 32
1.4.4. Zarządzanie plikami ...................................................................................... 36
1.4.5. Inspektor obiektów ........................................................................................ 37
1.5. Łączenie komponentów z kodem ............................................................................ 45
1.5.1. Wprowadzenie do obsługi zdarzeń ............................................................... 46
1.5.2. Podstawowe możliwości procedur obsługi zdarzeń ...................................... 49
1.5.3. Przegląd modułu formularza ......................................................................... 51
1.5.4. Zdarzenia w programie przykładowym ......................................................... 54
1.5.5. Pomoc w edytorze ......................................................................................... 64
1.5.6. Łączenie zdarzeń — nawigacja, zmiany, usuwanie ...................................... 72
1.5.7. Spojrzenie za kulisy ...................................................................................... 74
1.6. Zarządzanie projektem ............................................................................................ 78
1.6.1. Pliki projektu ................................................................................................. 78
1.6.2. Zarządzanie projektem .................................................................................. 81
1.6.3. Przeglądarka symboli w projektach i kompilatach .NET .............................. 84
1.6.4. Listy „rzeczy do zrobienia” ........................................................................... 89
1.7. Debuger ................................................................................................................... 91
1.7.1. Punkty wstrzymania ...................................................................................... 92
1.7.2. Kontrolowanie zmiennych ............................................................................ 95
1.7.3. Wykonywanie kodu ...................................................................................... 98
1.7.4. Ogólne okna debugera .................................................................................. 99
4
Delphi 2005
Rozdział 2. Biblioteka klas .NET ..................................................................... 103
2.1. Zaawansowane projektowanie formularzy ............................................................ 106
2.1.1. Hierarchia kontrolek i kolejność Z .............................................................. 108
2.1.2. Zmiany wielkości formularzy i kontrolek ................................................... 111
2.1.3. Związki pomiędzy formularzami i kontrolkami .......................................... 116
2.1.4. Dziedziczenie formularzy ........................................................................... 120
2.1.5. Efekty przezroczystości i przenikania ......................................................... 121
2.2. Podstawy biblioteki Windows-Forms .................................................................... 124
2.2.1. Obsługa formularzy .................................................................................... 125
2.2.2. Formularze dialogów .................................................................................. 129
2.2.3. Przykładowy program WallpaperChanger .................................................. 131
2.2.4. Zarządzanie kontrolkami w czasie działania programu ............................... 137
2.2.5. Kolekcje w bibliotece FCL ......................................................................... 144
2.2.6. Wymiana danych i mechanizm przeciągnij-i-upuść .................................... 147
2.3. Stosowanie kontrolek ............................................................................................ 155
2.3.1. Podstawowe cechy wspólne wszystkich kontrolek ..................................... 155
2.3.2. Pola wprowadzania danych ......................................................................... 165
2.3.3. Pola tekstowe RTF i tabele właściwości ..................................................... 167
2.3.4. Kontrolka LinkLabel ................................................................................... 172
2.3.5. Menu ........................................................................................................... 175
2.4. Kontrolki list i kontrolka TreeView ...................................................................... 177
2.4.1. ListBox ....................................................................................................... 177
2.4.2. ListView ..................................................................................................... 186
2.4.3. TreeView .................................................................................................... 193
2.5. Grafika ................................................................................................................... 203
2.6. Przechowywanie i zarządzanie plikami ................................................................. 206
2.6.1. Serializacja .................................................................................................. 206
2.6.2. Pliki i katalogi ............................................................................................. 216
2.6.3. Odczytywanie i zapisywanie plików ........................................................... 220
2.6.4. Zachowywanie ustawień użytkownika ........................................................ 226
2.7. XML ...................................................................................................................... 231
2.7.1. Podstawy XML ........................................................................................... 232
2.7.2. Program do graficznego podglądu plików XML ......................................... 238
2.7.3. Zachowywanie ustawień użytkownika w formacie XML ........................... 242
2.7.4. Zapisywanie dokumentów programu w postaci plików XML .................... 246
2.8. Wątki ..................................................................................................................... 251
2.8.1. Równoległe wykonywanie fragmentów programów ................................... 251
2.8.2. Wątki w bibliotece FCL .............................................................................. 258
2.8.3. Wiele wątków i ich synchronizacja ............................................................. 263
Rozdział 3. Język Delphi w środowisku .NET .................................................... 273
3.1. Przestrzenie nazw i kompilaty ............................................................................... 275
3.1.1. Podstawowe pojęcia środowiska .NET ....................................................... 275
3.1.2. Przestrzenie nazw w Delphi ........................................................................ 278
3.1.3. Kompilaty w Delphi .................................................................................... 284
3.1.4. Moduły Delphi ............................................................................................ 293
3.1.5. Moduły Delphi dla nowicjuszy ................................................................... 296
3.2. Obiekty i klasy ...................................................................................................... 296
3.2.1. Deklaracja klasy .......................................................................................... 297
3.2.2. Atrybuty widoczności ................................................................................. 299
3.2.3. Samoświadomość metody ........................................................................... 300
3.2.4. Właściwości ................................................................................................ 302
3.2.5. Metody klas i zmienne klas ......................................................................... 306
3.2.6. Dziedziczenie .............................................................................................. 310
Spis treści
5
3.2.7. Uprzedzające deklaracje klas ...................................................................... 312
3.2.8. Zagnieżdżone deklaracje typów .................................................................. 313
3.3. Obiekty w czasie działania programu .................................................................... 314
3.3.1. Inicjalizacja obiektów: konstruktory ........................................................... 314
3.3.2. Zwalnianie zasobów i czyszczenie pamięci ................................................ 316
3.3.3. Metody wirtualne ........................................................................................ 324
3.3.4. Konwersja typów i informacje o typach ...................................................... 329
3.3.5. Konstruktory wirtualne ............................................................................... 333
3.4. Typy interfejsów .................................................................................................... 335
3.4.1. Czym jest interfejs? ..................................................................................... 335
3.4.2. Implementowanie interfejsu ........................................................................ 339
3.5. Podstawy języka Object Pascal ............................................................................. 344
3.5.1. Elementy leksykalne ................................................................................... 345
3.5.2. Instrukcje kompilatora ................................................................................ 347
3.5.3. Typy i zmienne ........................................................................................... 350
3.5.4. Stałe i zmienne inicjowane .......................................................................... 351
3.5.5. Obszary widoczności i zmienne lokalne ..................................................... 353
3.5.6. Atrybuty ...................................................................................................... 355
3.6. Typy ...................................................................................................................... 356
3.6.1. Typy proste ................................................................................................. 356
3.6.2. Operatory i wyrażenia ................................................................................. 364
3.6.3. Tablice ........................................................................................................ 367
3.6.4. Różne typy ciągów znaków ........................................................................ 370
3.6.5. Typy strukturalne ........................................................................................ 375
3.6.6. Kategorie typów w CLR ............................................................................. 376
3.7. Instrukcje ............................................................................................................... 379
3.8. Procedury i funkcje ............................................................................................... 384
3.8.1. Typy parametrów ........................................................................................ 385
3.8.2. Przeciążanie metod i parametry standardowe ............................................. 389
3.8.3. Wskaźniki metod ........................................................................................ 391
3.9. Wyjątki .................................................................................................................. 392
3.9.1. Wywoływanie wyjątków ............................................................................. 392
3.9.2. Klasy wyjątków .......................................................................................... 393
3.9.3. Zabezpieczanie kodu z wykorzystaniem sekcji finally ............................... 394
3.9.4. Obsługa wyjątków ...................................................................................... 395
3.9.5. Asercja ........................................................................................................ 399
Rozdział 4. Aplikacje VCL.NET ........................................................................ 401
4.1. Biblioteki VCL.NET i FCL ................................................................................... 401
4.1.1. Komponenty ................................................................................................ 403
4.2. Aplikacje VCL w IDE Delphi ............................................................................... 409
4.2.1. Nowy układ IDE dla aplikacji VCL ............................................................ 409
4.2.2. Projekty VCL dla środowisk .NET i Win32 ............................................... 411
4.2.3. Różnice w projektowaniu formularzy ......................................................... 413
4.2.4. Okno struktury w czasie projektowania formularza .................................... 415
4.2.5. Moduły formularzy VCL ............................................................................ 416
4.2.6. Pliki zasobów formularzy ........................................................................... 419
4.2.7. Instalowanie komponentów VCL ................................................................ 422
4.3. Programowanie z wykorzystaniem biblioteki VCL ............................................... 424
4.3.1. Dopasowanie biblioteki VCL do środowiska .NET .................................... 425
4.3.2. Hierarchie kontrolek ................................................................................... 428
4.3.3. Najważniejsze części wspólne kontrolek .................................................... 430
4.3.4. Obsługa formularzy .................................................................................... 432
4.3.5. Kontrolki w czasie działania programu ....................................................... 438
6
Delphi 2005
4.3.6. Kontrolki TListBox, TListView i TTreeView ............................................ 438
4.3.7. Listy, kolekcje i strumienie ......................................................................... 441
4.3.8. Grafika ........................................................................................................ 445
4.3.9. Mechanizm przeciągnij-i-upuść .................................................................. 452
4.3.10. Wątki ......................................................................................................... 456
4.4. Techniki ponownego wykorzystania formularzy ................................................... 459
4.4.1. Repozytorium obiektów .............................................................................. 460
4.4.2. Dziedziczenie formularzy ........................................................................... 463
4.4.3. Ramki .......................................................................................................... 467
4.5. Przykładowa aplikacja VCL .................................................................................. 471
4.5.1. O programie TreeDesigner .......................................................................... 472
4.5.2. Krótki opis i obsługa programu ................................................................... 474
4.6. Komponenty akcji ................................................................................................. 479
4.6.1. Listy poleceń z komponentu TActionList ................................................... 480
4.6.2. Akcje standardowe ...................................................................................... 483
4.6.3. Komponenty menedżera akcji ..................................................................... 484
4.6.4. Komponent TControlBar ............................................................................ 490
4.6.5. Przykładowy interfejs użytkownika ............................................................ 493
4.7. Przenoszenie aplikacji VCL .................................................................................. 495
4.7.1. Przygotowania ............................................................................................. 496
4.7.2. Dopasowywanie aplikacji do środowiska .NET .......................................... 499
4.7.3. Wywołania funkcji API i transpozycja danych ........................................... 503
4.7.4. Zmiany w interfejsie biblioteki VCL .......................................................... 509
4.7.5. Operacje na strumieniach ............................................................................ 511
4.8. Aplikacje VCL.NET i środowisko Win32 ............................................................. 519
4.9. Biblioteki VCL.NET i FCL w ramach jednej aplikacji ......................................... 524
4.9.1. Łączenie bibliotek FCL i VCL na poziomie klas ........................................ 524
4.9.2. Łączenie bibliotek FCL i VCL na poziomie formularzy ............................. 528
4.9.3. Łączenie bibliotek FCL i VCL na poziomie komponentów ........................ 535
Rozdział 5. Aplikacje bazodanowe ................................................................... 541
5.1. Biblioteka ADO.NET w Delphi ............................................................................ 542
5.1.1. Zbiory danych w pamięci ............................................................................ 543
5.1.2. Komponenty udostępniające dane (ang. Providers) .................................... 547
5.1.3. Komponenty Borland Data Providers ......................................................... 552
5.1.4. Eksplorator danych ..................................................................................... 555
5.2. Programowanie z wykorzystaniem biblioteki ADO.NET ..................................... 556
5.2.1. Wiązanie danych ......................................................................................... 557
5.2.2. Kolumny i wiersze ...................................................................................... 566
5.2.3. Zbiory danych określonego typu ................................................................. 574
5.2.4. Relacje ........................................................................................................ 576
5.2.5. Ważne operacje na bazach danych .............................................................. 581
5.3. Przykładowa aplikacja korzystająca z biblioteki ADO.NET ................................. 589
5.3.1. Tworzenie bazy danych .............................................................................. 589
5.3.2. Formularze aplikacji ................................................................................... 596
5.3.3. Zapytania SQL ............................................................................................ 599
5.3.4. Zapytania SQL z parametrami .................................................................... 602
5.3.5. Aktualizacje danych .................................................................................... 606
5.3.6. Aktualizacje w polach z automatyczną inkrementacją ................................ 610
5.3.7. Wygodny formularz wprowadzania danych ................................................ 614
5.3.8. Konflikty przy wielodostępie ...................................................................... 620
5.4. Aplikacje bazodanowe w bibliotece VCL.NET ..................................................... 630
5.4.1. Dostęp do danych za pomocą dbExpress .................................................... 631
5.4.2. Formularze bazy danych i moduły danych .................................................. 636
5.4.3. Kontrolki operujące na danych z baz danych .............................................. 640
Spis treści
7
5.4.4. Podstawowe operacje na danych ................................................................. 642
5.4.5. Kolumny tabeli, czyli pola .......................................................................... 648
5.4.6. Pola trwałe i edytor pól ............................................................................... 650
5.4.7. Dane z aktualnego wiersza .......................................................................... 652
5.4.8. Sortowanie, szukanie i filtrowanie .............................................................. 655
5.4.9. Przykładowa aplikacja terminarza .............................................................. 659
Rozdział 6. Tworzenie komponentów .NET ....................................................... 679
6.1. Wprowadzenie ....................................................................................................... 680
6.1.1. Przegląd przykładowych komponentów ..................................................... 680
6.1.2. Klasy komponentów ................................................................................... 682
6.1.3. Tworzenie komponentów w IDE Delphi ..................................................... 683
6.1.4. Kompilaty komponentów ............................................................................ 684
6.1.5. Pakiety komponentów ................................................................................. 684
6.1.6. Komponent minimalny ............................................................................... 688
6.1.7. Przykład przydatnego komponentu ............................................................. 690
6.2. Komponenty „od środka” ...................................................................................... 693
6.2.1. Zdarzenia .................................................................................................... 694
6.2.2. Wywoływanie zdarzeń ................................................................................ 696
6.2.3. Zdarzenia typu multicast ............................................................................. 698
6.2.4. Zdarzenia w komponentach ........................................................................ 701
6.2.5. Właściwości dla zaawansowanych .............................................................. 703
6.2.6. Interfejs środowiska programistycznego ..................................................... 710
6.3. Rozbudowywanie istniejących komponentów ....................................................... 713
6.3.1. Od komponentu ComboBox do FontComboBox ........................................ 714
6.3.2. Kontrolka ComboBox z automatyczną historią ........................................... 716
6.4. Kontrolki składane z innych kontrolek .................................................................. 723
6.5. Nowe kontrolki ...................................................................................................... 727
6.5.1. Tworzenie środowiska testowego ............................................................... 728
6.5.2. Interfejs nowej palety kolorów .................................................................... 729
6.5.3. Atrybuty właściwości .................................................................................. 736
6.5.4. Implementacja komponentu ........................................................................ 738
6.5.5. Zdarzenia z możliwością reakcji ................................................................. 743
6.6. Edytory w czasie projektowania ............................................................................ 745
6.6.1. Proste edytory właściwości ......................................................................... 746
6.6.2. Menu czasu projektowania dla palety kolorów ........................................... 750
6.6.3. Edytowanie kolekcji obiektów .................................................................... 752
6.7. Pozostałe komponenty przykładowe ..................................................................... 758
6.7.1. Komponent StateSaver ................................................................................ 758
6.7.2. Wyłączanie wybranych okien z komunikatami ........................................... 762
6.7.3. Wyświetlanie struktur katalogów i list plików ............................................ 764
Skorowidz ................................................................................... 767
Rozdział 3.
Język Delphi
w środowisku .NET
W tym rozdziale zajmować się będziemy językiem programowania Delphi — znanym
też pod nazwą Object Pascal — i jego przekształcaniem w klasy i kompilaty środowiska
.NET. Rozdział ten nie ma być dokumentacją tego języka (taka dokumentacja stanowi
część systemu aktywnej pomocy Delphi; znaleźć ją można w gałęzi Borland Help/
Delphi 2005 (Common)/Reference/Delphi Language Guide) i w związku z tym nie
będę tu opisywał wszystkich jego szczegółów. W rozdziale tym będę się starał przed-
stawić jak najpełniejsze wprowadzenie do języka, skierowane do osób „przesiadających”
się z innych narzędzi programistycznych lub z wcześniejszych wersji Delphi. Poza tym
omawiał będę powiązania istniejące pomiędzy Delphi i CLR (ang. Common Language
Runtime — wspólne środowisko uruchomieniowe dla wszystkich aplikacji .NET) oraz
wyjaśniał wszystkie właściwości języka, jakie będą wykorzystywane w książce (roz-
dział ten opisywać będzie też ograniczenia języka w tym zakresie).
Na początku rozdziału nie będziemy zajmować się drobnymi elementami języka, ta-
kimi jak typy danych, zmienne i instrukcje, ale od razu przejdziemy do większych za-
gadnień, takich jak kompilaty (podrozdział 3.1) i model obiektów (podrozdziały 3.2
do 3.4). Od podrozdziału 3.5 przejdziemy do szczegółów języka, czyli zmiennych,
stałych, typów, instrukcji, deklaracji metod i wyjątków.
Wprowadzenie
Język Object Pascal lub Delphi, jak ostatnio nazywa go firma Borland, jest bezpośrednim
następcą języka Borland Pascal with Objects, który został wprowadzony w roku 1989
w pakiecie Turbo Pascal 5.5 (środowisko programistyczne dla systemu DOS), a krótko
potem w pakiecie Turbo Pascal dla Windows, działającym również w systemie Win-
dows. Od czasu powstania pierwszej wersji Delphi w roku 1995 do języka tego do-
dawano wiele poprawek i rozszerzeń, ale z każdą następną wersją języka liczba do-
datków cały czas się zmniejszała, co oznacza, że język ustabilizował się na względnie
wysokim poziomie.
274
Delphi 2005
Wraz z przeniesieniem Delphi do środowiska .NET, do języka Object Pascal znów
wprowadzono kilka ważnych rozszerzeń. Wygląda jednak na to, że osoby przesiadające
się z języka C++ na język C# muszą przyswajać sobie dużo więcej zmian w języku,
niż osoby zmieniające Delphi 7 na Delphi dla .NET. Częściowo można to wytłumaczyć
wspomnianym wyżej wysokim poziomem języka Object Pascal w Delphi 7, do którego
języki przygotowywane przez Microsoft musiały dopiero dotrzeć, ale częściowo wy-
nika też z tego, że firmie Borland dość dobrze udało się zamaskować przed programi-
stami różnice pomiędzy językiem stosowanym w Delphi a wymaganiami środowiska
.NET. Dzięki temu zachowany został wysoki zakres wstecznej zgodności języka z po-
przednimi wersjami i pozwoliło to na znacznie łatwiejsze przenoszenie programów na
inne platformy, w których działa Delphi, takie jak Win32 lub Linux.
Nowości w stosunku do Delphi 7
W tym rozdziale opisywać będę następujące unowocześnienia języka wprowadzone
do niego od czasu Delphi 7:
(cid:141) Działanie mechanizmu oczyszczania pamięci (ang. Garbage Collector);
przenoszenie starych mechanizmów zwalniania pamięci z języka Object
Pascal, takich jak destruktory i ręczne zwalnianie obiektów metodą Free
(punkt 3.3.2).
(cid:141) Zagnieżdżone deklaracje typów (punkt 3.2.8).
(cid:141) Koncepcja typów wartości i typów wskaźników (punkt 3.6.6).
(cid:141) Mechanizm Boxingu (punkt 3.6.6).
(cid:141) Rekordy jako klasy typów wartości z metodami (3.6.5).
(cid:141) Zmienne klas, właściwości klas, konstruktory klas (punkt 3.2.5).
(cid:141) Drobne rozszerzenia języka: strict private, strict protected (punkt 3.2.2)
i sealed (punkt 3.2.6).
(cid:141) Operatory przeciążone (tylko zastosowanie operatorów przeciążonych
— punkt 3.6.2).
Delphi a języki C++ i C#
Język Object Pascal już we wcześniejszych wersjach Delphi charakteryzował się
rozwiązaniami, których nie można się było doszukać w języku C++, a które w tej lub
innej formie obecne są dzisiaj w języku C#:
(cid:141) Wirtualne konstruktory, rozszerzające koncepcję polimorfizmu również
na mechanizmy konstrukcji obiektów (będzie o tym mowa w punkcie 3.3.5).
W języku C# konstruktory wirtualne nie są co prawda dostępne, ale w językach
środowiska .NET podobny efekt uzyskać można za pomocą mechanizmu
Reflection, „wirtualnie” wywołując konstruktor poprzez metodę InvokeMember
danego obiektu Type.
Rozdział 3. ♦ Język Delphi w środowisku .NET
275
(cid:141) Wskaźniki metod, które są znacznie wydajniejsze i praktyczniejsze od podobnych
wskaźników z języka C++ (punkt 3.8.3). W języku C# wskaźniki te nazywane
są delegacjami. Mówiąc dokładniej, typ wskaźnika metody obecny w Delphi
od pierwszej wersji w języku C# odpowiada egzemplarzowi (instancji)
typu Delegat.
(cid:141) Wyjątki odpowiadające wyjątkom obsługiwanym w stylu języka C. Mają one
tę przewagę nad wyjątkami języka C++, że pozwalają na stosowanie sekcji
finally (dostępna jest ona również w języku C# — podrozdział 3.9).
(cid:141) Informacje o typach wykraczające poza możliwości oferowane przez mechanizm
RTTI z języka C++ (punkt 3.3.4). W środowisku .NET informacje te dostępne
są w jeszcze szerszym zakresie niż Delphi 7 (mechanizm Reflection).
(cid:141) Konstruktory tablic otwartych pozwalające na uzyskanie praktycznie dowolnej
listy parametrów (punkt 3.8.1).
(cid:141) Interfejsy, bardzo podobne do interfejsów znanych z języka Java, pozwalające na
uzyskanie wielu operacji, które w języku C++ możliwe są tylko z wykorzystaniem
dziedziczenia wielobazowego, a dodatkowo wolne są od zagrożeń, jakie stwarza
ta właściwość języka C++ (podrozdział 3.4).
Oprócz przedstawionych na początku jasnych stron języka Object Pascal, wymienić
można tu jeszcze inne zalety, które znane były już we wcześniejszych wersjach Del-
phi: zbiory (punkt 3.6.5), otwarte tablice (punkt 3.8.1) i chyba najczęściej wykorzy-
stywana w tej książce przewaga języka Pascal nad językiem C++ — instrukcja with
(podrozdział 3.7).
3.1. Przestrzenie nazw i kompilaty
Jak już mówiłem, forma Borland tworząc Delphi dla .NET chciała uzyskać jak naj-
większy stopień zgodności z poprzednimi wersjami Delphi i przenośności oprogra-
mowania do systemów Windows i Linux. W wyniku tych dążeń do środowiska .NET
przeniesione zostały koncepcje znane z poprzednich wersji Delphi, takie jak moduły
i pakiety, które połączone zostały z koncepcjami funkcjonującymi w środowisku .NET,
takimi jak przestrzenie nazw i kompilaty. Zanim zajmiemy się samym Delphi, w tym
podrozdziale postaram się dokładniej opisać te podstawowe pojęcia środowiska .NET.
3.1.1. Podstawowe pojęcia środowiska .NET
W tym punkcie zajmiemy się najpierw pojęciami kompilatów (ang. Assembly) i prze-
strzeni nazw (ang. Namespace) oraz przyjrzymy środowisku zarządzanemu przez CLR,
w którym wykonywane są wszystkie kompilaty. Opisywać będę również takie mecha-
nizmy jak oczyszczanie pamięci (ang. Garbage Collector) i system wspólnych typów
(ang. Common Type System), które w kolejnych rozdziałach grać będą znaczącą rolę.
276
Kompilaty
Delphi 2005
Kompilaty (ang. Assemblies) są podstawowym budulcem aplikacji środowiska .NET.
W wielu przypadkach kompilat jest po prostu biblioteką dynamiczną .dll albo plikiem
wykonywalnym .exe, ale koncepcja kompilatów jest o wiele szersza niż koncepcja
plików. Jeden kompilat może rozciągać się na wiele plików, które traktowane są jako
jedna całość. Pliki te, traktowane jako jeden kompilat, mają dokładnie te same numery
wersji oraz wspólną „strefę prywatną” — w środowisku .NET istnieje szczególny
atrybut widoczności o nazwie assembly, umożliwiający dostęp do identyfikatora tylko
z wnętrza danego kompilatu.
Co prawda podziały istniejące w kompilatach wpływają przede wszystkim na sposób
wykonywania programu, jednak część z nich dotyczy również jego fizycznej struktury
(kompilaty ładowane są jako całkowicie niezależne od siebie składniki programu,
w związku z czym w czasie aktualizacji oprogramowania mogą być aktualizowane
niezależnie od siebie). Istnieje też podział wpływający na logiczną strukturę programu,
który największe znaczenie ma w czasie projektowania aplikacji.
Przestrzenie nazw
Przestrzenie nazw (ang. Namespaces) pozwalają na dokonanie podziałów w cały czas
rosnących i przez to coraz trudniejszych do ogarnięcia bibliotekach klas. Na przykład
klasy przeznaczone do generowania grafiki umieszczone zostały w przestrzeni nazw
System.Drawing, natomiast wszystkie kontrolki znane z aplikacji systemu Windows,
takie jak kontrolki ListBox lub Button, zapisane są w przestrzeni nazw System.Windows.
Forms. Dostępne są też inne kontrolki, przygotowane specjalnie do wykorzystania
w aplikacjach WWW, które również nazywają się ListBox i Button, chociaż są to klasy
całkowicie niezależne od klas standardowych kontrolek. Rozróżnienie pomiędzy tymi
pierwszymi a tymi drugimi kontrolkami umożliwiają właśnie przestrzenie nazw: System.
Windows.Forms.ListBox to kontrolka listy współdziałająca ze standardowymi aplikacjami
działającymi bezpośrednio na komputerze użytkownika i na ekranie wyświetlana jest
z wykorzystaniem interfejsu GDI+. Z kolei System.Web.UI.WebControls.ListBox to
kontrolka listy współpracująca z aplikacjami WWW działającymi na serwerach WWW,
a na komputer użytkownika przenoszona w postaci kodu HTML.
Różnorodność koncepcji przestrzeni nazw i kompilatów polega między innymi na tym,
że jedna przestrzeń nazw może w sobie zawierać wiele kompilatów, a każdy z kom-
pilatów może przechowywać w sobie wiele przestrzeni nazw. Mówiąc dokładniej,
kompilat nie może w sobie tak naprawdę „zawierać” przestrzeni nazw, ponieważ może
być ona rozbudowywana przez inne kompilaty. W związku z tym należałoby powie-
dzieć, że kompilat może przechowywać nazwy pochodzące z wielu przestrzeni nazw,
które z kolei mogą być rozsiane wśród wielu kompilatów.
Hierarchia przestrzeni nazw
Hierarchia przestrzeni nazw budowana jest za pomocą kropek umieszczanych pomiędzy
kolejnymi nazwami. Na przykład przestrzeń nazw System.Drawing.Printing podpo-
rządkowana jest hierarchicznie przestrzeni nazw System.Drawing, która z kolei podpo-
rządkowana jest przestrzeni nazw System. Można też powiedzieć, że nadrzędne prze-
strzenie nazw zawierają w sobie wszystkie przestrzenie podrzędne.
Rozdział 3. ♦ Język Delphi w środowisku .NET
277
Takie hierarchiczne związki zawierania mają jednak naturę wyłącznie koncepcyjną i mają
służyć przede wszystkim ludziom korzystającym ze środowiska .NET, umożliwiając
lepszą orientację w jego zawartości. Istnieje na przykład konwencja mówiąca, że podrzędna
przestrzeń nazw powinna być zależna od przestrzeni nadrzędnej, ale nie odwrotnie1.
Dla środowiska CLR związki zawierania przestrzeni nazw nie mają żadnego znaczenia.
Zawierane przestrzenie nazw mogą być zapisywane w osobnych kompilatach, nieza-
leżnych od nadrzędnej przestrzeni nazw, a takie kompilaty mogą być instalowane, ła-
dowane i usuwane całkowicie niezależnie od kompilatów nadrzędnej przestrzeni nazw.
Najczęściej jednak podrzędna przestrzeń nazw wykorzystuje elementy z przestrzeni
nadrzędnej, a odpowiednie kompilaty mogą być załadowane tylko wtedy, gdy dostępne
są też kompilaty nadrzędnej przestrzeni nazw. Ta zależność nie jest jednak definiowana
przez nazwy przestrzeni nazw, ale przez bezpośrednie instrukcje nakazujące włączenie
danej przestrzeni nazw (w języku C# instrukcja ta nazywa się using, a w Delphi — uses).
Kod zarządzany i CLR
Kod tworzony przez Delphi dla .NET jest kodem pośrednim zapisanym w języku
MSIL (ang. Intermediate Language) przygotowanym przez Microsoft, który dopiero
w czasie pracy programu w CLR przetłumaczony zostaje na kod maszynowy, dokład-
nie dopasowany do aktualnie używanego w systemie procesora. Z tego powodu apli-
kacje .NET mogą być uruchamiane tylko tym systemie, w którym zainstalowany jest
pakiet środowiska .NET.
Kod, który wykonywany jest przez CLR, nazywany jest też kodem zarządzanym (ang.
Managed Code). Na podobnej zasadzie, kod tworzony przez Delphi 7 określany jest
mianem kodu niezarządzanego (ang. Non-managed Code), który tak naprawdę jest do
pewnego stopnia zarządzany, choć nie przez system operacyjny, ale przez procesor.
W przypadku kodu niezarządzanego system operacyjny ogranicza się do załadowania
kodu w określone miejsce w pamięci i obsługi zgłoszonych przez procesor naruszeń
zabezpieczeń występujących na przykład w sytuacji, gdy z powodu błędnie ustawio-
nego wskaźnika program próbuje uzyskać dostęp do pamięci zarezerwowanej dla systemu
operacyjnego.
Zupełnie inaczej wygląda natomiast zarządzanie kodem wykonywanym w ramach CLR:
Środowisko CLR może odczytać wszystkie metadane zapisane w kompilatach i na ich
podstawie poznać typ każdej zmiennej stosowanej w programie oraz przeanalizować
kod programu w najdrobniejszych szczegółach. Nie ma tu możliwości uzyskania dostępu
do obcych obszarów pamięci, ponieważ w zarządzanym kodzie nie istnieją wskaźniki,
a CLR cały czas monitoruje wszystkie operacje na tablicach, nie pozwalając na dostępy
wykraczające poza zakres tablicy. Innymi słowy, kod zarządzany tylko wtedy może
spowodować naruszenie zabezpieczeń, kiedy nieprawidłowo działać będzie CLR.
Pozostałe cechy środowiska CLR, które można zaliczyć do kategorii „zarządzanie”,
to automatyczne zwalnianie pamięci (ang. Garbage Collector) i monitorowanie reguł
bezpieczeństwa zabraniających na przykład zapisywania plików klasom pochodzącym
z internetu i wykonywanym w przeglądarce internetowej.
1 Więcej na ten temat znaleźć można w dokumentacji środowiska .NET, w dokumencie „Namespace
Naming Guidelines”, ms-help://borland.bds3/cpgenref/html/cpconnamespacenamingguidelines.htm.
278
Delphi 2005
System wspólnych typów
Ze względu na bardzo ścisłe reguły stosowane w czasie automatycznego monitorowania
aplikacji przez CLR, nie ma już potrzeby przechowywania poszczególnych aplikacji
w całkowicie odizolowanych od siebie przestrzeniach pamięci, tak jak dzieje się to w no-
woczesnych systemach operacyjnych. Wszystkie aplikacje mogą być ładowane do tego
samego obszaru pamięci i działać w ramach jednego egzemplarza środowiska CLR.
Bardzo ważną zaletą takiego rozwiązania jest możliwość realizowania łatwej ko-
munikacji pomiędzy aplikacjami. Aplikacje odizolowane od siebie nawzajem mogą
wymieniać się danymi tylko poprzez specjalne mechanizmy, podczas gdy w środowisku
CLR aplikacje mogą przekazywać sobie i współużytkować całe obiekty.
W tym wszystkim najbardziej rewolucyjne jest to, że nie ma tu znaczenia język, w jakim
przygotowany został dany obiekt. Aplikacja napisana w języku C# może korzystać
z obiektów przygotowanych w Delphi, a Delphi może z kolei korzystać z obiektów
tworzonych w VB.NET. Co więcej, można napisać klasę w Delphi, będącą rozbudową
klasy przygotowanej oryginalnie w języku C#, a klasa ta może być tworem zbudowanym
na podstawie klasy środowiska .NET.
Kluczem do możliwości wspólnego wykorzystywania obiektów jest jeden z elementów
środowiska CLR: wspólny system typów (ang. Common Type System — CTS). Defi-
niuje on model obiektów każdej aplikacji środowiska .NET, a także typy podstawowe,
z którymi pracować muszą wszystkie aplikacje i z których można budować bardziej
złożone typy i klasy. Znany z Delphi typ SmallInt jest tylko inną nazwą dla funkcjo-
nującego w środowisku .NET typu Int16. Każda klasa w Delphi wśród swoich przodków
ma przynajmniej klasę Object pochodzącą ze środowiska .NET. Podobnie, wszystkie
pozostałe języki programowania .NET w ten czy inny sposób wykorzystują typ Int16
i klasę Object.
Jak widać, CTS jest wspólnym systemem typów obowiązujących wszystkie języki do-
stępne w środowisku .NET i w czasie działania tworzy wspólne implementacje wszyst-
kich podstawowych typów, wykorzystywanych we wszystkich aplikacjach .NET. Jak
wiemy, wszystkie aplikacje działające w środowisku .NET składają się z klas rozwi-
jających klasy CTS, wobec tego każdą aplikację można traktować jak część CTS lub
jego rozszerzenie.
Więcej szczegółów na temat związków pomiędzy typami CTS a typami Delphi po-
dawać będę w podrozdziale 3.6.
3.1.2. Przestrzenie nazw w Delphi
Jako programiści tworzący w Delphi, związkami łączącymi przestrzenie nazw i kom-
pilaty martwić się musimy dopiero wtedy, gdy sytuacja zmusza nas do wykorzystania
„obcych” przestrzeni nazw i kompilatów. W programowaniu w Delphi przestrzenie
nazw i kompilaty wynikają ze starszych pojęć funkcjonujących w języku Object Pascal
— modułu (ang. unit), programu (ang. program) i pakietu (ang. package):
Rozdział 3. ♦ Język Delphi w środowisku .NET
279
(cid:141) Każdy projekt w Delphi kompilowany jest do jednego kompilatu i w związku
z tym zawiera w sobie te przestrzenie nazw, które tworzone są w modułach
tego projektu.
(cid:141) Każdy moduł w Delphi automatycznie tworzy nową przestrzeń nazw, o nazwie
zgodnej z nazwą modułu. Moduł MyUnit.pas powiązany jest z przestrzenią
nazw MyUnit, a jeżeli moduł ten znajdować się będzie w projekcie MyProject.dpr,
to z plikiem projektu powiązana zostanie kolejna przestrzeń nazw, o nazwie
MyProject. Jedyną metodą pozwalającą na ręczną zmianę nazewnictwa przestrzeni
nazw jest zmiana nazewnictwa modułów.
Tworzenie przestrzeni nazw
W czasie nadawania nazw nowym modułom i programom tworzymy jednocześnie nazwy
przestrzeni nazw, dlatego twórcy języka Delphi w firmie Borland pozwolili na stoso-
wanie kropek w nazwach programów i modułów. Dzięki temu możemy teraz nazwać plik
projektu na przykład MojaFirma.MojProgram.dpr, a jednemu z modułów nadać nazwę
MojaFirma.MojProgram.UI.Dialogi.Login.pas. Na podstawie nazwy pliku zawierają-
cej kropki kompilator przygotuje nazwę przestrzeń nazw, usuwając z nazwy pliku
ostatni człon wraz z kropką, tak jak pokazano to na listingu 3.1.
Listing 3.1. Sposób tworzenia przestrzeni nazw na podstawie nazw programów i modułów
// Pierwszy wiersz w pliku .dpr:
program MojaFirma.MojProgram;
// - Przestrzeń nazw nazywa się MojaFirma
// Pierwszy wiersz w pliku .pas:
unit MojaFirma.MojProgram.UI.Dialogi.Login;
// - Przestrzeń nazw nazywa się MojaFirma.MojProgram.UI.Dialogi
Mimo kropek znajdujących się w nazwach, kompilator Delphi rozpoznaje je tylko jako
całość. Jeżeli w programie użyjemy osobnego identyfikatora, takiego jak MojaFirma lub
Login, to kompilator zgłosi błąd, informując nas o znalezieniu nieznanego identyfikatora.
Informacja dla osób, które pracowały już w Delphi 8: w Delphi 2005 zmieniona
została stosowana w kompilatorze konwencja nazewnictwa przestrzeni nazw.
W Delphi 8 nie był usuwany ostatni człon nazwy, tak więc w podawanym wyżej
przykładzie nazwa modułu w całości wchodziłaby do nazwy przestrzeni nazw,
włącznie z ostatnim członem Login. Jeżeli weźmiemy pod uwagę fakt, że przestrzenie
nazw są kontenerami dla typów, a w module Login z całą pewnością zadeklarowany
będzie typ formularza o nazwie LoginForm, to dojdziemy do wniosku, że mecha-
nizm nazywania stosowany w Delphi 2005 jest lepiej zorganizowany. W Delphi 2005
pełny identyfikator typu tego formularza otrzymałby nazwę MojaFirma.MojProgram.
UI.Dialogi.LoginForm, podczas gdy w Delphi 8 ten sam identyfikator otrzymałby nieco
dłuższą i powtarzającą się na końcu nazwę MojaFirma.MojProgram.UI.Dialogi.
Login.LoginForm.
280
Delphi 2005
Korzystając z narzędzia Reflection, można kontrolować przestrzenie nazw, jakie zapi-
sywane są w kompilatach tworzonych przez Delphi. Każda z nazw tych przestrzeni
nazw rozkładana jest zgodnie z umieszczonymi w niej kropkami na części określające
hierarchiczne poziomy, a każdemu poziomowi przyporządkowany jest osobny symbol
folderu. W kompilacie naprawdę znajdują się tylko te przestrzenie nazw, przy których
symbolach folderów znajdują się kolejne węzły podrzędne, a przynajmniej jeden symbol
o nazwie Unit.
Na rysunku 3.1 przedstawiono projekt, do którego w ramach porównania dołączono
trzy podobne nazwy modułów (proszę przyjrzeć się zawartości okna menedżera pro-
jektu znajdującego się w prawej dolnej części rysunku. Przedstawiony projekt został
skompilowany do pliku .exe i załadowany do programu Reflection.
Rysunek 3.1.
Moduły Delphi
wyświetlane
w menedżerze
projektu i powiązane
z nimi przestrzenie
nazw wyświetlane
w programie
Reflection
Wykorzystywanie przestrzeni nazw i kompilatów
Chcąc w swoim programie wykorzystywać symbole pochodzące z innych przestrzeni
nazw, musimy wymienić je po słowie kluczowym uses we wszystkich modułach pro-
gramu, w których używane są symbole danej przestrzeni nazw. W module MonitorForm
z przykładowego programu SystemLoadMonitor (punkt 1.5.4) wykorzystywany jest
cały szereg klas środowiska .NET, w związku z czym do modułu musiało zostać dołą-
czonych kilka przestrzeni nazw, o czym można przekonać się, przeglądając listing 3.2.
Rozdział 3. ♦ Język Delphi w środowisku .NET
281
Listing 3.2. Przestrzenie nazw używane w module MonitorForm programu SystemLoadMonitor
unit MonitorForm;
interface
uses
System.Drawing, System.Collections,
System.ComponentModel, System.Windows.Forms, System.Data,
System.Diagnostics, Microsoft.Win32,
System.Runtime.InteropServices, System.Globalization;
Oprócz tego, kompilator musi jeszcze wiedzieć, w których kompilatach będzie mógł
znaleźć podane przestrzenie nazw (a dokładniej: symbole zapisane w podanych prze-
strzeniach nazw). W tym celu do projektu należy dodać odpowiednie referencje, umiesz-
czając je w menedżerze projektu, w gałęzi References (proszę zobaczyć rysunek 3.2).
Rysunek 3.2.
Kompilaty,
do których odwołuje
się program, muszą
zostać wymienione
w menedżerze projektu
Kompilaty przedstawione na rysunku dodawane są do projektu automatycznie, zaraz
po utworzeniu nowego projektu. Przechowują one w sobie bardzo wiele ważnych klas
środowiska .NET. Przy okazji dodawania do formularza nowego komponentu Delphi
rozbudowuje listę kompilatów, uzupełniając ją w razie potrzeby o wszystkie te kompilaty,
których wymaga nowo dodany komponent.
Jeżeli w programie korzystać chcemy z klas, które nie są umieszczone w standardo-
wych kompilatach, to musimy własnoręcznie rozbudować listę kompilatów, dodając
do niej nowe pozycje. W tym celu należy wywołać z menu kontekstowego menedżera
projektu pozycję Add Reference i wybrać jeden lub kilka kompilatów z przedstawionej
listy (okno z tą listą zobaczyć można na rysunku 3.3). Po naciśnięciu przycisku Add
Reference wybrane kompilaty przenoszone są do dolnej listy New References, a po
naciśnięciu przycisku OK kompilaty znajdujące się na dolnej liście dołączane są do
projektu. Jeżeli potrzebny nam kompilat nie jest obecny na przedstawionej w oknie liście,
to korzystając z przycisku Browse możemy wyszukać na dysku dowolny kompilat.
Delphi 2005
282
Rysunek 3.3.
Wybrane zostały
dwa kompilaty
środowiska .NET,
które zajmują się
funkcjonowaniem
komponentów
w czasie
projektowania
aplikacji
Każda referencja wymieniona w menedżerze projektu wpisywana jest też do pliku
projektu (zawartość tego pliku zobaczyć można, wybierając z menu pozycję Project
View Source), którego przykład można zobaczyć na listingu 3.3.
Listing 3.3. Referencje kompilatów zapisane w pliku projektu
program SystemLoadMonitor;
{ DelphiDotNetAssemblyCompiler
$(SystemRoot)microsoft.netframeworkv1.1.4322System.dll }
{ DelphiDotNetAssemblyCompiler
$(SystemRoot)microsoft.netframeworkv1.1.4322System.Data.dll }
...
Konsolidacja statyczna i dynamiczna
Do programów przygotowanych w Delphi kompilaty środowiska .NET dołączane są
dopiero w czasie ich działania, co oznacza, że dołączone są one poprzez konsolidację
dynamiczną. Części samego programu, czyli jego moduły, włączane są do pliku .exe już
w czasie kompilacji programu (konsolidacja statyczna). W przypadku modułów do-
starczanych razem z Delphi nie jesteśmy ograniczeni do stosowania konsolidacji sta-
tycznej, ale wszystkie biblioteki czasu wykonania obecne w Delphi można też dołączać
do programu dynamicznie.
W tym miejscu ponownie trzeba wykorzystać polecenie menedżera projektu Add Reference.
Biblioteki dostarczane razem z Delphi zapisane są w szeregu plików .dll, do których
referencje możemy umieścić w naszym programie. Moduły znajdujące się w tak dołączo-
nych do programu bibliotekach nie muszą być już fizycznie integrowane z plikiem .exe
aplikacji w procesie kompilacji.
Rozdział 3. ♦ Język Delphi w środowisku .NET
283
Mały przykład: W każdej aplikacji tworzonej w Delphi nieodzowna jest jedna z bibliotek
czasu wykonania dostarczanych razem z Delphi (moduł System), która znajduje się
w pliku borland.delphi.dll. Jeżeli bibliotekę tę dodamy do naszej aplikacji tak jak po-
kazano na rysunku 3.4, to w efekcie uzyskamy znacznie mniejszy plik wykonywalny
aplikacji. W minimalnej aplikacji Windows-Forms, składającej się z jednego pustego
formularza, wielkość pliku .exe spada z 21 do 7 kB, a najprostsza aplikacja konsolowa
kompilowana z wykorzystaniem konsolidacji dynamicznej zamyka się w pliku o wielkości
5 kB. W przypadku aplikacji konsolowych korzystających z modułu SysUtils konieczne
jest dołączenie do programu referencji biblioteki borland.vcl, co ma zablokować włą-
czenie tej biblioteki do pliku wykonywalnego.
Rysunek 3.4.
Dynamicznie
konsolidowane
mogą być też
biblioteki czasu
wykonania
dostarczane
razem z Delphi
Tworząc aplikacje konsolidowane dynamicznie musimy upewnić się, że kompilaty, do
których tworzymy referencje, rzeczywiście znajdować się będą na komputerze, na którym
pracować ma nasza aplikacja.
Jeżeli chcielibyśmy się dowiedzieć, czy w pliku .exe naszej aplikacji nadal znajdują
się niepotrzebnie obciążające go biblioteki, to wystarczy otworzyć ten plik w IDE
Delphi, a wszystkie dane pliku wyświetlone zostaną w narzędziu Reflection. Jeżeli
w wyświetlanym drzewie nie ma gałęzi o nazwie Borland, to znaczy, że w pliku nie
zostały zapisane żadne moduły przygotowane przez firmę Borland.
Wymaganie powiązania każdej aplikacji Delphi (w sposób statyczny lub dynamiczny)
z modułem System nie jest niczym wyjątkowym, ponieważ takie samo wymaganie
istnieje we wszystkich innych językach środowiska .NET z wyjątkiem języka C#.
Dołączenie biblioteki dopasowującej język do podstawy tworzonej przez CLR wy-
magane jest także w językach VB.NET, i C++ dla .NET. Jedynie język C# nie po-
trzebuje stosowania takiego dopasowania, ponieważ został on od podstaw zapro-
jektowany do współpracy ze środowiskiem .NET.
Wszystkie trzy przykłady tworzenia aplikacji („aplikacja WinForms konsolidowana
statycznie”, „aplikacja WinForms konsolidowana dynamicznie” i „aplikacja konsolowa
konsolidowana dynamicznie”) znaleźć można na płycie CD dołączonej do książki
w katalogu Rozdzial3LinkSorts.
284
Delphi 2005
3.1.3. Kompilaty w Delphi
Jak już mówiłem w punkcie 3.1.2, kompilator Delphi przekształca projekt aplikacji
w kompilat środowiska .NET. O typie tworzonego kompilatu (jak wiemy, istnieją dwa
rodzaje plików kompilatów) decyduje typ projektu przygotowywanego w Delphi.
Kompilaty EXE
Jeżeli projekt Delphi zapisywany jest w pliku o rozszerzeniu .dpr, a tekst źródłowy
projektu rozpoczyna się od słowa program, to taki projekt może być nazywany rów-
nież aplikacją, a Delphi na jego podstawie przygotowywać będzie plik (kompilat)
wykonywalny, którego rozszerzenie będzie identyczne z rozszerzeniem aplikacji sto-
sowanych w środowisku Win32 — .exe. To rozszerzenie informuje nas też o tym, że
plik ten może być uruchamiany dokładnie tak samo jak każdy inny plik o rozszerze-
niu .exe, na przykład dwukrotnym kliknięciem w Eksploratorze Windows albo wy-
wołaniem z wiersza poleceń. Takie działanie jest możliwe dlatego, że każdy z takich
plików zawiera w sobie kod maszynowy, który może być uruchomiony w systemach
Win32. Jedynym zadaniem tego kodu jest sprawdzenie obecności w systemie środo-
wiska .NET i CLR, i w przypadku ich znalezienia — wywołanie tego środowiska w celu
uruchomienia właściwej aplikacji.
W IDE Delphi dostępne są wstępnie przygotowane szablony projektów przeznaczone
do budowania różnych aplikacji, takich jak aplikacje konsolowe (ang. Console Application),
aplikacje Windows-Forms (ang. Windows Forms Application) lub aplikacje VCL (ang.
VCL Forms Application; są to pozycje menu FileNewOther).
Kompilaty DLL
Kompilaty DLL tworzone są wtedy, gdy kompilowany jest pakiet (ang. Package)
Delphi. Projekt pakietu zapisywany jest w pliku źródłowym o rozszerzeniu .dpk, w którym
najważniejszym słowem jest słowo kluczowe package. Nowy projekt pakietu środowiska
.NET tworzony jest w IDE Delphi wywołaniem pozycji menu FileNewOtherDelphi
for .NET ProjectsPackage.
Pakiety również mogą mieć własne referencje na inne kompilaty, ale w menedżerze pro-
jektów nie są one nazywane referencjami (ang. References), ale wypisywane są w węźle
Required (wymagane), co dobrze widać na rysunku 3.5.
Rysunek 3.5. Przykładowa biblioteka dynamiczna zawierająca jeden formularz, przedstawiona
w menedżerze projektu
Rozdział 3. ♦ Język Delphi w środowisku .NET
285
Przykład przedstawiony na rysunku (na płycie CD znaleźć można go w katalogu
Rozdzial3PackagesFormTestpackage.dpr) jest pakietem, który ma za zadanie udo-
stępniać poprzez bibliotekę dynamiczną prosty formularz testowy. Pakiet ten przy-
gotowany został w trzech bardzo prostych krokach:
(cid:141) Utworzenie nowego pakietu wywołaniem z menu pozycji FileNewOther
Delphi for .NET ProjectsPackage (na tym etapie w węźle Requires znajduje
się tylko pozycja Borland.Delphi.dll).
(cid:141) Przygotowanie nowego formularza wywołaniem z menu pozycji FileNew
OtherDelphi for .NET ProjectsNew FilesWindows Form (w tym momencie
do menedżera projektu dodawane są pozostałe wpisy).
(cid:141) Ułożenie na formularzu etykiety pozwalającej na rozpoznanie go w czasie
testowych wywołań.
Jawne użycie modułów
Najważniejsza reguła tworzenia pakietów mówi, że wszystkie moduły muszą być jawnie
dowiązywane do pakietu, co oznacza, że:
(cid:141) Albo moduł musi znajdować się w bibliotece dynamicznej, która dowiązywana
jest do pakietu poprzez referencję (w menedżerze projektu wypisana musi być
w gałęzi Requires — jeżeli do tego węzła dodamy nowe pozycje korzystając
z polecenia Add Reference, to operację tę przeprowadzać będziemy w oknie
przedstawionym na rysunku 3.3).
(cid:141) Albo moduł musi znajdować się w węźle o nazwie Contains (zawiera).
W menu kontekstowym tego węzła znajdziemy pozycję Add…, która
otwiera okno dialogowe umożliwiające wybranie potrzebnego nam modułu.
Wszystkie biblioteki DLL pochodzące z Delphi powinny być dynamicznie dołączane
do tworzonych pakietów, ponieważ tylko taka konfiguracja pozwoli na stosowanie
pakietu wewnątrz aplikacji przygotowanej w Delphi, która również wymaga zastosowania
tych samych bibliotek dynamicznych. Jeżeli w tworzonym pakiecie usuniemy z węzła
Requires zapisaną w nim bibliotekę Borland.Delphi.dll, to moduł Borland.Delphi.
System zostanie dołączony do pakietu statycznie. W takiej sytuacji użycie tego pakietu
w aplikacji przygotowanej w Delphi wiązałoby się z dwukrotnym uruchomieniem bi-
blioteki DLL — jednym z aplikacji, a drugim z używanego przez nią pakietu. Po wy-
kryciu takiego przypadku kompilator przerwie kompilowanie aplikacji i wypisze na-
stępujący komunikat:
[Fatal Error] Package FormTestPackage already contains unit
Borland.Delphi.System .
Używanie samodzielnie przygotowanych pakietów
W celu dowiązania pakietu do własnego projektu należy skorzystać z procedury przed-
stawionej w punkcie 3.1.2 i dodać do projektu referencję pliku .dll pakietu. Jeżeli tego nie
zrobimy, a jedynie umieścimy nazwy modułów zawartych w pakiecie w klauzuli uses, to
kompilator dołączy te moduły bezpośrednio do pliku wykonywalnego naszego projektu.
286
Delphi 2005
Na rysunku 3.6 zobaczyć można, w jaki sposób przygotowana przed chwilą biblioteka
dynamiczna o nazwie FormTestPackage.dll wykorzystywana jest w aplikacji tworzo-
nej w Delphi. Przygotowany został nowy projekt aplikacji Windows-Forms, a biblioteka
DLL dołączona została do niego w menedżerze projektu za pomocą pozycji menu
Required/Add reference/Browse. Następnie moduł z biblioteki został wprowadzony
do modułu formularza aplikacji poprzez dopisanie jego nazwy do klauzuli uses (w czasie
uzupełniania listy uses można skorzystać z pomocy w programowaniu).
Rysunek 3.6. Przykładowa biblioteka dynamiczna z formularzem przedstawiana w menedżerze projektu
Kolejnym krokiem było umieszczenie na formularzu aplikacji przycisku opisanego
Wywołaj formularz biblioteki, który opatrzymy został bardzo prostą procedurą obsługi
zdarzenia Click, przedstawioną na listingu 3.4.
Listing 3.4. Procedura wywołująca formularz pobrany z biblioteki dynamicznej
// Na płycie CD: Rozdzial3PackagesDLLUser.bdsproj (projekt Delphi)
procedure TWinForm2.Button1_Click(sender: System.Object;
e: System.EventArgs);
begin
FormForDll.TWinForm2.Create.ShowDialog;
end;
Nic więcej nie trzeba — program i biblioteka DLL są od razu gotowe do uruchomienia.
Należy tu zauważyć, że równie łatwo biblioteki napisane w Delphi można wykorzy-
stywać w programach tworzonych w języku C#. Kroki, jakie należy w tym celu wy-
konać w pakiecie C#-Builder, są niemal identyczne z tymi znanymi z Delphi: utworzyć
Rozdział 3. ♦ Język Delphi w środowisku .NET
287
nowy projekt, przygotowaną w Delphi bibliotekę dopisać do referencji projektu, do-
wiązać przestrzeń nazw (w C# zamiast słowa uses stosowane jest słowo using) i wy-
wołać formularz. Ten ostatni krok wymaga użycia nieco zmienionej składni, ponie-
waż z punktu widzenia języka C# konstruktory nie tylko nie nazywają się Create, ale
w ogóle nie mają nazwy i wywoływane są przez operator new. Kod takiego wywołania
zapisanego w języku C# podaję na listingu 3.5, a wynik działania tego kodu zobaczyć
można na rysunku 3.7.
Listing 3.5. Procedura wywołująca formularz pobrany z biblioteki dynamicznej zapisana w języku C#
// Na płycie CD: Rozdzial3PackagesCSharpDLLUser.bdsproj (projekt C#-Builder)
using FormForDll;
...
private void button1_Click(object sender, System.EventArgs e)
{
(new FormForDll.TWinForm2()).ShowDialog();
}
Rysunek 3.7. Formularz skompilowany w Delphi wyświetlany jest przez aplikację napisaną w języku C#.
Tutaj jeszcze w starym, oddzielnym pakiecie C#-Builder, który teraz zintegrowany jest z Delphi 2005
W punkcie 6.1.4 dokładniej przyjrzymy się pakietowi przykładowych komponentów
przygotowanych na potrzeby tej książki, który oprócz tego, że zawiera kilka cieka-
wych komponentów, jest przykładem całkowicie normalnego pakietu.
Biblioteki z punktami wejścia Win32
Specjalną alternatywą tworzenia bibliotek dynamicznych środowiska .NET jest projekt
typu library, który w IDE Delphi znaleźć można w pozycji menu FileNewOther
Lib
Pobierz darmowy fragment (pdf)