Reputation: 43
I created a window and made a rectangle on it. When i minimize my window the program crashes. I'm aware it's because when i minimize the buffer that the function used to create the rectangle is accessing memory outside of the buffer and that's why it keeps crashing.
So i tried to use a clamp function called limit() to keep the limits inside of the buffer. But no matter what i try it still crashes when i minimize the window. I copied my code below, i think the main problems are from somewhere in the limit() and draw_rect() function. When i don't run the draw_rect() function and just have the render_background(), my window works fine and doesn't collapse when minimized.
#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;
}
Upvotes: 0
Views: 165
Reputation: 18297
when you minimize, GetClientRect
returns {0,0,0,0}
, which has a size of 0, and allocating a buffer of zero size fails and returns a nullptr
if you check GetClientRect remarks.
In conformance with conventions for the RECT structure, the bottom-right coordinates of the returned rectangle are exclusive. In other words, the pixel at (right, bottom) lies immediately outside the rectangle.
almost all drawing and coordinates in windows API assumes end is exclusive, you should follow this convention in your code to avoid similar bugs, therefore the following code is wrong
for (int y = y0; y <= y1; y++)
and should be
for (int y = y0; y < y1; y++)
which will correctly not try to write to a zero sized buffer.
Upvotes: 1