我有一个TMemo,我想要总是让它足够高,以显示它包含的行数。不幸的是,我不太清楚如何计算。我不能将它基于.Font.Size
属性,因为这会因DPI而异。我无法使用TCanvas.TextHeight
,因为TMemo似乎没有画布。
任何人都知道如何做到这一点?
答案 0 :(得分:7)
我看到一个问题,我认为TMemo上的所有线条在高度上相等,但有些线条可能是空的......
因此,当TMemo上的高度不为零时,获得空的高度将为零。
因此,解决方案可能会执行类似Memo.Lines.Count * LineHeight
的操作请注意Canvas.TextHeight可能无法获取Lineheight,因为Canvas.TextHeight会为文本提供或多或少精确的最小高度...我的意思是它不会为文本'ABC'提供相同的高度而不是'ABCp'等......
我建议(如果不想调用Windows API)使用Font.Height,但如果是负数,则不测量每行的内部前导...
所以我建议你做下一步(测试):
我个人在TForm OnCreate事件上做这个(确保它只完成一次),只是为了确保不改变视觉字体大小,MyMemo.Font.Height包含每行的内部引导:
MyMemo.Font.Height:=Abs(MyMemo.Font.Size*MyMemo.Font.PixelsPerInch div Screen.PixelsPerInch);
确保以前只做一次,否则文字大小会越来越大,就像你运行它的次数一样......这是因为并非总是MyMemo.Font.PixelsPerInch等于Screen.PixelsPerInch ......在我的情况下,他们分别是80和96。
然后,当我需要知道行高时,我只需使用:
Abs(MyMemo.Font.Height*Screen.PixelsPerInch div 72)
这给出了一条TMemo线的精确高度,因为所有线都有相同的高度,总高度为:
MyMemo.Lines.Count*Abs(MyMemo.Font.Height*Screen.PixelsPerInch div 72)
因此,为了使TMemo的高度与其包含的文本一样大,我这样做(阅读每行的注释,它们非常重要):
MyMemo.Font.Height:=Abs(MyMemo.Font.Size*MyMemo.Font.PixelsPerInch div Screen.PixelsPerInch); // I do this on the Tform OnCreate event, to ensure only done once
MyMemo.Height:=1+MyMemo.Lines.Count*Abs(MyMemo.Font.Height*Screen.PixelsPerInch div 72); // I do this anywhere after adding the text and/or after editing it
我不想玩Screen.PixelsPerInch你可以这样做(阅读每一行的评论,它们非常重要):
MyMemo.Font.Height:=Abs(MyMemo.Font.Height); // This may make text size to visually change, that was why i use the corrector by using MyMemo.Font.PixelsPerInch and Screen.PixelsPerInch
MyMemo.Height:=1+MyMemo.Lines.Count*Abs(MyMemo.Font.Height*MyMemo.Font.PixelsPerInch div 72);
希望这可以帮助任何人。
答案 1 :(得分:4)
您可以为TMemo编写自己的TCanvas.TextHeight实现:
function CountMemoLineHeights(Memo: TMemo): Integer;
var
DC: HDC;
SaveFont: HFont;
Size: TSize;
I: Integer;
begin
DC:= GetDC(Memo.Handle);
SaveFont:= SelectObject(DC, Memo.Font.Handle);
Size.cX := 0;
Size.cY := 0;
// I have not noticed difference in actual line heights for TMemo,
// so the next line should work OK
Windows.GetTextExtentPoint32(DC, 'W', 1, Size);
// BTW next (commented) line returns Size.cY = 0 for empty line (Memo.Lines[I] = '')
// Windows.GetTextExtentPoint32(DC, Memo.Lines[I], Length(Memo.Lines[I]), Size);
Result:= Memo.Lines.Count * Size.cY;
SelectObject(DC, SaveFont);
ReleaseDC(Memo.Handle, DC);
end;
答案 2 :(得分:3)
您需要使用TCanvas。您可以在后台创建TBitMap并使用其TCanvas(在将Memo的Font属性分配给Bitmap.Canvas之后),或者使用来自其他组件的TCanvas。像这样的事情:
BMP:=TBitMap.Create;
TRY
BMP.Canvas.Font.Assign(Memo.Font);
TotalHeight:=0;
FOR LineNo:=1 TO Memo.Lines.Count DO INC(TotalHeight,BMP.Canvas.TextHeight(Memo.Lines[PRED(I)]))
FINALLY
FreeAndNIL(BMP)
END;
编辑:
或许这一个:
BMP:=TBitMap.Create;
TRY
BMP.Canvas.Font.Assign(Memo.Font);
LineHeight:=BMP.Canvas.TextHeight('Wq');
TotalHeight:=Memo.Lines.Count*LineHeight
FINALLY
FreeAndNIL(BMP)
END;
答案 3 :(得分:0)
我最初建议查看TMemo中的“Lines”TStrings列表成员。
相反,请查看父类TCustomEdit中的“Font”成员。
'希望有所帮助.. PS