windows下編程--模擬時鐘的實現,windows編程--時鐘
windows下編程--模擬時鐘的實現:
主要可以分為幾個步驟:
(1) 編寫按鍵事件處理(啟動和停止時鐘)
(2) 編寫時鐘事件處理,調用顯示時鐘函數
(3) 編寫顯示時鐘函數,要調用顯示數字時鐘函數、畫出鐘面函數和畫出指針函數
(4) 編寫顯示數字時鐘函數。注意要自己用矩形填充(FillRect)擦除背景。
(5) 編寫畫出鐘面函數
(6) 編寫畫出指針函數
(7) 增加WM_PAINT消息處理:調用顯示時鐘函數,防止在停止時鐘後從窗口最小化恢復會不顯示內容。
最後結果類似於這種形式---一個模擬時鐘,數字時鐘+畫面時鐘




每一步的說明:
(1)編寫按鍵事件處理(啟動和停止時鐘)

(2) 編寫時鐘事件處理,調用顯示時鐘函數

(3) 編寫顯示時鐘函數,要調用顯示數字時鐘函數、畫出鐘面函數和畫出指針函數

(4) 編寫顯示數字時鐘函數。注意要自己用矩形填充(FillRect)擦除背景。

(5) 編寫畫出鐘面函數

(6) 編寫畫出指針函數(注意好時針分針秒針的角度關系計算方法就行了)

(7) 增加WM_PAINT消息處理:調用顯示時鐘函數,防止在停止時鐘後從窗口最小化恢復會不顯示內容。

基本上只是考察了基本的windows編程,掌握好時鐘事件和按鈕的編程。
最後附上長長的代碼...

