GDI +破折号模式是否被窃听?

时间:2018-03-06 15:43:13

标签: .net drawing gdi+ artifacts

我使用Embarcadero RAD Studio XE7创建了一个C ++图形应用程序,我试图使用GDI +和一些破折号模式属性来设置循环进度动画。

这个想法非常简单:通过配置一个模式,其中短划线足够长以填充圆的圆周,并且空白部分足够长以防止两个破折号在圆上一起可见,这是可能的显示循环进度,其中破折号偏移属性可用于显示当前进度位置。

但是,我无法通过GDI +实现目标,因为可以看到几个图形工件,而且我无法找到解决方案。我非常确定我使用的值是正确的,因为Direct2D处理的完全相同的绘图工作正常。

以下是显示问题的示例代码。一个圆圈用GDI +绘制,另一个圆圈用Direct2D绘制。对于2个圆圈,绘图配置完全相同。

// fill the background
TRect rect(0, 0, ClientWidth, ClientHeight);
Canvas->Brush->Color = clWhite;
Canvas->Brush->Style = bsSolid;
Canvas->FillRect(rect);

const float startY     =  100.0f;
const float penWidth   =  32.0f;
const float dashOffset = -559.0f + (float(tb1->Position) * 559.0f * 0.01f);

std::vector<float> dashPattern;
dashPattern.push_back(559.0f / penWidth);
dashPattern.push_back(559.0f / penWidth);

// --------------------------------- USING GDI+ --------------------------------------

// create a GDI+ path showing a circle
Gdiplus::GraphicsPath path;
path.StartFigure();
path.AddBezier(Gdiplus::PointF(99.99999, 11.05255 + startY),
               Gdiplus::PointF(51.31296, 11.05255 + startY),
               Gdiplus::PointF(11.05254, 51.31297 + startY),
               Gdiplus::PointF(11.05254, 100 + startY));
path.AddBezier(Gdiplus::PointF(11.05254, 100 + startY),
               Gdiplus::PointF(11.05254, 148.6871 + startY),
               Gdiplus::PointF(51.31297, 188.9475 + startY),
               Gdiplus::PointF(99.99999, 188.9475 + startY));
path.AddBezier(Gdiplus::PointF(99.99999, 188.9475 + startY),
               Gdiplus::PointF(148.687,  188.9475 + startY),
               Gdiplus::PointF(188.9474, 149.1552 + startY),
               Gdiplus::PointF(188.9474, 100 + startY));
path.AddBezier(Gdiplus::PointF(188.9474, 100 + startY),
               Gdiplus::PointF(188.9474, 50.84483 + startY),
               Gdiplus::PointF(149.1552, 11.05255 + startY),
               Gdiplus::PointF(99.99998, 11.05255 + startY));
path.CloseFigure();

// configure the GDI+ pen
Gdiplus::Pen pen(Gdiplus::Color(255, 0, 0, 0));
pen.SetWidth(penWidth);
pen.SetDashOffset(dashOffset / penWidth);

const Gdiplus::LineCap lineCapStart = Gdiplus::LineCapFlat;
const Gdiplus::LineCap lineCapEnd   = Gdiplus::LineCapFlat;
const Gdiplus::DashCap dashCap      = Gdiplus::DashCapFlat;

pen.SetLineCap(lineCapStart, lineCapEnd, dashCap);

const Gdiplus::LineJoin lineJoin = Gdiplus::LineJoinMiter;
pen.SetLineJoin(lineJoin);
pen.SetMiterLimit(4.0f);

// configure dash style to custom (meaning that dash pattern should be used)
pen.SetDashStyle(Gdiplus::DashStyleCustom);

// configure dash pattern
pen.SetDashPattern(&dashPattern[0], dashPattern.size());

// draw the path using GDI+
Gdiplus::Graphics graphics(Canvas->Handle);
graphics.DrawPath(&pen, &path);

// ------------------------------- USING DIRECT2D ------------------------------------

const float startX = 300.0f;

// get a Direct2D canvas
TRect canvasRect(0, 0, ClientWidth, ClientHeight);
TDirect2DCanvas* pCanvas = new TDirect2DCanvas(Canvas->Handle, canvasRect);

// begin draw
pCanvas->BeginDraw();

ID2D1Factory* pD2DFactory;

