在前幾篇文章中,我們建立 Win32 應用程式的標準流程是:設計視窗類別、註冊視窗類別、建立視窗。然而,當開始使用控制項時,會發現直接在視窗上排版控制項相當麻煩。相反地,資源編輯器中的對話框提供了圖形化設計介面,配置控制項輕鬆許多。因此,許多開發者萌生了一個想法:能不能直接把對話框當作主視窗使用?
這個概念在網路上已有高手實作(甚至有用 Win32 組合語言完成的),改寫成 C++ 更是輕而易舉。本文將介紹兩種主要做法。
這是最直接的方式,步驟如下:
CreateDialog,父視窗指定為 GetDesktopWindow()。#include <Windows.h>
#include "resource.h"
// 啟用視覺樣式 (Common Controls 6.0)
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE hgInst;
int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow) {
hgInst = hThisApp;
// 建立對話框,父視窗為桌面視窗
HWND hdlg = CreateDialog(hThisApp, MAKEINTRESOURCE(IDD_MY),
GetDesktopWindow(), (DLGPROC)DlgProc);
if (!hdlg) return 0;
ShowWindow(hdlg, SW_SHOW);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG:
// 設定對話框圖示
SendMessage(hDlg, WM_SETICON, ICON_SMALL,
(LPARAM)LoadIcon(hgInst, MAKEINTRESOURCE(IDI_APP)));
return 0;
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE) {
PostQuitMessage(0); // 退出訊息迴圈
}
return 0;
}
return (INT_PTR)FALSE;
}

此法保留傳統「設計視窗類別→註冊→建立視窗」流程,差別在於 WM_CREATE 時建立一個 Form View 風格的對話框並將其貼在主視窗上。
WM_CREATE 處理函式中,呼叫 CreateDialog 建立對話框,父視窗傳入主視窗 hwnd,並以 SW_SHOWNA 顯示(不啟動視窗)。case WM_CREATE: {
// 建立 Form View 對話框,父視窗為 hwnd
HWND hdlg = CreateDialog(hgAppInst, MAKEINTRESOURCE(IDD_MYFORM),
hwnd, (DLGPROC)DlgProc);
// 顯示但不啟動
ShowWindow(hdlg, SW_SHOWNA);
} return 0;




#include <Windows.h>
#include "resource.h"
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE hgAppInst;
int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow) {
// 設計視窗類別
WNDCLASS wc = { };
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.lpszClassName = L"supper_man";
wc.hInstance = hThisApp;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
hgAppInst = hThisApp;
// 建立主視窗
HWND hwnd = CreateWindow(L"supper_man", L"超級應用",
WS_OVERLAPPEDWINDOW, 40, 25, 380, 300,
NULL, NULL, hThisApp, NULL);
if (!hwnd) return 0;
ShowWindow(hwnd, nShow);
UpdateWindow(hwnd);
// 訊息迴圈
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
HWND hdlg = CreateDialog(hgAppInst, MAKEINTRESOURCE(IDD_MYFORM),
hwnd, (DLGPROC)DlgProc);
ShowWindow(hdlg, SW_SHOWNA);
} return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
// 對話框訊息處理
INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) {
/* 處理對話框內控制項的訊息 */
return (INT_PTR)FALSE;
}