Delphi, cz. 8.
Tak jak mówiłem w poprzednim rozdziale tym razem omówię podstawy grafiki. Pod koniec tego rozdziału przedstawię również prawie wszystkie dostępne funkcje do wykorzystania wraz z komponentem RichEdit. No to, co, zaczynamy?
Ładowanie obrazków
Ładowanie obrazków z dysku umożliwia komponent "Image". Nie musisz jednak stosować komponentu, aby załadować obrazek. Umożliwia to zmienna typu "TBitmap".
Oto przykład załadowania obrazka:
var
Bitmap : TBitmap;
begin
Bitmap := TBitmap.Create; // tworz zmienna
Bitmap.LoadFromFile('C:\obrazek.bmp'); // zalduj obrazek
Canvas.Draw(10, 10, Bitmap); // wyswietl obrazek
Bitmap.Free; // zwolnij zmienna
Kod ten nie wygląda tak strasznie, co? :) Dobra już omawiam jego działanie. Na samym początku utworzona zostaje zmienna typu "TBitmap" ( w pamięci komputera zarezerwowana zostaje pamięć dla tej zmiennej). Następnie załadowany zostaje obrazek ( obrazek musi mieć rozszerzenie *.bmp! ). Kolejna instrukcja to wyświetlenie obrazka na formie. Zauważ słowo "Canvas". Oznacza ono tzw. płótno, czyli obszar na formularzu. To na nim będzie można rysować i wykonywać różne rzeczy :) A więc funkcja "Draw" wyświetla obrazek w miejscu oznaczonym poprzez dwie pierwsze wartości tej funkcji. Czyli dla kompilatora takie polecenie brzmi tak: "Wyświetl zmienną typu "Bitmap" w miejscu 10, 10". Na samym końcu tej funkcji następuje zwolnienie pamięci zajętej przez zmienna "Bitmap". Jest to bardzo ważne! Jeżeli chciałbyś wyświetlić obrazek JPG to należałoby użyć zmiennej typu "TJPEGImage". Trochę o tym była mowa w poprzednim rozdziale. Do listy uses dodaj słowo "jpeg". Teraz w procedurze napisz tak:
var
JPG : TJPEGImage;
begin
JPG := TJPEGImage.Create;
JPG.LoadFromFile('C:\Moje dokumenty\mikolaj.JPG');
Canvas.Draw(10, 10, JPG);
JPG.Free;
Jak widzisz budowa takiej procedury jest baaardzo podobna. Tyle, ze zmienna typu "TBitmap" zastąpiono "TJPEGImage". :)
Płótno, czyli Canvas
Tak jak powiedziałem wcześniej płótno stanowi obszar, po którym będziemy rysować. Na początek coś prostego, czyli wyświetlenie tekstu "I co się tak gapisz!". Żeby spowodować takie efekt musisz zrobić tak:
Canvas.TextOut(100, 20, 'I co się tak gapisz?");
Polecenie "TextOut" wyświetla tekst w punkcie 100 i 20. Jak się zapewne domyślasz pierwsza cyfra jest współrzędną X, a druga to Y :)) Jeżeli użyjesz takiej funkcji to ujrzysz na formie tekst. Ale cóż to, tekst ma białe tło.... łeeee, ale brzydko wygląda... Dobra, przecież można to zmienić ustawiając tło na przeźroczyste. Teraz coś o wiele trudniejszego - załadowanie obrazka, ustawienie tła na przeźroczyste, a następnie wyświetlenie tekstu na obrazku:
procedure TForm1.Button1Click(Sender: TObject);
var
Bitmap : TBitmap;
begin
Bitmap := TBitmap.Create; // stworzenie zmiennej
Bitmap.LoadFromFile('C:\Moje dokumenty\obrazek.BMP'); // saldowanie obrazka
Canvas.Draw(100, 50, Bitmap); // wyswietl obrazek
Canvas.Brush.Style := bsClear; // ustaw tło na przezroczyste
Canvas.Font.Color := clWhite; // kolor czcionki: biały
Canvas.Font.Name := 'Arial Black'; // nazwa czcionki: Arial Black
Canvas.Font.Size := 16; // rozmiar czcionki: 16 pkt.
Canvas.TextOut(120, 60, 'Obrazek...'); // wyświetlenie tekstu
end;
Kodu tutaj jest więcej, ale przy okazji dowiadujesz się jak ustawić czcionkę, jej kolor i rozmiar :) Początek jest już znany ( załadowanie obrazka ). Na chwilę zatrzymam się przy linii: Canvas.Brush.Style := bsClear; Otóż ta linia ustawia styl tła na przeźroczysty. Możliwe są jeszcze takie style:
bsSolid - stały jednolity kolor
bsCross - siatka
bsDiagCross - siatka przecinająca się pod ukosem :)
bsHorizontal - linie poziome
bsVertical - linie pionowe
bsClear - styl przeźroczysty
bsBDiagonal - linie pod ukosem "spadające" z prawego górnego rogu w dolny lewy
bsFDiagonal - linie "spadające" z lewego górnego rogu na prawy dolny.
Już niedługo przekonasz się jak to wszystko działa, ale wcześniej omówię jeszcze ustawianie czcionki. Czcionkę ustawia się poprzez polecenie "Font":
Canvas.Font.Name := 'Arial Black'; // czionka
Canvas.Font.Size := 18; // rozmiar czionki
Canvas.Font.Color := clBlue; // kolor czcionki
Canvas.Font.Style := Font.Style + [fsUnderline] + [fsBold] + [fsItalic];
// styl czcionki ( podkreślenie, kursywa, pogrubienie ).
Rysowanie figur
Delphi umożliwia oczywiście rysowanie różnych figur. Np., żeby narysować prostokąt piszesz:
Canvas.Rectangle(20, 20, 120, 120);
Pierwsze dwa parametry to lewy górny narożnik, a dwa ostatnie to prawy, dolny narożnik. Wygląd nie jest zbyt ciekawy, prawda? Białe tło, hmm można by było to zmienić. Także obramowanie. Delphi oferuje klasę "TPen". Ustawia ona styl, kolor pióra, czyli w naszym wypadku obramowania prostokąta. Oto właściwości tej klasy:
Color - określa kolor linii;
Mode - określa, w jaki sposób linia będzie rysowana. Dostępne są takie oto sposoby: pmBlack, pmWhite, pmNop, pmNot, pmCopy, pmNotCopy, pmMergePenNot, pmMaskPenNot, pmMergeNotPen, pmMaskNotPen, pmMerge, pmNotMerge, pmMask, pmNotMask, pmXor, pmNotXor. Wypróbuj je, aby sprawdzić jak działają.
Width - grubość linii w pixelach;
Style - Styl linii - możliwe jest:
- psClear - linia niewidoczna;
- psDash - linia przerywana;
- psDashDot - linia i kreska ( na przemian );
- psDot - linia kropkowana;
- psSolid - linia ciągła;
- psDashDotDot - kreska i dwie kropki;
Teraz żeby określić linie piszesz:
Canvas.Pen.Color := clBlue;
Canvas.Pen.Size := 10;
Canvas.Pen.Style := psDash;
Canvas.Rectangle(20, 20, 220, 220);
Zróbmy test: napiszemy program, który co sekundę będzie wyświetlał w losowym położeniu prostokąt o różnych kolorach i stylach. Postępuj, więc według poniższych wskazówek:
1. Na formularzu umieść komponent Timer. ( paleta: System ). Komponent ten służy do generowania, co ileś czasu określonego zdarzenia.
2. Zmień właściwość "Interval" komponentu na 500. Właściwość ta określa, co ile milisekund występować będzie zdarzenie.
3. Teraz mając zaznaczony komponent "Timer" kliknij w Inspektorze Obiektów na zakładkę "Events". Wygeneruj zdarzenie "OnTimer". Wpisz taki tekst:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Randomize; // losowanie...
with Canvas do
begin
// kolor tła
Brush.Color := RGB(Random(255), Random(255), Random(255));
// kolor pędzla
Pen.Color := RGB(Random(255), Random(255), Random(255));
Pen.Width := Random(10); // szerokość linii
case Random(5) of // styl
0: Pen.Style := psDash;
1: Pen.Style := psDashDot;
2: Pen.Style := psDot;
3: Pen.Style := psSolid;
4: Pen.Style := psDashDotDot;
end;
{ rysowanie prostokąta o wylosowanych wymiarach }
Rectangle(Random(Width), Random(Height), Random(Width),
Random(Height));
end;
end;
Najpierw odpal program, aby zobaczyć działanie. I jak? Może być? No to omawiamy. Pierwsza linia w tej procedurze odpowiada za losowanie. Gdybyśmy tego nie użyli po każdym uruchomieniu programu prostokąty rysowane by były w tych samych pozycjach. Następna instrukcja to instrukcja wiążąca. Później losowany jest kolor tła. Tutaj na chwile się zatrzymamy. RGB oznacza trzy podstawowe kolory ( ang. Red, Green, Blue ). W nawiasach losowo wybierany jest odcień dla tych kolorów i następuje wymieszanie wszystkiego razem oraz złączenie w jedną całość - w ten sposób powstaje kolor :) Zobacz, co by się stało gdybyś zrobił tylko tak: Random(255); wtedy wylosowany by został tylko odcień czerwonego i nie wyglądałoby to ciekawie. Tak samo jest z losowaniem koloru pędzla. Następnie losowanie grubości linii. Następnie mamy instrukcje "case", która odpowiada za odpowiednie ustawienie stylu pędzla. W zależności od wylosowanego wyniku ustawiany jest odpowiedni styl. No i na samym końcu losowanie wymiarów. Losowanie następuje spośród szerokości okna ( Width ) oraz jego wysokości ( Height ). Nie musisz pisać:
Form1.Width gdyż Delphi "wie”, o jaką szerokość chodzi.
Jeszcze jeden przykład? OK, pewnie nie raz się spotkałeś, ot choćby w Windowsie z rysowaniem prostokąta podczas przeciągania kursorem myszy. Dobra, pewnie nie wiesz, o co mi chodzi. Chwyć kursorem myszy na pulpit i nie puszczając przycisku przeciągnij myszką. Co widzisz? Prostokąt, który się przeciąga wraz z ruchem myszy. Ty też tak możesz zrobić. Do sekcji "private" dodaj takie linie:
MD : Boolean; // określenie czy przycisk myszy jest wciśnięty, czy też nie
P : TPoint; // zmienna zawiera pozycje X i Y kursora.
Pierwsza zmienna określa, czy klawisz myszy jest wciśnięty ( True ), czy też nie ( False ). Trzeba omówić zmienna "TPoint"? Otóż zawiera ona pozycje X i Y. Zrozumiesz to później :))
Teraz wygeneruj procedurę "OnMouseDown" formy. Procedura ta będzie generowana w chwili naciśnięcia klawiszem myszy w obszar formularza. ( o generowaniu procedur była mowa w poprzednich rozdziałach ). W procedurę tę wpisz taki kod:
MD := True; // klawisz myszy naciśnięty
GetCursorPos(p); // pobierz pozycje kursora
Funkcja "GetCursorPos" pobiera pozycje kursora. Pozycja ta wyrażona jest we współrzędnych X i Y dlatego też należało skorzystać ze zmiennej "TPoint". Do ustawiania kursora w wybranym przez Ciebie miejscu słuzy funkcja "SetCursorPos" ( to tak na marginesie :)).
Teraz wygeneruj procedurę "OnMouseMove" - uruchamiana ona będzie podczas przesuwania myszą:
if MD then // czy klawisz myszy jest wciśnięty?
begin
Repaint; // odświeć obraz...
Canvas.Brush.Style := bsClear; // styl na przezroczysty
Canvas.Pen.Style := psDot; // styl lini: przerywany
Canvas.Rectangle(P.X, P.Y, X, Y); // rysuj prostokat
end;
Jeżeli zmienna "MD" przybrala wartość "True" ( klawisz myszy jest wcisniety ) to wykonaj nastepujace operacje: odśwież obraz, ustaw odpowiedni styl pedzla, a nastepnie narysuj prostokąt. Rysowanie prostokąta: dwie pierwsze wartości to miejsce gdzie kliknąłeś myszą ( zostały one pobrane w poprzedniej procedurze ) - od tego miejsca zacznie się rysowanie prostokąta. Dwie ostatnie wartości: X i Y to aktualne współrzędne myszy. Po prostu w procedurze "OnMouseMove" są one pobierane poprzez dwie zmienne X i Y.
Pozostało jeszcze napisanie procedury "OnMouseUp", które uruchamiane będzie podczas puszczenia klawisza myszy:
MD := False;
Całość powinna wyglądać tak:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
MD : Boolean;
P : TPoint;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
MD := True; // klawisz myszy naciśnięty
GetCursorPos(p); // pobierz pozycje kursora
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if MD then // czy klawisz myszy jest wciśnięty?
begin
Repaint; // odświeć obraz...
Canvas.Brush.Style := bsClear; // styl na przezroczysty
Canvas.Pen.Style := psDot; // styl lini: przerywany
Canvas.Rectangle(P.X, P.Y, X, Y); // rysuj prostokat
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
MD := False;
end;
end.
Na zakończenie to co obiecałem, czyli główne ( prawie wszystkie ) dostępne funkcje komponentu "RichEdit":
RichEdit.PlainText := True; // Jeżeli jest to "False" to Delphi zapisuje wszelkie formatowanie tekstu ( pogrubienie, kolor itp. ).
RichEdit.Print('Moj dokument'); // to polecenie powoduje drukowanie komponentu;
RichEdit.SelText := 'Adam; // wstawienie w miejsce kursora tekstu;
RichEdit.Lines.Add('Adam'); // wstawienie tekstu w nowej linii
RichEdit.SelAttributes.Name := 'Arial Black'; // zmiana czcionki zaznaczonego tekstu na "Arial Black"
RichEdit.SelAttributes.Size := 24; // zmiana rozmiaru czcionki zaznaczonego tekstu
RichEdit.SelAttributes.Color := clRed; // zmiana koloru zaznaczonego tekstu na czerwony
RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsItalic]; { do zaznaczonego tekstu dodawane jest kursywa;
może to być także pobrubienie [fsBold] lub podkreślenie [fsUnderline]; }
RichEdit.Undo; // cofa ostatnią operacje
RichEdit.SelectAll; // zaznacza cały tekst w obrębie kontrolki
RichEdit.WordWrap := True; // Jezeli jest to "True" to włączone jest zawijanie tekstu
RichEdit.CutToClipboard; // wycinanie zaznaczonego tekstu do schowka
RichEdit.CopyToClipboard; // kopiowanie tekstu do schowka
RichEdit.PasteFromClipboard; // wklejanie tekstu do RichEdit
RichEdit.Paragraph.Alignment := taCenter; // wycentrowanie tekstu; możliwe jest: taLeftJustify - do lewej; taRightJustify - do prawej
RichEdit.Paragraph.Numbering := nsBullet; // wypunktowanie tekstu;
RichEdit.Paragraph.LeftIndent := 30; // wcięcie z lewej
RichEdit.Paragraph.RightIndent := 50; // wcięcie z prawej
RichEdit.Paragraph.FirstIndent := 30; // wcięcie pierwszego akapitu
A więc to są najczęściej używane komendy. Resztę możesz doczytać w systemie pomocy Delphi. Jeżeli nie za bardzo wiesz jak tego użyć to proponuje ściągnięcie ze strony www.programowanie.of.pl edytora tekstu "Pad". Znajduje się on w dziale "Źródła", czyli są to kompletne kody źródłowe do edytora tekstu ( w miarę zaawansowanego :)).
Jak zwykle czekam na listy!
Adam Boduch <boduch@poland.com>
http://www.programowanie.of.pl