窗口机制 消息循环 消息队列

合集下载

Windows消息机制详解

Windows消息机制详解

Windows消息机制详解Windows操作系统最大的特点就是其图形化的操作界面,其图形化界面是建立在其消息处理机制这个基础之上的。

如果不理解Windows消息处理机制,肯定无法深入的理解Windows编程。

可惜很多程序员对W indows消息只是略有所闻,对其使用知之甚少,更不了解其内部实现原理,本文试着一步一步向大家披露我理解的Windows消息机制。

可以说,掌握了这一部分知识,就是掌握了Windows编程中的神兵利器,灵活运用它,将会极大的提高我们的编程能力。

一、消息概述Windows窗体是怎样展现在屏幕上的呢?众所周知,是通过API绘制实现的。

Windows操作系统提供了一系列的API函数来实现界面的绘制功能,例如:DrawText绘制文字DrawEdge绘制边框DrawIcon绘制图标BitBlt 绘制位图Rectangle绘制矩形…再复杂的程序界面都是通过这个函数来实现的。

那什么时候调用这些函数呢?显然我们需要一个控制中心,用来进行“发号施令”,我们还需要一个命令传达机制,将命令即时的传达到目的地。

这个控制中心,就是一个动力源,就像一颗心脏,源源不断地将血液送往各处。

这个命令传达机制就是Windows消息机制,Windows消息就好比是身体中的血液,它是命令传达的使者。

Windows消息控制中心一般是三层结构,其顶端就是Windows内核。

Windows内核维护着一个消息队列,第二级控制中心从这个消息队列中获取属于自己管辖的消息,后做出处理,有些消息直接处理掉,有些还要发送给下一级窗体(Window)或控件(Control)。

第二级控制中心一般是各Windows应用程序的Applicat ion对象。

第三级控制中心就是Windows窗体对象,每一个窗体都有一个默认的窗体过程,这个过程负责处理各种接收到的消息。

消息是以固定的结构传送给应用程序的,结构如下:Public Type MSGhwnd As Longmessage As LongwParam As LonglParam As Longtime As Longpt As POINTAPIEnd Type其中hwnd是窗体的句柄,message是一个消息常量,用来表示消息的类型,wParam和lParam都是32位的附加信息,具体表示什么内容,要视消息的类型而定,time是消息发送的时间,pt是消息发送时鼠标所在的位置。

mfc消息机制原理

mfc消息机制原理

MFC(Microsoft Foundation Classes)是一种用于开发Windows应用程序的C++类库,它建立在Win32 API之上,并提供了更高层次的抽象和封装。

在MFC中,消息机制是实现应用程序与用户交互和事件处理的基础。

MFC消息机制的原理如下:1.消息映射表:在MFC应用程序中,每个窗口类(如对话框类、视图类等)通常都有一个消息映射表(message map),用于将消息与相应的处理函数关联起来。

消息映射表是一个静态数据结构,通过DECLARE_MESSAGE_MAP宏进行声明,并在类的实现文件中使用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏定义映射表的内容。

2.消息处理函数:每个消息映射表项将消息的ID(或者命令ID)与相应的消息处理函数绑定在一起。

消息处理函数是成员函数,由开发人员根据需要自行定义。

当相应的消息被触发时,系统会自动调用与该消息对应的处理函数。

3.消息循环:MFC应用程序在运行时通过消息循环(message loop)不断接收和分发消息。

消息循环负责从操作系统获取消息,并将消息派发给目标窗口的消息处理函数进行处理。

消息循环可以使用Run函数或AfxGetApp()->Run函数启动。

4.分发消息:当系统从消息队列中获取到一个消息后,会根据消息的目标窗口通过HWND来查找对应的CWnd对象,并调用该窗口的响应函数(如PreTranslateMessage、OnCmdMsg等)进行消息处理。

如果消息在目标窗口的消息映射表中找到了对应的处理函数,则将该消息转发给对应的处理函数进行处理。

