我从 TPanel 继承了一个控件,在 Paint 事件处理程序中,我使用渐变绘制了整个客户端矩形。在用户调整大小之前,这工作得很好。调整面板大小时,面板组件闪烁过多。
我怎样才能避免这种闪烁。我在MS office 2007中看到了渐变,即使我们调整客户区的大小,也不会出现闪烁。请赐教。
感谢期待
您可能想看看这个问题如何消除 TPaintBox 右边缘的闪烁(例如调整大小时)
很好地概述了避免闪烁以及 TPanel 的选项。
编辑:我在 Windows 7 上的 Delphi XE 版本中进行了快速测试。
使用此代码,我无法重现任何闪烁。继承的 Paint 被删除,并且 Paint 例程非常快。
如果您仍然可以看到闪烁,Simon 的建议可以实施,但最好保留为组件本身的生命周期创建的位图。
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
type
TGradientPanel = class(TPanel)
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
end;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
sPanel : TGradientPanel;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
Uses Math;
procedure GradVertical(Canvas:TCanvas; Rect:TRect; FromColor, ToColor:TColor) ;
var
Y:integer;
dr,dg,db:Extended;
C1,C2:TColor;
r1,r2,g1,g2,b1,b2:Byte;
R,G,B:Byte;
cnt:Integer;
begin
C1 := FromColor;
R1 := GetRValue(C1) ;
G1 := GetGValue(C1) ;
B1 := GetBValue(C1) ;
C2 := ToColor;
R2 := GetRValue(C2) ;
G2 := GetGValue(C2) ;
B2 := GetBValue(C2) ;
dr := (R2-R1) / Rect.Bottom-Rect.Top;
dg := (G2-G1) / Rect.Bottom-Rect.Top;
db := (B2-B1) / Rect.Bottom-Rect.Top;
cnt := 0;
for Y := Rect.Top to Rect.Bottom-1 do
begin
R := R1+Ceil(dr*cnt) ;
G := G1+Ceil(dg*cnt) ;
B := B1+Ceil(db*cnt) ;
Canvas.Pen.Color := RGB(R,G,B) ;
Canvas.MoveTo(Rect.Left,Y) ;
Canvas.LineTo(Rect.Right,Y) ;
Inc(cnt) ;
end;
end;
constructor TGradientPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Self.ParentBackground := FALSE;
end;
procedure TGradientPanel.Paint;
var
rect : TRect;
begin
//inherited; // Avoid any inherited paint actions as they may clear the panel background
rect := GetClientRect;
GradVertical( Self.Canvas, rect, clBlue, clRed);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
sPanel := TGradientPanel.Create( Self);
sPanel.Parent := Self;
sPanel.Top := 10;
sPanel.Left := 10;
sPanel.Width := 300;
sPanel.Height := 300;
sPanel.Anchors := [akLeft,akRight,akTop,akBottom];
sPanel.Enabled := TRUE;
sPanel.Visible := TRUE;
end;
end.
减少闪烁的一种方法是将渐变绘制到临时位图上,将位图的全部内容绘制到面板上。此方法假定您有一个 OnPaint 方法和一个可以在继承的面板中绘制的画布。
所以像这样的东西(未经测试)
var bmp : Tbitmap;
procedure AfterConstruction;
begin
bmp := TBitmap.Create;
end;
procedure Destroy()
begin
if Assigned(bmp) then FreeandNil(bmp);
end;
//redraw you bmp gradient
procedure Panel1.OnResize();
begin
if Assigned(bmp) then //ensure the bmp s created in your constructor
begin
try
bmp.SetBounds(Panel1.Clientrect); //ensure the bmp is the same size as the panel
//draw your gradient on the bmp
Panel1.OnPaint();//repaint the tpanel
finally
bmp.Free;
end;
end;
//paint to the panel
procedure Panel1.OnPaint()
begin
Panel1.Canvas.Draw(0,0,bmp); //use the OnPaint method to draw to the canvas
end;
end;
end;