How to avoid broken dashed lines in GDI+?

Thes screenshots, taken from my MFC application, show lines 2 that should be parallel. 2条平行线,一条固定,另一条虚线

The Lines are drawn using Gdiplus::Graphics::Drawline() .

A minor issue is that the dashed lines are not straigt but broken. You notice it but it's not a big deal...

The real problem is that it's not consistent and lines drawn with Gdiplus::DashStyleSolid are really straight.

Is this a bug in GDI+? Is there a workaround?

Update 1

I tried making a minimal example but I'm struggling to reproduce it... It may have something to do with very large coordinate values and little difference between their coordinates. These are some example line coordinates:

Line 1: PointF(2.21866e+006, 1.40198e+006), PointF(2.21732e+006, 1.40111e+006)
Line 2: PointF(2.21866e+006, 1.40198e+006), PointF(2.21732e+006, 1.40112e+006)

I noticed that the start points are identical but this may be caused by rounding in the debug output...

Update 2

I could reproduce it now: The sample application was generated as SDI project and the view class inherits CScrollView (code and screenshot below). The "broken line" effect also appears to be related to the pen's thickness. The line runs a bit different with varying thickness but I did not find a value that results in parallel lines all the time.

Vincent Porvik suggests in a comment that this might be the result of rounding errors, since Gdiplus::REAL is defined as float . I believe this is the case as well...

Do I have any options other than somehow using smaller coordinate values here?

Code and Screenshot

These functions were added/modified (in addition to the GDI+ initialization code):

void CgdiplusLinesView::OnDraw(CDC* pDC)
{
    CgdiplusLinesDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    pDC->SetBkMode(TRANSPARENT);

    using namespace Gdiplus;
    Graphics g(pDC->m_hDC);
    g.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);

    Pen solidPen(Color(0,0,0), 2.f);
    Pen dashedPen(Color(0,0,0), 2.f);
    dashedPen.SetDashStyle(DashStyleDash);

    g.DrawLine(&dashedPen, PointF(4438749.500000, 2805806.500000), PointF(4434280.500000, 2802106.500000));
    g.DrawLine(&solidPen,  PointF(4438746.500000, 2805809.500000), PointF(4434277.500000, 2802109.500000));
}

void CgdiplusLinesView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
    pDC->SetMapMode(MM_ISOTROPIC);

    const int mapSizePixels = 8388608;
    pDC->SetWindowExt(mapSizePixels, mapSizePixels);
    pDC->SetViewportExt(mapSizePixels, mapSizePixels);
    pDC->SetWindowOrg(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT));

    //__super::OnPrepareDC(pDC, pInfo);
}

void CgdiplusLinesView::OnInitialUpdate()
{
    CScrollView::OnInitialUpdate();

    SetScrollSizes(MM_TEXT, CSize(8388608, 8388608), CSize(1361, 1054));
    SetScrollPos(SB_HORZ, 4434897.5);
    SetScrollPos(SB_VERT, 2802645.);
}


I don't think it has to do with dashed vs solid, but with float precision. Your coordinates seem to be geographic coordinates. The usual good practice has been to store all coordinates as doubles, and when you need to work with a lower precision library, offset all coordinates yourself before passing them to the graphics functions.

The correct way to do that is to choose a reference point that is close to the points in your dataset (first coordinate you find is ok) and then substract its coordinates to all other points. This keeps the numerical values near 0.0 that is where floats have higher resolution density.

链接地址: http://www.djcxy.com/p/11350.html

上一篇: 是否有可能在C#中创建System.Int32?

下一篇: 如何避免在GDI +中破碎的虚线?