说上书系统有一个系统消息队列,程序有一个程序的消息队列,
等到我后来学习Windows核心编程的时候,又知道了每个线程都有一个线程消息队列,
那么我想问:线程消息队列和程序的消息队列 是怎样的关系?
还有就是:系统消息队列中的消息是什么时候,如何进入程序的消息队列的呢?

解决方案 »

  1.   

    这里的程序消息队列,好拗口哦,应该说进程的消息队列更合适点,进程的消息队列就是进程的所有线程的消息队列的总称了。另外,也不是所有的线程都有消息队列,只有在线程调用过某些GUI相关的API后,系统才会为线程创建消息队列。系统消息队列中的消息是由操作系统负责,在必要的时刻投递到进程的消息队列的。
      

  2.   

    说上书系统有一个系统消息队列,程序有一个程序的消息队列,
    等到我后来学习Windows核心编程的时候,又知道了每个线程都有一个线程消息队列,
    那么我想问:线程消息队列和程序的消息队列 是怎样的关系?
    还有就是:系统消息队列中的消息是什么时候,如何进入程序的消息队列的呢?
    =====================
    消息队列是属于线程的,所以消息队列是对线程来说的,进程并不存在消息队列一说,虽然线程属于进程,但是进程并不是执行单元,所以认为所有的线程消息队列合在一起就是进程的消息队列这个没有什么意义。我从来没有听说过有一个系统消息队列。
      

  3.   

    不好意思,刚才又找了些资料,应该是有系统消息队列的。
    当消息产生时,比如按了下键盘,这个事件转成消息,然后放到系统消息队列中,windows从系统消息队列中移走消息,确实消息的接收窗口,打到相应窗口所在的线程,然后将消息放入到线程的消息队列中。
      

  4.   

    系统消息队列由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的目的是为了减少刷新窗口的次数。
    ---------------------------------------------------
    这里解释的很清楚了
      

  5.   

    http://bbs.51cto.com/viewthread.php?tid=487054
    这边讲得还算蛮清楚的
      

  6.   

    Whenever the user moves the mouse, clicks the mouse buttons, or types on the keyboard, the device driver for the mouse or keyboard converts the input into messages and places them in the system message queue. The system removes the messages, one at a time, from the system message queue, examines them to determine the destination window, and then posts them to the message queue of the thread that created the destination window. A thread's message queue receives all mouse and keyboard messages for the windows created by the thread. The thread removes messages from its queue and directs the system to send them to the appropriate window procedure for processing. With the exception of the WM_PAINT message, the WM_TIMER message, and the WM_QUIT message, the system always posts messages at the end of a message queue. This ensures that a window receives its input messages in the proper first in, first out (FIFO) sequence. The WM_PAINT message, the WM_TIMER message, and the WM_QUIT message, however, are kept in the queue and are forwarded to the window procedure only when the queue contains no other messages. In addition, multiple WM_PAINT messages for the same window are combined into a single WM_PAINT message, consolidating all invalid parts of the client area into a single area. Combining WM_PAINT messages reduces the number of times a window must redraw the contents of its client area. The system posts a message to a thread's message queue by filling an MSG structure and then copying it to the message queue. Information in MSG includes: the handle of the window for which the message is intended, the message identifier, the two message parameters, the time the message was posted, and the mouse cursor position. A thread can post a message to its own message queue or to the queue of another thread by using the PostMessage or PostThreadMessage function. An application can remove a message from its queue by using the GetMessage function. To examine a message without removing it from its queue, an application can use the PeekMessage function. This function fills MSG with information about the message. After removing a message from its queue, an application can use the DispatchMessage function to direct the system to send the message to a window procedure for processing. DispatchMessage takes a pointer to MSG that was filled by a previous call to the GetMessage or PeekMessage function. DispatchMessage passes the window handle, the message identifier, and the two message parameters to the window procedure, but it does not pass the time the message was posted or mouse cursor position. An application can retrieve this information by calling the GetMessageTime and GetMessagePos functions while processing a message. A thread can use the WaitMessage function to yield control to other threads when it has no messages in its message queue. The function suspends the thread and does not return until a new message is placed in the thread's message queue. You can call the SetMessageExtraInfo function to associate a value with the current thread's message queue. Then call the GetMessageExtraInfo function to get the value associated with the last message retrieved by the GetMessage or PeekMessage function. 
    这是 MSDN上的一段话  说明了 我问的那个问题 和你们说的 基本上是一样的 我很感谢大家
    但是 Windows程序设计   这本书上是这么写的:
    After the UpdateWindow call, the window is fully visible on the video display. The program must now make itself ready to read keyboard and mouse input from the user. Windows maintains a "message queue" for each Windows program currently running under Windows. When an input event occurs, Windows translates the event into a "message" that it places in the program's message queue. 翻译成:
    呼叫UpdateWindow之后,窗口就出现在视讯显示器上。程序现在必须准备读入使用者用键盘和鼠标输入的数据。Windows为当前执行的每个Windows程序维护一个「消息队列」。在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中。它说程序 有一个消息队列
    它说的这个程序消息队列到底是指什么呀,谁能告诉我怎么去理解他书中的这句话呀
      

  7.   

    还有就是  Windows程序设计中还有两段话 也提到了 程序消息队列 ,这又该怎么理解呢:
    As the user presses and releases keys on the keyboard, Windows and the keyboard device driver translate the hardware scan codes into formatted messages. However, these messages are not placed in an application's message queue right away. Instead, Windows stores these messages in something called the system message queue. The system message queue is a single message queue maintained by Windows specifically for the preliminary storage of user input from the keyboard and the mouse. Windows will take the next message from the system message queue and place it in an application's message queue only when a Windows application has finished processing a previous user input message. The reasons for this two-step process—storing messages first in the system message queue and then passing them to the application message queue—involves synchronization. As we just learned, the window that is supposed to receive keyboard input is the window with the input focus. A user can be typing faster than an application can handle the keystrokes, and a particular keystroke might have the effect of switching focus from one window to another. Subsequent keystrokes should then go to another window. But they won't if the subsequent keystrokes have already been addressed with a destination window and placed in an application message queue. 翻译成:
    当使用者按下并释放键盘上的键时,Windows和键盘驱动程序将硬件扫描码转换为格式消息。然而,这些消息并不保存在消息队列中。实际上,Windows在所谓的「系统消息队列」中保存这些消息。系统消息队列是独立的消息队列,它由Windows维护,用于初步保存使用者从键盘和鼠标输入的信息。只有当Windows应用程序处理完前一个使用者输入消息时,Windows才会从系统消息队列中取出下一个消息,并将其放入应用程序的消息队列中。此过程分为两步:首先在系统消息队列中保存消息,然后将它们放入应用程序的消息队列,其原因是需要同步。就像我们刚才所学的,假定接收键盘输入的窗口就是有输入焦点的窗口。使用者的输入速度可能比应用程序处理按键的速度快,并且特定的按键可能会使焦点从一个窗口切换到另一个窗口,后来的按键就输入到了另一个窗口。但如果后来的按键已经记下了目标窗口的地址,并放入了应用程序消息队列,那么后来的按键就不能输入到另一个窗口。
    这里面提到的程序的消息队列又是指什么呢
      

  8.   

    The system maintains a single system message queue and one thread-specific message queue for each GUI thread.
    这句话是我上面那段MSDN上的话中的一句。
    简单的翻译是:
    系统维持一个单独的系统消息队列和一个指定线程(GUI线程)的消息队列
    所以我认为 GUI线程的消息队列 也是由系统来维护的不是由 GUI线程自身维护的 
    请问 我这样认为 有什么不恰当之处吗
      

  9.   

    思考一下,SendMessage函数的第一个参数是 HWND,也就是窗口句柄。这个句柄值是不会跨进程的。所以消息队列没必要放在虚拟内存的内核区域。这样别的进程也就无法随便干涉你进程里GUI线程的消息队列。
    所以猜测进程中GUI线程的消息队列应该是放在用户区域的。另外,想象系统如何将一些消息从系统的队列中取出来送给某个进程中的GUI线程呢?
    我觉得可以等到那个线程得到CPU调度的时候,再发送到位于虚拟内存用户区域的消息队列中。
    而由于进程中的所有线程共享的是一个句柄表,所以猜测GUI线程的消息队列也可以是多个(因为句柄值在在进程环境下是可以在多个线程间区分的。)个人意见,待考证哈。
      

  10.   

    楼上的:所以猜测进程中GUI线程的消息队列应该是放在用户区域的。这和放在用户区或系统区有什么关系?
    难道放在系统区,别的进程就可以随便干涉你进程里GUI线程的消息队列 了?
      

  11.   

    如果进程没有自己的消息队列,那么WinMain里的消息循环去哪里取消息?难道系统运行的所有进程,通过互斥系统消息队列去取消息??
    进程的消息队列,就是主线程的消息队列.GetMessage 会等到有消息才返回,PeekMessage不管有没有消息都返回
    while (GetMessage (&msg, NULL, 0, 0))
    {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
    }
      

  12.   

    系统消息队列,就是windows系统自己控制的队列,编程人员管不了也不看不到
    系统消息队列就是解析和分发每个消息到 哪一个应用程序当中关键是 系统中运行的每一个应用程序,都有一个或只能有一个主线程,这个主线程里面就是一个死循环的解析消息队列(winmain里面),那么应用程序中的其他所有线程或者其他所有窗口都共用主线程中的一个消息队列,当然也可以在线程中去写消息队列解析,但默认是都共用主线程的消息队列,然后解析中分发消息到各自窗体的消息映射函数