5.消息处理:消息处理函数执行相应的逻辑,可以进行界面更新、控件操作、数据处理等操作。

处理函数的返回值通常是布尔型,表示是否终止消息的传递。

通过这种消息机制,MFC应用程序可以实现用户交互和事件处理的功能,使开发人员可以方便地处理窗口消息,响应用户操作,以及完成界面和数据之间的交互。

mfc 消息机制

mfc 消息机制

mfc消息机制
MFC(Microsoft Foundation Class)是微软开发的一种面向对象的C++框架,用于Windows操作系统的应用程序开发。

MFC消息机制是MFC框架的核心之一,其基本原理是在窗口、控件等对象之间传递消息,以便处理事件和交互。

具体而言,MFC消息机制包括以下几个方面:1.消息循环:MFC使用一个消息循环来接受和处理Windows操作系统发送的Windows消息,处理完消息后将处理结果反馈给Windows操作系统。

2.消息映射:MFC中的控件和窗口都有一个关联的消息映射表,用于将Windows消息映射到应用程序代码中的相应处理函数上。

当某个控件或窗口收到消息后,根据消息类型在相应的消息映射表中查找对应的消息处理函数,并调用相应的处理函数处理消息。

3.消息类型:MFC处理的Windows消息类型包括键盘和鼠标消息、定时器消息、系统负载消息、窗口大小变化消息等等,具体的消息类型可以在MFC框架的文档中查找。

4.消息处理函数:MFC中的消息处理函数是C++成员函数,定义为afx_msg 修饰的函数,Windows消息处理函数命名时需要遵循一定的命名规则,例如OnPaint()函数用于处理绘图事件。

需要注意的是,MFC消息机制是针对Windows操作系统设计的,其他操作系统可能具有不同的消息机制。

此外,MFC框架已经不是微软推荐的最先进的应用程序开发框架,已经逐渐被其他框架和技术所取代,例如.NET Framework,WPF,UWP等。

windows消息机制的工作原理

windows消息机制的工作原理

windows消息机制的工作原理Windows消息机制是一种用于不同进程间进行通信的机制,Windows操作系统以消息队列为基础,将消息作为一种最基本的通信单元进行传输。

在这个机制下,进程之间可以通过发送和接收消息来进行通信。

Windows消息机制的工作原理如下:1. 消息队列的创建:每个进程都有自己的消息队列,用于存储接收到的消息。

当进程初始化时,系统会为该进程创建一个消息队列,并为之分配一个唯一的标识符。

2. 消息的发送:当一个进程需要向其他进程发送消息时,它首先需要明确消息的发送目标。

在Windows中,每个进程都有一个唯一的标识符(句柄),可以用来标识其他进程。

发送消息的进程根据目标进程的标识符,将消息发送到目标进程的消息队列。

3. 消息的接收:当一个进程接收到消息时,它需要从自己的消息队列中读取消息。

Windows提供了一种机制,使得进程可以通过消息循环来接收和处理消息。

消息循环是一个无限循环,负责从消息队列中读取消息,并将消息分发给相应的处理函数。

4. 消息的处理:一旦消息被分发给相应的处理函数,进程就可以根据消息的类型和附加数据来进行相应的处理。

处理函数可以修改进程中的状态,调用相应的函数,或者发送其他消息。

5. 消息的传递:在发送和接收消息的过程中,消息并不是实时传输的。

当一个进程发送消息时,消息并不会立即发送给目标进程,而是先存储在发送进程的消息队列中。

接收进程通过消息循环来读取消息,也是间断性的进行读取。

因此,消息的传递是一种异步的过程。

6. 消息的优先级:Windows中的消息有不同的优先级,系统会根据消息的优先级来确定消息的处理顺序。

一般情况下,系统会优先处理高优先级的消息,然后才会处理低优先级的消息。

7. 消息的同步和异步:在发送消息的过程中,Windows提供了两种方式:同步方式和异步方式。

同步方式下,发送消息的进程会等待接收进程对消息的处理完成,然后才会继续执行。

