TMemo with Auto Show/Hide Scrollbars
Asked Answered
M

1

14

I need simple TMemo that does NOT display scroll bars when they are not needed (ie insufficient text), but does when they are. something like ScrollBars = ssAuto or like the TRichEdit HideScrollBars.

I have tried to subclass a TMemo and use the ES_DISABLENOSCROLL in the CreateParams like in the TRichEdit but it does not work.

Edit: This should work with or without WordWrap enabled.

Mumbletypeg answered 18/4, 2012 at 15:17 Comment(4)
Does anyone know if this is a VCL issue, or if the Microsoft Windows (multiline) EDIT control behaves like this (that is, no auto-setting of scrollbar visibility)?Preoccupancy
I think it is a Windows 'issue'. Look at Notepad, for instance.Preoccupancy
@zigiz - Hi. Have you found a complete solution to this?Sholapur
delphi.xcjc.net/viewthread.php?tid=44882Sholapur
P
6

If your memo is placed on the form, the form will be notifed with an EN_UPDATE when the text has been changed and the contents will be redrawn. You can decide here if there will be any scroll bars. I'm assuming we're playing with the vertical scroll bar and there's no horizontal scrollbar:

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  protected
    procedure WMCommand(var Msg: TWMCommand); message WM_COMMAND;
  public

...

procedure SetMargins(Memo: HWND);
var
  Rect: TRect;
begin
  SendMessage(Memo, EM_GETRECT, 0, Longint(@Rect));
  Rect.Right := Rect.Right - GetSystemMetrics(SM_CXHSCROLL);
  SendMessage(Memo, EM_SETRECT, 0, Longint(@Rect));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Memo1.ScrollBars := ssVertical;
  Memo1.Lines.Text := '';
  SetMargins(Memo1.Handle);
  Memo1.Lines.Text := 'The EM_GETRECT message retrieves the formatting ' +
  'rectangle of an edit control. The formatting rectangle is the limiting ' +
  'rectangle into which the control draws the text.';
end;

procedure TForm1.WMCommand(var Msg: TWMCommand);
begin
  if (Msg.Ctl = Memo1.Handle) and (Msg.NotifyCode = EN_UPDATE) then begin
    if Memo1.Lines.Count > 6 then   // maximum 6 lines
      Memo1.ScrollBars := ssVertical
    else begin
      if Memo1.ScrollBars <> ssNone then begin
        Memo1.ScrollBars := ssNone;
        SetMargins(Memo1.Handle);
      end;
    end;
  end;
  inherited;
end;


The thing with setting the right margin is that, removing/putting vertical scroll bar looks utter ugly if the text has to be restructured to fit in.


Note that the above example assumes a maximum of 6 lines. To know how many lines could fit in your memo see this question: How do I determine the height of a line of text in a TMemo programmatically?.

Polytechnic answered 18/4, 2012 at 16:4 Comment(3)
There should be horizontal scroll bar when WordWrap is False, and the text exceeds the visible area of the TMemo.Mumbletypeg
@Mumbletypeg - I've provided a possible idea to you to play with. The question didn't give specifics. You can work on the details yourself if you like :).Polytechnic
Thank you for the effort! I will look more deeply into it :)Mumbletypeg

© 2022 - 2024 — McMap. All rights reserved.