Can I make a TMemo size itself to the text it contains?

狂风中的少年 提交于 2019-11-28 13:24:17
A. I. Breveleri

Set the WordWrap property of the TMemo to true, dump your text into it, count the lines, and set the height to the product of the line count and the line height, but you need to know the line height.

The TMemo does not expose a line height property, but if you're not changing the font or font size at runtime, you can determine the line height experimentally at design time.

Here's the code I used to set the height of the TMemo that had a line height of 13 pixels. I also found that I needed a small constant to account for the TMemo's top and bottom borders. I limited the height to 30 lines (396 pixels) to keep it on the form.

// Memo.WordWrap = True (at design time)
Memo.Text := <ANY AMOUNT OF TEXT>;
Memo.Height := Min(19 + Memo.Lines.Count * 13, 396); 

If you absolutely must extract the line height from the object at runtime, then you might use Someone's answer. Or, you can use TRichEdit, which has the SelAttributes property containing a Height property giving the line height.

-Al.

This works just fine for me. The constant added (8) might vary on whether you are using a border and/or bevel, experiment with it.

procedure TForm1.Memo1Change(Sender: TObject);
var
  LineHeight: Integer;
  DC: HDC;
  SaveFont : HFont;
  Metrics : TTextMetric;
  Increase: Integer;
  LC: Integer;
begin
  DC := GetDC(Memo1.Handle);
  SaveFont := SelectObject(DC, Memo1.Font.Handle);
  GetTextMetrics(DC, Metrics);
  SelectObject(DC, SaveFont);
  ReleaseDC(Memo1.Handle, DC);
  LineHeight := Metrics.tmHeight;
  Increase := Memo1.Height;
  LC := Memo1.Lines.Count;
  if LC < 1 then
    LC := 1;
  Memo1.Height := LC * LineHeight + 8;
  Increase := Memo1.Height - Increase;
  Memo1.Parent.Height := Memo1.Parent.Height + Increase;
end;

I've implemented a self-growing TMemo as a nice example of LiveBindings (one of the few useful examples I could come up with for LiveBindings in VCL).

A quote From my Delphi XE2 Development Essentials courseware manual:

"To build this example, place a TMemo component on a VCL form, open the LiveBindings property, and select the “New LiveBinding” option. Pick the TBindExpression choice. Open BindExpressionMemo11 in the Object Inspector and set SourceComponent to Memo1 and SourceExpression to Lines.Count * 22. To get a better result at runtime, set SourceExpression to the more exact expression

Font.Size - 4 + (Lines.Count + 1) * -1 * (Font.Height - 3)

Finally, in the OnChange event handler of the TMemo, write one line of code:

BindingsList1.Notify(Sender, '');

That’s it. Compile and run to see the growing memo in action.

[screenshot]

Initially, the TMemo control will be two lines high (the line with the contents, and a next line), and whenever we hit enter or word wrapping advances us to the next line, the TMemo control will grow in height (growing down actually, so make sure to leave enough space on the form for the TMemo to expand itself)."

Groetjes, Bob Swart

alisa
procedure TTmpMessage.edMsgChange (Sender: TObject);
var
    LineHeight : Integer;
    DC         : HDC;
    SaveFont   : HFont;
    Metrics    : TTextMetric;
begin
    DC := GetDC ( TRxRichEdit (Sender).Handle );
    SaveFont := SelectObject ( DC, TRxRichEdit (Sender).Font.Handle );
    GetTextMetrics (DC, Metrics);
    SelectObject (DC, SaveFont);
    ReleaseDC ( TRxRichEdit (Sender).Handle, DC );
    LineHeight := Metrics.tmHeight;
    Height := TRxRichEdit (Sender).Lines.Count * LineHeight + 32;
end;
user3223924

And why not just:

Memo1.Height := Memo1.ContentBounds.Height + 5;
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!