Hi,
I'd like to be able at run-time to measure the screen size of the text of a
TRichEdit so that I can resize the control
to show exactly the text.
For that, I created the following function, based on TRichEdit.Print:
{
--------------------------------------------------------------------------------
}
Function GetTextHeightOfRichEdit(Const RichEdit : TCustomRichEdit) : Integer;
Var
Range: TFormatRange;
LastChar, MaxLen, OldMap, LogX, LogY : Integer;
SaveRect: TRect;
DC : HDC;
Begin
Result := 0;
{ We want to use the control itself as rendering DC: }
DC := GetDC(RichEdit.Handle);
LogX := GetDeviceCaps(DC, LOGPIXELSX);
LogY := GetDeviceCaps(DC, LOGPIXELSY);
FillChar(Range, SizeOf(TFormatRange), 0);
with Range do
begin
hdc := DC;
hdcTarget := DC;
rc.left := 0;
rc.top := 0;
{ The width of RichEdit will stay as it is, we want to know the
height of the text that fits in
this width (converted to TWIPS): }
rc.right := RichEdit.ClientWidth * 1440 div LogX;
rc.bottom := 0;
rcPage := rc;
{ Whole text: }
chrg.cpMax := -1;
End;
SaveRect := Range.rc;
LastChar := 0;
MaxLen := RichEdit.GetTextLen;
OldMap := SetMapMode(Range.hdc, MM_TEXT);
SendMessage(RichEdit.Handle, EM_FORMATRANGE, 0, 0);
try
repeat
Range.rc := SaveRect;
Range.chrg.cpMin := LastChar;
LastChar := SendMessage(RichEdit.Handle, EM_FORMATRANGE, 0,
LongInt(@Range));
Inc(Result, (Range.rc.Bottom * LogY Div 1440));
until (LastChar >= MaxLen) or (LastChar = -1);
finally
SendMessage(RichEdit.Handle, EM_FORMATRANGE, 0, 0);
SetMapMode(Range.hdc, OldMap);
ReleaseDC(RichEdit.Handle, DC);
end;
End;
When I want to resize my RichEdit, I just have to do:
RichEdit1.ClientHeight := GetTextHeightOfRichEdit(RichEdit1);
However, I have a small problem here:
It seems that the call to SendMessage(RichEdit.Handle, EM_FORMATRANGE, 0,
LongInt(@Range)) is executed for each line in my RichEdit, returning the
height of each line in Range.rc.Bottom instead of the whole text, hence the
need for me to add all the calculated heights in the function result via:
Inc(Result, (Range.rc.Bottom * LogY Div 1440)) inside the repeat loop.
In my Range param, I clearly specify that I want all the text measured
(chrg.cpMax := -1;) so what if wrong with my code?
Thanks for any help.
David.