我试图在Bitmap
上绘制一条带有一条线的椭圆,类似于这张图片:
我的应用可以加载位图图片,可以是任何尺寸。我只需要在其中画一条椭圆线。
我知道如何绘制椭圆,但我的问题是它内部的一行:
Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height);
Bmp.Canvas.MoveTo(?, ?);// Here is my problem
Bmp.Canvas.LineTo(?, ?);// here too
我试试这个:
Bmp.Canvas.MoveTo(0, 0);
Bmp.Canvas.LineTo(Bmp.Width, Bmp.Height);
但是这会从图片的左上角到右下角画一条线。
答案 0 :(得分:5)
像你一样使用Canvas.MoveTo()
和Canvas.LineTo()
会很好。你只需要约束椭圆内部线条的绘制,这样你在椭圆之外绘制的任何东西都不会被看到。
您可以使用Win32 API clipping region和CreateEllipticRgn()
函数在绘制线之前将SelectClipRgn()
应用于Canvas
,例如:
// draw the actual ellipse first...
Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height);
// then create a region to match the ellipse...
Rgn := CreateEllipticRgn(0, 0, Bmp.Width, Bmp.Height);
try
SelectClipRgn(Bmp.Canvas.Handle, Rgn);
try
// then draw the line inside the region...
Bmp.Canvas.MoveTo(0, 0);
Bmp.Canvas.LineTo(Bmp.Width, Bmp.Height);
finally
SelectClipRgn(Bmp.Canvas.Handle, 0);
end;
finally
DeleteObject(Rgn);
end;
或者,您可以使用Win32 API clipping path,BeginPath()
和EndPath()
函数来应用椭圆SelectClipPath()
,例如:
// draw the actual ellipse first...
Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height);
// then create a path to match the ellipse...
BeginPath(Bmp.Canvas.Handle);
try
Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height);
finally
EndPath(Bmp.Canvas.Handle);
end;
SelectClipPath(Bmp.Canvas.Handle, RGN_COPY);
// then draw the line inside the path...
Bmp.Canvas.MoveTo(0, 0);
Bmp.Canvas.LineTo(Bmp.Width, Bmp.Height);
有关详细信息,请参阅MSDN上的Clipping Overview。
例如:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
Bmp: TBitmap;
Rgn: HRGN;
begin
Bmp := TBitmap.Create;
try
Bmp.SetSize(Image1.Width, Image1.Height);
Bmp.Canvas.Brush.Color := clWhite;
Bmp.Canvas.FillRect(Rect(0, 0, Bmp.Width, Bmp.Height));
Bmp.Canvas.Pen.Color := clRed;
Bmp.Canvas.Pen.Width := 5;
// draw the actual ellipse first...
Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height);
// then create a region to match the ellipse...
Rgn := CreateEllipticRgn(0, 0, Bmp.Width, Bmp.Height);
try
SelectClipRgn(Bmp.Canvas.Handle, Rgn);
try
// then draw the line inside the region...
Bmp.Canvas.MoveTo(0, 0);
Bmp.Canvas.LineTo(Bmp.Width, Bmp.Height);
finally
SelectClipRgn(Bmp.Canvas.Handle, 0);
end;
finally
DeleteObject(Rgn);
end;
Image1.Picture.Assign(Bmp);
finally
Bmp.Free;
end;
Bmp := TBitmap.Create;
try
Bmp.SetSize(Image2.Width, Image2.Height);
Bmp.Canvas.Brush.Color := clWhite;
Bmp.Canvas.FillRect(Rect(0, 0, Bmp.Width, Bmp.Height));
Bmp.Canvas.Pen.Color := clRed;
Bmp.Canvas.Pen.Width := 5;
// draw the actual ellipse first...
Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height);
// then create a path to match the ellipse...
BeginPath(Bmp.Canvas.Handle);
try
Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height);
finally
EndPath(Bmp.Canvas.Handle);
end;
SelectClipPath(Bmp.Canvas.Handle, RGN_COPY);
// then draw the line inside the path...
Bmp.Canvas.MoveTo(0, 0);
Bmp.Canvas.LineTo(Bmp.Width, Bmp.Height);
Image2.Picture.Assign(Bmp);
finally
Bmp.Free;
end;
end;
end.