异步方式下,发送消息的进程不需要等待接收进程的处理结果,可以立即继续执行。

Windows窗口消息机制简介

Windows窗口消息机制简介

从图中可以看出,Windows维护着一个全局系统消息队列,外界的一切动作变化,都首先以消息的形式传入到系统消息队列中。

Windows 又为每一个应用程序维护着一个属于单个应用程序的消息队列,Windows会对系统消息队列中的消息进行筛选,将属于某个应用程序的消息分配到对应的应用程序消息队列中。

无论是系统消息队列,还是应用程序的消息队列,全部都是在Windows的控制下,应用程序通过GetMessage系统调用从Windows 管辖的相对应的应用程序消息队列中取得消息,并进行处理。

从图中可以看出,通过GetMessage取得消息,有一个从用户态到内核态的过程。

因为能操作消息队列的,只有Windows自己。

应用程序取得消息之后,对消息进行简单的处理(TranslateMessage)后,通过DispatchMessage系统调用将消息返还给Windows,再由Windows以该消息为参数,调用应用程序的窗口过程函数。

也就是说,应用程序的窗口过程不是由应用程序自己直接调用的,而是通过Windows系统间接调用的。

应用程序的窗口过程之所以要由Windows来调用,而不是应用程序亲自调用,主要是因为下面几点原因:1.一个应用程序可能会有多个窗口,不同窗口的消息应该发给不同的窗口过程,如果这个过程由应用程序自己来管理的话,会给编程带来很大的难度。

2.其它的应用程序可能会通过SendMessage系统调用直接将消息通过Windows发给应用程序的窗口过程3.Windows并不是将所有的消息都放入到应用程序的消息队列中,一些紧急的消息,Windows会直接调用应用程序的窗口过程。

图中还有关于postMessage和sendMessage的介绍:postMessage是由其它应用程序调用,将消息放入到应用程序的消息队列中。

sendMessage是由其它应用程序调用,将消息直接发送大应用程序的窗口过程。

这两个方法同样都是通过Windows系统操作应用程序的窗口过程^_^。

消息循环的处理过程

消息循环的处理过程

消息循环的处理过程消息循环是计算机程序中一种常见的处理机制,用于接收、处理和分发用户输入、系统事件和消息的过程。

消息循环通常用于图形界面应用程序和操作系统中,是程序与用户进行交互的重要环节。

下面将详细讲解消息循环的处理过程。

一、消息的产生和传递在程序运行过程中,用户输入或系统事件会产生各种消息,如鼠标点击、键盘输入、窗口关闭等。

这些消息首先由操作系统捕获,并根据消息类型进行封装。

然后,操作系统将封装好的消息传递给相应的应用程序。

在应用程序中,消息通常被放入一个消息队列中,按照先进先出的顺序进行排列。

二、消息循环的启动和运行当应用程序启动后,消息循环开始运行。

消息循环是一个不断循环的过程,在每次循环中,应用程序会从消息队列中取出一条消息进行处理。

如果消息队列为空,应用程序会进入等待状态,直到有新的消息到达。

三、消息的处理在消息循环的每次循环中,应用程序会根据消息的类型进行相应的处理。

通常,应用程序会根据消息的目标窗口或控件,将消息发送给相应的处理函数进行处理。

处理函数可以是系统提供的默认处理函数,也可以是应用程序自定义的处理函数。

在处理函数中,应用程序可以根据消息的具体内容进行不同的操作。

例如,对于鼠标点击消息,应用程序可以根据鼠标的位置和按键状态来执行相应的操作,如打开菜单、选中文本等。

对于键盘输入消息,应用程序可以根据按键的键值来执行相应的操作,如输入文本、执行命令等。

四、消息的分发在处理完消息后,应用程序会根据需要将消息分发给其他窗口或控件。

例如,当用户点击一个按钮时,按钮会产生一个鼠标点击消息,应用程序会将这个消息发送给按钮对应的处理函数进行处理。

处理函数可以执行相应的操作,如显示下拉菜单、弹出对话框等。

