关于mfc画线问题一直自动链接原点

老哥们为什么我用mfc画线的时候最新的那个端点一直链接原点是怎么回事,感觉主要问题是在那一串星号下面的代码,因为那个点的颜色会随那个rgb一起改变

img

img


那个原点会一直连接我最新的控制点和绘制出来的曲线的点

void CbView::DoubleBuffer(CDC* pDC) {
    CRect rect;
    GetClientRect(&rect);
    nClientWidth = rect.Width();
    nClientHeight = rect.Height();
    pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetWindowExt(rect.Width(), rect.Height());
    pDC->SetViewportExt(rect.Width(), -rect.Height());
    pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
    CDC memDC;//内存DC
    memDC.CreateCompatibleDC(pDC);//创建一个与显示pDC兼容的内存memDC
    CBitmap NewBitmap, * pOldBitmap;//内存中承载的临时位图
    NewBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());//创建兼容位图
    pOldBitmap = memDC.SelectObject(&NewBitmap);//将兼容位图选入memDC
    memDC.FillSolidRect(rect, pDC->GetBkColor());
    rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2);
    memDC.SetMapMode(MM_ANISOTROPIC);//内存自定义DC坐标系
    memDC.SetWindowExt(rect.Width(), rect.Height());
    memDC.SetViewportExt(rect.Width(), -rect.Height());
    memDC.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
    *************************
    CPen NewPen, * pOldPen;
    NewPen.CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
    pOldPen = memDC.SelectObject(&NewPen);
    CBrush NewBrush, * pOldBrush;
    pOldBrush = (CBrush*)memDC.SelectStockObject(BLACK_BRUSH);
    for (int i = 0; i < max; i++) {
    
        if (i == 0) {
            memDC.MoveTo(P[i].x,P[i].y);
            memDC.Ellipse(Round(P[i].x) - 5, Round(P[i].y) - 5, Round(P[i].x) + 5, Round(P[i].y) + 5);
        }

        else{

            memDC.LineTo(Round(P[i].x), Round(P[i].y));
        memDC.Ellipse(Round(P[i].x) - 5, Round(P[i].y) - 5, Round(P[i].x) + 5, Round(P[i].y) + 5);
    }
    
    }
    if (CtrlPtNum != -1) {
        CString str;
        str.Format(_T(" x=%.0f,y=%.0f"), P[CtrlPtNum].x, P[CtrlPtNum].y);
        memDC.TextOut(Round(P[CtrlPtNum].x) + 5, Round(P[CtrlPtNum].y) + 5, str);
    }
    pDC->SelectObject(pOldBrush);
    memDC.SelectObject(pOldPen);
    DrawBSplineCurve(&memDC);//绘制曲线 
    pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, -rect.Width() / 2, -rect.Height() / 2, SRCCOPY);
    //pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, NULL, NULL, SRCCOPY);
    memDC.SelectObject(pOldBitmap);
    NewBitmap.DeleteObject();
    memDC.DeleteDC();}
void CbView::OnMouseMove(UINT nFlags, CPoint point)
{
     //TODO: 在此添加消息处理程序代码和/或调用默认值



    CString str;
    str.Format(_T("[%d,%d]  "), point.x - nClientWidth / 2, nClientHeight / 2 - point.y); //引号中的两个空格是为了消除重叠现象
    CDC* pDC = GetDC();
    pDC->TextOut(0, 0, str); //窗口左上角坐标为(0,0),修改可改变鼠标坐标的显示位置
    pDC->MoveTo(nClientWidth / 2, nClientHeight / 2);
    pDC->LineTo(nClientWidth / 2, nClientHeight / 2);

    if (TRUE == bMove)
    {
        if (CtrlPtNum == -1) { CtrlPtNum = 0; }
        else {
            P[CtrlPtNum] =Convert( point);
        
        }
    }
    CtrlPtNum = -1;
    int i;


    for (i = 0; i < max; i++) {
        CP2 CursorPt = Convert (point);//得到鼠标当前位置并且将点存在变量中
        CString str1;
        if ((CursorPt.x - P[i].x) * (CursorPt.x - P[i].x) + (CursorPt.y - P[i].y) * (CursorPt.y - P[i].y) < 25) //如果鼠标与某个控制点的距离不超过5个像素点认为当前鼠标指向点
        {

            CtrlPtNum = i;
            bLBtnDown = TRUE;
            SetCursor(LoadCursor(NULL, IDC_SIZEALL));//鼠标改
            break;



        }
    }
    if (max == i)
    {
        CtrlPtNum = -1;
    }
    ReleaseDC(pDC);
    Invalidate(FALSE);

    CView::OnMouseMove(nFlags, point);
    



}