![]()
1 /*------------------------------------------------------------
2 HELLOWIN.C -- Displays "Hello, Windows 98!" in client area
3 (c) Charles Petzold, 1998
4 ------------------------------------------------------------*/
5
6 #include <windows.h>
7 #include <stdio.h>
8 #include <math.h>
9
10 #define PI 3.14159265358979323846
11 #define TIMER_SEC 1
12 #define TIMER_MIN 2
13 #define BUTTON1 3
14 #define BUTTON2 4
15
16 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
17
18 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
19 PSTR szCmdLine, int iCmdShow)
20 {
21 static TCHAR szAppName[] = TEXT ("HelloWin") ;
22 HWND hwnd,hwndButton1,hwndButton2;
23 MSG msg ;
24 WNDCLASS wndclass ;
25
26 wndclass.style = CS_HREDRAW | CS_VREDRAW ;
27 wndclass.lpfnWndProc = WndProc ;
28 wndclass.cbClsExtra = 0 ;
29 wndclass.cbWndExtra = 0 ;
30 wndclass.hInstance = hInstance ;
31 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
32 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
33 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
34 wndclass.lpszMenuName = NULL ;
35 wndclass.lpszClassName = szAppName ;
36
37 if (!RegisterClass (&wndclass))
38 {
39 MessageBox (NULL, TEXT ("This program requires Windows NT!"),
40 szAppName, MB_ICONERROR) ;
41 return 0 ;
42 }
43
44 hwnd = CreateWindow (szAppName, // window class name
45 TEXT ("Analog Clock"), // window caption
46 WS_OVERLAPPEDWINDOW, // window style
47 CW_USEDEFAULT, // initial x position
48 CW_USEDEFAULT, // initial y position
49 560, // initial x size
50 360, // initial y size
51 NULL, // parent window handle
52 NULL, // window menu handle
53 hInstance, // program instance handle
54 NULL) ; // creation parameters
55
56 ShowWindow (hwnd, iCmdShow) ;
57 UpdateWindow (hwnd) ;
58
59 hwndButton1 = CreateWindow(TEXT("button"), // 窗口類名(系統內部定義了該窗口類)
60 TEXT("StartTimer"), // 標題
61 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // 樣式
62 100, 250, // 左上角位置x,y
63 120, 40, // 寬度,高度
64 hwnd, // 父窗口句柄
65 (HMENU)BUTTON1, // 控件ID
66 hInstance, // 實例句柄
67 NULL); // 自定義參數
68
69 hwndButton2 = CreateWindow(TEXT("button"), // 窗口類名
70 TEXT("StopTimer"), // 標題
71 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // 樣式
72 300, 250, // 左上角位置x,y
73 120, 40, // 寬度,高度
74 hwnd, // 父窗口句柄
75 (HMENU)BUTTON2, // 控件ID
76 hInstance, // 實例句柄
77 NULL);
78
79 while (GetMessage (&msg, NULL, 0, 0))
80 {
81 TranslateMessage (&msg) ;
82 DispatchMessage (&msg) ;
83 }
84 return msg.wParam ;
85 }
86
87 // 畫出鐘面(不包括指針)
88 void DrawClockFace(HDC hdc){
89 // PAINTSTRUCT ps;
90 RECT rect;
91 HPEN hPen;
92 HPEN oldPen;
93 hPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 255)); // 創建畫筆(線形,線寬,顏色)
94 oldPen = (HPEN)SelectObject(hdc, hPen); // 選擇畫筆,並保留原畫筆
95 Ellipse(hdc, 180, 20, 340, 180); // 時鐘--半徑 80 作出時鐘原始圖像
96 Rectangle(hdc, 220, 205, 295, 230);
97 double xStart1, yStart1, xEnd1, yEnd1;
98 for (int i = 0; i <= 11; i++){
99 if (i <= 3){
100 xEnd1 = 260 + 80 * sin(i* PI / 6);
101 xStart1 = 260 + (80 - 10) * sin(i* PI / 6);
102 yEnd1 = 100 - 80 * cos(i* PI / 6);
103 yStart1 = 100 - (80 - 10) * cos(i* PI / 6);
104 }
105 if (i > 3 && i <= 6){
106 xEnd1 = 260 + 80 * sin(i* PI / 6);
107 xStart1 = 260 + (80 - 10) * sin(i* PI / 6);
108 yStart1 = 100 + (80 - 10) * cos(PI - i* PI / 6);
109 yEnd1 = 100 + 80 * cos(PI - i* PI / 6);
110 }
111 if (i > 6 && i <= 9)
112 {
113 xEnd1 = 260 - 80 * cos(1.5*PI - i* PI / 6);
114 xStart1 = 260 - (80 - 10) * cos(1.5*PI - i* PI / 6);
115 yStart1 = 100 + (80 - 10) * sin(1.5*PI - i* PI / 6);
116 yEnd1 = 100 + 80 * sin(1.5*PI - i* PI / 6);
117 }
118 if (i > 9){
119 xEnd1 = 260 - 80 * sin(2 * PI - i* PI / 6);
120 xStart1 = 260 - (80 - 10) * sin(2 * PI - i* PI / 6);
121 yEnd1 = 100 - 80 * cos(2 * PI - i* PI / 6);
122 yStart1 = 100 - (80 - 10) * cos(2 * PI - i* PI / 6);
123 }
124 MoveToEx(hdc, xStart1, yStart1, NULL);
125 LineTo(hdc, xEnd1, yEnd1);
126 }
127 DeleteObject(hPen);
128 // 鐘面相應數字 --- 12
129 rect.left = 250;
130 rect.top = 5;
131 rect.right = 270;
132 rect.bottom = 18;
133 DrawText(hdc, TEXT("12"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
134 // 鐘面相應數字 --- 11
135 rect.left = 210;
136 rect.top = 15;
137 rect.right = 220;
138 rect.bottom = 30;
139 DrawText(hdc, TEXT("11"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
140 // 鐘面相應數字 --- 10
141 rect.left = 175;
142 rect.top = 50;
143 rect.right = 190;
144 rect.bottom = 60;
145 DrawText(hdc, TEXT("10"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
146 // 鐘面相應數字 --- 9
147 rect.left = 165;
148 rect.top = 95;
149 rect.right = 175;
150 rect.bottom = 105;
151 DrawText(hdc, TEXT("9"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
152 // 鐘面相應數字 --- 8
153 rect.left = 175;
154 rect.top = 135;
155 rect.right = 190;
156 rect.bottom = 145;
157 DrawText(hdc, TEXT("8"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
158 // 鐘面相應數字 --- 7
159 rect.left = 208;
160 rect.top = 167;
161 rect.right = 215;
162 rect.bottom = 185;
163 DrawText(hdc, TEXT("7"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
164 // 鐘面相應數字 --- 6
165 rect.left = 250;
166 rect.top = 182;
167 rect.right = 270;
168 rect.bottom = 192;
169 DrawText(hdc, TEXT("6"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
170 // 鐘面相應數字 --- 5
171 rect.left = 295;
172 rect.top = 170;
173 rect.right = 310;
174 rect.bottom = 180;
175 DrawText(hdc, TEXT("5"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
176 // 鐘面相應數字 --- 4
177 rect.left = 335;
178 rect.top = 135;
179 rect.right = 345;
180 rect.bottom = 145;
181 DrawText(hdc, TEXT("4"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
182 // 鐘面相應數字 --- 3
183 rect.left = 345;
184 rect.top = 95;
185 rect.right = 355;
186 rect.bottom = 105;
187 DrawText(hdc, TEXT("3"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
188 // 鐘面相應數字 --- 2
189 rect.left = 335;
190 rect.top = 48;
191 rect.right = 345;
192 rect.bottom = 60;
193 DrawText(hdc, TEXT("2"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
194 // 鐘面相應數字 --- 1
195 rect.left = 300;
196 rect.top = 20;
197 rect.right = 310;
198 rect.bottom = 30;
199 DrawText(hdc, TEXT("1"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
200 return;
201 }
202
203 // 畫出時鐘指針
204 void DrawClockHands(HDC hdc,int hour,int min,int sec){
205 PAINTSTRUCT ps;
206 RECT rect;
207 HPEN hPen;
208 HPEN oldPen;
209 double xStart1, yStart1, xEnd1, yEnd1;
210 hour = (hour >= 12 ? hour - 12 : hour);
211 hPen = CreatePen(PS_SOLID, 5, RGB(255, 0, 0)); // 創建畫筆(線形,線寬,顏色)
212 oldPen = (HPEN)SelectObject(hdc, hPen); // 選擇畫筆,並保留原畫筆
213 // 顯示時針
214 xStart1 = 260;
215 yStart1 = 100;
216 xEnd1 = 260 + (80 - 50) * sin(hour*PI / 6 + ((min * 60 + sec) * PI / (1800*12)));
217 yEnd1 = 100 - (80 - 50) * cos(hour*PI / 6 + ((min * 60 + sec) * PI / (1800*12)));
218 MoveToEx(hdc, xStart1, yStart1, NULL);
219 LineTo(hdc, xEnd1, yEnd1);
220 DeleteObject(hPen);
221
222 hPen = CreatePen(PS_SOLID, 3, RGB(0, 255, 0)); // 創建畫筆(線形,線寬,顏色)
223 oldPen = (HPEN)SelectObject(hdc, hPen); // 選擇畫筆,並保留原畫筆
224 // 顯示分針
225 xStart1 = 260;
226 yStart1 = 100;
227 xEnd1 = 260 + (80 - 35) * sin(min*PI / 30 + (sec * PI / 1800));
228 yEnd1 = 100 - (80 - 35) * cos(min*PI / 30 + (sec * PI / 1800));
229 MoveToEx(hdc, xStart1, yStart1, NULL);
230 LineTo(hdc, xEnd1, yEnd1);
231 DeleteObject(hPen);
232
233 hPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); // 創建畫筆(線形,線寬,顏色)
234 oldPen = (HPEN)SelectObject(hdc, hPen); // 選擇畫筆,並保留原畫筆
235 // 顯示秒針
236 xStart1 = 260;
237 yStart1 = 100;
238 xEnd1 = 260 + (80 - 15) * sin(sec * PI / 30);
239 yEnd1 = 100 - (80 - 15) * cos(sec * PI / 30);
240 MoveToEx(hdc, xStart1, yStart1, NULL);
241 LineTo(hdc, xEnd1, yEnd1);
242 DeleteObject(hPen);
243
244 return;
245 }
246 /*////////////////////////////////////////////////////
247 void ShowTime1(HDC hdc){ // use for debug
248 HPEN hPen, oldPen;
249 hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); // 創建畫筆(線形,線寬,顏色)
250 oldPen = (HPEN)SelectObject(hdc, hPen); // 選擇畫筆,並保留原畫筆
251 MoveToEx(hdc, 5, 5, NULL);
252 LineTo(hdc, 10, 10);
253 }
254 *////////////////////////////////////////////////////
255
256 // 顯示數字時鐘,注意用函數FillRect擦除背景
257 void ShowTime(HDC hdc,int hour,int min,int sec){
258 PAINTSTRUCT ps;
259 RECT rect;
260 LOGBRUSH logbrush;
261 HBRUSH hBrush, oldBrush;
262 HRGN hRgn; // 區域用於區域填充、剪切、合並、反轉、畫邊框或設無效區
263
264 HDC hdc1;
265 HPEN hPen, oldPen;
266 hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); // 創建畫筆(線形,線寬,顏色)
267 oldPen = (HPEN)SelectObject(hdc1, hPen); // 選擇畫筆,並保留原畫筆
268 MoveToEx(hdc1, 5, 5, NULL);
269 LineTo(hdc1, 10, 10);
270
271 // logbrush.lbColor = RGB(255, 255, 255);
272 // logbrush.lbHatch = HS_BDIAGONAL; // 陰影樣式:HS_BDIAGONAL 對角線,HS_DIAGCROSS 對角交叉線
273 // logbrush.lbStyle = BS_HATCHED; // 畫刷樣式:BS_SOLID 實心,BS_HATCHED 陰影
274 // hBrush = (HBRUSH)CreateBrushIndirect(&logbrush);
275 hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
276 oldBrush = (HBRUSH)SelectObject(hdc, hBrush); // 選擇畫刷,並保留原畫刷
277 SelectObject(hdc, hBrush);
278 hRgn = CreateEllipticRgn(195, 35, 325, 165); // 定義區域
279 FillRgn(hdc, hRgn, hBrush); // 填充區域
280 DeleteObject(hBrush); // 刪除畫刷
281 SelectObject(hdc, oldBrush); // 恢復原畫刷
282
283 DrawClockHands(hdc, hour, min, sec);
284 return;
285 }
286
287 // 顯示時鐘函數,
288 void ShowClock(HWND hwnd){
289 int x,y,r;
290 HDC hdc = GetDC(hwnd);
291 RECT rect;
292 TCHAR buf[100];
293 SYSTEMTIME st;
294
295 //GetClientRect(hwnd,&rect);
296 rect.left = 230;
297 rect.top = 210;
298 rect.right = rect.left + 100;
299 rect.bottom = rect.top + 30;
300 GetLocalTime(&st);
301 wsprintf(buf, TEXT("%d:%d:%d\0"), st.wHour, st.wMinute, st.wSecond);
302 DrawText(hdc, buf, -1, &rect,
303 DT_SINGLELINE | DT_LEFT | DT_TOP);
304
305 ReleaseDC(hwnd, hdc);
306 return;
307 }
308
309 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
310 {
311 HDC hdc ;
312 PAINTSTRUCT ps ;
313 HPEN hPen;
314 HPEN oldPen;
315 SYSTEMTIME st;
316 switch (message)
317 {
318 case WM_CREATE:
319 PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
320 return 0 ;
321
322 case WM_PAINT:
323 hdc = BeginPaint (hwnd, &ps) ;
324 DrawClockFace(hdc); // 畫鐘
325 GetLocalTime(&st); //畫時針分針秒針
326 DrawClockHands(hdc ,st.wHour, st.wMinute, st.wSecond);
327 ShowClock(hwnd);// 當窗口重刷時顯示時間,否則停止時鐘時可能空白
328 // EndPaint(hwnd, &ps) ;
329 return 0 ;
330
331 case WM_COMMAND:
332 // LOWORD (wParam) 子窗口ID, HIWORD (wParam) 按鈕通知碼, lParam 子窗口句柄
333
334 switch (LOWORD(wParam)) //子窗口ID
335 {
336 case BUTTON1:
337 SetTimer(hwnd, TIMER_SEC, 1000, NULL); // 啟動定時器(1000毫秒一次),TIMER_SEC為自定義索引號
338 break;
339 case BUTTON2:
340 KillTimer(hwnd, TIMER_SEC); // 刪除定時器
341 break;
342 }
343 return 0;
344
345 case WM_TIMER:
346 switch (wParam)
347 {
348 case TIMER_SEC:
349 ShowClock(hwnd);//每秒一次的處理
350 InvalidateRgn(hwnd, NULL, 1); // 使區域無效
351 // ShowTime1(hdc);
352 ShowTime(hdc, st.wHour, st.wMinute, st.wSecond);
353
354 break;
355 case TIMER_MIN: //每分鐘一次的處理
356 break;
357 }
358 return 0;
359 case WM_DESTROY:
360 PostQuitMessage (0) ;
361 return 0 ;
362 }
363 return DefWindowProc (hwnd, message, wParam, lParam) ;
364 }
View Code