2013-04-15 29 views
1

我正在嘗試編寫一個程序,當勾選複選框時,會在大屏幕上顯示一個網格。我試圖在WM_PAINT中使用BitBlt來做到這一點,我的顯示功能肯定是用正確的布爾值調用的。但是,它不會對窗口進行任何更改。我在做一些愚蠢的事情,還是沒有實現這個目標的實際方法?如果這是無法實現的,是否有任何方法獲得類似的結果,而不指定包含網格的不同圖像集合?BitBlt兩個圖像在另一個上面

void DisplayRoom(HWND hwnd, char TileList[][100], POINT pMaxDisplay, POINT pMinDisplay, HBITMAP ahbmTileset[], bool bDisplayBars) 
{ 
HBITMAP hbmSprite, hbmMask; 
BITMAP bm; 
PAINTSTRUCT ps; 
HINSTANCE hinNULL = GetModuleHandle(NULL); 
HDC hdc = BeginPaint(hwnd, &ps); 
HDC hdcMem = CreateCompatibleDC(hdc); 
HBITMAP hbmOld; 
POINT Position; 
hbmSprite = LoadBitmap(hinNULL, MAKEINTRESOURCE(IDB_CLEAR_GROUND)); 
hbmOld = (HBITMAP)SelectObject(hdcMem, hbmSprite); 
GetObject(hbmSprite, sizeof(bm), &bm); 
for (int iii = pMinDisplay.x; iii < pMaxDisplay.x; iii++) 
    for (int jjj = pMinDisplay.y; jjj < pMaxDisplay.y; jjj++) 
    { 
     switch(TileList[iii][jjj]) 
     { 
     case 'g': 
      hbmSprite = ahbmTileset[0]; 
      break; 
     case 'd': 
      hbmSprite = ahbmTileset[1]; 
      break; 
     case 'i': 
      hbmSprite = ahbmTileset[2]; 
      break; 
     case 'l': 
      hbmSprite = ahbmTileset[3]; 
      break; 
     } 
        assert(hbmSprite != NULL); 
     SelectObject(hdcMem, hbmSprite); 
     BitBlt(hdc, (iii - pMinDisplay.x) * 34 + 90, (jjj - pMinDisplay.y) * 34 + 60, 34, 34, hdcMem, 0, 0, SRCCOPY); 
    } 
DeleteDC(hdcMem); 
EndPaint(hwnd, &ps); 
if (bDisplayBars) 
{ 
    HDC hdc = BeginPaint(hwnd, &ps); 
    HDC hdcMem = CreateCompatibleDC(hdc); 
    hbmSprite = LoadBitmap(hinNULL, MAKEINTRESOURCE(IDB_GRID)); 
      assert(hbmSprite != NULL); 
    hbmMask = CreateBitmapMask(hbmSprite, RGB(0,0,0)); 
    for (int iii = pMinDisplay.x; iii < pMaxDisplay.x; iii++) 
     for (int jjj = pMinDisplay.y; jjj < pMaxDisplay.y; jjj++) 
     { 
      SelectObject(hdcMem, hbmMask); 
      BitBlt(hdc, (iii - pMinDisplay.x) * 34 + 90, (jjj - pMinDisplay.y) * 34 + 60, 34, 34, hdcMem, 0, 0, SRCAND); 
      SelectObject(hdcMem, hbmSprite); 
      BitBlt(hdc, (iii - pMinDisplay.x) * 34 + 90, (jjj - pMinDisplay.y) * 34 + 60, 34, 34, hdcMem, 0, 0, SRCPAINT); 
     } 
    DeleteDC (hdcMem); 
    EndPaint(hwnd, &ps); 
} 
} 

對話框過程如下所示。

BOOL CALLBACK CreateRoom(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 
{ 
static char achTileDetails[100][100]; 
static POINT pDimensions, pMonsterLocations, pMinDisplay, pMaxDisplay; 
static HBITMAP ahbmTileset[4]; 
static bool bShowBars; 
switch(Message) 
{ 
case WM_INITDIALOG: 
    SetFocus(hwnd); 
    for (int iii = 0; iii < 100; iii++) 
     for(int jjj = 0; jjj < 100; jjj++) 
      achTileDetails[iii][jjj] = 'g'; 
    pDimensions.x = 20; 
    pDimensions.y = 10; 
    pMinDisplay.x = 0; 
    pMinDisplay.y = 0; 
    pMaxDisplay.x = 20; 
    pMaxDisplay.y = 10; 
    for (int iii = 0; iii < 4; iii++) 
     ahbmTileset[iii] = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_CLEAR_GROUND + iii)); 
    return TRUE; 
case WM_PAINT: 
    DisplayRoom(hwnd, achTileDetails, pMaxDisplay, pMinDisplay, ahbmTileset, bShowBars); 
    break; 
case WM_COMMAND: 
    switch(LOWORD(wParam)) 
    { 
    case IDCANCEL: 
     EndDialog(hwnd, IDCANCEL); 
     break; 
    case IDC_DISPLAY_GRID: 
     switch(HIWORD(wParam)) 
     { 
     case BN_CLICKED: 
      bShowBars = SendMessage(GetDlgItem(hwnd, IDC_DISPLAY_GRID), BM_GETCHECK, 0, 0); 
      InvalidateRect(hwnd, NULL, TRUE); 
      UpdateWindow(hwnd); 
      break; 
     } 
     break; 
    } 
    break; 
case WM_LBUTTONDOWN: 

    break; 
default: 
    return FALSE; 
} 
} 
+0

我想這會幫助你如果你顯示調用代碼。你也可以在這裏去掉95%的代碼並且仍然說明錯誤。我注意到你根本沒有檢查錯誤。最後,一個完整的可編譯程序將使我們解決您的問題變得微不足道。請提供。 –

+0

@DavidHeffernan我已經添加了對話框過程和一些斷言,以確保位圖加載正確。斷言在運行程序時沒有拋出任何東西。 –

+0

我看到@john發現了這個問題。對他有好處。如果你已經將代碼剝離到最低限度,那麼你會看到,一旦你找到一個單獨的「Begin/EndPaint」對,繪畫就開始表現出來。作爲建議的一般意見,創建一個小的可編譯複製不僅對我們有幫助,它將會在10次中有9次允許你自己解決問題。 –

回答

3

主要的問題,我可以看到的是,你在呼喚BeginPaintEndPaint兩次。在任何繪畫完成之前,您只應該執行一次BeginPaint,並且在完成所有繪畫之後執行EndPaint

可能還有其他問題,這個東西很難得到完全正確的。

+0

哇,這是愚蠢的......是的,它工作正常,如果我只是改變......我認爲我想要單獨的DC,因此稱爲塗料兩次。非常感謝您指出這一點 –

相關問題