云顶娱乐平台 20

【云顶娱乐平台】关于windows操作系统之消息和消息队列

这个窗口所属的进程PID =
0xc54,正好是excel的进程,说明ShellExecuteEx确实发送了DDE消息给excel,而且可执发送的消息的thread就是主线程

4 队列消息(Queued Messages)和非队列消息(Non-Queued Messages)
1)队列消息(Queued Messages)
 
消息会先保存在消息队列中,消息循环会从此队列中取消息并分发到各窗口处理
如鼠标,键盘消息。
2) 非队列消息(NonQueued Messages) 消息会绕过系统消息队列和线程消息队列直接发送到窗口过程被处理
如: WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR, WM_WINDOWPOSCHANGED 
注意: postMessage发送的消息是队列消息,它会把消息Post到消息队列中;
SendMessage发送的消息是非队列消息, 被直接送到窗口过程处理

WM_MOUSEHOVER = 673

非消息队列方式,直接调用窗口过程,系统立即切换到接收线程执行,发送线程锁住,知道接收线程处理完毕

SendMessageTimeout

云顶娱乐平台 1

1. 窗口过程 
每个窗口会有一个称为窗口过程的回调函数(WndProc),它带有四个参数,分别为:窗口句柄(Window
Handle),消息ID(Message ID),和两个消息参数(wParam,
lParam),当窗口收到消息时系统就会调用此窗口过程来处理消息。(所以叫回调函数)

当系统颜色改变时,发送此消息给所有顶级窗口

用于判断当前窗口过程所处理的消息,是否来自其他线程的SendMessage调用。

PeekMessage
1.该函数核查线程消息队列中是否有消息,并将消息放在参数结构体中
2.如果hWnd参数=-1,则只返回hWnd=NULL的消息,这种消息来自PostThreadMessage
3.参数wRemoveMsg需要注意

3.2.1
根据微软的文档可知,发送DDE消息除了WM_DDE_INITIATE和WM_DDE_ACK之外用的都是PostMessage

2 消息类型 
1) 系统定义消息(System-Defined Messages)
 
在SDK中事先定义好的消息,非用户定义的,其范围在[0x0000, 0x03ff]之间,
可以分为以下三类:
1>窗口消息(Windows Message) 
与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等。可以是一般的窗口,也可以是Dialog,控件等。
如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL…
2>命令消息(Command Message):注意这类消息通称为WM_COMMAND
与处理用户请求有关, 如单击菜单项或工具栏或控件时, 就会产生命令消息。
WM_COMMAND, LOWORD(wParam)表示菜单项,工具栏按钮或控件的ID。如果是控件,
HIWORD(wParam)表示控件消息类型
3> 控件通知(Notify Message) 
控件通知消息, 这是最灵活的消息格式, 其Message, wParam,
lParam分别为:WM_NOTIFY,
控件ID,指向NMHDR的指针。NMHDR包含控件通知的内容, 可以任意扩展。
2) 程序定义消息(Application-Defined Messages) 
用户自定义的消息, 对于其范围有如下规定:
WM_USER: 0x0400-0x7FFF    (ex. WM_USER+10)
WM_APP(winver>4.0): 0x8000-0xBFFF (ex.WM_APP+4)
RegisterWindowMessage: 0xC000-0xFFFF

WM_STYLECHANGED =125

lParam指向一个函数地址,被调用的将是这个函数,而非窗口过程

GetMessage
应用程序使用该函数返回值来决定是否终止消息循环,并退出程序。

2> 运行http_server.py(需先安装python)

9 BroadcastSystemMessage 
我们一般所接触到的消息都是发送给窗口的,其实,
消息的接收者可以是多种多样的,它可以是应用程序(applications),
可安装驱动(installable drivers),网络设备(network drivers),
系统级设备驱动(system-level device drivers)等, 
BroadcastSystemMessage这个API可以对以上系统组件发送消息。

当剪贴板包含CF_OWNERDIPLAY格式的数据并且剪贴板观察窗口的客户区域的大小已经改变是此消息通过剪贴板观察窗口发送给剪贴板的所有者;

关于windows操作系统之消息和消息队列

关于消息和消息队列
不像基于MS-DOS的应用程序,基于Windows的程序是事件驱动的。他们不做任何显示调用来获取输入。而是通过等待系统传递给他们。

系统为应用程序传递所有输入到程序中的不同窗口。每个窗口都有一个称为窗口过程的函数,用于处理所有到该窗口的输入。窗口处理过程处理输入,并将控制返回给系统。

如果一个顶层窗口停止响应消息超过两秒,系统将会认为该窗口为非响应状态。在这种情况下,系统将隐藏该窗口并用拥有同样Z顺序,位置,尺寸和可视化属性的ghost窗口替代该窗口。这种情况下,允许用户移动它,或者改变他的尺寸,甚至关闭应用程序。然后,这也是仅仅可以做的动作,因为应用程序现在是不响应的。当在调试状态下,系统不会产生ghost窗口。

这个段落,讨论如下主题:
windows消息
系统以消息的形式传递输入到窗口的处理过程。系统和应用程序均可产生消息。系统在每次输入事件时,产生一个消息,比如,当用于敲击,移动鼠标或者点击滚动条一类的控件。应用程序引起系统改变也会导致系统产生消息,比如一个应用程序改变了系统的字体资源池或者改变了他自己窗口的大小。一个应用程序可以产生这样的消息,该消息可以引导他的窗口直接执行任务或者和其他应用程序的窗口进行交互。

消息分类:
系统定义消息
当系统和应用程序交互时,系统发送系统消息,以控制应用程序的操作以及给程序传递输入或者其他消息。应用程序也可以发送系统消息,应用程序通常用这些消息来控制通过预先注册的窗口类创造的窗口的行为。

消息常量标记指定了其所属系统预定义消息种类。前缀确定可以翻译或者处理的消息种类。如下。
AMB/ABN ===application desktop toolbar
acm/acn ===animation control
cb/cbn ===combobox control
ccm ===generatl control
cdm ===common dialog box
dfm ===default contex menu
dl ===drag list box
sb ===status bar
tvm/tvn ===tree view contro
udm/udm === up-down controm
wm === general
……
tcm/tcn === tab control
{
Clipboard Messages Clipboard Notifications Common Dialog Box
Notifications Cursor Notifications Data Copy Message Desktop Window
Manager Messages Device Management Messages Dialog Box Notifications
Dynamic Data Exchange Messages Dynamic Data Exchange Notifications Hook
Notifications Keyboard Accelerator Messages Keyboard Accelerator
Notifications Keyboard Input Messages Keyboard Input Notifications Menu
Notifications Mouse Input Notifications Multiple Document Interface
Messages Raw Input Notifications Scroll Bar Notifications Timer
Notifications Window Messages Window Notifications
}

大体上,windows消息覆盖了一个比较宽的范围,包括鼠标键盘,菜单,对话框输入,窗口创建管理,DDE动态数据交换

应用程序定义的消息
应用程序可以创建消息,其自身窗口可以使用,也可以用于和其他进程进行交互。

消息标记符的值应用如下:
1.系统保留了0x0000-0x03ff(即wm_user-1),应用程序不可以使用这些值用于私有消息
2.0×0400(WM_USER)-0x7fff可以用于私有消息
3.如果应用程序在4.0系统上,你可以使用0x8000(wm_app)-0xbfff于私有消息
4.RegisterWindowMessage返回的值在0XC000-0XFFFF之间。这个函数的返回值,可以避免其他进程用同样值而引起的冲突

消息路由
使用使用两种方式来窗口过程消息的路线:post类消息是通过先进先出的消息队列方式,消息队列是临时存储消息的系统定义内存对象,以及sending类消息直接到达窗口过程。

队列消息1
系统在同一时间可以显示任意数量的窗口。为了路由鼠标键盘输入到正确的窗口,系统采用了消息队列。

系统维护了一个系统消息队列,并为每个GUI线程维护了而一个线程专有消息队列。为了避免为非GUI线程过多创建消息队列,所有线程在创建时没有消息队列。系统仅仅在线程第一次发起某个专门用户函数时,创建线程消息队列;没有GUI函数调用将引起消息队列的创建。

未懂:
The system creates a thread-specific message queue only when the thread
makes its first call to one of the specific user functions; no GUI
function calls result in the creation of a message queue.

队列消息2
任何时候,用户移动鼠标,点击按钮或者敲击键盘,鼠标或者键盘驱动将转换这些输入为消息,并将它们放到系统消息队列中。系统在检测它们的目窗口时,同时从系统消息队列中移除它们。然后将他们发送到消息相关窗口的窗口创建线程。线程从它们的消息队列中接收所有鼠标和键盘消息。线程从它们的队列中删除消息,并指引系统将它们发送到正确的窗口过程进行处理。

除了WM_PATIN,WM_TIMER,WM_QUIT消息外,系统一直将它们发送到消息队列的末尾,以确保输入消息的FIFO序列,仅当消息对用中没有其他消息事后,WM_PATIN,WM_TIMER,WM_QUIT才被向前推至窗口处理过程。再就是,多个WM_PAINT消息将被合并为一个,确定所有客户端无效区域到一个单独的区域。合并WM_PATINT就是为了减少窗口冲回客户区内容的次数。

从消息队列中删除一个消息后,应用程序将用DispatchMessage函数direct系统发送这个消息到窗口处理过程以紧凑处理。DispatchMessage没有发送消息位置和时间到窗口过程,应用程序可以通过GetmessageTime和GetMessagePos函数。

当消息队列中没有消息的时候,线程可以使用WaitMessage函数来将控制器交给其他线程,这个函数暂停线程,知道一个新消息到来,该函数才返回。

你也可以调用SetMessageExtraInfo来为当前消息队列附加一个值,通过GetMessageExtraInfo来获取这个值。

非队列消息
绕过了系统和线程消息队列,非队列消息直接发送至窗口过程。系统典型发送非队列消息来通知一个窗口,一个事件影响了它。例如,当用户激活一个新窗口,系统发送给窗口
WM_ACTIVATE, WM_SETFOCUS, and
WM_SETCURSOR消息。这些消息通知窗口它已经被激活了,键盘输入正指向该窗口,鼠标光标已经移至了窗口边框内。当应用程序调用某些系统函数时,也会窗口非队列消息,比如,应用程序在调用SetWindowPos时,系统将发送WM_WINDOWPOSCHANGED消息。

有些消息发送非队列消息:BroadcastSystemMessage,
BroadcastSystemMessageEx, SendMessage, SendMessageTimeout, and
SendNotifyMessage.

消息处理
多线程应用程序,会在每个创建了窗口的线程包含一个消息队列。

MSG msg;
BOOL bRet;

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
一个应用程序可以通过调用PostQuitMessage来结束其自身的消息循环,响应应用程序主窗口的WM_DESTROY消息,就比较典型。

PostMessage发送一个NULL窗口句柄的消息,该消息将会被放在当前线程消息队列中,应用程序必须处理这个消息。PostMessage也可以通过HWND_TOPMOST
句柄来给所有顶层窗口发送消息。

PostMessage一直能够成功发送消息,通常是一个错误的假设,比如消息队列是满的。一个应用程序应该核查PostMessage的返回值。如果失败了,需要重新发送消息。

SendMessage通常用户父子窗口之间的交互。

SendMessageCallback函数发送一个消息,并立即返回,窗口过程在处理完这个消息后,系统将调用指定的回调函数。该回调函数的具体,请看SendAsyncProc

偶尔,你可能想向所有顶层窗口发送消息。例如,应用程序改变了时间,可以通过SendMessage,并制定HWND_TOPMOST,发送WM_TIMECHANGE.你也可以通过BroadcastSystemMessage函数,并给lpdwRecipients参数制定BSN_APPLICATIONS

消息死锁
1.SendMessage会等待窗口过程处理完毕后才返回,如果窗口过程此时所在线程激昂控制权放弃,那么僵早晨死锁。
2.如果接收线程附加到了和发送线程同一个消息队列,也将导致应用程序死锁的发送

注意,正在接收消息的线程,不应该显示放弃控制权;调用下面函数将引起线程隐私放弃控制权。
DialogBox
?DialogBoxIndirect
?DialogBoxIndirectParam
?DialogBoxParam
?GetMessage
?MessageBox
?PeekMessage
?SendMessage

为了避免潜在死锁,考虑使用SendNotifyMessage或者SendMessageTimeout。要不然,窗口过程可以通过InSendMessage或者InSendMessageEx检测其接收到的消息是否来自其他线程.在处理一个消息时,在调用上面列表中任何函数前,窗口过程应该调用InSendMessage(Ex).如果返回TRUE,窗口过程必须在yeild前,调用ReplyMessage函数。

