滚动条绘画问题与加厚的非客户端窗口边框

And*_*and 11 delphi controls border nonclient scrollbar

我试图在带有滚动条的自定义控件的客户区周围绘制彩色边框.为此,我设置BorderWidth为正整数并响应该WM_NCPAINT消息.这听起来像混合VCL和Win32,但该BorderWidth属性只是导致对WM_NCCALCSIZE消息的适当处理.

以下代码是SSCCE:

unit Unit6;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TSample = class(TCustomControl)
  protected
    procedure Paint; override;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
  published
    property BorderWidth;
  end;

  TForm6 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form6: TForm6;

implementation

{$R *.dfm}

{ TSample }

procedure TSample.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.Style := Params.Style or WS_VSCROLL or WS_HSCROLL;
end;

procedure TSample.Paint;
begin
  inherited;
  Canvas.Brush.Color := clWhite;
  Canvas.FillRect(ClientRect);
end;
procedure TSample.WMNCPaint(var Message: TWMNCPaint);
var
  dc: HDC;
  R: TRect;
begin
  DefaultHandler(Message);
  dc := GetWindowDC(Handle);
  try
    Brush.Color := clYellow;
    GetWindowRect(Handle, R);
    with R do
      R := Rect(0, 0, Right - Left, Bottom - Top);
    ExcludeClipRect(dc, BorderWidth, BorderWidth,
      R.Right - BorderWidth, R.Bottom - BorderWidth);
    FillRect(dc, R, Brush.Handle);
  finally
    ReleaseDC(Handle, dc);
  end;
end;

procedure TForm6.FormCreate(Sender: TObject);
begin
  with TSample.Create(self) do
  begin
    Parent := Self;
    SetBounds(10, 10, 500, 100);
    BorderWidth := 10;
  end;
end;

end.
Run Code Online (Sandbox Code Playgroud)

结果如下:

截图

除了右下方之外,这看起来很完美.通过做一些事情可以很容易地解决这个问题.我故意不画这个区域,因为它与我试图描述的实际问题无关.所以请忽略那个方格.

现在,我可以通过拖动它的右边框来调整表单的大小.我首先将其缩小,以便隐藏样本控制窗口的垂直滚动条.然后我慢慢放大表格,使样品控制再次完全可见.然后它看起来像这样:

截图

在这里你可以看到问题:BorderSize垂直滚动条的〜最左边的像素似乎没有被操作系统绘制.

一些观察:

  1. 使用完整inherited而不仅仅是DefaltHandler(Message)使问题更严重.在这种情况下,黄色区域将在窗体临时移出屏幕后以及在控制遮挡形式收缩 - 生长操作之后完全遮挡滚动条.

截图

  1. 实现对WM_NCHITTEST消息的匹配响应使控件以更好的方式运行,但不解决滚动条绘制问题.

  2. 我知道如何使用滚动条在控件的非客户区域内绘制自定义边框?; 这个Q的答案都受到上述问题的困扰.

我正在使用Delphi 2009和Windows 7 Home Premium,64位,Aero启用.