WM_PAINTメッセージの間に多くの描画が行われるゲームを作成しています。ウィンドウが無効になり、強制的に再描画される場所がいくつかあります。すべてをオフスクリーンDCに描画し、それをウィンドウに描画して、ちらつきのない「フレーム」を作成します。
しかし、時々、すべてが突然間違って描かれ始めます。私が使用する5つのビットマップのうち、最初の3つは多かれ少なかれ(完全ではありませんが)正しく描画し続けます。のように、これら3つの色情報はすべて正しいです。これら3つの後に描かれている他の2つは、間違った色で描かれています。白はまだ白として描かれていると思いますが、他のすべては灰色として描かれています。そして、私はグレースケールについて話しているのではありません。つまり、白以外はすべて同じ色、つまり灰色です。
また、これが発生し始めると、多くの場合、すべてが高すぎます(約20〜30ピクセル)。さらに、フォントとメッセージボックスは機能しなくなります-すべてのテキストはデフォルトのフォントで描画され(ただし、奇妙なことに、正しい色)、メッセージボックスはテキストなしで短時間だけ表示され、その後消えます-しかし、通常のように閉じる必要があります( Enterキーを押す必要があります。そうでない場合、メインウィンドウをクリックすると、入力を受け取るメッセージボックスが開いているときに通常どおりに実行されます(点滅してエラートーンをpingします)。だから、すべてが王室に台無しにされています。
私はこのプロジェクトにしばらく取り組んでいますが、このエラーが発生し始めたのは最近のことですが、以下のコードは文字通りまったく変更していません。たまにしか起こらないように見えるので、これを行うことができるものをテストするのは本当に難しいです。
WndProcのWM_CREATEとWM_PAINTのコードは次のとおりです。
case WM_CREATE:
{
hdc = GetDC(hWnd);
hdcmem = CreateCompatibleDC(hdc);
RECT rc;
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));
if(bg == NULL || mainCont == NULL)
ThrowError("A bitmap failed to load.");
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
// Background
hdcold = (HBITMAP)SelectObject(hbcmem, bg);
BitBlt(hdcmem, 0, 0, 237, 196, hbcmem, 0, 0, SRCCOPY);
BitBlt(hdcmem, 237, 0, 237, 196, hbcmem, 0, 0, SRCCOPY);
BitBlt(hdcmem, 237 * 2, 0, 237, 196, hbcmem, 0, 0, SRCCOPY);
BitBlt(hdcmem, 0, 196, 237, 196, hbcmem, 0, 0, SRCCOPY);
BitBlt(hdcmem, 237, 196, 237, 196, hbcmem, 0, 0, SRCCOPY);
BitBlt(hdcmem, 237 * 2, 196, 237, 196, hbcmem, 0, 0, SRCCOPY);
// Main Game Container
hdcold = (HBITMAP)SelectObject(hbcmem, mainCont);
BitBlt(hdcmem, 26, 26, 300, 300, hbcmem, 0, 0, SRCCOPY);
// Side Info
HBITMAP side = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SIDEINFO));
hdcold = (HBITMAP)SelectObject(hbcmem, side);
BitBlt(hdcmem, 339, 26, 154, 300, hbcmem, 0, 0, SRCCOPY);
DrawLevelNumber(game.map.levelnumber);
if (color)
sprites = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_COLOR_SPRITES));
else sprites = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BLACKWHITE_SPRITES));
hdcold = (HBITMAP)SelectObject(hbcmem, sprites);
// Find x and y coordinate for the top left of the visible screen
int x = game.player.x, y = game.player.y, ypos = 0;
if (x < 4) x = 4;
if (x > 27) x = 27;
if (y < 4) y = 4;
if (y > 27) y = 27;
x -= 4;
y -= 4;
// Draw lower layer
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (game.map.Layer_Two[x + i][y + j] != 0)
{
int xpos = game.get_pos(game.map.Layer_Two[x + i][y + j].get(), ypos, false);
BitBlt(hdcmem, (i * 32) + 32, (j * 32) + 32, 32, 32, hbcmem, xpos, ypos, SRCCOPY);
}
}
}
// Draw upper layer
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if ((game.map.Layer_Two[x + i][y + j] != 0 && game.map.Layer_One[x + i][y + j] >= 64 && game.map.Layer_One[x + i][y + j] <= 111))
{
int xpos = game.get_pos(game.map.Layer_One[x + i][y + j].get(), ypos, true);
BitBlt(hdcmem, (i * 32) + 32, (j * 32) + 32, 32, 32, hbcmem, xpos + 96, ypos, SRCPAINT);
BitBlt(hdcmem, (i * 32) + 32, (j * 32) + 32, 32, 32, hbcmem, xpos, ypos, SRCAND);
} else {
int xpos = game.get_pos(game.map.Layer_One[x + i][y + j].get(), ypos, false);
BitBlt(hdcmem, (i * 32) + 32, (j * 32) + 32, 32, 32, hbcmem, xpos, ypos, SRCCOPY);
}
}
}
// If it isn't started, show title
if (!game.started)
{
HDC tmphdc = CreateCompatibleDC(hdcmem);
HDC tmp = CreateCompatibleDC(tmphdc);
RECT rc;
GetClientRect(hWnd, &rc);
string str = game.map.leveltitle.substr(0, game.map.leveltitle.length() - 1);
TCHAR* tch = new TCHAR[str.length()];
mbstowcs_s(NULL, tch, _tcslen(tch), str.c_str(), str.length());
HFONT font = CreateFont(25, 0, 0, 0, FW_BOLD, false, false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, NULL);
SelectObject(tmp, font);
DrawText(tmp, tch, str.length(), &rc, DT_CALCRECT);
rc.right += 16;
HBITMAP tmpbm = CreateCompatibleBitmap(hdcmem, rc.right, rc.bottom);
HBITMAP tmpold = (HBITMAP)SelectObject(tmphdc, tmpbm);
HBRUSH hbr = CreateSolidBrush(RGB(255, 255, 255));
HPEN pen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
SelectObject(hdcmem, pen);
SelectObject(hdcmem, hbr);
Rectangle(hdcmem, 176 - (rc.right / 2), 243, 177 + (rc.right / 2), 248);
hbr = CreateSolidBrush(RGB(128, 128, 128));
pen = CreatePen(PS_SOLID, 1, RGB(128, 128, 128));
SelectObject(hdcmem, pen);
SelectObject(hdcmem, hbr);
Rectangle(hdcmem, 176 - (rc.right / 2), 294, 177 + (rc.right / 2), 299);
HBITMAP left = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_LEFT));
hdcold = (HBITMAP)SelectObject(hbcmem, left);
BitBlt(hdcmem, 176 - (rc.right / 2) - 4, 243, 4, 56, hbcmem, 0, 0, SRCCOPY);
HBITMAP right = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_RIGHT));
hdcold = (HBITMAP)SelectObject(hbcmem, right);
BitBlt(hdcmem, 176 + (rc.right / 2) + ((rc.right % 2) != 0), 243, 4, 56, hbcmem, 0, 0, SRCCOPY);
SelectObject(tmphdc, font);
SetTextColor(tmphdc, RGB(255, 255, 0));
SetBkColor(tmphdc, RGB(0, 0, 0));
DrawText(tmphdc, tch, str.length(), &rc, DT_CENTER);
BITMAP structBitmapHeader;
memset( &structBitmapHeader, 0, sizeof(BITMAP) );
HGDIOBJ hBitmap = GetCurrentObject(tmphdc, OBJ_BITMAP);
GetObject(hBitmap, sizeof(BITMAP), &structBitmapHeader);
BitBlt(hdcmem, 176 - (rc.right / 2), 247, structBitmapHeader.bmWidth, structBitmapHeader.bmHeight, tmphdc, 0, 0, SRCCOPY);
DeleteDC(tmphdc);
DeleteDC(tmp);
}
// If paused
if (game.paused)
{
RECT rc;
rc.top = 32;
rc.left = 32;
rc.bottom = 330;
rc.right = 330;
BitBlt(hdcmem, 32, 32, 288, 288, NULL, 0, 0, BLACKNESS);
HFONT font = CreateFont(50, 0, 0, 0, FW_NORMAL, false, false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, NULL);
SelectObject(hdcmem, font);
SetTextColor(hdcmem, RGB(255, 0, 0));
SetBkColor(hdcmem, RGB(0, 0, 0));
DrawText(hdcmem, L"PAUSED", 6, &rc, (DT_CENTER + DT_SINGLELINE + DT_VCENTER));
}
nums = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_NUMBERS));
hdcold = (HBITMAP)SelectObject(hbcmem, nums);
for (int i = 100; i > 0; i /= 10) // coins and time left
{
int tmp;
if (i == 100)
tmp = game.coinsleft / 100;
if (i == 10)
tmp = ((game.coinsleft % 100) - (game.coinsleft % 10)) / 10;
if (i == 1)
tmp = game.coinsleft % 10;
if (game.coinsleft < i && i > 1)
tmp = 10;
int ypos = game.get_num_pos(tmp, (game.coinsleft == 0));
BitBlt(hdcmem, 417 + ((3 - (int)floor(log10((double)i)) * 17)), 215, 17, 23, hbcmem, 0, ypos, SRCCOPY);
if (i == 100)
tmp = game.timeleft / 100;
if (i == 10)
tmp = ((game.timeleft % 100) - (game.timeleft % 10)) / 10;
if (i == 1)
tmp = game.timeleft % 10;
if (game.timeleft < i && i > 1)
tmp = 10;
if (game.map.timelimit == 0)
tmp = 11;
ypos = game.get_num_pos(tmp, (game.timeleft < 16 || game.map.timelimit == 0));
BitBlt(hdcmem, 369 + ((3 - (int)floor(log10((double)i))) * 17), 125, 17, 23, hbcmem, 0, ypos, SRCCOPY);
}
if (game.onhint)
{
HBITMAP sidebg = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SIDEBG));
hdcold = (HBITMAP)SelectObject(hbcmem, sidebg);
BitBlt(hdcmem, 353, 165, 127, 146, hbcmem, 0, 0, SRCCOPY);
HFONT font = CreateFont(18, 0, 0, 0, FW_BOLD, true, false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, NULL);
SelectObject(hdcmem, font);
SetTextColor(hdcmem, RGB(0, 255, 255));
SetBkColor(hdcmem, RGB(0, 0, 0));
RECT rc;
rc.top = 168;
rc.left = 356;
rc.bottom = 308;
rc.right = 477;
string str = "Hint: " + game.map.hint;
TCHAR* tch = new TCHAR[str.length()];
mbstowcs_s(NULL, tch, _tcslen(tch), str.c_str(), str.length());
DrawText(hdcmem, tch, str.length(), &rc, DT_CENTER + DT_WORDBREAK);
} else {
hdcold = (HBITMAP)SelectObject(hbcmem, sprites); // LOWER SIDE INFO
if (game.player.key1 > 0)
BitBlt(hdcmem, 352, 247, 32, 32, hbcmem, 192, 160, SRCCOPY);
else BitBlt(hdcmem, 352, 247, 32, 32, hbcmem, 0, 0, SRCCOPY);
if (game.player.key2 > 0)
BitBlt(hdcmem, 384, 247, 32, 32, hbcmem, 192, 128, SRCCOPY);
else BitBlt(hdcmem, 384, 247, 32, 32, hbcmem, 0, 0, SRCCOPY);
if (game.player.key3 > 0)
BitBlt(hdcmem, 416, 247, 32, 32, hbcmem, 192, 224, SRCCOPY);
else BitBlt(hdcmem, 416, 247, 32, 32, hbcmem, 0, 0, SRCCOPY);
if (game.player.key4)
BitBlt(hdcmem, 448, 247, 32, 32, hbcmem, 192, 192, SRCCOPY);
else BitBlt(hdcmem, 448, 247, 32, 32, hbcmem, 0, 0, SRCCOPY);
if (game.player.mod1)
BitBlt(hdcmem, 352, 279, 32, 32, hbcmem, 192, 256, SRCCOPY);
else BitBlt(hdcmem, 352, 279, 32, 32, hbcmem, 0, 0, SRCCOPY);
if (game.player.mod2)
BitBlt(hdcmem, 384, 279, 32, 32, hbcmem, 192, 288, SRCCOPY);
else BitBlt(hdcmem, 384, 279, 32, 32, hbcmem, 0, 0, SRCCOPY);
if (game.player.mod3)
BitBlt(hdcmem, 416, 279, 32, 32, hbcmem, 192, 320, SRCCOPY);
else BitBlt(hdcmem, 416, 279, 32, 32, hbcmem, 0, 0, SRCCOPY);
if (game.player.mod4)
BitBlt(hdcmem, 448, 279, 32, 32, hbcmem, 192, 352, SRCCOPY);
else BitBlt(hdcmem, 448, 279, 32, 32, hbcmem, 0, 0, SRCCOPY);
}
BitBlt(hdc, 0, 0, 518, 401, hdcmem, 0, 0, SRCCOPY);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
SelectObject(hdc,hdcold);
DeleteDC(hdcmem);
DeleteDC(hbcmem);
ReleaseDC(hWnd, hdc);
DeleteObject(bg);
PostQuitMessage(0);
break;
また、構文、効率、および/またはコード内で物事を行うためのより良い方法について、誰かが提供できるアドバイス/批評にも本当に感謝しています。私はWin32にかなり慣れていません。