How can I draw something on the Forms canvas and over controls on the Form?
I try the following:
procedure TForm1.FormPaint(Sender: TObject);
var x,y: Integer;
begin
x := Mouse.CursorPos.X - 10;
y := Mouse.CursorPos.Y - 10;
x := ScreentoClient(point(x,y)).X - 10;
y := ScreenToClient(point(x,y)).Y - 10;
Canvas.Brush.Color := clRed;
Canvas.FillRect(rect(x, y, x + 10, y + 10));
Invalidate;
end;
The rectangle is drawn before other controls are drawn, so it is hidden behind the controls (this is expected behavior according to the Delphi Docs).
My questions is how can I draw over controls?
Do not ‘invalidate’ in a paint handler. Invalidating causes a
WM_PAINTto be sent, which of course starts the paint handling all over. Even if you don’t move the mouse, the code sample you posted will cause the ‘OnPaint’ event to run again and again. Since your drawing depends on the position of the cursor, you’d use the ‘OnMouseMove’ event for this. But you need to intercept mouse messages for other windowed controls as well. The below sample uses a ‘ApplicationEvents’ component for this reason. If your application will have more than one form, you need to device a mechanism to differentiate which form you are drawing on.Also see on the docs that, VCL’s
Invalidateinvalidates the entire window. You don’t need to do that, you’re drawing a tiny rectangle and you know exactly where you’re drawing. Just invalidate where you’ll draw and where you’ve drawn.As for drawing on controls, actually the drawing part is easy, but you can’t do that with the provided canvas. Forms have got
WS_CLIPCHILDRENstyle, child windows’ surfaces will be excluded from the update region, so you’d have to useGetDCExorGetWindowDC. As ‘user205376’ mentioned in the comments, erasing what you’ve drawn is a bit more tricky, since you can be drawing one rectangle actually on more than one control. But the api has a shortcut for this too, as you’ll see in the code.I tried to comment a bit the code to be able to follow, but skipped error handling. The actual painting could be in the ‘OnPaint’ event handler, but controls which do not descend from ‘TWinControl’ are being painted after the handler. So it’s in a WM_PAINT handler.