Niteya
Niteya

Reputation: 13

Drawing an ellipse with GDI+ while dragging mouse

With a small change, the code under WM_MOUSEMOVE in the link below can draw a 10 pixel thick red ellipse by dragging the mouse. The first Ellipse function erases the previous ellipse.

https://learn.microsoft.com/en-us/windows/win32/gdi/using-filled-shapes

        case WM_MOUSEMOVE:
        {
             if(wParam && MK_LBUTTON) {
                hdc = GetDC(hwnd);
                SetROP2(hdc, R2_NOTXORPEN);

                HGDIOBJ obj_pen = SelectObject(hdc, CreatePen(PS_SOLID, 10, RGB(255,0,0)));

                // If a previous target rectangle exists, erase it by drawing another rectangle on top.
                if(!IsRectEmpty(&rcTarget)) {
                   Ellipse(hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom);
                }

                if((pt.x < (LONG) LOWORD(lParam)) && (pt.y > (LONG) HIWORD(lParam))) {
                   SetRect(&rcTarget, pt.x, HIWORD(lParam), LOWORD(lParam), pt.y);
                }
                else if ((pt.x > (LONG) LOWORD(lParam)) && (pt.y > (LONG) HIWORD(lParam))) {
                   SetRect(&rcTarget, LOWORD(lParam), HIWORD(lParam), pt.x, pt.y);
                }
                else if ((pt.x > (LONG) LOWORD(lParam)) && (pt.y < (LONG) HIWORD(lParam))) {
                   SetRect(&rcTarget, LOWORD(lParam), pt.y, pt.x, HIWORD(lParam));
                }
                else {
                   SetRect(&rcTarget, pt.x, pt.y, LOWORD(lParam), HIWORD(lParam));
                }

                // Draw the new target rectangle.
                Ellipse(hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom);

                SelectObject(hdc, obj_pen);
                ReleaseDC(hwnd, hdc);
            }
            return 0;
        }

enter image description here

I want to do the same operation with GDI+. Since I couldn't find the equivalent of the SetROP2 function in GDI+, I have tried the first DrawEllipse function to erase the previous ellipse using background color as pen color. But I couldn't get the result I expected:

        case WM_MOUSEMOVE:
        {
             if(wParam && MK_LBUTTON) {
                hdc = GetDC(hwnd);

                Gdiplus::Graphics graphics(hdc);
                graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);

                // If a previous target rectangle exists, erase it by drawing another rectangle on top.
                if(!IsRectEmpty(&rcTarget)) {
                   Gdiplus::Pen pen(Gdiplus::Color(255, 236, 236, 236), 10); // Background color
                   graphics.DrawEllipse(&pen, (int) rcTarget.left, (int) rcTarget.top,
                                              (int) rcTarget.right-(int)rcTarget.left, (int)rcTarget.bottom-(int)rcTarget.top);
                }

                if((pt.x < (LONG) LOWORD(lParam)) && (pt.y > (LONG) HIWORD(lParam))) {
                   SetRect(&rcTarget, pt.x, HIWORD(lParam), LOWORD(lParam), pt.y);
                }
                else if ((pt.x > (LONG) LOWORD(lParam)) && (pt.y > (LONG) HIWORD(lParam))) {
                   SetRect(&rcTarget, LOWORD(lParam), HIWORD(lParam), pt.x, pt.y);
                }
                else if ((pt.x > (LONG) LOWORD(lParam)) && (pt.y < (LONG) HIWORD(lParam))) {
                   SetRect(&rcTarget, LOWORD(lParam), pt.y, pt.x, HIWORD(lParam));
                }
                else {
                   SetRect(&rcTarget, pt.x, pt.y, LOWORD(lParam), HIWORD(lParam));
                }

                // Draw the new target rectangle.
                Gdiplus::Pen pen(Gdiplus::Color(255, 255, 0, 0), 10); // Pen color
                graphics.DrawEllipse(&pen, (int) rcTarget.left, (int) rcTarget.top,
                                           (int) rcTarget.right-(int)rcTarget.left, (int)rcTarget.bottom-(int)rcTarget.top);

                ReleaseDC(hwnd, hdc);
            }
            return 0;
        }

The program image is below:

enter image description here

What is the best way to accomplish this operation?

@Jeaninez - MSFT @Simon Mourier

Now the code works fine for drawing a single ellipse or independent ellipses. However, when ellipses are drawn on top of each other, the ellipse area underneath is also erased. How can I solve this problem?

case WM_MOUSEMOVE:
{
     if(wParam && MK_LBUTTON) {
        hdc = GetDC(hwnd);

        Gdiplus::Graphics graphics(hdc);
        graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);

        // If a previous target rectangle exists, erase it by drawing another rectangle on top.
        if(!IsRectEmpty(&rcTarget)) {
           Gdiplus::Pen pen(Gdiplus::Color(255, 236, 236, 236), 12); // Background color
           graphics.DrawEllipse(&pen, (int) rcTarget.left, (int) rcTarget.top,
                                      (int) rcTarget.right-(int)rcTarget.left, (int)rcTarget.bottom-(int)rcTarget.top);
        }

        if((pt.x < (LONG) LOWORD(lParam)) && (pt.y > (LONG) HIWORD(lParam))) {
           SetRect(&rcTarget, pt.x, HIWORD(lParam), LOWORD(lParam), pt.y);
        }
        else if ((pt.x > (LONG) LOWORD(lParam)) && (pt.y > (LONG) HIWORD(lParam))) {
           SetRect(&rcTarget, LOWORD(lParam), HIWORD(lParam), pt.x, pt.y);
        }
        else if ((pt.x > (LONG) LOWORD(lParam)) && (pt.y < (LONG) HIWORD(lParam))) {
           SetRect(&rcTarget, LOWORD(lParam), pt.y, pt.x, HIWORD(lParam));
        }
        else {
           SetRect(&rcTarget, pt.x, pt.y, LOWORD(lParam), HIWORD(lParam));
        }

        // Draw the new target rectangle.
        Gdiplus::Pen pen2(Gdiplus::Color(255, 255, 0, 0), 10); // Pen color
        graphics.DrawEllipse(&pen2, (int) rcTarget.left, (int) rcTarget.top,
                                   (int) rcTarget.right-(int)rcTarget.left, (int)rcTarget.bottom-(int)rcTarget.top);

        ReleaseDC(hwnd, hdc);
    }
    return 0;
}

Program window

Upvotes: 0

Views: 187

Answers (1)

Jeaninez - MSFT
Jeaninez - MSFT

Reputation: 4040

I suggest you could try to set the width of the background color pen larger then the width of target color pen (10).

For example:

Set the width to 9:

//Pen pen(Color(255, 236, 236, 236), 10); // Background color
Pen pen(Color(255, 255, 255, 255), 9); // My background color is white

enter image description here

Set the width to 11:

//Pen pen(Color(255, 236, 236, 236), 10); // Background color
Pen pen(Color(255, 255, 255, 255), 11); // My background color is white

enter image description here

Upvotes: -2

Related Questions