用Window API编写的定时器程序
这是一个用Window API编写的小程序,主要功能是倒计时提醒。通过设定倒计时间,待时间归零后通过托盘汽球提示提醒。学习了Window的消息处理机制、对话框按钮的窗口机制以及Win32的托盘程序编程。
程序由来
有时候煤气灶炖东西、洗衣机放水都需要一段等待时间,这时候去做其它事情很容易忘记时间,引发汤锅溢出、浪费水资源。以前在广告上看过一款水果定时器,是机械式的,只要根据时间长短一拧,就能在时间到了的时候发出声音提醒,很好、很方便,可是那是要钱的。根据自身经验,一般在家务无人值守时间经常是在电脑前,遂想找一款定时器程序。网上一般有两种,设定一个时间进行提醒,这种太麻烦了;还要一种就是倒计时提醒,正是我需要的,但网上的一般都不完善,而且用对话框弹出挺吓人的,没办法只能自己做一个了。另外还可以用这个工具来掐广告时间,对于一边看电视,一边玩电脑的朋友再好不过了。
设计思路
小巧、方便,这是小工具开发的一般要求,想了很多方案也拿出来晒晒。前阵子学了一段时间的GTK+编程,本来想做它来做,但这需要安装GTK+动态库,不方便用户使用,而且也用不着在Linux下使用(Linux下可以用很多脚本语言实现:Bash、Paython、Perl),还是考虑用MFC开发吧。但VC6的SDK老了点,不支持托盘程序编写,还要升级SDK,遂考虑用Win API来实现,反正程序也不大,而且与GTK+编程有点类似,另外也可以保证程序纯绿色产品,不用额外安装其它组件。开发环境用的是MinSYS+MinGW最新版的,里机的SDK支持托盘程序的开发,也是我比较喜欢的开发方式:C+VIM+GCC。
一开始考虑程序可以支持快捷操作,如设定几个常用定时按钮:1min、5min、10min、30min、60min等,这样直接一点就可以启动定时器了;用滑块来设定时间,用鼠标直接点击拖动就可以设定时间,都不用键盘输入;可以设定倒计时的时、分、秒;可以设定多组定时器,而且可以设定每组定时器的提醒内容等,便这一切都会大大的增加程序的复杂性、体积,显示功能累赘,在一系列比较、思想斗争后选定了最终方案。一个程序只能设定一组定时器,如果您需要多组那么可以开多个程序;定时时间限定在60分钟以内,这可以减少程序对输入数据的有限性验证有数据溢出的麻烦,如果超过一小时请使用更专业的软件;取消提醒内容设定,理由同上;用户交互只使用一个文本框和一个按钮,简化API程序开发。
使用方法
可执行文件总共24.1KB,运行时占用内存3.6MB,程序运行界面如下:
在右上的文件框中输入要等待的时间,数值范围为:1~60,单位为分钟,输入完成后点击“apply”按钮,这时程序会最小化到屏幕右下脚托盘区,点击托盘图标可以呼出主界面查看剩余时间或重新设定时间。时间归零后屏幕右下脚出现汽球提示如下图,单击提示退出程序。
完整程序如下:
#define _WIN32_IE 0x0600 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #include <time.h> #define ID_TIMER 1 #define ID_APPLY 2002 #define ID_HIDE 2003 #define ID_ICON 2005 HWND hwnd; HWND hwnd_apply; HWND hwnd_min; HWND hwnd_rest; HWND hwnd_current; HWND hwnd_tips; NOTIFYICONDATA nd; int RestTime = 0; char szAppName[] = "PSCountdown"; void ShowNotify(void) { nd.uFlags |= NIF_INFO; strcpy(nd.szInfoTitle, "PSCountdown"); strcpy(nd.szInfo, "Setting Time Count Down!!!"); Shell_NotifyIcon(NIM_MODIFY, &nd); } void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) { char m_str[30] = {0}; SYSTEMTIME SysTime; if (RestTime > 0) { RestTime--; sprintf(m_str, "Rest Seconds: %d", RestTime); SetWindowText(hwnd_rest, m_str); if(RestTime <= 0)ShowNotify(); } GetLocalTime(&SysTime); sprintf(m_str, "Current Time: %02d:%02d:%02d", SysTime.wHour, SysTime.wMinute, SysTime.wSecond); SetWindowText(hwnd_current, m_str); return; } void SetRestTime(void) { int setime = 0; char m_time[3] = {0}; GetWindowText(hwnd_min, m_time, 3); setime = atoi(m_time); if(setime>60 || setime<=0) MessageBox(hwnd, "Setting Time must be 1~60 min!", "Warning", 0); else RestTime = setime * 60; } void QuitWin(void) { Shell_NotifyIcon(NIM_DELETE, &nd); PostQuitMessage(0); } void IconNotifyProc(LPARAM lParam) { switch(lParam) { case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: ShowWindow(hwnd, SW_NORMAL); break; case 0x404: case 0x405: QuitWin(); break; default: break; } } LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { case WM_COMMAND: switch(wParam) { case ID_APPLY: SetRestTime(); ShowWindow(hwnd, SW_HIDE); break; case ID_ICON: IconNotifyProc(lParam); break; default: break; } break; case WM_SYSCOMMAND: if(wParam == SC_MINIMIZE) { ShowWindow(hwnd, SW_HIDE); return 0; } break; case WM_DESTROY: QuitWin(); return 0; } return DefWindowProc(hwnd, iMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) { MSG msg; WNDCLASSEX wc; DWORD style; wc.cbSize = sizeof(wc); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_INFORMATION); wc.hIconSm = LoadIcon(NULL, IDI_INFORMATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND; wc.lpszClassName = szAppName; wc.lpszMenuName = NULL; RegisterClassEx(&wc); style = WS_OVERLAPPEDWINDOW; style &= ~(WS_MAXIMIZEBOX | WS_SIZEBOX); hwnd = CreateWindow(szAppName, "PSCountdown - By stars_625", style, CW_USEDEFAULT, CW_USEDEFAULT, 320, 240, NULL, NULL, hInstance, NULL); hwnd_apply = CreateWindow("BUTTON", "apply", WS_VISIBLE | WS_CHILD | BS_FLAT, 230, 90, 50, 20, hwnd, (HMENU)ID_APPLY, hInstance, NULL); hwnd_min = CreateWindow("EDIT", "3", WS_CHILD | WS_VISIBLE | WS_BORDER, 230, 40, 50, 20, hwnd, NULL, hInstance, NULL); hwnd_rest = CreateWindow("STATIC", "Rest Seconds:", WS_CHILD | WS_VISIBLE, 20, 90, 180, 20, hwnd, NULL, hInstance, NULL); hwnd_current = CreateWindow("STATIC", "Current Time:", WS_CHILD | WS_VISIBLE, 20, 40, 180, 20, hwnd, NULL, hInstance, NULL); hwnd_tips = CreateWindow("STATIC", "http://www.stars625.com/pscountdown.html", WS_CHILD | WS_VISIBLE, 10, 150, 290, 20, hwnd, NULL, hInstance, NULL); /* Create tray icon */ nd.cbSize = sizeof (NOTIFYICONDATA); nd.hWnd = hwnd; nd.uID = ID_ICON; nd.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nd.hIcon = LoadIcon(NULL, IDI_INFORMATION); nd.uCallbackMessage = WM_COMMAND; strcpy(nd.szTip, "PSCountdown - A Time Count Down"); Shell_NotifyIcon(NIM_ADD, &nd); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); SetTimer(hwnd, ID_TIMER, 1000, TimerProc); while ( GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
对于程序需要改进的地方欢迎大家跟帖留言。


如果同意 我的QQ:783830321 E-MAIL:ASTONISH1@126.COM
哥们 我们也想做 灭火机器人 能 提供些资料吗 谢谢
所有资料已公存在博客上了http://www.stars625.com/tag/firefighter
很生活化很实用~~
来膜拜下、、、
.”". .”",
| | / /
| | / /
| | / /
| |/ ;-._
} ` _/ / ;
| /` ) / /
| / /_/\_/\
|/ / |
( ‘ \ ‘- |
\ `. /
| |
| |