07, ## Documents ##, Delphi 4 dla każdego


Rozdział 7.
Komponenty VCL


Jak już pewnie zauważyłeś, jednym z głównych źródeł potęgi Delphi są komponenty. Projektant Formularzy umożliwia umieszczenie w formularzu dowolnego komponentu i zmodyfikowanie jego właściwości. W niektórych przypadkach postępowanie takie jest w pełni wystarczające. W miarę potrzemy, można również manipulować komponentem w trakcie pracy programu przez zmianę jego właściwości i wywoływanie jego metod. Ponadto, każdy komponent projektowany jest w taki sposób, aby mógł reagować na określone zdarzenia. Właściwości, metody i zdarzenia zostały omówione w rozdziale piątym „Model komponentów wizualnych”, dlatego nie będą one tutaj opisywane po raz wtóry.

Rozdział ten poświęcony jest omówieniu komponentów. Poznasz najczęściej stosowane komponenty, co w rezultacie doprowadzi do zaznajomienia się z reprezentującymi je klasami biblioteki VCL. Nic nie stoi na przeszkodzie, aby w trakcie czytania tego rozdziału prowadzić własne eksperymenty. Jeżeli przeczytasz coś, co chciałbyś sprawdzić, jak najbardziej zrób to. Doświadczenia to najcenniejsza forma nauki, dlatego nie bój się eksperymentować.

Przegląd komponentów

Podsumujmy wiadomości o komponentach poznane do tej pory. Zanim jednak do tego przejdziemy, chciałbym oderwać się na chwilę od tematu, aby wytłumaczyć różnice występujące między komponentem VCL, a systemową kontrolką Windows. Do kontrolek Windows zaliczyć można takie komponenty jak pola edycyjne, listy zwykłe i rozwijalne (tzw. pola combo), obiekty statyczne (etykiety) i przyciski, nie wspominając już o kontrolkach biblioteki Win32. Kontrolki Windows z założenia nie posiadają właściwości, metod i zdarzeń. Zamiast nich stosowane są komunikaty, których zadaniem jest przekazywanie poleceń do kontrolki i pobieranie od niej informacji. Mówiąc oględnie, posługiwanie się kontrolkami na tym poziomie jest co najmniej nużące i nieporęczne.

Komponent VCL jest klasą, która reprezentuje kontrolkę Windows (chociaż nie jest to regułą). W praktyce to komponent VCL dodaje właściwości, metody i zdarzenia do kontrolki Windows, aby ułatwić współpracę z nią. Można powiedzieć, że VCL stanowi świeże podejście w pracy z kontrolkami Windows. Słuszne jest również stwierdzenie iż komponenty VCL są kontrolkami, chociaż nie wszystkie kontrolki są komponentami. Przykładowo, komponent VCL TEdit jest kontrolką, ale standardowa kontrolka edycji Windows nie jest komponentem VCL. Celem współpracy komponentów VCL z kontrolkami Windows jest umożliwienie ich programowania na wyższym poziomie.

Biorąc pod uwagę powyższe rozważania, w dalszej części książki komponenty VCL będą (zamiennie) nazywane jednym z terminów: kontrolka lub komponent. (Nigdy jednak słowo komponent nie zostanie użyte w stosunku do kontrolki Windows).

Komponenty wizualne

Do komponentów wizualnych zaliczyć można między innymi kontrolki edycji, przyciski, pola list, etykiety itp. Większość komponentów stosowanych w aplikacjach Delphi to komponenty wizualne. Tego typu komponenty już w trakcie projektowania przybierają, na ile jest to możliwe, wygląd jaki posiadać będą w trakcie pracy programu.

0x01 graphic

Niektóre komponenty są komponentami wizualnymi; inne to tzw. komponenty niewidoczne. Komponent niewidoczny jest elementem niewidocznym w czasie działania uruchomionego programu; jest natomiast widoczny na etapie projektowania.

Komponenty niewidoczne

Komponenty niewidoczne pracują w tle, wykonując określone zadania programistyczne. Przykładami takich komponentów są „timery” systemowe, komponenty „bazodanowe” i listy rysunków. Za komponenty niewidoczne uważa się również standardowe okienka dialogowe Windows takie jak File Open (otwieranie plików), File Save (zapisywanie plików), Font (Zmiana czcionki). W trakcie pracy programu nie są one widoczne same przez się, natomiast ich praca objawia się wyświetlaniem odpowiednich okien.

Standardowe okna dialogowe są omawiane dalej w sekcji „Standardowe okna dialogowe.”

Po umieszczeniu komponentu niewidocznego w formularzu, Delphi wyświetli tam reprezentującą go ikonę. Ikona ta umożliwia dostęp do komponentu i wprowadzenie zmian do jego właściwości w fazie projektowania, jednak sama nie jest widoczna w trakcie pracy programu. Komponenty niewidoczne posiadają właściwości, metody i zdarzenia, tak jak ma to miejsce w przypadku komponentów wizualnych.

Przyjrzyjmy się teraz pewnym właściwościom wspólnym dla większości komponentów.

Właściwość Name

Właściwość Name pełni kluczową rolę w komponencie. W rozdziale piątym „Model komponentów wizualnych”, w sekcji „Odkrywanie VCL” omówione zostały zjawiska zachodzące po umieszczeniu komponentu w formularzu. Delphi przystępuje do pracy w tle bezpośrednio po umieszczeniu dowolnego komponentu w formularzu. Jedną z rzeczy, którą wykonuje jest utworzenie wskaźnika do komponentu i nadanie mu nazwy określonej przez właściwość Name. Załóżmy przykładowo, że umieściłeś w formularzu komponent Edit i zmieniłeś jego właściwość Name na MojEdit. W tym momencie Delphi umieszcza następujące wyrażenie w sekcji publicznej deklaracji formularza:

MojEdit : TEdit;

Kiedy aplikacja zostanie uruchomiona, Delphi utworzy egzemplarz klasy TEdit i przypisze go zmiennej wskaźnikowej MojEdit. Dzięki temu wskaźnikowi masz dostęp do komponentu w trakcie pracy programu. Ustawienie tekstu dla kontrolki edycji można wtedy zrealizować w następujący sposób:

MojEdit.Text:= 'Jenna Lynn';

Delphi korzysta również z właściwości Name podczas tworzenia nazw procedur obsługujących zdarzenia. Załóżmy, że w utworzonym przez siebie komponencie edycji chcesz odpowiednio zareagować na zdarzenie OnChange. Zadanie to realizujesz normalnie przez podwójne kliknięcie na kolumnie Value w Inspektorze Obiektów obok zdarzenia OnChange, zmuszając w ten sposób Delphi do wygenerowania funkcji obsługującej to zdarzenie. Delphi tworzy domyślną nazwę funkcji bazując na wartości właściwości Name komponentu i w ten sposób zdarzenie zostaje obsłużone. W powyższym przykładzie Delphi wygenerowałoby funkcję o nazwie MojEditChange.

Wartość właściwości Name może być modyfikowana w dowolnej chwili, pod warunkiem, że modyfikacja ta odbywa się wyłącznie poprzez Inspektor Obiektów. Jeżeli zmienisz właściwość Name komponentu w trakcie fazy projektowania, Delphi przejdzie przez cały wygenerowany uprzednio kod i zmieni nazwę wskaźnika, a także nazwy wszystkich funkcji obsługujących zdarzenia.

0x01 graphic

Delphi zmodyfikuje cały wygenerowany przez niego kod, aby odpowiadał on nowej wartości właściwości Name komponentu, nie wprowadzi jednak żadnych zmian do kodu napisanego przez Ciebie. Innymi słowy, Delphi modyfikuje jedynie własny kod, programista odpowiada natomiast za aktualizację kodu stworzonego przez siebie. Generalnie rzecz biorąc, właściwość Name powinna być ustawiana bezpośrednio po umieszczeniu komponentu w formularzu i od tej pory nie modyfikowana. Wprowadzanie zmian nazwy komponentu w późniejszym czasie nie napotyka żadnych przeszkód, ale może wymagać dodatkowego nakładu pracy.

Rozważając dalej poprzedni przykład, jeżeli dokonasz zmiany właściwości Name komponentu edycji z MojEdit na Imie, Delphi zmieni nazwę wskaźnika na Imie, a nazwę funkcji obsługującej zdarzenie OnChange na ImieChange. Zostanie to wykonane automatycznie; programista musi jedynie zmienić właściwość Name i przyjąć na słowo, że Delphi wykona resztę pracy.

0x01 graphic

Nigdy nie zmieniaj właściwości Name w trakcie pracy programu. Nie zmieniaj nazwy komponentu (nazwy, którą Delphi przydziela wskaźnikowi komponentu) lub nazw funkcji obsługujących zdarzenia ręcznie w Edytorze Kodu. Jeżeli wykonasz którąś z tych operacji, Delphi utraci kontrolę nad komponentami, co przyniesie niedobre rezultaty (mówiąc oględnie). Możesz nawet utracić możliwość ładowania swojego formularza. Jedyna bezpieczna metoda zmiany właściwości Name komponentu wiedzie przez Inspektor Obiektów.

Wszystkim komponentom umieszczanym w formularzu nadawana jest nazwa domyślna. Przykładowo, po umieszczeniu (na formularzu) komponentu Edit Delphi przypisze jego właściwości Name wartość Edit1. Jeżeli w formularzu umieszczony zostanie drugi komponent tego typu, Delphi przypisze mu nazwę Edit2, itd. Powinieneś nadawać swoim komponentom nazwy znaczące najszybciej jak jest to możliwe, aby uniknąć zamieszania i niepotrzebnej pracy w przyszłości.

0x01 graphic

Możesz pozostawić domyślne nazwy tych komponentów, do których nie będą występowały odwołania w kodzie. Przykładowo, jeżeli posiadasz kilka etykiet zawierających tekst statyczny (nie zmieniający się), możesz pozostawić ich domyślne nazwy, ponieważ do tych komponentów nie będziesz się odwoływał w trakcie pracy.

Ważne właściwości standardowe

Wszystkie komponenty posiadają pewne wspólne właściwości. Przykładowo, wszystkie komponenty wizualne zawierają właściwości Left i Top określające położenie komponentu w formularzu. Właściwości takie jak Left, Top, Height, Width są w miarę proste, dlatego zostaną tutaj pominięte. Niemniej jednak jest kilka standardowych właściwości, które wymagają bliższego spojrzenia.

Właściwość Align

Właściwości Align i Alignment zostały omówione w rozdziale szóstym „Praca z Projektantem Formularzy i Projektantem Menu”, dlatego ich szczegółowe omówienie nie będzie tutaj powtórnie prezentowane. Kompletną informację na temat właściwości Align znajdziesz w rozdziale szóstym. Godne zaznaczenia jest tutaj jednak to, iż nie wszystkie komponenty udostępniają właściwość Align w fazie projektowania. Przykładowo, kontrolka pojedynczej linii edycyjnej powinna zajmować standardową wysokość, dlatego w jej przypadku właściwość Align nie ma sensu. W miarę zdobywania doświadczenia w Delphi (i w zależności od typu pisanych aplikacji) będziesz prawdopodobnie mocno bazował na właściwości Align.

Właściwość Color

Właściwość Color określa kolor tła komponentu. (Kolor tekstu jest ustawiany poprzez właściwość Font.) Chociaż korzystanie z tej właściwości jest proste, istnieje kilka aspektów dotyczących kolorów komponentów, które powinny tutaj zostać wskazane.

Sposób obsługiwania właściwości Color przez Inspektor Obiektów jest nieco unikalny. Jeżeli klikniesz na kolumnie Value zobaczysz przycisk rozwinięcia informujący o możliwości wyboru z listy kolorów. Tego typu możliwość jest powszechnie spotykana, ale to nie wszystko. Jeżeli klikniesz podwójnie na kolumnie Value, wyświetlone zostanie okno dialogowe Kolor. Okno to (rys. 7.1) umożliwia wybór jednego z predefiniowanych kolorów lub utworzenie własnych kolorów przez kliknięcie na przycisku Dodaj do kolorów użytkownika.

Rysunek 7.1.

Okno wyboru koloru

0x01 graphic

0x01 graphic

Jest to to samo okno, jakie wyświetlone zostanie po zaimplementowaniu w aplikacji komponentu ColorDialog.

Po wybraniu barwy w oknie dialogowym Kolor zauważysz zmianę wartości właściwości Color polegającą na pojawieniu się łańcucha szesnastkowego. Łańcuch ten reprezentuje wartości kolorów czerwonego zielonego i niebieskiego (RGB) które w sumie tworzą wybraną barwę. Jeżeli znasz dokładną wartość RGB koloru (co rzadko się zdarza), możesz wpisać ją w pole bezpośrednio.

W większości przypadków będziesz wybierał kolory z dostępnej listy kolorów predefiniowanych. Po kliknięciu na przycisku rozwinięcia zobaczysz listę, która generalnie dzieli się na dwie grupy wartości. Pierwsza grupa kolorów zaczyna się od clBlack i kończy na clWhite. Są to predefiniowane kolory Delphi; na liście znajdują się te, najczęściej stosowane. Aby wybrać jeden z kolorów wystarczy kliknąć na nim w obszarze listy. Jeżeli nie możesz znaleźć odpowiedniego koloru na liście, skorzystaj z okna Kolor, tak jak zostało to omówione powyżej.

Druga grupa kolorów zaczyna się od clScrollBar. Grupa ta reprezentuje system kolorów Windows. Wykorzystanie kolorów z tej listy sprawi, że nasza aplikacja będzie automatycznie dopasowywała swoje barwy wraz ze zmianą schematu kolorystycznego Windows przez użytkownika. Jeżeli chcesz, aby Twoja aplikacja przestrzegała schematu kolorystycznego, jaki użytkownik wybrał dla swojego systemu powinieneś stosować tę listę zamiast poprzedniej.

Użycie kolorów powinno być starannie przemyślane. Dobrze dobrane barwy utworzą estetycznie przyciągające środowisko dla użytkownika. Nadużycie kolorów sprawi, że aplikacja przybierze ohydny wygląd, a jej użycie będzie irytujące. Obfitość kolorów jest kusząca dla nowych programistów - powszechną praktyką jest chęć wykorzystania dużej ilości kolorów, ponieważ ich zastosowanie jest proste i przyjemne, nie pozwól jednak przyłapać się na zabawie odbywającej się kosztem Twoich użytkowników.

Właściwość Cursor

Właściwość Cursor określa typ kursora wyświetlanego w chwili, gdy użytkownik przemieszcza mysz nad komponentem. Dla niektórych komponentów kursor jest zmieniany w sposób automatyczny przez Windows. Przykładowo, kiedy kursor znajdzie się nad jednym z komponentów typu Edit, Memo lub RichEdit Windows nada mu kształt przypominający literę „I”.

Aby Windows mógł zarządzać kursorem, właściwość Cursor musi pozostać ustawiona na wartość crDefault. Jeżeli dysponujemy oknami (komponentami) przeznaczonymi do określonego celu, możemy dla nich określić jeden z pozostałych typów kursorów. Kiedy mysz zostanie przesunięta nad obszar komponentu, Windows zmieni kursor na wyspecyfikowany.

Częstej zmiany kursora trzeba będzie dokonywać w trakcie pracy programu. Użytkownik powinien być, na przykład, informowany o rozpoczęciu długiego procesu przez wyświetlenie kursora klepsydry. Po zmianie kursora trzeba zadbać o przywrócenie jego oryginalnej postaci. Koncepcję tą ilustruje poniższy fragment kodu:

var

OldCursor : TCursor;

begin

OldCursor := Screen.Cursor;

