控制項本質上是子視窗,建立方式與視窗相同,使用 CreateWindow/CreateWindowEx,必須加上 WS_CHILD 與 WS_VISIBLE 樣式。建立時機通常在主視窗的 WM_CREATE 訊息中處理。
Microsoft 提供 Control Spy 工具可預覽控制項外觀、樣式與訊息流向。下載連結:MSDN 下載頁面
case WM_CREATE: {
CreateWindow(L"Button", L"有種就來點擊我!",
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
35, 45, 160, 65, hwnd, NULL, hg_app, NULL);
} return 0;
控制項 ID 設定:CreateWindow 的 hMenu 參數對子視窗而言即為控制項識別碼。習慣用 #define 定義常數:
#define IDB_ONE 3301
#define IDB_TWO 3302
#define IDB_THREE 3303
按鈕點擊產生 WM_COMMAND:
LOWORD(wParam) = 控制項 IDHIWORD(wParam) = 通知碼(如 BN_CLICKED)lParam = 控制項視窗控制代碼case WM_COMMAND: {
switch (LOWORD(wParam)) {
case IDB_ONE:
MessageBox(hwnd, L"您點擊了第一個按鈕。", L"提示", MB_OK|MB_ICONINFORMATION);
break;
case IDB_TWO:
MessageBox(hwnd, L"您點擊了第二個按鈕。", L"提示", MB_OK|MB_ICONINFORMATION);
break;
case IDB_THREE:
MessageBox(hwnd, L"您點擊了第三個按鈕。", L"提示", MB_OK|MB_ICONINFORMATION);
break;
}
} return 0;

利用 WM_COMMAND 的 lParam 取得按鈕控制代碼,發送 WM_SETTEXT 訊息:
case WM_COMMAND: {
switch (LOWORD(wParam)) {
case IDB_ONE:
SendMessage((HWND)lParam, WM_SETTEXT, 0, (LPARAM)L"第一個按鈕已點擊");
break;
case IDB_TWO:
SendMessage((HWND)lParam, WM_SETTEXT, 0, (LPARAM)L"第二個按鈕已點擊");
break;
case IDB_THREE:
SendMessage((HWND)lParam, WM_SETTEXT, 0, (LPARAM)L"第三個按鈕已點擊");
break;
}
} return 0;
關鍵點:WindowProc 的第一個參數 hwnd 是主視窗控制代碼,操作按鈕必須用 lParam 轉型為 HWND。

#include <Windows.h>
#include <WinNT.h>
#define IDB_ONE 3301
#define IDB_TWO 3302
#define IDB_THREE 3303
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LPCWSTR lps_cl = L"MyApp";
LPCWSTR wd_text = L"超級應用";
HINSTANCE hg_app;
int WINAPI wWinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPWSTR lpCmd, int nShow) {
WNDCLASSEX wc = { };
wc.cbSize = sizeof(WNDCLASSEX);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hInstance = hThisApp;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.lpszClassName = lps_cl;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
HWND hwnd = CreateWindowEx(WS_EX_WINDOWEDGE, lps_cl, wd_text,
WS_OVERLAPPEDWINDOW, 20, 25, 400, 300,
NULL, NULL, hThisApp, NULL);
if (hwnd == NULL) return -1;
ShowWindow(hwnd, nShow);
UpdateWindow(hwnd);
hg_app = hThisApp;
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_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CREATE: {
CreateWindow(L"Button", L"按鈕一", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
35, 10, 160, 60, hwnd, (HMENU)IDB_ONE, hg_app, NULL);
CreateWindow(L"Button", L"按鈕二", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
35, 80, 160, 60, hwnd, (HMENU)IDB_TWO, hg_app, NULL);
CreateWindow(L"Button", L"按鈕三", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
35, 150, 160, 60, hwnd, (HMENU)IDB_THREE, hg_app, NULL);
} return 0;
case WM_COMMAND: {
switch (LOWORD(wParam)) {
case IDB_ONE:
SendMessage((HWND)lParam, WM_SETTEXT, 0, (LPARAM)L"第一個按鈕已點擊");
break;
case IDB_TWO:
SendMessage((HWND)lParam, WM_SETTEXT, 0, (LPARAM)L"第二個按鈕已點擊");
break;
case IDB_THREE:
SendMessage((HWND)lParam, WM_SETTEXT, 0, (LPARAM)L"第三個按鈕已點擊");
break;
}
} return 0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
WS_CHILD | WS_VISIBLECreateWindow 的 hMenu 參數傳入WM_COMMAND 回應按鈕點擊,lParam 為按鈕控制代碼SendMessage(hBtn, WM_SETTEXT, 0, (LPARAM)新文字)