// get factory associated with canvas
pCanvas->RenderTarget->GetFactory(&pD2DFactory);

// create a Direct2D path showing a circle
ID2D1PathGeometry* pGeometry;
pD2DFactory->CreatePathGeometry(&pGeometry);

ID2D1GeometrySink* pSink;
pGeometry->Open(&pSink);
pSink->BeginFigure(D2D1::Point2F(99.99999 + startX, 11.05255 + startY), D2D1_FIGURE_BEGIN_FILLED);
pSink->AddBezier(D2D1::BezierSegment(D2D1::Point2F(51.31296 + startX, 11.05255 + startY),
                                     D2D1::Point2F(11.05254 + startX, 51.31297 + startY),
                                     D2D1::Point2F(11.05254 + startX, 100 + startY)));
pSink->AddBezier(D2D1::BezierSegment(D2D1::Point2F(11.05254 + startX, 148.6871 + startY),
                                     D2D1::Point2F(51.31297 + startX, 188.9475 + startY),
                                     D2D1::Point2F(99.99999 + startX, 188.9475 + startY)));
pSink->AddBezier(D2D1::BezierSegment(D2D1::Point2F(148.687 + startX,  188.9475 + startY),
                                     D2D1::Point2F(188.9474 + startX, 149.1552 + startY),
                                     D2D1::Point2F(188.9474 + startX, 100 + startY)));
pSink->AddBezier(D2D1::BezierSegment(D2D1::Point2F(188.9474 + startX, 50.84483 + startY),
                                     D2D1::Point2F(149.1552 + startX, 11.05255 + startY),
                                     D2D1::Point2F(99.99998 + startX, 11.05255 + startY)));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
pSink->Close();
pSink->Release();

// configure the Direct2D stroke properties
::D2D1_STROKE_STYLE_PROPERTIES strokeProps;
strokeProps.startCap   = D2D1_CAP_STYLE_FLAT;
strokeProps.endCap     = D2D1_CAP_STYLE_FLAT;
strokeProps.dashCap    = D2D1_CAP_STYLE_FLAT;
strokeProps.lineJoin   = D2D1_LINE_JOIN_MITER;
strokeProps.miterLimit = 4.0f;
strokeProps.dashStyle  = D2D1_DASH_STYLE_CUSTOM;
strokeProps.dashOffset = dashOffset / penWidth;

// get the stroke style to apply
ID2D1StrokeStyle* pStrokeStyle;
pD2DFactory->CreateStrokeStyle(strokeProps,
                               &dashPattern[0],
                               dashPattern.size(),
                               &pStrokeStyle);

::ID2D1SolidColorBrush* pSolidBrush;

::D2D1_COLOR_F color;
color.r = 0.0f;
color.g = 0.0f;
color.b = 0.0f;
color.a = 1.0f;

// create a solid color brush
pCanvas->RenderTarget->CreateSolidColorBrush(color, &pSolidBrush);

// draw the geometry
pCanvas->RenderTarget->DrawGeometry(pGeometry, pSolidBrush, penWidth, pStrokeStyle);

pCanvas->EndDraw();

delete pCanvas;

tb1-&gt; Position属性只是一个可在0到100之间移动的轨迹栏控制光标。

使用上面的代码,我注意到2绘图之间存在一些差异:

  1. 当tb1-> Position = 0时,GDI +圆圈是完全可见的,而Direct2D圆圈是不可见的(这是我想达到的正确效果)。

  2. 当tb1-&gt;位置介于1到99之间时,GDI +圆圈结尾绘制不正确。 enter image description here

  3. 当tb1-> Position = 100时,在GDI +圈上可以看到图形伪像 enter image description here

  4. 不幸的是,使用像Direct2D这样的其他库而不是GDI +对我来说不是一个选择。我的问题是:为什么当我用GDI +绘制虚线圆圈时会发生上述差异?我做错了什么,还是GDI +错误?

    重要编辑:在上面的图像中,在Direct2D绘图上启用了抗锯齿功能,而在GDI +绘图中禁用了抗锯齿功能。 这不是问题。上面提到的问题是关于图形工件,例如段结尾的方向,它们在GDI +和Direct2D之间明显不同,或者在圆形满时出现的空白工件。 无论是否使用抗锯齿都会发生这些问题

0 个答案:

没有答案