Delphi - объектно-ориентированный язык программирования, разработанный компанией Borland в 1995 году. Он основан на языке программирования Pascal, но имеет более расширенные возможности и добавлены новые функции.
Delphi является интегрированной средой разработки (IDE), которая позволяет разрабатывать программное обеспечение для различных платформ, включая Windows, macOS, Android и iOS. Delphi достигает многоплатформенности с помощью...
unitUnit1; 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
.