C、C++
以下是我阅读MSDN关于消息处理主题的文章的随手做的笔记,拿出来和大家分享,有兴趣的朋友一起讨论吧:
一、WINDOWS的消息(Windows Messages)
操作系统将输入信息以消息的形式传送给窗口过程(WINDOW PROCEDURE)。(操作)系统和应用程序均可以产生消息。每当有输入产生的时候,例如:用户敲击键盘、移动鼠标或者是电击SCROLL BAR的时候,操作系统都将产生输入的事件(EVENT),操作系统也将应用程序造成的系统的改变产生消息,例如:当应用程序改变系统字体资源池或者RESIZE它自己所属的窗口。而应用程序可以通过产生消息指引自己的窗口去完成指定定的任务或者和其它应用程序的WINDOW通讯。
操作系统发送消息的时候用到四个参数:WINDOW句柄(window handle),消息标识(message identifier),和两个消息参数(message parameter)。
WINDOW句柄----指定了消息要发送到那个窗口。
消息标识-----一个预定义的常量,用于决定如何处理消息。
消息参数(两个)-----它们的含义又上面的两个参数的内容决定,不同的窗口和消息标识对这两个参数有不同的解释,例如:是指定的数据或者是数据指针等等。
二、消息的类型(message type)
1、系统定义的消息
每个系统消息都有一个唯一的消息ID和指定消息的作用的标识的常量(字符标识,在SDK的头文件中定义)。例如:WM_PAINT常量要求窗口画它的内容。
标识常量的的前缀指明了那种类型的窗口可以解释和处理该消息。以下是前缀与窗口类型的对应:
Prefix Message category
ABM Application desktop toolbar
BM Button control
CB Combo box control
CBEM Extended combo box control
CDM Common dialog box
DBT Device
DL Drag list box
DM Default push button control
DTM Date and time picker control
EM Edit control
HDM Header control
HKM Hot key control
IPM IP address control
LB List box control
LVM List view control
MCM Month calendar control
PBM Progress bar
PGM Pager control
PSM Property sheet
RB Rebar control
SB Status bar window
SBM Scroll bar control
STM Static control
TB Toolbar
TBM Trackbar
TCM Tab control
TTM Tooltip control
TVM Tree-view control
UDM Up-down control
WM General window
General window的消息覆盖的范围非常广。
2、应用程序定义的消息
接收到应用程序自定义的消息的窗口必须能够解释应用程序的自定义消息,并且能够处理它。
消息标识(message identifier)的值必须符合以下的条件:
1)、0x0000---0x03FF被系统保留。
2)、0x0400---0x7FFF可应用于私有的WINDOW CLASS。
3)、如果你的应用程序的版本是4.0,你可以使用0x8000---0xBFFF(WM_APP)为私有的消息。
4)、当应用程序使用RegisterWindowMessage函数登记一个消息的时候,操作系统返回的位于0xC000到0xFFFF之间的消息标识。这样的消息标识可以保证是系统唯一的消息标识 。
三、消息的路由(message routing)
操作系统分发message到窗口过程(window procedure)的时候有两种方法:
1)、post----消息发送到一个先进先出的消息队列中。这些消息称为排队消息(queue message),多半来自用户的鼠标或键盘输入例如 WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN, 和 WM_CHAR 等。
2)、send----消息被直接发送到窗口过程中,称为非排队消息(nonqueue messages)。
1、排队消息
通过消息队列,操作系统发送消息到相应的窗口。
操作系统自己拥有一个消息队列,每个GUI线程都有自己的消息队列。每个队列在刚建立的时候都没有自己消息队列,当线程第一次调用WIN32 USER或GDI函数的时候,系统为线程创建消息队列。
用户的输入(鼠标或键盘)被驱动程序捕获后,驱动程序产生相应的消息并放到系统的消息队列。系统每次从队列中取得一条消息,并将消息从队列中删除,将消息发送到相应线程的消息队列中,该线程再将消息发送到对应的窗口过程处理。
除WM_PAINT外,所有的消息都被发送到系统消息队列的末尾。WM_PAINT只有在队列中没有其它的消息的时候才发送到窗口过程,否则,它(WM_PAINT)将一直放在队列中,当此时又有新的WM_PAINT发送到队列中时,两个WM_PAINT将被合并为一个消息,它们的更新区域自然也合并了,这样就减少了窗口更新的次数。
消息队列中放置的消息是以MSG结构的形式存在,MSG包括:窗口句柄、消息标识、消息的两个参数(WPARAM和LPARAM)、消息发送(POST)的时间以及鼠标的位置。
GetMessage函数将消息从队列中删除,而PeekMessage则只查看消息而并不删除消息。
DispatchMessage负责分发系统的消息到窗口过程。分发的过程中并不传送消息发送的时间和鼠标的位置,应用程序可以在处理消息的时候,通过GetMessageTime和GetMessagePos函数可以取得相应的时间和位置。
线程通过WaitMessage函数将控制权让给其它的线程,并suspend本线程,直到有新的消息发送到本线程的队列中。
用户可以调用SetMessageExtraInfo函数将一个值关联(associate)到当前线程的消息队列中。然后,可以通过GetMessageExtraInfo函数取得在队列中最近取得的消息关联的值(就是上面所附加的)。
2、非队列消息(Nonequeue Messages)
非队列消息不经过消息队列而直接发送到窗口过程。通常是窗口的通报消息(Notify),例如:WM_ACTIVATE,WM_SETFOCUS,WM_SETCURSOR。
调用一些系统函数也可能导致非队列消息的产生,如:调用SetWindowPos函数后,操作系统会向窗口发送这样一个 消息:WM_WINDOWPOSCHANGED。
一、WINDOWS的消息(Windows Messages)
操作系统将输入信息以消息的形式传送给窗口过程(WINDOW PROCEDURE)。(操作)系统和应用程序均可以产生消息。每当有输入产生的时候,例如:用户敲击键盘、移动鼠标或者是电击SCROLL BAR的时候,操作系统都将产生输入的事件(EVENT),操作系统也将应用程序造成的系统的改变产生消息,例如:当应用程序改变系统字体资源池或者RESIZE它自己所属的窗口。而应用程序可以通过产生消息指引自己的窗口去完成指定定的任务或者和其它应用程序的WINDOW通讯。
操作系统发送消息的时候用到四个参数:WINDOW句柄(window handle),消息标识(message identifier),和两个消息参数(message parameter)。
WINDOW句柄----指定了消息要发送到那个窗口。
消息标识-----一个预定义的常量,用于决定如何处理消息。
消息参数(两个)-----它们的含义又上面的两个参数的内容决定,不同的窗口和消息标识对这两个参数有不同的解释,例如:是指定的数据或者是数据指针等等。
二、消息的类型(message type)
1、系统定义的消息
每个系统消息都有一个唯一的消息ID和指定消息的作用的标识的常量(字符标识,在SDK的头文件中定义)。例如:WM_PAINT常量要求窗口画它的内容。
标识常量的的前缀指明了那种类型的窗口可以解释和处理该消息。以下是前缀与窗口类型的对应:
Prefix Message category
ABM Application desktop toolbar
BM Button control
CB Combo box control
CBEM Extended combo box control
CDM Common dialog box
DBT Device
DL Drag list box
DM Default push button control
DTM Date and time picker control
EM Edit control
HDM Header control
HKM Hot key control
IPM IP address control
LB List box control
LVM List view control
MCM Month calendar control
PBM Progress bar
PGM Pager control
PSM Property sheet
RB Rebar control
SB Status bar window
SBM Scroll bar control
STM Static control
TB Toolbar
TBM Trackbar
TCM Tab control
TTM Tooltip control
TVM Tree-view control
UDM Up-down control
WM General window
General window的消息覆盖的范围非常广。
2、应用程序定义的消息
接收到应用程序自定义的消息的窗口必须能够解释应用程序的自定义消息,并且能够处理它。
消息标识(message identifier)的值必须符合以下的条件:
1)、0x0000---0x03FF被系统保留。
2)、0x0400---0x7FFF可应用于私有的WINDOW CLASS。
3)、如果你的应用程序的版本是4.0,你可以使用0x8000---0xBFFF(WM_APP)为私有的消息。
4)、当应用程序使用RegisterWindowMessage函数登记一个消息的时候,操作系统返回的位于0xC000到0xFFFF之间的消息标识。这样的消息标识可以保证是系统唯一的消息标识 。
三、消息的路由(message routing)
操作系统分发message到窗口过程(window procedure)的时候有两种方法:
1)、post----消息发送到一个先进先出的消息队列中。这些消息称为排队消息(queue message),多半来自用户的鼠标或键盘输入例如 WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN, 和 WM_CHAR 等。
2)、send----消息被直接发送到窗口过程中,称为非排队消息(nonqueue messages)。
1、排队消息
通过消息队列,操作系统发送消息到相应的窗口。
操作系统自己拥有一个消息队列,每个GUI线程都有自己的消息队列。每个队列在刚建立的时候都没有自己消息队列,当线程第一次调用WIN32 USER或GDI函数的时候,系统为线程创建消息队列。
用户的输入(鼠标或键盘)被驱动程序捕获后,驱动程序产生相应的消息并放到系统的消息队列。系统每次从队列中取得一条消息,并将消息从队列中删除,将消息发送到相应线程的消息队列中,该线程再将消息发送到对应的窗口过程处理。
除WM_PAINT外,所有的消息都被发送到系统消息队列的末尾。WM_PAINT只有在队列中没有其它的消息的时候才发送到窗口过程,否则,它(WM_PAINT)将一直放在队列中,当此时又有新的WM_PAINT发送到队列中时,两个WM_PAINT将被合并为一个消息,它们的更新区域自然也合并了,这样就减少了窗口更新的次数。
消息队列中放置的消息是以MSG结构的形式存在,MSG包括:窗口句柄、消息标识、消息的两个参数(WPARAM和LPARAM)、消息发送(POST)的时间以及鼠标的位置。
GetMessage函数将消息从队列中删除,而PeekMessage则只查看消息而并不删除消息。
DispatchMessage负责分发系统的消息到窗口过程。分发的过程中并不传送消息发送的时间和鼠标的位置,应用程序可以在处理消息的时候,通过GetMessageTime和GetMessagePos函数可以取得相应的时间和位置。
线程通过WaitMessage函数将控制权让给其它的线程,并suspend本线程,直到有新的消息发送到本线程的队列中。
用户可以调用SetMessageExtraInfo函数将一个值关联(associate)到当前线程的消息队列中。然后,可以通过GetMessageExtraInfo函数取得在队列中最近取得的消息关联的值(就是上面所附加的)。
2、非队列消息(Nonequeue Messages)
非队列消息不经过消息队列而直接发送到窗口过程。通常是窗口的通报消息(Notify),例如:WM_ACTIVATE,WM_SETFOCUS,WM_SETCURSOR。
调用一些系统函数也可能导致非队列消息的产生,如:调用SetWindowPos函数后,操作系统会向窗口发送这样一个 消息:WM_WINDOWPOSCHANGED。