学习Windows 编程,从MSDN翻译开始--1

来源:互联网 发布:淘宝天猫优惠券招代理 编辑:程序博客网 时间:2024/06/05 18:38

Using Messages and Message Queues

Creating a Message Loop 创建一个消息循环

系统通常不会自动为每一个线程创建一个消息队列。相反,系统只会为那些执行操作并且这些操作需要一个消息队列的线程创建消息队列。如果线程创建了一个或多个窗口,那系统必定会为其提供一个消息循环。该消息循环通过GetMessage函数从消息队列中检索消息,然后通过相应的窗口过程来处理它们。

因为在一个应用程序中,系统是为特定的窗口传递消息的,所以在某个线程进入它的消息循环之前至少要创建一个窗口。大部分的应用程序都是单线程创建窗口的,即主线程。一个经典的应用程序通常是这样的:为其主窗口创建注册一个窗口类,然后创建显示出它的主窗口,然后再启动消息循环·····所有这些都会写在WinMain函数里。

你在创建消息循环时都会用到GetMessage和DispatchMessage函数。如果你的应用程序一定要能够接受用户的字符消息(诸如WM_KEYDOWN,WM_KEYUP),那就应该在消息循环中加上TranslateMessage函数。TranslateMessage函数能够将虚拟键消息转换成字符消息。下面这个例子就是一个基本的应用程序的消息循环实现:

下面是一个线程的消息循环,线程中使用了键盘加速并显示一个非模态对话框。当TranslateAccelerator函数或IsDialogMessage函数返回True时(表明消息已经被处理了),TranslateMessage和DispatchMessage将不被调用。原因是TranslateAccelerator和IsDialogMessage已经做了所有必要的消息转换和消息处理工作。

有时候,应用程序需要从线程消息循环外面来检测消息队列的内容。例如,如果一个应用程序的窗口过程正在执行一个很长的描画操作,你可以期望用户可以中断这个操作。除非你的应用程序在描画操作的执行过程中能定期的检测鼠标键盘消息,否则直到描画操作结束应用程序都不会响应用户的输入。原因就是线程消息循环中的DispatchMessage函数会一直等待,等窗口过程处理完那个窗口描画操作,DispatchMessage才会返回。

在一个较长的操作执行的过程中,你可以通过PeekMessage函数来检测消息队列。PeekMessage函数跟GetMessage函数很相似,这两者都是从消息队列中检索出符合条件的消息,并且会复制消息的相关信息存储到一个MSG类型的结构体中。这两者主要的区别就是GetMessage直到找到一个符合条件的消息才会返回,而PeekMessage不会考虑消息队列中是否存在消息,立即返回。

其他的函数包括GetQueueStatus和GetInputStatus也允许你去检测一个线程消息队列的内容。GetQueueStatus返回一个消息队列中消息类型的标志的数组。这个函数是判断一个消息队列中是否存在消息的最快的方法。GetInputStatus在检索到鼠标或键盘消息时返回TRUE。这两个函数都可以用来判断消息队列中是否存在需要被处理的消息。

Posting a Message

你可以通过PostMessage函数发送一个消息到消息队列中。PostMessage会把消息放到消息队列的最后,然后会立即返回,它并不会等待线程去处理这个消息。这个函数的参数包括窗口的句柄,一个消息的标识符和两个消息参数。系统会拷贝这些参数到一个MSG类型的结构体,然后再填充结构体中的time和pt两个参数,最后把这个结构体放置到消息队列中。

系统会通过PostMessage函数传入的句柄来决定哪个线程的消息队列来接受这个消息。如果窗口句柄是HWND_TOPMOST,则系统会将消息放在顶层窗口的线程消息队列中。

你可以通过PostThreadMessage函数来给一个指定的线程消息队列发送消息。PostThreadMessage跟PostMessage很相似,只是第一个参数不一样。你可以通过GetCurrentThreadId函数来取得线程的标识符。

使用PostQuitMessage函数来退出消息循环。PostQuitMessage会向当前执行线程发送一个WM_QUIT消息。线程的消息循环终止然后将控制权限返回给操作系统,PostQuitMessage函数通常用来响应WM_DESTORY消息。

Sending a Message

SendMessage函数用于直接向窗口过程发送消息。SendMessage函数调用窗口过程,等待窗口过程处理完这个消息才返回。通过这个函数可以向操作系统的任何一个窗口发送消息。所有这一切都只需要一个窗口句柄。操作系统通过这个窗口句柄来决定由哪个窗口过程来处理这个消息。

消息有可能是从另外一个线程发送来的,所以在处理消息之前,窗口过程会调用InSentMessage函数来做判断。如果InSentMessage返回TRUE,则窗口过程需要在第一时间调用ReplyMessage函数。

 

原创粉丝点击