用Window API编写的定时器程序

Posted: 九月 20th, 2009 | Views: 1,642 次浏览 | 4 Comments »

这是一个用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,程序运行界面如下:

PSCountdown主界面

PSCountdown主界面

在右上的文件框中输入要等待的时间,数值范围为:1~60,单位为分钟,输入完成后点击“apply”按钮,这时程序会最小化到屏幕右下脚托盘区,点击托盘图标可以呼出主界面查看剩余时间或重新设定时间。时间归零后屏幕右下脚出现汽球提示如下图,单击提示退出程序。

PSCountdown定时器提醒界面

PSCountdown定时器提醒界面

完整程序如下:

#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;
}

点击下载完整程序和可执行文件

对于程序需要改进的地方欢迎大家跟帖留言。

Filed under: 学习分享 | Tags: ,

4 Comments on “用Window API编写的定时器程序”

  1. 匿名 说:

    如果同意 我的QQ:783830321 E-MAIL:ASTONISH1@126.COM

  2. 匿名 说:

    哥们 我们也想做 灭火机器人 能 提供些资料吗 谢谢

  3. V 说:

    很生活化很实用~~
    来膜拜下、、、
    .”". .”",
    | | / /
    | | / /
    | | / /
    | |/ ;-._
    } ` _/ / ;
    | /` ) / /
    | / /_/\_/\
    |/ / |
    ( ‘ \ ‘- |
    \ `. /
    | |
    | |


Leave a Reply

  • Name
  • Mail (will not be published)
  • Website
Page 1 of 0