Reputation: 300
I am attempting to write a program that, when a checkbox is ticked, displays a grid over a large area of the screen. I'm attempting to do this in WM_PAINT using BitBlt, and my display function is definitely called with the right boolean value. However, it doesn't make any change to the window. Am I doing something stupid, or is there no practical way of achieving this? If this is unachievable, is there any way of getting similar results without specifying a different set of images containing the grid?
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);
}
}
The dialog procedure is shown below.
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;
}
}
Upvotes: 1
Views: 386
Reputation: 8027
Main issue I can see is that you are calling BeginPaint
and EndPaint
twice. You should do it only once BeginPaint
before any painting is done, and EndPaint
after all painting has finished.
There could be other issues, this stuff is tricky to get exactly right.
Upvotes: 3