Windows下编程--模拟时钟的实现
时间:2022-06-09
本文章向大家介绍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 "), 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 }
- Java常用类(四)之数组工具类Arrays
- java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.isAsyncStarted()Z 的解决
- JS魔法堂:定义页面的Dispose方法——[before]unload事件启示录
- HashSet/HashMap详解
- Ajax大显身手
- bash编程之xargs实用技巧
- 表单验证和正则表达式
- ELK日志系统:Elasticsearch + Logstash + Kibana 搭建教程
- 兰花协议—让世界自由的互联网
- Git(二)Git几个区的关系与Git和GitHub的关联
- maven/gradle 打包后自动上传到nexus仓库
- bash/shell编程学习(1)
- Git(一)之基本操作详解
- JavaScript中的函数基础
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法