本文完整演示如何用純 Win32 API(C 語言)實現一個模擬指針時鐘 + 數字時鐘的桌面程序。涵蓋窗口創建、定時器驅動、GDI 繪圖(畫筆/畫刷/文本/幾何)、WM_PAINT 重繪機制、按鈕控制啟停——是 Windows 圖形編程的優秀入門項目。
SetTimer/KillTimer)WM_TIMER,調用顯示更新FillRect 擦除舊文本 → DrawText 繪製新時間Ellipse 畫圓 + 三角函數計算 12 個刻度座標 + DrawText 寫數字MoveToEx/LineTo 畫線,區分粗細顏色WNDCLASS wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = TEXT("AnalogClock");
RegisterClass(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, TEXT("Analog Clock"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 560, 360,
NULL, NULL, hInstance, NULL);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_START: SetTimer(hwnd, TIMER_ID, 1000, NULL); break;
case ID_STOP: KillTimer(hwnd, TIMER_ID); break;
}
return 0;
void DrawClockFace(HDC hdc) {
HPEN hPen = CreatePen(PS_SOLID, 1, RGB(0,0,255));
SelectObject(hdc, hPen);
Ellipse(hdc, 180, 20, 340, 180); // 圓心 (260,100) 半徑 80
// 12 個刻度
for (int i=0; i<12; i++) {
double angle = i * M_PI / 6;
int x1 = 260 + 70 * sin(angle);
int y1 = 100 - 70 * cos(angle);
int x2 = 260 + 80 * sin(angle);
int y2 = 100 - 80 * cos(angle);
MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x2, y2);
}
// 繪製 1~12 數字(略)
DeleteObject(hPen);
}
| 指針 | 角度公式(弧度) | 長度 | 顏色/粗細 |
|---|---|---|---|
| 時針 | (hour%12)*π/6 + (min*60+sec)*π/(1800*12) | 30px | 紅色 5px |
| 分針 | min*π/30 + sec*π/1800 | 45px | 綠色 3px |
| 秒針 | sec*π/30 | 65px | 黑色 1px |
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
DrawClockFace(hdc);
GetLocalTime(&st);
DrawClockHands(hdc, st.wHour, st.wMinute, st.wSecond);
EndPaint(hwnd, &ps);
return 0;
WinMain:註冊類、創建窗口、消息循環WndProc:處理 WM_CREATE/WM_COMMAND/WM_TIMER/WM_PAINT/WM_DESTROYDrawClockFace、DrawClockHands、ShowTime、ShowClock:繪圖模塊my_listen:示例中未用到的佔位函數CreatePen/SelectObject/DeleteObject 三部曲,防止 GDI 洩漏。SetTimer(hwnd, id, 1000, NULL) 約 1 秒,非實時系統足夠。y = centerY - r*cos(angle)。WM_PAINT 與定時器調用的公共函數,保證一致性。這個項目雖小,卻串聯了 Windows 圖形編程的核心知識點,是進階學習 Direct2D、WPF、WinUI 3 等現代框架前的寶貴基石。