3
votes

I want to draw a dotted grid on a TPaintbox canvas in a Firemonkey project, the outcome should be exactly like this:

enter image description here

To start with I thought I would draw the vertical dotted lines and then the horizontal dotted lines, so with that in mind I attempted to draw a single line first in attempt to get the appearance just right, this is what I tried:

Canvas.Stroke.Color := TAlphaColorRec.Black;
Canvas.Stroke.Dash := TStrokeDash.Dot;
Canvas.Stroke.Kind := TBrushKind.Solid;
Canvas.Stroke.Thickness := 1;
Canvas.DrawLine(PointF(0, 0), PointF(0, 150), 1);

The result is not what I had hoped, in fact the TLine shape can do a dotted line how I want it to:

enter image description here

But I need to do this drawing myself on the canvas and not use additional controls. For the record TLine simply needs the Stroke.Dash property changing to Dot.

So, using the canvas in a Firemonkey project how may I draw a dotted line the same as TLine does so that I can draw a grid like the first sample image?

1
Just a note I am adding here, setting the thickness to 2 shows as a dotted line but not small/fine enough.Craig
Additional note, didn't realise you can use float values like 0.5 for thickness but still cannot get the drawn line looking right.Craig

1 Answers

5
votes

Without going into the 'why it works' you can achieve 1 pixel dotted line (like in TLine) by adding (or subtracting) half the line width to the coordinates. I got the idea when tracing through what TLine does; during rendering it uses

InflateRect(Result, -(FStroke.Thickness / 2), -(FStroke.Thickness / 2));

Applying the 0.5 modification to the line coordinates, gives the same result.

procedure TForm24.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
  a: integer;
begin
  Canvas.BeginScene;
  try
    Canvas.Stroke.Dash := TStrokeDash.Dot;

    for a := 0 to 10 do
      Canvas.DrawLine(PointF(a * 20 + 0.5, 0.5), PointF(a * 20 + 0.5, 200.5), 1);

    for a := 0 to 10 do
      Canvas.DrawLine(PointF(0.5, a * 20 + 0.5), PointF(200.5, a * 20 + 0.5), 1);

    Canvas.DrawLine(PointF(0.5, 0.5), PointF(200.5, 200.5), 1);
    Canvas.DrawEllipse(RectF(5.0, 5.0, 195.5, 195.5), 1);
  finally
    Canvas.EndScene;
  end;
end;

produces this result:

enter image description here enter image description here

Magnifier view is 500%

Edit 2018.02.23:

An alternative way, worth to test, is to change the forms Quality property to HighPerformance