2013-01-03 81 views
0

我有一個函數,其中一堆東西被繪製到屏幕外緩衝區。在函數結束時,它調用InvalidateRect。出於某種原因,有時它會在函數的中途重繪,導致閃爍。以下是該功能的代碼:Win32混淆閃爍

// 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.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.Layer_Two[x + i][y + j] != 0) 
     { 
      int xpos = game.get_pos(game.Layer_Two[x + i][y + j], 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.Layer_Two[x + i][y + j] != 0 && game.Layer_One[x + i][y + j] >= 64 && game.Layer_One[x + i][y + j] <= 111)) 
     { 
      int xpos = game.get_pos(game.Layer_One[x + i][y + j], 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.Layer_One[x + i][y + j], 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.leveltitle.substr(0, game.leveltitle.length() - 1) + "\nPassword: " + game.password; 
    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) + 1, 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); 
} 

// 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 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, 369 + ((3 - 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.timelimit == 0) 
     tmp = 11; 
    ypos = game.get_num_pos(tmp, (game.timeleft < 16 || game.timelimit == 0)); 
    BitBlt(hdcmem, 369 + ((3 - 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); 
} else { 
    hdcold = (HBITMAP)SelectObject(hbcmem, sprites);    // LOWER SIDE INFO 
    if (game.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.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.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.key4) 
     BitBlt(hdcmem, 448, 247, 32, 32, hbcmem, 192, 192, SRCCOPY); 
    else BitBlt(hdcmem, 448, 247, 32, 32, hbcmem, 0, 0, SRCCOPY); 
    if (game.water) 
     BitBlt(hdcmem, 352, 279, 32, 32, hbcmem, 192, 256, SRCCOPY); 
    else BitBlt(hdcmem, 352, 279, 32, 32, hbcmem, 0, 0, SRCCOPY); 
    if (game.fire) 
     BitBlt(hdcmem, 384, 279, 32, 32, hbcmem, 192, 288, SRCCOPY); 
    else BitBlt(hdcmem, 384, 279, 32, 32, hbcmem, 0, 0, SRCCOPY); 
    if (game.ice) 
     BitBlt(hdcmem, 416, 279, 32, 32, hbcmem, 192, 320, SRCCOPY); 
    else BitBlt(hdcmem, 416, 279, 32, 32, hbcmem, 0, 0, SRCCOPY); 
    if (game.suction) 
     BitBlt(hdcmem, 448, 279, 32, 32, hbcmem, 192, 352, SRCCOPY); 
    else BitBlt(hdcmem, 448, 279, 32, 32, hbcmem, 0, 0, SRCCOPY); 
} 

RECT rc; 
rc.left = 0; 
rc.top = 0; 
rc.right = 518; 
rc.bottom = 401; 
InvalidateRect(hWnd, &rc, false); 

什麼導致閃爍?

回答

2
  1. 確保您處理WM_ERASEBKGND消息並返回TRUE,這將防止窗口基類繪製背景。

  2. 而不是在您的繪圖程序結束時調用InvalidateRect,將您的繪圖代碼放入WM_PAINT消息處理程序中,這可確保您的繪圖代碼在窗口重新繪製時被調用。

+0

我試過這兩種。它仍然隨機閃爍。 –

+1

是否有可能在DrawLevelNumber中的某處觸發繪畫? – RichardBrock

+0

就是這樣。我有像BitBlt(hdc,0,0,518,401,hdcmem,0,0,SRCCOPY);在DrawLevelNumber中。謝謝! –