Question

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;
        } 
            ...
Was it helpful?

Solution 3

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.

OTHER TIPS

It's because of the call to pDC->SetROP2(R2_NOT). The R2_NOT flag means "Pixel remains unchanged.", according to MSDN. You can read the documentation here - http://msdn.microsoft.com/en-us/library/99ax95h9.aspx.

The ellipse is drawn with the current pen, and its interior is filled with the current brush.

From the CDC::Ellipse() reference from MSDN

 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);
     }
 if(do_what==DRAW_CIRCLE){
           assist.y=point.y-point.x+start.x;
     }
 pDC->Ellipse(start.x,assist.y,point.x,point.y);

So our ROP is R2_COPYPEN which states that the pixel to use is the current pen color. My guess is that the pen is black and the ellipse gets filled in as black (read ellipse description above about brush being used to fill ellipse).

 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);
     }
 if(do_what==DRAW_CIRCLE){
           assist.y=point.y-point.x+start.x;
     }
 // pDC->Ellipse(start.x,assist.y,point.x,point.y);

So if we delete the 2nd Ellipse call then we use R2_NOT, so the pixel remains the same (so the gray background) so we end up drawing the ellipse with a pen the same color as the background, so it's never seen.

You really need to debug to see what's going on but if you can find out the pen color and brush color at each point, you should get a good idea of what's going on.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top