在Windows中,不仅用户程序可以调用系统的API函数,系统也会调用用户程序,这个调用是通过消息来进行的。wParam和lParam表示的信息随消息的不同而不同。
每一个Windows应用程序开始执行后,系统都会为该程序创建一个消息队列,这个消息队列用来存放该程序创建的窗口消息。
Windows程序中的消息分为进队消息和不进队消息。进队消息将由系统放入到应用程序的消息队列中,然后由应用程序取出并发送。不进队消息在系统调用窗口过程时直接发送给窗口。不管进队消息还是不进队消息,最终都由系统调用窗口过程函数对消息进行处理。
创建一个完整的窗口步骤:设计窗口类、注册窗口类、创建窗口、显示及更新窗口。当窗口发生重绘时,窗口中的文字和图形将被擦除。
窗口过程函数是一个回调函数。回调函数不是由函数的实现方直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应。回调函数的实现机制是:
(1)定义一个回调函数。
(2)提供函数实现的一方在初始化的时候,将回调函数的指针注册给调用者。
(3)当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
一个Windows程序可以包含多个窗口过程函数,一个窗口过程总是与某一个特定的窗口类相关联,基于该窗口类创建的窗口使用同一个窗口函数。
GetMessage函数接收到除WM_QUIT外的消息均返回非零值。对于WM_QUIT消息,该函数返回0。如果出现错误,该函数返回-1。
TranslateMessage函数用于将虚拟键消息转换为字符消息。字符消息被投递到调用线程,当下一次调用GetMessage时被取出。TranslateMessage函数并不会修改原有的消息,它只是产生新的消息并投递到消息队列中。
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
Windows应用程序的消息处理机制如图:
(1)操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。
(2)应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条消息。取出消息后,应用程序可以对消息进行一些预处理,例如,放弃对某些消息的响应或调用TranslateMessage产生新的消息。
(3)应用程序调用DispatchMessage,将消息回传给操作系统。
(4)系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理(即“系统给应用程序发送了消息”)。
从消息队列中获取消息还可以调用PeekMessage函数。发送消息可以使用SendMessage和PostMessage。SendMessage将消息直接发送给窗口,并调用窗口过程进行处理。在窗口过程对消息处理完毕后,该函数才返回(SendMessage发送的消息为不进队消息)。PostMessage将消息放入与创建窗口的线程相关联的消息队列后立即返回。此外,PostThreadMessage用于向线程发送消息。对于线程消息,MSG结构体中的hwnd为NULL。