在Windows PC上編程,GDI是一個很重要的技術點。不少程序在運行一段時間後出現異常,致使程序崩潰,除了衆所周知的內存泄露之外,GDI資源泄露也是一個很直接的緣由。下面是我列出的一些注意事項。編程
這裏的Create指的是以它爲開頭的GDI函數,好比,CreateDIBitmap,CreateFont等等,最後都要調用DeleteObject來釋放。函數
假如咱們要使用GDI函數畫圖,正確的步驟應該以下:code
- a.建立一個內存兼容DC(CreateCompatibleDC) - b.建立一個內存兼容bitmap(CreateCompatibleBitmap) - c.關聯建立的內存兼容DC和bitmap(SelectObject) - d.畫圖 - e.BitBlt到目的DC上 - f.斷開內存兼容DC和bitmap關聯(SelectObject) - g.銷燬內存兼容bitmap - h.銷燬內存兼容DC
因爲SelectObject在選入一個新的GDI對象的時候會返回一個原來的GDI對象(假如成功的話),因此須要在步驟c的時候保存返回值,在步驟f的時候看成入口參數使用。還有,步驟g和步驟h實際上順序能夠隨意,由於他們兩個此刻已經沒有關係了,可是爲告終構清晰,我建議按照"先Create的後釋放,後Create的先釋放"的原則進行。
關於步驟f,可能會有爭議,由於即便省略這一步,步驟g和步驟h看起來照樣能夠返回一個成功的值。但實際上可能並無執行成功,至少boundschecker會報告有錯,錯誤信息大體是說,在釋放DC的時候還包含有非默認的GDI對象,在釋放GDI對象的時候又說這個GDI對象還被一個DC在使用。因此,我建議保留步驟f。對象
典型GDI畫圖代碼以下:內存
CRect rc; HDC hDC = ::GetDC(m_hWnd); ::GetClientRect(m_hWnd, &rc); HDC memDCDes = ::CreateCompatibleDC(NULL); HBRUSH hbrush = ::CreateSolidBrush(RGB(191, 219, 255)); HBITMAP memHbmp = ::CreateCompatibleBitmap(hDC, rc.right-rc.left, rc.bottom-rc.top); HBITMAP hmpOld = (HBITMAP)::SelectObject(memDCDes, memHbmp); ::FillRect(memDCDes, &rc, hbrush); ::SetBkMode(memDCDes, TRANSPARENT); // 畫圖 。。。 ::BitBlt(hDC, 0, 0, rc.right-rc.left, rc.bottom-rc.top, memDCDes, 0, 0, SRCCOPY); ::SelectObject(memDCDes, hmpOld); ::DeleteObject(memHbmp); ::DeleteObject(hbrush); ::DeleteDC(memDCDes); ::ReleaseDC(m_hWnd, hDC);