Screen.Cursor := crHourGlass;

...

{przeprowadzenie operacji, która zajmuje długi okres czasu}

...

Screen.Cursor :=OldCursor;

end;

Takie rozwiązanie gwarantuje, że kursor oryginalnie ustawiony dla aplikacji zostanie poprawnie odtworzony.

Inna właściwość - DragCursor - jest używana do ustawienia kursora stosowanego gdy mysz przemieści się nad obszar komponentu wspierającego mechanizm „drag-and-drop”. Podobnie jak w przypadku kolorów, należy być bardzo rozważnym przy korzystaniu z kursorów. Używaj własnych kursorów kiedy jest to niezbędne, ale nie przesadzaj z nimi.

Właściwość Enabled

Właściwość Enabled pozwala na włączanie i wyłączanie dostępu do komponentów. Kiedy komponent jest zablokowany, nie może przyjąć stanu aktywności (klikanie na nim nie daje żadnego efektu) i zazwyczaj informuje o swoim stanie w sposób wizualny. Biorąc na przykład pod uwagę przyciski, zarówno tekst jak i dowolna bitmapa na przycisku jest przyciemniona. Enabled jest właściwością typu Boolean: wartość True udostępnia dany komponent, podczas gdy wartość False blokuje dostęp do niego. Udostępnianie i dezaktywowanie okien (pamiętaj, że komponenty typu okienkowego są również traktowane jako okna) jest cechą samego systemu Windows.

0x01 graphic

Niektóre komponenty pokazują swój stan zablokowania w fazie projektowania, ale większość tego nie robi. Jednym z komponentów, który pokazuje zablokowanie w trakcie projektowania, jest BitBtn.

Właściwość Enabled znajduje zastosowanie głównie dla komponentów okienkowych, chociaż w równym stopniu może znaleźć zastosowanie dla komponentów nieokienkowych - przykładem komponentu tego typu jest SpeedButton.

0x01 graphic

Modyfikowanie właściwości Enabled komponentu Panel wiąże się z jeszcze jedną konsekwencją. Panele są często wykorzystywane jako pojemniki dla innych kontrolek. W takiej sytuacji Panel staje się komponentem rodzicielskim dla umieszczonych w nim kontrolek. Jeżeli Panel stanie się nieaktywny, komponenty umieszczone w jego wnętrzu będą wskazywać na swoją aktywność, ale nie będą funkcjonować ze względu na nieaktywność swojego rodzica (Panelu).

Mimo, że dostęp do komponentów może być wyłączany na etapie projektowania, ich udostępnianie i blokowanie dostępu odbywa się zazwyczaj w trakcie pracy programu. Elementy menu, dla przykładu, powinny być udostępniane lub blokowane w zależności od tego, czy w danej chwili ma sens ich użycie. Ta sama reguła odnosi się do przycisków. Oprócz tego istnieje również szereg innych powodów dla których zachodzić może potrzeba blokowania określonych typów komponentów.

Aby wyłączyć dostęp do komponentu w trakcie pracy programu, wystarczy jego właściwości Enabled przypisać wartość False, natomiast ponowna aktywacja komponentu wymaga przypisania tej właściwości wartości True. Poniższy fragment kodu przedstawia przykład udostępniania lub dezaktywacji elementu menu na podstawie pewnego warunku:

if CanSave then

FileSave.Enabled := True

else

FileSave.Enabled : = False;

Proces tego typu jest często nazywany udostępnianiem poleceń i stanowi istotną część profesjonalnych programów dla Windows.

0x01 graphic

Do udostępniania komponentu lub grupy komponentów można wykorzystać komponent TActionList. Jest on szczegółowo omawiany w rozdziale trzynastym „Wykraczanie ponad podstawy”, w sekcji „Dodawanie funkcji związanych z udostępnianiem poleceń”.

Właściwość Font

Font jest ważną właściwością i dlatego wymaga uwzględnienia w tym miejscu, chociaż mało jest rzeczy, które należy powiedzieć na jej temat. Właściwość Font jest egzemplarzem klasy TFont i jako taka posiada swoje własne właściwości. Ustawienia właściwości Font można dokonać przez dwukrotne kliknięcie na jej polu w Inspektorze Obiektów (co spowoduje rozwinięcie węzła Font i ukazanie jego właściwości) lub przez przywołanie okna dialogowego Czcionka (Font). (Szczegółowe omówienie tego okna znajduje się w dalszej części rozdziału w sekcji „Okno dialogowe Czcionka.”) Właściwość Font z rozwiniętym węzłem ukazującym jej właściwości przedstawiona została na rysunku 7.2.

Rysunek 7.2.

Inspektor Obiektów prezentujący
aściwość Font

0x01 graphic

Właściwość Color decyduje o kolorze czcionki, natomiast właściwość Name umożliwia wybór kroju pisma czcionki.

Na wyszczególnienie zasługują również dwie właściwości klasy TFont: Height i Size:

Zamiana jednej z tych właściwości powoduje automatyczną zmianę drugiej. Właściwość Height jest często określana przez wartość ujemną. Wyjaśnienie tego zjawiska znajdziesz w systemie pomocy - w rozdziale poświęconym klasie TFont.

Właściwość Pitch nie jest szczególnie użyteczna. Do jej omówienia przejdziemy za chwilę, wcześniej jednak przejdziesz krótkie szkolenie na temat czcionek. Czcionka może posiadać rozmiar proporcjonalny lub ustalony:

Teoretycznie, właściwość Pitch może zostać wykorzystana do wymuszenia stałego rozmiaru czcionki proporcjonalnej i odwrotnie. Problem polega na tym, że Windows jest w stanie dokonać zamiany czcionki aby przeprowadzić tego typu konwersję; inaczej mówiąc, trudno jest przewidzieć efekt takiej operacji. Zamiast polegać na właściwości Pitch, o wiele lepszym rozwiązaniem jest wybór takiej czcionki, która w pełni odpowiada naszym potrzebom.

Ostatnia właściwość - Style - klasy TFont służy do ustawienia pogrubienia, pochylenia, podkreślenia lub przekreślenia czcionki. Style te nie wykluczają się wzajemnie, stąd możliwe jest wykorzystanie ich dowolnych kombinacji.

0x01 graphic

Chociaż można dokonywać zmian właściwości czcionki poprzez Inspektor Obiektów, lepsze możliwości daje okno dialogowe Czcionka (wywoływane kliknięciem na przycisku z wielokropkiem obok właściwości Font), ponieważ umożliwia ono przyglądanie się próbce czcionki w miarę wybierania kolejnych opcji. Jeżeli chcesz tylko zmienić właściwość stylu czcionki (Style) lub jej rozmiar (Size) użyj Inspektora Obiektów. Jeśli jednak szukasz czcionki dokładnie pasującej do potrzeb, lepszym rozwiązaniem wydaje się okno dialogowe czcionek.

Właściwość Hint

Właściwość ta służy do określenia tekstu pomocy kontekstowej dla komponentu. Tekst ten dzieli się na dwie części. Pierwsza z nich nazywana jest czasami krótką pomocą kontekstową. Jest to tekst wyświetlany w chwili gdy użytkownik umieści kursor nad komponentem i zatrzyma go przez chwilę w tej pozycji. Okno, które wyświetla tekst pomocy kontekstowej, nazywa się podpowiedzią (tooltip).

Druga część to tzw. długa pomoc kontekstowa. Długa pomoc kontekstowa stanowi opcjonalny tekst wyświetlany na pasku stanu, gdy użytkownik przemieści kursor nad określony komponent. Znakiem oddzielającym długą i krótką pomoc kontekstową jest pipeline (|). Przykładowo, aby zdefiniować długą i krótką pomoc kontekstową dla przycisku paska narzędzi File Open, właściwości Hint należałoby przypisać następujący tekst:

Otwórz plik | Otwórz plik do edycji

Aby podpowiedzi były wyświetlane, właściwość ShowHint obiektu aplikacji musi być ustawiona na wartość True (jest to ustawienie domyślne). Wyświetlanie długich tekstów pomocy kontekstowej na pasku stanu wymaga odrobinę więcej pracy, dlatego dyskusję na ten temat odłożymy do następnego rozdziału.

0x01 graphic

Można określić krótki tekst pomocy, długi tekst pomocy lub obydwa. Do określenia, który tekst jest wprowadzany, należy posłużyć się znakiem pipeline. Jeżeli znak ten nie zostanie użyty, zarówno krótka, jak i długa pomoc kontekstowa będą korzystać z tego samego tekstu.

0x01 graphic

Mimo, że nie ma ograniczenia na długość tekstu zarówno krótkiej, jak i długiej pomocy kontekstowej, powinieneś rozsądnie tę długość dobierać. Krótkie teksty pomocy kontekstowej powinny być ograniczone do 30 znaków lub nawet mniej. Długie teksty pomocy mogą być bardziej opisowe, ale pamiętaj, że zbyt obszerne teksty zostaną obcięte podczas wyświetlania na pasku stanu.

Właściwości ParentColor, ParentCtl3D, ParentFont i ParentShowHint

Właściwości ParentColor, ParentCtl3D, ParentFont i ParentShowHint działają w ten sam sposób, dlatego zostaną omówione wspólnie. Kiedy wszystkie one są ustawione na wartość True, komponent pobiera ustawienia koloru (Color), trójwymiarowości (Ctl3D), czcionki (Font) i wyświetlania pomocy kontekstowej (ShowHint) od swojego rodzica. Przykładowo, dla większości komponentów właściwość ParentFont jest domyślnie ustawiona na wartość True. Oznacza to, że komponent będzie dziedziczył czcionkę, z której w danej chwili korzysta jego rodzic. Dla lepszego zrozumienia tego zagadnienia przeprowadź poniższe ćwiczenie:

  1. Stwórz pusty formularz. Ustaw pole Size właściwości Font na wartość 16.

  2. Umieść w formularzu komponent etykiety (Label). Zwróć uwagę, że etykieta automatycznie korzysta z 16-punktowej czcionki.

  3. Dodaj przycisk (Button) do formularza, zauważ że i on korzysta z 16-punktowej czcionki.

Możesz ustawić tę właściwość na wartość False, ale od momentu kiedy komponent zostanie umieszczony w formularzu nie ma już odwrotu i ewentualne zmiany jego czcionki muszą być przeprowadzane w sposób ręczny.

Właściwość Tag

Właściwość Tag to nic innego jak 4-bajtowa zmienna zarezerwowana na potrzeby programisty. Można wykorzystać ją do przechowywania dowolnych danych, jakie przydać się mogą komponentowi. Przechowywaną daną może być w szczególności wskaźnik do innej klasy, wartość indeksowa lub cokolwiek innego. Korzystanie z tej właściwości należy traktować jako zaawansowaną technikę programistyczną.

Inne właściwości standardowe

W tabeli 7.1 znajduje się lista innych, wykorzystywanych często właściwości standardowych. Nie wymagają one aż tak dokładnego wyjaśnienia, dlatego zostały przedstawione w formie źródła odniesienia. Nie każdy komponent posiada wszystkie właściwości znajdujące się na liście.

Tabela 7.1. Dodatkowe właściwości standardowe

Właściwość

Opis

BorderStyle

Może posiadać wartość bsSingle lub bsNone. Użyj bsNone jeśli chcesz, aby komponent wtapiał się w tło.

BoundsRect

Prostokątny obszar całego komponentu (nie ograniczony jedynie do obszaru klienta).

Caption

Określa tytuł komponentu. Wiele komponentów nie posiada tytułu, dlatego właściwość ta jest dla nich niewidoczna.

ClientHeight

Zawiera wysokość obszaru klienta w komponencie.

ClientRect

Zawiera współrzędne prostokątnego obszaru klienta w komponencie.

ClientWidth

Zawiera szerokość obszaru klienta w komponencie.

Constraints

Określa wymiary ograniczające komponent (maksymalną i minimalną szerokość i wysokość). Właściwość bardziej istotna dla formularzy niż dla innych komponentów.

Ctl3D

Określa, czy komponent powinien być rysowany z trójwymiarowym obramowaniem. Jeżeli właściwość BorderStyle jest ustawiona na bsNone, właściwość ta nie ma znaczenia.

Height

Określa wysokość komponentu.

HelpContext

Służy do skojarzenia numeru indeksu w pliku pomocy z określonym komponentem.

Left

Określa współrzędną x komponentu.

Parent

Wskaźnik do rodzica komponentu.

PopupMenu

Specyfikuje menu kontekstowe wyświetlane w chwili, gdy użytkownik kliknie prawym przyciskiem myszki.

TabOrder

Związana z komponentami typu okienkowego. Ustala pozycję komponentu w porządku zgodnym z klawiszem Tab.

cd. na następnej stronie

Tabela 7.1. cd. Dodatkowe właściwości standardowe

Właściwość

Opis

TabStop

Związana z komponentami typu okienkowego. Decyduje o tym, czy
komponent może być włączony do cyklu wymuszanego przez klawisz Tab. Wartość False eliminuje komponent z tego cyklu.

Top

Określa współrzędną y komponentu.

Visible

Określa czy komponent jest aktualnie widoczny. Jej zmiana objawia się ukryciem lub wyświetleniem komponentu.

Width

Określa szerokość komponentu.

Podstawowe metody komponentów

Istnieje ponad 20 metod wspólnych dla większości komponentów. W przypadku komponentów okienkowych zbiór wspólnych metod rośnie do 40. Co ciekawe, niewiele z nich jest powszechnie stosowanych. Większość funkcji komponentu realizowana jest poprzez właściwości. Na przykład, aby ukryć komponent można wywołać metodę Hide lub nadać właściwości Visible wartość False. Dodatkowo komponenty zawierają zazwyczaj zestaw funkcji specyficznych dla ich przeznaczenia i to prawdopodobnie z nich będziesz korzystał najczęściej podczas pracy z komponentami.

Istnieje jednak kilka metod wartych wspomnienia, zostały one przedstawione poniżej (w tabeli 7.2). Weź pod uwagę, że niektóre z tych metod nie są dostępne dla wszystkich kontrolek. Nie są to najczęściej stosowane metody wspólne dla wszystkich komponentów, ale raczej najpowszechniej stosowane metody komponentów w ogólności. Ponadto lista ta koncentruje się na komponentach reprezentujących kontrolki (tzn. komponentach umieszczanych w formularzach), a nie na komponentach jako formularzach. Metody specyficzne dla formularzy były omawiane w rozdziale czwartym „Środowisko zintegrowane (IDE).”

Teraz przyjrzyjmy się niektórym ze zdarzeń, na które najczęściej reagują komponenty.

Zdarzenia podstawowe

Podobnie jak w przypadku właściwości i metod, istnieją również pewne zdarzenia, na które komponenty reagują najczęściej. Komponenty obejmują szeroki zakres dostępnych kontrolek Windows, dlatego każdy z nich ma indywidualne potrzeby. Zdarzenia specyficzne dla formularzy nie zostały tutaj uwzględnione, ponieważ była o nich mowa w rozdziale czwartym. Najczęściej wykorzystywane zdarzenia zostały przedstawione w rozdziale 7.3.

Już za chwilę zaczniemy z bliska przyglądać się niektórym komponentom VCL. Najpierw jednak chcę, abyś poznał klasę, która jest często wykorzystywana przez niektóre komponenty VCL - TStrings.

Tabela 7.2. Wspólne metody komponentów

Metoda

Opis

Broadcast

Wysyła komunikat do wszystkich komponentów potomnych typu okienkowego.

ClientToScreen

Konwertuje współrzędne okna użytkownika (klienta) do współrzędnych ekranowych.

ContainsControl

Zwraca wartość True, jeżeli określony komponent jest potomkiem danego komponentu lub formularza.

