kolmck/Addons/richprint.pas

203 lines
5.8 KiB
ObjectPascal

unit RichPrint;
{* By Savva. A unit to print rich edit control content. }
interface
uses Windows, KOL, {$IFNDEF NOT_USE_PRINTER_OBJ}
{$IFDEF USE_MHPRINTER} KOLMHPrinters {$ELSE} KOLPrinters {$ENDIF}
,{$ENDIF}
RichEdit, CommDlg;
procedure FilePrint(ACaption : string;fRichEdit : PControl);
{* ïå÷àòü áåç èñïîëüçîâàíèÿ îáúåêòà Printer }
{$IFNDEF NOT_USE_PRINTER_OBJ}
procedure PrintRichEdit(CONST fRichEdit : PControl;const Caption: string);
{* ïå÷àòü c èñïîëüçîâàíèåì îáúåêòà Printer }
{$ENDIF}
implementation
//*****************************************************
// ïå÷àòü áåç èñïîëüçîâàíèÿ îáúåêòà Printer
// -----------------------------------------------------
// Ôóíêöèÿ FilePrint
// -----------------------------------------------------
procedure FilePrint(ACaption : string;fRichEdit : PControl);
var
fr : FORMATRANGE;
docInfo : TDOCINFO;
lLastChar, lTextSize :integer ;
pd : TPRINTDLG ;
nRc : integer ;
hPrintDC : HDC ;
szErr : string;
dwErr :DWORD ;
//TextLenEx: TGetTextLengthEx;
begin
// Èíèöèàëèçèðóåì ïîëÿ ñòðóêòóðû PRITDLG
ZeroMemory(@pd, sizeof(pd));
pd.lStructSize := sizeof(TPRINTDLG);
pd.hwndOwner := fRichEdit.Handle;
pd.hInstance := HInstance;
pd.Flags := PD_RETURNDC or PD_NOPAGENUMS or PD_NOSELECTION or PD_PRINTSETUP or
PD_ALLPAGES;
pd.nFromPage := $ffff;
pd.nToPage := $ffff;
pd.nMinPage := 0;
pd.nMaxPage := $ffff;
pd.nCopies := 1;
// Âûâîäèì íà ýêðàí äèàëîãîâóþ ïàíåëü, ïðåäíàçíà÷åííóþ
// äëÿ ïå÷àòè äîêóìåíòà
if PrintDlg(pd) then begin
// if(TRUE) then begin
hPrintDC := pd.hDC;
// Èíèöèàëèçèðóåì ïîëÿ ñòðóêòóðû FORMATRANGE
ZeroMemory(@fr, sizeof(fr));
// Áóäåì ïå÷àòàòü ñ èñïîëüçîâàíèåì êîíòåêñòà
// ïðèíòåðà, ïîëó÷åííîãî îò ôóíêöèè PrintDlg
fr.hdc := hPrintDC;
fr.hdcTarget:=fr.hdc;
// Ïå÷àòàåì âåñü äîêóìåíò
fr.chrg.cpMin := 0;
fr.chrg.cpMax := -1;
// Óñòàíàâëèâàåì ðàçìåðû ñòðàíèöû â TWIPS-àõ
fr.rcPage.top := 0;
fr.rcPage.left := 0;
fr.rcPage.right :=
MulDiv(GetDeviceCaps(hPrintDC, PHYSICALWIDTH),
1440, GetDeviceCaps(hPrintDC, LOGPIXELSX));
fr.rcPage.bottom := MulDiv(GetDeviceCaps(hPrintDC,
PHYSICALHEIGHT),1440,
GetDeviceCaps(hPrintDC, LOGPIXELSY));
fr.rc := fr.rcPage;
// Îñòàâëÿåì ïîëÿ
if (fr.rcPage.right > 2*3*1440/4+1440) then begin
fr.rc.left := 3*1440 div 4;
fr.rc.right :=fr.rc.right - (fr.rc.left);
end;
if(fr.rcPage.bottom > 3*1440) then begin
fr.rc.top := 1440;
fr.rc.bottom:=fr.rc.bottom - (fr.rc.top);
end;
// Çàïîëíÿåì ïîëÿ ñòðóêòóðû DOCINFO
ZeroMemory(@docInfo, sizeof(DOCINFO));
docInfo.cbSize := sizeof(DOCINFO);
docInfo.lpszOutput := nil;
docInfo.lpszDocName := PChar(ACaption);
// Íà÷èíàåì ïå÷àòü äîêóìåíòà
nRc := StartDoc(hPrintDC, docInfo);
// Åñëè ïðîèçîøëà îøèáêà, ïîëó÷àåì è âûâîäèì íà ýêðàí
// êîä îøèáêè
if (nRc < 0) then begin
dwErr := GetLastError();
szErr:=format( 'Print Error %ld \r\n %s', [dwErr,SysErrorMessage(dwErr)]);
MessageBox(0, PChar(szErr),
'Error printing', MB_OK or MB_ICONEXCLAMATION);
DeleteDC(hPrintDC);
exit;
end;
// Íà÷èíàåì ïå÷àòü ñòðàíèöû
StartPage(hPrintDC);
lLastChar := 0;
// Îïðåäåëÿåì äëèíó òåêñòà
lTextSize := fRichEdit.RE_TextSizePrecise;
// Öèêë ïî âñåì ñòðàíèöàì äîêóìåíòà
while (lLastChar < lTextSize) do begin
// Ôîðìàòèðóåì äàííûå äëÿ ïðèíòåðà è ïå÷àòàåì èõ
lLastChar := SendMessage(fRichEdit.Handle, EM_FORMATRANGE, DWORD(TRUE),
LPARAM( @fr));
if(lLastChar < lTextSize) then begin
// Çàâåðøàåì ïå÷àòü î÷åðåäíîé ñòðàíèöû
EndPage(hPrintDC);
// Íà÷èíàåì íîâóþ ñòðàíèöó
StartPage(hPrintDC);
fr.chrg.cpMin := lLastChar;
fr.chrg.cpMax := -1;
end;
end;
// Óäàëÿåì èíôîðìàöèþ, êîòîðàÿ õðàíèòñÿ â
// îðãàíå óïðàâëåíèÿ Rich Edit
SendMessage(fRichEdit.Handle, EM_FORMATRANGE, DWORD(TRUE), LPARAM(nil));
// Çàâåðøàåì ïå÷àòü ñòðàíèöû
EndPage(hPrintDC);
// Çàâåðøàåì ïå÷àòü äîêóìåíòà
EndDoc(hPrintDC);
// Óäàëÿåì êîíòåêñò ïðèíòåðà
DeleteDC(hPrintDC);
end;
end;
{$IFNDEF NOT_USE_PRINTER_OBJ}
//*****************************************************
// ïå÷àòü c èñïîëüçîâàíèåì îáúåêòà Printer
procedure PrintRichEdit(CONST fRichEdit : PControl;const Caption: string);
var
Range: TFormatRange;
LastChar, MaxLen, LogX, LogY, OldMap: Integer;
SaveRect: TRect;
begin
FillChar(Range, SizeOf(TFormatRange), 0);
Printer.Title := Caption;
Printer.BeginDoc;
Range.hdc := Printer.Handle;
Range.hdcTarget := Range.hdc;
LogX := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
LogY := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
Range.rc.right := Printer.PageWidth * 1440 div LogX;
Range.rc.bottom := Printer.PageHeight * 1440 div LogY;
Range.rcPage := Range.rc;
SaveRect := Range.rc;
LastChar := 0;
// MaxLen := fRichEdit.Perform(WM_GETTEXTLENGTH, 0, 0);
MaxLen := fRichEdit.RE_TextSizePrecise;
Range.chrg.cpMax := -1;
// ensure printer DC is in text map mode
OldMap := SetMapMode(range.hdc, MM_TEXT);
fRichEdit.Perform(EM_FORMATRANGE, 0, 0); // flush buffer
try
repeat
Range.rc := SaveRect;
Range.chrg.cpMin := LastChar;
LastChar := fRichEdit.Perform(EM_FORMATRANGE, 1, Longint(@Range));
if (LastChar < MaxLen) and (LastChar <> -1) then Printer.NewPage;
until (LastChar >= MaxLen) or (LastChar = -1);
Printer.EndDoc;
finally
fRichEdit.Perform(EM_FORMATRANGE, 0, 0); // flush buffer
SetMapMode(Range.hdc, OldMap); // restore previous map mode
end;
end;
{$ENDIF}
end.