系统广播消息-略

总结:
1.消息分为系统定义消息和用户自定义消息,其ID值皆有自己的范围。
2.每个线程默认是没有消息队列的,线程只有在第一次调用用户接口时(比如创建窗口),系统才为其创建消息队列。
3.系统自身维护一个系统消息队列,然后还为每个GUI线程线程维护一个线程专门消息队列。
4.鼠标、键盘等驱动,首先将事件转换为消息放置在系统消息队列中,然后系统又通过窗口来确定将其放入到哪个线程消息队列中。
5.线程消息循环取出消息,进行处理,将消息再派发给系统,系统调用消息对应的窗口过程。
6.PostMessage不一定成功,比如队列是满的。
7.避免消息死锁,比如接收消息的窗口过程,在弃权前,需要检测消息是否发自其它线程。否则其它线程将长时间等待。其实我感觉这里不能成为死锁嘛,毕竟还是可能再执行的,只是时间长短而已。
8.需要注意wm_paint,wm_timer,wm_quit等特殊消息
9.系统预定义消息其实大都是那些控件消息,通知消息,系统广播消息等等。

 

8(消息死锁( Message Deadlocks) 
假设有线程A和B, 现在有以下下步骤
1) 线程A SendMessage给线程B, A等待消息在线程B中处理后返回
2) 线程B收到了线程A发来的消息,并进行处理, 在处理过程中,B也向线程A
SendMessgae,然后等待从A返回。
因为此时, 线程A正等待从线程B返回, 无法处理B发来的消息,
从而导致了/线程A,B相互等待, 形成死锁。多个线程也可以形成环形死锁。
可以使用 SendNotifyMessage或SendMessageTimeout来避免出现死锁。

此消息给这些空件的所有者

该函数通过调用窗口过程的方式发送消息,如果窗口属于不同线程,SendMessageTimerout将知道消息处理完毕才返回或者指定的超时已经过去,如果窗口就在当前线程,则直接调用窗口过程,并忽略time-out超时

SendNotifyMessage
如果窗口创建于属于发送消息的线程,则调用窗口过程,并等待窗口过程处理完毕该消息。如果是不同线程,则将消息传递到窗口过程,并立即返回,不等待窗口过程的消息处理过程。


TranslateMessage
1.将虚拟键消息转换为字符消息,然后将字符消息发送到调用线程的消息队列中,该字符消息将在下次调用GetMessage或者PeekMessage消息的时候获取到。
2.WM_(SYS)KEYDOWN/UP—>WM_(SYS)_CHAR
3.如果应用程序为了其他目的,处理虚拟键消息,那么就不应该调用TranslateMessage.与一个实例,应用程序不应该在TranslateAccelerator函数返回非0值时调用TranslateMessage

关于消息和消息队列
不像基于MS-DOS的应用程序,基于Windows的程序是事件驱动的。他们不做任何显示调…

云顶娱乐平台 2

6 GetMessage, PeekMessage 
PeekMessage会立即返回可以保留消息
GetMessage在有消息时返回会删除消息

当一个按钮控件将要被绘制时发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

该函数将获取和hWnd或者其子窗口相关的消息。

DWORD GetMessagePos(void);

2> 然后创建一个”WorkerW”的窗口用于DDE通信

5 PostMessage(PostThreadMessage), SendMessage 
PostMessage:把消息放到指定窗口所在的线程消息队列中后立即返回。
PostThreadMessage:把消息放到指定线程的消息队列中后立即返回。
SendMessage:直接把消息送到窗口过程处理,处理完了才返回。

message: UINT / /消息常量标识符

该函数只是简单表明被请求终止的线程将会终止。接收WM_QUIT的线程,应该终止消息循环,并将控制权交给系统。返回给系统的退出值,一定是WM_QUIT的wParam参数

BOOL PostThreadMessage(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);

接收消息的线程,通过GetMessage/PeekMessage来获取消息,hWnd成员将会是空


RegisterWindowMessage
同一字符串,注册的值,在整个系统中是唯一的


SendMessage

可知是ShellExecuteEx内部创建的线程,所以win7上ShellExecuteEx创建了一个线程专门用来处理和excel的DDE消息通信,这样就能正常的接收处理excel发过来的WM_DDE_INITIATE消息了

此消息通知某个窗口,非客户区正在销毁

如果发送消息低于WM_USER范围,到异步消息队列函数(PostMessage、SendNotifyMessage),消息参数不应该包含指针,不然的话,操作将失败。该函数将在接收线程有机会处理该消息前返回,发送者将释放刚刚用到的内存。

PostQuitMessage

5>
excel收到WM_DDE_EXECUTE消息后会广播WM_DDE_INITIATE消息,”WorkerW”窗口所在的console进程由于没有定义消息处理函数,ShellExecuteEx定义的”WorkerW”窗口消息处理函数得不到CPU执行机会,导致不会response该消息,从而导致excel
hang住

3 消息队列(Message Queues) 
Windows中有两种类型的消息队列
1) 系统消息队列(System Message Queue) 这是一个系统唯一的Queue,设备驱动(mouse,
keyboard)会把操作输入转化成消息存在系统队列中,然后系统会把此消息放到目标窗口所在的线程的消息队列(thread-specific
message queue)中等待处理
2) 线程消息队列(Thread-specific Message Queue) 每一个GUI线程都会维护这样一个线程消息队列。(这个队列只有在线程调用GDI函数时才会创建,默认不创建)。然后线程消息队列中的消息会被送到相应的窗口过程(WndProc)处理.
注意:
线程消息队列中WM_PAINT,WM_TIMER只有在Queue中没有其他消息的时候才会被处理,WM_PAINT消息还会被合并以提高效率。其他所有消息以先进先出(FIFO)的方式被处理。

程序发送此消息给editcontrol或combobox撤消最后一次操作

获取线程最近一次准备处理一个消息的系统时间(GetTickCount)

GetMessageSource
MSGSRC_SOFTWARE_POST表面键盘消息来自software(postmessage标记为software).
MSGSRC_HARDWARE_KEYBOARD 表面消息来自keyboard. MSGSRC_UNKNOWN

云顶娱乐平台 3

7 TranslateMessage, TranslateAccelerator 
TranslateMessage: 把一个virtual-key消息转化成字符消息(character
message),并放到当前线程的消息队列中,消息循环下一次取出处理。
TranslateAccelerator:将快捷键对应到相应的菜单命令。它会把WM_KEYDOWN 或
WM_SYSKEYDOWN转化成快捷键表中相应的WM_COMMAND或WM_SYSCOMMAND消息,
然后把转化后的 WM_COMMAND或WM_SYSCOMMAND直接发送到窗口过程处理,
处理完后才会返回。

也可以修改他们;

4.如果应用程序正在创建顶层窗口时调用PeekMessage,将导致窗口窗口被创建在Z-Order的最后。你需要在PeekMessage后,显式调用SetForegroundWindow。如果应用程序以及有一个前置窗口了,那么新窗口将被前置。

PostMessage
应用程序要用HWND_BROADCAST进行程序间的交互,消息应该获取于RegisterWindowMessage()

3.2 为了验证3.1.1的猜想,用API Monitor一下ShellExecuteEx

WM_NCACTIVATE = 134

消息相关函数:

DispatchMessage

LONG DispatchMessage(
const MSG* lpmsg
);
1.该函数将消息,通过系统派发给窗口过程
2.如果是一个定时器消息,lParam参数不是空,

 

WM_QUIT = 18

该函数返回消息x,y坐标,在多重monitor下,可能有负值。

GetMessageQueueReadyTimeStamp

shell_execute.exe的主要code:

当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口

返回值得高字节表示当前在消息队列中的消息类型。低字节表示从上次GetQueueStatus,GetMessage或者PeekMessage后被加入队列的消息类型。

InSendMessage

发送给最小化窗口当它图标将要被重画

消息来源未知

DWORD GetQueueStatus(
UINT flags
);
在消息队列中的消息的类型
flags为要检测的消息类型。

1> 解压iqy_test.zip

WM_ENTERMENULOOP =529

云顶娱乐平台 4

当用户选择一条菜单项时发送此消息给菜单的所有者(一般是窗口)

此消息有一个LBS_WANTKEYBOARDINPUT风格的发出给它的所有者来响应WM_KEYDOWN消息

云顶娱乐平台 5

然后我们修改一下窗口过程:

注意到win7下PostMessageW是用的线程2调用的,搜一下线程创建API
CreateThread

WM_DDE_TERMINATE =WM_DDE_FIRST + 1

 

在WM_NOTIFY消息,使用此控件能使某个控件与它的父控件之间进行相互通信

云顶娱乐平台 6

//双击鼠标左键

刚好就是打开test.iqy的命令,说明ShellExecuteEx就是先创建了excel的进程,然后发送test.iqy的文件命令给excel打开。

每当打印管理列队增加或减少一条作业时发出此消息

 

表A-2  常用Windows消息

5.1 在API Monitor中看下PostMessageW

L B N _ K I L L F OC U S列表框正在失去输入焦点

注意到下一个API GetWindowThreadProcessId ( 0x00310172 , 0x0012fb70
),刚好是获取这个窗口的pid和tid,查看下参数窗口:

lParam
通常是一个指向内存中数据的指针。由于WParm、lParam和Pointer都是32位的,因此,它们之间可以相互转换。

3.1.1 用windbg附加到excel上,输入如下命令查看主线程hang住的地方

WM_TIMER = 275 //发生了定时器事件

3> Post WM_DDE_EXECUTE给excel,告知打开test.iqy的命令

发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口

根据DDE的消息参数,可知wParam就是发送消息的窗口,其句柄为2425190 =
0x250166,反向查询知这是ShellExecuteEx创建的”WorkerW”窗口

WM_DEADCHAR = 259

4. 为什么双击打开excel不会hang住

程序发送此消息给MDI客户窗口让子窗口从最大最小化恢复到原来大小

消息1000为WM_DDE_EXECUTE,Post窗口句柄为0x00310172。

通过使用给定的相关显示设备的句柄来设置按纽的文本和背景颜色

由此可以怀疑是由于console进程在和excel用DDE消息通信时,console没有响应excel发送的DDE消息,导致excel
hang住

C B N _ C L O S E UP组合框的列表框被关闭

当在console中调用API
ShellExecuteEx打开”test.iqy”文件时,发现excel会hang住,console退出后excel才会响应,但直接双击”test.iqy”是没有问题的,有意思的是这个情况只有在xp发生,在win7上没有这个问题。

消息名称

说 明

CBN_CLOSEUP

组合框的列表框被关闭

CBN_DBLCLK

用户双击了一个字符串

CBN_DROPDOWN

组合框的列表框被拉下

CBN_EDITCHANGE

用户修改了组合框中的文本

CBN_EDITUPDATE

组合框内的文本即将更新

CBN_ERRSPACE

组合框内存不足

CBN_KILLFOCUS

组合框失去输入焦点

CBN_SELCHANGE

在组合框中选择了一项

CBN_SELENDCANCEL

用户的选择将被忽略

CBN_SELENDOK

用户的选择将被执行

CBN_SETFOCUS

组合框获得输入焦点

 

当用户双击鼠标右键同时光标某个窗口在非客户区十发送此消息

可以看到Excel
hang在NtUserMessageCall()中,经过查询知,SendMessage()内部就是调用NtUserMessageCall()来发送消息的。

L B N _ S E L C H AN G E选择了另一项

因为双击打开实际是用explorer.exe打开,而explorer.exe是有窗口的,能够正常的接收处理WM_DDE_INITIATE消息

WM_MBUTTONDOWN =519

说明excel给所有顶层窗口发送一个WM_DDE_INITIATE消息,但是有窗口没有response

WM_ENTERSIZEMOVE =561

1. 问题

云顶娱乐平台 7typedef struct tagMsg
云顶娱乐平台 8{
云顶娱乐平台 9       HWND    hwnd;       //接受该消息的窗口句柄
云顶娱乐平台 10       UINT    message;    //消息常量标识符,也就是我们通常所说的消息号
云顶娱乐平台 11       WPARAM  wParam;     //32位消息的特定附加信息,确切含义依赖于消息值
云顶娱乐平台 12       LPARAM  lParam;     //32位消息的特定附加信息,确切含义依赖于消息值
云顶娱乐平台 13       DWORD   time;       //消息创建时的时间
云顶娱乐平台 14       POINT   pt;         //消息创建时的鼠标/光标在屏幕坐标系中的位置
云顶娱乐平台 15}MSG;
云顶娱乐平台 16

查看一下buff的地址:

得到与一个窗口有关的文本的长度(不包含空字符)

