Wprowadzenie do
C++Buildera
Rozdział ten stanowi wprowadzenie do C++Buildera, jednego z najczęściej używanych narzędzi
do tworzenia aplikacji internetowych, bazodanowych typu desktop i klient-serwer, programowania
rozproszonego itp. C++Builder łączy w sobie charakterystyczne cechy środowiska typu RAD
(ang. Rapid Applications Development błyskawiczne tworzenie aplikacji) z funkcjonalnością
ANSI C++. Jest narzędziem na wskroś uniwersalnym, przydatnym zarówno dla amatorów
programowania, jak i profesjonalnych zespołów projektowych.
Podstawowe informacje na temat zalet C++Buildera i korzyści wynikających z jego
zastosowania znajdziesz na stronie http://www.borland.com/bcppbuilder/ w
punktach Features & Benefits i New C++Builder Users .
Zaawansowani programiści mogą rozdział ten pominąć; pozostali znajdą w nim informacje o
podstawowych elementach C++Buildera, a także porównanie jego istotnych cech z innymi
środowiskami projektowymi i wskazówki dotyczące przenoszenia na jego grunt aplikacji z tychże
środowisk.
Zainteresowani Czytelnicy znajdą tu również wprowadzenie do Kyliksa jednego z
najciekawszych produktów ostatnich lat, będącego w istocie adaptacją Delphi i C++Buildera na
gruncie Linuksa. Kylix pozwala tworzyć zaawansowane aplikacje w środowisku tego
zdobywającego coraz większą popularność systemu z równą łatwością, jak w środowisku
Windows. Większość zagadnień dotyczących C++Buildera, omawianych w tej książce, odnosi się
także do Kyliksa.
Podstawowe elementy C++Buildera
W podrozdziale tym przedstawimy podstawowe elementy C++Buildera i zilustrujemy ich
zastosowanie na przykładzie prostej aplikacji.
Pierwsze spojrzenie
Jeżeli już zainstalowałeś C++Buildera na swoim komputerze i chciałbyś szybko wykonać za jego
pomocą coś pożytecznego nie ma na co czekać; już za chwilę staną się dla Ciebie jasne takie
pojęcia, jak: projekt, komponenty VCL, inspektor obiektów i ich rola w środowisku IDE.
Pierwotnie programiści posługiwali się narzędziami dla DOS-a, uruchamianymi z wiersza poleceń.
Kiedy MS Windows zdominowały rynek systemów operacyjnych, w naturalny sposób również i
rynek kompilatorów zwrócił się w stronę tego środowiska; jednym z najbardziej znanych
kompilatorów C dla Windows był kompilator C++ w wersji 3.1. Nie uprościło to bynajmniej
samego procesu programowania, a wręcz przeciwnie: na programiście spoczywała
odpowiedzialność za całokształt komunikacji z systemem operacyjnym obsługa komunikatów,
utrzymywanie odpowiedniego wyglÄ…du okienek itp. Nawet prosty program powodujÄ…cy tylko
wyświetlanie pustego okienka miał rozmiar kilkustronicowy.
Sytuacja zmieniła się nieco (na korzyść programistów) po opracowaniu przez Borland narzędzia o
nazwie ObjectWindows Library (OWL). OWL, zgodne ze standardami kompilatora wersji 3.1,
przejmowało na siebie większość nużących szczegółów systemowych, pozwalając programiście
skupić się na istocie rozwiązywanego problemu. Zostało ono rozbudowane wraz z
wprowadzeniem na rynek nowego kompilatora C++ w wersji 5.0.
Prawdziwym przełomem okazało się pojawienie Delphi, narzędzia z kategorii RAD, będącego de
facto czymś na kształt wizualnego Pascala jeżeli trzymać się analogii do Visual Basica czy też
Visual C. Niedługo pózniej Borland opracował analogiczne narzędzie oparte na C++, nadając mu
nazwÄ™ C++Builder. Korzysta ono z tych samych bibliotek co Delphi, ponadto posiada niemal
identyczny interfejs użytkownika.1 W porównaniu z innym popularnym kompilatorem Visual
C++ charakteryzuje się większą łatwością tworzenia aplikacji i większą przenośnością tych
ostatnich pomiędzy różnymi platformami.
Niewątpliwie dobre opanowanie języka programowania (również C++) wymaga kilku lat praktyki.
Narzędzia kategorii RAD np. C++Builder mogą jednakże uczynić tę naukę bardziej efektywną,
ponadto umożliwiają tworzenie nietrywialnych aplikacji już na wczesnym etapie tej drogi, a to za
sprawą obiektowych komponentów VCL, skrywających w sobie wiele skomplikowanych
możliwości i uwalniających użytkownika od żmudnego programowania.
Przystąpmy więc do konkretów; pominiemy przy tym wiele szczegółów dotyczących instalacji i
obsługi C++Buildera, które znalezć można w dokumentacji, a których wyczerpujący opis
wymagałby odrębnej książki. Skoncentrujemy się za to na metodologii tworzenia konkretnej
aplikacji.
Po prawidłowym zainstalowaniu C++Buildera i jego uruchomieniu ukaże się zintegrowane
środowisko projektowe (IDE Integrated Development Environment) przedstawione na rysunku
1.1. Składa się ono z trzech zasadniczych okien, za pośrednictwem których możliwe jest
1
Oczywiście w ramach odpowiadających sobie wersji C++ i Delphi; porównanie drogi rozwojowej Delphi i
C++Buildera (określane niekiedy mianem żabiego skoku ) znajduje się w rozdziale 21. książki Delphi 4 dla
każdego (Helion, Gliwice 1999) przyp. tłum.
manipulowanie kontrolkami i komponentami, ustawianie ich właściwości oraz wpisywanie kodu
programu.
Pasek Menu główne Paleta
narzędziowy komponentów
Inspektor
Formularz
obiektów
Edytor kodu
Rysunek 1.1. Åšrodowisko zintegrowane C++Buildera 5
Biblioteka VCL, formularze i komponenty
Biblioteka komponentów (ang. VCL Visual Component Library) stanowi magazyn
komponentów wykorzystywanych do tworzenia aplikacji. Poszczególne komponenty biblioteki
odpowiadają poszczególnym komponentom gotowego programu menu, przyciskom, listom
wyboru, obrazkom itp. Komponenty te skrywają w sobie znaczną część kodu, przez co
programista zwolniony jest w dużej części z kodowania podstawowych funkcji programu.
Poszczególne aspekty zachowania się komponentów mogą być regulowane za pomocą ich
właściwości (ang. properties) dostępnych za pośrednictwem inspektora obiektów (patrz rys.
1.1), bądz bezpośrednio w kodzie programu. Oprócz wykorzystywania gotowych komponentów
zaawansowany programista ma możliwość tworzenia nowych komponentów, stosownie do swych
potrzeb.
Formularze
Poszczególne formularze aplikacji odpowiadają poszczególnym oknom działającego programu;
gdy rozpoczynasz tworzenie nowej aplikacji, wyświetlony zostaje automatycznie pusty formularz,
zwany formularzem głównym w działającym programie stanie się on jego oknem głównym.
Umieszczając na formularzu komponenty VCL oraz ustalając ich położenie i rozmiary, budujemy
żądany interfejs użytkownika. Oprócz komponentów wizualnych istnieją również tzw.
komponenty niewidoczne na etapie projektowania sÄ… one reprezentowane przez odpowiednie
ikony, natomiast w działającym programie nie są bezpośrednio widoczne w interfejsie
użytkownika, jakkolwiek spełniają zadania nie mniej ważne od komponentów wizualnych.
Przykładami komponentów niewidocznych są zegary (ang. timers), służące do odmierzania
ustalonych odcinków czasu.
Paski narzędziowe
Paski przycisków (ang. speedbars) umożliwiają szybki dostęp do najczęściej wykorzystywanych
opcji menu, jak: Run (uruchomienie aplikacji), Step Through (praca krokowa), View Form
(oglądanie formularza) itp. Użytkownik ma możliwość przystosowywania zawartości pasków
narzędziowych do swoich potrzeb.
Konfigurowanie pasków narzędziowych
Jedną z niezaprzeczalnych zalet środowiska IDE jest jego konfigurowalność. Zawartość
dowolnego paska narzędziowego może być łatwo zmieniana poprzez dodawanie i usuwanie
przycisków wyjątkiem w tym względzie jest paleta komponentów, nie zawierająca przycisków,
lecz (zgodnie z nazwÄ…) komponenty VCL.
C++Builder zawiera następujące paski narzędziowe:
" Standard;
" View;
" Debug;
" Custom;
" Component Palette (paleta komponentów).
Aby zmienić zawartość dowolnego paska narzędziowego, wykonaj kolejno następujące czynności:
1. Kliknij prawym przyciskiem myszy gdziekolwiek w wolnym obszarze paska (poza
przyciskami).
2. Z wyświetlonego menu kontekstowego wybierz opcję Customize.
3. Wyświetlone zostanie okno dialogowe konfiguracji (rys. 1.2); przejdz na jego stronę
Commands.
4. Przeciągnij żądane polecenia z okna dialogowego na pasek.
5. Jeżeli chcesz usunąć któryś z przycisków, przeciągnij go po prostu poza obszar paska.
Rysunek 1.2. Okno dialogowe konfiguracji paska narzędziowego
Paleta komponentów
Paleta komponentów, znajdująca się bezpośrednio pod menu głównym, stanowi zasobnik
komponentów VCL. Komponenty te zorganizowane są w strony, odpowiadające poszczególnym
kategoriom. Aby przenieść komponent na formularz, należy kliknąć jego ikonę w palecie
komponentów, a następnie kliknąć w miejscu, w którym ma się on docelowo znalezć. Jak już
wcześniej wspomniano, wygląd i szczegóły funkcjonowania komponentów mogą być regulowane
za pomocą właściwości, dostępnych za pośrednictwem inspektora obiektów lub bezpośrednio w
kodzie programu.
Zdarzenia i ich obsługa
Tym, co decyduje o dynamice działającego programu, są zdarzenia (ang. events). Aby wyjaśnić
ich istotÄ™, zbudujemy prostÄ… aplikacjÄ™ w postaci pojedynczego przycisku na formularzu (rys. 1.3).
Przyciski są niezwykle często spotykanymi elementami interfejsu użytkownika, który za ich
pośrednictwem poleca aplikacji wykonanie określonych czynności.
Komponent odpowiadajÄ…cy przyciskowi umieszczony jest w palecie na stronie Standard pod
nazwą Button; jego ikona przedstawia przycisk z napisem OK. Aby przenieść ów komponent na
formularz, należy kliknąć najpierw tę ikonę, a następnie odpowiednie miejsce formularza.
Rysunek 1.3. Prosta aplikacja pojedynczy przycisk na formularzu
Tak przygotowaną aplikację można już skompilować i uruchomić, lecz nie okaże się ona
szczególnie użyteczna: klikanie w przycisk nie będzie powodowało żadnych widocznych efektów.
Dzieje się tak dlatego, iż zdarzenie generowane w wyniku kliknięcia przycisku nie jest w żaden
sposób obsługiwane. Darujmy sobie w tym momencie ścisłą definicję zdarzenia ; na użytek
tworzonej aplikacji można przyjąć, iż w wyniku wystąpienia zdarzenia wywoływana jest
odpowiednia funkcja, zwana funkcją obsługi zdarzenia (ang. event handler). Aby przypisać
funkcję obsługującą kliknięcie przycisku, zakończmy uruchomioną aplikację, powracając do etapu
projektowania i kliknijmy ów przycisk dwukrotnie (lewym przyciskiem myszy); C++Builder
wyświetli wówczas fragment kodu aplikacji z wygenerowanym szkieletem odpowiedniej funkcji
obsługi:
void __fastcall TForm1::Button1Click(Tobject *Sender)
{
}
Ten sam efekt można wywołać, wybierając komponent Button1 w inspektorze obiektów,
przechodzÄ…c na stronÄ™ Events i klikajÄ…c dwukrotnie pozycjÄ™ odpowiadajÄ…cÄ… zdarzeniu
OnClick. Jak łatwo zauważyć, nazwa funkcji składa się z nazwy odpowiedniego komponentu
(Button1) i nazwy zdarzenia (Click).
Po kliknięciu prawym przyciskiem myszy okna edytora kodu i wybraniu z menu kontekstowego
pozycji Open Source/Header File C++Builder wyświetli następujący kod:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include
#include
#include
#include
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Powyższy kod generowany jest automatycznie i jego szczegóły nie są w tej chwili szczególnie
istotne; zamieściliśmy go tutaj raczej w celu pokazania, w jak dużym stopniu C++Builder potrafi
wyręczyć programistę. Powróćmy jednak do naszej funkcji obsługi, obecnie jeszcze pustej.
Sprawmy, by kliknięcie przycisku na formularzu powodowało zakończenie działania programu
w tym celu kliknijmy w oknie edytora kodu zakładkę Unit1.cpp i uzupełnijmy rzeczoną
funkcję obsługi następująco:
void __fastcall TForm1::Button1Click(Tobject *Sender)
{
ShowMessage("Witam!To jest aplikacja testowa. Naciśnij OK");
Close();
}
Teraz należy skompilować i uruchomić aplikację można to zrobić na jeden z trzech sposobów:
" naciskajÄ…c klawisz F9;
" wybierajÄ…c opcjÄ™ Run z menu Run;
" klikając przycisk (na pasku narzędziowym) w kształcie zielonego trójkącika.
Kliknięcie przycisku na formularzu w uruchomionym programie spowoduje teraz wywołanie
funkcji TForm1::Button1Click, której treść jest raczej intuicyjnie jasna nawet dla
początkującego programisty: otóż najpierw wyświetlone zostanie okienko ze standardowym
komunikatem (polecenie Naciśnij OK. odnosi się do przycisku w tymże oknie, nie do naszego
przycisku na formularzu przyp. tłum.), po którego zamknięciu wywołana zostanie metoda
Close() naszego formularza głównego, zamykająca ów formularz i tym samym kończąca
wykonanie programu.
Pierwsze programy
Pokażemy teraz, jak łatwo jest zbudować niewielkim wysiłkiem całkiem przyzwoity program
oczywiście jeżeli ma się pod ręką C++Buildera. Wybierz z menu głównego opcję File|New
Application; C++Builder stworzy nowy projekt i wyświetli pusty formularz główny.
Przejdz na stronę Additional w palecie komponentów i kliknij komponent Image (rys. 1.4):
Image
Rysunek 1.4. Komponent Image
Kliknij następnie formularz komponent Image zaprezentuje się w postaci czarnej ramki.
Przejdz do inspektora obiektów, znajdz właściwość Stretch i ustaw ją na true.
Następnie przejdz na stronę Dialogs palety komponentów (być może konieczne okaże się
przewinięcie palety w lewo) i kliknij najpierw komponent OpenDialog (rys. 1.5), a następnie
kliknij w pobliżu lewego górnego narożnika formularza, gdzie powinna pojawić się ikona tego
komponentu.
OpenDialog
Rysunek 1.5. Komponent OpenDialog
W inspektorze obiektów, wskazującym komponent OpenDialog1, znajdz właściwość Filter i
wpisz w jej pole wartości następujący tekst:
Bitmapy|*.BMP
W ten oto sposób stworzyłeś komponent dialogowy, za pomocą którego będzie możliwy wybór
plików z rozszerzeniem .BMP.
Kolej teraz na dwa przyciski, z których pierwszy inicjował będzie akcję wczytywania pliku, drugi
natomiast posłuży do zakończenia pracy aplikacji. Komponent przycisku Button znajduje się w
palecie na stronie Standard (rys. 1.6); w czasie jego klikania przytrzymaj klawisz Shift
spowoduje to, iż komponent pozostanie zaznaczony i każdorazowe kliknięcie w obszarze
formularza powodować będzie umieszczenie na nim kolejnego przycisku, do czasu kliknięcia w
białą strzałkę na początku palety. Dla naszej aplikacji potrzebne są dwa przyciski C++Builder
automatycznie nada im nazwy Button1 i Button2.
Button
Rysunek 1.6. Komponent Button
Wypadałoby nadać pierwszemu z przycisków tytuł adekwatny do roli, jaką ma on pełnić w
aplikacji w tym celu kliknij go, a następnie w inspektorze obiektów przypisz właściwości
Caption napis Wczytaj.
Kolejnym komponentem naszej aplikacji będzie pasek statusu, na którym wyświetlana będzie
nazwa wczytanego ostatnio pliku. Przejdz do strony Win32 w palecie komponentów i kliknij
komponent StatusBar (rys. 1.7); gdy klikniesz formularz, pasek stanu automatycznie usadowi
się przy jego dolnej krawędzi.
StatusBar
Rysunek 1.7. Komponent StatusBar
Używając inspektora obiektów ustaw właściwość SimplePanel paska StatusBar1 na true.
Należy teraz sprawić, by przycisk opatrzony tytułem Wczytaj istotnie powodował wczytanie
pliku bitmapy; jak zapewne pamiętasz, jest to kwestia właściwego obsłużenia generowanego przez
ów przycisk zdarzenia OnClick. Kliknij go dwukrotnie i uzupełnij wyświetlony szkielet funkcji
zdarzeniowej do następującej postaci:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if (OpenDialog1->Execute())
Image1->Picture->LoadFromFile(OpenDialog1->FileName);
StatusBar1->SimpleText = OpenDialog1->FileName;
}
Wyświetlone okno edytora kodu przysłoniło formularz, ale to żaden kłopot za pomocą klawisza
F12 można łatwo przełączać się pomiędzy formularzem i odpowiadającym mu modułem kodu
zródłowego; można w tym celu użyć również stosownego przycisku na pasku narzędziowym (rys.
1.8).
Rysunek 1.8. Przycisk przełączający pomiędzy edytorem kodu a formularzem
Pozostaje jeszcze obsłużyć przycisk Button2. Używając inspektora obiektów, nadaj mu tytuł
Zamknij, następnie klikając go dwa razy uzupełnij jego funkcję zdarzeniową w następujący
sposób:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Close();
}
Uruchom teraz aplikację, naciskając klawisz F9. Kliknięcie przycisku Wczytaj spowoduje
otwarcie okna dialogowego, za pomocą którego wybrać można plik, który wyświetlony zostanie
za pomocą komponentu Image. Na użytek naszej aplikacji wykorzystamy bitmapę
Instalator.bmp wyświetlaną podczas instalacji Windows 98 (rys. 1.9).
Rysunek 1.9. Wyświetlenie grafiki załadowanej do komponentu Image
Przyjrzyjmy się teraz nieco dokładniej temu, co tak naprawdę dzieje się w działającej aplikacji. Jej
centralnym punktem jest prostokąt, w którym wyświetlana jest zawartość wczytanej bitmapy.
Wyświetlanie pliku *.BMP nie jest bynajmniej sprawą trywialną: poza poszczególnymi pikselami
może ona (chociaż nie musi) zawierać również informacje o palecie, przy użyciu której będzie
wyświetlana, ponadto plik noszący rozszerzenie *.BMP niekoniecznie musi mieć format
charakterystyczny dla bitmapy, co oczywiście należy zasygnalizować jako błąd. Tradycyjne
zaprogramowanie tych czynności wymagałoby kilkustronicowego kodu, podczas gdy C++Builder
załatwia całą sprawę za pomocą jednego gotowego komponentu.
Sam wybór pliku do wyświetlenia również jest czynnością na swój sposób skomplikowaną
mamy wszak do czynienia z przeszukiwaniem hierarchicznej struktury dysków i folderów, nie są
ponadto uwzględniane pliki inne niż te noszące rozszerzenie .BMP (decyduje o tym właściwość
Filter komponentu OpenDialog). Wybór konkretnego pliku jest w środowisku Windows
czynnością na tyle powszechną, iż została ona zautomatyzowana w postaci jednego z tzw.
powszechnych narzędzi dialogowych; komponent OpenDialog stanowi obudowaną postać tegoż
narzędzia, przystosowaną do platformy C++Buildera.
Właściwe reakcje aplikacji na klikanie przycisków Wczytaj i Zamknij zapewnione są dzięki
odpowiedniemu oprogramowaniu funkcji zdarzeniowych. Zdarzenia C++Buildera stanowiÄ…
obudowę mechanizmów bardziej prymitywnych komunikatów Windows i są od nich
nieporównanie bardziej wygodne w użyciu; zamiast (znowu) kilkustronicowego kodu mamy
jedynie dwie krótkie funkcje obsługi zdarzeń.
Reasumując gdyby zaprogramować omawianą aplikację w sposób tradycyjny, skończyłoby się
na dwudziestokilkustronicowym kodzie; wobec rozmiaru kodu, który faktycznie musieliśmy
napisać, zalety C++Buildera stają się wyraznie widoczne.
Stwórzmy więc jeszcze jedną aplikację. Wybierz z menu File opcję New Application;
C++Builder zapyta Cię, czy chcesz zachować istniejącą aplikację (Save changes to
project& ?) nie musisz tego robić, gdyż znajduje się ona na dołączonej do książki płycie
CD-ROM; kliknij więc przycisk No. Zostanie zainicjowany nowy projekt i wyświetlony czysty
formularz.
Rozpocznij od zapisania plików nowego projektu. W tym celu wybierz opcję Save Project
As z menu File; C++Builder wyświetli kolejno dwa okna dialogowe związane z dwoma plikami
projektu.
Pierwsze ze wspomnianych okien (rys. 1.10) dotyczyć będzie modułu głównego, noszącego
rozszerzenie cpp, związanego z formularzem głównym. Jako że generalnie łatwiej panować nad
projektami, jeżeli przechowywane są one w oddzielnych katalogach, rozpocznij od utworzenia
nowego podkatalogu dla projektu, klikajÄ…c stosowny przycisk okna; C++Builder utworzy katalog
o nazwie Nowy folder zmień tę nazwę na Composers i przejdz do utworzonego katalogu
klikając go dwukrotnie. Następnie zmień nazwę modułu (w wierszu Nazwa pliku:) na
Mainform i kliknij przycisk Zapisz.
Nowy
podkatalog
Nazwa
modułu
Rysunek 1.10. Zapisywanie modułu głównego
Zapisywanie pliku projektu (plik ten nosi rozszerzenie .bpr) odbywa się podobnie z tą różnicą,
iż domyślnym katalogiem w oknie dialogowym będzie katalog przed chwilą utworzony; zmień
proponowaną nazwę tego pliku (Project2) na bardziej sugestywną, na przykład
ComposersProj. Tak naprawdę zapisywane są tutaj dwa pliki oprócz pliku .bpr tworzony
jest również plik .cpp z tą samą nazwą, jednak nie wynika to w żaden sposób z treści dialogu.
Umieść teraz na formularzu dwa komponenty ListBox znajdują się one na stronie Standard
palety komponentów. C++Builder nada im automatycznie nazwy ListBox1 i ListBox2.
Konkretna ich lokalizacja na formularzu nie jest szczególnie istotna, wskazane jest jednak, by
wyrównane były w poziomie.
Pod komponentami ListBox umieść następnie komponent Edit, również ze strony Standard.
C++Builder nada mu automatycznie nazwę Edit1. Przejdz do inspektora obiektów i wyczyść
pole związane z jego właściwością Text.
Bezpośrednio przed komponentem Edit1 umieść komponent Label; za pomocą inspektora
obiektów zmień jego tytuł (właściwość Caption) na Nowy: .
Dwa ostatnie komponenty projektu to przyciski (komponenty Button C++Builder nada im
nazwy Button1 i Button2); za pomocą inspektora obiektów nadaj im tytuły (właściwość
Caption) Dodaj i Usuń .
Ze względów estetycznych możesz zmniejszyć formularz projektu, chwytając kursorem myszy i
przesuwając prawą jego krawędz, następnie robiąc to samo z krawędzią dolną. Wygląd formularza
projektu z kompletem opisanych przed chwilą komponentów pokazuje rysunek 1.11.
Rysunek 1.11. Kompletny formularz projektu ComposersProj
Kolej teraz na oprogramowanie zdarzeń związanych z poszczególnymi komponentami. Pierwsze
ze zdarzeń dotyczyć będzie samego formularza a dokładniej tego, co automatycznie dzieje się
przy jego tworzeniu. Zdarzenie to nosi nazwÄ™ OnCreate i w naszym projekcie wykorzystane
zostanie do załadowania lewej listy (komponent ListBox1) domyślną zawartością. Kliknij więc
gdziekolwiek w wolnym obszarze formularza (nie żaden z komponentów!), przejdz do inspektora
obiektów (który w górnym okienku powinien wskazywać Form1 jako wybrany komponent) i na
zakładce Events zlokalizuj pozycję odpowiadającą zdarzeniu OnCreate i kliknij ją
dwukrotnie; C++Builder wyświetli wówczas następujący szkielet funkcji zdarzeniowej:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
}
który należy wypełnić następującym kodem:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
ListBox1->Items->Add("Cesar Franck");
ListBox1->Items->Add("Charles Marie Widor");
ListBox1->Items->Add("Louis Vierne");
ListBox1->Items->Add("Maurice Durufle");
ListBox1->Items->Add("Jehan Alain");
}
Każdy z wierszy powoduje dodanie jednej pozycji do listy ListBox1; nazwiska kompozytorów
są tu oczywiście przykładowe i mogą zostać zmienione bez szkody dla projektu.
Zajmijmy się teraz przyciskami Dodaj i Usuń. Kliknięcie pierwszego z nich spowoduje dodanie
do prawej listy (ListBox2) podświetlonej pozycji z lewej listy (ListBox1). Indeks
podświetlonej pozycji listy reprezentowany jest przez jej właściwość ItemIndex, wszystkie zaś
pozycje zgrupowane są w tablicy będącej pod właściwością Strings właściwości Items; ta
ostatnia odpowiedzialna jest za całokształt zarządzania pozycjami listy na przykład jej metoda
Add powoduje dodanie nowej pozycji do listy. Zgodnie z tym funkcja zdarzeniowa zwiÄ…zana z
lewym przyciskiem (jej szkielet wyświetlony zostanie po dwukrotnym kliknięciu tego przycisku)
wyglądać powinna następująco:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String GetListItem = ListBox1->Items->Strings[ListBox1->ItemIndex];
ListBox2->Items->Add(GetListItem);
}
Usuwanie pozycji z prawej listy (ListBox2) jest nieco mniej skomplikowane funkcja
zdarzeniowa prawego przycisku prezentuje się następująco:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
ListBox2->Items->Delete(ListBox2->ItemIndex);
}
Wpisanie czegokolwiek do okienka komponentu Edit1 i naciśnięcie klawisza Enter spowoduje
powielenie zawartości tego okienka w obydwu listach. Aktualna zawartość komponentu Edit
ukrywa się pod jego właściwością Text, zaś każdorazowe naciśnięcie klawisza (w sytuacji, gdy
komponent ten jest aktywnym komponentem formularza) generuje zdarzenie OnKeyPress.
Jednym z parametrów funkcji obsługującej to zdarzenie jest kod naciśniętego klawisza, nietrudno
więc wykorzystać tę funkcję do skopiowania zawartości reprezentowanej przez właściwość Text
do obydwu list:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
if (Key==13)
{
ListBox2->Items->Add(Edit1->Text);
ListBox1->Items->Add(Edit1->Text);
}
}
Wartość 13 jest kodem klawisza Enter; bardziej elegancko byłoby użyć w tej roli stałej
symbolicznej VK_ENTER. Aby uzyskać szkielet powyższej funkcji, należy najpierw kliknąć
jednokrotnie komponent Edit1 (by uczynić go komponentem aktywnym), a następnie kliknąć
dwukrotnie pozycjÄ™ odpowiadajÄ…cÄ… zdarzeniu OnKeyPress na stronie Events inspektora
obiektów.
Po wykonaniu opisanych czynności należy zapisać zmienioną zawartość projektu za pomocą opcji
Save All menu File, dostępnej również przez klawisz skrótu Shift+Ctrl+S. Tak
naprawdę zapisywanie projektu w trakcie jego tworzenia powinno odbywać się jak najczęściej,
bowiem w przypadku ewentualnej awarii (np. wyłączenia zasilania) tracimy tylko tę część pracy,
którą wykonaliśmy po ostatnim zapisie.
Projekt gotowy jest do uruchomienia na przykład przez naciśnięcie klawisza F9. Ukaże się
wówczas okno główne, w którym lewa lista wypełniona będzie zawartością początkową. Klikając
w którąkolwiek z jej pozycji, spowodujemy jej podświetlenie, zaś kliknięcie w przycisk Dodaj
spowoduje skopiowanie podświetlonej pozycji do prawej listy. Do usuwania podświetlonych
pozycji prawej listy służy przycisk Usuń. Do wprowadzania nowych pozycji służy komponent
Edit1 jeżeli jest on komponentem wybranym, naciśnięcie klawisza Enter spowoduje
skopiowanie jego bieżącej zawartości do obydwu list.
Opisaną aplikację zbudować można niemalże w ciągu kilku minut jeżeli porównać to z czasem
niezbędnym do stworzenia podobnej aplikacji w środowisku Visual C++ lub Microsoft Foundation
Classes (MFC), ponownie uwidaczniają się zalety C++Buildera jako narzędzia kategorii RAD.
Kilka pytań
Oto kilka pytań związanych z C++Builderem (i ogólnie z narzędziami typu RAD) zadawanych
przez początkujących programistów:
" W jaki sposób mogę podejrzeć kod pliku głównego projektu i modułów związanych z
poszczególnymi formularzami?
Służy do tego menedżer projektu, którego okno wyświetlone zostaje w wyniku wybrania opcji
View|Project Manager lub naciśnięcia klawiszy Ctrl+Alt+F11. Dzięki niemu
dostępny jest również (po skompilowaniu projektu) kod zródłowy modułów bibliotecznych.
Główny plik zródłowy projektu (ten z nazwą projektu i rozszerzeniem .cpp) można również
obejrzeć za pomocą opcji Project|View Source.
" W jaki sposób mogę zmieniać właściwości komponentów?
Temu celowi służy inspektor obiektów, dostępny poprzez opcję View|Object
Inspector lub przez klawisz skrótu F11. Niektóre właściwości danego komponentu mogą
być jednak niedostępne w czasie projektowania i niewidoczne w oknie inspektora obiektów
właściwości te mogą być odczytywane i modyfikowane jedynie bezpośrednio w kodzie
programu.
" Co mam zrobić, jeżeli operowanie myszą nie pozawala mi na osiągnięcie żądanej precyzji
ułożenia komponentów na formularzu?
Przesuwać wybrany komponent można za pomocą klawiszy strzałek, trzymając jednocześnie
wciśnięty klawisz Ctrl; umożliwia to pozycjonowanie komponentów z dokładnością do
pojedynczych pikseli.
" Po uruchomieniu program zawiesił się, a ekran upstrzony został jakimiś dziwnymi okienkami.
W jaki sposób mogę przywrócić normalną sytuację?
C++Builder umożliwia zresetowanie działającego programu w dowolnej chwili. Należy w tym
celu nacisnąć kombinację Ctrl+F2 lub wybrać z menu głównego opcję Run|Program
Reset. Program zostanie wówczas zatrzymany i sterowanie powróci do IDE.
" W jaki sposób mogę opatrzyć okno programu swoją własną ikoną?
Należy otworzyć okno opcji projektu za pomocą opcji Project|Options menu
głównego lub kombinacji klawiszy Shift+Ctrl+F11 przejść na kartę Application,
nacisnąć przycisk Load Icon i za pomocą wyświetlonego okna dialogowego wybrać
stosowny plik ikony. Jeżeli plik ten jeszcze nie istnieje, można go stworzyć, używając edytora
obrazów, uruchamianego za pomocą opcji Tools|Image Editor. Po przypisaniu ikony
konieczna jest kompletna rekompilacja projektu wykonuje siÄ™ jÄ…, wybierajÄ…c opcjÄ™
Project|Build All Projects z menu głównego IDE.
" W jaki sposób mogę zmienić standardowy tytuł Form1 wyświetlany na pasku tytułowym
okna mojego programu?
Tytuł ten ukrywa się pod właściwością Caption formularza projektu, można więc go zmienić
za pomocą inspektora obiektów.
" Czy istnieje szybszy dostęp do elementów IDE niż nawigowanie wśród opcji menu
głównego?
Służą temu przyciski paska narzędziowego (speedbar) umieszczonego standardowo nad
inspektorem obiektów. Jeżeli nie jesteś pewien znaczenia danego przycisku, zatrzymaj na nim
kursor myszy przez kilka sekund, co spowoduje wyświetlenie treści równoważnej opcji menu
w formie podpowiedzi.
" W jaki sposób mogę zabezpieczyć się przez przypadkowym przesunięciem komponentu na
formularzu w trakcie projektowania aplikacji?
Do zablokowania pozycji i rozmiaru komponentów służy opcja Edit|Lock Controls. Po
jej wybraniu komponenty formularza stają się niewrażliwe na klawisze strzałek i ruchy kursora
myszy. W dalszym ciągu możliwe jest jednak modyfikowanie położenia i rozmiaru
komponentów za pomocą inspektora obiektów. Ponowne wybranie opcji Edit|Lock
Controls odblokowuje komponenty.
Co nowego w wersji 5. C++Buildera?
Jak już wcześniej wspominaliśmy, droga rozwojowa C++Buildera spleciona jest w pewnym
stopniu z Delphi, tak więc również w przypadku najnowszej jego wersji większość (choć nie
wszystkie!) nowości pojawiła się już w ostatniej wersji Delphi Delphi 5. Nowości te związane są
głównie z programowaniem internetowym, aplikacjami rozproszonymi, projektowaniem
zespołowym i ogólnie pojętą produktywnością programisty. Większość z nich omówiona zostanie
szczegółowo w dalszej części książki.
C++Builder 5 dostępny jest w trzech wersjach: Standard (Std), Professional (Pro) i Enterprise
(Ent). Wersja Standard jest oczywiście wersją najuboższą, mimo to jest jednak funkcjonalnym
narzędziem do programowania w Windows, zawierającym ponad 85 komponentów, uznany
powszechnie kompilator i debugger oraz wiele innych użytecznych możliwości. Wersja
Professional posiada ponad 150 komponentów oraz dodatkowe narzędzia bazodanowe, śledzenie
wieloprocesowe i specjalizowane narzÄ™dzie CodeGuardÛö. Najbogatsza z wersji Enterprise
oferuje ponad 200 komponentów związanych m.in. z technologią CORBA, MS SQL Serwerem 7,
Oracle8i, technologią MIDAS, programowaniem internetowym itp., a także środki ułatwiające
tworzenie aplikacji w wielu wersjach językowych oraz menedżer kontroli kodu zródłowego w
warunkach pracy zespołowej (TeamSource).
Z wersji 5. C++Buildera usunięto natomiast PVCS Version Control firmy Merant (dawniej
Intersolv).
Kompletny wykaz nowości w każdej z wersji C++Buildera 5 (Standard, Professional, Enterprise)
dostępny jest pod adresem http://www.borland.com/bcppbuilder w punkcie
Feature List , większość z nich opisana jest również w systemie pomocy pod hasłem What s
New .
Większość z nowości opisywanych w tym rozdziale dotyczy wersji Professional i Enterprise z
wyjątkiem miejsc, gdzie wyraznie zaznaczono konkretną wersję za pomocą skrótów Std , Pro i
Ent ; skrót All oznacza, iż opisywany mechanizm odnosi się do wszystkich wersji. W
następnych rozdziałach książki zrezygnowaliśmy jednak z takiego rozróżniania; informacje o
stosowaniu konkretnych mechanizmów w poszczególnych wersjach dostępne są w miejscach
przed chwilÄ… wymienionych.
Programowanie internetowe
C++Builder dawno już zdobył sobie uznanie programistów jako poręczne narzędzie do tworzenia
aplikacji internetowych. Możliwości C++Buildera w tym względzie zostały w wersji 5.
wzbogacone m.in. o: kreator Active Server Page (ASP) Application Wizard, komponenty
Internet Express (Ent), nowy komponent przeglÄ…darki WWW i rozszerzenia komponentu
WebBroker.
Komponenty Internet Express (Ent) umożliwiają tworzenie aplikacji cienkiego klienta
sieci WWW, udostępniającego dane z serwerów MIDAS-a i zaplecza bazodanowego (back-end
databases) na podstawie języka XML i HTML 4. Aplikacje te są znacznie prostsze i mniejsze niż
tradycyjne implementacje grubego klienta; nie dokonują bezpośredniego dostępu do bazy
danych, nie wymagają więc instalowania BDE (Borland Database Engine) na komputerach
klientów.
Komponent WebBroker, obecny dotąd jedynie w wersji Enterprise, teraz dostępny jest również
w wersji Professional; został on przystosowany do obsługi HTML 4. Najważniejszą nowością w
zakresie programowania internetowego jest natomiast nowy komponent przeglÄ…darki WWW,
umożliwiający integrację tworzonej aplikacji z językiem HTML. To, wydawałoby się drobne,
rozszerzenie ma jednak niebagatelne skutki praktyczne, między innymi:
" możliwość łatwego tworzenia dedykowanych przeglądarek WWW, przystosowanych do
specyficznych warunków, na przykład do przeglądania jedynie zasobów firmowego intranetu;
" możliwość tworzenia interfejsu użytkownika aplikacji w postaci HTML. Stwarza to znaczne
korzyści dialogowa strona aplikacji może być powierzona nieprogramistom, zaś firmowi
specjaliści od tworzenia stron WWW mogą być zaangażowani również w tworzenie aplikacji.
Możliwe jest także łatwe zróżnicowanie interfejsu granicznego poszczególnych
użytkowników, stosownie do ich kwalifikacji czy też posiadanych uprawnień, ponadto
dystrybucja nowej wersji interfejsu użytkownika sprowadza się po prostu do ściągnięcia jej z
Internetu;
" integracja języka HTML z systemem pomocy aplikacji, co czyni tworzenie plików pomocy
równie łatwym, jak tworzenie stron WWW.
Możliwości te zostały wykorzystane w kilku znanych produktach, między innymi MS Office 2000
i MS Encarta, ponadto serwisy America Online (AOL) i CompuServe tworzÄ… swoje
zaawansowane aplikacje na podstawie kontrolek przeglÄ…darki WWW.
Aplikacje rozproszone
Implementacja specyfikacji CORBA (Ent) rozszerzona została o obsługę Visibrokera ORB 4.00
oraz elementów specyfikacji charakterystycznych dla wersji CORBA 2.3. Z innych tego typu
rozszerzeń wymienić należy: Portable Object Adapter i Object By Value oraz
usprawnienie edytora biblioteki typów (Visual TypeLibrary Editor), rozszerzenia repozytorium
interfejsów (Interface Repository), a także nowe kreatory CORBA.
MIDAS (Ent) rozszerzony został o: obsługę języka XML, bezstanowy komponent DataBroker,
nowe komponenty Web Connection, pulę połączeń (server object pooling) i opcje
dostarczyciela danych (provider options).
Projektowanie zespołowe
Narzędzie do zespołowego projektowania aplikacji o nazwie TeamSource, dostarczane wraz z
wersją Enterprise i dostępne za dodatkową opłatą dla wersji Professional, stanowi interfejs
czołowy (front-end) menedżera kontroli wersji, umożliwiającego równoległą pracę wielu
programistów nad pojedynczym projektem. Każdy programista pracuje na odrębnej lokalnej kopii
kodu zródłowego, zaś zadaniem wspomnianego menedżera jest synchronizacja każdej kopii z
głównymi zródłami; narzędzia do wizualnego porównywania modułów ułatwiają rozwiązywanie
ewentualnych konfliktów powstających przy tej okazji. TeamSource śledzi historię zmian kodu,
umożliwia także zaznaczenie konkretnej postaci zródeł jako jedną z wersji błyskawicznie dostępną
na ewentualne pózniejsze żądanie.
Mechanizm zaplecza (back-end) mechanizmu zarzÄ…dzania wersjÄ… realizowany jest przez osobnÄ…
część oprogramowania. C++Builder 5 (Ent) wykorzystuje w tym celu bibliotekę Borland Zlib oraz
udostępnia interfejs dla sprzedawanego teraz oddzielnie PVCS firmy Merant. Możliwe jest
również konstruowanie własnych wtyczek (plug-in) dla obsługi przez TeamSource innych
programów zaplecza.
Lokalizacja aplikacji
Nowością C++Buildera 5 (Ent) są narzędzia umożliwiające tłumaczenie aplikacji pomiędzy
różnymi platformami językowymi oraz równoległe tworzenie kilku wersji językowych:
Translation Suite, Translation Repository, RC Translator i DFM Translator; narzędzia te dostępne
są również za dodatkową opłatą dla wersji Professional.
Również kreator Resource DLL Wizard został rozszerzony o możliwości łatwej zmiany wersji
językowej aplikacji.
Åšledzenie
Bodaj jednÄ… z najbardziej spektakularnych nowoÅ›ci C++Buildera 5 jest narzÄ™dzie CodeGuardÛö.
Oferuje ono rozbudowane narzędzia śledzenia, umożliwiające łatwe wykrywanie błędów i ich
przyczyn, między innymi wycieków pamięci oraz gubienia zasobów w postaci np. uchwytów
plikowych. Możliwe jest również (All) zaprogramowanie różnorodnych akcji związanych z
punktami przerwań (breakpoints) i ich grupowanie, jak również czytelny podgląd instrukcji
zmiennoprzecinkowych i MMX.
Programowanie bazodanowe
Najważniejszymi nowościami C++Buildera 5 w zakresie tworzenia aplikacji bazodanowych są:
DataModule Designer, InterBase Express i ADO Express.
Projektant modułów bazodanowych Datamodule Designer po raz pierwszy pojawił się w
Delphi 5 jest narzędziem wizualnym, uwidaczniającym w czytelnej postaci relacje (np. master-
details) i zależności zachodzące pomiędzy komponentami modułu danych (Datamodule).
InterBase Express umożliwia tworzenie zaawansowanych aplikacji bazodanowych bez
użycia BDE. Ulepszona wersja SQL Monitora ułatwia kontrolowanie szczegółów dostępu do
danych.
ADO Express to grupa komponentów stanowiących otoczkę technologii MS ActiveX Data
Object (ADO) i OLEDB. Komponenty te pozwalają na tworzenie aplikacji obsługujących
relacyjne i nierelacyjne bazy danych, arkusze kalkulacyjne, różnorodne systemy plików i pocztę
elektronicznÄ…. Aplikacje stworzone na bazie ADO Express nie korzystajÄ… z BDE.
Dopełnieniem bazodanowych możliwości C++Buildera 5 jest najnowsza wersja Interbase (5.6)
oraz obsługa MS SQL Servera 7 i Oracle8i.
Produktywność programisty
C++Builder 5 nie pozostaje w tyle również pod względem środków zwiększających
produktywność programisty. Wielowątkowa kompilacja w tle (All) umożliwia kontynuowanie
pracy nad projektem w czasie, gdy kompilator wykonuje swoją pracę. Możliwe jest również
zaaranżowanie dwóch różnych postaci IDE (Customizable Desktop Settings) osobno dla śledzenia
programu, osobno dla normalnego uruchomienia przełączanie pomiędzy nimi odbywa się
automatycznie.
Znacznym ułatwieniem w procesie stopniowego budowania projektu są komentarze o specjalnej
postaci (ang. To-Do), rozpoczynające się znakami //TODO: i przypominające użytkownikowi o
rzeczach, które pozostały jeszcze do zrobienia w kontekście określonego miejsca w kodzie
projektu. Do zarządzania nimi służy specjalny menedżer dostępny poprzez opcję View|To-Do
List.
Dodano również kilka kreatorów, między innymi: Windows 2000 Client Logo
Application Wizard (All), Console Application Wizard (All), Control Panel
Applet Wizard oraz dwa proste kreatory związane z językiem C i C++.
Rozszerzono także obsługę Visual C++, m.in. w zakresie Microsoft Foundation Classes (MFC)
6.0 i Active Template Library (ATL) 3.0. Całości dopełniają ułatwienia w rodzaju podziału na
właściwości na kategorie (All) i wizualizacja właściwości graficznych (All) w inspektorze
obiektów, programowalne mapowanie klawiszy w edytorze kodu (All) i import serwerów
automatyzacji jako komponentów.
Zgodność i unowocześnianie aplikacji
C++Builder 5 pojawił się oficjalnie na rynku 22 marca 2000 roku. W chwili gdy piszemy te słowa,
znanych jest kilka problemów związanych ze zgodnością istniejących projektów z poprzednich
wersji oraz narzędzi niezależnych producentów; wykryto również kilka błędów C++Buildera 5 w
tym względzie oficjalny ich wykaz znajduje się pod adresem
http://www.borland.com/bcppbuilder/ w punktach Updates and Patches i
Investigate Bugs . Stosowna łata nie została dotąd opublikowana.
Wskazówki dotyczące radzenia sobie ze znanymi błędami znajdują się również w pliku
README.TXT w głównym folderze krążka instalacyjnego C++Buildera.
Unowocześnianie wersji C++Buildera
C++Builder 5 może współistnieć z poprzednimi wersjami nawet na tym samym dysku, lecz pliki
współużytkowane przez wszystkie wersje (jak np. BDE) muszą zostać unowocześnione do wersji
najnowszej. To samo odnosi się do współistnienia C++Buildera 5 i Delphi.
Jeżeli nie zamierzasz używać poprzednich wersji C++Buildera, odinstaluj je przed instalacją
wersji 5.; stosowne wskazówki w tym względzie znajdują się w plikach INSTALL.TXT i
README.TXT w głównym folderze krążka instalacyjnego.
Obsługa istniejących projektów
Gdy wczytujesz do C++Buildera 5 projekt stworzony w którejś z poprzednich wersji, projekt ten
jest automatycznie uaktualniany do najnowszej wersji. Plik główny projektu (.bpr) uaktualniany
jest do formatu XML, zaÅ› zawarte w nim informacje o wymaganych dotÄ…d bibliotekach
systemowych zastępowane są informacjami o bibliotekach wymaganych w wersji 5. Czynione są
również pewne drobne modyfikacje w głównym pliku .cpp projektu.
Zdarza się jednak, iż projekt zawiera fragmenty kodu, które muszą być obsługiwane przez
konkretną wersję C++Buildera i nie będą pracować z nowszą jego wersją; dotyczy to szczególnie
komponentów pochodzących od niezależnych dostawców. Takie wersjonowanie kodu
wykonywane jest tradycyjnie przy użyciu klauzul #ifdef VERXXX; problem w tym, iż projekt
przeznaczony dla wersji C++Buildera 4 (VER125) nie zna jeszcze symbolu VER130
(zdefiniowanego w wersji 5.), tak więc sekcja uzależniona od klauzuli #ifdef VER125 musi
zostać podzielona na dwie sekcje zależne od symboli (odpowiednio) VER125 i VER130, o ile
oczywiście ma być dokonane rozróżnienie pomiędzy wersjami 4. i 5. (oprócz istniejącego już
odróżnienia wersji 4. od wersji wcześniejszych).
Jeżeli nie posiadasz kodu zródłowego dla jakiegoś komponentu lub pakietu, uzyskanie od
producenta nowszej jego wersji (lub, być może, kodu zródłowego) jest warunkiem koniecznym
uaktualnienia projektu.
Tworzenie projektów zgodnych z poprzednimi
wersjami C++Buildera
Jest oczywiste, iż projekt mający bezproblemowo współpracować z poprzednimi wersjami
C++Buildera, nie może odwoływać się do mechanizmów w tych wersjach nieobecnych, w
szczególności tych, które pojawiły się dopiero w wersji 5.
Dotyczy to głównie formatu, w jakim przechowywane są pliki formularzy (*.dfm); w wersji 5.
jest to (domyślnie) format tekstowy, w wersjach poprzednich binarny. Aby w wersji 5. wymusić
zapisywanie danego formularza w formacie binarnym, należy odznaczyć opcję Text DFM w jego
menu kontekstowym (uruchamianym kliknięciem prawego przycisku myszy w jego wolnym
obszarze). Aby spowodować binarny zapis wszystkich tworzonych w przyszłości formularzy,
należy odznaczyć opcję New Forms as Text na stronie Preferences okna opcji
środowiska (dostępnego za pośrednictwem opcji Tools|Environment Options).
Plik projektu (.bpr) w wersji 5. zapisywany jest w formacie XML; w wersjach poprzednich był
to charakterystyczny format makefile. Aby zapisać bieżący projekt w tym formacie, należy wybrać
opcjÄ™ Export Makefile z menu Project spowoduje to utworzenie pliku o nazwie
tożsamej z nazwą projektu i rozszerzeniu .mak. Należy następnie zmienić rozszerzenie tego pliku
na .bpr oraz dokonać kilku niezbędnych zmian w jego zawartości; zmiany te polegają na
wpisaniu odpowiedniej wersji C++Buildera (w dyrektywie VERSION) i plików biblioteki VCL (w
dyrektywach LIBRARIES, SPARELIBS, PACKAGES), a także modyfikacji opcji w dyrektywie
CFLAG1.
Jakkolwiek dyrektywy To Do są nowością wersji 5., nie kolidują z wersjami poprzednimi, gdzie
traktowane są jak zwykłe komentarze.
Format pliku symbolicznego *.tds różni się pomiędzy wersjami C++Buildera; wczytanie
projektu utworzonego w innej wersji może spowodować wyświetlenie komunikatu Error
reading symbol file. Nie stanowi to żadnego problemu, gdyż w wyniku ponownej
kompilacji projektu plik ten zostanie utworzony na nowo, już w poprawnym formacie.
Inne problemy ze zgodnością
W wersji 5. C++Buildera zostały zmienione definicje niektórych klas, ich metod i właściwości, co
oczywiście stanowi pewien problem przy unowocześnianiu projektów. Oto najważniejsze ze
wspomnianych zmian kompletny ich wykaz znajduje siÄ™ w systemie pomocy:
" TPoint nie jest już strukturą (klasą bez konstruktora); inicjowanie wartości tego typu
posiada obecnie formę rzutowania dwóch wartości całkowitych na typ TPoint
TPoint station = { TPoint(1,1) };
w miejsce dotychczasowego inicjowania struktury
TPoint station = { {1,1} };
które obecnie spowoduje błąd kompilacji.
" Zmieniła się lista parametrów konstruktora klasy TPropertyEditor jego deklaracja
wyglÄ…da teraz tak:
TPropertyEditor (const di_IFormDesigner ADesigner, int AropCount)
" Pojawiła się nowa klasa o nazwie TComponentList, służąca do przechowywania listy
komponentów. Jest ona zdefiniowana w pliku cntnrs.hpp, jej szczegóły opisane są w
systemie pomocy.
" Metoda sprintf() klasy AnsiString nadpisuje obecnie dotychczasową zawartość
łańcucha, zamiast dołączać nowy łańcuch na jej końcu; dołączanie takie realizowane jest
teraz przez metodÄ™ cat_sprintf.
" Komponent THTML (firmy Netmasters) został zastąpiony przez komponent
TCppWebBrowser. Związane z tym wskazówki odnośnie unowocześniania projektu
zawarte sÄ… w systemie pomocy.
" Zmieniły się niektóre elementy MIDAS-a; szczegóły opisane są w systemie pomocy.
Migracja ze środowiska Delphi
Podrozdział ten stanowi krótkie porównanie równoważnych konstrukcji Delphi i C++Buildera.
Jest on przeznaczony dla programistów Delphi, którzy rozpoczynają pracę z C++Builderem, nie
powinien być jednak traktowany jako kompendium programowania w C++. Przed przystąpieniem
do szczegółów należy przypomnieć niezwykle istotny fakt w przeciwieństwie do Delphi (i
Pascala w ogóle) C++Builder wrażliwy jest na wielkość liter; może to być początkowo
uciążliwe dla programistów przyzwyczajonych do obojętności Delphi w tym zakresie.
Komentarze
Komentarze C++Buildera posiadają nieco inną składnię niż komentarze Delphi; różnice te
prezentujemy w tabeli 1.1.
Tabela 1.1. Porównanie komentarzy Delphi i C++Buildera
Delphi C++Builder
{ Komentarz w Delphi } /* Komentarz w C++Builderze */
(* Inny komentarz
w Delphi *)
// komentarz jednolinijkowy // komentarz jednolinijkowy
Zmienne
Podobnie jak w Delphi, zmienne w C++Builderze muszą być zadeklarowane przed użyciem.
Tabela 1.2 zawiera porównanie typów zmiennych dostępnych w obydwu środowiskach, wraz ze
wskazaniem ich rozmiarów w bajtach.
Tabela 1.2. Typy zmiennych Delphi i C++Buildera
Typ Rozmiar (w Delphi C++Builder
bajtach)
ShortInt char
Liczba całkowita ze 1
znakiem
SmallInt short,
2
short int
Integer, int, long
4
Longint
Int64 __int64
8
Byte BYTE,
Liczba całkowita bez 1
unsigned short
znaku
Word unsigned short
2
Cardinal, unsigned long
4
LongWord
Single float
Liczba 4
zmiennoprzecinkowa
Double double
8
Extended long double
10
Variant, OleVariant,
Variant 16
OleVariant, VARIANT
TVarData
Char char
Znak 1
WideChar WCHAR
2
AnsiString AnsiString
Aańcuch dynamiczny
WideString WideString
Aańcuch dynamiczny
znaków dwubajtowych
PChar char *
Aańcuch z zerowym
ogranicznikiem
PWideChar LPCWSTR
Aańcuch znaków
dwubajtowych z
zerowym
ogranicznikiem
Pointer void *
Wskaznik amorficzny 4
Boolean bool
Wartość logiczna 1
(boolowska)
Więcej informacji na temat typów zmiennych C++Buildera znajdziesz w systemie pomocy.
Stałe
W C++Builderze stałe mogą być deklarowane na dwa sposoby. Pierwszy, tradycyjny,
wykorzystuje dyrektywÄ™ preprocesora #define:
#define myconstant 100
Nowszy i bezpieczniejszy sposób polega na użyciu słowa kluczowego const:
const int myconstant = 100;
Operatory
Punkt ten zawiera opis znaczenia poszczególnych operatorów C++Buildera i wskazówki odnośnie
przekształcania równoważnych operatorów Delphi. Na początek porównanie operatorów
występujących w obydwu środowiskach.
Tabela 1.3. Porównanie operatorów Delphi i C++Buildera
Typ operatora Operator Delphi C++Builder
:= =
przypisanie przypisz
+=
dodaj i przypisz
=
odejmij i przypisz
*=
pomnóż i przypisz
/=
podziel i przypisz
%=
oblicz resztÄ™ z
dzielenia i przypisz
&=
oblicz koniunkcjÄ™
bitowÄ… i przypisz
|=
oblicz alternatywÄ™
bitowÄ… i przypisz
^=
oblicz bitową różnicę
symetrycznÄ… i przypisz
<<=
przesuń bity w lewo i
przypisz
>>=
przesuń bity w prawo i
przypisz
= ==
porównanie równy
<> !=
nierówny
> >
większy
>= >=
większy lub równy
< <
mniejszy
<= <=
mniejszy lub równy
+ +
arytmetyczny dodaj
odejmij
* *
pomnóż
/ /
podziel
zmiennoprzecinkowo
div /
podziel
stałoprzecinkowo
mod %
oblicz resztÄ™ z
dzielenia
and &&
logiczny koniunkcja
or ||
alternatywa
not !
zaprzeczenie
And &
bitowy koniunkcja
Or |
alternatywa
Xor ^
różnica symetryczna
Not ~
negacja
Shl <<
przesunięcie w lewo
Shr >>
przesunięcie w prawo
wskaznikowy wskazanie ^typ typ *
adresowanie wskaznik^ *wskaznik
adres zmiennej @zmienna &zmienna
var
referencja typ&
class class
klasowy deklaracja klasy
record struct
deklaracja struktury
. ::
kwalifikator zakresu
. .
bezpośrednie
odwołanie
kwalifikowane
>
pośrednie odwołanie
kwalifikowane
Inc() ++
inny inkrementacja
Dec()
dekrementacja
' "
ogranicznik łańcucha
Operatory przypisania
W przeciwieństwie do Delphi, w C++ możliwe jest połączenie różnych operatorów z operatorem
przypisania. Na przykład poniższa instrukcja
x = x + 2;
może być zapisana jako
x += 2;
Operatory inkrementacji i dekrementacji
W C++ inkrementacja i dekrementacja może być połączona z przypisaniem na jeden z dwóch
sposobów: prefiksowy, kiedy to inkrementacja lub dekrementacja odbywa się przed
przypisaniem i postfiksowy, kiedy odbywa siÄ™ po dokonaniu przypisania:
x = ++y; // inkrementacja prefiksowa
x = y++; // inkrementacja postfiksowa
Oto konkretny przykład:
int x=5, y=5;
x = ++y;
// teraz x=y=6
x = y++;
// teraz x=6, y=7
Operator warunkowy
Operator ten nie występuje w Delphi. Jest on operatorem trójargumentowym, zwracającym
wartość drugiego lub trzeciego wyrażenia, zależnie od wartości logicznej pierwszego:
(wyr1) ? (wyr2) : (wyr3)
Tak więc instrukcja:
return ((a > b) ? c : d )
równoważna jest następującej:
if (a>b) return (c);
else return (d);
Operatory wskaznikowe
Operator * używany jest zarówno do deklarowania wskazników, jak i do adresowania za pomocą
wskaznika. Obydwie te sytuacje są oczywiście bezbłędnie rozróżniane przez kompilator. Spójrz na
poniższy przykład:
int x, y = 8;
int* ptr = &y; // deklaracja zmiennej ptr i zainicjowanie jej
// adresem zmiennej y
x = *ptr; // odwołanie się do adresu zawartego w zmiennej ptr
Oto równoważna konstrukcja w Delphi:
var
x, y : Integer;
ptr: ^Integer;
begin
y := 8;
ptr := @y;
x := ptr^;
end;
Tak więc operatory * i & C++Buildera równoważne są operatorom (odpowiednio) ^ i @ Delphi.
Operator & nazywany jest operatorem adresu, zwraca bowiem adres zmiennej, będącej jego
operandem.
Operator & wykorzystywany jest również do deklarowania referencji. Referencja jest
szczególnym rodzajem odwołania się do zmiennej może być traktowana jako równoważny jej
obiekt i jest użyteczna przy przekazywaniu parametrów do funkcji. Odpowiednikiem referencji
jest w Delphi przekazywanie parametrów (do procedur i funkcji) przez zmienną (notabene zwane
także przekazywaniem przez referencję), w pewnym sensie więc słowo kluczowe var (w Delphi)
może być traktowane jako odpowiednik operatora &.2
2
Pewną analogią referencji w C++ może być w Delphi także nakładanie na siebie zmiennych za pomocą
dyrektywy absolute przyp. tłum.
Operatory new i delete
Deklaracja zmiennej może mieć zawsze postać podobną do poniższej:
char buffer[255];
Przydział pamięci dla zmiennej następuje wówczas na stosie; zmienna taka nazywana jest zmienną
lokalną, gdyż istnieje tylko do zakończenia realizacji zawierającej ją funkcji. Podstawowym
problemem w przypadku takich zmiennych jest ograniczona pojemność stosu.
Alternatywne podejście polega na alokowaniu zmiennych na stercie, na przykład:
char* buffer;
buffer = new char;
lub krócej:
char* buffer = new char;
Zmienna utworzona w ten sposób istnieje aż do momentu jawnego jej zwolnienia za pomocą
operatora delete:
delete buffer;
Operatory klasowe
Dostęp do elementów definicji klasy może odbywać się w dwojaki sposób: bezpośrednio albo
pośrednio. Wyjaśnimy to zagadnienie w dalszej części rozdziału.
Przepływ sterowania w programie
Podobnie jak Delphi, również i C++Builder oferuje różnorodne konstrukcje dla realizacji skoków
warunkowych i pętli są nimi:
" instrukcje if else;
" instrukcje switch;
" pętle for;
" pętle while i do while.
C++ posiada również instrukcje break i continue, które zaadaptowane zostały kiedyś na
gruncie Turbo Pascala i nadal obecne są w Delphi. Przykłady skoków warunkowych w Delphi i
C++Builderze przedstawia tabela 1.4.
Tabela 1.4. Porównanie instrukcji skoków i pętli Delphi i C++Buildera
Instrukcja Delphi C++Builder
if else if (i = val) then begin if (i == val)
instrukcja1; {instrukcja1; ...;}
...;
end; if (i == val1)
{instrukcja1;...;}
if (i = val1) then begin else if (i == val2)
instrukcja1; {instrukcja1;...;}
... ; else
end {instrukcja1;...;}
else if (i = val2) then
begin
instrukcja1;
..;
end
else
begin
instrukcja1;
...;
end;
switch case of switch () {
val1: case Val1:
instrukcja; instrukcja; break;
val2: case Val2:
instrukcja; instrukcja; break;
... ...
... ...
else default : instrukcja
instrukcja }
end;
for for i := val1 to val2 do for(i=val1;i<=val2;i+=inc)
begin {instrukcja1;...;}
instrukcja1;
...; for(i=val1;i>=val2;i =dec)
end; {instrukcja 1;...;}
for i := val1 downto val2 do
begin
instrukcja1;
...;
end;
While while i = val do While (i == val)
begin {instrukcja1;...;}
instrukcja1;
...;
end;
do while repeat do
instrukcja1; {
... instrukcja1;
until (i = val); ...
} while ( i!= val);
Oto kilka dodatkowych wskazówek, związanych z instrukcjami sterującymi C++Buildera:
" Zazwyczaj każdy wariant (case) instrukcji switch kończony jest instrukcją break; przy
braku takiej instrukcji sterowanie przejdzie automatycznie do następnego wariantu.
Jakkolwiek działanie takie może być zamierzone przez programistę, to jednak często jest
przejawem powszechnie popełnianego błędu, szczególnie przez programistów
przyzwyczajonych do Delphi.
" W roli wyrażenia selekcyjnego instrukcji switch może wystąpić tylko wyrażenie typu
porządkowego nie może nim być np. łańcuch.
" Konstrukcja for(;;) równoważna jest konstrukcjom while(true) i while(1) i
oznacza nieskończoną pętlę; wyjście z takiej pętli może nastąpić tylko w wyniku wykonania
instrukcji break.
Funkcje i procedury
Podobnie jak w Delphi, funkcje C++Buildera muszą być deklarowane ( prototypowane ) przed
użyciem; w przeciwieństwie jednak do Delphi nie istnieje w C++ żadne specjalne słowo kluczowe
na oznaczenie funkcji (w rodzaju function czy procedure). Przykłady deklaracji funkcji w
Delphi i C++Builderze przedstawia tabela 1.5.
Tabela 1.5. Porównanie deklaracji funkcji w Delphi i C++Builderze
Delphi C++Builder
procedure Add; void Add();
procedure Add(x, y: Integer); void Add(int x, y);
function Add: Integer; int Add();
function Add(x, y: Integer): int Add (int x, y);
Integer;
Każdy program w C++Builderze posiada główną funkcję main(), od której rozpoczyna się
jego wykonanie; dla programów w środowisku GUI funkcja ta nazywa się WinMain().
Składniowo funkcja główna programu nie różni się od innych funkcji posiada parametry i
zwraca wartość nie może być jednak wywoływana w sposób bezpośredni. Przykład funkcji
głównej w oknie edytora kodu przedstawia rysunek 1.12.
Rysunek 1.12. Funkcja główna przykładowego projektu
Powyższy rysunek ma w oryginale numer 1.4 (strona 39)
Treść funkcji ujęta jest w nawiasy { }; odpowiadają one nawiasom pionowym begin& end w
Delphi. Do przekazania wartości zwrotnej służy instrukcja return; stanowi ona pewną analogię
do słowa kluczowego Result w Delphi z tą jednak różnicą, iż wykonanie instrukcji return
kończy jednocześnie wykonywanie całej funkcji.
Klasy
Delphi i C++Builder realizują tę samą koncepcję enkapsulacji, polegającej na zamknięciu pól i
operujących na tych polach funkcji w ramach jednostki zwanej klasą. Język C++ odziedziczył
ponadto z języka C pojęcie struktury, definiowanej za pomocą słowa kluczowego struct; różni
się ona od klasy tym, iż wszystkie jej pola i funkcje są publiczne, tj. dostępne na zewnątrz
struktury bez ograniczenia, podczas gdy pola i funkcje składowe (metody) klasy są domyślnie
prywatne.
Podobnie jak w Delphi, każda klasa C++Buildera charakteryzuje się następującymi cechami:
" posiada konstruktor (jeden lub więcej) i destruktor;
" umożliwia selektywne określenie dostępności poszczególnych pól i metod;
" udostępnia wskaznik do swej bieżącej instancji pod postacią słowa kluczowego this,
stanowiÄ…cego odpowiednik wskaznika self z Delphi.
Użyteczną możliwością klas C++Buildera, nieobecną w Delphi, jest wielokrotne dziedziczenie
(ang. multiple inheritance) klasa pochodna może być wyprowadzona z więcej niż jednej klasy
bazowej; poniższy przykład wyjaśnia bliżej, o co chodzi:
// brak dziedziczenia:
class MyClass { // brak dziedziczenia
// elementy deklarowane tutaj są z założenia prywatne
private
// deklaracje prywatne
protected
// deklaracje chronione
public
// deklaracje publiczne
}; // deklaracja klasy kończona jest średnikiem
// pojedyncze dziedziczenie:
class MyClass: BaseClass1
{ ... };
// wielokrotne dziedziczenie:
class MyClass: BaseClass1, BaseClass2, BaseClass3
{ ... };
Konstruktory i destruktory
Każda klasa posiada konstruktor i destruktor; jeżeli programista nie zadeklaruje żadnego
konstruktora (destruktora), kompilator automatycznie wygeneruje konstruktor (destruktor)
domyślny.
Podstawowym zadaniem konstruktora jest przydzielenie pamięci dla instancji klasy i
zainicjowanie jej pól; zadaniem destruktora jest natomiast zwolnienie pamięci zajętej przez tę
instancjÄ™.
Klasa może zawierać kilka konstruktorów, lecz tylko jeden destruktor; konstruktor i destruktor
podobne są do zwykłych funkcji składowych klasy, posiadają jednak kilka cech szczególnych:
" nie zwracają żadnego wyniku (nawet typu void);
" nazwa konstruktora tożsama jest z nazwą klasy, zaś nazwa destruktora powstaje przez
poprzedzenie nazwy klasy znakiem tyldy (~) na przykład:
class A {
public:
A(); // konstruktor
~A(); //destruktor
}
" destruktor nie może posiadać parametrów;
" konstruktory i destruktory nie mogą być wywoływane jak zwykłe funkcje.
Dostęp do pól i funkcji składowych klasy
Spójrz na poniższą definicję prostej klasy:
class Rabbit {
private
int speed=20;
};
Poniższe deklaracje tworzą dwie instancje tej klasy. Pierwsza z nich (Rabbit1) lokowana jest na
stosie, druga (Rabbit2) na stercie:
Rabbit Rabbit1;
Rabbit* Rabbit2 = new Rabbit;
Odwołania do pola speed obydwu instancji będą miały postać następującą:
Rabbit.speed=30;
(*Rabbit2).speed=30;
Zmienna Rabbit2 jest tak naprawdÄ™ wskaznikiem do instancji, dlatego w jej przypadku
odwołanie to ma postać bardziej skomplikowaną. Aby ułatwić odwołania do elementów klasy w
przypadku reprezentowania jej instancji przez wskazniki, wprowadzono w C++ operator
odwołania pośredniego ( >); drugą z powyższych instrukcji można więc napisać w równoważnej
postaci:
Rabbit2 >speed=30;
Wskaznik this
Podobnie jak wskaznik Self w Delphi, this reprezentuje (w treści funkcji składowej) instancję,
na rzecz której funkcja ta jest aktywowana. Oto przykłady jego użycia:
__fastcall TForm1::TForm1(Tcomponent* Owner): TForm(Owner)
{
TLabel *Label1 = new TLabel(this);
Label1 >Parent = this;
Label1 >Caption = this >Width; // to samo, co Form1 >Width
}
Dyrektywy preprocesora
Dyrektywy preprocesora stanowiÄ… specjalne polecenia dla kompilatora. Wiersz zawierajÄ…cy
dyrektywę rozpoczyna się od symbolu #. Niektóre dyrektywy mogą znajdować się w dowolnym
miejscu modułu, inne natomiast jak np. #pragma argsused muszą znajdować się przed
definicjami funkcji, których dotyczą. Przyjrzyjmy się bliżej dwu najczęściej spotykanym
dyrektywom: #define i #include.
Dyrektywa #define
Jak pokazano to nieco wcześniej w tym rozdziale, dyrektywa #define może być
wykorzystywana do definiowania stałych, na przykład:
#define myconstant 100
Za pomocą dyrektywy #define można również definiować makroinstrukcje. Makroinstrukcja
podobna jest do funkcji i może posiadać parametry, na przykład:
#define MAX(A,B) ((A)>(B))?(A): (B)
#define MIN(A,B) ((A)>(B))?(B): (A)
Oto sposób użycia jednej z ww. makroinstrukcji:
int x, y, max;
x = 5;
y = 6;
max = MAX(x,y); // C++Builder rozróżnia wielkość liter
Dyrektywa #include
Użycie dyrektywy #include wiąże się nierozerwalnie z plikami nagłówkowymi. W większości
przypadków wszystkie deklaracje stałych, zmiennych i funkcji umieszczane są w plikach
nagłówkowych, zaś w plikach zródłowych *.cpp znajduje się jedynie część implementacyjna
modułu.
Na czas kompilacji dyrektywa #include zostaje zastąpiona zawartością pliku, którego nazwa
specyfikowana jest jako argument. Specyfikacja ta może mieć jedną z dwóch postaci,
skutkujących odmiennym algorytmem poszukiwania pliku nagłówkowego (w strukturze
katalogów). W przypadku dyrektywy #include poszukiwanie prowadzone jest
jedynie w obrębie katalogów wymienionych w polu Include path na karcie
Directories/Conditionals opcji projektu; nieznalezienie pliku traktowane jest jako błąd.
Dyrektywa #include "nazwa" skutkuje natomiast poszukiwaniem pliku nagłówkowego
kolejno:
" w katalogu, w którym znajduje się plik zawierający odnośną dyrektywę #include;
" w katalogach zawierajÄ…cych inne pliki, zawierajÄ…ce dyrektywy #include, odnoszÄ…ce siÄ™ do
tego samego pliku nagłówkowego;
" w katalogu bieżącym;
" w ścieżce określonej przez dyrektywę /I kompilatora.
Typy plików
Tabela 1.6 przedstawia wykaz różnych typów plików związanych z realizacją projektów Delphi i
C++Buildera.
Tabela 1.6. Typy plików Delphi i C++Buildera
Delphi C++Builder Przeznaczenie pliku
DPR BPR
Główny plik projektu
PAS CPP
Plik kodu zródłowego modułu (w C++Builderze również główny
plik zródłowy projektu)
DFM DFM
Plik binarny opisujÄ…cy kompletnÄ… strukturÄ™ formularza wraz z
komponentami
PAS H lub HPP
Plik nagłówkowy
RES RES
Skompilowany plik zasobów
DCU OBJ
Skompilowany plik modułu
BPG BPG
Plik opisujący grupę projektów
DPK BPK
Plik zawierający listę modułów pakietu
BPI
Plik importowy biblioteki tworzony dla każdego pakietu
BPL BPL
Biblioteka czasu wykonania (runtime); fizycznie jest to
biblioteka DLL wzbogacona o elementy specyficznie dla Delphi
(C++Buildera)
LIB
Statyczna biblioteka
~* ~*
Kopie zapasowe rozmaitych plików
MAK
Plik tekstowy zawierajÄ…cy scenariusz budowania binarnej postaci
projektu na podstawie jego plików zródłowych.
MAP MAP
Plik tekstowy zawierający informacje symboliczne dla śledzenia
niskopoziomowego
TDS
Plik zawierajÄ…cy informacje symboliczne dla Turbo Debuggera.
Z wymienionymi kategoriami plików związane są ponadto następujące reguły:
" Pliki wymienione na pierwszych pięciu pozycjach tworzone są przy pierwszym zapisywaniu
projektu.
" Pliki *.CPP i *.HPP C++Buildera stanowiÄ… odpowiedniki sekcji INTERFACE i
IMPLEMENTATION plików *.PAS w Delphi.
" Pliki *.OBJ tworzone są w wyniku kompilacji modułu lub pakietu.
" Plik *.BPK tworzony jest przy zapisywaniu pliku zródłowego pakietu.
" Pliki *.BPI, *.BPL i *.LIB tworzone sÄ… w wyniku kompilacji lub instalacji pakietu.
" W wersjach 4. i 5. C++Buildera plik *.MAK zastąpiony został przez plik *.BPR; otwarcie
pliku *.MAK w tych wersjach spowoduje automatyczną konwersję wczytanej zawartości do
postaci właściwej plikowi *.BPR.
" Plik *.TDS tworzony jest wówczas, gdy włączona jest opcja Debug Information na
karcie Compiler opcji projektu.
Mocne i słabe strony C++Buildera
W podrozdziale tym omówimy nieco dokładniej podstawowe cechy C++Buildera, mające
bezpośredni związek z tworzeniem i rozwijaniem projektów programistycznych. Dla większości
Czytelników tej książki C++Builder będzie zapewne preferowanym narzędziem projektowym,
wydaje się zatem celowe opisanie tych jego aspektów, które decydują o jego użyteczności jako
narzędzia RAD z jednoczesnym uwzględnieniem tych, które zdają się sprawiać niejakie kłopoty.
Wizualna rzeczywistość naprawdę błyskawiczne
tworzenie aplikacji
Dla programistów bazujących na języku C++, potrzebujących narzędzi do projektowania aplikacji
posiadających bogaty i funkcjonalny interfejs użytkownika, C++Builder ze swym rozbudowanym
IDE, biblioteką VCL i repozytorium zdaje się nie mieć alternatywy. Nawet średnio zaawansowany
programista zdolny jest przy użyciu C++Buildera stworzyć nietrywialną aplikację w rodzaju
wieloplikowego edytora tekstów w niespełna godzinę poza oczywistymi korzyściami
praktycznymi daje to przecież niebagatelną satysfakcję, ponadto możliwość kontrolowania
różnych aspektów zachowania się aplikacji już na etapie jej projektowania znacznie zmniejsza
liczbę niezbędnych prób i błędów.
Wersja 5. C++Buildera niesie ze sobą dodatkowe nowości, czyniące proces projektowania jeszcze
łatwiejszym. Przykładowo komponent TFrame ( ramka ) umożliwia pracę z niezależnymi
oknami podobnymi do formularzy, które to okna mogą być pózniej umieszczane na rzeczywistych
formularzach lub nawet w palecie komponentów. Wizualizacja właściwości graficznych w
inspektorze obiektów czyni ich konfigurowanie jeszcze łatwiejszym, zaś podział właściwości i
zdarzeń na kategorie pozwala szybciej znajdować żądane pozycje, przez ukrycie kategorii rzadko
wykorzystywanych.
Rysunek 1.13 przedstawia środowisko IDE z projektem wykorzystującym trzy ramki TFrame
(dwie znajdują się już na formularzu) w czasie dokonywania wyboru odpowiedniej postaci kursora
w inspektorze obiektów.
Proszę w tym miejscu wkleić rysunek znajdujący się w załączniku pod nazwą Orig-1-5.bmp.
Rysunek ten jest odpowiednikiem rysunku znajdującego się w oryginale na stronie 45; rozbieżność
z oryginalną numeracją nie jest tutaj pomyłką, lecz wynika z dodania przeze mnie dodatkowych
rysunków.
Rysunek 1.13. Przykładowy projekt w IDE C++Buildera 5
Microsoft Visual C++, mimo przymiotnika visual w swej nazwie, nie oferuje podobnej metody
projektowania typu WYSIWYG3 i właśnie na tym polu w największym stopniu ustępuje on
C++Builderowi. Użytkownicy Visual C++ mają do wyboru dwie realne alternatywy w stosunku
do klasycznego programowania w Windows. Podstawą pierwszej z nich jest edytor zasobów i
biblioteka MFC (Microsoft Foundation Classes), druga natomiast polega na tworzeniu bibliotek
DLL przeznaczonych do użytku przez aplikacje stworzone w środowiskach lepiej
przystosowanych do programowania wizualnego, jak na przykład Visual Basic.
Pod względem pierwszej ze wspomnianych opcji Visual C++ wyraznie nie dorównuje
C++Builderowi mimo iż funkcjonowanie edytora zasobów przypomina nieco funkcjonowanie
projektanta formularzy (Form Designer), nie jest on jednak w stanie konkurować z tym ostatnim
pod względem swobody rozmieszczania kontrolek na formularzu i operowania ich
właściwościami. Ponadto edytor zasobów zdolny jest tworzyć wyłącznie standardowe kontrolki,
podczas gdy projektant formularzy potrafi wykorzystać całą rozbudowaną bibliotekę VCL, być
może o zawartości liczonej w tysiącach komponentów.
Jakby tego było mało, C++Builder obsługuje MFC być może nie tyle ze względu na te rzadkie
przypadki, kiedy użytkownik chciałby go użyć, ile raczej ze względów zgodności (w kontekście
istniejącego kodu). Visual C++ nie posiada natomiast żadnych środków ułatwiających migrację z
platformy C++Buildera.
Druga ze wspomnianych opcji tworzenie bibliotek DLL do wykorzystania w innym środowisku
jest o tyle interesująca, iż realizuje w praktyce oddzielenie całej maszynerii aplikacji od jej
interfejsu użytkownika. C++Builder stanowi jednak także połączenie dwóch zestawów funkcji
efektywnego kompilatora C++ oraz użytecznego projektanta GUI; w dobrze zaprojektowanej
aplikacji oddzielenie jej maszynerii od interfejsu użytkownika da się zrealizować równie
efektywnie.
3
ang. WYSIWYG What You See Is What You Get co widzisz, to otrzymasz ; potoczne określenie cechy
programu graficznego (tu: C++Buildera), którego ostateczne wyniki (tu: wygląd działającej aplikacji) są
identyczne lub niemal identyczne z ich symbolicznÄ… reprezentacjÄ… w postaci roboczej (tu: wyglÄ…dem i
ułożeniem komponentów aplikacji w czasie jej projektowania) przyp. tłum.
Dotrzymywanie kroku zgodność ze standardami
Przez wiele lat obecności na rynku narzędzi programistycznych firma Borland nieodmiennie
dotrzymywała kroku standardom ANSI/ISO pod względem zgodności swych kompilatorów z
owymi standardami. C++Builder, którego podstawą jest wersja 5.5 modelu 32-bitowego
kompilatora C++ (BCC32), nie jest w tym względzie wyjątkiem: szczegóły obecnej wersji języka
sformalizowane zostały w ostatniej specyfikacji ANSI/ISO różni się ona od poprzednich wersji
w kilku istotnych kwestiach, między innymi w temacie wzorców (templates) i przestrzeni nazw
(namespaces).
Nie ma to być może większego znaczenia dla małych, monolitycznych aplikacji, konstruowanych
wyłącznie za pomocą projektanta formularzy, jednakże dla dużych, poważnych aplikacji,
tworzonych z myślą o przyszłej skalowalności, tak rygorystyczna zgodność kompilatora ze
standardami, jak w przypadku wspomnianego BCC32, jest czynnikiem koniecznym
długoterminowego powodzenia projektu.
Niestety, wymóg zgodności ze standardami nie zawsze daje się w pełni pogodzić z inną skądinąd
ze wszech miar pożądaną tendencją rozwoju narzędzi programistycznych, mianowicie ciągłym
usprawnianiem procesu kompilacji. Tłumaczy to poniekąd fakt, iż niektóre aplikacje stworzone w
poprzednich wersjach C++Buildera nie dały się skompilować w wersji 5., głównie ze względu na
zmiany specyfikacji pod kątem wspomnianych przed chwilą wzorców i przestrzeni nazw. Co
prawda przystosowywanie aplikacji do nowych standardów z pewnością jest pouczającym
doświadczeniem, jednakże konieczność jego dokonywania kłóci się po prostu z ekonomiczną
stroną działalności programistycznej, skąd wniosek nie można bezkrytycznie polegać na
najlepszych nawet kompilatorach pod względem absolutnej zgodności we wszystkich szczegółach.
Wyraznym, tym razem zamierzonym, odstępstwem od zgodności ze standardami są natomiast
elementy właściwe tylko platformie C++Buildera, wprowadzone do języka w związku z biblioteką
VCL. Jednym z przykładów może być słowo kluczowe __closure, umożliwiające
konstruowanie wskazników do funkcji składowych klas na podstawie instancji klas, nie zaś klas
jako takich; efektu tego nie da się w prosty i klarowny sposób osiągnąć w zgodzie z obowiązującą
specyfikacjÄ… ANSI/ISO.
Osobiste preferencje
Niezależnie od rekomendacji producentów i najpochlebniejszych nawet opinii użytkowników, nie
ma produktów idealnych. Trudno zadowolić wszystkich, tak więc to, co dla jednych wydaje się
zaletą, przez innych może być bezlitośnie krytykowane. Ponadto niezależnie od osobistych
upodobań w każdym oprogramowaniu mogą ujawnić się bezdyskusyjne błędy wszak zostało ono
stworzone przez omylnych w końcu ludzi, przy ograniczonych nakładach finansowych i w
ograniczonym czasie. Takie są realia życia zawodowego programistów.
C++Builder stworzony został jako narzędzie projektowe, nie zaś panaceum na wszelkie kłopoty
programistyczne; nie ma więc nic więc nadzwyczajnego w tym, iż w pewnych obszarach
zastosowań może on okazać się idealny, podczas gdy jego przydatność w innych dziedzinach
będzie raczej ograniczona. Ma to również związek z osobistymi upodobaniami dla programistów
przyzwyczajonych do filozofii Microsoftu wystarczającym argumentem może okazać się proste
stwierdzenie, iż Borland to nie Microsoft&
Zalety i wady C++Buildera konkluzje
Każda dyskusja na temat zalet i wad czegokolwiek pozostaje dyskusją jałową, jeśli nie wesprzeć
jej konkretami; w przypadku C++Buildera konkretami takimi są z pewnością jego cechy
projektowe i wydaje się naturalne, iż to właśnie do nich a nie do narzędzia enigmatycznie
postrzeganego jako całość odnosić można wszelkie opinie wartościujące. Poniższa lista z
pewnością daleka jest od kompletności, zawiera jednak najistotniejsze cechy C++Buildera.
Tak więc do tych elementów C++Buildera 5, które zdobyły sobie największe uznanie
programistów, należą między innymi:
" niezwykle funkcjonalny projektant formularzy;
" przydatność zarówno do szybkiego tworzenia aplikacji, jak i tradycyjnego programowania w
C++, dzięki umiejętnemu połączeniu zgodnego z najnowszymi standardami kompilatora ze
środowiskiem projektowania wizualnego;
" biblioteka komponentów VCL z możliwością wzbogacania jej o nowe, gotowe komponenty i
narzędziami do tworzenia własnych komponentów;
" rozszerzenia języka wykraczające co prawda poza standardy, lecz dostarczające
funkcjonalnych konstrukcji programistycznych;
" wzorce projektów i repozytorium obiektowe umożliwiające wielokrotne wykorzystanie
stworzonego kodu oraz pozwalające na szybkie tworzenie projektów;
" szeroka obsługa mechanizmów bazodanowych dzięki BDE oraz dedykowanym
komponentom;
" ogromne możliwości w zakresie tworzenia aplikacji internetowych;
" łatwa migracja z innych środowisk, między innymi z Visual C++;
" otwarta droga do przenoszenia aplikacji na platformÄ™ Linuksa.
Wśród najczęściej wymienianych niedostatków C++Buildera wymienia się:
" łatwość operowania mechanizmami projektanta formularzy może łatwo doprowadzić do
chaosu w aplikacji zle zaprojektowanej lub wręcz pozbawionej projektu;
" ze względu na znaczące zmiany kompilatora w wersji 5. przenoszenie złożonej aplikacji z
wersji poprzednich może okazać się nieopłacalne;
" migracja na platformÄ™ Visual C++ jest zazwyczaj bardzo trudna;
" ze względu na dominującą pozycję Microsoftu na rynku systemów operacyjnych wybór
narzędzia programistycznego Borlanda może mieć długofalowe konsekwencje o różnorakim
charakterze.
Przygotowania do Kyliksa
Kylix jest roboczą nazwą projektu Borlanda, mającego na celu stworzenie środowiska dla systemu
operacyjnego Linux; w przełożeniu na realia techniczne chodzi tu po prostu o zaadaptowanie
Delphi i C++Buildera na platformÄ™ Linuksa. W wyniku tego tworzenie wizualnych aplikacji w
środowisku Linuksa ma się stać równie łatwe, jak tworzenie ich w Windows przy użyciu Delphi i
C++Buildera.
Istnieje wiele podobieństw pomiędzy Kyliksem a C++Builderem (i Delphi), są też i znaczące
różnice, będące głównie konsekwencją różnic pomiędzy samymi systemami Windows i Linux
należy o tym pamiętać, planując w przyszłości przenoszenie tworzonych obecnie aplikacji w
Windows na platformÄ™ Linuksa.
Informacje zawarte w tym podrozdziale pochodzą zarówno z publicznych anonsów Borlanda, jak i
z dostępnych dyskusji na temat Kyliksa, mają więc charakter po trosze spekulatywny; w efekcie
może się okazać, iż w ukończonym produkcie brak będzie niektórych zapowiadanych szczegółów.
Podobieństwa pomiędzy Kyliksem a C++Builderem
Podstawowa struktura Kyliksa jest pod wieloma względami bardzo podobna do C++Buildera.
Mimo generalnej różnicy pomiędzy interfejsem Windows a rozmaitymi dostępnymi interfejsami
graficznymi dla Linuksa, IDE obydwu produktów są niemal identyczne zawierają inspektora
obiektów, przeglądarkę klas, paletę komponentów i edytor kodu. Rysunek 1.14 prezentuje wygląd
projektu Delphi załadowanego do wczesnej (pre-release) wersji Kyliksa; w charakterze interfejsu
graficznego dla Linuksa wykorzystano tu K Desktop Environment (KDE).
Proszę o zeskanowanie i wklejenie tutaj rysunku znajdującego się na stronie 49. oryginału i
noszÄ…cego oryginalnie numer 1.6
Rysunek 1.14. Środowisko IDE Kyliksa pod Linuksem używającym KDE
Jako że Delphi i C++Builder współdzielą znaczną część dostępnych funkcji, można się
spodziewać, iż wprzęgnięcie mechanizmów związanych z Kyliksem będzie miało w obydwu tych
produktach charakter niemal identyczny. W efekcie nowości w ramach jednego z produktów z
pewnością będą miały swe odpowiedniki w najbliższej wersji drugiego.
Różnice pomiędzy Kyliksem a C++Builderem
Zasadnicza różnica pomiędzy Linuksem a Windows nie może oczywiście pozostać bez wpływu na
Kyliksa, przynajmniej w początkowym okresie jego istnienia. Dotyczy to w pierwszym rzędzie
charakterystycznych dla Windows technologii: COM, DCOM, COM+, ActiveX i oczywiście
samego Win32 API. Kilka lat temu Microsoft we współpracy z Digitalem i innymi znaczącymi
firmami przystąpił jednak do opracowywania DCOM w wersji dla serwerów uniksowych; jej
ukazanie siÄ™ wydaje siÄ™ teraz tylko kwestiÄ… czasu.
Można mieć ponadto nadzieję, iż wywołania funkcji Win32 będą miały swe odpowiedniki w
Linuksie w postaci odrębnej, przezroczystej warstwy, albo w postaci równoważnych funkcji
systemowych; ten drugi wariant jest znacznie mniej korzystny z punktu widzenia przenoszenia
gotowych aplikacji.
Biblioteka komponentów nosić będzie nazwę Borland Component Library for Cross Platform
(CLX w skrócie clicks ). Poszczególne komponenty CLX pogrupowane zostaną zapewne w
kategorie (analogicznie do C++Buildera i Delphi), zaÅ› ich warstwa wizualna zrealizowana zostanie
w oparciu o technologię Qt firmy TrollTech, którą to technologię uznał Borland za
najodpowiedniejszą dla środowiska linuksowego. Qt instalowane jest wraz z KDE, w przypadku
innych interfejsów graficznych jak np. Gnome musi być instalowane oddzielnie.
Prawdopodobnie komponenty kategorii CLX pojawią się również w wersji C++Buildera dla
Windows budowanie aplikacji z ich użyciem ułatwi pózniejsze jej przenoszenie na platformę
Linuksa; z punktu widzenia sprawności zaleca się jednak używanie tradycyjnych komponentów
VCL dla aplikacji, w stosunku do których nie planuje się migracji z platformy Windows.
Podsumowanie
W rozdziale tym przedstawiliśmy podstawy C++Buildera na użytek programistów początkujących
lub tych, którzy znają już Delphi i chcą rozpocząć pracę z C++Builderem. Staraliśmy się pokazać
jego wyjątkową funkcjonalność jako narzędzia projektowego, jak również jego ulepszenia i
rozszerzenia, które pojawiły się w wersji 5. Zajęliśmy się problemem przenoszenia aplikacji
zarówno z poprzednich wersji C++Buildera, jak również z (do) innych środowisk projektowych
bazujących na C++, głównie Visual C++. Przedstawiliśmy również zarys realizowanej właśnie
przez Borland adaptacji Delphi i C++Buildera w środowisku Linuksa, znanej pod roboczą nazwą
Kylix.
Większość z poruszonych tu tematów omówimy szczegółowo w następnych rozdziałach książki.
Wyszukiwarka
Podobne podstrony:
r01 03
863 03
r01 02 popr (2)
ALL L130310?lass101
Mode 03 Chaos Mode
więcej podobnych podstron