Here you have a little demo. Like mentioned above - you should never call Invalidate from within Paint method. Some widgetsets don't like - especially GTK2. Just put two buttons on the form and assign onclick events.
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, LCLIntf;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
{ private declarations }
InvRectOnly: Boolean;
InvRect: TRect;
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
InvRectOnly := True;
InvRect := Rect(20, 20, 100, 100);
InvalidateRect(self.Handle, @InvRect, True);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
InvRectOnly := False;
Invalidate;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
if not InvRectOnly
then Canvas.GradientFill(Rect(0, 0, Width, Height), clRed, clBlue, gdHorizontal)
else begin
Canvas.Brush.Color := clGreen;
Canvas.FillRect(InvRect);
end;
InvRectOnly := False;
end;
end.