五、消息循环的结束消息循环会一直运行,直到应用程序退出。

退出时,消息循环会被终止,程序不再接收和处理新的消息。

在退出前,应用程序通常会执行一些清理工作,如关闭文件、保存数据等。

总结消息循环是程序与用户进行交互的重要环节,它负责接收、处理和分发消息。

windows程序消息机制(Winform界面更新有关)

windows程序消息机制(Winform界面更新有关)

windows程序消息机制(Winform界⾯更新有关)1. Windows程序消息机制Windows GUI程序是基于消息机制的,有个主线程维护着消息泵。

这个消息泵让windows程序⽣⽣不息。

Windows程序有个消息队列,窗体上的所有消息是这个队列⾥⾯消息的最主要来源。

这⾥的While循环使⽤了GetMessage() 这个⽅法,这是个阻塞⽅法,也就是队列为空时⽅法就会阻塞,从⽽这个While循环停⽌运动,这避免了⼀个程序把cpu⽆缘⽆故的耗尽,让其他程序难以得到响应。

当然在某些需要cpu最⼤限度运动的程序⾥⾯就可以使⽤另外的⽅法,例如某些3d游戏或者及时战略游戏中,⼀般会使⽤PeekMessage()这个⽅法,它不会被windows阻塞,从⽽保证整个游戏的流畅和⽐较⾼的帧速。

(PeekMessage是⼀个Windows API函数。

该函数为⼀个消息检查线程消息队列,并将该消息(如果存在)放于指定的结构。

DispatchMessage功能是发送消息给窗⼝,窗⼝收到消息,执⾏事件)。

这个主线程维护着整个窗体以及上⾯的⼦控件。

当它得到⼀个消息,就会调⽤DispatchMessage()⽅法派遣消息,这会引起对窗体上的窗⼝过程的调⽤。

窗⼝过程⾥⾯当然是程序员提供的窗体数据更新代码和其它代码。

2. dotnet⾥⾯的消息循环public static void Main(string[] args){Form f = new Form();Application.Run(f);}Dotnet窗体程序封装了上述的while循环,这个循环就是通过Application.Run⽅法启动的。

3、线程外操作GUI控件的问题如果从另外⼀个线程操作windows窗体上的控件,就会和主线程产⽣竞争,造成不可预料的结果,甚⾄死锁。

因此windows GUI编程有⼀个规则,就是只能通过创建控件的线程来操作控件的数据,否则就可能产⽣不可预料的结果。

windows窗口消息回调函数

windows窗口消息回调函数

windows窗口消息回调函数Windows窗口消息回调函数是Windows操作系统中的一个重要概念,它允许我们对窗口消息做出相应的处理。

在本文中,我们将一步一步回答关于窗口消息回调函数的问题,包括什么是窗口消息回调函数,为什么需要使用窗口消息回调函数,以及如何实现窗口消息回调函数。

一、什么是窗口消息回调函数?在Windows操作系统中,窗口是图形用户界面的基本组成部分,它提供了用户与计算机之间的交互界面。

窗口消息回调函数是一种机制,它允许我们对窗口接收到的消息做出相应的处理。

当窗口接收到消息时,操作系统会调用注册的窗口消息回调函数来处理这些消息。

二、为什么需要使用窗口消息回调函数?在一个窗口应用程序中,窗口会接收到各种不同类型的消息,比如鼠标消息、键盘消息、窗口绘制消息等等。

如果没有窗口消息回调函数的机制,我们将无法对这些消息做出相应的处理。

而有了窗口消息回调函数,我们可以根据不同的消息类型,编写相应的处理代码,从而实现对窗口消息的控制和响应。

三、如何实现窗口消息回调函数?在Windows操作系统中,实现窗口消息回调函数需要以下几个步骤:1. 注册窗口类:在创建窗口之前,我们需要先注册一个窗口类。

窗口类是一个结构体,它描述了窗口的一些特性,比如窗口名称、窗口样式等。

