|
Электронные мозги могут ошибаться горазда точнее.
|
Я написал программу, передающую невидимому 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;
|
|