我希望能够在ImgView32的透明层上绘制一个空的椭圆。 知道怎么做吗? 到目前为止,我所能想到的只有:
BL := TBitmapLayer.Create(ImgView.Layers);
BL.Bitmap.DrawMode := dmTransparent;
BL.Bitmap.SetSize(imwidth,imheight);
BL.Bitmap.Canvas.Pen.Width := penwidth;
BL.Bitmap.Canvas.Pen.Color := pencolor;
BL.Location := GR32.FloatRect(0, 0, imwidth, imheight);
BL.Scaled := False;
BL.OnMouseDown := LayerMouseDown;
BL.OnMouseUp := LayerMouseUp;
BL.OnMouseMove := LayerMouseMove;
BL.OnPaint := LayerOnPaint;
...
BL.Bitmap.Canvas.Pen.Color := clBlue;
BL.Bitmap.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
BL.Bitmap.Canvas.Ellipse(FStartPoint.X, FStartPoint.Y,FEndPoint.X, FEndPoint.Y);
在鼠标事件中获取起点和终点。
我实际上是在尝试绘制动态椭圆(在鼠标事件上)。因此onMouseDown(LayerMouseDown),onMouseUp(LayerMouseUp)和OnMouseMove(LayerMouseMove)事件都涉及到。 作为参考,请检查此question,它涉及动态绘制线条。我想做同样的事情但是使用省略号而不是行。
因此,我没有AddLineToLayer,而是使用了AddCircleToLayer程序 事件现在看起来像这样:
procedure TForm5.SwapBuffers32;
begin
TransparentBlt(
BL.Bitmap.Canvas.Handle, 0, 0, BL.Bitmap.Width, BL.Bitmap.Height,
bm32.Canvas.Handle, 0, 0, bm32.Width, bm32.Height, clWhite);
end;
procedure TForm5.ImgViewResize(Sender: TObject);
begin
OffsX := (ImgView.ClientWidth - imwidth) div 2;
OffsY := (ImgView.ClientHeight - imheight) div 2;
BL.Location := GR32.FloatRect(OffsX, OffsY, imwidth+OffsX, imheight+OffsY);
end;
procedure TForm5.LayerMouseDown(Sender: TObject; Buttons: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
FStartPoint := Point(X-OffsX, Y-OffsY);
FDrawingLine := true;
end;
procedure TForm5.LayerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if FDrawingLine then
begin
SwapBuffers32;
if RadioGroup1.ItemIndex=0 then
begin
BL.Bitmap.Canvas.Pen.Color := pencolor;
BL.Bitmap.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
BL.Bitmap.Canvas.LineTo(X-OffsX, Y-OffsY);
end
else
begin
BL.Bitmap.Canvas.Pen.Color := pencolor;
BL.Bitmap.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
SwapBuffers32;
BL.Bitmap.Canvas.Ellipse(FStartPoint.X, FStartPoint.Y,X-OffsX, Y-OffsY);
end;
end;
end;
procedure TForm5.LayerMouseUp(Sender: TObject; Buttons: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if RadioGroup1.ItemIndex=0 then
begin
FDrawingLine := false;
FEndPoint := Point(X-OffsX, Y-OffsY);
AddLineToLayer;
SwapBuffers32;
end
else
begin
FDrawingLine := false;
FEndPoint := Point(X-OffsX, Y-OffsY);
AddCircleToLayer;
SwapBuffers32;
end
end;
procedure TForm5.LayerOnPaint(Sender: TObject; Buffer: TBitmap32);
begin
SwapBuffers32;
end;
procedure TForm5.AddLineToLayer;
begin
bm32.Canvas.Pen.Color := pencolor;
bm32.Canvas.Pen.Width := penwidth;
bm32.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
bm32.Canvas.LineTo(FEndPoint.X, FEndPoint.Y);
end;
procedure TForm5.AddCircleToLayer;
begin
bm32.Canvas.Pen.Color := pencolor;
bm32.Canvas.Pen.Width := penwidth;
bm32.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
bm32.Canvas.Ellipse(FStartPoint.X, FStartPoint.Y,FEndPoint.X, FEndPoint.Y);
SwapBuffers32;
end;
但是当我使用这段代码时,圆圈(椭圆)充满了白色(如图中所示) 直到我开始绘制下一个椭圆(所以在onMouseMove和onMouseUp上填充椭圆)。只有当我在另一个onMouseDown上执行操作时,前一个圆圈才会被清空,但新的椭圆也会被填充为白色(如此图所示)
此外,如果您尝试一个接一个地执行更多的省略号,并且在旧版本的onTop上,您会注意到会有onMouseMove省略号的痕迹,如下图所示:
因此,此代码必须存在我遗漏的内容。
请帮我解决这个问题。
答案 0 :(得分:3)
如果您使用主干中的最新GR32代码,您也可以使用此代码段来定义椭圆
Points := Ellipse(Center.X, Center.Y, Radius.X, Radius.Y);
甚至更简单
Points := Ellipse(Center, Radius);
其中Points
定义为
Points: TArrayOfFloatPoint;
这将生成一个椭圆的多边形,其中心位于Center
,而独立的x和y相关半径由Radius
定义。
获得多边形后,可以使用任何矢量渲染器渲染它。例如,您可以将内置VPR渲染器与
一起使用PolygonFS(Bitmap, Points, SomeColor32);
渲染填充的椭圆。
但是,如果您只想渲染帧,则可以使用此
PolylineFS(Bitmap, Points, AnotherColor32, True, PenWidth);
这方面的参数是
如果您愿意,也可以通过一次通话(如
)进行渲染PolylineFS(Bitmap, Ellipse(Center, Radius), AnotherColor32, True, PenWidth);
为了获得任意(旋转)椭圆,您需要在渲染之前变换多边形。你可以使用
TransformPolygon(Points, Transformation);
为此获取TTransformation
实例作为第二个参数。这可以包括所有常见操作,如旋转,倾斜,缩放和平移。
如果使用此选项,您也可以使用更简单的圆作为多边形输入,并缩放圆以产生椭圆。
上面的代码使得必须将单元GR32_VectorUtils,GR32_Polygons包含到项目中,例如
uses
GR32_VectorUtils, GR32_Polygons;
优点是您不依赖GDI进行渲染,因此您可以从GR32的可用渲染器中选择渲染器。其中一些包括类似ClearType的效果,并提高了LCD屏幕的可见性。更不用说抗锯齿质量和控制渲染伽玛的能力。
答案 1 :(得分:1)
因此,在绘制圆/椭圆时,将画笔颜色设置为0,如:
procedure TForm5.AddCircleToLayer;
begin
bm32.Canvas.Pen.Color := pencolor;
bm32.Canvas.Pen.Width := penwidth;
bm32.Canvas.Brush.Color := 0; // this here does the magic
bm32.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
bm32.Canvas.Ellipse(FStartPoint.X, FStartPoint.Y,FEndPoint.X, FEndPoint.Y);
SwapBuffers32;
end;
也在LayerMouseMove事件中执行相同操作