我想我可以把它扔到那里然后问:我已经看到Delphi控件在图形效果方面完美无缺.含义:没有闪烁,分段更新(仅重绘标记为脏的控件部分)和平滑滚动.
我已经编写了很多多年来图形控制的,所以我知道双缓冲,DIBS,bitblts和所有的"共同"的东西(我一直使用的DIB如果可能的话绘制的一切,但有一个开销).还要了解InvalidateRect并检查需要更新的实际rect的TCanvas.ClipRect.尽管有这些典型的解决方案,但我发现创建与Developer Express或Razed Components相同质量的组件非常困难.如果图形是平滑的,你可以打赌滚动条(本机)闪烁,如果滚动条和框架是平滑的,你可以在滚动期间发誓背景闪烁.
是否有标准的代码设置来处理这个问题?一种确保平滑重绘整个控件的最佳实践 - 包括控件的非客户区域?
例如,这是一个"裸骨"控件,它为分段更新占用高度(仅重绘所需的内容).如果在表单上创建它,请尝试在其上移动一个窗口,然后观察它用颜色替换部件(请参阅绘制方法).
有没有人有类似的基类可以处理非客户区重绘而不闪烁?
type
TMyControl = Class(TCustomControl)
private
(* TWinControl: Erase background prior to client-area paint *)
procedure WMEraseBkgnd(var Message: TWmEraseBkgnd);message WM_ERASEBKGND;
Protected
(* TCustomControl: Overrides client-area paint mechanism *)
Procedure Paint;Override;
(* TWinControl: Adjust Win32 parameters for CreateWindow *)
procedure CreateParams(var Params: TCreateParams);override;
public
Constructor Create(AOwner:TComponent);override;
End;
{ TMyControl }
Constructor TMyControl.Create(AOwner:TComponent);
Begin
inherited Create(Aowner);
ControlStyle:=ControlStyle - [csOpaque];
end;
procedure TMyControl.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
(* When a window has this style …Run Code Online (Sandbox Code Playgroud) 我试图在带有滚动条的自定义控件的客户区周围绘制彩色边框.为此,我设置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; …Run Code Online (Sandbox Code Playgroud) 在编写自定义控件时,在尝试BorderWidth正确实现默认属性时,我似乎偶然发现了滚动条显示时绘画行为中的错误:滚动条和控件范围之间的空格未绘制.
要重现该错误,请OnCreate为新项目的主窗体实现以下处理程序:
procedure TForm1.FormCreate(Sender: TObject);
begin
AutoScroll := True;
BorderWidth := 20;
SetBounds(10, 10, 200, 200);
with TGroupBox.Create(Self) do
begin
SetBounds(300, 300, 50, 50);
Parent := Self;
end;
end;
Run Code Online (Sandbox Code Playgroud)
D7和XE2的结果:

这似乎在Delphi XE2中得到了解决.可能,这个bug会存在TWinControl.WMNCPaint,但是看看Controls.pas,我发现D7和XE2之间的实现没有任何显着差异.
我想得到答案: