4

我正在尝试创建一个带有扁平边框的 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,加上bkFlatRTL BidiMode 的“中断”,看起来真的很糟糕。

4

1 回答 1

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;
于 2012-11-26T13:57:19.007 回答