HandleAllocated

Zwraca wartość True, jeżeli dla komponentu utworzony został uchwyt. Utworzenie uchwytu (o ile nie został on jeszcze utworzony) następuje automatycznie w wyniku zwykłego odczytania wartości właściwości Handle, dlatego metoda HandleAllocated może zostać wykorzystana do sprawdzenia istnienia uchwytu bez jego tworzenia.

Hide

Ukrywa komponent. Komponent jest nadal dostępny i może być ponownie wyświetlony w czasie późniejszym.

Invalidate

Wymusza przerysowanie komponentu (jego odświeżenie). Przerysowanie to nastąpi w najbliższym dogodnym dla Windows czasie.

Perform

Przekazuje komunikat bezpośrednio do komponentu, zamiast przesyłać go przez system komunikatów Windows.

Refresh

Wymusza natychmiastowe przerysowanie komponentu i czyści go tuż przed ponownym namalowaniem.

Repaint

Wymusza natychmiastowe przerysowane komponentu. Tło komponentu nie jest czyszczone przed ponownym namalowaniem.

SetBounds

Umożliwia jednoczesne ustawienie właściwości Top, Left, Width i Height. Operacja taka oszczędza czas w porównaniu z ręcznym ustawianiem każdej właściwości z osobna.

SetFocus

Czyni komponent aktywnym. Działa jedynie w przypadku komponentów typu okienkowego.

Update

Wymusza natychmiastowe odświeżenie komponentu. Zazwyczaj w celu odświeżenia komponentów powinieneś stosować metody Refresh i Repaint.

Tabela 7.3. Najczęściej obsługiwane zdarzenia komponentów

Zdarzenie

Opis

OnChange

Zdarzenie jest generowane, gdy w komponencie zajdzie jakakolwiek zmiana. Dokładna implementacja zależy od typu komponentu.

OnClick

Generowane jest, gdy użytkownik kliknie dowolnym przyciskiem myszy na obszarze komponentu.

OnDblClick

Generowane gdy użytkownik kliknie podwójnie na komponencie.

OnEnter

Pojawia się, gdy komponent typu okienkowego stanie się aktywny.

cd. na następnej stronie

Tabela 7.3. cd. Najczęściej obsługiwane zdarzenia komponentów

Zdarzenie

Opis

OnExit

Pojawia się, gdy komponent typu okienkowego straci stan aktywności w wyniku przeniesienia go przez użytkownika do innego komponentu. Zdarzenie to nie pojawia się kiedy użytkownik przełącza się między
formularzami lub przechodzi do innej aplikacji.

OnKeyDown

Generowane jest po naciśnięciu klawisza przez użytkownika w chwili gdy kontrolka posiada stan aktywności. Naciśniętym klawiszem może być jeden z klawiszy alfanumerycznych, strzałka kursora, Home, End, Ctrl itd.

OnKeyPress

Zdarzenie to jest również wywoływane po naciśnięciu klawisza przez
użytkownika, ale tylko jeżeli klawiszem tym był któryś z klawiszy
alfanumerycznych, Tab, Backspace, Enter lub Esc.

OnKeyUp

Pojawia się za każdym razem, gdy zwolniony zostanie naciśnięty klawisz.

OnMouseDown

Generowane jest w chwili gdy kursor znajdzie się nad komponentem
i naciśnięty zostanie jeden z przycisków myszy. Parametry przekazywane do funkcji obsługującej to zdarzenie informują o tym który z przycisków myszy został kliknięty, które z klawiszy specjalnych (Alt, Shift, Ctrl) zostały naciśnięte, a także jakie były współrzędne położenia x i y kursora myszy w chwili pojawienia się zdarzenia.

OnMouseMove

Pojawia się za każdym razem, gdy mysz przemieszcza się nad komponentem.

OnMouseUp

Generowane jest, gdy przycisk myszy zostanie zwolniony nad komponentem. Przycisk musi wcześniej zostać wciśnięty, gdy kursor myszy znajduje się nad komponentem.

OnPaint

Pojawia się zawsze, gdy komponent wymaga odświeżenia (ponownego narysowania). Można samodzielnie reagować na to zdarzenie po to, aby wykonywać takie operacje odświeżające, jakie potrzebne są z naszego punktu widzenia.

TStrings

TStrings jest klasą biblioteki VCL, która zarządza listami łańcuchów. Kilka komponentów VCL używa egzemplarzy tej klasy do zarządzania swoimi danymi (zwykle tekstami). Dla przykładu, w rozdziale szóstym korzystałeś z klasy TStrings budując aplikację ScratchPad. W tej chwili mówisz: „Nie przypominam sobie użycia klasy TStrings.” Jednak jej użycie miało miejsce, tylko nie byłeś tego świadomy. Pamiętasz zapisywanie i ładowanie plików? Użyłeś wtedy następującej konstrukcji:

Memo.Lines.SaveToFile(SaveDialog.FileName);

Właściwość Lines klasy TMemo jest obiektem klasy TStrings. Metoda SaveToFile tej klasy pobiera łańcuchy i zapisuje je do pliku na dysku. Tej samej techniki można użyć do załadowania zawartości pola listy z pliku lub zapisania jej na dysk. W przypadku klasy TListBox, właściwość przechowująca elementy pola listy nosi nazwę Items. Dla przykładu, spróbuj wykonać poniższe ćwiczenie:

Obsługiwanie zdarzeń myszy

Zdarzenia myszy posiadają kilka cech szczególnych, których istnienia powinieneś być świadom. Jeżeli naszym zadaniem jest reagowanie tylko w przypadku kliknięcia na komponencie, możemy zrobić to w sposób prosty reagując jedynie na zdarzenie OnClick. Jeżeli konieczne stanie się użycie zdarzeń OnMouseDown i OnMouseUp, należy pamiętać, że razem z tymi zdarzeniami wysyłane jest zawsze zdarzenie OnClick. Przykładowo, pojedyncze kliknięcie spowoduje powstanie następujących zdarzeń (we wskazanej kolejności):

OnMouseDown

OnClick

OnMouseUp

Podobnie, po podwójnym kliknięciu użytkownika na przycisku myszy aplikacja może otrzymać więcej zdarzeń, niż by się mogło nam wydawać. Podwójne kliknięcie na komponencie powoduje powstanie następujących zdarzeń:

OnMouseDown

OnClick

OnDblClick

OnMouseUp

Chcę tu uświadomić, iż trzeba szczególnie uważać reagując na oba zdarzenia pojedynczego i podwójnego kliknięcia komponentu. Bądź świadom tego, że dla podwójnego kliknięcia generowane są cztery różne zdarzenia.

Również w przypadku naciśnięcia klawisza generowanych jest wiele zdarzeń. Naciśnięcie klawisza we wnętrzu (na przykład) kontrolki edycyjnej spowoduje powstanie zdarzeń OnKeyDown, OnKeyPress, OnChange i OnKeyUp.

Kod związany z niniejszą książką (na załączonej dyskietce) zawiera program o nazwie EventTst, który ilustruje fakt pojawiania się wielu zdarzeń w wyniku kliknięcia na myszce lub wciśnięcia klawisza. Uruchom go, aby przekonać się, jak różnorodne zdarzenia generowane są w zależności od akcji podejmowanych przez użytkownika.

  1. Utwórz nową aplikację i umieść w jej formularzu komponent ListBox. Zmodyfikuj rozmiar komponentu według własnego uznania.

  1. Zmień właściwość Name listy na ListBox.

  2. Kliknij podwójnie na tle formularza (poza polem listy). W Edytorze Kodu wyświetlona zostanie procedura FormCreate.

  3. Zmodyfikuj procedurę FormCreate tak, aby przyjęła ona następującą postać:

procedure TForm1.FormCreate(Sender : TObject);

var

WinDir : array [0..255] of Char;

FileName : string;

begin

GetWindowsDirectory(WinDir, SizeOf(WinDir));

FileName := WinDir + '\win.ini';

ListBox.Items.LoadFromFile(FileName);

end;

  1. Kliknij na przycisku Run, aby skompilować i uruchomić program.

Po starcie programu pole listy wypełnione jest zawartością pliku WIN.INI. Przy użyciu tej metody można w łatwy sposób załadować listę elementów z dowolnego pliku tekstowego w standardzie ASCII. Również komponent ComboBox posiada właściwość Items, która działa dokładnie w ten sam sposób.

Wywołując metody klasy TStrings: Add, Append, Delete, Insert i Move można (odpowiednio) dodawać, usuwać, wstawiać i przesuwać elementy pola listy, listy rozwijalnej i Memo.

0x01 graphic

Działanie metody Add zależy od wartości właściwości Stored. Jeżeli jest ona ustawiona na wartość True, funkcja Add wstawi element dokładnie tam, gdzie powinien się on znaleźć. W przypadku wartości False nowy łańcuch zostanie dodany na końcu listy.

Zawartość listy może zostać wyczyszczona przez wywołanie metody Clear. Dostęp do pojedynczego elementu listy odbywa się poprzez operator indeksu tablicy. Przykładowo, aby dotrzeć do pierwszego łańcucha na liście, można użyć następującego przypisania:

Edit.Text:= List.Items[0];

0x01 graphic

Łańcuchy w klasie TStrings są tak naprawdę przechowywane we właściwości Strings. Właściwość Strings jest zadeklarowana jako domyślna właściwość tablicowa klasy TStrings, dlatego nie ma potrzeby jej jawnego wskazywania podczas odwoływania się do określonego łańcucha (chociaż nie jest to wcale zakazane). W związku z tym dwie poniższe linie zostaną przetworzone przez kompilator na ten sam fragment kodu:

Edit.Text := ListBox.Items[0];

Edit.Text := ListBox.Items.Strings[0];

Każdy łańcuch tablicy w klasie TStrings zawiera oprócz samego siebie również cztery dodatkowe bajty danych. Dostęp do nich jest możliwy poprzez właściwość Objects, natomiast ich wykorzystanie jest zależne od woli użytkownika. Załóżmy przykładowo, że utworzyłeś samodzielnie rysującą się listę, która wyświetla bitmapy. Wtedy oprócz zwykłego przechowywania łańcuchów, można również przechowywać wskaźniki do obiektów klasy TBitmap w tablicy Objects.

0x01 graphic

Czasem może zaistnieć sytuacja, kiedy niezbędne okaże się zarządzanie tablicą łańcuchów nie związanych z komponentem. Właśnie do tego celu służy klasa TstringList. Jej działanie jest niemal identyczne jak w przypadku klasy TStrings z tą różnicą, że może ona zostać wykorzystana niezależnie od komponentów. Klasa TStringList jest szczególnie dogodna przy odczytywaniu, manipulowaniu i zapisywaniu plików tekstowych.

0x01 graphic

W rzeczywistości TStrings jest czymś co nazywa się abstrakcyjną klasą podstawową. Abstrakcyjna klasa podstawowa nie jest nigdy używana w sposób bezpośredni; służy tylko jako klasa podstawowa do wyprowadzania innych klas. Właściwość Lines nie jest tak naprawdę obiektem klasy TStrings (jak zostało to powiedziane wcześniej), ale obiektem klasy TMemoStrings. Może to być trochę mylące, ponieważ właściwość Lines jest zadeklarowana jako wskaźnik klasy TStrings, ale w rzeczywistości wskaźnik ten wskazuje na egzemplarzem klasy TMemoStrings. Deklaracja i utworzenie właściwości Lines wygląda następująco:

var

Lines : TStrings;

...

begin

...

Lines := TMemoStrings.Create;

Właśnie dlatego właściwość Lines wydaje się być obiektem klasy TStrings mimo, iż w rzeczywistości nim nie jest. Moim zamiarem nie było sprowadzenie Cię na manowce, ale sądziłem że najlepiej będzie wprowadzić rozróżnienie po dyskusji na temat klasy TStrings zamiast mącić Ci w głowie tą informacją w trakcie jej trwania.

0x01 graphic

Abstrakcyjna klasa podstawowa jest klasą, której nie można użyć w sposób bezpośredni. Niezbędne jest utworzenie klasy potomnej względem abstrakcyjnej klasy podstawowej i użycie jej egzemplarza w zamian.

Standardowe komponenty reprezentujące kontrolki Windows

Dawno, dawno temu istniało coś takiego jak Windows 3.0. Udostępniał on takie elementy, jak kontrolki edycyjne (składające się z jednego lub kilku wierszy), pola list, obiekty combo (listy rozwijalne), przyciski, pola wyboru, pola opcji i kontrolki statyczne. Kontrolki te musiały być dosyć dobrze zaprojektowane, ponieważ są one bardzo powszechnie stosowane w obecnych programach dla Windows - mimo pojawienia się nowych kontrolek biblioteki Win32.

Nie będziemy tutaj omawiać każdej kontrolki Windows i odpowiadającego jej komponentu VCL. Istnieje jednak kilka kwestii, które powinieneś znać biorąc pod uwagę komponenty standardowe, o których mowa będzie w następnych sekcjach.

0x01 graphic

Odwołania do komponentów będą realizowane na jeden z dwóch sposobów: poprzez nazwę komponentu lub poprzez nazwę klasy VCL która definiuje komponent. Możliwe będzie stwierdzenie „Komponent Label jest wykorzystywany do...” lub „Komponent TLabel jest wykorzystywany do...”. Obydwa przypadki dotyczą tego samego komponentu.

Kontrolki edycyjne

Delphi udostępnia cztery komponenty kontrolek edycyjnych. Komponenty Edit, Memo i MaskEdit bazują na standardowych kontrolkach Windows. Komponent RichEdit jest oparty na kontrolce Win32 o tej samej nazwie - kontrolka ta nie zalicza się do zestawu kontrolek standardowych Windows. Mimo to zostanie on omówiony w tej części książki, ponieważ posiada wiele cech wspólnych z innymi kontrolkami edycyjnymi.

Komponent Edit

Komponent Edit realizuje prostą kontrolkę edycji jednowierszowej. Komponent ten nie posiada właściwości Align ani Alignment. Brak właściwości Alignment wynika z faktu, iż w kontrolce pojedynczej linii edycji tekst może być wyrównywany jedynie do lewej strony. Właściwość Align nie występuje w komponencie Edit, ponieważ nie może (lub ściślej, nie powinien) on mieć możliwości powiększenia się do pełnego obszaru klienta w oknie.

0x01 graphic

Jeżeli potrzebujesz komponentu edycji z wyrównywaniem do prawej strony lub centrowaniem, użyj komponentu Memo ustawiając jego wysokość na wymiar odpowiadający wysokości standardowego komponentu Edit. Następnie zmodyfikuj właściwość Alignment według własnych wymagań.

0x01 graphic

Kiedy jest to możliwe, staraj się utrzymywać standardowe formy kontrolek. Mimo że kontrolce Edit można nadać dowolną wysokość, będzie to mylące dla użytkownika, jeżeli przekroczy ona rozmiar standardowej kontrolki edycyjnej Windows (użytkownikowi może się wydać, że jest to kontrolka edycyjna składająca się z wielu wierszy).

Komponent MaskEdit

Komponent MaskEdit to komponent Edit z dołączonym filtrem wejściowym lub maską. Komponent ten nie reprezentuje kolejnej standardowej kontrolki Windows, ale jest raczej rozszerzeniem VCL standardowej kontrolki edycyjnej. Maska stosowana jest w celu wymuszenia ograniczeń na ilość bądź repertuar wprowadzanych znaków. Dodatkowo maska może zawierać pewne znaki specjalne które domyślnie umieszczane są w wnętrzu kontrolki edycji. Przykładowo, data jest często formatowana w sposób następujący:

26/03/99

