Советы по Delphi

         

Я написал программу, передающую невидимому


Я написал программу, передающую невидимому RichEdit введенную пользователем с помощью кнопок и нескольких checkbox (кнопки с независимой фиксацией) информацию. Программа разрабатывалась и эксплуатировалась под Windows 95 и работала без проблем. Но под NT 4.0 строка ...

RichEdit1.Print('');

возвращала ошибку "Divide by Zero" (деление на ноль). Единственный выход из создавшегося положения заключался в сохранении файла c последующей его загрузкой и печатью с помощью MS Word.

Кому-нибудь приходилось решать эту проблему?

Да, я знаю что нужно сделать...

Чтобы решить эту проблему, необходимо небольшое хирургическое вмешательство в VCL модуль ComCtrls.pas.

Я протестировал исправленный код на большинстве платформ, в том числе на NT 4.0 и Win95, и, кажется, все работает как положено. На самом деле это легко исправить, только нужно знать где...

    {
Существует проблема совместимости при вызове оригинального метода RichEdit.Print


под NT 4.0. Исключительная ситуация EDivByZero происходит из-за того,
что свойство Printer.Handle вне блока BeginDoc/EndDoc под NT 4.0
возвращает дескриптор информационного контекста (Information Context - IC) вместо
дескриптора контекста устройства (Device Context - DC). EM_FORMATRANGE пытается использовать этот IC
вместо реального DC принтера, вызывая этим исключительную ситуацию. Если свойство Handle
акцептуется ПОСЛЕ BeginDoc, дескриптор контекста устройства возвращает истину,
что и было мною исправлено в коде. Я оставил на том же месте в коде оригинальное
месторасположение вызова BeginDoc, при этом сделав соответствующий комментарий
для указания на внесенные изменения.
}
procedure TCustomRichEdit.Print(const Caption: string);
var
Range: TFormatRange; LastChar, MaxLen, LogX, LogY: Integer; begin
FillChar(Range, SizeOf(TFormatRange), 0); with Printer, Range do begin LogX := GetDeviceCaps(Handle, LOGPIXELSX); LogY := GetDeviceCaps(Handle, LOGPIXELSY); // Спозиционированный вызов BeginDoc для обеспечения // совместимости под NT 4.0 и Win95 BeginDoc; hdc := Handle; hdcTarget := hdc; 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; Title := Caption; // Оригинальная позиция BeginDoc { BeginDoc; } LastChar := 0; MaxLen := GetTextLen; chrg.cpMax := -1; repeat 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; end; SendMessage(Handle, EM_FORMATRANGE, 0, 0); end;
Nomadic советует:

Проблема, насколько помнится, касается только Delphi 2.0 без патчей.

сходил на http://www.borland.com и -

    unit PrtRichU;
interface

uses
SysUtils, Windows, Classes, ComCtrls, RichEdit, Printers;

procedure PrintRichEdit(const Caption: string; const RichEdt: TRichEdit);

implementation

procedure
PrintRichEdit(const Caption: string; const RichEdt: TRichEdit);
var
Range: TFormatRange;
LastChar, MaxLen, LogX, LogY, OldMap: Integer;
begin
FillChar(Range, SizeOf(TFormatRange), 0);
with Printer, Range do
begin

BeginDoc;
hdc := Handle;
hdcTarget := hdc;
LogX := GetDeviceCaps(Handle, LOGPIXELSX);
LogY := GetDeviceCaps(Handle, LOGPIXELSY);
if IsRectEmpty(RichEdt.PageRect) then
begin

rc.right := PageWidth * 1440 div LogX;
rc.bottom := PageHeight * 1440 div LogY;
end
else
begin

rc.left := RichEdt.PageRect.Left * 1440 div LogX;
rc.top := RichEdt.PageRect.Top * 1440 div LogY;
rc.right := RichEdt.PageRect.Right * 1440 div LogX;
rc.bottom := RichEdt.PageRect.Bottom * 1440 div LogY;
end;
rcPage := rc;
Title := Caption;
LastChar := 0;
MaxLen := RichEdt.GetTextLen;
chrg.cpMax := -1; OldMap := SetMapMode(hdc, MM_TEXT);
SendMessage(RichEdt.Handle, EM_FORMATRANGE, 0, 0);
try
repeat

chrg.cpMin := LastChar;
LastChar := SendMessage(RichEdt.Handle, EM_FORMATRANGE, 1,
Longint(@Range));
if (LastChar < MaxLen) and (LastChar <> -1) then NewPage;
until (LastChar >= MaxLen) or (LastChar = -1);
EndDoc;
finally
SendMessage(RichEdt.Handle, EM_FORMATRANGE, 0, 0);
SetMapMode(hdc, OldMap);
end;
end;
end;

end.
и печатает.

Версия DBaware - TrxDBRichEdit из комплекта RX Library. Более корректный компонент - TrxRichEdit из комплекта RX Library. [000233]


Содержание раздела