My previous post I wrote about how to reduce flicker on a gradient background and did not mention how to create a gradient background. Here is how I create a gradient background.
Interface
procedure GradVertical(Canvas: TCanvas; Rect: TRect; FromColor, ToColor: TColor);
Implemention
procedure TForm1.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;
procedure TForm1.ButtonClick(Sender: TObject);
var
Rect: TRect;
begin
Rect := GetClientRect;
GradVertical(Self.Canvas, Rect, clBlack, clRed);
end;
Monday, 26 November 2012
How to draw a gradient background
Thursday, 22 November 2012
Screen flicker with gradient background
Recently I had a problem with flickering when resizing a screen due to a gradient background. The problem was mainly noticeable with control on top of the background. Below are a couple of snippets that might help.
First I tried this:
// Interface
procedure WMEraseBackground(var _message:TMessage); message WM_ERASEBKGND;
// Implementation
procedure TForm.WMEraseBackground(var _message: TMessage);
begin
_message.Result := 1;
end;
This helped with the flicker on the gradient panel, but I noticed other issues with some other controls not painting correctly and a panel having a thicker border. Then I tried this:
// Interface
procedure WMEnterSizeMove(var Message:TWMMove); message WM_ENTERSIZEMOVE;
procedure WMExitSizeMove(var Message:TWMMove); message WM_EXITSIZEMOVE;
procedure TfrmMain.WMEnterSizeMove(var Message: TWMMove);
begin
// Set controls to visible = false
end;
procedure TfrmMain.WMExitSizeMove(var Message: TWMMove);
begin
// Set controls to visible = true
end;
Doing this really helped the other controls from flicking, when the user resizes the window the controls disappear and then reappear once the resize is complete.
First I tried this:
// Interface
procedure WMEraseBackground(var _message:TMessage); message WM_ERASEBKGND;
// Implementation
procedure TForm.WMEraseBackground(var _message: TMessage);
begin
_message.Result := 1;
end;
This helped with the flicker on the gradient panel, but I noticed other issues with some other controls not painting correctly and a panel having a thicker border. Then I tried this:
// Interface
procedure WMEnterSizeMove(var Message:TWMMove); message WM_ENTERSIZEMOVE;
procedure WMExitSizeMove(var Message:TWMMove); message WM_EXITSIZEMOVE;
procedure TfrmMain.WMEnterSizeMove(var Message: TWMMove);
begin
// Set controls to visible = false
end;
procedure TfrmMain.WMExitSizeMove(var Message: TWMMove);
begin
// Set controls to visible = true
end;
Doing this really helped the other controls from flicking, when the user resizes the window the controls disappear and then reappear once the resize is complete.
Labels:
background,
Delphi,
flicker,
flickering,
gradient,
move,
problem,
refresh,
resize,
screen,
solution,
wm_entersizemove,
wm_erasebkgnd,
wm_exitsizemove
Tuesday, 6 November 2012
Prevent screen refresh and flickering
To prevent screen refresh and flickering in an application it is often useful to lock the screen. This can occur with data aware controls which involve iteration and can make the application look strange to the user. I have found 2 solutions to this problem, the first is the one I use most of the time, but the second also works well.
Solution 1
LockWindowUpdate(Handle);
try
// Code goes here
finally
LockWindowUpdate(0);
end;
Solution 2
SendMessage(Handle, WM_SETREDRAW, WPARAM(False), 0);
try
// Code goes here
finally
SendMessage(Handle, WM_SETREDRAW, WPARAM(True), 0);
RedrawWindow(Self.Handle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
end;
These 2 solutions help with screen refresh, however there are other instances when these do not work, for example when using a gradient background.
Solution 1
LockWindowUpdate(Handle);
try
// Code goes here
finally
LockWindowUpdate(0);
end;
Solution 2
SendMessage(Handle, WM_SETREDRAW, WPARAM(False), 0);
try
// Code goes here
finally
SendMessage(Handle, WM_SETREDRAW, WPARAM(True), 0);
RedrawWindow(Self.Handle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
end;
These 2 solutions help with screen refresh, however there are other instances when these do not work, for example when using a gradient background.
Labels:
Delphi,
flickering,
locking,
LockWindowUpdate,
RedrawWindow,
screen
Subscribe to:
Posts (Atom)