Maska edycji dla daty może z góry posiadać w ustalonych miejscach znaki slash; w ten sposób od użytkownika wymaga się jedynie wprowadzenia wartości liczbowych. Maska edycji określałaby ponadto, iż wprowadzane mogą być jedynie liczby, eliminując możliwość wpisywania przez użytkownika znaków nie będących cyframi.

0x01 graphic

Istnieje specjalizowany komponent o nazwie DateTimePicker (rezydujący na stronie Win32), umożliwiający wybieranie daty i czasu. Kiedy właściwość Kind jest ustawiona na wartość dtkDate, komponent wyświetla rozwijalny kalendarz z którego użytkownik może wybrać datę. Gdy właściwość Kind jest ustawiona na wartość dtkTime, komponent wyświetla kontrolkę edycyjną umożliwiającą użytkownikowi ustawienie godzin, minut i sekund, a także pory dnia (AM lub PM). Gdy zachodzi konieczność wprowadzania daty i czasu, spośród komponentów MaskEdit i DateTimePicker preferowany jest ten drugi.

Komponent EditMask ma wpływ na stosowaną maskę wprowadzania. Po kliknięciu na przycisku wielokropka w kolumnie Value właściwości EditMask wyświetlony zostaje Edytor Maski Wprowadzania (Input Mask Editor). Okno to umożliwia wybór jednej z predefiniowanych masek lub utworzenie własnej. Można wybierać gotowe maski wprowadzania związane z kilkoma krajami. Na rysunku 7.3 przedstawiony został Edytor Maski Wprowadzania wyświetlający zestaw predefiniowanych masek dla Stanów Zjednoczonych.

Rysunek 7.3.

Edytor Maski Wprowadzania

0x01 graphic

Po dalsze informacje na temat budowania własnych masek wprowadzania odsyłam do systemu pomocy Delphi.

Komponent Memo

Komponent Memo realizuje wielowierszową kontrolkę edycyjną. Najbardziej znacząca właściwość tego komponentu nosi nazwę Lines. Jak wspomniałem wcześniej podczas dyskusji na temat klasy TStrings, właściwość Lines umożliwia zapisywanie zawartości komponentu Memo na dysk, ładowanie do komponentu tekstu pochodzącego z pliku lub przetwarzanie każdej linii notatki w sposób indywidualny.

Cechą szczególną komponentu Memo jest jego właściwość ScrollBars. Określa ona, czy komponent posiada poziomy, pionowy lub obydwa paski przewijania. Z właściwości tej korzystałeś w rozdziale szóstym pisząc aplikację ScratchPad. Memo jest niezwykle uniwersalnym komponentem, z którego na pewno będziesz często korzystał.

Komponent RichEdit

Komponent RichEdit jest największym i najlepszym komponentem spośród wszystkich komponentów edycyjnych; bazuje on na kontrolce biblioteki Win32 o tej samej nazwie. Komponent RichEdit umożliwia zmianę czcionki, stosowanie wcięć, pogrubianie czcionki, stosowanie kursywy, podkreślenia i wielu innych opcji. W zasadzie komponent RichEdit jest mini-edytorem tekstu zamkniętym w jednym zgrabnym pakiecie; w stosunku do komponentu Memo posiada on kilka dodatkowych właściwości dostępnych na etapie projektowania. Z ważniejszych właściwości dostępnych w czasie wykonania programu wymienić należy SelAttributes i Paragraph.

RichEdit jest komponentem złożonym, ale łatwym w użyciu - jeżeli wziąć pod uwagę stopień tej złożoności. Szczegółowe informacje na temat komponentu RichEdit znajdziesz w systemie pomocy Delphi.

Właściwości standardowych kontrolek edycyjnych

W tabeli 7.4 znajdują się właściwości specyficzne dla komponentów bazujących na kontrolkach edycyjnych.

Tabela 7.4. Właściwości kontrolek edycji

Element

Odnosi się do …

Opis

Właściwości dostępne na etapie projektowania

AutoSelect

Edit, MaskEdit

Przy ustawieniu na True tekst we wnętrzu kontrolki będzie automatycznie zaznaczany gdy użytkownik przejdzie do niej klawiszem Tab. Wartość domyślna: True.

AutoSize

Edit, MaskEdit

Przy ustawieniu na True kontrolka automatycznie zmodyfikuje swój rozmiar, jeżeli używana w jej wnętrzu czcionka ulegnie zmianie. W przeciwnym przypadku kontrolka nie zmienia swojego rozmiaru przy zmianie czcionki. Wartość domyślna: True.

Tabela 7.4. cd. Właściwości kontrolek edycji

Element

Odnosi się do …

Opis

CharCase

Edit, MaskEdit

Określa, czy kontrolka wyświetla tekst składający się dużych znaków (ecUpperCase), małych znaków (ecLowerCase) lub mieszanych
(ecNormal). Wartość domyślna: ecNormal.

HideScrollBars

RichEdit

Przy ustawieniu na True paski przewijania są wyświetlane jedynie wtedy, gdy zachodzi taka potrzeba, natomiast w pozostałych sytuacjach są ukryte. W przypadku wartości False obecność pasków przewijania zależy od wartości
właściwości ScrollBars.

HideSelection

Edit, Memo, RichEdit

Przy ustawieniu na True dowolny zaznaczony tekst przestanie być pokazywany jako taki, kiedy użytkownik przejdzie do innej kontrolki używając klawisza Tab. Wartość domyślna: True.

Lines

Memo, RichEdit

Przechowuje tekst stanowiący zawartość
komponentu.

MaxLength

wszystkich

Określa maksymalną liczbę znaków jaką
komponent jest w stanie pomieścić. W przypadku wartości 0 liczba znaków możliwych do
wprowadzenia jest nieograniczona (ściślej - ograniczona jedynie przez możliwości systemu). Wartość domyślna: 0.

OEMConvert

Edit, Memo

Ustaw tę wartość na True jeżeli wprowadzany tekst będzie składał się z nazw plików. Wartość domyślna: False.

PasswordChar

Edit, MaskEdit

Kiedy właściwość ta zawiera znak inny niż ASCII #0, wprowadzany tekst jest odwzorowywany na ekranie przez wyspecyfikowany znak, zamiast w sposób dosłowny. Właściwość wpływa jedynie na wygląd kontrolki na ekranie - zapamiętywany tekst stanowi wierne odzwierciedlenie wprowadzanych znaków. Większość kontrolek edycyjnych hasła używa znaku gwiazdki (*) w roli znaku „maskującego”. Wartość domyślna: #0.

PlainText

RichEdit

Przy ustawionej wartości True pliki formatu RTF (Rich Text Format) będą wyświetlane w postaci zwykłego tekstu bez formatowania znaków i paragrafów. Przy ustawionej wartości False pliki będą wyświetlane z pełnym formatowaniem RTF. Wartość domyślna: False.

ReadOnly

wszystkich

Przy ustawionej wartości True komponent będzie wyświetlał swój tekst, ale nie będzie możliwości jego modyfikacji. Użytkownik może jednak zaznaczać i kopiować tekst do Schowka. Wartość domyślna: False.

cd. na następnej stronie

Tabela 7.4. cd. Właściwości kontrolek edycji

Element

Odnosi się do …

Opis

ScrollBars

Memo, RichEdit

Określa, które paski przewijania powinny być wyświetlane. Możliwe wartości to: ssNone, ssBoth, ssHorizontal i ssVertical.
Wartość domyślna: ssNone.

Text

Edit, MaskEdit

Przechowuje tekst stanowiący zawartość
komponentu.

WantReturns

Memo, RichEdit

Przy ustawionej wartości True po naciśnięciu przez użytkownika klawisza Enter komponent przechwytuje znak powrotu karetki (return) i wstawia nową linię do obszaru edycji.
W przypadku wartości False naciśnięcie klawisza Enter obsługiwane jest przez formularz (co może spowodować efekt „naciśnięcia” domyślnego przycisku - o ile taki istnieje - i zamknięcie formularza). Wartość domyślna: True.

WantTabs

Memo, RichEdit

Przy ustawionej wartości True po naciśnięciu przez użytkownika klawisza Tab w obszarze edycji wstawiany jest znak tabulacji. Wartość False powoduje przekazanie znaku do formularza, co umożliwia opuszczenie kontrolki edycyjnej. Wartość domyślna: False.

WordWrap

Memo, RichEdit

Przy ustawionej wartości True wpisywany tekst jest „zawijany” do nowej linii po osiągnięciu prawej krawędzi kontrolki. Wartość False sprawia, że kontrolka automatycznie przesuwa tekst w miarę wprowadzania nowych znaków. Wartość domyślna: True.

Właściwości dostępne w czasie wykonania

Modified

wszystkich

Określa, czy zawartość komponentu zmieniła się od momentu, kiedy właściwość Modified została ustawiona po raz ostatni. Po zapisaniu zawartości komponentu Memo lub RichEdit do pliku właściwości tej powinno przypisać się wartość False.

SelLength

wszystkich

Zawiera długość tekstu aktualnie zaznaczonego we wnętrzu kontrolki.

SelStart

wszystkich

Zawiera indeks pierwszego znaku zaznaczonego tekstu. Pierwszy znak w kontrolce ma indeks 0.

SelText

wszystkich

Reprezentuje zaznaczony tekst.

Kontrolki edycyjne posiadają wiele wspólnych metod; jest ich zbyt dużo, aby można było je tutaj przedstawić w całości. Metody CutToClipboard, CopyToClipboard, PasteFromClipboard dotyczą operacji na Schowku i manipulowania tekstem. Metody GetSelTextBuf i GetTextBuf pobierają - odpowiednio - tekst zaznaczony w komponencie oraz cały tekst komponentu. Przejrzyj tematy pomocy Delphi: TEdit, TMaskEdit, TMemo i TRichEdit, znajdziesz tam kompletną listę metod związanych z każdą kontrolką edycyjną.

Interesujące nas zdarzenia zależeć będą od typu kontrolki edycyjnej, jaką wybierzemy. Ogólnie rzecz biorąc, najczęściej wykorzystywanymi zdarzeniami są OnEnter, OnExit, OnChange, OnKeyDown (lub OnKeyPress) i OnKeyUp.

Komponenty ListBox i ComboBox

ListBox i ComboBox są również powszechnie stosowanymi komponentami. Komponent ListBox reprezentuje standardową listę wyboru w Windows. Jeżeli lista zawiera więcej elementów, niż jest w stanie jednocześnie wyświetlić, dostęp do pozostałych jest możliwy dzięki paskom przewijania.

0x01 graphic

Niektóre listy mogą mieć tę cechę, że każdy z ich elementów rysowany w sposób specyficzny, określony przez programistę (nosi to w oryginale nazwę owner-drawing).

Jeżeli zajdzie taka potrzeba, możesz sam utworzyć listy „ręcznie rysowane”. Chociaż możesz sobie nie zdawać z tego sprawy, utworzenie takiej listy jest w miarę proste. W rozdziale czwartym rozmawialiśmy o modyfikowaniu paska narzędzi Delphi według własnych potrzeb. Częścią tej dyskusji było zapoznanie się z oknem dialogowym edytora paska narzędzi Delphi. Okno to składa się z dwóch list (rysunek 7.4).

Rysunek 7.4.

Pole listy Commands w oknie edytora paska narzędzi jest rysowane w sposób „ręczny”

0x01 graphic

Lista po lewej stronie jest listą standardową; jej zawartość stanowią nazwy grup przycisków. Lista po prawej stronie jest listą rysowaną w sposób „ręczny”. Pokazuje ona rzeczywisty wygląd przycisków, jaki przyjmą on po umieszczeniu na pasku narzędzi, a także tekstowe opisy pełnionych przez nie funkcji.

Specjalizowanymi listami są listy rozwijalne typu combo. W rzeczywistości lista combo jest kombinacją listy i kontrolki edycyjnej. Użytkownik może wybrać element z listy lub wpisać wartość w polu edycji. Gdy użytkownik wybierze element z listy, zostanie on umieszczony w kontrolce edycji. Istnieją trzy różne typy obiektów combo - przedstawia je tabela 7.5. Właściwością określającą ten typ jest właściwość Style.

Tabela 7.5. Typy obiektów combo

Element

Opis

Simple

Styl prosty (simple) to nic więcej jak kontrolka edycyjna umieszczona na szczycie pola listy. Użytkownik może wybrać jeden z elementów listy lub wpisać tekst w pole edycji.

Drop-down

Styl podobny do prostego poza tym, że pole listy nie jest początkowo wyświetlane. Zamiast tego dodawany jest przycisk rozwinięcia, umożliwiający użytkownikowi wyświetlenie listy i wybranie z niej elementu. Oprócz tego użytkownik może również wpisać tekst w pole edycji.

Drop-down list

Jest to najbardziej ograniczający styl obiektu combo. Tak jak w przypadku stylu drop-down, lista jest początkowo niewidoczna. Użytkownik może kliknąć na przycisku rozwinięcia w celu wyświetlenia listy i wybrać z niej dowolny element, ale nie ma możliwości wpisania tekstu w pole edycji. Używaj tego pola kiedy chcesz, aby użytkownik mógł dokonywać wyboru jedynie z góry określonego zakresu możliwości.

Kod źródłowy przeznaczony dla tej książki zawiera program o nazwie ComboTst ilustrujący różne typy obiektów combo. Program w działaniu został przedstawiony na rysunku 7.5. Uruchom go i wypróbuj wszystkie pola combo aby przekonać się, w jaki sposób funkcjonują.

Rysunek 7.5.

Program ComboTst

0x01 graphic

Właściwości wspólne dla pól list i obiektów combo zestawione zostały w tabeli 7.6.

ListBox i ComboBox - podobnie jak inne komponenty edycji, którym przyglądaliśmy się uprzednio - posiadają bardzo niewiele metod. Metoda Clear czyści wszelkie dane zapisane w kontrolce. ItemAtPos zwraca element listy znajdujący się na pozycji wskazywanej przez współrzędne x i y. SelectAll zaznacza tekst znajdujący się w edycyjnej części obiektu combo.

Najczęściej używanymi zdarzeniami podczas pracy z obiektami combo i listami są OnChange i OnClick. Używaj ich aby sprawdzać, czy dokonano wyboru z listy.

0x01 graphic

Kliknięcie na części edycyjnej obiektu combo lub na przycisku rozwinięcia nie powoduje wysłania zdarzenia OnClick. Źródłem tego zdarzenia jest jedynie kliknięcie na obszarze listy obiektu combo.

Tabela 7.6. Właściwości list i obiektów combo

Właściwość

Odnosi się do …

Opis

Właściwości dostępne na etapie projektowania

Columns

ListBox

Zawiera liczbę kolumn w liście. Możliwe jest utworzenie kilku kolumn przez nadanie tej właściwości wartości większej niż 1.
Wartość domyślna: 0.

ExtendedSelection

ListBox

Określa możliwość stosowania rozszerzonego wyboru. Rozszerzony wybór pozwala użytkownikowi na wielokrotny wybór elementów za pomocą kombinacji Shift+klik i Ctrl+klik. Właściwość ta przestaje mieć znaczenie jeżeli wartością właściwości
MultiSelect jest False.
Wartość domyślna: True.

IntegralHeight

ListBox

Przy wartości True wysokość listy będzie
modyfikowana tak, aby uniknąć wyświetlania
niepełnych wierszy. Wartość domyślna: False.

ItemHeight

ListBox, ComboBox

Wykorzystywana w przypadku „ręcznie” rysowanych pól list i obiektów combo. Określa wysokość elementów w kontrolce. Wartość domyślna: 13.

Items

ListBox, ComboBox

