C and C++ Windows programming quick reference from message boxes and basic windows to multi-threading, file I/O, custom drawing, and COM basics.
📦 1. Including the Header
Section titled “📦 1. Including the Header”#include <windows.h> // Main Win32 API header — includes everything#include <stdio.h> // Standard I/O (optional but useful)🟢 BEGINNER
Section titled “🟢 BEGINNER”2. Hello World Message Box
Section titled “2. Hello World Message Box”#include <windows.h>
int main() { // MessageBoxA = ASCII version, MessageBoxW = Wide (Unicode) // Args: (parent window, message, title, buttons/icon flags) MessageBoxA(NULL, "Hello, World!", "My First Window", MB_OK | MB_ICONINFORMATION); return 0;}3. Common Data Types
Section titled “3. Common Data Types”// Win32 defines its own types — always prefer these in Win32 codeBOOL flag = TRUE; // Basically int (TRUE=1, FALSE=0)DWORD val = 0xFFFFFFFF; // Unsigned 32-bit integerWORD small = 0xFFFF; // Unsigned 16-bit integerBYTE b = 0xFF; // Unsigned 8-bit integerHANDLE h = NULL; // Generic opaque object handleHWND hwnd = NULL; // Handle to a WindowHINSTANCE hInst = NULL; // Handle to a module/instanceLPSTR str = "hello"; // Long Pointer to char (ASCII string)LPCSTR cstr = "const"; // Long Pointer to const charLPWSTR wstr = L"wide"; // Long Pointer to wide char (Unicode)4. String Operations (Win32 Style)
Section titled “4. String Operations (Win32 Style)”TCHAR buf[256];
// lstrlen — length of a Win32 stringint len = lstrlen(TEXT("Hello")); // TEXT() macro handles A/W automatically
// lstrcpy — copy a stringlstrcpy(buf, TEXT("Hello Win32"));
// lstrcmp — compare strings (0 = equal)if (lstrcmp(buf, TEXT("Hello Win32")) == 0) { // Strings are equal}
// wsprintf — safe sprintf for Win32 (no floats)wsprintf(buf, TEXT("Value: %d"), 42);5. Getting Last Error
Section titled “5. Getting Last Error”HANDLE h = CreateFile(TEXT("missing.txt"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); // Retrieve the last Win32 error code // Common codes: 2 = FILE_NOT_FOUND, 5 = ACCESS_DENIED printf("Error: %lu\\n", err);}6. Console Output
Section titled “6. Console Output”// Attach or allocate a console windowAllocConsole(); // Creates a new console for the process
// Write to console via standard handleHANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // Get stdout handleDWORD written;WriteConsole(hOut, TEXT("Hello Console\\n"), 14, &written, NULL);🟡 INTERMEDIATE
Section titled “🟡 INTERMEDIATE”7. Creating a Basic Window (WinMain)
Section titled “7. Creating a Basic Window (WinMain)”#include <windows.h>
// Window Procedure — handles messages sent to the windowLRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); // Signal the message loop to exit break; default: return DefWindowProc(hwnd, msg, wParam, lParam); // Default handling } return 0;}
// Entry point for GUI apps (instead of main)int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmd, int nShow) { // Step 1: Register the window class WNDCLASS wc = {0}; wc.lpfnWndProc = WndProc; // Assign our message handler wc.hInstance = hInstance; wc.lpszClassName = TEXT("MyWindow"); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // White background wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Standard arrow cursor RegisterClass(&wc);
// Step 2: Create the window HWND hwnd = CreateWindow( TEXT("MyWindow"), // Class name (must match RegisterClass) TEXT("My App"), // Window title WS_OVERLAPPEDWINDOW, // Style flags (title bar, borders, etc.) 100, 100, // X, Y position 800, 600, // Width, Height NULL, NULL, hInstance, NULL );
ShowWindow(hwnd, nShow); // Make it visible UpdateWindow(hwnd); // Force a WM_PAINT
// Step 3: Message loop — keeps app alive and processes events MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); // Translate virtual keys to WM_CHAR DispatchMessage(&msg); // Send message to WndProc } return (int)msg.wParam;}8. Handling Common Messages
Section titled “8. Handling Common Messages”LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: // Called once when the window is first created — good for init break;
case WM_PAINT: { // Called when window needs to be redrawn PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // Get device context for painting TextOut(hdc, 10, 10, TEXT("Hello from WM_PAINT"), 19); EndPaint(hwnd, &ps); // Always pair with BeginPaint break; }
case WM_KEYDOWN: // wParam holds the virtual key code (e.g., VK_ESCAPE, VK_RETURN) if (wParam == VK_ESCAPE) PostQuitMessage(0); break;
case WM_LBUTTONDOWN: // Mouse left button clicked // LOWORD(lParam) = X, HIWORD(lParam) = Y MessageBox(hwnd, TEXT("Clicked!"), TEXT("Mouse"), MB_OK); break;
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0;}9. Controls (Button, Edit, Static)
Section titled “9. Controls (Button, Edit, Static)”// Create controls inside WM_CREATE using CreateWindowcase WM_CREATE: { // Button control CreateWindow(TEXT("BUTTON"), TEXT("Click Me"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 50, 50, 120, 30, // x, y, width, height hwnd, (HMENU)1, // Parent, control ID hInstance, NULL);
// Single-line text input CreateWindow(TEXT("EDIT"), TEXT(""), WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 50, 100, 200, 25, hwnd, (HMENU)2, hInstance, NULL);
// Static label CreateWindow(TEXT("STATIC"), TEXT("Enter text:"), WS_VISIBLE | WS_CHILD, 50, 80, 100, 20, hwnd, (HMENU)3, hInstance, NULL); break;}
// Handle button click via WM_COMMANDcase WM_COMMAND: if (LOWORD(wParam) == 1) { // Control ID 1 = Button // BN_CLICKED is in HIWORD(wParam), but for buttons just match ID TCHAR buf[256]; GetDlgItemText(hwnd, 2, buf, 256); // Read text from edit control ID 2 MessageBox(hwnd, buf, TEXT("You typed:"), MB_OK); } break;10. File I/O (Win32 Style)
Section titled “10. File I/O (Win32 Style)”// --- Write to a file ---HANDLE hFile = CreateFile( TEXT("output.txt"), // Filename GENERIC_WRITE, // Access mode 0, // No sharing NULL, // Default security CREATE_ALWAYS, // Overwrite if exists FILE_ATTRIBUTE_NORMAL, // Normal file NULL);
if (hFile != INVALID_HANDLE_VALUE) { const char* data = "Hello File!"; DWORD written; WriteFile(hFile, data, lstrlenA(data), &written, NULL); CloseHandle(hFile); // Always close handles when done}
// --- Read from a file ---hFile = CreateFile(TEXT("output.txt"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) { char buf[256] = {0}; DWORD bytesRead; ReadFile(hFile, buf, sizeof(buf) - 1, &bytesRead, NULL); printf("Read: %s\\n", buf); CloseHandle(hFile);}11. Timers
Section titled “11. Timers”// Set a timer with ID=1, fires every 1000ms (1 second)SetTimer(hwnd, 1, 1000, NULL);
// Handle in WndProccase WM_TIMER: if (wParam == 1) { // Called every second — update UI, check state, etc. InvalidateRect(hwnd, NULL, TRUE); // Trigger repaint } break;
// Stop the timer when no longer neededKillTimer(hwnd, 1);12. Registry Read/Write
Section titled “12. Registry Read/Write”HKEY hKey;
// --- Write a registry value ---// Opens or creates a subkey under HKCURegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Software\\\\MyApp"), 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL);
DWORD val = 42;RegSetValueEx(hKey, TEXT("MyValue"), 0, REG_DWORD, (BYTE*)&val, sizeof(val)); // Write DWORD valueRegCloseKey(hKey);
// --- Read a registry value ---RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\\\MyApp"), 0, KEY_READ, &hKey);
DWORD data, size = sizeof(data);RegQueryValueEx(hKey, TEXT("MyValue"), NULL, NULL, (BYTE*)&data, &size); // Read into 'data'RegCloseKey(hKey);printf("Registry value: %lu\\n", data);🔴 ADVANCED
Section titled “🔴 ADVANCED”13. Threads
Section titled “13. Threads”// Thread function — must match LPTHREAD_START_ROUTINE signatureDWORD WINAPI MyThread(LPVOID lpParam) { int* val = (int*)lpParam; // Cast the parameter printf("Thread got: %d\\n", *val); return 0; // Exit code}
int data = 99;HANDLE hThread = CreateThread( NULL, // Default security 0, // Default stack size MyThread, // Thread function &data, // Parameter passed to thread 0, // Run immediately (use CREATE_SUSPENDED to delay) NULL // Don't need thread ID);
WaitForSingleObject(hThread, INFINITE); // Block until thread finishesCloseHandle(hThread);14. Mutex (Thread Synchronization)
Section titled “14. Mutex (Thread Synchronization)”// Create a named mutex — prevents multiple instances or race conditionsHANDLE hMutex = CreateMutex(NULL, FALSE, TEXT("MyAppMutex"));
if (GetLastError() == ERROR_ALREADY_EXISTS) { // Another instance is already running MessageBox(NULL, TEXT("Already running!"), TEXT("Error"), MB_OK); return 1;}
// Acquire the mutex (lock) — waits up to 5 secondsWaitForSingleObject(hMutex, 5000);
// --- Critical section (shared resource access) ---// ... do thread-safe work here ...
ReleaseMutex(hMutex); // Release the lockCloseHandle(hMutex);15. Critical Sections (Faster than Mutex for same-process)
Section titled “15. Critical Sections (Faster than Mutex for same-process)”CRITICAL_SECTION cs;InitializeCriticalSection(&cs); // Init once at startup
// In each thread, wrap shared data access:EnterCriticalSection(&cs); // Lock — only one thread enters at a time // ... access shared data safely ...LeaveCriticalSection(&cs); // Unlock
DeleteCriticalSection(&cs); // Cleanup on exit16. Process Creation
Section titled “16. Process Creation”STARTUPINFO si = {0};PROCESS_INFORMATION pi = {0};si.cb = sizeof(si); // Must set this field
// Launch notepad.exe as a child processBOOL ok = CreateProcess( NULL, // No module name (use command line) TEXT("notepad.exe"), // Command line NULL, NULL, // Process/Thread security attributes FALSE, // Don't inherit handles 0, // Normal priority NULL, // Use parent's environment NULL, // Use parent's working directory &si, &pi);
if (ok) { WaitForSingleObject(pi.hProcess, INFINITE); // Wait for it to finish CloseHandle(pi.hProcess); CloseHandle(pi.hThread);}17. Memory Mapped Files (Shared Memory Between Processes)
Section titled “17. Memory Mapped Files (Shared Memory Between Processes)”// Process A — create and writeHANDLE hMap = CreateFileMapping( INVALID_HANDLE_VALUE, // Use paging file (not a real file) NULL, PAGE_READWRITE, 0, 256, // Max size: 256 bytes TEXT("MySharedMem") // Named so other processes can open it);
LPVOID pBuf = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 256);CopyMemory(pBuf, "Hello from A!", 14); // Write to shared memory
// Process B — open and readHANDLE hMap2 = OpenFileMapping(FILE_MAP_READ, FALSE, TEXT("MySharedMem"));LPVOID pBuf2 = MapViewOfFile(hMap2, FILE_MAP_READ, 0, 0, 256);printf("Shared: %s\\n", (char*)pBuf2);
// CleanupUnmapViewOfFile(pBuf); CloseHandle(hMap);UnmapViewOfFile(pBuf2); CloseHandle(hMap2);18. Hooks (Global Keyboard Hook)
Section titled “18. Hooks (Global Keyboard Hook)”HHOOK hHook;
// Callback for low-level keyboard eventsLRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode == HC_ACTION) { KBDLLHOOKSTRUCT* kb = (KBDLLHOOKSTRUCT*)lParam; if (wParam == WM_KEYDOWN) { printf("Key pressed: %lu\\n", kb->vkCode); } } return CallNextHookEx(hHook, nCode, wParam, lParam); // MUST call this!}
// Install the hookhHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, NULL, 0);
// Run message loop to keep hook aliveMSG msg;while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);
// Remove hook when doneUnhookWindowsHookEx(hHook);19. Custom Drawing with GDI
Section titled “19. Custom Drawing with GDI”case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps);
// Draw a filled rectangle HBRUSH hBrush = CreateSolidBrush(RGB(0, 120, 215)); // Blue brush RECT rc = {50, 50, 200, 150}; FillRect(hdc, &rc, hBrush); DeleteObject(hBrush); // Always delete GDI objects!
// Draw a line MoveToEx(hdc, 0, 0, NULL); // Move pen to (0,0) LineTo(hdc, 300, 300); // Draw line to (300,300)
// Draw text with custom font HFONT hFont = CreateFont(24, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, TEXT("Arial")); SelectObject(hdc, hFont); // Apply font to DC SetTextColor(hdc, RGB(255,255,255)); SetBkMode(hdc, TRANSPARENT); // Transparent text background TextOut(hdc, 60, 90, TEXT("Win32 GDI"), 9); DeleteObject(hFont);
EndPaint(hwnd, &ps); break;}20. Window Subclassing
Section titled “20. Window Subclassing”// Save original WndProc of a control (e.g., an EDIT box)WNDPROC OldEditProc;
LRESULT CALLBACK SubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_KEYDOWN && wParam == VK_RETURN) { MessageBox(hwnd, TEXT("Enter pressed in edit!"), TEXT(""), MB_OK); return 0; // Eat the message } // Pass everything else to the original handler return CallWindowProc(OldEditProc, hwnd, msg, wParam, lParam);}
// Subclass the edit controlHWND hEdit = CreateWindow(TEXT("EDIT"), ..., hwnd, (HMENU)2, hInstance, NULL);OldEditProc = (WNDPROC)SetWindowLongPtr(hEdit, GWLP_WNDPROC, (LONG_PTR)SubclassProc);21. COM Basics (Component Object Model)
Section titled “21. COM Basics (Component Object Model)”#include <windows.h>#include <shobjidl.h> // IFileOpenDialog
// COM must be initialized before useCoInitialize(NULL);
IFileOpenDialog* pDialog = NULL;
// Create a COM object (File Open Dialog)CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, &IID_IFileOpenDialog, (void**)&pDialog);
pDialog->lpVtbl->Show(pDialog, NULL); // Show the dialog
IShellItem* pItem = NULL;pDialog->lpVtbl->GetResult(pDialog, &pItem); // Get selected file
PWSTR filePath;pItem->lpVtbl->GetDisplayName(pItem, SIGDN_FILESYSPATH, &filePath);// filePath now holds the selected file path (wide string)
CoTaskMemFree(filePath); // Free COM-allocated stringpItem->lpVtbl->Release(pItem); // Release COM objects when donepDialog->lpVtbl->Release(pDialog);
CoUninitialize(); // Cleanup COM22. Useful Macros & Helpers Quick Reference
Section titled “22. Useful Macros & Helpers Quick Reference”// ---- Bit manipulation helpers ----LOWORD(0xABCD1234) // → 0x1234 (lower 16 bits) — used for coords/IDsHIWORD(0xABCD1234) // → 0xABCD (upper 16 bits)MAKELONG(lo, hi) // Combine two WORDs into a DWORD
// ---- Window helpers ----GetClientRect(hwnd, &rc); // Get window's inner drawable areaSetWindowText(hwnd, TEXT("New Title")); // Change window titleGetWindowText(hwnd, buf, 256); // Read window titleEnableWindow(hwnd, FALSE); // Disable/grey out a controlShowWindow(hwnd, SW_HIDE); // Hide a windowInvalidateRect(hwnd, NULL, TRUE); // Force window to repaint
// ---- Screen/cursor ----GetCursorPos(&pt); // Get mouse position on screenScreenToClient(hwnd, &pt); // Convert screen → window coordinatesGetSystemMetrics(SM_CXSCREEN); // Screen width in pixelsGetSystemMetrics(SM_CYSCREEN); // Screen height in pixels
// ---- Module/path ----GetModuleFileName(NULL, buf, 256); // Path of current .exeGetCurrentDirectory(256, buf); // Current working directorySetCurrentDirectory(TEXT("C:\\\\")); // Change working directory
// ---- Timing ----DWORD t = GetTickCount(); // Milliseconds since system boot (32-bit wraps)ULONGLONG t2 = GetTickCount64(); // 64-bit version — no wrap issuesSleep(1000); // Pause thread for 1000ms📌 Quick Flags Reference
Section titled “📌 Quick Flags Reference”| Flag | Meaning |
|---|---|
MB_OK | Message box with OK button |
MB_YESNO | Yes/No buttons |
MB_ICONERROR | Error icon |
MB_ICONWARNING | Warning icon |
WS_OVERLAPPEDWINDOW | Standard window with title/borders |
WS_CHILD | Child control (inside another window) |
WS_VISIBLE | Make visible immediately |
| `CS_HREDRAW \ | CS_VREDRAW` |
VK_ESCAPE | Escape virtual key |
VK_RETURN | Enter virtual key |
GENERIC_READ | Open file for reading |
GENERIC_WRITE | Open file for writing |
CREATE_ALWAYS | Create/overwrite file |
OPEN_EXISTING | Open only if exists |
Built for Win32 C/C++ development. Compile with -luser32 -lgdi32 -lkernel32 or use Visual Studio / MinGW.