那些“消息”

来源:互联网 发布:食堂刷卡机数据导出 编辑:程序博客网 时间:2024/05/01 22:40

WM_QUIT,WM_CLOSE,WM_DESTROY

WM_CLOSE:

  在系统菜单里选择了“关闭”或者点击了窗口右上角的“X”按钮,你的窗口过程就会收到WM_CLOSE。DefWindowProc对WM_CLOSE的处理是调用DestroyWindow。当然,你可以不让DefWindowProc处理,而是自己处理,例如询问用户是否保存更改等。如果用户选择“取消”,你忽略此消息,那么程序照常运行;如果用户确认要退出,你就调用DestroyWindow。


WM_DESTROY:

  接下来,DestroyWindow完成窗口的清理工作,最后像窗口过程发送WM_DESTROY。对于WM_DESTROY,DefWindowProc不会处理。也就是说,你如果不处理这个消息,虽然你的窗口已经销毁,但进程并不会结束。一般处理WM_DESTROY时都是释放资源(例如申请的内存等),然后调用PostQuitMessage。

 

WM_QUIT:

  PostQuitMessage会发送WM_QUIT给消息队列。注意,WM_QUIT永远不会到达窗口过程,因为GetMessage得到WM_QUIT后就会返回FALSE,从而结束消息循环,最后进程结束,程序退出。

 

SendMessage 和 PostMessage 的区别

 

PostMessage 只是把消息放入队列,不管其他程序是否处理都返回,然后继续执行 ;
SendMessage 必须等待其他程序处理消息后才返回,继续执行。

PostMessage
的返回值表示 PostMessage 函数执行是否正确 ;
SendMessage 的返回值表示其他程序处理消息后的返回值。


使用这两个发送消息函数的最重要的是要看你的程序是否要对消息的滞后性关注否 ,PostMessage 会造成消息的滞后性 , SendMessage 则不会 , 但如果 SendMessage 消息处理失败 , 则会造成程序停止 !

 

SendMessage (GetSafeHwnd(), WM_QUIT, 0, 0)为什么没用

在MSDN中查WM_QUIT

1、首先是返回值意义的区别,我们先看一下 MSDN 里的声明:
LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
BOOL PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);                                                                                                                                                                 
其中 4 个参数的意义是一样的,返回值类型不同(其实从数据上看他们一样是一个 32 位的数,只是意义不一样),LRESULT 表示的是消息被处理后的返回值,BOOL 表示的是消息是不是 Post 成功。                  
2、PostMessage 是异步的,SendMessage 是同步的。                                                                     
PostMessage 只把消息放入队列,不管消息是否被处理就返回,消息可能不被处理;而 SendMessage 等   待消息被处理完了之后才返回,如果消息不被处理,发送消息的线程将一直被阻塞。                                 
3、如果在同一个线程内,SendMessage 发送消息时,由 USER32.DLL 模块调用目标窗口的消息处理程     序,并将结果返回。SendMessage 在同一线程中发送消息并不入线程消息队列。PostMessage 发送消息    时,消息要先放入线程的消息队列,然后通过消息循环分派到目标窗口(DispatchMessage)。                
如果在不同线程内,SendMessage 发送消息到目标窗口所属线程的消息队列,然后发送消息的线程在    USER32.DLL 模块内监视和等待消息处理,直到目标窗口处理完返回。SendMessage 在返回前还做了很多工作,比如,响应别的线程向它 SendMessage。Post 到别的线程时,最好用 PostThreadMessage 代替    PostMessage,PostMessage 的 hWnd 参数可以是 NULL,等效于 PostThreadMessage + GetCurrentThreadId。Post WM_QUIT 时,应使用 PostQuitMessage 代替。                                             
4、系统只整编(marshal)系统消息(0 到 WM_USER 之间的消息),发送用户消息(WM_USER 以上)到别的进程时,需要自己做整编。                                                                                                              
用 PostMessage、SendNotifyMessage、SendMessageCallback 等异步函数发送系统消息时,参数里不可以使用指针,因为发送者并不等待消息的处理就返回,接受者还没处理指针就已经被释放了。                    
5、在 Windows 2000/XP 里,每个消息队列最多只能存放 10,000 个 Post 的消息,超过的还没被处理的将   不会被处理,直接丢掉。这个值可以改得更大:                                                                                            [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Windows]     USERPostMessageLimit,最小可以是 4000。    

 

 

 

 

 

 

 

Do not post the WM_QUIT message using the PostMessage function; use PostQuitMessage。至于为什么,就得看PostQuitMessage做什么事了。现在不讨论为什么不让使用PostMessage发送WM_QUIT消息,但就为什么SendMessage无法完成PostMessage能完成的功能来做一下研究。

注意到WM_QUIT消息让消息循环终止归根结底是让GetMessage返回为0,而GetMessage函数是从消息对列里取一条消息,然后再返回,只能当消息为WM_QUIT时才返回0结束消息循环。再仔细看一下SendMessage的注释发现,SendMessage直接发送到窗口,并调用窗口处理程序,完成消息响应,即SendMessage 根本就没有将消息发到消息对列中,因此GetMessage无法从消息对列中收到WM_QUIT的消息。而PostMessage却直接发送消息到消息对列中,然后立即返回,这一点点的区别就解决了我们上面的问题。

    了解了这一点,就不难理解上面注释中说的为什么不让直接使用PostMessage来发送WM_QUIT消息来终止程序了。

    另外需要注意的是,发送消息让对话框关闭,应该发送WM_CLOSE消息,这样可以让对话框完成它自身的资源释放回收。

 

 

原创粉丝点击