我创建了一个窗口并在其上制作了一个矩形。当我最小化窗口时,程序崩溃了。我知道这是因为当我最小化缓冲区时,用于创建矩形的函数正在访问缓冲区外部的内存,这就是它不断崩溃的原因。
所以我尝试使用名为 limit() 的钳位函数来将限制保留在缓冲区内。但无论我如何尝试,当我最小化窗口时它仍然会崩溃。我复制了下面的代码,我认为主要问题来自 limit() 和 draw_rect() 函数中的某个地方。当我不运行draw_rect()函数而只运行render_background()时,我的窗口工作正常并且最小化时不会崩溃。
#include <windows.h>
#include <Memoryapi.h>
#include <stdio.h>
#pragma comment(lib, "Gdi32.lib")
#pragma comment(lib, "onecore.lib")
//global variables
bool run = true;
int width, height, buffer_memory_size;
void *memory;
BITMAPINFO BMINFO;
//function used to color background
void render_background()
{
unsigned int *ptr = (unsigned int *)memory;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
*ptr = 0xff5500;
ptr++;
}
}
}
//function used to keep draw_rect inside buffer
void draw_rect(int x0, int y0, int x1, int y1, unsigned int color)
{
for (int y = limit(0,height - 1,y0); y <= limit(0,height - 1,y1); y++)
{
unsigned int *ptr = (unsigned int *)memory + y * width;
for (int x = limit(0,width - 1,x0); x <= limit(0,width - 1,x1); x++)
{
ptr[x] = color;
}
}
}
//function used to draw rectangle
void draw_rect(int x0, int y0, int x1, int y1, unsigned int color)
{
for (int y = limit(0,height - 1,y0); y <= limit(0,height - 1,y1); y++)
{
unsigned int *ptr = (unsigned int *)memory + y * width;
for (int x = limit(0,width - 1,x0); x <= limit(0,width - 1,x1); x++)
{
ptr[x] = color;
}
}
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
run = false;
return 0;
case WM_SIZE:
//obtain the new size of the window and the memory size of new needed buffer
RECT R;
GetClientRect(hwnd,&R);
width = R.right - R.left;
height = R.bottom - R.top;
buffer_memory_size = width*height*sizeof(unsigned int); //buffer memory size in terms of bytes
//allocate memory in the heap for new buffer
if (memory != NULL)
{
VirtualFree(memory,0,MEM_RELEASE);
}
memory = VirtualAlloc(0, buffer_memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//update BMINFO with updated class members
BMINFO.bmiHeader.biSize = sizeof(BMINFO.bmiHeader);
BMINFO.bmiHeader.biWidth = width;
BMINFO.bmiHeader.biHeight = height;
BMINFO.bmiHeader.biPlanes = 1;
BMINFO.bmiHeader.biBitCount = 32;
BMINFO.bmiHeader.biCompression = BI_RGB;
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
//create window class
const wchar_t name[] = L"window class";
WNDCLASS wc = {};
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpszClassName = name;
wc.lpfnWndProc = MainWndProc;
//register window class
RegisterClass(&wc);
//create window and display window
HWND H = CreateWindowExW(0, name, L"First Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 1280, 720, 0, 0, hInstance, 0);
HDC hdc = GetDC(H);
//game loop
while (run)
{
MSG msg;
//input
while (PeekMessage(&msg, H, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//logic
render_background();
//drawing rectangle x0 = 400, x1 = 700, y0 = 300, y1 = 500
draw_rect(400,300,700,500,0xff00ff);
//rendering
StretchDIBits(hdc,0,0,width,height,0,0,width,height,memory,&BMINFO,DIB_RGB_COLORS,SRCCOPY);
}
return 0;
}
最小化时,
GetClientRect
返回{0,0,0,0}
,其大小为0,分配零大小的缓冲区失败并返回nullptr
如果您勾选了GetClientRect备注。
为了符合 RECT 结构的约定,返回的矩形的右下坐标是不包括的。换句话说,(右、下)处的像素紧邻矩形外部。
换句话说,Windows API 中几乎所有的绘图和坐标都假定 end 是互斥的,您应该在代码中遵循此约定以避免类似的错误,因此以下代码是错误的
for (int y = y0; y <= y1; y++)
并且应该是
for (int y = y0; y < y1; y++)