【发布时间】:2020-02-02 07:42:20
【问题描述】:
我一直在用 Visual C++ 处理位图和渲染,遇到了一个奇怪的问题。
我正在尝试在用户调整窗口大小时调整绘图区域的大小。现在,不仅扩大窗口不会扩大可见的绘图区域(白色边框出现在原始窗口边界之外),而且改变窗口大小似乎弄乱了我的位图。
这是游戏在启动时的样子:
更改窗口的宽度或高度后,紫色字符现在已被橙色字符替换。
最后,三个都变成蓝色了。
如果我继续下去,所有的字符都会被绿草背景位图覆盖。
位图的渲染顺序似乎与此相反。添加第二行字符确认这在渲染代码中没有问题 - 内存中的实际位图正在以某种方式发生变化。删除调整大小代码会导致位图错误停止重现。
当我尝试重新初始化设备上下文时,我的调整大小代码几乎可以肯定是一个错误,但我不确定它是什么。
这是相关的设置代码:
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() 的主循环:
while (!Exit)
{
while (PeekMessage (&msg, nullptr, 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
}
Render ();
}
调整大小的回调函数:
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()实际渲染:
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);
}
【问题讨论】:
-
好久没用windows API了,难道你不需要把原来的句柄恢复到
hdc_temp吗?例如:Render() { HGDIOBJ h = SelectObject (hdc_temp, background_bitmap); /*existing code*/ SelectObject(hdc_temp, h); }
标签: c++ bitmap resize window gdi