通过一个小小的改动,下面链接中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;
}
我想用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;
}
程序图片如下:
完成此操作的最佳方法是什么?
我使用双缓冲简化了代码,并使用按钮运行。什么也没有变。我希望我做得正确。请检查一下代码好吗?
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);