重现环境:XP sp3 / Office 2007(其他office版本应该也可以,没有测试)

消息名称

说 明

LBN_DBLCLK

用户双击了一项

LBN_ERRSPACE

列表框内存不足

LBN_KILLFOCUS

列表框正在失去输入焦点

LBN_SELCANCEL

用户选择被取消

LBN_SELCHANGE

用户选择将改变

LBN_SETFOCUS

列表框获得输入焦点

5. 为什么win7上不会有这样的问题

WM_NULL = 0

 

发送此消息来取消某种正在进行的摸态(操作)

云顶娱乐平台 17

wParam 通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。

3.2.2 为了验证3.2.1的结论,在PostMessageW上下断点跟踪一下

WM_CANCELMODE = 31

3. 原因分析

通过使用给定的相关显示设备的句柄来设置消息框的文本和背景颜色

类似,我们可以创建一个带窗口的程序,启动后将其挂起,这时,即使直接双击打开test.iqy也会hang住。

WM_MENUCOMMAND =294

call stack显示确实是ShellExecuteEx所调用

WM_DESTROY = 2

查看参数知excel调用NtUserMessageCall()类似如下:

公用控件,自定义控件和他们的父窗口通过此消息来判断控件是使用ANSI还是UNICODE结构

4> ShellExecuteEx执行结束,但并不destroy “WorkerW”窗口

E N _ H S C R O L L用户点击了水平滚动条

 

WM_NCHITTEST =132//移动鼠标,按住或释放鼠标时发生

云顶娱乐平台 18

WM_NCMBUTTONDOWN =167

bool shell_execute_file(wstring file_path)
{
    SHELLEXECUTEINFOW shell_exec_info = { 0 };
    shell_exec_info.cbSize = sizeof(SHELLEXECUTEINFOW);
    shell_exec_info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
    shell_exec_info.hwnd = NULL;
    shell_exec_info.lpVerb = NULL;
    shell_exec_info.lpFile = file_path.c_str();
    shell_exec_info.lpParameters = NULL;
    shell_exec_info.lpDirectory = NULL;
    shell_exec_info.nShow = SW_SHOW;
    shell_exec_info.hInstApp = NULL;
    bool ret = ShellExecuteExW(&shell_exec_info);
    printf("process handle is %pn", shell_exec_info.hProcess);

    return ret;
}

WM_MOUSEWHEEL = 522

3.1 excel hang在哪里?

WM_PENWINLAST = 911

3.3 总结

当用户释放鼠标中键同时光标又在窗口的非客户区时发送此消息

2. 重现步骤

WM_SETREDRAW = 11

云顶娱乐平台 19

应用程序发送此消息给多文档的客户窗口通知客户窗口激活另一个MDI子窗口,当客户窗口收到

3> 执行”shell_execute.exe test.iqy”

  由于Windows本身是由消息驱动的,举一个例子来说明这个问题。打开记事本程序,该程序有一个File菜单,那么,在运行该应用程序的时候,如果用户单击了File菜单里New命令时,这个动作将被Windows
(而不是应用程序本身!)所捕获,Windows经过分析得知这个动作应该由上面所说的那个应用程序去处理,既然是这样,Windows就发送了个叫做WM_COMMAND的消息给应用程序,该消息所包含信息告诉应用程序:”用户单击了New菜单”,应用程序得知这一消息之后,采取相应的动作来响应它,这个过程称为消息处理。Windows为每一个应用程序(确切地说是每一个线程)维护了相应的消息队列,应用程序的任务就是不停的从它的消息队列中获取消息,分析消息和处理消息,直到一条接到叫做WM_QUIT消息为止,这个过程通常是由一种叫做消息循环的程序结构来实现的。

云顶娱乐平台 20

WM_INPUTLANGCHANGE= 81

NtUserMessageCall(HWND_BROADCAST, WM_DDE_INITIATE)

end

1> ShellExecuteEx打开test.iqy的时先创建excel进程

WM_QUERYNEWPALETTE= 783

在API Monitor中搜索一下PostMessage的调用,果然搜到一条

E N _ E R R S PA CE编辑框内存不足

此消息发送给某个窗口来返回与某个窗口有关连的大图标或小图标的句柄;

WM_【云顶娱乐平台】关于windows操作系统之消息和消息队列。CTLCOLORDLG =310

当用户释放鼠标右键同时光标又在窗口的非客户区时发送此消息

WM_EXITSIZEMOVE =562

当一个应用程序传递数据给另一个应用程序时发送此消息

WM_IME_REQUEST =648

//双击鼠标右键

//按下鼠标左键

   
消息可以由系统或者应用程序产生。系统在发生输入事件时产生消息。举个例子,
当用户敲键,
移动鼠标或者单击控件。系统也产生消息以响应由应用程序带来的变化,
比如应用程序改变系统字体改变窗体大小。应用程序可以产生消息使窗体执行任务,或者与其他应用程序中的窗口通讯。

当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后发送此消息给拥有焦点的窗口

程序发送此消息给MDI客户窗口以层叠方式重新排列所有MDI子窗口

WM_ACTIVATEAPP = 28

WM_NCLBUTTONDOWN =161

WM_NEXTDLGCTL = 40

当用户正在调整窗口大小时发送此消息给窗口;通过此消息应用程序可以监视窗口大小和位置

当MDI子窗口被创建或被销毁,或用户按了一下鼠标键而光标在子窗口上时发送此消息给它的父窗口

当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后提交此消息给拥有焦点的窗口

WM_POWER = 72(适用于16位的windows)

WM_DDE_POKE =WM_DDE_FIRST + 7

WM_MDIMAXIMIZE =549

WM_IME_STARTCOMPOSITION= 269

WM_DESTROYCLIPBOARD= 775

消息中有什么?
   我们给出了上面的注释,是不是会对消息结构有了一个比较清楚的认识?如果还没有,那么我们再试着给出下面的解释:
     hwnd
32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)。
    
message用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。消息标识符以常量命名的方式指出消息的含义。当窗口过程接收到消息之后,他就会使用消息标识符来决定如何处理消息。例如、WM_PAINT告诉窗口过程窗体客户区被改变了需要重绘。符号常量指定系统消息属于的类别,其前缀指明了处理解释消息的窗体的类型。
     wParam 通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。
     lParam
通常是一个指向内存中数据的指针。由于WParam、lParam和Pointer都是32位的,因此,它们之间可以相互转换。

WM_MDITILE = 550

云顶娱乐平台 21LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
云顶娱乐平台 22{
云顶娱乐平台 23       switch(message)
云顶娱乐平台 24      {
云顶娱乐平台 25             HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);
云顶娱乐平台 26             HANDLE_MSG(hWnd,WM_DESTROY,MsgCracker);
云顶娱乐平台 27           default:
云顶娱乐平台 28                    return DefWindowProc(hWnd, message, wParam, lParam);
云顶娱乐平台 29   }
云顶娱乐平台 30  return 0;
云顶娱乐平台 31}

当用translatemessage函数翻译WM_KEYUP消息时发送此消息给拥有焦点的窗口

/////////////////////////////////////////////////////////////////////

WM_MDIRESTORE = 547

转载:

Windows消息大全

WM_SHOWWINDOW = 24

WM_IME_CHAR = 646

//释放鼠标中键

应用程序发送此消息来判断热键与某个窗口是否有关联

WM_COMMAND = 273

WM_SYSCOMMAND = 274

程序发送此消息给MDI客户窗口以平铺方式重新排列所有MDI子窗口

当用户窗口恢复以前的大小位置时,把此消息发送给某个图标

WM_KEYFIRST = 256

应用程序创建一个窗口

 

WM_USERCHANGED = 84

WM_CAPTURECHANGED =533

//释放鼠标右键

WM_KILLFOCUS = 8

WM_CHILDACTIVATE =34

当一个窗口或应用程序要关闭时发送一个信号

一个DDE服务程序提交此消息给DDE客户程序来传递个一数据项给客户或通知客户的一条可用数据项

C B N _ K I L L F OC U S组合框失去输入焦点

此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的hook程序

WM_PENWINFIRST =896

WM_NEXTMENU = 531

获得焦点后

WM_MENUCHAR = 288

窗口过程
 窗口过程是一个用于处理所有发送到这个窗口的消息的函数。任何一个窗口类都有一个窗口过程。同一个类的窗口使用同样的窗口过程来响应消息。系统发送消息给窗口过程将消息数据作为参数传递给他,消息到来之后,按照消息类型排序进行处理,其中的参数则用来区分不同的消息,窗口过程使用参数产生合适行为。
 一个窗口过程不经常忽略消息,如果他不处理,它会将消息传回到执行默认的处理。窗口过程通过调用DefWindowProc来做这个处理。窗口过程必须
return一个值作为它的消息处理结果。大多数窗口只处理小部分消息和将其他的通过DefWindowProc传递给系统做默认的处理。窗口过程被所有属于同一个类的窗口共享,能为不同的窗口处理消息。下面我们来看一下具体的实例:

WM_IME_COMPOSITION= 271

WM_CTLCOLORSCROLLBAR=311

消息名称

说 明

EN_CHANGE

编辑框中的文本己更新

EN_ERRSPACE

编辑框内存不足

EN_HSCROLL

用户点击了水平滚动条

EN_KILLFOCUS

编辑框失去输入焦点

EN_MAXTEXT

插入的内容被截断

EN_SETFOCUS

编辑框获得输入焦点

EN_UPDATE

编辑框中的文本将要更新

EN_VSCROLL

用户点击了垂直滚动条

的边框体

WM_RBUTTONDOWN =516

程序发送此消息给某个窗口当它(窗口)的框架必须被绘制时;

当用户按住ALT键同时按下其它键时提交此消息给拥有焦点的窗口;

WM_GETTEXT = 13

此消息显示用户按下了F1,如果某个菜单是激活的,就发送此消息个此窗口关联的菜单,否则就

WM_IME_SETCONTEXT =641

消息名称

说 明

BN_CLICKED

单击按钮

BN_DISABLE

按钮被禁止

BN_DOUBLECLICKED

双击按钮

BN_HILITE

加亮按钮

BN_PAINT

按钮应当重画

BN_UNHILITE

加亮应当去掉

应用程序发送此消息给多文档的客户窗口来关闭一个MDI 子窗口

 

当一个静态控件将要被绘制时发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

 

程序发送此消息给MDI客户窗口来最大化一个MDI子窗口;

WM_NCRBUTTONUP =165

当隐藏或显示窗口是发送此消息给这个窗口

WM_ERASEBKGND = 20

  Windows是一消息(Message)驱动式系统,Windows消息提供了应用程序与应用程序之间、应用程序与Windows系统之间进行通讯的手段。应用程序要实现的功能由消息来触发,并靠对消息的响应和处理来完成。Windows系统中有两种消息队列,一种是系统消息队列,另一种是应用程序消息队列。计算机的所有输入设备由
Windows监控,当一个事件发生时,Windows先将输入的消息放入系统消息队列中,然后再将输入的消息拷贝到相应的应用程序队列中,应用程序中的消息循环从它的消息队列中检索每一个消息并发送给相应的窗口函数中。一个事件的发生,到达处理它的窗口函数必须经历上述过程。值得注意的是消息的非抢先性,即不论事件的急与缓,总是按到达的先后排队(一些系统消息除外),这就使得一些外部实时事件可能得不到及时的处理。

此消息发送给某个窗口仅当它的非客户区需要被改变来显示是激活还是非激活状态;

WM_DDE_INITIATE =WM_DDE_FIRST + 0

WM_ICONERASEBKGND =39

云顶娱乐平台 32   #define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) 
云顶娱乐平台 33     (void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))

发送此消息给控件的所有者

WM_HSCROLL = 276

C B N _ S E T F O CU S组合框获得输入焦点

  
首先,GetMessage从进程的主线程的消息队列中获取一个消息并将它复制到MSG结构,如果队列中没有消息,则GetMessage函数将等待一个消息的到来以后才返回。如果你将一个窗口句柄作为第二个参数传入GetMessage,那么只有指定窗口的的消息可以从队列中获得。GetMessage也可以从消息队列中过滤消息只接受消息队列中落在范围内的消息。这时候就要利用GetMessage/PeekMessage指定一个消息过滤器。这个过滤器是一个消息标识符的范围或者是一个窗体句柄,或者两者同时指定。当应用程序要查找一个后入消息队列的消息是很有用。WM_KEYFIRST
和 WM_KEYLAST 常量用于接受所有的键盘消息。 WM_MOUSEFIRST 和
WM_MOUSELAST 常量用于接受所有的鼠标消息。 
 然后TranslateAccelerator判断该消息是不是一个按键消息并且是一个加速键消息,如果是,则该函数将把几个按键消息转换成一个加速键消息传递给窗口的回调函数。处理了加速键之后,函数TranslateMessage将把两个按键消息WM_KEYDOWN和WM_KEYUP转换成一个