Obiekt klasy TStrings zawierający zbiór elementów listy. (Opis właściwości i metod tej klasy znajduje się we wcześniejszej części tego rozdziału, w sekcji „TStrings”.)

MaxLength

ComboBox

Maksymalna liczba znaków, jaką użytkownik może wpisać w części edycyjnej.

MultiSelect

ListBox

Przy wartości True możliwy jest wybór wielu elementów jednocześnie. Wartość domyślna: False.

Sorted

ListBox, ComboBox

Przy wartości True elementy listy są sortowane w porządku rosnącym. W przypadku wartości False elementy listy są nieposortowane. Wartość domyślna. False.

Style

ComboBox

Styl obiektu combo. Możliwe wartości to csSimple, csDropDown, csDropDownList, csOwnerDrawFixed i csOwnerDrawVariable. (Opis trzech podstawowych stylów znaleźć można w tabeli 7.5) Wartość domyślna: csDropDown.

ListBox

Style listy - możliwe wartości to: lbStandard, lbOwnerDrawFixed i lbOwnerDrawVariable. Wartość domyślna: lbStandard.

cd. na następnej stronie

Tabela 7.6. cd. Właściwości list i obiektów combo

Właściwość

Odnosi się do …

Opis

TabWidth

ListBox

W polu listy może być stosowana tabulacja. Właściwość określa szerokość tabulacji w pikselach. Wartość domyślna: 0.

Text

ComboBox

Przechowuje tekst znajdujący się w części edycyjnej obiektu combo.

Właściwości dostępne w czasie wykonania

ItemIndex

ListBox

Przechowuje indeks aktualnie wybranego
elementu; pierwszy element listy ma indeks 0. Gdy żaden element nie jest wybrany, właściwość ta ma wartość -1. Przypisanie wartości właściwości ItemIndex powoduje automatyczne wybranie odnośnego elementu.

SelCount

ListBox

Zawiera liczbę elementów zaznaczonych na liście (umożliwiającej wybór wielu elementów).

Selected

ComboBox

Zwraca wartość True jeżeli określony element jest elementem wybranym i False w przeciwnym razie.

SelLength

ComboBox

Zawiera długość tekstu wybranego aktualnie w edycyjnej części obiektu combo.

SelStart

ComboBox

Zawiera indeks pierwszego znaku zaznaczonego tekstu w kontrolce edycyjnej (pierwszy znak w kontrolce ma indeks 0).

SelText

ComboBox

Przechowuje aktualnie zaznaczony tekst
w kontrolce edycyjnej.

TopIndex

ListBox

Przechowuje indeks pierwszego (od góry)
wyświetlanego elementu listy.

Zdarzenie OnChange może zostać wykorzystane do wykrywania zmian zachodzących w części edycyjnej obiektu combo w taki sam sposób, jak w przypadku kontrolek edycyjnych. Zdarzenie OnDropDown służy do wykrywania kliknięcia na przycisku rozwinięcia listy obiektu combo, zaś zdarzenia OnMeasureItem i OnDrawItem służą do samodzielnego rysowania elementów list i obiektów combo.

Typy przycisków biblioteki VCL

Biblioteka VCL zawiera kilka typów przycisków, które można wykorzystać we własnych aplikacjach. Pomimo, iż nie wszystkie z nich opierają się na standardowych kontrolkach przycisków Windows, zamierzam przedstawić tutaj ich kompletną listę. Zanim jednak przejdziemy do omówienia konkretnych komponentów przycisków, zajmijmy się na początek wiadomościami podstawowymi.

0x01 graphic

Ustawiając właściwość Caption przycisku skorzystaj ze znaku „&”, tak jak w przypadku ustawiania tej wartości dla elementu menu. Znak następujący po znaku & zostanie podkreślony i będzie służył jako tzw. akcelerator dla przycisku.

Właściwości przycisku

Komponenty przycisków posiadają jedynie cztery właściwości warte wzmianki:

Właściwość ModalResult

Właściwość ModalResult udostępnia wbudowane mechanizmy zamykania formularzy wyświetlanych za pomocą metody ShowModal. Domyślnie wartością ModalResult jest mrNone (równoważna liczbie 0). Korzystaj z tej wartości w przypadku zwykłych przycisków, które nie powodują zamknięcia formularza. Jeżeli właściwości ModalResult nadana zostanie wartość niezerowa, naciśnięcie przycisku spowoduje zamknięcie formularza i zwrócenie tej wartości. Przykładowo, jeżeli w formularzu umieścisz przycisk i nadasz jego właściwości ModalResult wartość mrOk, po jego kliknięciu formularz zostanie zamknięty, a metoda ShowModal zwróci wartość mrOk (czyli 1). Wziąwszy pod uwagę powyższe wiadomości możesz zrobić rzecz następującą:

var

Res : Integer;

begin

Res := MojForm.ShowModal;

if Res = mrOk then

WykonajOkresloneZadania;

if Res = mrCancel then

Exit;

end;

W tabeli 7.7 przedstawione zostały wartości właściwości ModalResult zdefiniowane w bibliotece VCL.

0x01 graphic

W przypadku własnych przycisków nie masz obowiązku korzystania ze stałych predefiniowanych właściwości ModalResult; możesz użyć dowolnej wartości, jaką sobie zażyczysz. Powiedzmy dla przykładu, że dysponujesz własnym oknem dialogowym, które może być zamknięte przy użyciu określonego zbioru przycisków. Każdemu z nich powinieneś wtedy przypisać inną wartość właściwości ModalResult (np. 100, 150 i 200). Dzięki takiemu rozwiązaniu będzie wiadomo, który z przycisków spowodował zamknięcie formularza. Właściwość może przyjąć dowolną wartość niezerową, nie przekraczającą zakresu typu Integer.

Tabela 7.7. Stałe właściwości ModalResult zdefiniowane w VCL

Stała

Wartość

mrNone

0

mrOk

1

mrCancel

2

mrAbort

3

mrRetry

4

mrIgnore

5

mrYes

6

mrNo

7

mrAll

8

mrNoToAll

9

mrYesToAll

10

Demonstracja użycia właściwości ModalResult została przedstawiona w programie ButtonTst dołączonym do książki. Program umożliwia uruchomienie formularza zawierającego kilka przycisków. Kliknięcie dowolnego przycisku spowoduje wyświetlenie wartości właściwości ModalResult w oknie głównego formularza.

Właściwość Default

Default jest kolejną kluczową właściwością przycisków. System Windows posiada standardowy mechanizm obsługi okien dialogowych. Jedna z cech tego mechanizmu przedstawia się następująco: jeżeli stan aktywności (związany z klawiaturą) należy do obiektu innego niż przycisk, a użytkownik naciśnie klawisz Enter, okno dialogowe zachowa się tak, jakby użytkownik nacisnął przycisk domyślny.

Domyślny przycisk jest to przycisk z ustawionym stylem BS_DEFPUSHBUTTON (zazwyczaj jest to przycisk OK). Cecha ta jest od lat zmorą wszystkich programistów i przekleństwem personelu zajmującego się wprowadzaniem danych. Właściwość Default służy do ustawienia domyślnego przycisku formularza. Jej domyślną wartością jest False. Aby uczynić przycisk domyślnym wystarczy nadać jego właściwości Default wartość True. Jeżeli jawnie nie nadasz żadnemu z przycisków wartości True jego właściwości Default, formularz nie będzie zamykany w wyniku naciśnięcia klawisza Enter.

0x01 graphic

Przed zamknięciem formularza w wyniku naciśnięcia klawisza Enter wywoływana jest procedura obsługująca zdarzenie OnClick przycisku domyślnego (o ile taki istnieje).

Właściwość Cancel

Właściwość Cancel współpracuje z klawiszem Esc w sposób przypominający współdziałanie właściwości Default z klawiszem Enter. Gdy użytkownik zamknie formularz naciskając klawisz Esc, wartością zwróconą przez metodę ShowModal będzie wartość właściwości ModalResult przycisku, którego właściwość Cancel jest ustawiona na wartość True. Jeżeli żaden z przycisków nie ma ustawionej wartości True, zamknięcie formularza klawiszem Esc będzie sygnalizowane zwróceniem wartości mrCancel (czyli liczby 2 - patrz tabela 7.7).

0x01 graphic

Jak należałoby się spodziewać, również zakończenie pracy formularza kliknięciem na systemowej ikonie zamknięcia lub naciśnięciem kombinacji klawiszy Alt+F4 spowoduje zwrócenie wartości mrCancel przez metodę ShowModal. Niemniej jednak naciśnięcie klawisza Esc zaowocuje zwróceniem wartości właściwości ModalResult, jaką posiadał przycisk z ustawioną na True właściwością Cancel. Przed zamknięciem formularza wywołana zostanie funkcja obsługująca zdarzenie OnClick tegoż przycisku. Żadna metoda obsługująca zdarzenie OnClick nie zostanie wywołana, jeżeli zamknięcie nastąpi w wyniku naciśnięcia kombinacji Alt+F4 lub kliknięcia na ikonie systemowej. Upewnij się, że przewidziałeś wszystkie możliwe sposoby postępowania ze swoim formularzem, jakich użyć (lub nadużyć) może użytkownik.

0x01 graphic

Nic nie stoi na przeszkodzie, aby utworzyć kilka przycisków z właściwością Default ustawioną na wartość True. Analogicznie, może istnieć kilka przycisków z właściwością Cancel ustawioną na wartość True. Niemniej jednak, kiedy użytkownik naciśnie klawisz Enter, uaktywniony zostanie pierwszy - w porządku zgodnym z klawiszem Tab - przycisk, którego właściwość Default jest ustawiona na wartość True. I analogicznie - kiedy naciśnięty zostanie klawisz Esc, wartością zwróconą przez metodę ShowModal będzie wartość właściwości ModalResult pierwszego w cyklu Tab przycisku o właściwości Cancel ustawionej na True.

Właściwość Enabled

Właściwość ta została już wspomniana wcześniej podczas ogólnych rozważań na temat komponentów. Jest ona często stosowana w odniesieniu do przycisków, aby móc udostępniać i blokować je w zależności od bieżącego stanu programu lub określonego formularza. Kiedy przycisk jest zablokowany (jego właściwość Enabled jest ustawiona na False), znajdujący się na nim tekst jest przyciemniony, sam zaś przycisk po prostu nie funkcjonuje. W przypadku przycisków zawierających bitmapy (BitBtn i SpeedButton) również bitmapa jest automatycznie przyciemniana.

Komponenty przycisków posiadają tylko jedną metodę godną uwagi: jest nią metoda Click, która symuluje kliknięcie myszą. Wywołanie metody Click danego przycisku powoduje wykonanie metody obsługującej zdarzenie OnClick tak, jakby użytkownik rzeczywiście kliknął na przycisku. Jeżeli chodzi o zdarzenia, zazwyczaj jedynym wykorzystywanym jest OnClick.

Przyjrzyjmy się teraz różnym komponentom przycisków, jakie udostępnia Delphi.

Komponent Button

Standardowy komponent Button można porównać z aktorem Dannym De Vito: wcale nie jest ładny, a mimo to dostaje wiele ofert pracy. Naprawdę niewiele więcej można dodać na temat standardowego komponentu Button. Posiada on domyślną wysokość (właściwość Height) równą 25 pikseli i domyślną szerokość (Width) równą 75 pikseli. Zazwyczaj przycisk taki umieszcza się w formularzu, oprogramowuje jego zdarzenie OnClick - i na tym koniec.

Komponent BitBtn

BitBtn jest perfekcyjnym przykładem pokazującym w jaki sposób można rozszerzyć komponent dając użytkownikom nowe możliwości. W tym przypadku standardowy komponent Button został rozszerzony o możliwość wyświetlania bitmapy na swojej powierzchni.

Komponent BitBtn posiada kilka dodatkowych właściwości w porównaniu z tym co oferuje komponent Button. Wszystkie te właściwości współpracują ze sobą przy zarządzaniu bitmapą znajdującą się na przycisku, a także sterują położeniem bitmapy i tekstu na przycisku. Wyjaśnienia tych właściwości znajdują się w kolejnych sekcjach książki.

Właściwość Glyph

Właściwość Glyph reprezentuje bitmapę na przycisku. Wartością właściwości Glyph jest rysunek lub wzorzec.

0x01 graphic

Wzorzec (ang. glyph) jest to rysunek zwykle reprezentowany przez plik bitmapy w formacie Windows BMP.

Wzorzec sam w sobie składa się z jednej lub kilku bitmap reprezentujących cztery stany (górny, dolny, nieaktywny i przytrzymany) w jakich znaleźć może się przycisk. Jeżeli budujesz swoje własne przyciski, prawdopodobnie bez problemu poradzisz sobie z utworzeniem zaledwie jednego wzorca, który zostanie następnie uzupełniony przez komponent BitBtn o pozostałe trzy możliwości. Po kliknięciu bitmapa będzie przesuwać się w prawo i w dół, natomiast po przejściu w stan nieaktywny zostanie przyciemniona. Wzorzec pozycji w stanie przytrzymania będzie identyczny jak w stanie górnym, chociaż oblicze przycisku zmieni się, aby nadać mu wygląd wciśnięcia.

Jeżeli zdecydujesz się utworzyć więcej niż jeden wzorzec, wszystkie one będą musiały mieć jednakową wysokość i szerokość, a także będą musiały być umieszczone na wspólnym pasku bitmapy. Bitmapy wchodzące w skład pakietu Delphi składają się z dwóch wzorców. Na rysunku 7.6. przedstawiona została bitmapa przycisku drukowania dostarczona razem z Delphi (print.bmp). Po prawej stronie znajduje się przycisk drukowania w naturalnej skali, z kolei po lewej stronie widnieje jego powiększenie ukazujące szczegóły. Zauważ, że każdy ze wzorców zajmuje taką samą przestrzeń bitmapy.

Aby ustawić ikonę dla komponentu BitBtn, należy kliknąć podwójnie na kolumnie Value w Inspektorze Obiektów obok właściwości Glyph. Wyświetlone zostanie okno edytora Picture Editor umożliwiające wybór bitmapy która posłuży jako ikona dla przycisku.

Rysunek 7.6.

Bitmapa PRINT.BMP

0x01 graphic

0x01 graphic

Piksel w lewym dolnym rogu bitmapy reprezentuje barwę, która będzie stosowana jako kolor przezroczysty. Wszelkie piksele bitmapy w tym kolorze staną się przezroczyste, gdy ikona zostanie wyświetlona na przycisku. Należy pamiętać o tym projektując własne bitmapy. Jeżeli nie chcesz w ogóle stosować barwy przezroczystej, wtedy piksel w lewym dolnym rogu będzie musiał przyjąć kolor nie używany nigdzie indziej w bitmapie. Jeżeli zależy nam na tym, aby nie stosować lewego dolnego piksela jako koloru przezroczystego, wtedy właściwości TransparentMode musimy nadać wartość tmFixed, a następnie wyspecyfikować kolor przezroczysty poprzez właściwość TransparentColor.

0x01 graphic

Standardowe ikony przycisków dostarczane razem z Delphi posiadają wymiary 15 × 15 pikseli. Rozmiar taki doskonale pasuje do standardowej wysokości przycisku, wynoszącej 25 pikseli. Tworzone samodzielnie ikony mogą mieć dowolny rozmiar, należy jednak pamiętać o tym, że komponent BitBtn nie podejmuje żadnych prób dopasowania rozmiaru przycisku do rozmiaru bitmapy. Dlatego, jeżeli użyjesz większej bitmapy, będziesz musiał odpowiednio zwiększyć rozmiar przycisku.

Właściwość Kind

