首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi Graphics32在图层上绘制透明椭圆

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

Stack Overflow用户
提问于 2015-02-18 04:45:30
回答 2查看 2.6K关注 0票数 4

我希望能够在ImgView32中的透明层上绘制一个空的椭圆。你知道怎么做吗?到目前为止,我能想到的就是:

代码语言:javascript
复制
 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过程,事件现在看起来像这样:

代码语言:javascript
复制
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椭圆的痕迹,如下图所示:

所以我一定是在这段代码中遗漏了什么。

请帮我解决这个问题。

EN

回答 2

Stack Overflow用户

发布于 2015-02-18 22:04:24

如果您正在使用主干中的最新GR32代码,则还可以使用此代码片段来定义椭圆

代码语言:javascript
复制
Points := Ellipse(Center.X, Center.Y, Radius.X, Radius.Y);

或者更简单

代码语言:javascript
复制
Points := Ellipse(Center, Radius);

其中Points定义为

代码语言:javascript
复制
Points: TArrayOfFloatPoint;

这将生成一个椭圆多边形,其中心在Center处,独立的x和y相关半径由Radius定义。

拥有多边形后,可以使用任何矢量渲染器对其进行渲染。例如,您可以使用内置的VPR渲染器

代码语言:javascript
复制
PolygonFS(Bitmap, Points, SomeColor32);

若要呈现实心椭圆,请执行以下操作。

但是,如果您只希望渲染帧,则可以使用以下代码

代码语言:javascript
复制
PolylineFS(Bitmap, Points, AnotherColor32, True, PenWidth);

它的参数是

颜色位图=要渲染到框架的位图实例=面点=面点(定义above)

  • AnotherColor32 =用于rendering

  • True的颜色=关闭面(否则,椭圆的起点和终点之间将出现间隙point

  • PenWidth =

如果您愿意,您还可以在一个调用中呈现它,比如

代码语言:javascript
复制
PolylineFS(Bitmap, Ellipse(Center, Radius), AnotherColor32, True, PenWidth);

为了得到一个任意的(旋转的)椭圆,你需要在渲染之前对多边形进行变换。您可以使用

代码语言:javascript
复制
TransformPolygon(Points, Transformation);

因此,它获取一个TTransformation实例作为第二个参数。这可以包括所有常见的操作,如旋转、倾斜、缩放和平移。

如果使用此选项,还可以从一个更简单的圆作为多边形输入开始,然后缩放该圆以生成椭圆。

上面的代码使得有必要在项目中包含单元GR32_VectorUtils和GR32_Polygons,比如

代码语言:javascript
复制
uses
  GR32_VectorUtils, GR32_Polygons;

这样做的好处是您不需要依赖GDI进行渲染,因此您可以从GR32提供的渲染器中选择渲染器。其中一些包括类似ClearType的效果,并改善了液晶屏上的可见性。更不用说抗锯齿质量和控制渲染的gamma的能力了。

票数 4
EN

Stack Overflow用户

发布于 2015-02-18 06:39:23

因此,当绘制圆/椭圆时,将画笔颜色设置为0,如下所示:

代码语言:javascript
复制
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事件中执行相同的操作

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28570792

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档