在注册窗口类时,我们需要指定一个回调函数,该回调函数将负责处理窗口接收到的消息。

2. 创建窗口:在注册窗口类之后,我们可以使用CreateWindow函数来创建一个窗口。

CreateWindow函数会返回一个窗口句柄,我们可以通过该句柄来操作窗口。

3. 消息循环:创建窗口之后,我们需要进入消息循环。

消息循环是一个无限循环,它负责从消息队列中获取消息并分发给相应的窗口进行处理。

在消息循环中,我们需要调用GetMessage函数来获取消息,并使用TranslateMessage和DispatchMessage函数来将消息传递给窗口消息回调函数进行处理。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

注:以下所说windows线程是指与调用了与图形用户界面相关的函数的线程,而windows 进程则是包含windows线程的进程,以区别于一般的进程和线程一个线程只有一个报文队列,但可以有多个窗口,每个窗口都有WndProc函数窗口对象如下:Typedef struct _WINDOW_OBJECT{PW32THREADINFO ti;PDESKTOP Desktop;……UNICODE_STRING WindowName;……RECT WindowRect;……//pointer to the owning thread’s message queuePUSER_MESSAGE_QUEUE MessageQueue; //指向所属进程的消息队列Struct _WINDOW_OBJECT *FirstChild;Struct _WINDOW_OBJECT *LastChild;Struct _WINDOW_OBJECT *NextSibling;Struct _WINDOW_OBJECT *PrevSibling;//ENTRY in the list of thread windowsLIST_ENTRY ThreadListEntry;//Handle to the owner windowHWND hOwner;……WNDPROC WndProc; //消息处理函数PRTHREAD OwnerThread; //指向具体窗口所属线程的ETHREAD结构……}WINDOW_OBJECT;当一个线程第一次被建立时,系统假定线程不会被用于任何与用户相关的任务。

这样可以减少线程对系统资源的要求。

但是,一旦这个线程调用一个与图形用户界面有关的函数(例如检查它的消息队列或建立一个窗口),系统就会为该线程分配一些另外的资源,以便它能够执行与用户界面有关的任务。

因此进程在建立之初,并没有与用户界面相关的数据结构,只有当进程中某一线程调用win32k.sys中的函数时,进程会转化为windows进程,调用为win2k.sys的线程则转化为windows线程。

一个进程只要其中有一个线程是windows线程,则就是windows进程。

Windows进程除了EPROCESS和KPROCESS外,还有个W32PROCESS结构,即系统为windows进程所分配的另外一些资源。

且EPROCESS结构中的指针Win32Process指向这个数据结构。

当线程转化为windows线程时,系统会为线程分配一个T H R E A D I N F O结构这个T H R E A D I N F O结构包含一组成员变量,利用这组成员,线程可以认为它是在自己独占的环境中运行。

T H R E A D I N F O是一个内部的、未公开的数据结构,用来指定线程的投递消息队列(posted-message queue)、发送消息队列(send-message queue)、应答消息队列(r e p l y -message queue)、虚拟输入队列(virtualized-input queue)、唤醒标志(wake flag)、以及用来描述线程局部输入状态的若干变量。

这里的登记消息即为投递消息(posted-message)注意:这里的各个消息队列的消息均指的时被投递的消息,被发送的消息……即发送方直接把消息放入接收方的相应消息队列当线程有了与之相联系的T H R E A D I N F O结构时,线程就有了自己的消息队列集合。

Windows中有两种类型的消息队列1) 系统消息队列(System Message Queue)这是一个系统唯一的Queue,设备驱动(mouse, keyboard)会把操作输入转化成消息存在系统队列中,然后系统会把此消息放到目标窗口所在的线程的消息队列(thread-specific message queue)中等待处理2) 线程消息队列(Thread-specific Message Queue)每一个GUI线程都会维护这样一个线程消息队列。

(这个队列只有在线程调用GDI函数时才会创建,默认不创建)。