Właściwość Kind jest bardzo dogodną cechą komponentu BitBtn umożliwiającą wybór jednego spośród kilku predefiniowanych typów przycisków. Wartością domyślną właściwości Kind jest bkCustom wskazująca, iż to programista dostarczy odpowiednią bitmapę i ustawi wszelkie inne właściwości przycisku. Wybranie dowolnego innego typu przycisku zaowocuje wystąpieniem pięciu następujących zdarzeń:

Przykładowo, jeżeli wartość właściwości Kind ustawimy na bkOK, przycisk stanie się przyciskiem OK. Ikona zmieni się na zielony znak zaznaczenia, właściwość Cancel zostanie ustawiona na wartość False, właściwości Default przypisana zostanie wartość True, właściwość ModalResult przyjmuje wartość mrOk, właściwości Caption przypisana zostanie wartość „OK" - a końcowy rezultat uwidoczni się na formularzu. Zawsze istnieje możliwość ręcznego zmodyfikowania właściwości ustawionych przez zmianę wartości w polu Kind, ale zwykle nie ma takiej potrzeby. Na rysunku 7.7 widoczny jest program Button Test (należący do kodu książki), z wyświetlonym formularzem BitBtn Test. Formularz ten zawiera wszystkie predefiniowane typy przycisków oraz jeden przycisk użytkownika.

Rysunek 7.7.

Predefiniowane typy komponentu BitBtn

0x01 graphic

Właściwość Layout

Właściwość Layout określa położenie ikony względem tekstu przycisku. Wartością domyślną jest blGlyphLeft (bitmapa po lewej stronie tekstu). Ikonę można również umieścić z prawej strony tekstu, nad tekstem i pod tekstem.

Właściwość Margin

Właściwość Margin określa margines między ikoną, a krawędzią (którą - to zależy od właściwości Layout). Wartość domyślna (równa -1) centruje ikonę i tekst względem przycisku. Dowolna wartość dodatnia powoduje ustawienie rzeczywistego marginesu (w pikselach).

Właściwość NumGlyphs

Właściwość NumGlyphs określa ilość wzorów ikon zapisanych na pasku bitmapy dla określonego przycisku. Jak zostało to wspomniane wcześniej, można dostarczyć od jednego do czterech wzorców. Muszą one występować na pasku bitmapy według określonego porządku: górny, dolny, nieaktywny, przytrzymany.

Właściwość Spacing

Właściwość Spacing określa odległość w pikselach między ikoną a tekstem przycisku. Wartość domyślna wynosi cztery piksele.

Komponent SpeedButton

Komponent SpeedButton został zaprojektowany do współpracy z komponentem Panel przy budowie pasków narzędzi. Różnica między nim, a komponentami Button i BitBtn jest taka, że nie jest on komponentem okienkowym - a więc nie może przyjąć stanu aktywności i nie można przejść do niego przy użyciu klawisza Tab.

Z drugiej strony, komponent SpeedButton posiada kilka cech wspólnych z komponentem BitBtn. Sposób korzystania przez komponent SpeedButton z właściwości Glyph jest dokładnie taki sam jak w przypadku komponentu BitBtn, dlatego nie będzie on tutaj omawiany po raz wtóry. Oprócz podobieństw istnieją jednak również pewne istotne różnice; przyjrzymy im się dokładniej.

Domyślnie przycisk SpeedButton posiada wymiar 25×25 pikseli. Tworzone samodzielnie przyciski mogą posiadać dowolny wymiar i zawierać tekst, chociaż zwyczajowo przyciski SpeedButton tekstu nie zawierają. Ich najważniejsze właściwości opisane zostały w poniższych sekcjach.

0x01 graphic

Tworzenie pasków narzędzi w Delphi 1 polegało na włączania do komponentu Panel różnorodnych komponentów, głównie przycisków SpeedButton. Delphi 4 oferuje w tym celu komponent ToolBar posiadający kilka dodatkowych zalet, co jednak czyni go nieco bardziej skomplikowanym w użyciu.

GroupIndex

Przyciski SpeedButton mogą być grupowane tak, aby zachowywały się jak przyciski opcji (przyciski opcji będą omawiane w dalszej części tego rozdziału w sekcji „Przyciski opcji i pola wyboru”). Po naciśnięciu jednego z przycisków danej grupy przycisk ten pozostaje w pozycji wciśniętej, natomiast przycisk poprzednio wciśnięty powraca do pozycji normalnej. Aby utworzyć grupę przycisków wystarczy przypisać dowolną wartość właściwości GroupIndex każdego z nich. (Wartość domyślna równa zero oznacza, że przycisk nie należy do żadnej grupy.) Dla lepszego zrozumienia tego zagadnienia spróbuj wykonać następujące ćwiczenie:

  1. Utwórz pusty formularz i umieść w jego wnętrzu pięć przycisków SpeedButton. (Nie będziemy przejmować się dodawaniem ikon do przycisków w tym prostym ćwiczeniu, ale jeśli chcesz możesz zrobić to sam).

  1. Wybierz wszystkie przyciski i zmień wartość ich właściwości GroupIndex na 1.

Opcjonalnie: zmień właściwość Down jednego z przycisków na wartość True.

  1. Skompiluj i uruchom program kliknięciem na przycisku Run.

Po wystartowaniu programu kliknij na kilku przyciskach. Zauważysz, że tylko jeden z nich może w danej chwili znajdować się w pozycji wciśniętej. Widoczna jest również zmiana zachowania przycisków po przypisaniu właściwości GroupIndex wartości niezerowej. Przycisk, którego właściwość GroupIndex jest równa zero w następstwie kliknięcia powraca do pozycji wyjściowej, podczas gdy kliknięcie na przycisku wchodzącym w skład grupy sprawia, iż pozostaje on w pozycji wciśniętej.

AllowAllUp

Domyślnie jeden z przycisków grupy musi pozostawać przez cały czas w pozycji wciśniętej. Można zmienić to zachowanie ustawiając właściwość AllowAllUp na wartość True. Wykonanie takiej operacji dla jednego z przycisków spowoduje automatyczną zmianę wartości AllowAllUp wszystkich przycisków grupy na wartość True. Od tej chwili w grupie może być wybrany jeden z przycisków lub żaden z nich.

0x01 graphic

Niekiedy zachodzi potrzeba użycia przycisku SpeedButton jako przełącznika. Przycisk przełączający służy do włączania lub wyłączania pewnej opcji i nie należy do żadnej grupy. Aby z pojedynczego przycisku SpeedButton uczynić przycisk przełączający należy ustawić jego właściwość GroupIndex na wartość niezerową, a właściwości AllowAllUp nadać wartość True. Jednocześnie trzeba upewnić się, że wartość przypisana właściwości GroupIndex nie jest używana przez inne komponenty formularza. Gdy użytkownik kliknie na takim przycisku, przycisk ten pozostanie wciśnięty. Ponowne kliknięcie spowoduje powrót do stanu pierwotnego.

Down

Odczyt właściwości Down udostępnia wartość True jeżeli w danej chwili przycisk znajduje się w pozycji wciśniętej i False w przeciwnym wypadku. Przypisanie właściwości Down nowej wartości spowoduje automatycznie adekwatną zmianę stanu przycisku (naciśnięty/ zwolniony). Nie dają jednak efektu zmiany właściwości Down przycisku nie należącego do żadnej grupy.

Przyciski opcji i pola wyboru

Mimo, że przyciski opcji i pola wyboru są kontrolkami specjalizowanymi, nie zmienia to w niczym faktu, iż są one przyciskami. Ze względu na prostotę ich implementacji nie poświęcimy im zbyt dużo czasu. Obydwa komponenty - RadioButton i CheckBox - posiadają właściwość o nazwie Checked, która może posłużyć do ustawienia stanu zaznaczenia, a także być odczytana w celu ustalenia jej bieżącego stanu.

Przyciski opcji zwyczajowo stosowane są w grupach. Typowo przyciski opcji znajdują zastosowanie dla grupy opcji z których w danej chwili może być wybrana tylko jedna (sytuacja podobna do grupy przycisków SpeedButton, o których mowa była przed chwilą). Nic nie stoi na przeszkodzie w użyciu pojedynczego, osamotnionego przycisku opcji, nie jest to jednak polecane ze względu na zamieszanie jakie może powstać wśród użytkowników. Kiedy zachodzi potrzeba użycia pojedynczego przycisku opcji, zamiast niego należy użyć pola wyboru - ponieważ właśnie do tego celu ono służy.

Przyciski opcji umieszczane w formularzu będą automatycznie traktowane jako część tej samej grupy. Jeżeli zachodzi potrzeba wyodrębnienia więcej niż jednej grupy przycisków opcji i grupy te muszą funkcjonować niezależnie od siebie, wtedy należy użyć komponentu RadioGroup. Komponent tego typu umożliwia szybkie ustawienie grupy przycisków opcji razem z otaczającą je trójwymiarową ramką i etykietą. Zobrazujmy te wiadomości następującym ćwiczeniem:

  1. Utwórz nowy formularz lub skorzystaj z utworzonego w poprzednim ćwiczeniu. Do formularza dodaj komponent RadioGroup (rezydujący na stronie Standard).

  1. Zlokalizuj właściwość Items i kliknij na niej podwójnie w kolumnie Value.

  2. Wyświetlony zostanie edytor listy łańcuchów (String list editor). Wpisz następujące linie tekstu:

Dwójkowo

Ósemkowo

Dziesiętnie

Szesnastkowo

  1. Zamknij okno edytora kliknięciem na przycisku OK. Ramka grupująca została wypełniona przyciskami opcji zawierającymi wpisany przez Ciebie tekst.

  2. Zmień właściwość Caption ramki grupującej na Wyświetlaj wyniki:.

  3. Uruchom program kliknięciem na przycisku Run.

Przycisk, na którym kliknięto, przejmuje stan aktywności od przycisku, który był aktywny do tej pory. Stosując komponent RadioGroup można umieścić w formularzu więcej niż jedną grupę przycisków. Komponent RadioGroup, podobnie jak lista i obiekt combo, posiada właściwość ItemIndex, którą można odczytywać w trackie pracy programu w celu określenia, który z elementów grupy jest wybrany. Można również ustawić tę właściwość, wymuszając w ten sposób wybranie odpowiedniego przycisku opcji. Być może zwróciłeś uwagę na fakt, iż w chwili uruchomienia programu żaden z przycisków nie był wybrany. Korzystając z Inspektora Obiektów zmień wartość właściwości ItemIndex na 0 i uruchom ponownie program. Tym razem wybrany będzie pierwszy przycisk opcji.

0x01 graphic

Do grupowania przycisków opcji można również wykorzystać komponent GroupBox. Komponent ten jest mniej wygodny w użyciu niż RadioGroup, ale za to jest bardziej elastyczny. W ramce grupującej tego typu można umieścić dowolne typy kontrolek. Po umieszczeniu kontrolek we wnętrzu ramki grupującej zarówno one jak i sama ramka mogą być przesuwane w trakcie projektowania jako całość.

Komponent CheckBox, stanowiący pole wyboru, umożliwia użytkownikom włączanie lub wyłączanie określonej opcji lub wskazuje na fakt aktywności lub nieaktywności opcji w danej chwili. Pole wyboru może przyjmować maksymalnie dwa lub trzy stany (w zależności od swojego stylu): aktywny, nieaktywny i przyciemniony. Jeżeli właściwość AllowGrayed pola wyboru jest ustawiona na wartość False, może ono być jedynie aktywne lub nieaktywne. Gdy wartość tej właściwości wynosi True, pole wyboru może przyjmować dodatkowo stan przyciemnienia; stan ten, zwany też stanem nieokreślonym, jest obsługiwany w sposób programowy.

Innymi słowy - do programisty należy określenie, co dla aplikacji znaczy stan przyciemnienia pola. Kiedy wartością właściwości AllowGrayed jest False (domyślnie), do określenia stanu pola można wykorzystać właściwość Checked. Jeżeli AllowGrayed posiada wartość True, do określenia stanu pola wyboru trzeba posłużyć się właściwością State, która może zwrócić jedną z trzech wartości: cbChecked (aktywne), cbUnchecked (nieaktywne), cbGrayed (przyciemnione).

0x01 graphic

Niekiedy konieczne okazuje się zobrazowanie stanu pewnej opcji, jednak z zablokowaną możliwością jej zmiany; reprezentujące opcję pole wyboru powinno posiadać normalny wygląd, nie powinno jednak reagować na klikanie. Rozwiązaniem jest umieszczenie pola wyboru w Panelu i ustawienie na False właściwości Enabled tego Panelu.

Komponent Label

Komponent Label służy do wyświetlania tekstu w formularzu. Czasami tekst ten jest określany w fazie projektowania i później nie ulega już zmianom. W innych przypadkach, etykieta zachowuje się w sposób dynamiczny, ulegając zmianom w trakcie pracy, w sposób zależny od przebiegu programu. Do zmiany tekstu etykiety w trakcie pracy programu należy korzystać z właściwości Caption. Komponent Label nie posiada żadnych specjalizowanych metod poza tymi, którymi dysponują inne komponenty. Właściwości specyficzne dla komponentu Label przedstawione zostały w tabeli 7.8.

Tabela 7.8. Właściwości komponentu Label

Właściwość

Opis

AutoSize

Przy wartości True etykieta automatycznie zmienia swój rozmiar dopasowując się do tekstu zawartego we właściwości Caption. Jeżeli wartością jest False, tekst wystający poza prawą krawędź jest obcinany. Wartość domyślna: True.

Tabela 7.8. cd. Właściwości komponentu Label

Właściwość

Opis

FocusControl

Etykieta jest komponentem nieokienkowym, nie może więc przyjąć stanu aktywności i nie można tym samym przejść do niej przy użyciu klawisza Tab. Czasami jednak etykieta służy jako tekst dla kontrolki takiej jak np. pole edycji. Wtedy etykiecie można przypisać klawisz akceleratora (używając znaku &), a jej właściwości FocusChange przypisać komponent, do którego ma być kierowany stan aktywności, jeżeli ów klawisz akceleratora zostanie naciśnięty.

ShowAccelChar

Należy nadać jej wartość True jeżeli chcemy aby znak ampersanda (&) w tekście etykiety (Caption) był traktowany na równi z innymi znakami (a nie jako znacznik akceleratora). Wartość domyślna: True.

Transparent

Kiedy właściwość ta jest ustawiona na True ignorowana jest właściwość Color i wszystko, co znajduje się pod etykietą, staje się przezroczyste. Właściwość ta przydaje się na przykład przy umieszczaniu etykiet na tle stworzonym z bitmapy. Wartość domyślna: False.

WordWrap

Przy wartości True tekst we wnętrzu etykiety będzie zawijany do nowej linii, gdy osiągnie jej prawą krawędź. Wartość domyślna: False.

0x01 graphic

Kolejnym typem etykiety jest komponent StaticText (na stronie Additional). Rożni się on tym od zwykłego komponentu Label, że jest komponentem okienkowym (jest z nim skojarzony uchwyt okna). Komponent ten umożliwia m.in. związanie klawisza akceleratora z etykietą bez pomocniczego wiązania jej z inną kontrolką (jak to było w przypadku TLabel). Ponadto niektóre pożyteczne operacje z użyciem Win32 API odnoszą się do konkretnego okna i jako takie wymagają właśnie uchwytu - którego komponent Label nie posiada.

Komponent ScrollBar

