我正在尝试创建一个平面边框的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,看起来真的很糟糕。
发布于 2012-11-26 13:57:19
实际上,您必须在WM_NCPAINT消息处理程序中绘制边框。使用GetWindowDC获得的设备上下文相对于控件,而使用GetWindowRect获得的矩形相对于屏幕。
正确的矩形是通过SetRect(R, 0, 0, Width, Height);得到的。
随后,将BorderWidth设置为您的愿望,ClientRect应相应地遵循。如果没有,则通过重写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;https://stackoverflow.com/questions/13564701
复制相似问题