简体   繁体   中英

Drawing a borderline of dots around a TBitmap?

I have written a routine which 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 enlarging the result, the resulting borderline instead of dots seems to be made of small dashes:

在此输入图像描述

Is this correct? If not, how can I get real dots instead of dashes?

It may seem simple to use DrawFocusRect , but if you need to draw something else than rectangles, you may want to read ahead.

The pen style psDot does not mean that every second pixel is colored and the other cleared. If you think about it, the higher the resolution the harder it would be to see the difference of dotted vs. gray solid f.ex. There is another pen style psAlternate which alternates the pixels. The docs say:

psAlternate

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

To define the pen and use it we do as follows

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 it looks like (the magnifier is at x 10)

在此输入图像描述

DrawFocusRect it's a Windows API call that make a border like you need.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM