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

问题描述

有人可以确认来自 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,200,200);

            SelectObject(hdc,GetStockObject(DC_PEN));
            SelectObject(hdc,GetStockObject(DC_Brush));
            SetDCBrushColor(hdc,RGB(255,0));
            SetDCPenColor(hdc,RGB(0,255));
            Rectangle(hdc,100,300,400);
            SetDCBrushColor(hdc,255,0));
            Rectangle(hdc,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
);

我意识到我需要在我创建的任何不是库存对象的画笔/笔上使用 DeleteObject

Microsoft 是否忘记将 SelectObject 与之前保存的原始画笔版本一起使用? (或者 Microsoft 是否应该使用 SaveDCRestoreDC?)

解决方法

微软是否忘记将 SelectObject 与以前保存的 原版刷机?

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

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

但问题并没有就此结束!链接的示例也“忘记”调用 EndPaint!来自here

BeginPaint 的每次调用都必须有一个对 EndPaint 功能。


或者微软应该使用 SaveDC 和 RestoreDC 吗?

为了方便和代码安全,我想说这是最好的策略:保存和恢复整个 DC 状态可以避免以后可能出现的任何问题,如果/当对DC 在未来的代码修订中进行。在 SaveDC()RestoreDC() 调用中括起您的代码还具有恢复字体颜色、文本模式、映射模式等的优势。

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