http://blogs.msdn.com/b/oldnewthing/archive/2005/11/04/489028.aspx

Why is there a special PostQuitMessage function?

Because it's not really a posted message.

Commenter A. Skrobov asked, "What's the difference

between PostQuitMessage and PostThreadMessage (GetCurrentThreadId, WM_QUIT)?"

They are not equivalent, though they may look that way at first glance.

The differences are subtle but significant.

Like the WM_PAINTWM_MOUSEMOVE, and WM_TIMER messages,

the WM_QUIT message is not a "real" posted message.

Rather, it is one of those messages that the system generates as if it were posted, even though it wasn't.

And like the other messages, the WM_QUIT message is a "low priority" message,

generated only when the message queue is otherwise empty.

When a thread calls PostQuitMessage, a flag in the queue state is set that says,

"If somebody asks for a message and there are no posted messages, then manufacture a WM_QUIT message."

This is just like the other "virtually posted" messages.

WM_PAINT messages are generated on demand if there are any invalid regions,

WM_MOUSEMOVE messages are generated on demand if the mouse has moved since the last time you checked, and

WM_TIMER messages are generated on demand if there are any due timers.

And since the message is "virtually posted", multiple calls coalesce,

in the same way that multiple paint messages, multiple mouse motions, and multiple timer messages also coalesce.

Why is WM_QUIT handled like a low-priority message?

Because the system tries not to inject a WM_QUIT message at a "bad time";

instead it waits for things to "settle down" before generating the WM_QUIT message,

thereby reducing the chances that the program might be in the middle of a multi-step procedure triggered by a sequence of posted messages.

If you PeekMessage(..., PM_NOREMOVE) a WM_QUIT message, this returns a WM_QUIT message but does not clear the flag.

The WM_QUIT message virtually "stays in the queue". You can peek it use PeekMessage(..., PM_NOREMOVE) again ?

  i := ;
while TRUE do
begin
if LongInt( PeekMessage( Msg, , , , PM_REMOVE ) ) > then
begin
case Msg.message of
WM_QUIT :
begin
Inc( i );
if i = then           // First WM_QUIT posted by other thread
begin
for j := to do
PostQuitMessage( j );    // only 1 WM_QUIT in queue !
end else if i = then     // i = 2
break;              // Never be executed, unless other thread posted WM_QUIT again
end;
end;
end else begin
Sleep( );
end;
end;

Only can peek WM_QUIT once even if more WM_QUIT posted !

  i := ;
while TRUE do
begin
if LongInt( PeekMessage( Msg, , , , PM_REMOVE ) ) > then
begin
case Msg.message of
WM_QUIT :
begin
Inc( i );
if i = then         // First WM_QIUT from other thread       
begin
for j := to do
begin
PostQuitMessage( j );  // Only set "quit message pending" flag
PostThreadMessage( GetCurrentThreadId( ), WM_USER+j, , ); // 1024, 1025, ....
end;
end else if i = then  // Next WM_QUIT from this thread, but no more ...
break;
end;
else
begin
Sleep( );           // 1024, 1025, ...
end;
end;
end else begin
Sleep( );              //
end;
end;
  i := ;
while TRUE do
begin
if LongInt( PeekMessage( Msg, , , , PM_REMOVE ) ) > then
begin
case Msg.message of
WM_QUIT :
begin
Inc( i );
if i = then
begin
for j := to do
begin
PostThreadMessage( GetCurrentThreadId( ), WM_QUIT, , );    
PostThreadMessage( GetCurrentThreadId( ), WM_USER+j, , );   // WM_QUIT, WM_USER+0, WM_QUIT, WM_USER+1, ... 
end;
end else if i = then
break;
end;
else
begin
Sleep( );
end;
end;
end else begin
Sleep( );
end;
end; // Exit from here

As another special behavior, the generated WM_QUIT message

bypasses the message filters passed to the GetMessage and PeekMessage functions.

If the internal "quit message pending" flag is set, then you will get a WM_QUIT message once the queue goes quiet, regardless of what filter you pass.

By comparison, PostThreadMessage just places the message in the thread queue (for real, not virtually),

and therefore it does not get any of the special treatment that a real PostQuitMessage triggers.


PostQuitMessage : Set "quit message pending" flag, Generate a WM_QUIT when the queue goes quit

PostThreadMessage : Place WM_QUIT in queue


Thread0 : PostThreadMessage( ThreadId, WM_QUIT )

Thread1 : PostThreadMessage( ThreadId, WM_USER )

Thread2 : PostThreadMessage( ThreadId, WM_XXXX )

Thread3 : PostThreadMessage( ThreadId, WM_QUIT )

Thread4 : PostThreadMessage( ThreadId, WM_YYYY )

PeekMessage() : WM_USER, WM_XXXX, WM_YYYY, WM_QUIT

Because the system tries not to inject a WM_QUIT message at a "bad time";

instead it waits for things to "settle down" before generating the WM_QUIT message,

thereby reducing the chances that the program might be in the middle of a multi-step procedure triggered by a sequence of posted messages.

函数GetMessage里是使用一个循环不断地检测消息,周止复始的,是不可能出现死亡的,但它会检测到消息WM_QUIT就退出来。
 
那现在问题是谁发送WM_QUIT消息出来呢?这就是PostQuitMessage函数所做的工作。
 
当你点击窗口右上角的关闭时,Windows就会把窗口从系统里删除,这时就会发出消息WM_DESTROY给窗口消息处理函数WindowProc,
 
WindowProc收到这条消息后,最需要做的一件事情就是调用PostQuitMessage发出退出消息,让消息循环结束。
 
函数GetMessage检测到消息WM_QUIT就退出来。
 
函数PostQuitMessage声明如下:
 
