定时器的用法

时间:2022-03-04 23:25:13

使用定时器需要用到如下几个函数:
1.设置定时器函数

//如果第四个参数为NULL则系统发送一个WM_TIMER消息到应用程序队列
//如果第一个参数为0 则第二个参数忽略 一般为0
//返回定时器ID,返回0表示失败
UINT SetTimer(
  HWND hWnd,     //窗口句柄
  UINT nIDEvent, //定时器ID 
  UINT uElapse,  //定时时间
  TIMERPROC lpTimerFunc //时间过程函数
); 

2.时间过程函数

void CALLBACK TimerProc(
  HWND hwnd,    //窗口句柄
  UINT uMsg,   //指定的WM_TIMER消息
  UINT idEvent, //定时器ID
  DWORD dwTime  //从GetTickCount函数返回的值
); 

3.关掉定时器

//非0表示成功 0表示失败
BOOL KillTimer(
  HWND hWnd,    
  UINT uIDEvent  //定时器ID
); 

注意:WM_TIMER消息并不是异步的,而是正常的队列消息,也需要排队,所以当消息队列拥挤的时候,比如你
设置定时器为1秒发送一次WM_TIMER消息,但是当队列中还有消息在排队的时候,程序是收不到WM_TIMER消息的。

使用定时器的三种方法:

  1. 将WM_TIMER发送到对应的程序窗口过程

    //当前程序的窗口句柄
    //定时器ID为1
    //时间间隔为1秒
    //无时间过程函数
    SetTimer(hwnd,1,1000,NULL);

    //你可以在任何地方关掉定时器,如果想使用一次性定时器就
    //在WM_TIMER消息中关掉定时器,否则在WM_DESTROY消息中关掉
    //第二个参数是要关掉的定时器ID
    KillTimer(hwnd,1);

    在WM_TIMER消息中,wParam等于定时器的ID,lParam是0

例如:

#define TIMER_1 1
#define TIMER_2 2
[其它代码]

case WM_CREATE:
        //定时器1
        SetTimer(hwnd, TIMER_1, 7000, nullptr);
        //定时器2
        SetTimer(hwnd, TIMER_2, 3000, nullptr);
        return 0;
[其他代码]


case WM_TIMER:

        switch (wParam)
        {
        case TIMER_1:
            MessageBox(hwnd, L"定时器1被触发了", L"", 0);
            break;
        case TIMER_2:
            MessageBox(hwnd, L"定时器2被触发了", L"", 0);
            break;
        default:
            break;
        }

        return 0;

[其他代码]

case WM_DESTROY:
        //关掉定时器1、2
        KillTimer(hwnd, TIMER_1);
        KillTimer(hwnd, TIMER_2);
        PostQuitMessage(0);
        return 0;
[其他代码]

2.设置一个回调函数来处理WM_TIMER消息

SetTimer(hwnd,1,1000,TimerProc);

KillTimer(hwnd,1);

例如:

case WM_CREATE:
        //定时器1
        SetTimer(hwnd, TIMER_1, 7000, TimerProc);
        //定时器2
        SetTimer(hwnd, TIMER_2, 3000, TimerProc);
        return 0;
[其他代码]

case WM_DESTROY:
        //关掉定时器1、2
        KillTimer(hwnd, TIMER_1);
        KillTimer(hwnd, TIMER_2);
        PostQuitMessage(0);
        return 0;
[其他代码]
.
.
.

//时间过程函数
//这个函数只处理WM_TIMER消息
void CALLBACK TimerProc(
    HWND hwnd,    //窗口句柄
    UINT uMsg,   //指定的WM_TIMER消息
    UINT idEvent, //定时器ID
    DWORD dwTime  //定时时间
    )
{
    switch (idEvent)
    {
    case TIMER_1:
        MessageBox(hwnd, L"定时器1被触发了", L"", 0);
        break;
    case TIMER_2:
        MessageBox(hwnd, L"定时器2被触发了", L"", 0);
        break;
    default:
        break;
    }
}

3.把第一个参数设置为NULL,第二个设置为0,返回值为定时器ID

//如果函数返回0表示没有可用的定时器,这个可能性非常低
iTimerID=SetTimer(NULL,0,1000,TimerProc);

//定时器必须这样关掉
KillTimer(NULL,iTimerID);

获取时间:

//获取当前时间
void GetLocalTime( 
  LPSYSTEMTIME lpSystemTime 
); 
void GetSystemTime( 
  LPSYSTEMTIME lpSystemTime 
); 
//一个是本地时间,一个是协调世界时(UTC)

//系统时间信息结构

typedef struct _SYSTEMTIME { 
  WORD wYear;     //当前年份
  WORD wMonth;    //当前月份
  WORD wDayOfWeek;//当前星期 Sunday=0 
  WORD wDay;      //当前月的第几天
  WORD wHour;     //当前的时间
  WORD wMinute; 
  WORD wSecond; 
  WORD wMilliseconds; 
} SYSTEMTIME;

例如:

//时间过程函数
//这个函数只处理WM_TIMER消息
void CALLBACK TimerProc(
    HWND hwnd,    //窗口句柄
    UINT uMsg,   //指定的WM_TIMER消息
    UINT idEvent, //定时器ID
    DWORD dwTime  //定时时间
    )
{
    //时间信息结构
    SYSTEMTIME st = { 0 };
    //获取时间信息
    GetLocalTime(&st);
    //打印时间信息
    MessageBoxPrintf(L"", L"现在是%d-%d-%d-%d-%d-%d-%d-%d", st.wYear,st.wMonth,st.wDay,st.wDayOfWeek,
        st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
}

如图:

定时器的用法