2013-06-05 67 views
1

我正在Win32下做一个简单的游戏。目前,我的主要文件中全局声明了大部分绘图对象,因此我从不必删除它们或重新加载位图。所以基本上所有的位图都在WM_CREATE中加载,然后什么都不需要删除 - 有人告诉我,我可以依靠系统清理项目终止时的资源。在WM_PAINT(每秒调用大约10次)中,我有很多BitBlt()调用,以及不少的SelectObject()调用。运行约10-15分钟后,SelectObject()。什么会导致SelectObject()失败,我是否正确使用GDI对象?Win32 - 什么是使用GDI对象的正确方法?

例:

// Top of the file 
HDC hdc; 
HDC hdcmem; 
HDC hbcmem; 
HBITMAP colorsprites, blackwhitesprites, nums; 
HBITMAP hdcold, hdcbmold, hdcbm; 

// Some functions to get the window ready 

// More variables used for drawing: 
HBITMAP bg, side, mainCont, tmpbm, tmpold, bm_left, bm_right, sidebg, win_bm; 
PAINTSTRUCT ps; 
RECT rc; 
HDC tmphdc; 
HDC tmp; 
HFONT font; 
HBRUSH hbr; 
HPEN pen; 
BITMAP structBitmapHeader; 
HGDIOBJ hBitmap; 
HCURSOR crosshairs = LoadCursorW(hInst, IDC_CROSS); 
HCURSOR normal = LoadCursorW(hInst, IDC_ARROW); 
POINT cursor; 
bool addPass = false, ignorePass; 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
     case WM_CREATE: 
      hdc = GetDC(hWnd); 
      hdcmem = CreateCompatibleDC(hdc); 
      GetClientRect(hWnd, &rc); 
      hdcbm = CreateCompatibleBitmap(hdc, rc.right, rc.bottom); 
      hbcmem = CreateCompatibleDC(hdcmem); 
      hdcbmold = (HBITMAP)SelectObject(hdcmem, hdcbm); 

      // Load bitmaps 
      bg     = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BACKGROUND)); 
      mainCont   = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_GAME_CONT)); 
      side    = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SIDEINFO)); 
      colorsprites  = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_COLOR_SPRITES)); 
      blackwhitesprites = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BLACKWHITE_SPRITES)); 
      sidebg    = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SIDEBG)); 
      nums    = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_NUMBERS)); 
      bm_left    = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_LEFT)); 
      bm_right   = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_RIGHT)); 
      win_bm    = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_VICTORY)); 
      if(bg == NULL || mainCont == NULL || side == NULL || colorsprites == NULL 
      || blackwhitesprites == NULL || sidebg == NULL || nums == NULL || bm_left == NULL 
      || bm_right == NULL) 
       ThrowError("A bitmap failed to load."); 

      break; 

     case WM_PAINT: 
      BeginPaint(hWnd, &ps); 

      // SelectObject() and BitBlt() are called a lot in here 

      EndPaint(hWnd, &ps); 

      break; 

     case WM_DESTROY: 
      // System will clean up all GDI stuff - no need to delete anything 
      PostQuitMessage(0); 
      break; 
    } 
} 
+1

展现此问题的代码的最短的完整示例将很好。 OS版本也可能有帮助。 – chris

+0

如果你可以让它失败得更快,那也会有很大的帮助。 – chris

+1

听起来像是一个GDI泄漏,确保你正确地调用'ReleaseDC'或'EndPaint'。 –

回答

3

确保当你摧毁一个DC,你所选择的原始位回吧。您的位图仍处于选中状态时,不应该销毁DC。

+0

你是什么意思的“原始”位图?你的意思是我必须在删除DC之前调用SelectObject(),如果我将某些东西加载到使用SelectObject som的其他地方? –

+3

@BrianGradin,'SelectObject'返回你应该保留并重新选择它,然后再销毁它(或者'WM_CREATE',它使用GetDC而不是创建一个,释放它)。 – chris

+1

@BrianGradin,找到我记得的。这是一个很好的阅读主题:http://blogs.msdn.com/b/oldnewthing/archive/2013/03/06/10399678.aspx – chris

相关问题