TPaintBox and Form Resizing Issue lazarus / 39-Graphics ---------------------------------------------------------------------- Steve · 2015-07-27 09:02 Hi, I am using 32-bit Lazarus version 1.2.6 on Windows 8.1. I have a form with a TPaintBox control which is set to Align = alClient, so that it is always the same size as the form client area when the form is resized. In the Paint event of the TPaintBox I am painting the background (TCanvas.FillRect) and text (TCanvas.TextOut) onto a TBitmap and then drawing the finished bitmap on the TPaintBox. During the Paint event the TBitmap is sized to match the client area of the TPaintBox. I have also set the Form to DoubleBuffered = True. On resizing the form the text and background of the TPaintBox are coming out fine and there is no flickering of the text, however, when making the form larger I am getting momentary black areas to the right and bottom of the TPaintBox. This is worst when Maximising the form. As far as I can tell the problem is between the TPaintBox and the Form, not between the TBitmap and the TPaintBox. I tested this on a TPanel control as well and had the same problem, even with the TPanel set to DoubleBuffered = True. The problem only occurs when the TPaintBox is set to resize with the form. I have tried resizing the TPaintBox via the Align and Anchor properties and in code, but the result is the same. Once the repainting catches up the TPaintBox bitmap painted area does fill up the entire form space, which is what I want. I am new to using Lazarus and the Graphics functionality so this may be something simple, but I would appreciate any ideas to try to have the resizing look a lot cleaner. Thanks ---------------------------------------------------------------------- balazsszekely · 2015-07-27 10:02 You should detect when the form is resizing and do the drawing accordingly. Try something like this: Code: [Select]uses windows; //... implementation var   PrevWndProc: WNDPROC;   IsResizing: Boolean;   NewW, NewH: Integer; function WndCallback(AHWND: HWND; uMsg: UINT; wParam: WParam; lParam: LParam): LRESULT; stdcall; var   Rect: TRect; begin   case uMsg of     WM_ENTERSIZEMOVE:     begin            IsResizing := True;       Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);     end;     WM_SIZE:     begin       GetWindowRect(AHWND, Rect);       NewW := Rect.Right - Rect.Left;       NewH := Rect.Bottom - Rect.Top;            Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);     end;     WM_EXITSIZEMOVE:     begin       IsResizing := False;            Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);     end;     else       Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);   end; end; procedure TForm1.FormCreate(Sender: TObject); begin  PrevWndProc := Windows.WNDPROC(SetWindowLongPtr(Self.Handle, GWL_WNDPROC, PtrInt(@WndCallback))); end; procedure TForm1.PaintBox1Paint(Sender: TObject); begin   if IsResizing then   begin     //use NewW, NewH --> represent the current width and height of the form(paintbox if alclient)   end end; ---------------------------------------------------------------------- howardpc · 2015-07-27 10:38 I think this can be achieved more simply using the paintbox's OnPaint event. Such as in the following example (generate a form OnShow event and a paintbox OnPaint event, and try the following). Code: [Select]unit Unit1; {$mode objfpc}{$H+} interface uses     Classes, Forms, Graphics, ExtCtrls, types; type   { TForm1 }   TForm1 = class(TForm)     pb: TPaintBox;     procedure FormShow(Sender: TObject);     procedure pbPaint(Sender: TObject);   end; const   example: string = 'example text at perimeter'; var   Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormShow(Sender: TObject); begin   pb.Color:=clMoneyGreen;   DoubleBuffered:=True; // not really needed    end; procedure TForm1.pbPaint(Sender: TObject); var   bmp: TBitmap;   r: TRect;   w, h: integer;   dim: TSize; begin   r:=ClientRect;   bmp:=TBitmap.Create;   try     dim:=pb.Canvas.TextExtent(example);     w:=r.Right-r.Left;     h:=r.Bottom-r.Top;     bmp.SetSize(w, h);     if (bmp.Canvas.Brush.Color <> pb.Color) then       bmp.Canvas.Brush.Color:=pb.Color;     bmp.Canvas.FillRect(r);     bmp.Canvas.TextOut(w - dim.cx, h - dim.cy, example);     pb.Canvas.Draw(0, 0, bmp);   finally     bmp.Free;   end; end; end. ---------------------------------------------------------------------- Steve · 2015-07-27 12:20 Thank you both for the replies. In respect of determining when the resizing was occurring and drawing accordingly; I wasn't sure exactly how to change the drawing in that circumstance as I was already resizing the PaintBox to the full size of the form. It just seemed like the PaintBox resizing wasn't keeping up with the form resizing. The example code posted by howardpc worked, but that was essentially what my code was already doing. In going through what the specific differences were I found that the main difference was that I was using a global TBitmap variable and not creating it in the Paint event itself. I changed my code to create the bitmap locally and then it also worked. However, not being entirely happy with doing that, even though it still seemed fast enough, I did some more testing and found that if I called the Clear() procedure of the global TBitmap before resizing and repainting it then that fixed the problem! Thanks very much for the replies and for helping me to fix the issue!