Drawing border of points around TBitmap?

I wrote a procedure that should add a dotted border to a bitmap:

procedure AddDottedBorderToBitmap(aBM: Vcl.Graphics.TBitmap);
var
  c: TCanvas;
begin
  c := aBM.Canvas;
  c.Pen.Color := clBlack;
  c.Pen.Mode  := pmXor;
  c.Pen.Style := psDot;

  c.MoveTo(0, 0);
  c.LineTo(0, aBM.Height - 1);
  c.LineTo(aBM.Width - 1, aBM.Height - 1);
  c.LineTo(aBM.Width - 1, 0);
  c.LineTo(0, 0);
end;

      

But when the result is increased, the resulting border, instead of dots, appears to be made of small dashes:

enter image description here

It is right? If not, how can I get real dots instead of dashes?

+3


source to share


2 answers


DrawFocusRect is a Windows API call that creates the border as you need it.



procedure AddDottedBorderToBitmap(aBM: Vcl.Graphics.TBitmap);
begin
  DrawFocusRect(aBM.canvas.Handle,Rect(0,0,aBM.Width,aBM.Height));
end;

      

+2


source


It may sound simple to use DrawFocusRect

, but if you need to draw something other than rectangles, you can read on.

Pen style psDot

does not mean every second pixel is colored and the other is cleared. If you think about it, the higher the resolution, the more difficult it would be to see the difference between the dotted line and the gray solid f.ex. There is another pen style psAlternate

that alternates between pixels. The docs say:

psAlternate

The pen sets every other pixel. (This style is only applicable to cosmetic pens.) This style is only applicable to pens created using the ExtCreatePen API function. (See MS Windows SDK docs.) This applies to both VCL and VCL.NET.

To define a pen and use it, we do the following:



var
  c: TCanvas;
  oldpenh, newpenh: HPEN; // pen handles
  lbrush: TLogBrush;      // logical brush

...

  c := pbx.Canvas; // pbx is a TPintBox, but can be anything with a canvas

  lbrush.lbStyle := BS_SOLID;
  lbrush.lbColor := clBlack;
  lbrush.lbHatch := 0;

  // create the pen
  newpenh := ExtCreatePen(PS_COSMETIC or PS_ALTERNATE, 1, lbrush, 0, nil);
  try
    // select it
    oldpenh := SelectObject(c.Handle, newpenh);

    // use the pen
    c.MoveTo(0, 0);
    c.LineTo(0, pbx.Height - 1);
    c.LineTo(pbx.Width - 1, pbx.Height - 1);
    c.LineTo(pbx.Width - 1, 0);
    c.LineTo(0, 0);

    c.Ellipse(3, 3, pbx.width-3, pbx.Height-3);

    // revert to the old pen
    SelectObject(c.Handle, oldpenh);
 finally
    // delete the pen
    DeleteObject(newpenh);
 end;

      

And finally, what does it look like (the magnifier is at x 10)

enter image description here

+6


source







All Articles