Strona g│≤wna

 

Drukowanie zawarto╢ci Memo

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.

Listing 1.1


(****************************************************************)
(*                                                              *)
(*      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.

Kodowy program korzystaj▒cy z tego kodu mo┐esz ╢ci▒gn▒µ klikaj▒c na poni┐szy link:

PrintMemo.zip ( 3 kB )

Przydatne linki:

  • podstawy drukowania [ Zobacz ]

Adam Boduch