Search code examples
c++mfccdc

Why function Ellipse(...) are needed twice here to draw an ellipse?


MFC: I read this code which is to draw an ellipse (not solid interior), but I cannot understand why function "pDC->Ellipse(...)" is needed twice here? (sol == 0, and do_what==DRAW_ELLIPSE)

void CMy078207017Dlg::OnLButtonUp(UINT nFlags, CPoint point) 
{
        flag = 0;
    end = point;
    assist = point;
    if(p != NULL)
    {
        CDC* pDC = GetDC();
        CPen pen;
        CBrush brush;
        getpen(pen, pDC, col, bol);
        if(do_what >= DRAW_LINE && do_what <= DRAW_RRECT)
        {
            p->p[0] = start;
            p->p[1] = end;
        }

        if(sol == 1)
        {
            getbrush(brush, pDC, col);
        }

        if(do_what == DRAW_LINE)
        {
            pDC->MoveTo(start);
            pDC->LineTo(end);
        }
        else
        {
            if(do_what == DRAW_ELLIPSE || do_what == DRAW_CIRCLE)
            {

                assist = start;
                if(do_what == DRAW_CIRCLE)
                {
                    assist.y = end.y - end.x + start.x;
                }


                pDC->SetROP2(R2_NOT);
                pDC->Ellipse(start.x, assist.y, end.x, end.y);


                pDC->SetROP2(R2_COPYPEN);
                if(sol == 0)
                {
                    pDC->SelectStockObject(NULL_BRUSH);
                }
                pDC->Ellipse(start.x, assist.y, end.x, end.y);


                end = point;
            }

        }
        ReleaseDC(pDC);
    }
    CDialog::OnLButtonUp(nFlags, point);
}

If I remove the first call to pDC->Ellipse(...), the ellipse will be black solid inside. If I remove the second call to pDC->Ellipse(...), the ellipse will never be drawn but disappears when left mouse button is up.

the dialog: when moving mouse: enter image description here mouse moving(the pen is green)

when mouse button pops: enter image description here mouse button pops(the pen is green)

Besides, what color of CBrush is if I use "CBrush brush; pDC->Ellipse(start.x,assist.y,end.x,end.y);"

the strategy may be more clear when it comes to rectangle:

             ...
    else if(do_what==DRAW_RECT||do_what==DRAW_RRECT){

            pDC->SetROP2(R2_NOT);
            if(do_what==DRAW_RECT)
            {
                pDC->Rectangle(start.x,start.y,end.x,end.y);
            }
            else if(do_what==DRAW_RRECT)
            {
                pDC->RoundRect(start.x,start.y,end.x,end.y,20,20);
            }


            pDC->SetROP2(R2_COPYPEN);
            if(sol==0)
            {   
                pDC->SelectStockObject(NULL_BRUSH);
            }
            if(do_what==DRAW_RECT)
            {
                pDC->Rectangle(start.x,start.y,point.x,point.y);
            }
            else if(do_what==DRAW_RRECT)
            {
                pDC->RoundRect(start.x,start.y,point.x,point.y,20,20);
            }
            end=point;
        } 
            ...

Solution

  • I finally get out of the trouble: codes elsewhere:

    void CDraw2009303476Dlg::OnMouseMove(UINT nFlags, CPoint point) 
    {
        if(flag == 1)   
        {
            CDC* pDC = GetDC();
            CPen pen;
            CBrush brush;
            getPen(pen, pDC, col, bol);
    
            if(sol == 1)
            {
                getBrush(brush, pDC, col);
            }
            if(type >= DRAW_LINE && type <= DRAW_RRECT)
            {
                pDC->SetROP2(R2_NOT);
                if(type == DRAW_LINE)
                {
                    p->drawLine(point, pDC);
                }
                else if(type == DRAW_ELLIPSE)
                {
                    p->drawEllipse(point, pDC);
                }
                else if(type == DRAW_CIRCLE)
                {
                    p->drawEllipse(point, pDC, 1);
                }
                else if(type == DRAW_RECT)
                {
                    p->drawRect(point, pDC);
                }
                else if(type == DRAW_RRECT)
                {
                    p->drawRect(point, pDC, 1);
                }
            }
            ReleaseDC(pDC);
        }
        CDialog::OnMouseMove(nFlags, point);
    }
    

    So, the strategy is: Using "pDC->SetROP2(R2_NOT);" once and "p->drawEllipse(point, pDC, 1);" twice in the same place to save the original pixels to get the line-drawing effects. And the final call to "pDC->SetROP2(R2_COPYPEN); p->drawEllipse(point, pDC, 1)" is what we really need to see the ellipsis. Thank you for all your helps.