请确认选择自定义笔和自定义画笔时恢复DC的最佳方式

Please confirm the best way to Restore the DC when a custom Pen and a custom Brush are selected

有人可以确认 Microsoft 的 this sample code 是否无法恢复使用 SetDCBrushColor 设置的自定义画笔吗?


    case WM_PAINT:        
        {    
            hdc = BeginPaint(hWnd, &ps);
        //    Initializing original object
            HGDIOBJ original = NULL;
        //    Saving the original object
            original = SelectObject(hdc,GetStockObject(DC_PEN));

        //    ...

            SelectObject(hdc, GetStockObject(BLACK_PEN));
            Rectangle(hdc,0,0,200,200);

            SelectObject(hdc, GetStockObject(DC_PEN));
            SelectObject(hdc, GetStockObject(DC_BRUSH));
            SetDCBrushColor(hdc, RGB(255,0,0));
            SetDCPenColor(hdc, RGB(0,0,255));
            Rectangle(hdc,100,300,200,400);
            SetDCBrushColor(hdc, RGB(0,255,0));
            Rectangle(hdc,300,150,500,300);

        //   Restoring the original object
            SelectObject(hdc,original);
        }
        
        break;
//...

Paul Watt等博主建议我们使用SelectObject分别恢复对笔和画笔的更改,或者我们使用SaveDCRestoreDC

https://www.codeproject.com/Articles/224754/Guide-to-Win32-Memory-DC

// Setup paint for first layer.
HGDIOBJ hOldBrush = ::SelectObject(hDC, hBrush);
HGDIOBJ hOldPen   = ::SelectObject(hDC, hPen);
HGDIOBJ hOldFont  = ::SelectObject(hDC, hFont);
HGDIOBJ hOldMan   = ::SelectObject(hDC, hBmp);

// ... Paint a motley display

::SelectObject(hDC, hOldBrush);
::SelectObject(hDC, hOldPen);
::SelectObject(hDC, hOldFont);
::SelectObject(hDC, hOldMan);

或者使用 SaveDCRestoreDC 来简化:

// Take a snap-shot of the current state of the DC
//https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-savedc
  int SaveDC(
    __in HDC hdc,           // Handle to the DC
);

// Restore the DC to a previously saved state
int RestoreDC(
    __in HDC hdc,           // Handle to the DC
    __in int nSavedDC       // Saved state claim ticket
);

我意识到我需要对我创建的任何 brushes/pens 非库存对象使用 DeleteObject

微软是不是忘记了使用SelectObject之前保存的原刷版本? (或者微软应该使用 SaveDCRestoreDC 吗?)

Did Microsoft forget to use SelectObject with a previously saved version of the original brush?

我会说:是的,他们做到了!

SetDCPenColor 调用的情况下,没有问题,因为恢复原始(保存的)笔将恢复所做的更改。该示例似乎忘记保存(并随后恢复)原始画笔;如果这是自定义画笔,那么仅使用 SetDCBrushColor 恢复画笔颜色(恕我直言)不足以恢复。

但问题并没有就此结束!链接示例也有 'forgotten' 调用 EndPaint!来自 here:

Each call to BeginPaint must have a corresponding call to the EndPaint function.


Or should Microsoft have used SaveDC and RestoreDC?

为了方便和代码安全,我认为这是最好的策略:保存和恢复 整个 DC 状态可以避免以后可能出现的任何问题 if/when 在未来的代码修订中对 DC 进行了其他更改。将您的代码放在 SaveDC()RestoreDC() 调用中还具有恢复字体颜色、文本模式、映射模式等 .

的优势

但是,对于可能执行得非常频繁的代码,仅保存和恢复您实际更改的组件可能会显示性能改进(尤其是在较旧或较慢的处理器上)。