二、Windows自己的窗口—消息循环
呼叫UpdateWindow之后,窗口就出现在视讯显示器上。程序现在必须准备读入使用者用键盘和鼠标输入的数据。Windows为当前执行的每个Windows程序维护一个「消息队列」。在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中。
程序通过执行一块称之为「消息循环」的程序代码从消息队列中取出消息:
while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; }
msg变量是型态为MSG的结构,型态MSG在WINUSER.H中定义如下:
typedef struct tagMSG { HWND hwnd ; UINT message ; WPARAM wParam ; LPARAM lParam ; DWORD time ; POINT pt ; } MSG, * PMSG ;
POINT数据型态也是一个结构,它在WINDEF.H中定义如下:
typedef struct tagPOINT { LONG x ; LONG y ; } POINT, * PPOINT;
消息循环以GetMessage呼叫开始,它从消息队列中取出一个消息:
GetMessage (&msg, NULL, 0, 0)
这一呼叫传给Windows一个指标,指向名为msg的MSG结构。第二、第三和第四个参数设定为NULL或者0,表示程序接收它自己建立的所有窗口的所有消息。Windows用从消息队列中取出的下一个消息来填充消息结构的各个字段,结构的各个字段包括:
-
hwnd 接收消息的窗口句柄。在HELLOWIN程序中,这一参数与CreateWindow传回的hwnd值相同,因为这是该程序拥有的唯一窗口。
-
message 消息标识符。这是一个数值,用以标识消息。对于每个消息,均有一个对应的标识符,这些标识符定义于Windows表头文件(其中大多数在WINUSER.H中),以前缀WM(「window message」,窗口消息)开头。例如,使用者将鼠标光标放在HELLOWIN显示区域之内,并按下鼠标左按钮,Windows就在消息队列中放入一个消息,该消息的message字段等于WM_LBUTTONDOWN。这是一个常数,其值为0x0201。
-
wParam 一个32位的「message parameter(消息参数)」,其含义和数值根据消息的不同而不同。
-
lParam 一个32位的消息参数,其值与消息有关。
-
time 消息放入消息队列中的时间。
-
pt 消息放入消息队列时的鼠标坐标。
只要从消息队列中取出消息的message字段不为WM_QUIT(其值为0x0012),GetMessage就传回一个非零值。WM_QUIT消息将导致GetMessage传回0。
叙述
TranslateMessage (&msg) ;
将msg结构传给Windows,进行一些键盘转换。(关于这一点,我们将在第六章中深入讨论。)
叙述
DispatchMessage (&msg) ;
又将msg结构回传给Windows。然后,Windows将该消息发送给适当的窗口消息处理程序,让它进行处理。这也就是说,Windows将呼叫窗口消息处理程序。在HELLOWIN中,这个窗口消息处理程序就是WndProe函数。处理完消息之后,WndProc传回到Windows。此时,Windows还停留在DispatchMessage呼叫中。在结束DispatchMessage呼叫的处理之后,Windows回到HELLOWIN,并且接着从下一个GetMessage呼叫开始消息循环。