How to add padding to a TCustomControl without losing the border "look and feel"?

1.1k Views Asked by At

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?

0

There are 0 best solutions below