要说除了鼠标、键盘消息之外,还有什么消息最重要。我想大概是就是定时器了。这定时器可长可短,如果是短定时器的话,那么就可以形成动画,记录成视频。如果是长定时器的话,那么就是普通的定时时间,代码按时进行处理就好了。举个例子来说,大家熟悉的tcp/ip网络看起来复杂,其实深究下去也就是状态机、定时器、校验码、出错重传、拥塞控制这些基本构件,其中定时器就发挥了巨大的作用。
要说在win32上怎么使用定时器,其实也不难,主要是SetTimer和KillTimer这两个函数。SetTimer有四个参数,第一参数是窗口句柄,第二个参数是timer的id好,这个可以自己设置,第三个参数是定时时间,第四个是定时器的回调函数,如果此函数没有,那么os会给窗口发送一个WM_TIMER的消息。KillTimer就更简单了,它有两个参数,第一个参数是窗口句柄,第二个参数就是timer的id号。SetTimer是开启定时器,KillTimer是关闭定时器。如果没有调用KillTimer的话,那么WM_TIMER消息就会定时发送一遍。
所以,了解了定时器的基本函数之后,我们就明白定时器基本的处理逻辑是这样的,
case WM_CREATE:
SetTimer(hWnd, 5000, 2000, NULL);
break;
case WM_TIMER:
KillTimer(hWnd, 5000);
MessageBox(NULL,"timer", "tips", NULL);
break;
当然,利用定时器弹出窗口,这本身没有什么创意。我们可以做一点有意思的代码。比如说,我们可以利用定时器定时在app打印出数据出来,比如说打印出一个不断在变化的数字就可以了,所以首先我们把定时器修改一下,
case WM_CREATE:
SetTimer(hWnd, 5000, 1000, NULL);
break;
case WM_TIMER:
InvalidateRect(hWnd, NULL, 0);
break;
大家可以看一下这里修改后的代码,首先定时的时间也变短了,从2s变成了1s。其次,代码删除了KillTimer的动作,这样可以保证timer一直执行下去,达到我们不断输出新数字的目的。接着,就该修改一下WM_PAINT下面的代码了,
case WM_PAINT:
g_text += 1;
buffer[9] = '\0';
_snprintf(buffer, 10, "%d", g_text);
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);
DrawText(hdc, buffer, strlen(buffer), &rt, DT_CENTER);
EndPaint(hWnd, &ps);
break;
大家发现,我们每次需要重新绘图的时候,都是调用InvalidateRect来完成的。通过这个function,os就会给app发送WM_PAINT消息,我们自己需要做的就是处理这个消息就可以了。注意,这里的g_text是一个全局变量,_snprintf的工作则是将数字变成字符串,最后调用DrawText将字符串输出到屏幕上,这样整个工作基本上就完成了。