int CALLBACK WinMain(
_In_ HINSTANCE hInstance, // 目前應用程式實例控制代碼
_In_ HINSTANCE hPrevInstance, // 前一個實例 (Win32 恆為 NULL)
_In_ LPSTR lpCmdLine, // 命令列參數 (ANSI 字串)
_In_ int nCmdShow // 主視窗顯示方式 (SW_SHOW 等)
);
CALLBACK = __stdcall 呼叫慣例 (Pascal 風格,參數由呼叫者清除堆疊)__cdecl,WinAPI 需 __stdcall




C++ 編譯器由上而下解析,WindowProc 實作在 WinMain 之後,必須前置宣告:
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd, _In_ UINT uMsg,
_In_ WPARAM wParam, _In_ LPARAM lParam
);
MyProc),但簽章必須一致lpfnWndProc 傳遞函數指標,系統透過此指標呼叫回呼函數DefWindowProc 預設處理
WNDCLASS wc = { }; // 大括號初始化,所有成員歸零
wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // 背景畫刷
wc.lpfnWndProc = WindowProc; // 視窗程序
wc.lpszClassName = L"My Class"; // 類別名稱
wc.hInstance = hInstance; // 實例控制代碼
// 註冊
RegisterClass(&wc);
MSDN 文件註明:"You must fill the structure with the appropriate class attributes before passing it to the function."
未初始化的成員含隨機值會導致 RegisterClass 失敗,視窗建立失敗 (hwnd = NULL)。
// 1. 逐一賦值 (繁瑣)
wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hCursor = ...; ...
// 2. 指定大小 (C 風格)
WNDCLASS wc = { sizeof(WNDCLASS) };
// 3. 空大括號 (C++11 推薦,最簡潔)
WNDCLASS wc = { };

HWND hwnd = CreateWindow(
L"My Class", // 類別名
L"我的應用程式", // 標題
WS_OVERLAPPEDWINDOW, // 視窗樣式
38, 20, 480, 250, // x, y, 寬, 高
NULL, NULL, // 父視窗、選單
hInstance, NULL // 實例、額外參數
);
if (hwnd == NULL) return 0; // 建立失敗檢查
ShowWindow(hwnd, SW_SHOW); // 顯示
UpdateWindow(hwnd); // 立即傳送 WM_PAINT (可選)
Windows 為訊息驅動架構,需死循環取出並分派訊息:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg); // 鍵盤訊息轉換 (WM_KEYDOWN → WM_CHAR)
DispatchMessage(&msg); // 分派至 WindowProc
}
GetMessage 從佇列取出訊息填入 MSG 結構,遇 WM_QUIT 回傳 0 跳出迴圈TranslateMessage 將虛擬鍵碼轉為字元訊息DispatchMessage 依 MSG.hwnd 找到視窗程序並呼叫視窗關閉觸發 WM_DESTROY,呼叫 PostQuitMessage(0) 貼上 WM_QUIT,使 GetMessage 回傳 0 結束迴圈:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0); return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
#include <Windows.h>
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd, _In_ UINT uMsg,
_In_ WPARAM wParam, _In_ LPARAM lParam
);
int CALLBACK WinMain(
_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine, _In_ int nCmdShow
) {
WCHAR* cls_Name = L"My Class";
WNDCLASS wc = { };
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = cls_Name;
wc.hInstance = hInstance;
RegisterClass(&wc);
HWND hwnd = CreateWindow(
cls_Name, L"我的應用程式", WS_OVERLAPPEDWINDOW,
38, 20, 480, 250, NULL, NULL, hInstance, NULL
);
if (hwnd == NULL) return 0;
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd, _In_ UINT uMsg,
_In_ WPARAM wParam, _In_ LPARAM lParam
) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0); return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
WNDCLASS **必須完整初始化**,推薦 WNDCLASS wc = { };RegisterClass 失敗會導致 CreateWindow 傳回 NULLGetMessage → TranslateMessage → DispatchMessageWM_DESTROY → PostQuitMessage → WM_QUIT → 迴圈結束 → 程式退出DefWindowProc 處理未關心的訊息,保留系統預設行為