Я пытаюсь нарисовать цветную рамку вокруг области клиента настраиваемого элемента управления с помощью полос прокрутки. С этой целью я устанавливаю 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
-
Реализация ответного ответа на сообщение
WM_NCHITTEST
заставляет управление вести себя лучше, но не разрешает проблема с картинкой прокрутки. -
Я знаю Как нарисовать пользовательскую границу внутри неклиентской области элемента управления с полосами прокрутки?; ответы на это Q все страдают от проблем, описанных выше.
Я использую Delphi 2009 и Windows 7 Home Premium, 64-разрядные, Aero.