GDI繪圖中經(jīng)常會創(chuàng)建一些畫刷、畫筆和位圖等資源,通常這些資源通過調(diào)用函數(shù)CreateSolidBrush、CreatePen、CreateCompatibleBitmap等方法創(chuàng)建。這些資源在使用完成以后必須通過調(diào)用DeleteObject()函數(shù)釋放資源,否則會發(fā)生資源泄漏,最終導(dǎo)致系統(tǒng)資源被耗光,不能再次成功創(chuàng)建資源。
考慮下面一段代碼:
HBITMAP hBmpLayer1,hBmpOldLayer1;
HBITMAP hBmpLayer0,hBmpOldLayer0;
HDC hDcLayer1 = 0;
HDC hDcLayer0 = 0;
int mouseX =0,mouseY =0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
{
RECT rt;
rt.left = 0;
rt.right = 20;
rt.top = 0;
rt.bottom = 20;
hDcLayer1 = CreateCompatibleDC(GetDC(NULL));
hBmpLayer1 = CreateCompatibleBitmap(GetDC(NULL),20,20);
hBmpOldLayer1 = (HBITMAP)SelectObject(hDcLayer1,hBmpLayer1);
FillRect(hDcLayer1,&rt,CreateSolidBrush(0));
rt.left =2;
rt.top = 2;
rt.bottom =17;
rt.right =17;
FillRect(hDcLayer1,&rt,CreateSolidBrush(0xff00ff));
return DefWindowProc(hWnd, message, wParam, lParam);
}
case WM_PAINT:
RECT rt;
int i,k,x,y,error;
HPEN hPen,hOldPen;
HBRUSH hBrshBlack,hBrsh;
hdc = BeginPaint(hWnd, &ps);
if(!hdc)
{
error = GetLastError();
}
// TODO: Add any drawing code here...
GetClientRect(hWnd, &rt);
if(hDcLayer0 != NULL)
{
SelectObject(hDcLayer0,hBmpOldLayer0);
DeleteDC(hDcLayer0);//釋放資源
DeleteObject(hBmpLayer0);//釋放資源
hDcLayer0 = NULL;
hBmpLayer0 = NULL;
hBmpOldLayer0 = NULL;
}
hDcLayer0 = CreateCompatibleDC(hdc);
if(!hDcLayer0)
{
error = GetLastError();
}
hBmpLayer0 = CreateCompatibleBitmap(hdc,rt.right-rt.left,rt.bottom-rt.top);
if(!hBmpLayer0)
{
error = GetLastError();
}
hBmpOldLayer0 = (HBITMAP)SelectObject(hDcLayer0,hBmpLayer0);
if(!hBmpOldLayer0)
{
error = GetLastError();
}
hBrshBlack = CreateSolidBrush(0);
FillRect(hDcLayer0,&rt,hBrshBlack);
x=rt.left;
y=rt.top+(rt.bottom-rt.top)/2;
hPen = CreatePen(PS_SOLID, 1, RGB(0xff,0x0,0x0));
hOldPen = (HPEN)SelectObject(hDcLayer0 ,hPen);//選入畫筆
MoveToEx(hDcLayer0 ,x,y,NULL);
LineTo(hDcLayer0 ,rt.right,y+5);//繪圖
SelectObject(hDcLayer0 ,hOldPen);//選出畫筆
DeleteObject(hPen);//釋放資源
hPen = CreatePen(PS_SOLID, 1, RGB(0x0,0xff,0x0));
hOldPen = (HPEN)SelectObject(hDcLayer0 ,hPen);
MoveToEx(hDcLayer0 ,x,y+10,NULL);
LineTo(hDcLayer0 ,rt.right,y+10);//繪圖
SelectObject(hDcLayer0 ,hOldPen);//選出畫筆
DeleteObject(hPen);
hPen = CreatePen(PS_SOLID, 1, RGB(0x0,0x0,0xff));
hOldPen = (HPEN)SelectObject(hDcLayer0 ,hPen);//選入畫筆
MoveToEx(hDcLayer0 ,x,y-10,NULL);
LineTo(hDcLayer0 ,rt.right,y-10);//繪圖
SelectObject(hDcLayer0 ,hOldPen);//選出畫筆
DeleteObject(hPen);//釋放畫筆資源
DeleteObject(hBrshBlack);//釋放畫刷資源
error = BitBlt(hdc,0,0,rt.right,rt.bottom,hDcLayer0,0,0,SRCCOPY);
if(!error)
error =GetLastError();
TransparentBlt(hdc,mouseX,mouseY,20,20,hDcLayer1,0,0,20,20,0);
EndPaint(hWnd, &ps);
break;
case WM_MOUSEMOVE:
{
mouseX = lParam&0xffff;
mouseY = lParam>>16;
InvalidateRect(hWnd,NULL,FALSE);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
如果將程序中釋放資源的部分去掉,那么在鼠標(biāo)移動一段時間以后,畫面將變成黑白圖像,其原因就是多次創(chuàng)建資源而沒有釋放,導(dǎo)致資源耗盡,無法再次分配資源。
對于DC資源,如果使用CreateCompitableDC()方法創(chuàng)建,則在使用完成后需要使用DeleteDC()釋放資源。
如果是通過GetDC()方法獲取的資源,則需要調(diào)用ReleaseDC()釋放資源。
對于已選入了DC的畫筆、畫刷、位圖等資源,必須將其選出后才能進(jìn)行資源釋放,否則不成功。