Komponent ScrollBar reprezentuje samodzielny pasek przewijania. Samodzielność polega na tym, że nie jest on związany z żadną kontrolką edycji, listą lub jakimkolwiek innym komponentem. Nie stwierdziłem również, aby kontrolka ta była stosowana bardzo często przeze mnie. Oczywiście istnieją określone typy aplikacji, które nagminnie wykorzystują tego typu komponenty, niemniej jednak w przypadku prostych aplikacji tworzonych z dnia na dzień ich wykorzystanie jest marginalne.

Sposób pracy paska przewijania określają właściwości Min, Max, LargeChange i SmallChange. Pozycja paska przewijania może zostać ustawiona lub pobrana poprzez właściwość Position. Właściwość Kind pozwala określić, czy pasek przewijania ma być pionowy, czy też poziomy.

Komponent Panel

Komponent Panel jest elementem napędowym Delphi. Możliwości wykorzystania paneli są niemal nieograniczone. Do ich zadań należy między innymi przechowywanie przycisków paska narzędzi, wyświetlanie etykiet tekstowych (takich jak tytuł formularza), wyświetlanie grafiki, jak również przechowywanie zwykłych przycisków. Jedną z zalet Panelu jest to, że umieszczone w nim komponenty stają się jego potomkami. Jako takie przemieszczają się zawsze tam, gdzie wędruje sam Panel. Cecha ta może być niezwykle pomocna zarówno w czasie projektowania jak i w uruchomionym programie.

Duża część funkcjonalności komponentu Panel wynika z jego właściwości Align. Załóżmy dla przykładu, że chcesz wyświetlić tytuł u samej góry formularza. Załóżmy ponadto, że życzysz sobie, aby tytuł był zawsze wycentrowany niezależnie od tego, w jaki sposób jego rozmiar zostanie zmieniony przez użytkownika. Wystarczy ustawić właściwość Align na wartość alTop, a właściwość Alignment na wartość taCenter, a tytuł będzie zawsze ułożony centralnie. Jak widać jest to bardzo proste.

Panel może przyjmować różnorodny wygląd. Zmianę wyglądu paneli umożliwiają jego właściwości: BevelInner, BevelOuter, BorderStyle i BorderWidth; efekty różnych opcji przedstawione zostały na rysunku 7.8.

Rysunek 7.8.

Przykład ukazujący różne style Panelu

0x01 graphic

Komponent Panel jest tak wszechstronny, iż rozpracowanie wszystkich jego możliwości wymaga nieco czasu.

To jeszcze nie wszystko...

Niestety, nie ma tutaj wystarczająco dużo miejsca na omówienie wszystkich komponentów, jakie oferuje Delphi. W rozdziale czwartym, podczas tworzenia programu przeglądarki plików graficznych, natknąłeś się na komponent Image. Również w rozdziale czwartym, w trakcie tworzenie okna dialogowego informacji o programie, miałeś okazję zapoznać się pokrótce z komponentem Bevel. W rozdziale szóstym, w trakcie ćwiczenia w ustawianiu komponentu, miałeś do czynienia z komponentem Shape. Są to tylko niektóre przykłady komponentów, które czekają na Ciebie. Każdy z nich wymagać wymaga przetestowania w celu określenia, jaką wartość użytkową sobą reprezentuje.

Istnieje jeszcze jedna grupa komponentów, która wymaga omówienia przed przejściem do innych zagadnień - grupa Dialog.

Standardowe okna dialogowe

Windows udostępnia zbiór standardowych okien dialogowych, z których korzystać może dowolny program pracujący w tym systemie; zaliczają się do nich między innymi:

Standardowe okna dialogowe znajdują się pod zakładką Dialogs Palety Komponentów. Komponenty te zaliczane są do niewidocznych, ponieważ nie dysponują one interfejsem wizualnym w fazie projektowania. Dalsze sekcje omawiają kolejno wszystkie ze wspomnianych okien dialogowych, z jednym wyjątkiem - okna dialogowe Drukuj i Ustawienia wydruku zostaną tutaj pominięte, ponieważ będzie o nich mowa w rozdziale trzynastym, podczas rozważań na temat procesu drukowania.

Metoda Execute

Jedną z cech, którą dzielą wszystkie standardowe okna dialogowe, jest metoda Execute, używana do tworzenia i wyświetlenia określonego okna. Okna wyświetlane są w sposób modalny, z wyłączeniem okien Znajdź i Zamień, które wyświetlane są niemodalnie. Metoda Execute zwraca wartość True jeżeli użytkownik kliknął na przycisku OK, podwójnie kliknął na nazwie pliku (w przypadku okien dialogowych plików) lub nacisnął klawisz Enter. Execute zwraca wartość False, jeżeli użytkownik kliknął na przycisku Cancel, nacisnął przycisk Esc lub zamknął okno dialogowe za pomocą przycisku systemowego. Standardowe okno dialogowe jest często implementowane w następujący sposób:

if OpenDialog.Execute then begin

{

użytkownik wybrał przycisk OK, więc można użyć nazwy pliku

}

Memo.Lines.LoadFromFile(OpenDialog.FileName);

{ wykonanie innych operacji }

end;

Powyższy kod wyświetla okno dialogowe Otwórz, umożliwiające wybór pliku przez użytkownika. Jeżeli użytkownik kliknął na przycisku OK, wykonywany jest blok instrukcji we wnętrzu instrukcji if, co oznacza załadowanie wybranego pliku do komponentu Memo. Jeżeli naciśniętym przyciskiem nie był OK, blok programu we wnętrzu instrukcji if jest ignorowany i w efekcie nie jest podejmowana żadna akcja.

0x01 graphic

Powyższy fragment kodu jest kolejnym przykładem skrótowej składni języka Object Pascal. Pierwsza linia kodu

if OpenDialog.Execute then begin

jest równoważna wyrażeniu

if OpenDialog.Execute = True then begin

Obydwie metody są dozwolone, ale preferowana jest pierwsza z nich.

Okna dialogowe Otwórz i Zapisz

Okna Otwórz i Zapisz posiadają kilka wspólnych właściwości. Okno Otwórz (rysunek 7.9) znajduje zastosowanie, gdy w naszej aplikacji chcemy umożliwić użytkownikom otwieranie plików. Okno Otwórz jest realizowane przez komponent OpenDialog. Okno Zapisz służy do uzyskania od użytkownika nazwy pliku w celu zapisania go. Jego odmianą jest okno Zapisz jako… . Komponentem realizującym okna Zapisz oraz Zapisz jako… jest SaveDialog.

Rysunek 7.9.

Typowe okno dialogowe Otwórz

0x01 graphic

Użytkowanie okien dialogowych plików jest w miarę proste w ich podstawowej formie. Posiadają one jednak pewne cechy, które wymagają wyjaśnienia, aby móc z nich w pełni korzystać. W kolejnych sekcjach znajduje się analiza właściwości specyficznych dla okien dialogowych plików.

0x01 graphic

Jedynym zadaniem jakie realizują komponenty OpenDialog i SaveDialog jest pobranie nazwy pliku od użytkownika. Właściwe wykorzystanie tej nazwy (np. otwarcie pliku i odczytanie jego zawartości) wymaga odrębnej akcji programisty.

Właściwość DefaultExt

Właściwość ta służy do określenia domyślnego rozszerzenia, z jakiego korzystać będzie okno dialogowe. Domyślne rozszerzenie jest to rozszerzenie dodawane automatycznie do nazw plików w przypadku, gdy nie zostanie ono wpisane przez użytkownika.

Właściwość FileName

Właściwość ta ma najbardziej oczywiste znaczenie wśród właściwości okna dialogowego plików. Przechowuje ona nazwę pliku wybranego przez użytkownika. Ustawienie jej przed wywołaniem okna dialogowego sprawi, że nazwa pliku zostanie wyświetlona w edycyjnej części okna, bezpośrednio po jego otwarciu. Po zamknięciu okna przez użytkownika kliknięciem na przycisku OK właściwość FileName będzie zawierać nazwę wybranego pliku oraz jego pełną ścieżkę dostępu.

Właściwość Files

Files - właściwość tylko do odczytu - jest obiektem klasy TStrings zawierającym listę wybranych plików, gdy dozwolony jest wybór wielu plików jednocześnie.

Właściwość Filter

Właściwość Filter zawiera listę typów plików, wśród których wybierać może użytkownik. Typy plików są wyświetlane w postaci listy rozwijalnej zatytułowanej Pliki typu: widocznej w oknie dialogowym plików. Właściwość Filter można ustawiać tak, aby odwzorować typy plików specyficzne dla tworzonej przez siebie aplikacji. Przykładowo, prosty program edytora tekstu mógłby posiadać filtr ustawiony na pliki typu .TXT, .INI i .LOG.

Filtr można z łatwością ustawić w fazie projektowania; do tego celu służy okno dialogowe edytora (Filter Editor) wywoływane podwójnym kliknięciem na kolumnie Value właściwości Filter w oknie Inspektora Obiektów. Edytor filtru dla okna otwierania pliku wypełniony danymi zaczerpniętymi z powyższego przykładu przedstawiony został na rysunku 7.10.

Kolumna Filter Name zawiera werbalny opis typu pliku. Kolumna Filter zawiera rzeczywistą maskę, która stosowana będzie do wyświetlania plików tego typu.

Rysunek 7.10.

Okno dialogowe edytora filtru

0x01 graphic

Chociaż łańcuch filtru może być wprowadzony bezpośrednio w kolumnie Value Inspektora Obiektów, łatwiej jest posłużyć się do tego celu oknem edytora. Jeżeli chcesz używać tylko jednego filtru, możesz wpisać go bezpośrednio w kolumnę Value właściwości Filter. Użyj znaku pipeline ( | ), aby oddzielić opis filtru od jego maski. Na przykład, aby utworzyć pojedynczy filtr dla wszystkich typów plików, należałoby wpisać następujący tekst:

Wszystkie pliki (*.*)|*.*

Właściwość FilterIndex

Właściwość FilterIndex służy do określenia filtru, który będzie używany bezpośrednio po wyświetleniu okna dialogowego. Właściwość zawiera indeks żądanego filtru (w kolejności, w jakiej pojawia się on w oknie edytora z rys. 7.10)

0x01 graphic

Pierwszy filtr na liście ma indeks 1, nie zero! Przykładowo, jeżeli (zgodnie z rysunkiem 7.10) domyślnym filtrem ma być filtr

Wszystkie pliki (*.*)|*.*

to właściwość FilterIndex powinna być ustawiona na wartość 4.

Właściwość InitialDir

Właściwość InitialDir określa katalog stosowany przez okno dialogowe plików jako początkowa lokalizacja w chwili jego wyświetlenia. Jeżeli właściwości tej nie zostanie nadana żadna wartość, użyty zostanie katalog bieżący (określony przez Windows).

0x01 graphic

Dobrze skonstruowane programy dla Windows pamiętają ostatni katalog, z którego użytkownik korzystał zarówno podczas otwierania jak i zapisywania plików. Informacja ta zazwyczaj przechowywana jest w Rejestrze. Aby zadbać o taki sam mechanizm w swoich aplikacjach, przed wyświetleniem okien Otwórz i Zapisz należałoby przypisać właściwości InitialDir katalog, z którego użytkownik ostatnio korzystał. Po wybraniu pliku przez użytkownika, w miarę potrzeby, trzeba uaktualnić Rejestr informacją o nowym katalogu.

Właściwość Options

Właściwość Options kontroluje sposób, w jaki używane jest okno dialogowe plików. Lista opcji jest zbyt długa, aby można było ją tutaj przedstawić; do jej podstawowych elementów zaliczają się: udostępnienie możliwości tworzenia nowych plików i katalogów, możliwość wyświetlenia przycisku pomocy w oknie dialogowym, zezwolenie na długie nazwy plików, zezwolenie na wybór wielu plików itp. Kompletną informację na ten temat znaleźć można w systemie pomocy, w części dotyczącej komponentów OpenDialog i SaveDialog.

Właściwość Title

Właściwość Title służy do ustawienia lub odczytania tytułu okna dialogowego plików. Jeżeli nie zostanie wyspecyfikowany żaden tytuł, używane będą nazwy standardowe: Otwórz dla komponentu OpenDialog i Zapisz dla komponentu SaveDialog.

0x01 graphic

Okno dialogowe Zapisz jako… nie jest niczym innym jak komponentem SaveDialog z właściwością Title ustawioną na wartość Zapisz jako….

Z oknami dialogowymi plików nie są skojarzone żadne zdarzenia.

0x01 graphic

Okno otwierania plików (jak każde inne standardowe okno dialogowe) może zostać zaimplementowane w trakcie pracy programu bez potrzeby umieszczania w formularzu komponentu OpenDialog. Aby tego dokonać, należy utworzyć obiekt klasy TOpenDialog, a następnie wywołać jego metodę Execute w następujący sposób:

procedure TForm1.Button1Click(Sender : TObject);

var

OpenDlg : TOpenDialog;

begin

OpenDlg := TOpenDialog.Create(Self);

if OpenDlg.Execute then begin

{przeprowadzanie niezbędnych operacji}

end;

OpenDlg.Free;

end;

W miarę potrzeby, przed wywołaniem metody Execute, można ustawić dowolne właściwości komponentu OpenDialog.

Okna dialogowe otwierania i zapisywania rysunków

Okna dialogowe File Open Picture i File Save Picture są niczym więcej jak zwykłymi oknami Otwórz i Zapisz z jedną dodatkową cechą, jaką jest okno podglądu, umożliwiające oglądanie aktualnie wybranego rysunku. Właściwość Filter tego typu

Rysunek 7.11.

Okno dialogowe otwierania plików graficznych

0x01 graphic

okien jest z góry ustawiona na formaty graficzne najczęściej występujące w Windows. Poza tym ich zachowanie jest identyczne jak w przypadku okien Otwórz i Zapisz. Okno otwierania plików graficznych (File Open Picture) przedstawione zostało na rysunku 7.11.

Okno dialogowe Kolor

Okno Kolor ( przedstawione na rysunku 7.1.) służy oczywiście do wyboru koloru. W chwili kliknięcia na przycisku OK informacja o kolorze znajdzie się we właściwości Color. Okno Kolor, podobnie jak okna dialogowe plików, nie posiada żadnych zdarzeń, na które można byłoby zareagować.

Okno dialogowe Czcionka

Okno Czcionka umożliwia użytkownikowi wybór czcionki z listy czcionek dostępnych w określonym systemie. Poprzez właściwość Device można określić, czy wyświetlane mają być tylko czcionki ekranowe, czcionki drukarki czy też obydwa te typy. Modyfikując właściwości MaxFontSize i MinFontSize można ograniczyć maksymalny i minimalny rozmiar czcionki, jaki jest w stanie wybrać użytkownik. Właściwość Option, podobnie jak w przypadku okien dialogowych plików, zawiera duży wybór opcji pozwalających kontrolować sposób funkcjonowania okna dialogowego Czcionka.

Jeżeli użytkownik kliknie na przycisku OK, we właściwości Font znajdą się wszelkie niezbędne informacje potrzebne do zaimplementowania nowej czcionki. Domyślną konfigurację okna Czcionka przedstawia rysunek 7.12.

Okno Czcionka posiada jedno dodatkowe zdarzenie ponad standardowy zestaw zdarzeń okna dialogowego. Zdarzenie OnApply występuje, gdy użytkownik kliknie na przycisku Zastosuj w oknie wyboru czcionki. Obecność tego przycisku w oknie Czcionka jest warunkowana wcześniejszym utworzeniem poprawnej (niepustej) funkcji obsługującej zdarzenie OnApply.

Okna dialogowe Znajdź i Zamień

Okna Znajdź i Zamień dają użytkownikom możliwość wprowadzenia wzorca poszukiwanego tekstu a także tekstu, którym znaleziony fragment ma zostać zastąpiony. Okno Znajdź reprezentowane jest w bibliotece VCL przez komponent FindDialog, natomiast komponentem reprezentującym okno Zamień jest komponent ReplaceDialog.

