2

I've written a custom TMemo, but noticed that the text was smack against the border with no padding at all. Although I could try and fix the issue inside the ClientRect by offsetting it, etc, it wouldn't be a very elegant solution at this stage. TMemo has at least 1px of padding there that is not part of the client area, so I thought I'd try and do the same (I'm assuming that's what they do anyway).

So I've shrunk the client area using WM_NCCALCSIZE, but then of course the border isn't fully painted, so I have to implement WM_NCPAINT as well. That works. I now draw a single clBlack border, followed by a padding rectangle of clWindow. So far so good.

On XP (classic style) however the 1px border looks a bit odd, so I thought maybe there's a way to draw the old "client edge" border, and also comply with the XP/Vista/Win7 theme client edge appearance (I don't know how to manually draw that using gradients).

And that's where I'm a bit stuck. Does anyone know how to paint the border in such a way that I can do the padding, and also how I can maintain the appropriate "client edge" look (1px or 2px)?

Much appreciated. ;)

(Other ways of doing this are welcome as well of course)

=====

EDIT: After some tinkering, I've come up with the following solution. I thought I'd post the it here.

procedure TTest.WMNCCalcSize(var Msg: TWMNCCalcSize);
begin
  inherited;

  InflateRect(Msg.CalcSize_Params.rgrc[0], -1, -1);

  Msg.Result := 0;
end;

procedure TTest.WMNCPaint(var Msg: TWMNCPaint);
var
  lCanvas: TCanvas;
  lRect: TRect;
  iBorderWidth: integer;
  iInflate: integer;
begin
  if ThemeServices.ThemesEnabled
    ThemeServices.PaintBorder(self, true)
  else
    inherited;

  lCanvas := TCanvas.Create;
  try
    lCanvas.Handle := GetWindowDC(Handle);
    with lCanvas do
    begin
      lRect := Rect(0, 0, Width, Height);
      iBorderWidth := (Width - ClientWidth) div 2;
      iInflate := -(iBorderWidth - 1);
      InflateRect(varRect, iInflate, iInflate);

      Brush.Color := clWindow;
      FrameRect(lRect);
    end;
  finally
    ReleaseDC(Handle, lCanvas.Handle);
    FreeAndNil(lCanvas);
  end;

  Msg.result := 0;
end;

EDIT: Argh! This stuff above breaks down when there's a scrollbar in play. I don't have a solution for that yet. Any suggestions?

Jarno
  • 103
  • 3
  • 7
  • *".. a way to draw the old "client edge" border ..*" - Normally you include `WS_EX_CLIENTEDGE` and not worry about `WM_NCCALCSIZE` etc.. – Sertac Akyuz Aug 30 '14 at 14:11
  • Hi Sertac. I was trying to add one extra pixel to the non-client area, so I have a padded ClientRect. WS_ES_CLIENTEDGE is on in CreateParams, and calling inherited will paint it, except when the Themes are on and calling PaintBorder is required. Unfortunately for me, the padding goes around the scrollbar, still not giving me a 1px reduced ClientRect. That to me was a strong indication that TMemo does not work like this, and I'm just about to give up on this approach altogether. – Jarno Aug 30 '14 at 20:31
  • @Jamo - If it's text being too near to edge bothering you, you can resolve it by using `EM_SETRECT`. – Sertac Akyuz Aug 31 '14 at 17:49
  • Thanks Sertac. I do believe that's for a TEdit/TMemo derived class though. I have decided to add the padding myself, and that works. Probably much like the EM_SETRECT. I do still use some of the above code to paint the border on Win7 using ThemeServices, etc. – Jarno Sep 25 '14 at 07:44

0 Answers0