WM_CHAR,不过需要注意的是,消息WM_KEYDOWN,WM_KEYUP仍然将传递给窗口的回调函数。     
 处理完之后,DispatchMessage函数将把此消息发送给该消息指定的窗口中已设定的回调函数。如果消息是WM_QUIT,则
GetMessage返回0,从而退出循环体。应用程序可以使用PostQuitMessage来结束自己的消息循环。通常在主窗口的
WM_DESTROY消息中调用。
 下面我们举一个常见的小例子来说明这个消息泵的运用:

WM_TCARD = 82

WM_SETFOCUS = 7

WM_DDE_DATA =WM_DDE_FIRST + 5

要求一个窗口重画自己

WM_RBUTTONUP = 517

WM_IME_COMPOSITIONFULL= 644

应用程序发送此消息让一个窗口与一个热键相关连

编辑框控件
 EN_CHANGE 编辑框中的文本己更新
 EN_ERRSPACE 编辑框内存不足
 EN_HSCROLL 用户点击了水平滚动条
 EN_KILLFOCUS 编辑框正在失去输入焦点
 EN_MAXTEXT 插入的内容被截断
 EN_SETFOCUS 编辑框获得输入焦点
 EN_UPDATE 编辑框中的文本将要更新
 EN_VSCROLL 用户点击了垂直滚动条消息含义

C B N _ E D I T C HA N G E用户修改了编辑框中的文本

应用程序发送此消息得到当前控件绘制文本的字体

此消息通知一个DDE(动态数据交换)程序已收到并正在处理WM_DDE_POKE,
WM_DDE_EXECUTE, WM_DDE_DATA, WM_DDE_ADVISE,WM_DDE_UNADVISE, or
WM_DDE_INITIAT消息

WM_UNDO = 772

WM_USER = 1024

当显示器的分辨率改变后发送此消息给所有的窗口

消息分流器
  通常的窗口过程是通过一个switch语句来实现的,这个事情很烦,有没有更简便的方法呢?有,那就是消息分流器,利用消息分流器,我们可以把switch语句分成更小的函数,每一个消息都对应一个小函数,这样做的好处就是对消息更容易管理。
  之所以被称为消息分流器,就是因为它可以对任何消息进行分流。下面我们做一个函数就很清楚了:

E N _ U P D AT E编辑框中的文本将要更新

发送此消息给那个窗口的大小和位置已经被改变时,来调用setwindowpos函数或其它窗口管理函数

WM_CLOSE = 16

通知它对话是否结束

B N _ C L I C K E D//用户单击了按钮

发送此消息给那个窗口的大小和位置将要被改变时,来调用setwindowpos函数或其它窗口管理函数

一个DDE客户程序通过此消息通知一个DDE服务程序不更新指定的项或一个特殊的剪贴板格式的项

一个DDE客户程序提交此消息给一个DDE服务程序,客户使用此消息来请求服务器接收一个未经同意的数据项;服务器通过答复WM_DDE_ACK消息提示是否它接收这个数据项;

//释放一个键

WM_DROPFILES = 563

WM_PRINT = 791

WM_MOUSEFIRST = 512

WM_DISPLAYCHANGE =126

云顶娱乐平台 34   #define HANDLE_WM_COMMAND(hwnd,wParam,lParam,fn) 
云顶娱乐平台 35             ((fn)((hwnd),(int)(LOWORD(wParam)),(HWND)(lParam),(UINT)HIWORD(wParam)),0L);

WM_GETICON = 127

程序发送此消息给MDI客户窗口激活下一个或前一个窗口

WM_MOUSEMOVE = 512

一个DDE客户程序提交此消息开始一个与服务器程序的会话来响应那个指定的程序和主题名;

B N _ D I S A B L E//按钮被禁止

WM_TIMECHANGE = 30

C B N _ S E L C H AN G E在组合框中选择了一项

当光标在一个窗口的非客户区内移动时发送此消息给这个窗口
//非客户区为:窗体的标题栏及窗

当用户按下鼠标中键同时光标又在窗口的非客户区时发送此消息

当一个下拉菜单或子菜单将要被激活时发送此消息,它允许程序在它显示前更改菜单,而不要

设置信息,在用户更新设置时系统马上发送此消息;

L B N _ D B L C L K用户双击了一项

在windows绘制消息框前发送此消息给消息框的所有者窗口,通过响应这条消息,所有者窗口可以

WM_INITDIALOG = 272

应用程序发送此消息仅当WINDOWS或其它应用程序发出一个请求要求绘制一个应用程序的一部分;

WM_GETDLGCODE = 135

WM_PALETTECHANGED =785

消息映射的内容
   
通过ClassWizard为我们生成的代码,我们可以看到,消息映射基本上分为2大部分:
   
在头文件(.h)中有一个宏DECLARE_MESSAGE_MAP(),他被放在了类的末尾,是一个public属性的;与之对应的是在实现部分(.cpp)增加了一章消息映射表,内容如下:
    BEGIN_MESSAGE_MAP(当前类, 当前类的基类)
       //{{AFX_MSG_MAP(CMainFrame)
         消息的入口项
       //}}AFX_MSG_MAP
   END_MESSAGE_MAP()
  
但是仅是这两项还远不足以完成一条消息,要是一个消息工作,必须有以下3个部分去协作:
1.在类的定义中加入相应的函数声明;
2.在类的消息映射表中加入相应的消息映射入口项;
3.在类的实现中加入相应的函数体;

WM_NCCREATE = 129

WM_QUERYENDSESSION= 17

当系统的字体资源库变化时发送此消息给所有顶级窗口

WM_COMPAREITEM = 57

WM_SYSKEYUP = 261

WM_COPYDATA = 74

表A-4  通知消息-组合框

程序发送此消息给MDI客户窗口来找到激活的子窗口的句柄

共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中选择部分文本、操作控件的

TMsg = packedrecord

程序发送此消息给editcontrol或combobox清除当前选择的内容;

WM_RBUTTONDBLCLK =518

WM_MDIICONARRANGE =552

WM_SYSKEYDOWN = 260

 

WM_MOUSEACTIVATE =33

当绘制文本时程序发送此消息得到控件要用的颜色

//按下一个键

WM_COMPACTING = 65

WM_NCMBUTTONUP =168

WM_MDINEXT = 548

此消息由一个LBS_WANTKEYBOARDINPUT风格的列表框发送给他的所有者来响应WM_CHAR消息

WM_QUERYDRAGICON =55

WM_MDIGETACTIVE =553

WM_SETCURSOR = 32

WM_CHAR = 258

前面,我们分析了消息的基本理论和基本的函数及用法,接下来,我们将进一步讨论消息传递在MFC中的实现。

WM_NCLBUTTONDBLCLK= 163

WM_HSCROLLCLIPBOARD= 782

也可以修改他们

通过响应WM_GETDLGCODE消息,应用程序可以把他当成一个特殊的输入控件并能处理它

WM_NCLBUTTONUP =162

WM_POWERBROADCAST =536

当用户选择结束对话框或程序自己调用ExitWindows函数

WM_PARENTNOTIFY =528

用来结束程序运行或当程序调用postquitmessage函数

WM_SYSCOLORCHANGE =21

C B N _ D R O P D OW N组合框的列表框被拉出

应用程序发送此消息给多文档的客户窗口来创建一个MDI 子窗口

WM_MDISETMENU = 560

WM_ENDSESSION = 22

lParam: LPA R AM  // 32位消息的特定附加信息

来改变系统调色板

WM_DDE_ACK = WM_DDE_FIRST+ 4

失去焦点

 

WM_COALESCE_LAST =927

WM_QUEUESYNC = 35

当一个窗口从剪贴板观察链中移去时发送此消息给剪贴板观察链的第一个窗口;

分离出用户输入消息

WM_MDIREFRESHMENU =564

程序发送此消息给editcontrol或combobox从剪贴板中得到数据

E N _ C H A N G E编辑框中的文本己更新

当用户按下由REGISTERHOTKEY函数注册的热键时提交此消息

WM_NCRBUTTONDOWN =164

WM_MOUSELAST = 522

显示剪贴板的新内容;

WM_SYSTEMERROR = 23

WM_KEYUP = 257

一个DDE客户程序提交此消息给一个DDE服务程序来发送一个字符串给服务器让它象串行命令一样被处理,服务器通过提交WM_DDE_ACK消息来作回应;

程序发送此消息给一个编辑框或combobox来删除当前选择的文本

WM_FONTCHANGE = 29

WM_NCCALCSIZE = 131

B N _ PA I N T按钮应当重画

WM_MENUSELECT = 287

WM_HANDHELDLAST =863

WM_DDE_EXECUTE =WM_DDE_FIRST + 8

WM_IME_ENDCOMPOSITION= 270

当窗口背景必须被擦除时(例在窗口改变大小时)

WM_NCMOUSEMOVE =160

B N _ D O U B L E CL I C K E D //用户双击了按钮

 

C B N _ E R R S PAC E组合框内存不足

WM_GETMINMAXINFO =36

E N _ S E T F O C US编辑框获得输入焦点

通过使用给定的相关显示设备的句柄来设置编辑框的文本和背景颜色

WM_CUT = 768

WM_KEYLAST = 264

程序在显示前更改菜单

//按下鼠标中键

WM_CTLCOLORMSGBOX =306

当剪贴板包含CF_OWNERDIPLAY格式的数据并且剪贴板观察窗口的客户区需要重画;

发送此消息来判定combobox或listbox新增加的项的相对位置

当button, combo box, list box, list view control, or menu item 被创建时

一个DDE客户程序提交此消息给一个DDE服务程序来请求服务器每当数据项改变时更新它

当光标在一个窗口的非客户区同时按下鼠标左键时提交此消息

WM_MBUTTONDBLCLK =521

WM_NOTIFYFORMAT =85

wParam: WPA R AM  // 32位消息的特定附加信息

当the list box 或 combo box 被销毁 或 当
某些项被删除通过LB_DELETESTRING,LB_RESETCONTENT, CB_DELETESTRING, or
CB_RESETCONTENT 消息

当某个窗口第一次被创建时,此消息在WM_CREATE消息发送前发送;

WM_QUERYUISTATE =297

WM_DDE_REQUEST =WM_DDE_FIRST + 6

当用户已经登入或退出后发送此消息给所有的窗口,当用户登入或退出时系统更新用户的具体

表A-6  通知消息-列表框

L B N _ S E T F O CU S列表框获得输入焦点

WM_LBUTTONUP = 514

WM_CTLCOLOREDIT =307

云顶娱乐平台 36if (::PeekMessage(&msg, m_hWnd, WM_KEYFIRST,WM_KEYLAST, PM_REMOVE))
云顶娱乐平台 37{
云顶娱乐平台 38          if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)...
云顶娱乐平台 39}
云顶娱乐平台 40

当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口

发此消息给应用程序哪个窗口是激活的,哪个是非激活的;

WM_IME_KEYLAST =271

   2、手动地添加消息处理函数
   
如果在Messages列表框中仍然看不到我们想要的消息,那么该消息可能是被系统忽略掉或者是你自己创建的,在这种情况下,就必须自己手工添加。根据我们前面所说的消息工作的3个部件,我们一一进行处理:
      1) 在类的.
h文件中添加处理函数的声明,紧接在//}}AFX_MSG行之后加入声明,注意:一定要以afx_msg开头。
     通常,添加处理函数声明的最好的地方是源代码中Class
Wizard维护的表下面,但是在它标记其领域的{{}}括弧外面。这些括弧中的任何东西都将会被Class
Wizard销毁。
      2)
接着,在用户类的.cpp文件中找到//}}AFX_MSG_MAP行,紧接在它之后加入消息入口项。同样,也是放在{
{} }的外面
      3) 最后,在该文件中添加消息处理函数的实体。

消息的添加
  
有了上面的这些只是作为基础,我们接下来就做我们最熟悉、最常用的工作:添加消息。MFC消息的添加主要有2种方法:自动/手动,我们就以这2种方法为例,说一下如何添加消息。
   1、利用Class Wizard实现自动添加
      在菜单中选择View–>Class
Wizard,也可以用单击鼠标右键,选择Class Wizard,同样可以激活Class
Wizard。选择Message Map标签,从Class
name组合框中选取我们想要添加消息的类。在Object
IDs列表框中,选取类的名称。此时,
Messages列表框显示该类的大多数(若不是全部的话)可重载成员函数和窗口消息。类重载显示在列表的上部,以实际虚构成员函数的大小写字母来表示。其他为窗口消息,以大写字母出现,描述了实际窗口所能响应的消息ID。选中我们向添加的消息,单击Add
Function按钮,Class Wizard自动将该消息添加进来。
     
