Delphi - Drukowanie
Tue, 9 November 2004
Wstęp
Drukowanie? Tak, dzisiaj tym się właśnie zajmiemy. Temat drukowania nie jest rozległy gdy korzystamy ze standardowych modułów dołączonych razem zDelphi. Za ich pomocą możemy wydrukować dosłownie wszystko, więc nie ma potrzeby zagłębiać się w bezpośrednią obsługę drukarki.
Jednym z najważniejszych problemów jaki napotkamy będzie pozycjonowanie. Wiele niedoświadczonych programistów nie zwraca uwagi na pewien szczególny oraz istotny fakt. Drukarki mają różną rozdzielczość. Jest to pierwsza i najważniejsza rzecz na jaką chciałbym zwrócić Wam uwagę. Właśnie z tą własnością będziemy mieli najwięcej problemów, a co za tym idzie, ze skalowaniem stron na różne rozdzielczości. To dlatego sprawdzając swój program na innym sprzęcie, często otrzymywałeś nie do końca wynik, który chciałeś uzyskać. Na jednych brakowało części wydruku, na innych znów wydruk był zbyt mały. Co zrobić w takiej sytuacji? Mam zamiar praktycznie odpowiedzieć na to pytanie. Zapraszam!
Jak zacząć?
Delphiudostępnia nam moduł "Printers", który będzie nam potrzebny. Dodajmy go więc do listy używanych modułów - "uses". Następne co nas czeka to zadeklarowanie i utworzenie nowej klasy typuTPrinter. Zawiera ona takie właściwości jak szerokość oraz wysokość strony w pikselach (różna dla różnych rozdzielczości), płótno po którym będziemy rysować, oraz wiele innych użytecznych własności.
Wspomniałem o płótnie. To prawda - aby coś wydrukować, musimy to narysować na "płótnie" (od ang.Canvasznaczy płótno) drukarki, tak jak to robimy rysując po formularzu, czy innym obiekcie.Canvasjest "powierzchnią aktualnie drukowanej kartki". Zawiera ona opcję, które pozwalają nam narysować linię, koło, prostokąt i wiele innych figur.
Drukujemy pierwszy tekst
Zaczniemy od wydrukowania pewnego tekstu w lewym górnym rogu strony, czyli w punkcie (0,0). Nie potrzeba tutaj jakiś wymyślnych technik skalowania, ponieważ punkt (0,0) (jako jedyny) zawsze będzie na swoim miejscu i zawsze oznaczał będzie lewy, górny róg strony.
- UruchamiamyDelphi.
- Przechodzimy do "Edytora Kodu" i dodajemy modułPrintersdo listy używanych modułów "uses".
- Musimy teraz zadeklarować globalnie nową klasę jakoTPrinter. Aby to uczynić musimy dodać następującą linię do sekcji "var" znajdującej się przed (!) sekcjąimplementation:
var Form1: TForm1; Drukarka: TPrinter;
- Zadeklarowaliśmy klasę, a jak wiadomo, klasy po deklaracji trzeba jeszcze utworzyć.
- Przechodzimy do "Widoku projektu" naciskając klawisz F12.
- Na formie układamy przycisk (paleta Standard) i klikamy nań dwukrotnie.Delphipomógł nam w tej chwili, automatycznie tworząc nową procedurę obsługującą zdarzenie kliknięcia na przycisk (czyli dla wtajemniczonych, obsługującą komunikatWM_LBUTTONCLICK).
- W nowo-utworzonej procedurze piszemy fragment kodu, który będzie odpowiedzialny za utworzenie nowej klasy:
Drukarka := TPrinter.Create;
- Mamy teraz dostęp do możliwości drukowania. Aby coś wydrukować, musimy najpierw wydać komendęBeginDoc. Gdy ukończymy rysowanie na płótnie drukarki musimy powiadomić o tym system wydając komendęEndDoc. Dopiero wtedy system prześle stronę do druku. Spójrzcie:
// Utworzenie klasy Drukarka := TPrinter.Create; // Rozpoczęcie drukowania Drukarka.BeginDoc; { tutaj rysujemy na Canvasie } // Zakończenie drukowania Drukarka.EndDoc;
- Do rysowania tekstu naCanvasieposłuży nam funkcjaTextOut(). Jej budowa przedstawia się następująco:
procedure TextOut(X, Y: Integer; const Text: string);
Pierwsze dwa parametry to pozycja tekstu (lewy górny róg), kolejny to tekst do narysowania.
- Spróbujemy teraz wydrukować tekst:
// Utworzenie klasy Drukarka := TPrinter.Create; // Rozpoczęcie drukowania Drukarka.BeginDoc; // Narysowanie tekstu na Canvasie (płótnie) Drukarka.Canvas.TextOut(0, 0, 'Jakiś tam tekst'); // Zakończenie drukowania Drukarka.EndDoc;
Po udanym, jakże trudnym do wykonania drukowaniu tekstu ;) zapraszam do zapoznania się z innymi użytecznymi właściwościami klasyTPrinterorazTCanvas:
Metoda | Opis |
---|---|
Abort | Zakańcza drukowanie powodując utratę nie wydrukowanych informacji |
BeginDoc | Rozpoczyna zadanie drukowania |
EndDoc | Zakańcza zadanie drukowania wysyłając dane do drukarki |
NewPage | Rozpoczyna nową stronę (pamiętajmy, że Windows XP domyślnie drukuje "od końca") |
Refresh | Uaktualnia informacje o czcionkach i drukarkach. |
Właściwość | Opis |
---|---|
Aborted | Przyjmuje wartość True (prawda) gdy użytkownik przerwał zadanie drukowania. |
Copies | Określa ilość kopii |
Fonts | Lista dostępnych czcionek dla danej drukarki |
Orientation |
Umożliwia zmianę orientacji strony (pionowo lub poziomo).
poPortrait - pionowo (domyślnie) poLandscape - poziomo |
PageHeight | Określa wysokość strony w pikselach dla aktualnie wybranej rozdzielczości. |
PageWidth | Określa szerokość strony w pikselach dla aktualnie wybranej rozdzielczości. |
PageNumber | Przechowuje numer aktualnie drukowanej strony. |
PrinterIndex | Umożliwia wybór drukarki (gdy przypiszesz tej właściwości wartość -1 to wybrana zostanie drukarka domyślna) |
Printers | Zwraca listę zainstalowanych w systemie drukarek. |
Printing | Określa, czy aktualnie coś jest drukowane |
Title | Określa tytuł dokumentu. Tytuł ten wyświetlany będzie w menager'ze drukarek. |
Metoda | Opis |
---|---|
TextOut | Umożliwia narysowanie tekstu na Canvasie w określonej pozycji. |
Draw | Umożliwia wyświetlenie obrazka (bitmapy, grafiki) w określonej pozycji. |
Ellipse | Umożliwia narysowanie elipsy (w tym oczywiście również koła). Parametrami są lewy, górny oraz prawy, dolny "róg". |
FillRect | Rysuje prostokąt o wypełnieniu i stylu zgodnym ze stylem pędzla (Brush). |
MoveTo()
LineTo() |
Dwie procedury do narysowania linii. Za pomocą pierwszej ustawiamy pióro w danej pozycji, a za pomocą drugiej kreślimy od tego punktu określonej długości linię. |
Lock | Zabezpiecza płótno w sposób, aby inne wątki nie miały do niego dostępu. Przeznaczone dla aplikacji wielowątkowych. |
Pie | Rysuje wycinek koła. Narzędzie przydatne przy rysowaniu wykresów. |
PolyBezier | Rysuje linię Bézier'a (taką linię można płynnie wyginać). |
Polygon | Rysuje figurę o wierzchołkach podanych jako parametr. |
Rectangle | Rysuje prostokąt o wierzchołkach podanych jako parametr. |
TextWidth | Zwraca wielkość tekstu podanego jako parametr w poziomie (w pikselach). |
TextHeight | Zwraca wielkość tekstu podanego jako parametr w pionie (w pikselach). |
Unlock | Odblokowuje płótno (po jego wcześniejszym zablokowaniu przez procedurę Lock). |
Refresh | Odświerza płótno. |
Drukujemy obrazek
Przejdźmy do rzeczy nieco trudniejszych niż drukowanie tekstu. Wydrukujmy obrazek. Co wy na to? Hmm... Myślę, że brzmi to interesująco. Potrzebny będzie nam tylko jakiś obrazek typu BMP. Spróbujmy więc.
- Uruchamiamy Delphi'ego.
- Naciśnięciem klawisza F12 przechodzimy do "Edytora kodu".
- Do listy "uses" dodajemy moduł "Printers".
- Do globalnej (tej przedimplementation) sekcji "var" dodajemy deklarację nowej klasy:
Drukarka: TPrinter;
- Przechodzimy do widoku formularza (F12).
- Kładziemy na formularzu nowy przycisk.
- Klikamy nań dwukrotnie, przez co znów przechodzimy do "Edytora kodu", który czeka na nas z nowo-utworzoną procedurą.
- Uzupełniamy procedurę następująco:
procedure TForm1.Button1Click(Sender: TObject); var obrazek : TBitmap; begin // Tworzymy nową klasę TBitmap obrazek := TBitmap.Create; // Ładujemy obrazek z pliku obrazek.LoadFromFile('C:\obrazek.bmp'); // Utworzenie klasy Drukarka := TPrinter.Create; // Rozpoczęcie drukowania Drukarka.BeginDoc; // Rysujemy obrazek na płótnie drukarki Drukarka.Canvas.Draw(0,0,obrazek); // Zmienna obrazek nie będzie już nam // potrzebna więc zwalniamy zajmowaną przez nią pamięć obrazek.Free; // Zakończenie drukowania Drukarka.EndDoc; end;
To już koniec. Tyle poleceń wystarczy aby wydrukować obrazek. Co zrobić aby był on na środku strony? Pomyślmy... Aby wypozycjonować obrazek w poziomie trzeba podzielić szerokość strony przez dwa i odjąć jeszcze połowę szerokości obrazka. Analogicznie należy postąpić z pozycją pionową:
Teoria | Wynik |
![]() |
![]() |
![]() |
![]() |
Po połączeniu wyników naszej pracy otrzymujemy efekt końcowy |
![]() |
procedure TForm1.Button1Click(Sender: TObject);
var
obrazek : TBitmap;
begin
// Tworzymy nową klasę TBitmap
obrazek := TBitmap.Create;
// Ładujemy obrazek z pliku
obrazek.LoadFromFile('C:\obrazek.bmp');
// Utworzenie klasy
Drukarka := TPrinter.Create;
// Rozpoczęcie drukowania
Drukarka.BeginDoc;
// Rysujemy obrazek na płótnie drukarki (wyśrodkowany)
Drukarka.Canvas.Draw((Drukarka.PageWidth div 2)-(obrazek.Width div 2), (Drukarka.PageHeight div 2)-(obrazek.Height div
2), obrazek);
// Zmienna obrazek nie będzie już nam
// potrzebna więc zwalniamy zajmowaną przez nią pamięć
obrazek.Free;
// Zakończenie drukowania
Drukarka.EndDoc;
end;
Może nie jest to najpiękniejsze rozwiązanie problemu, ale ważne, że działa (przynajmniej u mnie ;)
Nasz wydrukowany obrazek jest jednak zbyt mały na wydruku. Co zrobić? Musimy go przeskalować! Najprostszą metodą jest napisanie takich instrukcji:
procedure TForm1.Button1Click(Sender: TObject);
var
Obrazek : TBitmap;
ProporcjaX, ProporcjaY : integer;
Obszar : TRect;
NowaSzerokosc, NowaWysokosc : integer;
begin
// Tworzymy nowe klasy typu TBitmap
Obrazek := TBitmap.Create;
// Utworzenie nowej klasy TPrinter
Drukarka := TPrinter.Create;
// Ustawianie orientacji strony na poziomą
Drukarka.Orientation := poLandscape;
// Liczymy proporcję rozdzielczości monitora do rozdzielczości drukarki
ProporcjaX := Drukarka.PageWidth div Screen.Width;
ProporcjaY := Drukarka.PageHeight div Screen.Height;
// Ładujemy obrazek z pliku
Obrazek.LoadFromFile('C:\obrazek.bmp');
// Nowy obrazek będzie miał rozmiar proporcjonalnie większy do starego
NowaSzerokosc := Obrazek.Width * ProporcjaX;
NowaWysokosc := Obrazek.Height * ProporcjaY;
// Stosujemy powiększenie obrazka zgodnie z obliczonymi proporcjami
Obszar := Rect((Drukarka.PageWidth div 2)-(NowaSzerokosc div 2),
(Drukarka.PageHeight div 2)-(NowaWysokosc div 2),
(Drukarka.PageWidth div 2)+(NowaSzerokosc div 2),
(Drukarka.PageHeight div 2)+(NowaWysokosc div 2));
// Rozpoczęcie drukowania
Drukarka.BeginDoc;
// Rysujemy odpowiednio powiększony obrazek na płótnie drukarki
Drukarka.Canvas.StretchDraw(Obszar, Obrazek);
// Zakończenie drukowania
Drukarka.EndDoc;
end;
Zwróćcie uwagę na linijkę zmieniającą orientację strony. Jest ona niezbędna do prawidłowego działania programu, gdyż zmienia orientację strony na taką, jaką mamy okazję obserwować na ekranie monitora (szerokość większa od wysokości).
Zakończenie
W przeciągu kilkunastu minut nauczyliście się obsługiwać drukarki. Pomyślcie co bylibyście w stanie zrobić przez minut czterdzieści! ;)
Do artykułu załączam kod źródłowy programu drukującego skalowane obrazki. Jest to typowy przykład dla tych którzy do tej pory nie uruchomili Delphiego ;)
Jednocześnie informuje, że zmienił się nieznacznie adres e-mail na który możecie pisać. Nowy adres e-mail macie poniżej.
Pozdrawiam!





Podobne artykuly:
- KillAd
- Delphi - Budowa modułu
- Delphi - Piszemy własny odtwarzacz multimedialny
- Delphi - Piszemy prosty edytor tekstu
- Delphi - Jak pisać?
- Delphi - Pobieranie plików z Internetu
- Delphi - Potęga możliwości ShellExecute()