TScrollBox具有自定义的扁平边框颜色和宽度?

Zig*_*giZ 4 delphi delphi-5

我正在尝试创建带有扁平边框的TScrollBox而不是丑陋的“ Ctl3D”。

这是我尝试过的,但是边框不可见:

type
  TScrollBox = class(Forms.TScrollBox)
  private
    procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
  protected
  public
    constructor Create(AOwner: TComponent); override;
  end;

...

constructor TScrollBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  BorderStyle := bsNone;
  BorderWidth := 1; // This will handle the client area
end;

procedure TScrollBox.WMNCPaint(var Message: TWMNCPaint);
var
  DC: HDC;
  R: TRect;
  FrameBrush: HBRUSH;
begin
  inherited;
  DC := GetWindowDC(Handle);
  GetWindowRect(Handle, R);
  // InflateRect(R, -1, -1);
  FrameBrush := CreateSolidBrush(ColorToRGB(clRed)); // clRed is here for testing
  FrameRect(DC, R, FrameBrush);
  DeleteObject(FrameBrush);
  ReleaseDC(Handle, DC);
end;
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?


我想自定义边框的颜色和宽度,这样我就不能使用BevelKind = bkFlat并且不能使用bkFlatRTL BidiMode来“中断”,而且看起来真的很糟糕。

NGL*_*GLN 5

确实,您必须在WM_NCPAINT消息处理程序中绘制边框。您获得的设备上下文GetWindowDC是相对于控件的,而您获得的矩形GetWindowRect是相对于屏幕的。

正确的矩形例如通过 SetRect(R, 0, 0, Width, Height);

随后,BorderWidth按照您的意愿设置,并ClientRect应遵循相应的步骤。如果不是,则通过覆盖进行补偿GetClientRect。这里有一些例子

在您自己的代码之前调用消息处理程序的继承链,这样可以正确绘制滚动条(需要时)。总而言之,它应该看起来像:

type
  TScrollBox = class(Forms.TScrollBox)
  private
    procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
  protected
    procedure Resize; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

...    

constructor TScrollBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  BorderWidth := 1;
end;

procedure TScrollBox.Resize;
begin
  Perform(WM_NCPAINT, 0, 0);
  inherited Resize;
end;

procedure TScrollBox.WMNCPaint(var Message: TWMNCPaint);
var
  DC: HDC;
  B: HBRUSH;
  R: TRect;
begin
  inherited;
  if BorderWidth > 0 then
  begin
    DC := GetWindowDC(Handle);
    B := CreateSolidBrush(ColorToRGB(clRed));
    try
      SetRect(R, 0, 0, Width, Height);
      FrameRect(DC, R, B);
    finally
      DeleteObject(B);
      ReleaseDC(Handle, DC);
    end;
  end;
  Message.Result := 0;
end;
Run Code Online (Sandbox Code Playgroud)