窗口的生命周期(详细说明请看图1-6)
1. 程序初始化过程中调用CreateWindow,为程序建立了一个窗口,做为程序的屏幕舞台。CreateWindow 产生窗口之后会送出WM_CREATE直接给窗口函数,后者于是可以在此时机做些初始化动作(例如配置内存、开文件、读初始数据...)。
2. 程序活着的过程中,不断以GetMessage从消息贮列中抓取消息。如果这个消息是WM_QUIT,GetMessage 会传回0而结束while循环,进而结束整个程序。
3. DispatchMessage 通过Windows USER 模块的协助与监督,把消息分派至窗口函数。消息将在该处被判别并处理。
4. 程序不断进行2.和3.的动作。
5. 当使用者按下系统菜单中的Close命令项,系统送出WM_CLOSE。通常程序的窗口函数不栏截此消息,于是DefWindowProc 处理它。
6. DefWindowProc收到WM_CLOSE后 ,调用DestroyWindow 把窗口清除 。DestroyWindow 本身又会送出WM_DESTROY。
7. 程序对WM_DESTROY的标准反应是调用PostQuitMessage。
8. PostQuitMessage 没什么其它动作,就只送出WM_QUIT 消息,准备让消息循环中的GetMessage 取得,如步骤2,结束消息循环。
为什么结束一个程序复杂如斯?因为操作系统与应用程序职责不同,二者是互相合作的关系,所以必需各做各的份内事,并互以消息通知对方。如果不依据这个游戏规则,可能就会有麻烦产生。你可以作一个小实验,在窗口函数中拦截 WM_DESTROY,但不调用 PostQuitMessage。你会发现当选择系统菜单中的 Close时,屏幕上这个窗口消失了,(因为窗口摧毁及数据结构的释放是 DefWindowProc 调用 DestroyWindow完成的),但是应用程序本身并没有结束(因为消息循环结束不了),它还留存在内存中。
闲置时间的处理:OnIdle
所谓闲置时间(idle time),是指「系统中没有任何消息等待处理」的时间。举个例子,没有任何程序使用定时器(timer,它会定时送来 WM_TIMER),使用者也没有碰触键盘和鼠标或任何外围,那么,系统就处于所谓的闲置时间。
闲置时间常常发生。不要认为你移动鼠标时产生一大堆的 WM_MOUSEMOVE,事实上夹杂在每一个WM_MOUSEMOVE之间就可能存在许多闲置时间。毕竟,计算机速度超乎想像。
后台工作最适宜在闲置时间完成。传统的 SDK 程序如果要处理闲置时间,可以以下列循环取代 WinMain 中传统的消息循环:
while (TRUE) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) {
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
OnIdle();
}
}