Подтвердить что ты не робот

Проблема с окраской прокрутки с утолщенной рамкой окна без клиента

Я пытаюсь нарисовать цветную рамку вокруг области клиента настраиваемого элемента управления с помощью полос прокрутки. С этой целью я устанавливаю 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.

Результаты выглядят следующим образом:

Снимок экрана http://privat.rejbrand.se/vclnonclient1.png

Это выглядит идеально, за исключением нижнего правого квадрата. Эта область легко фиксируется, делая что-то с ней; Я намеренно не рисую эту область, потому что это не имеет никакого отношения к фактической проблеме, которую я пытаюсь описать. Поэтому просто игнорируйте этот квадрат, пожалуйста.

Теперь я могу изменить размер формы, перетащив ее вправо. Я сначала делаю его меньше, так что вертикальная полоса прокрутки окна управления образцом скрыта. Затем я медленно увеличиваю форму, чтобы контроль образца снова был полностью виден. Тогда это выглядит так:

Снимок экрана http://privat.rejbrand.se/vclnonclient2.png

Здесь вы можете увидеть проблему: ~ BorderSize самые левые пиксели вертикальной полосы прокрутки, по-видимому, не окрашены операционной системой.

Некоторые наблюдения:

  • Использование полного inherited вместо простого DefaltHandler(Message) делает проблему намного хуже. В этом случае желтая область будет закрывать полосы прокрутки полностью после того, как форма была временно перемещена за пределы экрана, а после операции сокращения окклюзионной формы - сжиматься.

Снимок экрана http://privat.rejbrand.se/vclnonclient3.png

  1. Реализация ответного ответа на сообщение WM_NCHITTEST заставляет управление вести себя лучше, но не разрешает проблема с картинкой прокрутки.

  2. Я знаю Как нарисовать пользовательскую границу внутри неклиентской области элемента управления с полосами прокрутки?; ответы на это Q все страдают от проблем, описанных выше.

Я использую Delphi 2009 и Windows 7 Home Premium, 64-разрядные, Aero.

4b9b3361