有时候,我们想要添加的消息本应该出现在Message列表中,可是就是找不到,怎么办?不要着急,我们可以利用Class
Wizard上Class Info标签以扩展消息列表。在该页中,找到Message
Filter组合框,通过它可以改变首页中Messages列表框中的选项。这里,我们选择Window,从而显示所有的窗口消息,一把情况下,你想要添加的消息就可以在Message列表框中出现了,如果还没有,那就接着往下看:)

WM_SYSDEADCHAR =263

  表A-3  通知消息-按钮

程序发送此消息让一个新的大图标或小图标与某个窗口关联;

E N _ M A X T E X T插入的内容被截断

WM_PAINT = 15

WM_MOVING = 534

WM_NCPAINT = 133

编辑框

WM_MENUDRAG = 291

WM_ACTIVATE = 6

通过使用给定的相关显示设备的句柄来设置列表框的文本和背景颜色

WM_MBUTTONUP = 520

E N _ K I L L F O CU S编辑框正在失去输入焦点

此消息发送给窗口当它将要改变大小或位置;

发送此消息给窗口当它失去捕获的鼠标时;

WM_PASTE = 770

消息的接收
 消息的接收主要有3个函数:GetMessage、PeekMessage、WaitMessage。
  GetMessage原型如下:BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT
wMsgFilterMin,UINT
wMsgFilterMax);该函数用来获取与hWnd参数所指定的窗口相关的且wMsgFilterMin和wMsgFilterMax参数所给出的消息值范围内的消息。需要注意的是,如果hWnd为NULL,则GetMessage获取属于调用该函数应用程序的任一窗口的消息,如果
wMsgFilterMin和wMsgFilterMax都是0,则GetMessage就返回所有可得到的消息。函数获取之后将删除消息队列中的除
WM_PAINT消息之外的其他消息,至于WM_PAINT则只有在其处理之后才被删除。
   PeekMessage原型如下:BOOL PeekMessage(LPMSG lpMsg,HWND hWnd,UINT
wMsgFilterMin,UINT wMsgFilterMax,UINT
wRemoveMsg);该函数用于查看应用程序的消息队列,如果其中有消息就将其放入lpMsg所指的结构中,不过,与GetMessage不同的是,PeekMessage函数不会等到有消息放入队列时才返回。同样,如果hWnd为NULL,则PeekMessage获取属于调用该函数应用程序的任一窗口的消息,如果hWnd=-1,那么函数只返回把hWnd参数为NULL的PostAppMessage函数送去的消息。如果
wMsgFilterMin和wMsgFilterMax都是0,则PeekMessage就返回所有可得到的消息。函数获取之后将视最后一个参数来决定是否删除消息队列中的除
WM_PAINT消息之外的其他消息,至于WM_PAINT则只有在其处理之后才被删除。
   WaitMessage原型如下:BOOL
WaitMessage();当一个应用程序无事可做时,该函数就将控制权交给另外的应用程序,同时将该应用程序挂起,直到一个新的消息被放入应用程序的队列之中才返回。

WM_CREATE = 1

//按下鼠标右键

C B N _ S E L E N DO K用户的选择是合法的

WM_CLEAR = 771

WM_STYLECHANGING =124

WM_HOTKEY = 786

当一个编辑型控件将要被绘制时发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

组合框控件
 CBN_CLOSEUP 组合框的列表框被关闭
 CBN_DBLCLK 用户双击了一个字符串
 CBN_DROPDOWN 组合框的列表框被拉出
 CBN_EDITCHANGE 用户修改了编辑框中的文本
 CBN_EDITUPDATE 编辑框内的文本即将更新
 CBN_ERRSPACE 组合框内存不足
 CBN_KILLFOCUS 组合框失去输入焦点
 CBN_SELCHANGE 在组合框中选择了一项
 CBN_SELENDCANCEL 用户的选择应当被取消
 CBN_SELENDOK 用户的选择是合法的
 CBN_SETFOCUS 组合框获得输入焦点

L B N _ E R R S PAC E列表框内存不够

发送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活,移动,改变大小

一个窗口被销毁

改变一个窗口的大小

E N _ V S C R O L L用户点击了垂直滚动条消息含义

  这里我们接受所有的键盘消息,所以就用WM_KEYFIRST 和
WM_KEYLAST作为参数。最后一个参数可以是PM_NOREMOVE 或者
PM_REMOVE,表示消息信息是否应该从消息队列中删除。                 
   所以这段小代码就是判断是否按下了Esc键,如果是就进行处理。

WM_NCDESTROY = 130

发送此消息给某个与对话框程序关联的控件,widdows控制方位键和TAB键使输入进入此控件

通过使用给定的相关显示设备的句柄来设置静态控件的文本和背景颜色

当菜单已被激活用户按下了某个键(不同于加速键),发送此消息给菜单的所有者;

WM_DDE_UNADVISE =WM_DDE_FIRST + 3

WM_DELETEITEM = 45

改变enable状态

当用户在移动窗口时发送此消息,通过此消息应用程序可以监视窗口大小和位置

WM_PAINTCLIPBOARD =777

消息名称

说  明

WM_NULL 

0x0000

空消息,此消息将被接收窗口忽略

WM_CREATE 

0x0001

应用程序创建一个窗口

WM_DESTROY

0x0002

一个窗口被销毁

WM_MOVE

0x0003

移动一个窗口

WM_SIZE

0x0005

改变一个窗口的大小

WM_ACTIVATE

0x0006

一个窗口被激活或失去激活状态

WM_SETFOCUS

0x0007

获得焦点后

WM_KILLFOCUS

0x0008

失去焦点

WM_ENABLE

0x000A

应用程序Enable状态改变时产生

WM_SETREDRAW

0x000B

设置窗口是否能重画

WM_SETTEXT

0x000C

应用程序发送此消息来设置一个窗口的文本

WM_GETTEXT

0x000D

应用程序发送此消息来复制对应窗口的文本到缓冲区

WM_GETTEXTLENGTH

0x000E

得到与一个窗口有关的文本的长度(不包含空字符)

WM_PAINT

0x000F

要求一个窗口重绘自己

WM_CLOSE

0x0010

当一个窗口或应用程序要关闭时发送一个信号

WM_QUERYENDSESSION

0x0011

用户选择结束对话框或应用程序自己调用ExitWindows()函数

WM_QUIT

0x0012

用来结束程序运行或应用程序调用Postquitmessage()函数来产生此消息

WM_QUERYOPEN

0x0013

当用户窗口恢复以前的大小位置时,把此消息发送给某个图标

WM_ERASEBKGND

0x0014

当窗口背景必须被擦除时(例如在窗口改变大小时)

WM_SYSCOLORCHANGE

0x0015

当系统颜色改变时,发送此消息给所有顶级窗口

WM_ENDSESSION

0x0016

当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序

WM_SHOWWINDOW

0x0018

当隐藏或显示窗口是发送此消息给这个窗口

WM_ACTIVATEAPP

0x001C

当某个窗口将被激活时,将被激活窗口和当前活动(即将失去激活)窗口会收到此消息,发此消息给应用程序哪个窗口是激活的,哪个是非激活的

WM_FONTCHANGE

0x001D

当系统的字体资源库变化时发送此消息给所有顶级窗口

WM_TIMECHANGE

0x001E

当系统的时间变化时发送此消息给所有顶级窗口

WM_CANCELMODE

0x001F

发送此消息来取消某种正在进行的操作

WM_SETCURSOR

0x0020

如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,发消息给该窗口

WM_MOUSEACTIVATE

0x0021

当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口

WM_CHILDACTIVATE

0x0022

发送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活、移动、改变大小

WM_QUEUESYNC

0x0023

此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的Hook程序分离出用户输入消息

WM_GETMINMAXINFO

0x0024

当窗口要将要改变大小或位置时,发送此消息给该窗口

WM_PAINTICON

0x0026

当窗口图标将要被重绘时,发送此消息给该窗口

WM_ICONERASEBKGND

0x0027

在一个最小化窗口的图标在重绘前,当图标背景必须被重绘时,发送此消息给该窗口

WM_NEXTDLGCTL

0x0028

发送此消息给一个对话框程序以更改焦点位置

WM_SPOOLERSTATUS

0x002A

当打印管理列队增加或减少一条作业时发出此消息

WM_DRAWITEM

0x002B

当Button,ComboBox,Listbox,Menu控件的外观改变时,发送此消息给这些控件的所有者

WM_MEASUREITEM

0x002C

当Button,ComboBox,list box,ListView,Menu 项被创建时,发送此消息给控件的所有者

WM_DELETEITEM

0x002D

当ListBox 或 ComboBox 被销毁或当某些项通过发送LB_DELETESTRING、LB_RESETCONTENT、 CB_DELETESTRING、CB_RESETCONTENT 消息被删除时,发送此消息给控件的所有者

WM_VKEYTOITEM

0x002E

一个具有LBS_WANTKEYBOARDINPUT风格的ListBox控件发送此消息给它的所有者,以此来响应WM_KEYDOWN消息

WM_CHARTOITEM

0x002F

一个具有LBS_WANTKEYBOARDINPUT风格的ListBox控件发送此消息给它的所有者,以此来响应WM_CHAR消息

WM_SETFONT

0x0030

应用程序绘制控件时,发送此消息得到以何种字体绘制控件中的文本

WM_GETFONT

0x0031

应用程序发送此消息得到当前控件绘制文本的字体

WM_SETHOTKEY

0x0032

应用程序发送此消息让一个窗口与一个热键相关联

WM_GETHOTKEY

0x0033

应用程序发送此消息来判断热键与某个窗口是否有关联

WM_QUERYDRAGICON

0x0037

此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序就返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标

WM_COMPAREITEM

0x0039

发送此消息来判定ComboBox或ListBox新增加的项的相对位置

WM_COMPACTING

0x0041

显示内存已经很少了

WM_WINDOWPOSCHANGING

0x0046

当调用SetWindowPos()函数改变窗口的大小和位置后,发送此消息给该窗口

WM_POWER

0x0048

当系统将进入挂起状态时发送此消息给所有进程

WM_COPYDATA

0x004A

当一个应用程序传递数据给另一个应用程序时发送此消息

WM_CANCELJOURNAL

0x004B

当某个用户取消程序日志激活状态,发送此消息给应用程序

WM_NOTIFY

0x004E

当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口

WM_INPUTLANGCHANGEREQUEST

0x0050

当用户选择某种输入语言,或输入语言的热键改变

WM_INPUTLANGCHANGE

0x0051

当应用程序输入语言改变后发送此消息给受影响的最顶级窗口

WM_TCARD

0x0052

当应用程序已经初始化Windows帮助例程时发送此消息给应用程序

WM_HELP

0x0053

当用户按下了F1,如果某个菜单是激活的,就发送此消息给此窗口关联的菜单,否则就发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口

WM_USERCHANGED

0x0054

当用户已经登录或退出后发送此消息给所有的窗口,当用户登录或退出时系统更新用户的具体设置信息,在用户更新设置时系统马上发送此消息

WM_NOTIFYFORMAT

0x0055

公用控件和它们的父窗口通过此消息来判断在WM_NOTIFY消息中是使用ANSI还是UNICODE形式的结构,使用此控件能使某个控件与它的父控件进行相互通信

WM_CONTEXTMENU

0x007B

当用户在某个窗口中点击右键,则发送此消息给该窗口

WM_STYLECHANGING

0x007C

当将要调用SetWindowLong()函数窗口的一个或多个风格时,发送此消息给该窗口

WM_STYLECHANGED

0x007D

当调用SetWindowLong()函数改变了窗口的一个或多个风格后,发送此消息给该窗口

WM_DISPLAYCHANGE

0x007E

当显示器的分辨率改变后发送此消息给所有的窗口

WM_GETICON

0x007F

发送此消息给某个窗口,返回与某个窗口有关联的大图标或小图标的句柄

WM_SETICON

0x0080

应用程序发送此消息让一个新的大图标或小图标与某个窗口关联

WM_NCCREATE

0x0081

当某个窗口第一次被创建时,此消息在WM_CREATE消息被发送前发送

WM_NCDESTROY

0x0082

此消息通知某个窗口,正在销毁非客户区

WM_NCCALCSIZE

0x0083

当计算某个窗口的客户区大小和位置时发送此消息

WM_NCHITTEST

0x0084

移动鼠标,按住或释放鼠标时产生此消息

WM_NCPAINT

0x0085

