2013-06-05 3 views
1

저는 Win32에서 간단한 게임을 만들고 있습니다. 현재, 대부분의 그리기 개체는 주 파일에서 전역 적으로 선언되므로 삭제하거나 비트 맵을 다시로드 할 필요가 없습니다. 그래서 기본적으로 모든 비트 맵은 WM_CREATE에로드되고 아무 것도 삭제 될 필요가 없습니다. 프로젝트 종료에 대한 리소스를 정리하기 위해 시스템에 의존 할 수 있다고 누군가에게 들었습니다. 약 1 초에 10 번 호출되는 WM_PAINT에는 많은 SelectButton() 호출과 많은 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

"원본"비트 맵의 ​​의미는 무엇입니까? SelectObject를 사용하여 무언가를로드 한 경우 DC를 삭제하기 전에 SelectObject()를 호출해야한다는 것을 의미합니까? –

+3

@BrianGradin는'SelectObject' 당신의 보류를 유지하고 당신이 그것을 파괴하기 전에 (또는 대신 하나를 만드는'GetDC'을 사용'WM_CREATE'의 경우에, 그것을 해제) 다시로 선택해야하는지 반환합니다. – chris

+1

@BrianGradin, 내가 기억하는 것을 발견했습니다. 나는'HBITMAP이있는 경우 나, 제대로 이해 해요 경우 http://blogs.msdn.com/b/oldnewthing/archive/2013/03/06/10399678.aspx – chris

관련 문제