void CbView::DrawBSplineCurve(CDC * pDC)//绘制曲线
{
    // TODO: 在此处添加实现代码.
    CPen redPen, greenPen, * pOldPen;
    redPen.CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
    greenPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0));
    CP2 pt;//曲线上的当前点
    pt.x = Round((P[0].x + 4.0 * P[1].x + P[2].x) / 6);
    pt.y = Round((P[0].y + 4.0 * P[1].y + P[2].y) / 6);
    pOldPen = pDC->SelectObject(&greenPen);
    pDC->Ellipse(Round(pt.x) - 5, Round(pt.y) - 5, Round(pt.x) + 5, Round(pt.y) + 5);
     pDC->SelectObject(pOldPen);
     pDC->MoveTo(Round(pt.x), Round(pt.y));
    for (int i = 3; i < max; i++) {
        for (double t = 0.0; t <= 1; t += 0.01) {
            double F03 = (-t * t * t + 3 * t * t - 3 * t + 1) / 6;
            double F13 = (3 * t * t * t - 6 * t * t + 4) / 6;
            double F23 = (-3 * t * t * t + 3 * t * t + 3 * t + 1) / 6;
            double F33 = t * t * t / 6;
             pt.x = P[i - 3].x* F03 + P[i-2].x * F13 + P[i - 1].x * F23 +P[i].x* F33;
             pt.y = P[i - 3].y * F03 + P[i - 2].y * F13 + P[i - 1].y * F23 + P[i].y * F33;        
             pDC->LineTo(Round(pt.x),Round(pt.y));//绘制曲线
        }

        pOldPen = pDC->SelectObject(&greenPen);
        pDC->Ellipse(Round(pt.x) - 5, Round(pt.y) - 5, Round(pt.x) + 5, Round(pt.y) + 5);
        pDC->SelectObject(pOldPen);
    }
    pDC->SelectObject(pOldPen);
    
}
CP2 CbView::Convert(CPoint point) {
    CP2 pt;
    pt.x = point.x - nClientWidth / 2;
    pt.y = nClientHeight / 2 - point.y;
    return pt;


}



void CbView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    if (Brd)
    {
        P[j] = Convert(point);
        if (j < max - 1) j++;
        else Brd = FALSE;
    
    }
    if (bLBtnDown == TRUE)
    {
        bMove = TRUE;
    }
    

    CView::OnLButtonDown(nFlags, point);
}


void CbView::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    bLBtnDown = FALSE;
    bMove = FALSE;
    //CtrlPtNum = 0;
    CView::OnLButtonUp(nFlags, point);
}


把max弄成j就行

也不知道你要画什麽,为啥for循环里要MoveTo,LineTo呢?

引用chatGPT作答,这段MFC代码的问题可能出在画线的for循环中。在每个点之间绘制线条时,用到了LineTo()函数,而这个函数会将当前绘图位置和指定点之间连一条线段,同时更新绘图位置到指定点。这就意味着,前一个点的绘图位置会被更新为后一个点,从而出现最后一个点连回原点的情况。

要解决这个问题,可以在循环开始前将绘图位置设置为第一个点的位置,即添加一行代码:memDC.MoveTo(Round(P[0].x), Round(P[0].y));。这样,绘图位置就不会被更新为最后一个点的位置了,从而避免了连接回原点的问题。

同时,这段代码还有一处错误:在循环中,每个点之后都会绘制一个圆形,但是最后一个点之后不应该再绘制圆形。因此,可以将绘制圆形的代码移到循环之外,只在循环中绘制线条即可。

以下内容部分参考ChatGPT模型:


可能是你没有正确更新起点的位置。在画线之前,更新起点的位置为当前的终点位置,这样就不会连接到原点了。示例代码如下:

CPoint startPoint = endPoint; // 更新起点位置
endPoint = newEndPoint; // 更新终点位置
pDC->MoveTo(startPoint); // 移动到起点
pDC->LineTo(endPoint); // 画线到终点

请注意,这只是一个示例代码,具体实现可能会根据你的代码有所不同。


如果我的建议对您有帮助、请点击采纳、祝您生活愉快

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
这种问题通常是由于绘制时没有正确设置起点引起的。从代码中可以看出,每次绘制完一个点之后,都会用 MoveTo() 方法将绘图起点移到这个点,但是在绘制曲线时,没有正确设置起点,导致新的一条曲线的起点会自动连接到上一条曲线的终点,也就是原点。

解决方法是,在绘制曲线时,首先使用 MoveTo() 方法将起点设置为当前曲线的起点,然后再开始绘制。以下是修改后的代码:

for (int i = 3; i < max; i++) {
    CP2 start = P[i - 3]; // 记录当前曲线的起点
    for (double t = 0.0; t <= 1; t += 0.01) {
        double F03 = (-t * t * t + 3 * t * t - 3 * t + 1) / 6;
        double F13 = (3 * t * t * t - 6 * t * t + 4) / 6;
        double F23 = (-3 * t * t * t + 3 * t * t + 3 * t + 1) / 6;
        double F33 = t * t * t / 6;
        pt.x = P[i - 3].x * F03 + P[i - 2].x * F13 + P[i - 1].x * F23 + P[i].x * F33;
        pt.y = P[i - 3].y * F03 + P[i - 2].y * F13 + P[i - 1].y * F23 + P[i].y * F33;        
        if (t == 0.0) { // 设置起点
            pDC->MoveTo(Round(pt.x),Round(pt.y));
        } else {
            pDC->LineTo(Round(pt.x),Round(pt.y));//绘制曲线
        }
    }

    pOldPen = pDC->SelectObject(&greenPen);
    pDC->Ellipse(Round(pt.x) - 5, Round(pt.y) - 5, Round(pt.x) + 5, Round(pt.y) + 5);
    pDC->SelectObject(pOldPen);
}

如果我的回答解决了您的问题,请采纳!