如果您发布不干净的设备上下文会发生什么?

时间:2014-03-09 07:54:07

标签: c winapi gdi

通常,如果程序将对象选择到设备上下文中,或者更改其属性,则应在释放设备上下文之前将其更改回来。如果没有会发生什么?

让我说我这样做:

HDC hdc = GetDC(some_window);
SelectObject(hdc, some_font);
SetTextColor(hdc, 0x123456);
SetBkColor(hdc, 0xFEDCBA);
SetROP2(hdc, R2_XORPEN);
ReleaseDC(some_window, hdc);

some_window的窗口类没有CS_OWNDCCS_CLASSDC标志。会发生什么?

2 个答案:

答案 0 :(得分:3)

在您列出的功能中,如果未取消选择对象(通过选择原始对象),SelectObject是唯一会导致问题的功能。这会导致some_font资源泄露,因为DC在发布时会持有一个打开的句柄。

你应该这样做:

HDC hdc = GetDC(some_window);
HGDIOBJ hOldObj = SelectObject(hdc, some_font);

// ... 

SelectObject(hdc, hOldObj);
ReleaseDC(some_window, hdc);

或许这个:

HDC hdc = GetDC(some_window);
int nSaved = SaveDC(hdc);
SelectObject(hdc, some_font);

// ... 

RestoreDC(nSaved);
ReleaseDC(some_window, hdc);

作为MSDN notes

  

这些函数中的每一个都返回一个标识新对象的句柄。   在应用程序检索句柄后,它必须调用    SelectObject 函数替换默认对象。但是,应用程序应保存标识默认对象的句柄   在不再需要时使用此句柄替换新对象。   当应用程序使用新对象完成绘制时,它必须   通过调用 SelectObject 函数来恢复默认对象   然后通过调用 DeleteObject 删除新对象   功能。无法删除对象会导致严重的性能   问题。

答案 1 :(得分:0)

无法恢复原始字体对象会导致句柄泄漏。操作系统将保留some_font的句柄。如果重复执行此代码,则每次都会泄漏另一个句柄。您将在任务管理器中看到Handles计数。如果这种情况持续很长时间,那么最终会出现一种看似垃圾的绘画失败。