当某个窗口的框架必须被绘制时,应用程序发送此消息给该窗口

WM_NCACTIVATE

0x0086

通过改变某个窗口的非客户区来表示窗口是处于激活还是非激活状态时,此消息被发送给该窗口

WM_NCMOUSEMOVE

0x00A0

当光标在窗口的非客户区(窗口标题栏及边框)内移动时发送此消息给该窗口

WM_NCLBUTTONDOWN

0x00A1

当光标在窗口的非客户区并按下鼠标左键时发送此消息

WM_NCLBUTTONUP

0x00A2

当光标在窗口的非客户区并释放鼠标左键时发送此消息

WM_NCLBUTTONDBLCLK

0x00A3

当光标在窗口的非客户区并双击鼠标左键时发送此消息

WM_NCRBUTTONDOWN

0x00A4

当光标在窗口的非客户区并按下鼠标右键时发送此消息

WM_NCRBUTTONUP

0x00A5

当光标在窗口的非客户区并释放鼠标右键时发送此消息

WM_NCRBUTTONDBLCLK

0x00A6

当光标在窗口的非客户区并双击鼠标右键时发送此消息

WM_NCMBUTTONDOWN

0x00A7

当光标在窗口的非客户区并按下鼠标中键时发送此消息

WM_NCMBUTTONUP

0x00A8

当光标在窗口的非客户区并释放鼠标中键时发送此消息

WM_NCMBUTTONDBLCL

0x00A9

当光标在窗口的非客户区并双击鼠标中键时发送此消息

WM_KEYDOWN

0x0100

按下一个非系统键(按下键时未按下“ALT”键)

WM_KEYUP

0x0101

释放一个非系统键

WM_CHAR

0x0102

按下某键,当TranslateMessage()转发WM_KEYDOWN后发送本消息

WM_DEADCHAR

0x0103

释放某键,当TranslateMessage()转发WM_KEYUP后发送本消息

WM_SYSKEYDOWN

0x0104

当按住ALT键同时按下其他键时发送此消息给拥有键盘焦点的窗口

WM_SYSKEYUP

0x0105

当释放一个键同时按住ALT键时发送此消息给拥有键盘焦点的窗口

WM_SYSCHAR

0x0106

当TranslateMessage()转发WM_SYSKEYDOWN后发送此消息给拥有键盘焦点的窗口

WM_SYSDEADCHAR

0x0107

当TranslateMessage()转发WM_SYSKEYUP后发送此消息给拥有键盘焦点的窗口

WM_INITDIALOG

0x0110

在被显示前发送此消息对话框,通常用此消息初始化控件和执行其他任务

WM_COMMAND

0x0111

选择窗口菜单项或某个控件发送一条消息给它的父窗口或按下一个快捷键时产生此消息

WM_SYSCOMMAND

0x0112

选择窗口菜单项或选择最大化或最小化时,发送此消息给该窗口

WM_TIMER

0x0113

发生了定时器事件

WM_HSCROLL

0x0114

当窗口水平滚动条产生一个滚动事件时发送此消息给该窗口和滚动条的所有者

WM_VSCROLL

0x0115

当窗口垂直滚动条产生一个滚动事件时发送此消息给该窗口和滚动条的所有者

WM_INITMENU

0x0116

当一个菜单将要被激活时发送此消息,它发生在按下菜单项或按下菜单快捷键时,它允许程序在显示前更改菜单

WM_INITMENUPOPUP

0x0117

当一个下拉菜单或子菜单将要被激活时发送此消息,它允许显示前在修改菜单而不必更改整个菜单

WM_MENUSELECT

0x011F

选择一条菜单项时发送此消息给菜单的所有者(一般是窗口)

WM_MENUCHAR

0x0120

当菜单已被激活且用户按下了某个键(非快捷键),发送此消息给菜单的所有者

WM_ENTERIDLE

0x0121

当一个有模式对话框或菜单进入空闲状态时发送此消息给它的所有者,空闲状态指在处理完一条或几条先前的消息后,消息列队为空

WM_MENURBUTTONUP

0x0122

当光标位于菜单项上时,释放鼠标右键产生此消息

WM_MENUDRAG

0x0123

当拖动菜单项时,发送此消息给拖放菜单的所有者

WM_MENUGETOBJECT

0x0124

当光标移入菜单项或者从菜单项中心移到菜单项顶部或底部时,发送此消息给拖放菜单的所有者

WM_UNINITMENUPOPUP

0x0125

当下拉菜单或者子菜单被销毁时产生此消息

WM_MENUCOMMAND

0x0126

当用户选择菜单项时产生此消息

WM_CHANGEUISTATE

0x0127

应用程序发送此消息表明用户界面(UI)状态应当被改变

WM_UPDATEUISTATE

0x0128

应用程序发送此消息改变指定窗口及其子窗口的用户界面(UI)状态

WM_QUERYUISTATE

0x0129

应用程序发送此消息得到某个窗口的用户界面(UI)状态

WM_CTLCOLORMSGBOX

0x0132

绘制消息框前发送此消息给它的父窗口,通过响应这条消息,父窗口可以通过使用给定的相关显示设备的句柄来设置消息框的文本和背景颜色

WM_CTLCOLOREDIT

0x0133

绘制编辑型控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

WM_CTLCOLORLISTBOX

0x0134

绘制列表框控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

WM_CTLCOLORBTN

0x0135

绘制按钮控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

WM_CTLCOLORDLG

0x0136

绘制对话框前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

WM_CTLCOLORSCROLLBAR

0x0137

绘制滚动条控件前发送此消息给它的父窗口,可用来设置滚动条控件的文本和背景颜色

WM_CTLCOLORSTATIC

0x0138

绘制静态控件前发送此消息给它的父窗口,可用来设置静态控件的文本和背景颜色

WM_MOUSEMOVE

0x0200

鼠标移动

WM_LBUTTONDOWN

0x0201

按下鼠标左键

WM_LBUTTONUP

0x0202

释放鼠标左键

WM_LBUTTONDBLCLK

0x0203

双击鼠标左键

WM_RBUTTONDOWN

0x0204

按下鼠标右键

WM_RBUTTONUP

0x0205

释放鼠标右键

WM_RBUTTONDBLCLK

0x0206

双击鼠标右键

WM_MBUTTONDOWN

0x0207

按下鼠标中键

WM_MBUTTONUP

0x0208

释放鼠标中键

WM_MBUTTONDBLCLK

0x0209

双击鼠标中键

WM_MOUSEWHEEL

0x020A

当鼠标滚轮转动时发送此消息给当前获得焦点的窗口

WM_PARENTNOTIFY

0x0210

当MDI子窗口被创建或被销毁,或当光标位于子窗口上且用户按了一下鼠标键时,发送此消息给它的父窗口

WM_ENTERMENULOOP

0x0211

发送此消息通知应用程序的主窗口进程已经进入了菜单模式循环

WM_EXITMENULOOP

0x0212

发送此消息通知应用程序的主窗口进程已经退出了菜单模式循环

WM_SIZING

0x0214

调整窗口大小时发送此消息给窗口,通过此消息应用程序可以监视或修改窗口大小和位置

WM_CAPTURECHANGED

0x0215

当窗口设定为不捕获鼠标事件时,发送此消息给该窗口

WM_MOVING

0x0216

移动窗口时发送此消息给窗口,通过此消息应用程序可以监视或修改窗口大小和位置

WM_POWERBROADCAST

0x0218

发送此消息给应用程序通知它有关电源管理事件

WM_DEVICECHANGE

0x0219

当设备的硬件配置改变时发送此消息给应用程序或设备驱动程序

WM_MDICREATE

0x0220

应用程序发送此消息给多文档的客户窗口来创建一个MDI 子窗口

WM_MDIDESTROY

0x0221

应用程序发送此消息给多文档的客户窗口来关闭一个MDI 子窗口

WM_MDIACTIVATE

0x0222

应用程序发送此消息给多文档的客户窗口通知客户窗口激活另一个MDI子窗口,当客户窗口收到此消息后,它发出WM_MDIACTIVE消息给MDI子窗口(未激活)来激活它

WM_MDIRESTORE

0x0223

应用程序发送此消息给MDI客户窗口通知子窗口恢复到原来大小

WM_MDINEXT

0x0224

应用程序发送此消息给MDI客户窗口激活下一个或前一个窗口

WM_MDIMAXIMIZE

0x0225

应用程序发送此消息给MDI客户窗口以最大化一个MDI子窗口

WM_MDITILE

0x0226

应用程序发送此消息给MDI客户窗口以平铺方式重新排列所有MDI子窗口

WM_MDICASCADE

0x0227

应用程序发送此消息给MDI客户窗口以层叠方式重新排列所有MDI子窗口

WM_MDIICONARRANGE

0x0228

应用程序发送此消息给MDI客户窗口重新排列所有最小化的MDI子窗口

WM_MDIGETACTIVE

0x0229

应用程序发送此消息给MDI客户窗口以找到激活的子窗口的句柄

WM_MDISETMENU

0x0230

应用程序发送此消息给MDI客户窗口用MDI菜单代替子窗口的菜单

WM_ENTERSIZEMOVE

0x0231

当窗口进入移动或改变大小模式循环时,发送此消息给该窗口

WM_EXITSIZEMOVE

0x0232

当窗口退出移动或改变大小模式循环时,发送此消息给该窗口

WM_DROPFILES

0x0233

当用户在应用程序窗口中拖动某个文件时,产生此消息

WM_MDIREFRESHMENU

0x0234

应用程序发送此消息给MDI客户窗口以刷新窗口菜单

WM_MOUSEHOVER

0x02A1

当光标在窗口客户区悬停超过TrackMouseEvent()指定的时间时,发送此消息给该窗口

WM_MOUSELEAVE

0x02A3

当光标离开窗口客户区超过TrackMouseEvent()指定的时间时,发送此消息给该窗口

WM_CUT

0x0300

应用程序发送此消息给一个编辑框或ComboBox以删除当前选择的文本

WM_COPY

0x0301

应用程序发送此消息给一个编辑框或ComboBox以复制当前选择的文本到剪贴板

WM_PASTE 

0x0302

应用程序发送此消息给一个编辑框或ComboBox以从剪贴板中得到数据

WM_CLEAR

0x0303

应用程序发送此消息给一个编辑框或ComboBox以清除当前选择的内容

WM_UNDO

0x0304

应用程序发送此消息给一个编辑框或ComboBox以撤消最后一次操作

WM_DESTROYCLIPBOARD

0x0307

当调用EmptyClipboard()清空剪贴板时,发送此消息给剪贴板所有者

WM_DRAWCLIPBOARD

0x0308

当剪贴板的内容变化时发送此消息给剪贴板观察链中的第一个窗口,它允许用剪贴板观察窗口来显示剪贴板的新内容

WM_PAINTCLIPBOARD

0x0309

当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口的客户区需要重绘时,发送此消息给剪贴板所有者

WM_VSCROLLCLIPBOARD

0x030A

当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口发生垂直滚动条事件时,剪贴板观察窗口发送此消息给剪贴板所有者

WM_SIZECLIPBOARD

0x030B

当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口的客户区域的大小已经改变时,剪贴板观察窗口发送此消息给剪贴板的所有者

WM_ASKCBFORMATNAME

0x030C

剪贴板观察窗口发送此消息给剪贴板所有者以获得CF_OWNERDISPLAY剪贴板格式的名字

WM_CHANGECBCHAIN

0x030D

当一个窗口从剪贴板观察链中移去时发送此消息给剪贴板观察链中的第一个窗口

WM_HSCROLLCLIPBOARD

0x030E

当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口发生水平滚动条事件时,剪贴板观察窗口发送此消息给剪贴板所有者

WM_QUERYNEWPALETTE

0x030F

发送此消息给将要获得键盘焦点的窗口,此消息使窗口在获得焦点时同时有机会实现它的逻辑调色板

WM_PALETTEISCHANGING

0x0310

应用程序将要实现它的逻辑调色板时发送此消息通知所有应用程序

WM_PALETTECHANGED

0x0311

获得焦点的窗口实现它的逻辑调色板后发送此消息给所有顶级并重叠的窗口,以此

来改变系统调色板

WM_HOTKEY

0x0312

当用户按下由RegisterHotKey()注册的热键时产生此消息

WM_PRINT

0x0317

应用程序发送此消息给窗口,要求窗口在指定设备环境中绘制自己,一般情况下是打印机设备环境

WM_PRINTCLIENT

0x0318

应用程序发送此消息给窗口,要求窗口在指定设备环境中绘制窗口客户区,一般情况下是打印机设备环境

WM_APP

0x8000

