PostQuitMessage, PostThreadMessage( WM_QUIT )
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_PAINT
, WM_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.
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 )的更多相关文章
- WM_QUIT,WM_CLOSE,WM_DESTROY 消息出现顺序及调用方式
http://bbs.ednchina.com/BLOG_ARTICLE_3005455.HTM VC中WM_CLOSE.WM_DESTROY.WM_QUIT消息出现顺序及调用方式 wxleasyla ...
- WM_CLOSE、WM_DESTROY、WM_QUIT的区别(询问,销毁窗口,退出进程,都不是一回事)
1.发送消息SendMessage.PostMessage PostMessage将消息放入消息队列后马上返回,而SendMessage直到窗口过程处理完消息后才返回 2.三个消息的区别 WM_CLO ...
- Windows 消息机制详解
总的来说: MSG包括: 窗口句柄,指示MSG发送的目的窗口 消息标识 lPARAM.wParam 发送时间 发送时的鼠标位置 关于消息队列: Windows系统有一个系统消息队列 每个线程都有一 ...
- 英文不好也能快速"记忆" API
英文不好不要紧,把API函数导入打字练习类软件,即是练习打字速度,提高编程效率:也能短时间记忆API. 坚持每天打一遍,约2小时,连续打两周,会对API有很好的记忆,此方法是结合英文学习方法!以下是W ...
- Win32/MFC的基本概念
一.MFC的基本概念 单文档.多文档和对话框框架的区别 MFC中的类继承图的基本框架 CView类与CDocument的关系 Onpaint()和Ondraw()的关系 hdc-cdc区别联系 RUN ...
- DMP文件的生成和使用
1.生成dmp的程序 #include <dbghelp.h> #pragma comment(lib, "dbghelp.lib") //设置异常处理回调函数Se ...
- MFC OnOk(),OnCancel(),OnClose(),OnDestroy()的区别总结
MFC OnOk(),OnCancel(),OnClose(),OnDestroy()的区别总结(转) 第一,OnOK()和OnCancel()是CDialog基类的成员函数,而OnClose()和O ...
- 第一个Windows窗口应用程序
学习目的 熟悉开发工具Visual C++ 6.0和MSDN 2001的使用. 应用Windows API函数, 手工编写具有最基本构成的Windows窗口应用程序(包含WinMain入口函数, 消息 ...
- VC++SDK编程——模拟时钟
#include <Windows.h> #include <tchar.h> #include <math.h> typedef struct Time { in ...
随机推荐
- Spring aop 实现异常拦截
使用aop异常挂载功能可以统一处理方法抛出的异常,减少很多重复代码,实现如下: 1.实现ThrowAdvice public class ExceptionHandler implements Thr ...
- CSS打造三级下拉菜单
<html><head><meta http-equiv="Content-Type" content="text/html; charse ...
- 让 PowerDesigner 支持 SQLite!
让 PowerDesigner 支持 SQLite! PowerDesigner是一个功能强大的数据库设计软件,最近正在用其设计新系统的数据库,但由于在项目初级阶段,希望使用轻量级的 SQLite ...
- selenium python (三)鼠标事件
# -*- coding: utf-8 -*-#鼠标事件 #ActionChains类中包括: # context_click() 右击: ...
- Selenium2Library系列 keywords 之 _SelectElementKeywords 之 unselect_from_list_by_value(self, locator, *values)
def unselect_from_list_by_value(self, locator, *values): """Unselects `*values` from ...
- js保留小数点后N位的方法介绍
js保留小数点后N位的方法介绍 利用toFixed函数 代码如下 复制代码 <script language="javascript"> document.write( ...
- cocos2d-x CCEditBox 字符不能显示完全的bug
cocos2d-x CCEditBox 字符不能显示完全的bug (cocos2dx版本 2.2.0)用CCEditBox制作帐号输入框,当输入的内容超过框的宽度时,框里面不会显示当前输入的字符,显示 ...
- 设计模式 外观 Facade
外观模式的作用是简化接口.它提供一个统一的接口用来访问子系统的一群接口.通过这个高层接口使子系统更容易使用. 同时,通过外观将客户从组件的子系统中解耦. Head 1st中使用了家庭影院的例子来说明外 ...
- 转-问自己:UI设计注意的十个问题
UI 设计需要自问的 10个问题 UI 设计的魅力在于,你不仅需要适当的技巧,更要理解用户与程序的关系.一个有效的用户界面关注的是用户目标的实现,包括视觉元素与功能操作在内的所有东西都需要完整一致 ...
- android 使用虚拟机安装apk(图文教程)(转)
1.启动虚拟机 2.我的android sdk在“E:\android\android开发环境\android SDK\platform-tools”把要安装的apk复制到这个根目录(和adb.exe ...