Delphi World - Распечатать RTF-файл и определить диапазон страницы для печати
Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Распечатать RTF-файл и определить диапазон страницы для печати

Оформил: DeeCo
Автор: http://www.swissdelphicenter.ch

unit Unit1;

 interface

 uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, RichEdit, RxRichEd, ExtCtrls, Printers;

 type
   TPageOffset = record
     mStart,
     mEnd: Integer;
     rendRect: TRect;
   end;
   TForm1 = class(TForm)
     Panel1: TPanel;
     Editor: TRxRichEdit;
     PrintBtn: TButton;
     PreviewBtn: TButton;
     CloseBtn: TButton;
     procedure PrintBtnClick(Sender: TObject);
     procedure PreviewBtnClick(Sender: TObject);
     procedure CloseBtnClick(Sender: TObject);
     procedure FormShow(Sender: TObject);
   private
     { Private-Deklarationen }
   public
     { Public-Deklarationen }
   end;

 var
   Form1: TForm1;

 implementation

 uses Unit2;

 {$R *.dfm}

 procedure TForm1.PrintBtnClick(Sender: TObject);
 var
    wPage, hPage, xPPI, yPPI, wTwips, hTwips: integer;
   pageRect, rendRect: TRect;
   po: TPageOffset;
   fr: TFormatRange;
   lastOffset, currPage, pageCount: integer;
   xOffset, yOffset: integer;
   FPageOffsets: array of TPageOffset;
   TextLenEx: TGetTextLengthEx;
   firstPage: boolean;
 begin
   //First, get the size of a printed page in printer device units 
  wPage := GetDeviceCaps(Printer.Handle, PHYSICALWIDTH);
   hPage := GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);
   //Next, get the device units per inch for the printer 
  xPPI := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
   yPPI := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
   //Convert the page size from device units to twips 
  wTwips := MulDiv(wPage, 1440, xPPI);
   hTwips := MulDiv(hPage, 1440, yPPI);
   //Save the page size in twips 
  with pageRect do
    begin
     Left := 0;
     Top := 0;
     Right := wTwips;
     Bottom := hTwips
   end;
   //Next, calculate the size of the rendering rectangle in twips 
  //Rememeber - two inch margins are hardcoded, so the below code 
  //reduces the width of the output by four inches 
  with rendRect do
    begin
     Left := 0;
     Top := 0;
     Right := pageRect.Right - (1440 * 4);
     Bottom := pageRect.Bottom - (1440 * 4)
   end;
   //Define a single page and set starting offset to zero 
  po.mStart := 0;
   //Define and initialize a TFormatRange structure. This structure is passed 
  //to the TRichEdit with a request to format as much text as will fit on a 
  //page starting with the chrg.cpMin offset and ending with the chrg.cpMax. 
  //Initially, we tell the RichEdit control to start at the beginning 
  //(cpMin = 0) and print as much as possible (cpMax = -1). We also tell it 
  //to render to the printer 
  with fr do
    begin
     hdc := Printer.Handle;
     hdcTarget  := Printer.Handle;
     chrg.cpMin := po.mStart;
     chrg.cpMax := -1;
   end;
   //In order to recognize when the last page is rendered, we need to know how 
  //much text is in the control. 
  if RichEditVersion >= 2 then
    begin
     with TextLenEx do
      begin
       flags := GTL_DEFAULT;
       codepage := CP_ACP;
     end;
     lastOffset := SendMessage(Editor.Handle, EM_GETTEXTLENGTHEX, wParam(@TextLenEx), 0)
   end
   else
      lastOffset := SendMessage(Editor.Handle, WM_GETTEXTLENGTH, 0, 0);
   //As a precaution, clear the formatting buffer 
  SendMessage(Editor.Handle, EM_FORMATRANGE, 0, 0);
   //Printers frequently cannot print at the absolute top-left position on the 
  //page. In other words, there is usually a minimum margin on each edge of the 
  //page. When rendering to the printer, RichEdit controls adjust the top-left 
  //corner of the rendering rectangle for the amount of the page that is 
  //unprintable. Since we are printing with two-inch margins, we are presumably 
  //already within the printable portion of the physical page. 
  SaveDC(fr.hdc);
   SetMapMode(fr.hdc, MM_TEXT);
   xOffset := GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);
   yOffset := GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY);
   xOffset := xOffset + MulDiv(1440 + 1440, xPPI, 1440);
   yOffset := yOffset + MulDiv(1440 + 1440, yPPI, 1440);
   SetViewportOrgEx(fr.hdc, xOffset, yOffset, nil);
   //Now we build a table of page entries, one entry for each page that would be 
  //printed. 
  while ((fr.chrg.cpMin <> -1) and (fr.chrg.cpMin < lastOffset)) do
    begin
     fr.rc := rendRect;
     fr.rcPage := pageRect;
     po.mStart := fr.chrg.cpMin;
     fr.chrg.cpMin := SendMessage(Editor.Handle, EM_FORMATRANGE, 0, Longint(@fr));
     po.mEnd := fr.chrg.cpMin - 1;
     po.rendRect := fr.rc;
     if High(FPageOffsets) = -1 then SetLength(FPageOffsets, 1)
     else
        SetLength(FPageOffsets, Length(FPageOffsets) + 1);
     FPageOffsets[High(FPageOffsets)] := po
   end;
   pageCount := Length(FPageOffsets);
   ShowMessage(Format('Es wurde %d Seiten ermittelt', [pageCount]));
   SendMessage(Editor.Handle, EM_FORMATRANGE, 0, 0);
   RestoreDC(fr.hdc, - 1);
   //Now, we are almost ready to actually print. 
  Printer.BeginDoc;
   fr.hdc := Printer.Handle;
   fr.hdcTarget := Printer.Handle;
   SaveDC(fr.hdc);
   SetViewportOrgEx(fr.hdc, xOffset, yOffset, nil);
   //Ok, here we go to print 
  firstPage := True;
   //At this point you can select from page and to page 
  currPage := 0;  //Print from the first page 
  pageCount := 1;  //Only One page for testing 
  while (currPage < pageCount) do
    begin
     if firstPage then firstPage := False
     else
        Printer.NewPage;
     SetViewportOrgEx(fr.hdc, xOffset, yOffset, nil);
     fr.rc := FPageOffsets[currPage].rendRect;
     fr.rcPage := pageRect;
     fr.chrg.cpMin := FPageOffsets[currPage].mStart;
     fr.chrg.cpMax := FPageOffsets[currPage].mEnd;
     fr.chrg.cpMin := SendMessage(Editor.Handle, EM_FORMATRANGE, 1, Longint(@fr));
     Inc(currPage);
   end;
   //At this point, we have finished rendering the contents of the RichEdit 
  //control. Now we restore the printer's HDC settings and tell Windows that 
  //we are through printing this document 
  RestoreDC(fr.hdc, - 1);
   Printer.EndDoc;
   //Finally, we clear the RichEdit control's formatting buffer and delete 
  //the saved page table information 
  fr.chrg.cpMin := SendMessage(Editor.Handle, EM_FORMATRANGE, 0, 0);
   Finalize(FPageOffsets);
   //That's it 
end;

 procedure TForm1.PreviewBtnClick(Sender: TObject);
 begin
   PreviewForm.ShowModal
 end;

 procedure TForm1.CloseBtnClick(Sender: TObject);
 begin
   Close
 end;

 procedure TForm1.FormShow(Sender: TObject);
 begin
   Editor.Lines.LoadFromFile('Exceltabelle.rtf');
 end;

 end.
Проект Delphi World © Выпуск 2002 - 2017
Автор проекта: Эксклюзивные курсы программирования