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