A: Here is the short and elegant way that works:
function TForm1.MemoLinesShowing(memo: TMemo): integer;
var
R: TRect;
begin
memo.Perform(EM_GETRECT, 0, Longint(@R));
result := (R.Bottom - R.Top) div Canvas.TextHeight('XXX');
end;
The caveat with this code is that it must use the same font for the
memo as the form uses. If the fonts are different, then there
is a problem or two to be solved. You can't just get the font
height. (That would be too easy. <G>) Delphi caches the
font but doesn't acutally select the font into the DC (canvas) until it
is actually going to draw something. That is why we have do
jump through these hoops. The problem in getting the
text height for a memo component is the font used in the memo
is not selected into the dc until a draw event happens. The cure is to
get the font and select it into the dc, then calc the text height!
function TForm1.MemoLinesShowingLong(memo: TMemo): integer;
Var
oldfont: HFont; {the old font}
dc: THandle; {a dc handle}
i: integer; {loop variable}
tm: TTextMetric; {text metric structure}
TheRect: TRect;
begin
dc := GetDC(Memo.handle); {Get the Dc for the memo}
oldFont := SelectObject(dc, Memo.Font.handle); {Select the memo's
font}
GetTextMetrics(dc, tm); {Get the text metric info}
memo.perform(em_GetRect, 0, longint(@TheRect));
result := (TheRect.bottom - TheRect.top) DIV (tm.tmHeight +
tm.tmExternalLeading);
SelectObject(dc, oldfont); {Select the old font}
ReleaseDC(Memo.handle, dc); {Release the Dc}
end;