然后线程消息队列中的消息会被送到相应的窗口过程(WndProc)处理. typedef struct tagMSG {HWND hwnd; //消息要发向的窗口句柄UINT message; //消息标示符,以WM_开头的预定义值WPARAM wParam;LPARAM lParam;DWORD time; //消息放入消息队列的时间POINT pt; //消息放入消息队列时鼠标位置} MSG,*PMSG;附:第二个成员变量message指定了消息的标识符。

在Windows中,消息是由一个数值来表示的,不同的消息对应不同的数值。

但是由于数值不便于记忆,所以Windows将消息对应的数值定义为WM_XXX宏(WM是Window Message的缩写)的形式,XXX对应某种消息的英文拼写的大写形式。

消息可分为两类:队列消息和非队列消息队列消息:消息会先保存在消息队列中,消息循环会从此队列中取消息并分发到各窗口处理,包括:投递消息(posted-message)输入消息或虚拟输入消息(input-message or virtualized-input message)非队列消息:消息会绕过系统消息队列和线程消息队列直接发送到窗口过程被处理,包括:发送消息(sent-message)一、将消息投递到线程的投递消息队列BOOL PostMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);PostMessage函数为每个被投递的消息创造一个MSG结构,并且把消息复制给相应的消息队列当一个线程调用这个函数时,系统要确定是哪一个线程建立了用h w n d参数标识的窗口。

然后系统分配一块内存,将这个消息参数存储在这块内存中,并将这块内存增加到相应线程的投递消息队列中。

并且,这个函数还设置Q S _ P O S T M E S S A G E唤醒位。

函数P o s t M e s s a g e在登记了消息之后立即返回,调用该函数的线程不知道登记的消息是否被指定窗口的窗口过程所处理。

二、向窗口发送消息LRESULT SendMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);使用S e n d M e s s a g e函数直接将窗口消息直接发送给一个窗口过程,窗口过程将处理这个消息。

只有当消息被处理之后,S e n d M e s s a g e才能返回到调用程序。

A、向线程自己的某个窗口发送消息LRESULT DeliverMessage(HWND hwnd,UNIT uMsg,WPARAM wparam,LPARAM lparam){ W NDPROC lpfnWndProc = (WNDPROC)GetWindowLongPtr(hwnd,GW;P_WNDPROC);Return CallWindowProc(lpfnWndProc,hwnd,uMsg,wParam,lParam);}//一个线程向线程自己的某个窗口发送消息,接收窗口的过程直接被调用LRESULT SendMessage_SameThread(HWND hwnd, UINT uMsg,WPARAM wParam, LPARAM lParam){return DeliverMessage(hwnd, uMsg, wParam, lParam);}B、向其他线程的窗口发送消息首先,发送的消息要追加到接收线程的发送消息队列,同时还为这个线程设定Q S _ S E N D M E S S A G E标志。

其次,如果接收线程已经在执行代码并且没有等待消息(如调用Ge t M e s s a g e、P e e k M e s s a g e或Wa i t M e s s a g e),发送的消息不会被处理,系统不能中断线程来立即处理消息。

当接收进程在等待消息时,系统首先检查Q S _ S E N D M E S S A G E唤醒标志是否被设定,如果是,系统扫描发送消息队列中消息的列表,并找到第一个发送的消息。

