为什么绘制正方形时窗口不更新?



当我尝试绘制矩形时,程序窗口不会更新。这不是程序没有响应,因为我仍然可以绘制背景,但矩形不会更新,我不知道该改变什么。没有弹出错误,唯一的警告是:

警告C28251 'WinMain'的注释不一致:此实例没有注释。

这个程序在两个.cpp文件中,第一个没有创建一个窗口(确保在属性中设置),第二个创建了一个窗口。

注:第一个.cpp文件称为render.cpp,并包含在第二个文件中。

下面是调试代码:
#include <Windows.h>
struct Render_State
{
int width;
int hight;
void* memory;
BITMAPINFO bitmap_info;
};
Render_State render_state;
void render_backround(HWND hwnd, int colour)
{
if (WM_PAINT)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
unsigned int* pixel = (unsigned int*)render_state.memory;
for (int y = 0; y < render_state.hight; y += 1)
{
for (int x = 0; x < render_state.width; x += 1)
{
*pixel++ = colour;
}
}
// render
StretchDIBits(hdc, 0, 0, render_state.width, render_state.hight, 0, 0,
render_state.width,
render_state.hight,
render_state.memory, &render_state.bitmap_info, DIB_RGB_COLORS, SRCCOPY); {}
EndPaint(hwnd, &ps);
}
}
void clear_screen(HWND hwnd, int colour)
{
if (WM_PAINT)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
unsigned int* pixel = (unsigned int*)render_state.memory;
for (int y = 0; y < render_state.hight; y += 1)
{
for (int x = 0; x < render_state.width; x += 1)
{
*pixel++ = colour;
}
}
// render
StretchDIBits(hdc, 0, 0, render_state.width, render_state.hight, 0, 0, render_state.width,
render_state.hight,
render_state.memory, &render_state.bitmap_info, DIB_RGB_COLORS, SRCCOPY); {}
EndPaint(hwnd, &ps);
}
}
void draw_rect(HWND hwnd, int X, int Y, int X2, int Y2, int colour)
{
if (WM_PAINT)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
for (int y = Y; y < Y2; y++)
{
//  unsigned int* pixel = (unsigned int*)render_state.memory;
size_t pixel = size_t(render_state.memory) + static_cast<size_t>(X) + static_cast<size_t> (y) * static_cast<size_t> (render_state.width);
for (int x = X; x < X2; x++)
{
pixel += 0xf5500;
}
}
// render
StretchDIBits(hdc, X, Y, X2, Y2, X, Y, render_state.width, render_state.hight,
render_state.memory, &render_state.bitmap_info, DIB_RGB_COLORS, SRCCOPY); {}
EndPaint(hwnd, &ps);
}
}
#include <Windows.h>
bool running = true;
#include "renderer.cpp"
LRESULT CALLBACK windows_callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
switch (uMsg)
{
case WM_CLOSE:
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
case WM_SIZE:
{
RECT rect;
GetClientRect(hwnd, &rect);
render_state.width = rect.right - rect.left;
render_state.hight = rect.bottom - rect.top;
int size = render_state.width * render_state.hight * sizeof(unsigned int);
if (render_state.memory) VirtualFree(render_state.memory, 0, MEM_RELEASE);
render_state.memory = VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
render_state.bitmap_info.bmiHeader.biSize = sizeof(render_state.bitmap_info.bmiHeader);
render_state.bitmap_info.bmiHeader.biWidth = render_state.width;
render_state.bitmap_info.bmiHeader.biHeight = render_state.hight;
render_state.bitmap_info.bmiHeader.biPlanes = 1;
render_state.bitmap_info.bmiHeader.biBitCount = 32;
render_state.bitmap_info.bmiHeader.biCompression = BI_RGB;
//render_backround(hwnd, 0xf2000);
//clear_screen(hwnd, 0xff5500);
draw_rect(hwnd, 3, 5, 50, 50, 0xff5500);
}
break;
default:
{
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
return result;
}
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
//compile window
CHAR clsName[] = "test";
WNDCLASSA window_class = {};
window_class.style = CS_HREDRAW | CS_VREDRAW;
window_class.lpszClassName = clsName;
window_class.lpfnWndProc = windows_callback;
//register clases
ATOM atom = RegisterClassA(&window_class);
if (0 == atom)
{
DWORD err = GetLastError();
return 1;
}
// create window
HWND window = CreateWindow(clsName, "game", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT,
CW_USEDEFAULT, 720, 360, 0, 0, hInstance, 0);
if (NULL == window)
{
DWORD err = GetLastError();
return 1;
}
MSG message;
HDC hdc = GetDC(window);
// Main message loop:
while (GetMessage(&message, nullptr, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
//simulate
//render
StretchDIBits(hdc, 0, 0, render_state.width, render_state.hight, 0, 0, render_state.width,
render_state.hight,
render_state.memory, &render_state.bitmap_info, DIB_RGB_COLORS, SRCCOPY); {}
}

draw_rect函数中,pixel为无符号整型。

for (int x = X; x < X2; ++x)
{
pixel += 0xf5500;
}

pixel += 0xf5500只会增加pixel的大小,因为pixel不是地址。

这就是为什么不能画正方形的原因=>render_state.memory没有颜色数据

您需要将pixel声明为指针变量。正如您在render_backround函数中声明的那样。

size_t* pixel = (size_t*)render_state.memory;
for (int y = 0; y < Y2; y += 1)
{
for (int x = 0; x < X2; x += 1)
{
*pixel++ = colour;
}
}   

整个draw_rect代码,

void draw_rect(HWND hwnd, int X, int Y, int X2, int Y2, int colour)
{
if (WM_PAINT)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

size_t* pixel = (size_t*)render_state.memory;
for (int y = 0; y < Y2; y += 1)
{
for (int x = 0; x < X2; x += 1)
{
*pixel++ = colour;
}
}     
render_state.bitmap_info.bmiHeader.biWidth = X2;
render_state.bitmap_info.bmiHeader.biHeight = Y2;
StretchDIBits(hdc, X, Y, X2, Y2, X, Y, X2, Y2,
render_state.memory, &render_state.bitmap_info, DIB_RGB_COLORS, SRCCOPY);
EndPaint(hwnd, &ps);
}
}

注意:只负责您当前的代码示例。如评论部分所述,您可以重新阅读win32窗口的绘图,特别是WindowProc回调函数。

如评论中所述,问题是您根本没有在windows_callback()中处理WM_PAINT消息。您需要做这样的事情:

renderer.h

#ifndef renderer_H
#define renderer_H
#include <Windows.h>
struct Render_State
{
int width;
int hight;
void* memory;
BITMAPINFO bitmap_info;
};
void render_background(HDC hdc, Render_State &state, int colour);
void clear_screen(HDC hdc, Render_State &state, int colour);
void draw_rect(HDC hdc, Render_State &state, int X, int Y, int X2, int Y2, int colour);
#endif

renderer.cpp

#include "renderer.h"
void render_background(HDC hdc, Render_State &state, int colour)
{
unsigned int* pixel = static_cast<unsigned int*>(state.memory);
for (int y = 0; y < state.hight; ++y)
{
for (int x = 0; x < state.width; ++x)
{
*pixel++ = colour;
}
}
// render
StretchDIBits(hdc,
0, 0, state.width, state.hight,
0, 0, state.width, state.hight,
state.memory, &state.bitmap_info,
DIB_RGB_COLORS, SRCCOPY);
} 
void clear_screen(HDC hdc, Render_State &state, int colour)
{
render_background(hdc, state, colour);
}
void draw_rect(HDC hdc, Render_State &state, int X, int Y, int X2, int Y2, int colour)
{
for (int y = Y; y < Y2; ++y)
{
//  unsigned int* pixel = static_cast<unsigned int*>(state.memory);
size_t pixel = size_t(state.memory) + static_cast<size_t>(X) + static_cast<size_t>(y) * static_cast<size_t>(state.width);

for (int x = X; x < X2; ++x)
{
pixel += 0xf5500;
}
}
// render
StretchDIBits(hdc,
X, Y, X2, Y2,
X, Y, state.width, state.hight,
state.memory, &state.bitmap_info,
DIB_RGB_COLORS, SRCCOPY);
}
#include <Windows.h>
#include "renderer.h"
bool running = true;
Render_State render_state = {};
LRESULT CALLBACK windows_callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;

case WM_SIZE:
{
RECT rect;
GetClientRect(hwnd, &rect);
render_state.width = rect.right - rect.left;
render_state.hight = rect.bottom - rect.top;
int size = render_state.width * render_state.hight * sizeof(unsigned int);
if (render_state.memory) VirtualFree(render_state.memory, 0, MEM_RELEASE);
render_state.memory = VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
render_state.bitmap_info.bmiHeader.biSize = sizeof(render_state.bitmap_info.bmiHeader);
render_state.bitmap_info.bmiHeader.biWidth = render_state.width;
render_state. bitmap_info.bmiHeader.biHeight = render_state.hight;
render_state. bitmap_info.bmiHeader.biPlanes = 1;
render_state. bitmap_info.bmiHeader.biBitCount = 32;
render_state .bitmap_info.bmiHeader.biCompression = BI_RGB;
InvalidateRect(hwnd, NULL, TRUE);
return 0;
}

case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// render_background(hdc, render_state, white);
// clear_screen(hdc, render_state, 0xff5500);
draw_rect(hdc, render_state, 30, 50, 500, 500, 0xff5500);
EndPaint(hwnd, &ps);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
//compile window
CHAR clsName[] = "test";
WNDCLASSA window_class = {};
window_class.style = CS_HREDRAW | CS_VREDRAW;
window_class.lpszClassName = clsName;
window_class.lpfnWndProc = windows_callback;
//register class
if (!RegisterClassA(&window_class))
{
DWORD err = GetLastError();
return 1;
}
// create window
HWND window = CreateWindow(clsName, "game", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, 
CW_USEDEFAULT, 720, 360, 0, 0, hInstance, 0);
if (!window)
{
DWORD err = GetLastError();
return 1;
}
// Main message loop:
MSG message;
while (GetMessage(&message, nullptr, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return 0;
}

最新更新