Search code examples
delphifiremonkeydelphi-xe7

How to draw a dotted line in Firemonkey?


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?


Solution

  • 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