Win32 - Drawing Pixels (C)
How to draw a pixel using Windows API
Updated Jun 20, 2023
// cl main.c
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdint.h>
#define Assert(c) do { if (!(c)) __debugbreak(); } while (0)
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "gdi32.lib")
typedef uint32_t u32;
int ClientWidth;
int ClientHeight;
void *Memory;
void DrawPixel(int X, int Y, u32 Color) {
u32 *Pixel = (u32 *)Memory;
Pixel += Y * ClientWidth + X;
*Pixel = Color;
}
void ClearScreen(u32 Color) {
u32 *Pixel = (u32 *)Memory;
for(int Index = 0; Index < ClientWidth * ClientHeight; ++Index) {
*Pixel++ = Color;
}
}
LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam) {
switch(Message) {
case WM_DESTROY: {
PostQuitMessage(0);
} break;
case WM_KEYDOWN: {
switch(WParam) {
case 'O': {
DestroyWindow(Window);
} break;
}
} break;
default: {
return DefWindowProcW(Window, Message, WParam, LParam);
}
}
return 0;
}
int WINAPI WinMain(HINSTANCE Instance, HINSTANCE PrevInstance, LPSTR Cmd, int CmdShow) {
// Create a window.
WNDCLASSW WindowClass = {
.lpszClassName = L"MyWindowClass",
.lpfnWndProc = WindowProc,
.hInstance = Instance,
.hCursor = LoadCursor(NULL, IDC_CROSS),
};
ATOM Atom = RegisterClassW(&WindowClass);
Assert(Atom && "Failed to register a window");
HWND Window = CreateWindowW(WindowClass.lpszClassName, L"Drawing Pixels", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, Instance, NULL);
Assert(Window && "Failed to create a window");
ShowWindow(Window, CmdShow);
// Allocate memory.
RECT Rect;
GetClientRect(Window, &Rect);
ClientWidth = Rect.right - Rect.left;
ClientHeight = Rect.bottom - Rect.top;
Memory = VirtualAlloc(0, ClientWidth * ClientHeight * 4, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
// Create BITMAPINFO struct for StretchDIBits().
BITMAPINFO BitmapInfo;
BitmapInfo.bmiHeader.biSize = sizeof(BitmapInfo.bmiHeader);
BitmapInfo.bmiHeader.biWidth = ClientWidth;
// Negative biHeight makes top left as the coordinate system origin. Otherwise it's bottom left.
BitmapInfo.bmiHeader.biHeight = -ClientHeight;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 32;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
HDC DeviceContext = GetDC(Window);
for(;;) {
MSG Message;
if(PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
if(Message.message == WM_QUIT) break;
TranslateMessage(&Message);
DispatchMessage(&Message);
continue;
}
// Clear screen.
ClearScreen(0x333333);
// Draw white pixel at 100, 100 (from top left).
DrawPixel(100, 100, 0xffffff);
// Display image.
StretchDIBits(DeviceContext, 0, 0, ClientWidth, ClientHeight, 0, 0, ClientWidth, ClientHeight, Memory, &BitmapInfo, DIB_RGB_COLORS, SRCCOPY);
}
return 0;
}
Inspired by: https://handmadehero.org/
Check this if you want to use Direct3D 11 to display software drawn pixels: https://gist.github.com/mmozeiko/6f36f2b82204b70a9b7fe6c05ccd868f