Главная страница | назад





Article #26772: How to resolve printing problems with TRichEdit on Windows 2000

Question

I'm trying to use a TPrintDialog with a TRichEdit under Windows 2000 and it's printing enormous amounts of blank pages (spooling infinitely). How do I fix this?

Answer

This is a problem with the way the EM_FORMATRANGE message changed with the advent of Windows 2000. The problem can be easily fixed by modifying ComCtrls.pas (located within $(BCB)sourcevcl), and compiling that file with (adding it to) all your projects that are affected by this problem. (NOTE: this change is unofficial and unsupported). You'll need to make the following changes in ComCtrl.pas:


//you'll need to add this function above TCustomRichEdit.Print
function GetPreciseTextLen(ARichEditCtrl : TRichedit): integer;
var
gtlex : TGetTextLengthEx;
begin
with gtlex do
begin
flags := GTL_PRECISE;
codepage := CP_ACP;
end;
Result := ARichEditCtrl.Perform(EM_GETTEXTLENGTHEX,WPARAM(@gtlex), 0 );
end;
//---------end new function---------
//this is the print function.
procedure TCustomRichEdit.Print(const Caption: string);
var
Range: TFormatRange;
LastChar, MaxLen, LogX, LogY, OldMap: Integer;
SaveRect: TRect;
begin
FillChar(Range, SizeOf(TFormatRange), 0);
with Printer, Range do
begin
Title := Caption;
BeginDoc;
hdc := Handle;
hdcTarget := hdc;
LogX := GetDeviceCaps(Handle, LOGPIXELSX);
LogY := GetDeviceCaps(Handle, LOGPIXELSY);
if IsRectEmpty(PageRect) then
begin
rc.right := PageWidth * 1440 div LogX;
rc.bottom := PageHeight * 1440 div LogY;
end
else begin
rc.left := PageRect.Left * 1440 div LogX;
rc.top := PageRect.Top * 1440 div LogY;
rc.right := PageRect.Right * 1440 div LogX;
rc.bottom := PageRect.Bottom * 1440 div LogY;
end;
rcPage := rc;
SaveRect := rc;
LastChar := 0;
// (commented out )MaxLen := GetTextLen; remove this line
MaxLen := GetPreciseTextLine; //add this line
chrg.cpMax := -1;
// ensure printer DC is in text map mode
OldMap := SetMapMode(hdc, MM_TEXT);
SendMessage(Self.Handle, EM_FORMATRANGE, 0, 0); // flush buffer
try
repeat
rc := SaveRect;
chrg.cpMin := LastChar;
LastChar := SendMessage(Self.Handle, EM_FORMATRANGE, 1, Longint(@Range));
if (LastChar < MaxLen) and (LastChar <> -1) then NewPage;
until (LastChar >= MaxLen) or (LastChar = -1);
EndDoc;
finally
SendMessage(Self.Handle, EM_FORMATRANGE, 0, 0); // flush buffer
SetMapMode(hdc, OldMap); // restore previous map mode
end;
end;
end;

Last Modified: 01-FEB-01