Drukowanie Memo
Adam Boduch
Komponent "Memo" nie posiada odpowiedniej procedury drukowania tekstu tak jak to jest w przypadku komponentu "RichEdit" - trzeba takową napisać.
Przy pisaniu procedury drukującej trzeba wsiąść pod uwagę wiele czynników m.in. ile linii zmieści się na jednej stronie, wysokość linii, odstępy między liniami.
Nie będę tutaj opisywał samego procesu drukowania - o tym możecie poczytać w artykule "Drukowanie".
Na samym początku należy obrać jednostkę miary. W naszym przypadku będzie to piksel. Należy jeszcze przeliczyć ilość
pikseli na jeden cal. Umożliwia to polecenie "GetDeciveCaps":
// liczba pikseli w poziomie
GetDeviceCaps(Printer.Handle, LOGPIXELSX);
// liczba pikseli w pionie
GetDeviceCaps(Printer.Handle, LOGPIXELSY);
Na tej podstawie można już obliczyć wysokość jednej linii:
{ Przypisz do drukarki czcionke uzywana przez komponent typu TMemo" }
Printer.Canvas.Font := memText.Font;
{
Tutaj nastepuje obliczenie wysokosci linii na podst. wielkosci czcionki uzywanej przez komponent "memo". Funkcja "MulDiv" wyznacza wysokosc linii, a polecenie "GetDeviceCaps" oblicza liczbe pikseli na cal ekranu ( LOGPIXELSY ). Wszystko to musi byc opatrzone slowem "Abs", ktore powoduje przeksztalcenie liczby ujemnej na dodatnia jezzeli nachodzi taka potrzeba.
}
LineHeight := Abs(MulDiv(Printer.Canvas.Font.Size,
GetDeviceCaps(Printer.Handle, LOGPIXELSY), 70));
To już mamy. Trzeba teraz sprawdzić ile linii zmieści się na jednej stronie:
LineCount := (Printer.PageHeight div LineHeight) - 5;
Liczbę linii przypadających na jedną stronę obliczana jest na podst. wysokości strony. Ta wartość zostanie dzielona przez wysokość linii co daje liczbę mogących się znaleźć na jednej stronie linijek. Od tej wartości odejmowana jest cyfra 5, żeby zostawić miejsce na dolny nagłówek.
To nie jest jednak wszystko co związane jest z obliczaniem różnych
wartości. Trzeba bowiem obliczyć przerwę między kolejnymi liniami.
Ja przyjąłem wartość 30% z wielkości linii. Oto kod:
{
Tutaj natomias oblicznaa jest wilekosc odstepu pomiedzy poszczegolnymi liniami. Wielkosc lini mnozona jest przez 3, a nastepnie wartosc ta dzielona jest przez 0 co w rezultadzie daje odstep w wysokosci 30%
}
Inc(LineHeight, (LineHeight * 3) div 10);
Ufff. Zacznijmy drukować :) Ja zrobiłem tak, aby można było na
samej górze strony umieszczać nagłówek. Ponieważ wyśrodkowanie
tekstu w poziomie umożliwia funkcja "DrawText" trzeba się
trochę pobawić. Funkcja ta wymaga podania prostokąta wobec którego
tekst zostanie wyśrodkowany. Trzeba w tym celu zadeklarować
zmienną typu "TRect".
{
Nastepuje tutaj oblicznie wielkosci naglowka. Zmienna "R" zawiera teraz kwadrat wewnatrz ktorego rysowany bedzie tekst. Kwadrat ten bedzie mial wysokosc dwoch linii tekstu.
}
with R do
begin
Top := LineHeight;
Left := 20;
Right := Printer.PageWidth; // szerokość strony
Bottom := LineHeight * 2;
end;
{ Wyswietl wycentrowany tekst mieszczacy sie w kwadracie "R". }
DrawText(Printer.Handle,
'Service for programmers [http://www.programowanie.of.pl]',-1, R, DT_CENTER);
Nagłówek już mamy. Jest OK. Może teraz wydaje Ci się to niejasne, ale poniżej przedstawiam cały listing i mam nadzieje, że wiele rzeczy się wówczas wyjaśni.
(****************************************************************)
(* *)
(* Example - programme printing text for Delphi 5 *)
(* Copyright (c) 2001 by Service for programmers *)
(* Adam Boduch - Build: 17.03.2001 *)
(* HTTP://WWW.PROGRAMOWANIE.OF.PL *)
(* E - mail: boduch@poland.com *)
(* *)
(****************************************************************)
unit MainFrm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TMainForm = class(TForm)
memText: TMemo;
btnPrint: TButton;
procedure btnPrintClick(Sender: TObject);
private
procedure PrintText(PText : TStrings; lMargin : Integer = 20);
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
uses Printers; { <-- modul umozliwiajacy operaje drukowania }
{$R *.DFM}
procedure TMainForm.PrintText(PText: TStrings; lMargin : Integer);
var
S : String;
I : Integer;
R : TRect;
LineCount : Integer; // ilosc linii mogacych zmiescic sie na jednej stronie
LineHeight : Integer; // wysokosc jednej linii na podst. wielkosci czcionki
Line : Integer; // aktualnie drukowana linia
begin
{ Przypisz do drukarki czcionke uzywana przez komponent typu "TMemo" }
Printer.Canvas.Font := memText.Font;
{
Tutaj nastepuje obliczenie wysokosci linii na podst. wielkosci czcionki uzywanej rzez komponent "memo". Funkcja "MulDiv" wyznacza wysokosc linii, a polecenie "GetDeviceCaps" oblicza liczbe pikseli na cal ekranu ( LOGPIXELSY ). Wszystko to musi byc opatrzone slowem "Abs", ktore powoduje przeksztalcenie liczby ujemnej na dodatnia jezzeli nachodzi taka potrzeba.
}
LineHeight := Abs(MulDiv(Printer.Canvas.Font.Size,
GetDeviceCaps(Printer.Handle, LOGPIXELSY), 70));
{
Tutaj natomias oblicznaa jest wilekosc odstepu pomiedzy poszczegolnymi liniami. Wielkosc lini mnozona jest przez 3, a nastepnie wartosc ta dzielona jest przez 10 co w rezultadzie daje odstep w wysokosci 30%
}
Inc(LineHeight, (LineHeight * 3) div 10);
{
Okreslenie ilosci linii mogacych sie znalezc na jednej stronie. Wartosc ta obliczana na podst. wysokosci strony, ktora to wielkosc zostanie dzielona przez wielkosc linii, a nastepnie od tej wartosci odejmowana jest cyfra 5, aby zostawic miejsce na dolny margines.
}
LineCount := (Printer.PageHeight div LineHeight) - 5;
Line := 5; // rozpocznij drukowanie w piatej linijce
Printer.BeginDoc; // rozpocznij drukowanie
{
Nastepuje tutaj oblicznie wielkosci naglowka. Zmienna "R" zawiera teraz kwadrat wewnatrz ktorego rysowany bedzie tekst. Kwadrat ten bedzie mial wysokosc dwoch linii tekstu.
}
with R do
begin
Top := LineHeight;
Left := 20;
Right := Printer.PageWidth; // szerokosc strony
Bottom := LineHeight * 2;
end;
{ Wyswietl wycentrowany tekst mieszczacy sie w kwadracie "R". }
DrawText(Printer.Handle,
'Service for programmers [http://www.programowanie.of.pl]', -1, R, DT_CENTER);
{
Przed chwila wydrukowany zostal naglowek. Teraz do tej wartosci dodawana jest liczba odpoiwadajaca wysokosci dwoch linii. Nastepnie rysowana zostaje pozioma linia przedzielajca naglowek od wlasciwego tekstu.
}
with Printer do
begin
Canvas.MoveTo(0, R.Top + LineHeight * 2);// ustaw kursor we właściwym miejscu
Canvas.LineTo(R.Right, R.Top + LineHeight * 2); // rysuj linie
end;
{
Ta pela odpowiada za drukowanie poszczegolnych linii - od zerowej do konca zawartosci zmiennej "PText".
}
for I := 0 to PText.Count -1 do
begin
Inc(Line); // zwieksz wartosc aktualnie drukowanej linii
if Line = LineCount then // Jezeli wiecej linii na stronie sie nie zmiesci...
begin
Line := 5; // ustaw na poczatku strony
Printer.NewPage; // rozpocznij drukowanie nowej strony
end;
S := PText.Strings[i]; // do zmiennej "S" przypisz aktualnie drukowana linie
{
Wydrukuj linie. Zostanie ona wydrukowana w miejscu okreslonym przez uzytkownika - tzn. poczatek drukowanej linii bedzie w punkcie oznaczonym przez zmienna "lMargin". Pozycja Y druokowanego tekstu okreslana bedzie przez pomnozenie aktualnie drukowanej linii przez wysokosc linii.
}
Printer.Canvas.TextOut(lMargin, Line * LineHeight, S);
end;
Printer.EndDoc; // zakoncz drukowanie
end;
procedure TMainForm.btnPrintClick(Sender: TObject);
begin
PrintText(memText.Lines); // wywolaj procedure
end;
end.
Taka mała rzecz. Jak wstawiłem to i drukowałem wieksze litery, a program (i pole Memo) były na cały ekran (rozdzielczość 1024/768) to linie ywszły po za kartkę :D
A może mi ktoś wytłumaczyć czym różni się RichEdit od Memo????
DO DUPY TO BYŁO
Jest troche roboty, ale można też tak
RichEdit1.Lines:= Memo1.Lines; RichEdit1.Print(); Richedit1.Lines.Clear;
Dla leniwych :)
Bardzo ciekawe!