如果我使用CreateFont()创建一个字体(作为非静态变量)并使用SelectObject在函数中使用它,那么在退出该函数之前,我必须选择前一个对象并使用DeleteObject删除该字体。
但是如果我声明一个全局变量HFONT gFont = CreateFont(...)
,那么在WM_DESTROY
消息中,我应该调用DeleteObject
来删除字体吗?
同样在这种情况下,如果我在函数中使用hOldFont = SelectObject(memDC, gFont);
,我应该在退出该函数之前调用SelectObject(memDC, hOldFont);
吗?在我看来,对于Bitmap,我们应该清理它,但我不知道其他GDI对象是否也是如此。
答案 0 :(得分:3)
将每个DeviceContext
(DC)视为画布。这些画布中的每一个一次只能为每个类型提供一个活动的 GDI对象。因此,您可以为该画布选择一个Brush
,Pen
,Font
等活动。
当您致电SelectObject()
时,您正在设置该类型的活动对象。把它想象成“拿起红笔画画,然后拿起蓝笔画画”。如果GDI函数采用Pen
(例如Rectangle
),它将通过SelectObject
使用最后选择的笔。这就是SelectObject
返回先前值的原因,因此您可以在完成后将其存储以恢复状态。
您应该始终在任何不再需要的已创建GDI对象上使用DestroyObject
。此外,对于每{{}}}次来电,您应始终使用DeleteDC
;对于每次CreateDC
来说,您应始终使用ReleaseDC
(当您不再需要DC时)。
最佳做法是将GetDC
(DC)恢复为您找到它的方式。因此,如果您设置DeviceContext
或Font
,则应在返回之前将其恢复为原始值。恢复并不重要的唯一时间是当你即将处置DC时,也许是在临时Brush
的情况下。
如果您使用Bitmap
,则无需致电GetStockObject
。
答案 1 :(得分:1)
一个Delphi(帕斯卡)示例:
Procedure AngleTextOut(hDC: THandle; const sTxt: string; iX, iY, iH, iAngle: integer);
var
aryC: array[0..255] of Char;
hFont, hFontOld: THandle;
begin
StrPCopy(aryC, sTxt);
hFont:= CreateFont(-iH, 0, iAngle *10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'arial');
hFontOld:= SelectObject(hDC, hFont);
TextOut(hDC, iX, iY, aryC, StrLen(aryC));
SelectObject(hDC, hFontOld);
DeleteObject(hFont);
end;// AngleTextOut