帮助用户自定义消息,自定义消息可以为WM_APP+X,X为正整数

WM_USER

0x0400

帮助用户自定义消息,自定义消息可以为WM_USER+X,X为正整数

WM_CHANGECBCHAIN =781

// 移动鼠标

WM_PRINTCLIENT =792

此消息发送给将要收到焦点的窗口,此消息能使窗口在收到焦点时同时有机会实现他的逻辑调色板

WM_INITMENUPOPUP =279

WM_KEYDOWN = 256

通过使用给定的相关显示设备的句柄来设置滚动条的背景颜色

C B N _ D B L C L K用户双击了一个字符串

WM_WINDOWPOSCHANGED= 71

WM_SETICON = 128

WM_MDICASCADE = 551

B N _ U N H I L I TE加亮应当去掉

按扭

一个窗口被激活或失去激活状态;

当button,combobox,listbox,menu的可视外观改变时发送

好了,事情到了这一步,应该一切都明朗了。
不过,我们发现在windowsx.h里面还有一个宏:FORWARD_WM_XXXX,我们还是那WM_COMMAND为例,进行分析:

知父窗口。通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows
95公

当用户选择窗口菜单的一条命令或当用户选择最大化或最小化时那个窗口会收到此消息

WM_IME_KEYUP = 657

云顶娱乐平台 41LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
云顶娱乐平台 42{
云顶娱乐平台 43 int wmId, wmEvent;
云顶娱乐平台 44 PAINTSTRUCT ps;
云顶娱乐平台 45 HDC hdc;
云顶娱乐平台 46 TCHAR szHello[MAX_LOADSTRING];
云顶娱乐平台 47 LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
云顶娱乐平台 48
云顶娱乐平台 49 switch (message) 
云顶娱乐平台 50 {
云顶娱乐平台 51  case WM_COMMAND:
云顶娱乐平台 52         wmId    = LOWORD(wParam); 
云顶娱乐平台 53         wmEvent = HIWORD(wParam); 
云顶娱乐平台 54         // Parse the menu selections:
云顶娱乐平台 55         switch (wmId)
云顶娱乐平台 56         {
云顶娱乐平台 57          case IDM_ABOUT:
云顶娱乐平台 58             DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
云顶娱乐平台 59             break;
云顶娱乐平台 60          case IDM_EXIT:
云顶娱乐平台 61             DestroyWindow(hWnd);
云顶娱乐平台 62             break;
云顶娱乐平台 63          default:
云顶娱乐平台 64             return DefWindowProc(hWnd, message, wParam, lParam);
云顶娱乐平台 65         }
云顶娱乐平台 66   break;
云顶娱乐平台 67
云顶娱乐平台 68  case WM_PAINT:
云顶娱乐平台 69         hdc = BeginPaint(hWnd, &ps);
云顶娱乐平台 70         // TODO: Add any drawing code here云顶娱乐平台 71
云顶娱乐平台 72         RECT rt;
云顶娱乐平台 73         GetClientRect(hWnd, &rt);
云顶娱乐平台 74         DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
云顶娱乐平台 75         EndPaint(hWnd, &ps);
云顶娱乐平台 76         break;
云顶娱乐平台 77
云顶娱乐平台 78  case WM_DESTROY:
云顶娱乐平台 79         PostQuitMessage(0);
云顶娱乐平台 80         break;
云顶娱乐平台 81  default:
云顶娱乐平台 82         return DefWindowProc(hWnd, message, wParam, lParam);
云顶娱乐平台 83  }
云顶娱乐平台 84  return 0;
云顶娱乐平台 85}
云顶娱乐平台 86

消息是指什么?
    
消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉。一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向
Windows发出一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。
   
消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做MSG,MSG含有来自windows应用程序消息队列的消息信息,它在Windows中声明如下:

当一个滚动条控件将要被绘制时发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

此消息后,它发出WM_MDIACTIVE消息给MDI子窗口(未激活)激活它;

实际上,HANDLE_WM_XXXX都是宏,例如:HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);将被转换成如下定义:

当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序,

当一个菜单将要被激活时发送此消息,它发生在用户菜单条中的某项或按下某个菜单键,它允许

WM_INPUTLANGCHANGEREQUEST= 80

队列消息和非队列消息
   从消息的发送途径来看,消息可以分成2种:队列消息和非队列消息。消息队列由可以分成系统消息队列和线程消息队列。系统消息队列由Windows维护,线程消息队列则由每个GUI线程自己进行维护,为避免给non-GUI现成创建消息队列,所有线程产生时并没有消息队列,仅当线程第一次调用GDI函数时系统才给线程创建一个消息队列。队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
    
对于队列消息,最常见的是鼠标和键盘触发的消息,例如WM_MOUSERMOVE,WM_CHAR等消息,还有一些其它的消息,例如:WM_PAINT、
WM_TIMER和WM_QUIT。当鼠标、键盘事件被触发后,相应的鼠标或键盘驱动程序就会把这些事件转换成相应的消息,然后输送到系统消息队列,由
Windows系统去进行处理。Windows系统则在适当的时机,从系统消息队列中取出一个消息,根据前面我们所说的MSG消息结构确定消息是要被送往那个窗口,然后把取出的消息送往创建窗口的线程的相应队列,下面的事情就该由线程消息队列操心了,Windows开始忙自己的事情去了。线程看到自己的消息队列中有消息,就从队列中取出来,通过操作系统发送到合适的窗口过程去处理。
    
一般来讲,系统总是将消息Post在消息队列的末尾。这样保证窗口以先进先出的顺序接受消息。然而,WM_PAINT是一个例外,同一个窗口的多个
WM_PAINT被合并成一个 WM_PAINT 消息,
合并所有的无效区域到一个无效区域。合并WM_PAIN的目的是为了减少刷新窗口的次数。
云顶娱乐平台 87

WM_DRAWCLIPBOARD =776

type

当一个列表框控件将要被绘制前发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

消息的处理
  接下来我们谈一下消息的处理,首先我们来看一下VC中的消息泵:

当剪贴板的内容变化时发送此消息给剪贴板观察链的第一个窗口;它允许用剪贴板观察窗口来

发送此消息通知应用程序的主窗口that已经进入了菜单循环模式

当用户选择一条菜单命令项或当某个控件发送一条消息给它的父窗口,一个快捷键被翻译

WM_HANDHELDFIRST =856

当设备的硬件配置改变时发送此消息给应用程序或设备驱动程序

此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序能

消息标识符的值
    
系统保留消息标识符的值在0x0000在0x03ff(WM_USER-1)范围。这些值被系统定义消息使用。应用程序不能使用这些值给自己的消息。应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到
0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,我们顺便说一下具有标志性的消息值:
     WM_NULL—0x0000    空消息。
     0x0001—-0x0087    主要是窗口消息。
     0x00A0—-0x00A9    非客户区消息 
     0x0100—-0x0108    键盘消息
     0x0111—-0x0126    菜单消息
     0x0132—-0x0138    颜色控制消息
     0x0200—-0x020A    鼠标消息
     0x0211—-0x0213    菜单循环消息
     0x0220—-0x0230    多文档消息
     0x03E0—-0x03E8    DDE消息
     0x0400              WM_USER
     0x8000              WM_APP
     0x0400—-0x7FFF    应用程序自定义私有消息

WM_CHARTOITEM = 47

当一个窗口标准垂直滚动条产生一个滚动事件时发送此消息给那个窗口也,发送给拥有它的控件
WM_INITMENU = 278

WM_MDICREATE = 544

改变全部

WM_DDE_FIRST = 992

在一个对话框程序被显示前发送此消息给它,通常用此消息初始化控件和执行其它任务

pt: TPoint / /消息创建时的鼠标位置

WM_IME_CONTROL =643

云顶娱乐平台 88
   
非队列消息将会绕过系统队列和消息队列,直接将消息发送到窗口过程,。系统发送非队列消息通知窗口,系统发送消息通知窗口。例如,当用户激活一个窗口系统发送WM_ACTIVATE,
WM_SETFOCUS, and
WM_SETCURSOR。这些消息通知窗口它被激活了。非队列消息也可以由当应用程序调用系统函数产生。例如,当程序调用SetWindowPos系统发送WM_WINDOWPOSCHANGED消息。一些函数也发送非队列消息,例如下面我们要谈到的函数。
     
消息的发送
    
了解了上面的这些基础理论之后,我们就可以进行一下简单的消息发送与接收。
     把一个消息发送到窗口有3种方式:发送、寄送和广播。
    
发送消息的函数有SendMessage、SendMessageCallback、SendNotifyMessage、
SendMessageTimeout;寄送消息的函数主要有PostMessage、PostThreadMessage、
PostQuitMessage;广播消息的函数我知道的只有BroadcastSystemMessage、
BroadcastSystemMessageEx。
     SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT
Msg,WPARAM wParam,LPARAM
lParam),这个函数主要是向一个或多个窗口发送一条消息,一直等到消息被处理之后才会返回。不过需要注意的是,如果接收消息的窗口是同一个应用程序的一部分,那么这个窗口的窗口函数就被作为一个子程序马上被调用;如果接收消息的窗口是被另外的线程所创建的,那么窗口系统就切换到相应的线程并且调用相应的窗口函数,这条消息不会被放进目标应用程序队列中。函数的返回值是由接收消息的窗口的窗口函数返回,返回的值取决于被发送的消息。
     PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM
wParam,LPARAM
lParam),该函数把一条消息放置到创建hWnd窗口的线程的消息队列中,该函数不等消息被处理就马上将控制返回。需要注意的是,如果hWnd参数为
HWND_BROADCAST,那么,消息将被寄送给系统中的所有的重叠窗口和弹出窗口,但是子窗口不会收到该消息;如果hWnd参数为NULL,则该函数类似于将dwThreadID参数设置成当前线程的标志来调用PostThreadMEssage函数。
  从上面的这2个具有代表性的函数,我们可以看出消息的发送方式和寄送方式的区别所在:被发送的消息是否会被立即处理,函数是否立即返回。被发送的消息会被立即处理,处理完毕后函数才会返回;被寄送的消息不会被立即处理,他被放到一个先进先出的队列中,一直等到应用程序空线的时候才会被处理,不过函数放置消息后立即返回。
云顶娱乐平台 89
  实际上,发送消息到一个窗口处理过程和直接调用窗口处理过程之间并没有太大的区别,他们直接的唯一区别就在于你可以要求操作系统截获所有被发送的消息,但是不能够截获对窗口处理过程的直接调用。
  以寄送方式发送的消息通常是与用户输入事件相对应的,因为这些事件不是十分紧迫,可以进行缓慢的缓冲处理,例如鼠标、键盘消息会被寄送,而按钮等消息则会被发送。
  广播消息用得比较少,BroadcastSystemMessage函数原型如下:
      long BroadcastSystemMessage(DWORD dwFlags,LPDWORD
lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM
lParam);该函数可以向指定的接收者发送一条消息,这些接收者可以是应用程序、可安装的驱动程序、网络驱动程序、系统级别的设备驱动消息和他们的任意组合。需要注意的是,如果dwFlags参数是BSF_QUERY并且至少一个接收者返回了BROADCAST_QUERY_DENY,则返回值为0,如果没有指定BSF_QUERY,则函数将消息发送给所有接收者,并且忽略其返回值。

WM_SIZE = 5

通知消息(Notification
message)是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通

一个DDE应用程序(无论是客户还是服务器)提交此消息来终止一个会话;

hwnd: HWND / /窗口句柄

WM_DDE_ADVISE =WM_DDE_FIRST + 2

列表框控件
 LBN_DBLCLK 用户双击了一项
 LBN_ERRSPACE 列表框内存不够
 LBN_KILLFOCUS 列表框正在失去输入焦点
 LBN_SELCANCEL 选择被取消
 LBN_SELCHANGE 选择了另一项
 LBN_SETFOCUS 列表框获得输入焦点

表A-5  通知消息-编辑框

WM_MOUSELEAVE = 675

WM_CTLCOLORSTATIC =312

程序发送此消息给一个编辑框或combobox来复制当前选择的文本到剪贴板

WM_EXITMENULOOP =530

此消息通过一个剪贴板观察窗口发送给剪贴板的所有者;它发生在当剪贴板包含CFOWNERDISPALY格式的数据并且有个事件在剪贴板观察窗的水平滚动条上;所有者应滚动剪贴板图象并更新滚动条的值;

当一个模态对话框或菜单进入空载状态时发送此消息给它的所有者,一个模态对话框或菜单进入空载状态就是在处理完一条或几条先前的消息后没有消息它的列队中等待

WM_MDIDESTROY = 545

列表框

WM_QUERYOPEN = 19

