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

时间:2012-11-26 12:17:33

标签: 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;

我做错了什么?


我想自定义边框颜色&宽度所以我不能使用BevelKind = bkFlat,加上bkFlat“打破”RTL BidiMode,看起来非常糟糕。

1 个答案:

答案 0 :(得分:5)

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

获得正确的矩形,例如按SetRect(R, 0, 0, Width, Height);

随后,根据您的意愿设置BorderWidthClientRect也应如此遵循。如果没有,则通过覆盖GetClientRect进行补偿。这是一个few examples

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

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;