Delphi Graphics32在一个图层上绘制透明椭圆

时间:2015-02-17 20:45:30

标签: delphi delphi-xe graphics32

我希望能够在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;

但是当我使用这段代码时,圆圈(椭圆)充满了白色(如图中所示) enter image description here 直到我开始绘制下一个椭圆(所以在onMouseMove和onMouseUp上填充椭圆)。只有当我在另一个onMouseDown上执行操作时,前一个圆圈才会被清空,但新的椭圆也会被填充为白色(如此图所示) enter image description here

此外,如果您尝试一个接一个地执行更多的省略号,并且在旧版本的onTop上,您会注意到会有onMouseMove省略号的痕迹,如下图所示:

enter image description here

因此,此代码必须存在我遗漏的内容。

请帮我解决这个问题。

2 个答案:

答案 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);

这方面的参数是

  1. Bitmap =要渲染为
  2. 的TBitmap32实例
  3. Points =多边形点(如上所述)
  4. AnotherColor32 = color,用于渲染
  5. True =关闭多边形(否则您的椭圆将在起点和终点之间留有空隙
  6. PenWidth =框架的宽度
  7. 如果您愿意,也可以通过一次通话(如

    )进行渲染
    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事件中执行相同操作