Rysunek 7.12.

Okno dialogowe Czcionka

0x01 graphic

Okno Zamień, zawierające wszystkie elementy okna Znajdź i dodatkowe cechy związane z zamianą, zostało przedstawione na rysunku 7.13.

Rysunek 7.13.

Okno dialogowe Zamień

0x01 graphic

Do podstawowych właściwości komponentów FindDialog i ReplaceDialog zaliczyć można FindText (zawierającą szukany wzorzec), ReplaceText (tekst, który ma zastąpić odnaleziony fragment tekstu) i Options. Oczywiście komponent FindDialog nie dysponuje właściwością ReplaceText. Właściwość Options przechowuje szeroki zakres informacji dotyczących różnorodnych opcji, jakie użytkownik ustawił przed kliknięciem na jednym z przycisków Następny, Zamień i Wszystkie.

Metoda Execute komponentów FindDialog i ReplaceDialog wygląda nieco inaczej, niż w przypadku innych standardowych komponentów dialogowych. Przede wszystkim okna Znajdź i Zamień są oknami niemodalnymi. Powrót z metody Execute następuje bezpośrednio po wyświetleniu okna.

Ponieważ okno dialogowe jest niemodalne, wartość zwracana przez metodę Execute jest bezwartościowa (zawsze równa True). Zamiast tej metody, do określenia stanu okna dialogowego wykorzystywane są zdarzenia OnFind i OnReplace, a także właściwość Options. Zdarzenie OnFind pojawia się w chwili kliknięcia na przycisku Następny. Komponent ReplaceDialog oprócz zdarzenia OnFind posiada również zdarzenie OnReplace, generowane w chwili kliknięcia na jednym z przycisków Zamień lub Wszystkie. Używaj tych zdarzeń w celu określenia, czy użytkownik zażądał operacji odnalezienia, czy też zamiany. W tworzonych przez siebie programach powinieneś również odczytywać właściwość Options, aby przekonać się w jaki sposób użytkownik życzy sobie przeprowadzić proces poszukiwania lub zamiany.

Podsumowanie

W rozdziale tym miałeś okazję zapoznać się z niektórymi podstawowymi komponentami oferowanymi przez Delphi. Zacząłeś od poznania ogólnych wiadomości na temat komponentów, aby później przejść do szczegółów funkcjonowania komponentów bazujących na kontrolkach Windows. Ważną rzeczą jest zrozumienie zasad funkcjonowania podstawowych kontrolek Windows i reprezentujących je komponentów Delphi. Na końcu rozdziału przyszła pora na przeanalizowanie niektórych standardowych okien dialogowych Windows.

Warsztat

Warsztat składa się z pytań kontrolnych oraz ćwiczeń utrwalających i pogłębiających zdobytą wiedzę. Odpowiedzi do pytań możesz znaleźć w dodatku A.

Pytania i odpowiedzi

I tak, i nie. Delphi zmieni wszystkie odwołania do nazwy tego komponentu w wygenerowanym przez siebie kodzie, ale w żaden sposób nie zmodyfikuje kodu napisanego przez użytkownika.

Ponieważ nie jest on widoczny w fazie projektowania. Jego „wizualność” ujawnia się dopiero w trakcie pracy programu, gdy zostanie on uaktywniony przez metodę Execute.

W trakcie pracy z Projektantem Formularzy, Delphi samodzielnie generuje kod bazując na właściwości Name. Jeżeli w późniejszym okresie właściwość ta zostanie zmieniona przez bezpośrednią edycję plików kodu źródłowego lub modyfikację w trakcie pracy programu, wszystkie odwołania do formularza lub komponentu (posiadacza tej właściwości) staną się nieprawidłowe i najprawdopodobniej doprowadzą do błędów kompilacji lub załamania się programu w trakcie pracy.

Absolutnie nie. W rzeczywistości, właśnie z myślą o takim wykorzystaniu projektowane są komponenty VCL. Dobrze napisany komponent w maksymalnym stopniu korzysta z właściwości. Z tego powodu nie można zbyt często używać jego metod. Używaj metod wtedy, kiedy jest to niezbędne, ale w pozostałych przypadkach korzystaj z właściwości do manipulowania komponentem w trakcie pracy programu.

Ponieważ kiedy klikasz podwójnie na komponencie, Windows generuje oba komunikaty pojedynczego i podwójnego kliknięcia. Sytuacji takiej nie da się zapobiec, trzeba więc napisać kod, który będzie ją uwzględniał.

Zamiast klasy TStrings skorzystaj z klasy TStringsList, która przeznaczona jest właśnie do tego typu zastosowań.

Nie. Istnieje jednak inny sposób: użyj komponentu Memo nadając mu wygląd zwykłego komponentu Edit. Właściwości WantReturn nadaj wartość False, ustaw wysokość komponentu (Height) na standardowy rozmiar komponentu Edit (21 pikseli), a następnie przypisz właściwości Alignment wartość taRightJustify. W efekcie komponent Memo przebierze wygląd zwykłej jednowierszowej kontrolki edycyjnej z wyrównywaniem do prawej strony.

W formularzu znajduje się przycisk z właściwością Cancel ustawioną na wartość True. Kiedy użytkownik naciska klawisz Esc, metoda ShowModal zwraca wartość właściwości ModalResult tego przycisku. Kiedy z kolei formularz zostaje zamknięty przy pomocy ikony systemowej, zwracaną wartością jest zawsze mrCancel. W takim przypadku trzeba być przygotowanym na wzięcie pod uwagę obu sposobów zamknięcia formularza.

Quiz

  1. Czy możliwa jest zmiana właściwości Name komponentu w trakcie pracy programu?

  1. Jaka właściwość służy do udostępniania i blokowania dostępu do kontrolek?

  2. W jaki sposób w trakcie pracy programu można stwierdzić, że przycisk jest zablokowany?

  3. Jaka różnica występuje między długim, a krótkim tekstem pomocy kontekstowej?

  4. Wymień trzy z czterech metod, które mogą zostać użyte do poinformowani kontrolki o konieczności odświeżenia samej siebie.

  5. Ile istnieje różnych typów obiektów combo?

  6. W jaki sposób wykorzystywana jest właściwość ModalResult komponentów- przycisków?

  7. Który z komponentów jest często wykorzystywany jako pojemnik dla innych komponentów?

  8. Jaką wartość zwraca metoda Execute komponentu OpenDialog, jeżeli użytkownik zamknie to okno kliknięciem na przycisku OK?

  9. W jaki sposób uczynić z komponentu SaveDialog okno dialogowe Zapisz jako…?

Ćwiczenia

  1. Stwórz program, który zawierać będzie dwa komponenty edycji. Spraw, aby w miarę wpisywania informacji przez użytkownika do pierwszej kontrolki pojawiała się ona również w kontrolce drugiej.

  1. Stwórz program zawierający listę. Napisz kod, który będzie ładował zawartość listy z pliku tekstowego, zanim jeszcze aplikacja stanie się widoczna.

  2. Do programu z ćwiczenia drugiego dodaj komponent edycyjny. Kiedy użytkownik wybierze element w liście - spraw, aby tekst tego elementu pojawił się w kontrolce edycyjnej.

  3. Do programu tworzonego w ćwiczeniach 2 i 3 dodaj przycisk. Napisz kod, który w przypadku kliknięcia w ten przycisk będzie dodawał do listy nowy element stworzony z tekstu zawartego w kontrolce edycyjnej.

  4. Stwórz program, w którym znajdzie się komponent RadioGroup zawierający czteroelementową grupę. Dodaj komponent etykiety, której tekst będzie się zmieniał w zależności od wybranego przycisku opcji.

  5. Stwórz program, który w górnej części formularza posiada tytuł wycentrowany niezależnie od tego, jaki rozmiar przyjmuje okno.

  6. Zmodyfikuj program z ćwiczenia szóstego tak, aby czcionka tytułu mogła być zmieniona na dowolną czcionkę dostępną w systemie przez kliknięcie na przycisku.

  7. Otwórz program przeglądarki plików graficznych stworzony w rozdziale czwartym. Zmodyfikuj go tak, aby zamiast zwykłych okien dialogowych korzystał on z okien otwarcia pliku graficznego (File Open Picture) i zapisania pliku graficznego (File Save Picture).


Podsumowanie
części I


W tej części książki zaprezentowana została niemała porcja wiadomości podstawowych. Część ta pod pewnymi względami była najtrudniejsza. Object Pascal, mimo że nie jest tak zniechęcający jak niektóre inne języki programowania, również wymaga czasu na nauczenie się. Nie ma jednak wątpliwości, że możesz nauczyć się programować w Delphi jeżeli przy nim pozostaniesz. Zrób sobie od czasu do czasu przerwę. Oryginalny tytuł tej książki mówi o 21 dniach, w trakcie których nauczysz się programować w Delphi, nie oznacza to jednak że mają to być dni kolejno następujące po sobie. Czasem dobrze jest zrobić sobie kilka dni przerwy, pozwalając w ten sposób aby cała wiedza wsiąknęła w nas.

Jeżeli niektóre zagadnienia składni języka Object Pascal wydają Ci się pogmatwane, nie sądź że jesteś osamotniony w tym przeświadczeniu. Na początku wszystko wydaje się nie mieć sensu. Nie martw się, ponieważ już niedługo zaczniesz „chwytać” w czym rzecz. W miarę pracy z Delphi, krok po krok wszystko zacznie nabierać sensu. To, czego prawdopodobnie teraz Ci brakuje, to doświadczenie wynikające z rozwiązywania rzeczywistych zadań. To właśnie wtedy naprawdę się uczysz. Właśnie ten typ wiedzy, zdobywany przez doświadczenie, pozostaje w nas na stałe. Moja rada to wyznaczyć sobie problem do rozwiązania i zamienić go w pracujący program. Nie jest powiedziane, że musisz dokonać tego w tym momencie, ale możesz przynajmniej rozpocząć działania w tym kierunku. Nikt nie wymaga, aby program ten był tak rozbudowany jak Microsoft Word, Netscape Navigator, czy gra DOOM. Ma to być coś, co pomoże Ci powiązać zdobytą wiedzę z doświadczeniem.

Na początku tej części rozdziału zajmowałeś się słowami kluczowymi i składnią języka Object Pascal. Elementy takie jak pętle i wyrażenia warunkowe if są w miarę proste do zrozumienia. Nie czuj się jednak zakłopotany, jeżeli będziesz musiał powrócić do zagadnień składni i przejrzeć je ponownie. Jest dużo rzeczy do nauczenia się i nikt nie wymaga, abyś zapamiętał każde słowo kluczowe i jego składnię. To przyjdzie samo z czasem, ale na tym etapie nauki nie jest to oczekiwane.

W rozdziale trzecim zetknąłeś się z klasami Object Pascala. Klasy stanowią ogromną część Object Pascala i programowania w Delphi. W niektórych przypadkach trzeba czasu aby dostrzec, gdzie w programie może zostać wykorzystana określona klasa. Przez dłuższy czas możesz korzystać jedynie z klas udostępnianych przez bibliotekę komponentów VCL, wstrzymując się od pisania własnych klas. Później najprawdopodobniej znajdziesz takie sytuacje, gdzie dla rozwiązania określonego zadania najlepiej będzie zastosować własną klasę - kiedy nadejdzie taki czas, będziesz przygotowany do tego, aby poradzić sobie z samodzielnym pisaniem takich struktur. Po napisaniu dwóch lub trzech własnych klas, ich tworzenie stanie się dla Ciebie czymś naturalnym.

Rozdział czwarty poświęcony był środowisku IDE. Dowiedziałeś się w jaki sposób dostosować otoczenie do swoich własnych potrzeb, przekonałeś się jak działa Paleta Komponentów, czym jest Inspektor Obiektów, itp. W tym rozdziale doświadczyłeś wiele zabawnych rzeczy. Nie ma nic niewłaściwego w użyciu słowa zabawa. Wszelkie zagadnienia związane z programowaniem uznaję za niezwykłą porcję zabawy. Właśnie tak to postrzegam i mam nadzieję, że Ty również uznasz to za niezłą zabawę.

W rozdziale piątym nastąpiło wprowadzenie do bibliotek klas, znanych również szkieletami (ang. frameworks). Jednym z nich jest VCL. Szkielet ułatwia nam życie, hermetyzując trudne zadania programistyczne Windows w postaci klas, z którymi można poradzić sobie na bardziej racjonalnym poziomie. Możesz uwierzyć mi na słowo, iż w niektórych przypadkach interfejs Windows API wydaje się zupełnie nieracjonalny. Użytkownik zwolniony jest z potrzeby martwienia się o takie sytuacje, ponieważ zastępuje go w tym VCL, on sam dostaje za to obiekty stojące na wyższym poziomie programowania i może z łatwością włączać je do swoich aplikacji. Nie oznacza to, że korzystanie z biblioteki VCL jest łatwe, ale na pewno jest o wiele prostsze niż bezpośrednie operowanie na Win32 API. Część dyskusji na temat szkieletów stanowiło wprowadzenie do modelu komponentu. Dowiedziałeś się co to są właściwości, metody i zdarzenia, a także w jaki sposób wykorzystać je do budowy programu dla Windows w Delphi.

Rozdział szósty dotyczył Projektanta Formularzy. Projektant Formularzy jest tym miejscem, gdzie odbywa się spora część pracy związana z projektowaniem aplikacji Delphi - przynajmniej jej części graficznej. Praca z Projektantem Formularzy może również przynosić wiele radości, której efektem będą doskonale wyglądające formularze. Pamiętaj, że w Twoich aplikacjach formularz reprezentuje okno. Większość aplikacji składa się z okna głównego i kilku okien dialogowych, wyświetlanych w zależności od przebiegu współpracy użytkownika z programem. W tym rozdziale stworzyłeś prosty lecz użyteczny program - ScratchPad. Był to swego rodzaju początek budowania programów w Delphi. ScratchPad będzie wielokrotnie wykorzystywany w dalszej części książki. W miarę zdobywania wiedzy programistycznej będziesz dodawał nowe cechy do tego programu, nabierając w ten sposób praktyki w stosowaniu zaprezentowanych technik. Jeżeli starasz się samodzielnie utworzyć swoją własną aplikację, zachęcam Cię do wyposażania jej w nowe cechy, w miarę ich poznawania.

W rozdziale siódmym poznałeś niektóre dostępne komponenty VCL. Nie wszystkie komponenty zostały omówione, a jedynie te, najczęściej używane podczas programowania dla Windows w Delphi. Z innymi komponentami zapoznasz się w przyszłości.

Mam nadzieję, że ta część książki nie wyczerpała Cię zbytnio. Jeśli tak, zrób sobie przerwę, aby później znowu wrócić do pracy. Jeżeli z kolei przestudiowanie tych siedmiu rozdziałów było radosnym i dostarczającym energii doświadczeniem, nie przerywaj go i zabierz się od razu za nowe rzeczy.

W nawiasach umieszczone zostały nazwy standardowych okien dialogowych w polskiej wersji Windows, nazwy te są stosowane w dalszej części rozdziału (przyp. tłum.)

Porównaj jednak pierwszy przypis w rozdziale 2. (przyp. red.)

4 Część I

308 C:\Dokumenty\Roboczy\Delphi 4 dla kazdego\07.doc

C:\Dokumenty\Roboczy\Delphi 4 dla kazdego\07.doc 307

308 Część I

Rozdzia³ 7. Komponenty VCL 305

Podsumowanie części I 309



Wyszukiwarka