Void DeliverInComingSentMessage(){While(有一个发送消息){MSG msg = 这个消息;从发送消息队列删除这个消息;if(这是一个特殊的消息){处理这个特殊的消息;}else{DeliverMessage(msg.hwnd,msg.message,msg.wParam,msg.lParam);把返回值返回给发送者;}}}附:函数中所说的“特殊的消息”是指采用S e n d M e s s a g e C a l l b a c k函数时,函数会立即返回,而当消息真正被处理后,接收线程会向发送端的应答队列发送一个消息,此时的消息即为“特殊的消息”SendToAnotherThread(...){将消息添加到接受者的发送消息队列中;//这两个函数将等待接收者响应if (Function == SendMessage || Function == SendMessageTimeout) { while (! message reply received && ! timed out) {DeliverlncomingSentMessages();等待新的消息或者 (如果是 SendMessageTimeout)超时;}}}当一个线程等待S e n d M e s s a g e返回时,它基本上是处于空闲状态。

但它可以执行一个任务:如果系统中另外一个线程向一个窗口发送消息,这个窗口是由这个等待S e n d M e s s a g e返回的线程所建立的,则系统要立即处理发送的消息。

在这种情况下,系统不必等待线程去调用G e t M e s s a g e、Peek Message或Wa i t M e s s a g e。

因为SendMessage函数只有等到消息被处理了才能返回,所以有可能会引起线程挂起,可以采用S e n d M e s s a g e Ti m e o u t、S e n d M e s s a g e C a l l b a c k、S e n d N o t i f y M e s s a g e和R e p l y M e s s a g e这四个函数防止这种情况出现三、消息的处理在消息的接收端,消息处理的原则:1、发送消息将被直接递送到窗口过程中2、接收投递消息(通过GetMessage或PeekMessage)接收输入消息(通过GetMessage或PeekMessage)一个线程必须将消息队列中的消息移除并进行处理,这包括两方面的内容:●消息循环●窗口过程—接收并处理发送给窗口的消息消息循环:MSG msg;BOOL bRet;while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0){if (bRet == -1){// handle the error and possibly exit}else{TranslateMessage(&msg); //键盘输入翻译为可传递的信息,即windows内部定义的信息,WM_xxxDispatchMessage(&msg); //派发消息,最终是对具体应用程序WndProc函数的调用,每个视窗都有个WndProc函数}}1、GetMessage/PeekMessage:GetMessage与PeekMessage的主要区别在于GetMessage只有在获得了一个投递消息或输入消息之后才会返回,而PeekMessage发完消息后,不管目标是否响应,都会从函数调用中返回,也还有其他一些次要的区别BOOL PeekMessage(LPMSG pmsg, HWND hwnd, UINT wMsgFilterMin,UINT wMsgFilterMax, UINT flags){DeliverlncomingSentMessages(); //前面有其伪代码if (有某个投递消息满足过滤条件) {*pmsg = 这个消息;if (flags & PM__REMOVE) 从投递消息队列中删除这个消息;return TRUE;}// 注意 WM_QUIT 消息将忽略过滤器if (有一个 WM_QUIT 消息正在等待处理并且没有投递消息) {清除 "WM_QUIT消息正在等待处理"的标志;*pmsg = WM_QUIT消息;return TRUE;}if (鼠标移动并且输入消息满足过滤条件) {清除"鼠标已移动"的标志;将WMJVIOUSEMOVE消息添加到输入消息队列中;}i f (有某个输入消息满足过滤条件) {*pmsg = 这个消息;if (flags & PM_REMOVE) 从输入消息队列删除这个消息;r e t u r n TRUE;}if (窗口需要进行绘制并且WM_PAINT消息满足过滤条件) {*pmsg = WM_PAINT消息;return TRUE;}if (计时器被触发了,并且WM_TIMER消息满足过滤条件) {将一个WM_TIMER消息添加到投递消息队列;*pmsg = 这个消息;if (flags & PM_REMOVE) 从投递消息队列中删除这个消息;return TRUE;}return FALSE;}// GetMessage只有在获得了一个投递消息或输入消息之后才会返回BOOL GetMessage(LPMSG pmsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax){while (!PeekMessage(pmsg, hwnd,wMsgFilterMin, wMsgFilterMax, PM_REMOVE)) {WaitMessage ();// wait for a new message to arrive}return pmsg->message != WM_QUIT;}GetMessage过程示意如下:我们只能将投递消息和输入消息过滤,不能过滤掉发送消息,这些消息是肯定会被处理的WM_PAINT、WM_TIMER、WM_QUIT消息比较特别,系统总是将消息投递到消息队列的最后,这是为了确保窗口其他信息能够在先进先出的消息队列中被处理。

相关文档
最新文档