錯誤代碼分析
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
CreateWindowEx(0, TEXT("#32770"), TEXT(""), WS_OVERLAPPEDWINDOW,
50, 50, 100, 100, NULL, NULL, hInstance, NULL);
return 0; // 程序立即退出
}
核心問題
- 無消息循環:Win32 GUI 程序必須運行
GetMessage/DispatchMessage 循環,否則窗口無法接收繪制、輸入等消息,創建後立即銷毀。
- 直接使用系統類 "#32770":該類為對話框專用,**不可直接用 CreateWindowEx 創建**,需用
DialogBox 或 CreateDialog 系列函數。
- 缺少窗口類註冊:普通窗口需先
RegisterClassEx 定義 WNDCLASSEX(窗口過程、圖標、光標、背景刷等)。
正確框架:最小 Win32 GUI 程序
#include
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY: PostQuitMessage(0); return 0;
case WM_PAINT: {
PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 10, 10, L"Hello Win32", 11);
EndPaint(hwnd, &ps); return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow) {
// 1. 註冊窗口類
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_HREDRAW|CS_VREDRAW, WndProc,
0, 0, hInst, LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(COLOR_WINDOW+1), NULL, L"MinWinClass", LoadIcon(NULL, IDI_APPLICATION) };
if (!RegisterClassEx(&wc)) return 0;
// 2. 創建窗口
HWND hwnd = CreateWindowEx(0, L"MinWinClass", L"最小窗口", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, NULL, hInst, NULL);
if (!hwnd) return 0;
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// 3. 消息循環
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
若確需模態對話框
// 資源腳本 .rc 中定義
IDD_MYDIALOG DIALOGEX 0, 0, 200, 150
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "我的對話框"
FONT 9, "微軟雅黑"
BEGIN
DEFPUSHBUTTON "確定", IDOK, 70, 120, 50, 14
PUSHBUTTON "取消", IDCANCEL, 130, 120, 50, 14
END
// 代碼調用
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG: return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, LOWORD(wParam)); return TRUE;
}
break;
}
return FALSE;
}
int WINAPI WinMain(...) {
DialogBox(hInst, MAKEINTRESOURCE(IDD_MYDIALOG), NULL, DlgProc);
return 0;
}
關鍵差異總結
| 特性 | 普通窗口 | 模態對話框 | 無模對話框 |
| 創建函數 | CreateWindowEx | DialogBox | CreateDialog |
| 窗口類 | 自定義 RegisterClassEx | 系統類 #32770 (內部) | 系統類 #32770 |
| 消息循環 | 手寫 GetMessage 循環 | 系統內部運行 | 主循環需 IsDialogMessage |
| 窗口過程 | WndProc 返回 LRESULT | DlgProc 返回 INT_PTR (BOOL) | 同模態 |
學習建議
- 先掌握「註冊類 → 創建窗口 → 消息循環 → 窗口過程」四步核心流程。
- 使用 Visual Studio 「Windows Desktop Application」模板生成完整樣板代碼。
- 參考《Windows 核心編程》第 1-3 章或 MSDN「Windows 經典桌面應用程序」教程。