Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

delphi - How do I determine the height of a line of text in a TMemo programmatically?

I've got a TMemo, and I want to always make it exactly high enough to display the number of lines it contains. Unfortunately, I don't quite know how to calculate that. I can't base it off the .Font.Size property, because that will vary based on DPI. And I can't use TCanvas.TextHeight because TMemo doesn't seem to have a canvas.

Anyone know how to do this right?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I see a problem, i think all lines on a TMemo are equal on height, but some can be empty...

So getting Height of empty ones will give zero while they are not zero height on the TMemo.

So the solution maybe doing something like Memo.Lines.Count*LineHeight

Beware that the Lineheight may not be getted by Canvas.TextHeight since Canvas.TextHeight will give more or less exact height of minimal height for a text... i mean it will not give same height for text 'ABC' than for 'ABCp', etc...

I would recomend (if not want to call Windows API) to use Font.Height, but if it is negative the internal leading of each line is not measured...

So i would recomend to do the next steps (tested):

  • Asign a positive value for Memo.Font.Height on the OnCreate event or anywhere you want, with this the lineheight ot the TMemo will be such value you asigned
  • Total height now can be obtained directly by Memo.Lines.Count*LineHeight, since you have asigned a positive value to Memo.Font.Height (remember that would make Memo.Font.Size to be negative)

Personally i do this on the TForm OnCreate event (to ensure it is done only once), just to ensure visual font size is not changed and MyMemo.Font.Height includes internal leading of each line:

MyMemo.Font.Height:=Abs(MyMemo.Font.Size*MyMemo.Font.PixelsPerInch div Screen.PixelsPerInch);

Ensure the previous to be done only once, otherwise the text size will be visaully bigger and bigger, as much as times you run it... it is caused because not allways MyMemo.Font.PixelsPerInch is equal to Screen.PixelsPerInch... in my case they are 80 and 96 respectively.

Then, when i need to know line height i just use:

Abs(MyMemo.Font.Height*Screen.PixelsPerInch div 72)

That gives exact height of one TMemo line, since all lines have the same height, the total height would be:

MyMemo.Lines.Count*Abs(MyMemo.Font.Height*Screen.PixelsPerInch div 72)

So, to make TMemo height as big as its contained text i do this (read the comment of each line, they are very important):

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

I you do not want to play with Screen.PixelsPerInch you can just do this (read the comment of each line, they are very important):

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);

Hope this can help anyone.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...