用GDI+拖动鼠标绘制椭圆

问题描述 投票:0回答:1

通过一个小小的改动,下面链接中WM_MOUSEMOVE下的代码可以通过拖动鼠标来绘制一个10像素粗的红色椭圆。第一个 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

我想用GDI+做同样的操作。由于我在 GDI+ 中找不到与 SetROP2 函数等效的函数,因此我尝试了第一个 DrawEllipse 函数,使用背景颜色作为画笔颜色来擦除以前的椭圆。但我没有得到我期望的结果:

        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;
        }

程序图片如下:

enter image description here

完成此操作的最佳方法是什么?

c++ winapi gdi+ gdi
1个回答
0
投票

我使用双缓冲简化了代码,并使用按钮运行。什么也没有变。我希望我做得正确。请检查一下代码好吗?

 hdc = GetDC(hwnd);

 RECT rc_main;
 GetClientRect(hwnd, &rc_main);

 HDC dc_comp = CreateCompatibleDC(hdc);
 HBITMAP bmp_comp = CreateCompatibleBitmap(hdc, rc_main.right-rc_main.left, rc_main.bottom-rc_main.top);

 HGDIOBJ obj_bmp = SelectObject(dc_comp, bmp_comp);

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

 BitBlt(dc_comp, 0, 0, rc_main.right-rc_main.left, rc_main.bottom-rc_main.top, hdc, 0, 0, SRCCOPY);

 Gdiplus::Pen pen(Gdiplus::Color(255, 255, 0, 0), 10); // Pen color
 graphics.DrawEllipse(&pen, 50, 50, 200, 150);

 Gdiplus::Pen pen2(Gdiplus::Color(255, 236, 236, 236), 10); // Background color
 graphics.DrawEllipse(&pen2, 50, 50, 200, 150);

 BitBlt(hdc, 0, 0, rc_main.right-rc_main.left, rc_main.bottom-rc_main.top, dc_comp, 0, 0, SRCCOPY);

 SelectObject(dc_comp, obj_bmp);
 DeleteObject(bmp_comp);
 DeleteObject(dc_comp);

 ReleaseDC(hwnd, hdc);
© www.soinside.com 2019 - 2024. All rights reserved.