#include "Window.h" static LRESULT CALLBACK wndow_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_CREATE: { HDC hdc = GetDC(hwnd); bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bitmap_info.bmiHeader.biWidth = window_width; bitmap_info.bmiHeader.biHeight = -window_height; // Negative to flip the image bitmap_info.bmiHeader.biPlanes = 1; bitmap_info.bmiHeader.biBitCount = 32; // 32 bits per pixel (RGBA) bitmap_info.bmiHeader.biCompression = BI_RGB; bitmap = CreateDIBSection(hdc, &bitmap_info, DIB_RGB_COLORS, (void**)&pixel_buffer, NULL, 0); hdc_mem = CreateCompatibleDC(hdc); SelectObject(hdc_mem, bitmap); ReleaseDC(hwnd, hdc); return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); HDC hdc_mem = CreateCompatibleDC(hdc); HGDIOBJ old_bitmap = SelectObject(hdc_mem, bitmap); BitBlt(hdc, 0, 0, window_width, window_height, hdc_mem, 0, 0, SRCCOPY); SelectObject(hdc_mem, old_bitmap); DeleteDC(hdc_mem); EndPaint(hwnd, &ps); return 0; } case WM_DESTROY: { DeleteDC(hdc_mem); DeleteObject(bitmap); SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); PostQuitMessage(0); return 0; } default: return DefWindowProc(hwnd, msg, wparam, lparam); } } int window_create(const char* title, HINSTANCE hInst, const int width, const int height) { RECT rect = {0, 0, width, height}; AdjustWindowRect(&rect, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE); window_width = rect.right - rect.left; window_height = rect.bottom - rect.top; WNDCLASS wc = {0}; wc.lpfnWndProc = wndow_proc; wc.hInstance = hInst; wc.lpszClassName = title; wc.hCursor = LoadCursor(hInst, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); RegisterClass(&wc); int screen_width = GetSystemMetrics(SM_CXSCREEN); int screen_height = GetSystemMetrics(SM_CYSCREEN); int pos_x = (screen_width - window_width) / 2; int pos_y = (screen_height - window_height) / 2; hwnd = CreateWindowEx(0, title, title, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, pos_x, pos_y, window_width, window_height, NULL, NULL, wc.hInstance, NULL); if (!hwnd) { return -1; } ShowWindow(hwnd, SW_SHOW); return 0; } void window_update_pixels(const vec4s color, const int pixel_x, const int pixel_y) { int pixel_index = (pixel_y * window_width + pixel_x) * 4; // NOTE: The pixel buffer is in BGRA format, so we need to swap the channels pixel_buffer[pixel_index] = COLOR_CLAMP(color.z * 255.0f); pixel_buffer[pixel_index + 1] = COLOR_CLAMP(color.y * 255.0f); pixel_buffer[pixel_index + 2] = COLOR_CLAMP(color.x * 255.0f); pixel_buffer[pixel_index + 3] = COLOR_CLAMP(color.w * 255.0f); } void window_refresh_region(const int pixel_x, const int pixel_y, const int region_width, const int region_height) { HDC hdc = GetDC(hwnd); BitBlt(hdc, pixel_x, pixel_y, region_width, region_height, hdc_mem, pixel_x, pixel_y, SRCCOPY); ReleaseDC(hwnd, hdc); }