WINUSERAPI
VOID
WINAPI
PostQuitMessage(
__in int nExitCode);

nExitCode是退出标识码,它被放到WM_QUIT消息的参数wParam里。

PostQuitMessage寄送一个WM_oUT消息给线程的消息队列并立即返回;

此函数向系统表明有个线程请求在随后的某一时间终止。

当线程从消息队列里取得WM_QUIT消息时,应当退出消息循环并将控制返回给系统。

返回给系统的退出值必须是消息WM_QUIT的wParam参数。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc; switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam); switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break; case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//
EndPaint(hWnd, &ps);
break; case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return ;
}

PostQuitMessage, PostThreadMessage( WM_QUIT )的更多相关文章

  1. WM_QUIT,WM_CLOSE,WM_DESTROY 消息出现顺序及调用方式

    http://bbs.ednchina.com/BLOG_ARTICLE_3005455.HTM VC中WM_CLOSE.WM_DESTROY.WM_QUIT消息出现顺序及调用方式 wxleasyla ...

  2. WM_CLOSE、WM_DESTROY、WM_QUIT的区别(询问,销毁窗口,退出进程,都不是一回事)

    1.发送消息SendMessage.PostMessage PostMessage将消息放入消息队列后马上返回,而SendMessage直到窗口过程处理完消息后才返回 2.三个消息的区别 WM_CLO ...

  3. Windows 消息机制详解

    总的来说: MSG包括: 窗口句柄,指示MSG发送的目的窗口 消息标识 lPARAM.wParam 发送时间 发送时的鼠标位置   关于消息队列: Windows系统有一个系统消息队列 每个线程都有一 ...

  4. 英文不好也能快速"记忆" API

    英文不好不要紧,把API函数导入打字练习类软件,即是练习打字速度,提高编程效率:也能短时间记忆API. 坚持每天打一遍,约2小时,连续打两周,会对API有很好的记忆,此方法是结合英文学习方法!以下是W ...

  5. Win32/MFC的基本概念

    一.MFC的基本概念 单文档.多文档和对话框框架的区别 MFC中的类继承图的基本框架 CView类与CDocument的关系 Onpaint()和Ondraw()的关系 hdc-cdc区别联系 RUN ...

  6. DMP文件的生成和使用

    1.生成dmp的程序 #include  <dbghelp.h> #pragma comment(lib,  "dbghelp.lib") //设置异常处理回调函数Se ...

  7. MFC OnOk(),OnCancel(),OnClose(),OnDestroy()的区别总结

    MFC OnOk(),OnCancel(),OnClose(),OnDestroy()的区别总结(转) 第一,OnOK()和OnCancel()是CDialog基类的成员函数,而OnClose()和O ...

  8. 第一个Windows窗口应用程序

    学习目的 熟悉开发工具Visual C++ 6.0和MSDN 2001的使用. 应用Windows API函数, 手工编写具有最基本构成的Windows窗口应用程序(包含WinMain入口函数, 消息 ...

  9. VC++SDK编程——模拟时钟

    #include <Windows.h> #include <tchar.h> #include <math.h> typedef struct Time { in ...

随机推荐

  1. Java中的OutOfMemoryError的各种情况及解决和JVM内存结构

    在JVM中内存一共有3种:Heap(堆内存),Non-Heap(非堆内存) [3]和Native(本地内存). [1] 堆内存是运行时分配所有类实例和数组的一块内存区域.非堆内存包含方法区和JVM内部 ...

  2. 怎样预防Ddos攻击

    一.为何要DDOS? 随着Internet互联网络带宽的增加和多种DDOS黑客工具的不断发布,DDOS拒绝服务攻击的实施越来越容易,DDOS攻击事件正在成上升趋势.出于商业竞争.打击报复和网络敲诈等多 ...

  3. $("#province").val();取不到select的值求解

    MVC下的razor视图开发中无法取到select的值问题求解 cshtml 如下 <select name="province" id="province&quo ...

  4. Pitcher Rotation

    题意: n个人m个对手给出每个人能战胜每个敌人的概率,现在有g个比赛,每个人赛完后要休息4天(可重复用),求能获得胜利的最大期望个数. 分析: 因为只有每个人5天就能用一次,所以对于每个人来说,只有得 ...

  5. maven(一)初步搭建,项目结构

    一.环境准备 java环境, jdk 1.5 以上 MyEclipse集成工具,我装的是8.5 版本 二.快速安装及配置 1.下载maven: http://maven.apache.org/docs ...

  6. Independence独立

    Independence refers to the degree to which each test case stands alone. That is, does the success or ...

  7. Enter回车切换输入焦点方法兼容各大浏览器

    做项目时,客户要求能够用enter回车直接切换输入(焦点),当最后一个时候,直接提交信息. 第一想法就是,网上去copy一段代码直接用.但了百度.谷歌找了个遍,找到的代码80%以上都是一样的.有的代码 ...

  8. IA32系统级架构总览(一) 实模式和保护模式

    应用程序的编写大部分的时候是不必关心系统级架构的,最多学习一下平台所给的API即可,也就是我们通常说的黑箱子.但是在学习操作系统的时候,系统级架构是要关心的. 系统级架构很难学习,其中一个很大的原因是 ...

  9. 从高铁G18中高端如厕看12306的验证码

    1.引子 最近疯狂的吐槽12306网站的虐心验证码. 从对铁老大的一贯作风来说,这个事不过是芝麻绿豆的事情.这个事件只是因为发生在网络上,而引起了广大网民的一致谴责而已. 相信更丰富的如厕经历,大家只 ...

  10. @Html.Raw()

    asp.net mvc中把html字符串以html效果输出来, @string变更输出的是HTML代码, 如果想以HTML标签效果输出来可以用函数@Html.Raw(str) 输出来的就是网效果了, ...