Windows的UI线程

    在Windows应用程序中,窗体是由一种称为“UI线程(User Interface Thread)”的特殊类型的线程建立的。函数

    首先,UI线程是一种“线程”,因此它具备一个线程应该具备的全部特征,好比有一个线程函数和一个线程ID。测试

    其次,“UI线程”又是“特殊”的,这是由于UI线程的线程函数中会建立一种特殊的对象——窗体,同时,还一并负责建立窗体上的各类控件。spa

    每一个UI线程都有一个消息队列,而不是每一个窗体一个消息队列!操作系统

    只有当一个线程调用Win32 API中的GDI(Graphics Device Interface)和User函数时,操做系统才会将其当作是一个UI线程,并为它建立一个消息队列。线程

     须要注意的是,消息循环是由UI线程的线程函数启动的(若是函数线程 没有实现消息循环函数就不能处理消息,这个概念要牢记。只产生了一个窗口,可是没有消息处理函数,窗口就没法处理消息),操做系统无论这件事,它只管为UI线程建立消息队列。所以,若是某个UI线程的线程函数中没有定义消息循环,那么,它所拥有的窗体是没法正确绘制的。对象

 

若是一个线程建立了窗口,拥有GUI资源,那么也称该线程为GUI线程,不然就为工做线程。建立窗口的线程就拥有该窗口。这种线程拥有关系的概念对窗口有重要的意义:创建窗口的线程必须是为窗口处理全部消息的线程。为了使这个概念更加明确具体,能够想像一个线程创建了一个窗口,而后就结束了。在这种状况下,窗口不会收到一个WM_DESTROY或WM_NCDESTROY消息,由于线程已经结束,不可能被用来使窗口接收和处理这些消息。每一个线程,若是它至少创建了一个窗口,都由系统对它分配一个消息队列。这个队列用于窗口消息的派送(dispatch)。为了使窗口接收这些消息,线程必须有它本身的消息循环。队列

 

消息分类:进程

 <1>.队列消息和非队列消息事件

  从消息的发送途径上看,消息分两种:队列消息和非队列消息。
  队列消息送到系统消息队列,而后到线程消息队列;非队列消息直接送给目的窗口过程。资源

  这里,对消息队列阐述以下:
  Windows维护一个系统消息队列(System message queue),每一个GUI线程有一个线程消息队列(Thread message queue)。

    通常键盘、鼠标消息是队列消息,此外队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。这些队列消息之外的绝大多数消息是非队列消息。

<2>.系统消息和应用程序消息

    系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;

    应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息由应用程序本身使用;0XC000到0XFFFF范围的消息用来和其余应用程序通讯,为了ID的惟一性,使用::RegisterWindowMessage来获得该范围的消息ID。

<3>.窗口消息,命令消息,控件通知消息
  根据处理过程的不一样,能够分为三类:窗口消息,命令消息,控件通知消息。
  
  (1).窗口消息
   通常以WM_开头,如WM_CREATE, WM_SIZE, WM_MOUSEMOVE等标准的Windows消息, 用于窗口相关的事件通知,窗口消息将由系统分配到该窗口的窗口过程处理。
  (2).命令消息 (WM_COMMAND)
   一种特殊的窗口消息,它从一个窗口发送到另外一个窗口以处理来自用户的请求,一般是从子窗口发送到父窗口,例如,点击按钮时,按钮的父窗口会收到
   WM_COMMAND消息,用以通知父窗口按钮被点击,经测试:子窗口向父窗口发送WM_COMMAND消息,或者称为父窗口会收到WM_COMMAND消息,操做系统并非经过将WM_COMMAND消息放入到父窗口的消息队列中去,而是直接调用了父窗口的窗口过程以 WM_COMMAND 为消息标识参数(UINT uMsg),实现这个功能的API函数正是: LRESULT DispatchMessage(const MSG *lpmsg);
  (3).控件通知消息
   WM_NOTIFY消息,当用户与控件交互(Edit, Button...)时,通知消息会从控件窗口发送到父窗口,这种消息的目的不是为了处理用户命令,而是为了让父窗
   口可以适时的改变控件。

 

Windows 如何知道消息应该送到哪个线程?

    这里咱们要分为两种状况 , 消息是否是队列消息 。

    是队列消息:

    好比在一个窗体空白处点击左键 , 首先 OS 会根据当前的context 来生成 MSG , MSG 中会包括要发送到的窗口的 Handle。首先 OS 会将这个消息放到 OS 的系统消息队列中 , 然后 OS 会有专门的进程根据 MSG 中的窗口的 Handle 找到建立该窗口的线程,而后将该 MSG 送到该线程的消息队列然后由该消息循环来处理这个消息, 最终由DispatchMessage 函数来将这个消息送到相应的窗口处理函数

    非队列消息:

    若是你在一个窗体上点击了一个 button 呢,消息的路径是怎样的呢?当你点击了一个 button 后, OS 产生三个MSG。 WM_LBUTTONDOWN和WM_LBUTTONUP,这两个消息的窗口Handle为button的handle。一个WM_command 或者 wm_notify 消息, OS 会将这个消息直接送给包含 button 的 window processdure 来处理,而不会将这个送到消息队列。

相关文章
相关标签/搜索