当用户双击鼠标中键同时光标又在窗口的非客户区时发送此消息

WM_MENURBUTTONUP =290

WM_CHANGEUISTATE =295

WM_MDIACTIVATE =546

message
用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。

应用程序发送此消息来设置一个窗口的文本

WM_CANCELJOURNAL =75

WM_GETFONT = 49

WM_UNINITMENUPOPUP= 293

WM_ENABLE = 10

当用户双击鼠标左键同时光标某个窗口在非客户区十发送此消息

滚动条都会产生通知消息。

WM_GETTEXTLENGTH =14

WM_NCMBUTTONDBLCLK= 169

显示内存已经很少了

发送此消息给一个对话框程序去更改焦点位置

WM_IME_SELECT = 645

hwnd
32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)。

当调用SETWINDOWLONG函数一个或多个 窗口的风格后发送此消息给那个窗口

WM_LBUTTONDOWN =513

WM_DDE_LAST =WM_DDE_FIRST + 8

WM_VSCROLL = 277

是否觉得一个消息记录中的信息像希腊语一样?如果是这样,那么看一看下面的解释:

WM_CTLCOLORBTN =309

WM_CTLCOLORLISTBOX= 308

当一个应用程序正要实现它的逻辑调色板时发此消息通知所有的应用程序

消息中有什么?

当用户某个窗口中点击了一下右键就发送此消息给这个窗口

B N _ H I L I T E//用户加亮了按钮

WM_UPDATEUISTATE =296

移动一个窗口

WM_SETHOTKEY = 50

WM_HELP = 83

消息范围

说 明

0 ~ WM_USER – 1

系统消息

WM_USER ~ 0x7FFF

自定义窗口类整数消息

WM_APP ~ 0xBFFF

应用程序自定义消息

0xC000 ~ 0xFFFF

应用程序字符串消息

> 0xFFFF

为以后系统应用保留

WM_SIZING = 532

当用户按下鼠标右键同时光标又在窗口的非客户区时发送此消息

 

C B N _ E D I T U PD AT E编辑框内的文本即将更新

WM_WINDOWPOSCHANGING= 70

当用户选择某种输入语言,或输入语言的热键改变

WM_LBUTTONDBLCLK =515

WM_GETOBJECT = 61

WM_DRAWITEM = 43

WM_SYSCHAR = 262

WM_PAINTICON = 38

消息有哪几种?
   其实,windows中的消息虽然很多,但是种类并不繁杂,大体上有3种:窗口消息、命令消息和控件通知消息。
    
窗口消息大概是系统中最为常见的消息,它是指由操作系统和控制其他窗口的窗口所使用的消息。例如CreateWindow、DestroyWindow和MoveWindow等都会激发窗口消息,还有我们在上面谈到的单击鼠标所产生的消息也是一种窗口消息。
    
命令消息,这是一种特殊的窗口消息,他用来处理从一个窗口发送到另一个窗口的用户请求,例如按下一个按钮,他就会向主窗口发送一个命令消息。
    
控件通知消息,是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通知父窗口。通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows公共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中选择部分文本、操作控件的滚动条都会产生通知消息。她类似于命令消息,当用户与控件窗口交互时,那么控件通知消息就会从控件窗口发送到它的主窗口。但是这种消息的存在并不是为了处理用户命令,而是为了让主窗口能够改变控件,例如加载、显示数据。例如按下一个按钮,他向父窗口发送的消息也可以看作是一个控件通知消息;单击鼠标所产生的消息可以由主窗口直接处理,然后交给控件窗口处理。
   
其中窗口消息及控件通知消息主要由窗口类即直接或间接由CWND类派生类处理。相对窗口消息及控件通知消息而言,命令消息的处理对象范围就广得多,它不仅可以由窗口类处理,还可以由文档类,文档模板类及应用类所处理。
   
由于控件通知消息很重要的,人们用的也比较多,但是具体的含义往往令初学者晕头转向,所以我决定把常见的几个列出来供大家参考:
按扭控件
BN_CLICKED        用户单击了按钮
 BN_DISABLE 按钮被禁止
 BN_DOUBLECLICKED  用户双击了按钮
 BN_HILITE  用/户加亮了按钮
 BN_PAINT  按钮应当重画
 BN_UNHILITE 加亮应当去掉

WM_RENDERFORMAT =773

云顶娱乐平台 90while(GetMessage(&msg, NULL, 0, 0))
云顶娱乐平台 91{
云顶娱乐平台 92       if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg))
云顶娱乐平台 93      { 
云顶娱乐平台 94            TranslateMessage(&msg);
云顶娱乐平台 95            DispatchMessage(&msg);
云顶娱乐平台 96       }
云顶娱乐平台 97}

此消息在一个拥有焦点的窗口实现它的逻辑调色板后发送此消息给所有顶级并重叠的窗口,以此

当某个用户取消程序日志激活状态,提交此消息给程序

MFC的消息映射的基类CCmdTarget
  如果你想让你的控件能够进行消息映射,就必须从CCmdTarget类中派生。CCmdTarget类是MFC处理命令消息的基础、核心。MFC为该类设计了许多成员函数和一些成员数据,基本上是为了解决消息映射问题的,所有响应消息或事件的类都从它派生,例如:应用程序类、框架类、文档类、视图类和各种各样的控件类等等,还有很多。
不过这个类里面有2个函数对消息映射非常重要,一个是静态成员函数DispatchCmdMsg,另一个是虚函数OnCmdMsg。
DispatchCmdMsg专门供MFC内部使用,用来分发Windows消息。OnCmdMsg用来传递和发送消息、更新用户界面对象的状态。
CCmdTarget对OnCmdMsg的默认实现:在当前命令目标(this所指)的类和基类的消息映射数组里搜索指定命令消息的消息处理函数。
  这里使用虚拟函数GetMessageMap得到命令目标类的消息映射入口数组_messageEntries,然后在数组里匹配命令消息ID相同、控制通知代码也相同的消息映射条目。其中GetMessageMap是虚拟函数,所以可以确认当前命令目标的确切类。
如果找到了一个匹配的消息映射条目,则使用DispachCmdMsg调用这个处理函数;
如果没有找到,则使用_GetBaseMessageMap得到基类的消息映射数组,查找,直到找到或搜寻了所有的基类(到CCmdTarget)为止;
如果最后没有找到,则返回FASLE。
  每个从CCmdTarget派生的命令目标类都可以覆盖OnCmdMsg,利用它来确定是否可以处理某条命令,如果不能,就通过调用下一命令目标的
OnCmdMsg,把该命令送给下一个命令目标处理。通常,派生类覆盖OnCmdMsg时,要调用基类的被覆盖的OnCmdMsg。
  在MFC框架中,一些MFC命令目标类覆盖了OnCmdMsg,如框架窗口类覆盖了该函数,实现了MFC的标准命令消息发送路径。必要的话,应用程序也可以覆盖OnCmdMsg,改变一个或多个类中的发送规定,实现与标准框架发送规定不同的发送路径。例如,在以下情况可以作这样的处理:在要打断发送顺序的类中把命令传给一个非MFC默认对象;在新的非默认对象中或在可能要传出命令的命令目标中。

  消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做T
M s g,它在Wi n d o w s单元中是这样声明的:

WM_ASKCBFORMATNAME= 780

组合框

WM_COALESCE_FIRST =912

云顶娱乐平台 98void MsgCracker(HWND hWnd,int id,HWND hWndCtl,UINT codeNotify)
云顶娱乐平台 99{
云顶娱乐平台 100      switch(id)
云顶娱乐平台 101      {
云顶娱乐平台 102     case ID_A:
云顶娱乐平台 103                  if(codeNotify==EN_CHANGE)云顶娱乐平台 104
云顶娱乐平台 105                  break;
云顶娱乐平台 106     case ID_B:
云顶娱乐平台 107                  if(codeNotify==BN_CLICKED)云顶娱乐平台 108
云顶娱乐平台 109                  break;
云顶娱乐平台 110             云顶娱乐平台 111.
云顶娱乐平台 112       }
云顶娱乐平台 113}
云顶娱乐平台 114

WM_SIZECLIPBOARD =779

WM_SPOOLERSTATUS =42

通过剪贴板观察窗口发送此消息给剪贴板的所有者来请求一个CF_OWNERDISPLAY格式的剪贴板的名字

当鼠标轮子转动时发送此消息个当前有焦点的控件

//释放鼠标左键

当一个窗口标准水平滚动条产生一个滚动事件时发送此消息给那个窗口,也发送给拥有它的控件

WM_VKEYTOITEM = 46

WM_PALETTEISCHANGING=784

WM_SETFONT = 48

所以实际上,FORWARD_WM_XXXX将消息参数进行了重新构造,生成了wParam &&
lParam,然后调用了我们定义的函数。

当平台现场已经被改变后发送此消息给受影响的最顶级窗口

WM_VSCROLLCLIPBOARD= 778

WM_COPY = 769

在WindowsX.h中定义了如下的HANDLE_MSG宏:

如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,就发消息给某个窗口

C B N _ S E L E N DC A N C E L用户的选择应当被取消

当系统的时间变化时发送此消息给所有顶级窗口

time: DWORD / /消息创建时的时间

当调用SETWINDOWLONG函数将要改变一个或多个
窗口的风格时发送此消息给那个窗口

通过使用给定的相关显示设备的句柄来设置对话框的文本背景颜色

设置窗口是否能重画

//按下某键,并已发出WM_KEYDOWN, WM_KEYUP消息

WM_SETTEXT = 12

WM_MEASUREITEM = 44

当一个对话框控件将要被绘制前发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

WM_GETHOTKEY = 51

当用户释放鼠标左键同时光标某个窗口在非客户区十发送此消息;

当用户释放一个键同时ALT 键还按着时提交此消息给拥有焦点的窗口

MFC消息的处理实现方式
  初看MFC中的各种消息,以及在头脑中根深蒂固的C++的影响,我们可能很自然的就会想到利用C++的三大特性之一:虚拟机制来实现消息的传递,但是经过分析,我们看到事情并不是想我们想象的那样,在MFC中消息是通过一种所谓的消息映射机制来处理的。
  为什么呢?在潘爱民老师翻译的《Visual
C++技术内幕》(第4版)中给出了详细的原因说明,我再简要的说一遍。在CWnd类中大约有110个消息,还有其它的MFC的类呢,算起来消息太多了,在C++中对程序中用到的每一个派生类都要有一个vtable,每一个虚函数在vtable中都要占用一个4字节大小的入口地址,这样一来,对于每个特定类型的窗口或控件,应用程序都需要一个440KB大小的表来支持虚拟消息控件函数。
  如果说上面的窗口或控件可以勉强实现的话,那么对于菜单命令消息及按钮命令消息呢?因为不同的应用程序有不同的菜单和按钮,我们怎么处理呢?在MFC
库的这种消息映射系统就避免了使用大的vtable,并且能够在处理常规Windows消息的同时处理各种各样的应用程序的命令消息。
  说白了,MFC中的消息机制其实质是一张巨大的消息及其处理函数的一一对应表,然后加上分析处理这张表的应用框架内部的一些程序代码.这样就可以避免在SDK编程中用到的繁琐的CASE语句。

程序发送此消息给MDI客户窗口用MDI菜单代替子窗口的菜单

WM_DEVICECHANGE =537

WM_NCRBUTTONDBLCLK= 166

一个DDE客户程序提交此消息给一个DDE服务程序来请求一个数据项的值;

应用程序发送此消息来复制对应窗口的文本到缓冲区

当某个窗口的客户区域必须被核算时发送此消息

WM_MOVE = 3

此消息能帮助应用程序自定义私有消息;

WM_NOTIFY = 78

当系统将要进入暂停状态时发送此消息

WM_APP = 32768

此消息发送给某个最小化窗口,仅当它在画图标前它的背景必须被重画

WM_CONTEXTMENU =123

L B N _ S E L C A NC E L选择被取消

WM_IME_NOTIFY = 642

当调用ENPTYCLIPBOARD函数时 发送此消息给剪贴板的所有者

WM_MENUGETOBJECT =292

返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标

WM_IME_KEYDOWN =656

当程序已经初始化windows帮助例程时发送此消息给应用程序

//双击鼠标中键

此消息发送给应用程序来通知它有关电源管理事件;

发送此消息通知应用程序的主窗口that已退出了菜单循环模式

云顶娱乐平台 115   #define HANDLE_MSG(hwnd,msg,fn) 
云顶娱乐平台 116             switch(msg): return HANDLE_##msg((hwnd),(wParam),(lParam),(fn));

WM_ENTERIDLE = 289

程序发送此消息给MDI客户窗口重新排列所有最小化的MDI子窗口