Delphi, cz. 6
No tak, w rozdziale 4 opisałem podstawy budowania edytora tekstów. Co dalej? Przede wszystkim procedura zapisującą text. Należy ja trochę unowocześnić. Pewnie zauważyłeś, ze zapisując tekst do pliku powstają jakieś "bohomazy"? :) No cóż nie włączyliśmy odpowiedniej opcji. Przyda się ona później. Przede wszystkim filtry. W okienku do zapisu pliku powinny być dostępne filtry. Zaznacz komponent "SaveDialog". W Inspektorze Obiektów kliknij w polu "Filter". Pojawi się okienko, w którym należy wpisać swoje filtry. Po lewej stronie wpisujemy nazwę filtry, a po prawej sam filtr - np.: *.txt
Ja wpisałem tak:
Lewa kolumna Prawa kolumna
Plik TeXTowy (*.txt) *.txt
Pliki INI (*.ini) *.ini
Pliki WordPada (*.wri) *.wri
Wszystkie pliki (*.*) *.*
Teraz użytkownik będzie mógł zapisać w 4 dostępnych filtrach. To nie wszystko - trzeba jeszcze dopisać kod. Jak zapewne wiesz pliki z rozszerzeniem *.wri są zapisywane w formacie WordPad'a. W tym formacie może być także zapisywany text z pokolorowanymi wyrazami, pogrubiony itp. Nasz edytor także będzie to potrafił.
Teraz należy zmodyfikować procedurę "btnSaveAs". Teraz wygląda ona tak:
if SaveDialog.Execute then
RichEdit.Lines.SaveToFile(SaveDialog.FileName); // zapisz plik
Caption := ExtractFileName(SaveDialog.FileName) + ' - ' + AppName;
RichEdit.Modified := False; // ustaw wartosc na "False"
Teraz zmodyfikuj ja w ten sposób:
procedure TMainFrm.btnSaveAsClick(Sender: TObject);
begin
{
W tej procedurze nastepuje wywolanie okna "Otworz", a
nastepnie zapisanie pliku. Wartosc "SaveDialog.FileName"
przechowuje sciezke pliku tekstowego pod jakim zapisales
swoj dokument. Na samym koncu nastepuje zmiana wlasciwoscie
"Caption" okna, a później ustawienie wartosci "Modified" na
"False"
}
if SaveDialog.Execute then
begin
with SaveDialog do // instrukcja wiazaca
begin
{
Kazdy filtr zawiera okreslony numer od 1 do ilosci
Twoich filtrow. Wlasciwosc "DefaultExt" zawiera info
o domyslnym filtrze.
}
case FilterIndex of // w zaleznosci od indeksu
1: DefaultExt := '.txt';
2: DefaultExt := '.ini';
3: DefaultExt := '.wri';
4: DefaultExt := '';
end;
if FilterIndex = 3 then
RichEdit.PlainText := False
else RichEdit.PlainText := True;
end;
RichEdit.Lines.SaveToFile(SaveDialog.FileName + SaveDialog.DefaultExt); // zapisz plik
Caption := ExtractFileName(SaveDialog.FileName) + ' - ' + AppName;
RichEdit.Modified := False; // ustaw wartosc na "False"
end;
end;
Chuch, trochę się rozrosła prawda? Już wyjaśniam. Przede wszystkim instrukcja wiążąca. Nie robi ona nic specjalnego - po prostu zmniejsza ilość słow. do napisania.
RichEdit.SelAttributes.Color := clRed;
RichEdit.SelText := 'boduch@poland.com';
Ten kod zmienia kolor czcionki komponentu "RichEdit" na czerwony i wstawia tekst w miejsce kursora. Poniższy kod jest równoznaczny z powyższym:
with RichEdit do
begin
SelAttributes.Color := clRed;
SelText := 'boduch@poland.com';
end;
Rozumiesz, mniej pisania - nie trzeba ciągle pisać "RichEdit" - wystarczy raz. I w procedurze wszystkie operacje wiążące są z komponentem "SaveDialog". Następnie instrukcja "case". Jest to instrukcja podobna do "if". Po prostu zamiast pisać:
var
I : Integer;
begin
I := 25;
if I = 20 then
ShowMessage('NIE');
if I = 14 then
ShowMessage('NIE');
if I = 25 then
ShowMessage('TAK');
Można napisać tak:
var
I : Integer;
begin
I := 25;
case I of
20: ShowMessage('NIE');
14: ShowMessage('NIE'0;
25: ShowMessage('TAK');
end;
Czyż nie jest to wygodniejsze i przejrzystsze :) Naturalnie, jeżeli blok instrukcji obejmuje więcej niz. jedna linie musisz dodać linie: begin i end:
case I of
20: begin
ShowMessage('NIE');
I := 23;
end;
W procedurze w zależności od numeru filtru ( pierwszy filtr do cyfra 1, a kolejny to po prostu kolejna cyfra ) przypisywane jest domyślne rozszerzenie ( właściwość "DefaultExt" to domyślne rozszerzenie, które automatycznie będzie dopisywane do nazwy pliku ). Zauważ, ze przy ostatnim ( 4 ) rozszerzeniu nie będzie dopisywane nic. Jedziemy dalej. Następnie warunek "if" sprawdza, jakie rozszerzenie wybraliśmy. Pamiętasz jak w zapisywanym pliku powstawały jakieś "krzaczki"? Właściwość "PlainText" określa czy te krzaczki będą, czy nie. No dobra, tak sobie mowie - krzaczki :) Tak naprawdę to zapisywane są kolory poszczególnych wyrazów, rozmiary czcionek itp. W przyszłości program nasz tak unowocześnimy, ze będzie można dokonywać zmian takich jak w Wordzie ( kolorowanie poszczególnych wyrazów, pogrubianie, zmiana czcionki itp. ) i wtedy ta właściwość się nam przyda. Jeżeli wybrałeś rozszerzenie *.wri - wtedy właściwość ta przybiera wartość "False" - w przeciwnym wypadku - "True”, czyli wyrazy nie będą kolorowane i będzie to "czysty" tekst.
Przyozdabianie programu
Te przyciski, które służą do otwierania, zapisywania są jakieś taki niemrawe :) Nie lepiej byłoby przyzdobic je jakimiś ikonami? Na palecie "Win32" znajduje się komponent "ImageList" - umieść go na formularzu. Ten komponent służy do gromadzenia ikonek w jednym pliku. Kliknij na niego dwukrotnie. Teraz możesz kliknąć na przycisku "Add". Możesz teraz wybrać jakąś bitmapke lub ikonke. Możesz poszukać w katalogu "Images\Buttons" na płytce z Delphi. Ja wybrałem teraz ikonki symbolizujące funkcje danego przycisku. Teraz naciśnij na przycisku OK, aby potwierdzić te ikony. Teraz pojedynczo kliknij na pasku "Tools". W Inspektorze Obiektów we właściwości, „Images" wybierz z listy "ImageList1" - nasze przyciski powinny ozdobić efektywne ikony. Teraz, jeżeli klikniesz na którymś z przycisków możesz w Inspektorze Obiektów kliknąć na pozycji "ImageIndex" i z listy wybrać odpowiednia ikonę.
W tym rozdziale zakończymy już temat edytora tekstów - dokończenie w następnej części. Jeżeli nie możesz się doczekać to stwórz trzy przyciski służące do wycinania, kopiowania i wklejania. Kod do tych funkcji to:
RichEdit.CutToClipBoard; // wycinanie do schowka
RichEdit.CopyToClipBoard; // kopiowanie do schowka
RichEdit.PasteFromClipBoard; // wklejanie
Możesz także ściągnąć sobie program "Pad" - tak będzie wyglądał nasz program w przyszłości :) Na stronie www.programowanie.of.pl w dziale "Programy". Jeżeli chciałbyś dowiedzieć się czegoś więcej o Delphi, poczytać trochę artykułów i pościągać programów to odwiedź stronę, której adres widnieje powyżej :)
Teraz cos nowego - wyjątki. Nigdy nie jesteś w stanie przewidzieć działania programy oraz działania użytkownika programu. Właśnie po to są wyjątki. Przećwiczmy to trochę :) Najłatwiej wytłumaczyć to na przykładzie. W naszym wypadku załadujemy obrazek.
Na palecie "Additional" znajduje się komponent "Image" - umieść go na formularzu. Komponent ten służy do przechowywania obrazków. Teraz na palecie "Dialogs" odnajdź komponent "OpenPictureDialog" i również umieść go na formularzu. Nazwij go "OpenPicture". Teraz umieść jeszcze przyciski wygeneruj procedurę "OnClick" - po prostu kliknij na przycisku. Wpisz taki oto kod:
try // sprobuj
OpenPicture.Execute; // wyswietl okienko...
// zaladuj obrazek do komponentu "Image"
Image1.Picture.LoadFromFile(OpenPicture.FileName);
except // wyswietl okienko w razie bledu
raise Exception.Create(
'Wystąpił bład w załadowaniu obrazka.');
end;
Ten kod spowoduje załadowanie obrazka, który wybierzesz w oknie "OpenPicture". Na samym początku znajduje się słowo "try”, co oznacza w dowolnym tłumaczeniu "spróbuj". Po tym słowie wykonywane są jakieś instrukcje. Jeżeli wszystko pójdzie dobrze nie zostanie wyświetlony żaden komunikat. Jeżeli wystąpi jakiś błąd - np. spróbujesz wczytać obrazek o rozszerzeniu *.txt :))) to wykonywane będą komendy po słowie "except". Po tym słowie mogą się znaleźć instrukcje, które będą wykonywane podczas zajścia nieprzewidzianej czynności, w większości przypadków jest to po prostu komunikat. W tym przypadku słowo "raise", które omówię później, a następnie generowany jest wyjątek. Wyjątek tworzy się przy użyciu polecenia "Exception.Create", a następnie w nawiasie wpisujemy treść komunikatu, który będzie wyświetlany. Na samym końcu jeszcze słowo "end".
Załadowanie obrazka chyba nie wymaga większych komentarzy - ot wystarczy jedna funkcja: "LoadFromFile", której jednym parametrem jest ścieżka programu, możesz wiec napisać tak:
Image1.Picture.LoadFromFile('C:\MojObrazek.bmp');
Właściwość "OpenPicture.FileName" zawiera pełna ścieżkę do obrazka.
Jeszcze trochę o słowie "raise"
Słowo "raise" służy do generowania wyjątku. Oto przykład:
var
X : Integer;
begin
X := 20;
if X <> 21 then
raise Exception.Create(
' Blad cholera.... ');
Zawsze będzie to powodować wyświetlenie komunikatu gdyż zmienna X jest równa 20. Jeszcze raz posłużę się powyższym przykładem.
try // sprobuj
OpenPicture.Execute; // wyswietl okienko...
// zaladuj obrazek do komponentu "Image"
Image1.Picture.LoadFromFile(OpenPicture.FileName);
except // wyswietl okienko w razie bledu
raise; // samo slowo "raise" !
end;
Widzisz? Teraz użyłem samego słowa "raise" bez dalszej części! Jeżeli wystąpi błąd to "Delphi" wygeneruje swój własny komunikat ( jaki uzna za stosowny :)).
try // sprobuj
OpenPicture.Execute; // wyswietl okienko...
// zaladuj obrazek do komponentu "Image"
Image1.Picture.LoadFromFile(OpenPicture.FileName);
except // wyswietl okienko w razie bledu
on EInvalidGraphic do // nieprawidlowy format
raise Exception.Create(
'Nieprawidłowy obrazek!');
on EFOpenError do // nie moge oczytac....
raise Exception.Create(
'Nie mogę odczytać pliku!');
end;
Można tez zrobić tak. W tym wypadku wyszczególniliśmy wyjątki. Fajnie nie? W zależności od zaistniałego błędu pojawi się inne okno. W tym wypadku, jeżeli format obrazka będzie nieprawidłowy lub wtedy, gdy nie będzie można z jakiś powodów odczytać pliku. Budowa jest prosta:
on <typ wyjątku> do
{ operacje do wykoania }
Jest wiele typów wyjątków. Opis większości z nich możecie znaleźć na stronie www.programowanie.of.pl w dziale "Delphi" ( artykuł "Wyjątki" ).
Istnieje jeszcze słowo "finally”, które pojawia się wraz z "try". Po instrukcji "finally" wykonywane będą operacje bez względu na to, czy wystąpił błąd, czy tez nie.
try // sprobuj
{ jakieś polecenia, bla, bla, bla }
finally
{ instrukcje koncowe, które zawsze i wszedzie zostana wykonane }
end;
Ufff, ale się rozpisałem. W następnej części kompresja grafiki do *.jpg!
Bald <boduch@poland.com>
Jak zawsze czekam na listy, pytania, uwagi, krytykę, błędy. bluzgi.. :)
P.S. Jeżeli chcecie do "Image'a" lądować obrazki JPG to dodajcie do listy uses słowo "jpeg".