0

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;
        } 
            ...
Al2O3
  • 3,103
  • 4
  • 26
  • 52

3 Answers3

1

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.

Mark Ingram
  • 71,849
  • 51
  • 176
  • 230
  • but I get puzzled here: why when I remove the first call to the function, the ellipse will be black solid inside. – Al2O3 Sep 21 '12 at 14:42
  • Remove the first call to *which* function? Have you tried debugging it? – Mark Ingram Sep 21 '12 at 15:03
  • the call to pDC->Ellipse(...) – Al2O3 Sep 21 '12 at 15:13
  • In that case it's just drawing an ellipse as it normally would. It looks like you don't have a brush selected into the DC though, which might explain why it's black, it's only transparent if `sol == 0`. – Mark Ingram Sep 21 '12 at 15:28
  • If I delete the first call, (I confirmed that sol == 0 and pen is green), but the result is: only the outline of it is green, and the interior is black. I really appreciate it if you would read the code edited. – Al2O3 Sep 22 '12 at 02:01
0

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.

display101
  • 2,035
  • 1
  • 14
  • 10
  • I am not good at debugging, but I got the color of the pen, which is RGB(0,255,0): green, but as you see, only the outline of it is green, and the interior is black. – Al2O3 Sep 21 '12 at 23:55
  • I wonder whether "CBrush brush;" makes " pDC->Ellipse(...)" draw an Ellipse with black interior. – Al2O3 Sep 22 '12 at 00:01
  • @JohnSon Yes the interior is black, and I'm willing to bet that if you look into the color of your brush, it's more than likely black. If you have a read of the docs on the `pDC->Ellipse()` [method](http://msdn.microsoft.com/en-US/library/6hkxb3kd%28v=vs.80%29.aspx), it mentions the brush color will be used to fill in the color of the ellipse. – display101 Sep 24 '12 at 08:25
0

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.

Al2O3
  • 3,103
  • 4
  • 26
  • 52