调整窗口大小会导致位图被覆盖 我一直在用VisualC++中的位图和渲染来解决问题,并遇到了一个奇怪的问题。

调整窗口大小会导致位图被覆盖 我一直在用VisualC++中的位图和渲染来解决问题,并遇到了一个奇怪的问题。,c++,bitmap,resize,window,gdi,C++,Bitmap,Resize,Window,Gdi,我试图让绘图区域在用户调整窗口大小时调整大小。现在,不仅扩大窗口不会扩大可见的绘图区域(白色边框出现在原始窗口边界之外),而且更改窗口大小似乎会弄乱我的位图 以下是游戏启动时的样子: 更改窗口的宽度或高度后,紫色字符现在已替换为橙色字符 最后,这三种颜色都变蓝了 如果继续,所有字符都将被绿草背景位图覆盖 这似乎与位图的渲染顺序相反。添加第二行字符确认渲染代码中没有问题-内存中的实际位图正在以某种方式更改。删除调整大小代码会导致位图错误停止重新编程 当我尝试重新初始化设备上下文时,几乎可以

我试图让绘图区域在用户调整窗口大小时调整大小。现在,不仅扩大窗口不会扩大可见的绘图区域(白色边框出现在原始窗口边界之外),而且更改窗口大小似乎会弄乱我的位图

以下是游戏启动时的样子:

更改窗口的宽度或高度后,紫色字符现在已替换为橙色字符

最后,这三种颜色都变蓝了

如果继续,所有字符都将被绿草背景位图覆盖

这似乎与位图的渲染顺序相反。添加第二行字符确认渲染代码中没有问题-内存中的实际位图正在以某种方式更改。删除调整大小代码会导致位图错误停止重新编程

当我尝试重新初始化设备上下文时,几乎可以肯定我的调整大小代码中存在错误,但我不确定这是什么

以下是相关的设置代码:

HBITMAP player_blue = (HBITMAP) LoadImage (NULL, L"Images/test_player_blue.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HBITMAP player_orange = (HBITMAP) LoadImage (NULL, L"Images/test_player_orange.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HBITMAP player_purple = (HBITMAP) LoadImage (NULL, L"Images/test_player_purple.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HBITMAP background_bitmap = (HBITMAP) LoadImage (NULL, L"Images/test_background.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

  HDC hdc = GetDC (Window);
  HDC hdc_temp = CreateCompatibleDC (hdc);
  HBITMAP bitmap_buffer = CreateCompatibleBitmap (hdc, resize.screen_width, resize.screen_height);
  SelectObject (hdc, bitmap_buffer);
wWinMain()中的主循环:

完成大小调整的回调函数:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
  switch (message)
    {
    case WM_SIZE:

      RECT window_rect;
      if (GetWindowRect (Window, &window_rect))
        {
        hdc = GetDC (Window);
        hdc_temp = CreateCompatibleDC (hdc);
        bitmap_buffer = CreateCompatibleBitmap (hdc, resize.screen_width, resize.screen_height);
        SelectObject (hdc, bitmap_buffer);

        screen_width = window_rect.right - window_rect.left;
        screen_height = window_rect.bottom - window_rect.top;
        }
      break;

    default:
      return DefWindowProc(hWnd, message, wParam, lParam);
    }
  return 0;
  }
通过BitBlt()进行的实际渲染:


正如Ken评论的那样,您正在泄漏宝贵的GDI资源。再调整几次大小,您的窗口可能会变成黑色:)

请参阅:

当您不再需要内存DC时,调用DeleteDC函数。
您可能不需要在每次调整大小时创建该DC


CreateCompatibleBitmap

也是如此。我已经很久没有使用Windows API了,但是您不需要将原始句柄还原为
hdc\u temp
?例如:
Render(){HGDIOBJ h=SelectObject(hdc_temp,background_bitmap);/*现有代码*/SelectObject(hdc_temp,h);}
谢谢-看起来这就是罪魁祸首。关于如何正确调整绘图区域的大小有什么见解吗?@噩梦-这取决于你想做什么:只是调整背景大小,或者缩放你的游戏碎片?无论如何,在处理
WM_SIZE
消息时,您只需像以前一样获取新的大小(可能需要准备DC)。确保在将新的GDI资源分配给现有句柄时,首先清除以前的内容。还请注意,您不能删除当前选择到任何DC中的资源,因此最佳做法是(正如Ken评论的那样)在退出
Render()
时保存以前选择的对象。另一种选择是使用
SaveDC()
RestoreDC()
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
  switch (message)
    {
    case WM_SIZE:

      RECT window_rect;
      if (GetWindowRect (Window, &window_rect))
        {
        hdc = GetDC (Window);
        hdc_temp = CreateCompatibleDC (hdc);
        bitmap_buffer = CreateCompatibleBitmap (hdc, resize.screen_width, resize.screen_height);
        SelectObject (hdc, bitmap_buffer);

        screen_width = window_rect.right - window_rect.left;
        screen_height = window_rect.bottom - window_rect.top;
        }
      break;

    default:
      return DefWindowProc(hWnd, message, wParam, lParam);
    }
  return 0;
  }
void Render ()
  {
  SelectObject (hdc_temp, background_bitmap);
  BitBlt (hdc, 0, 0, 800, 600, hdc_temp, 0, 0, SRCCOPY);

  SelectObject (hdc_temp, player_blue);
  BitBlt (hdc, 0, 0, 126, 126, hdc_temp, 0, 0, SRCCOPY);
  SelectObject (hdc_temp, player_orange);
  BitBlt (hdc, 126, 0, 126, 126, hdc_temp, 0, 0, SRCCOPY);
  SelectObject (hdc_temp, player_purple);
  BitBlt (hdc, 252, 0, 126, 126, hdc_temp, 0, 0, SRCCOPY);
  }