PostQuitMessage(WM_QUIT) 退不出程序
2010-05-24 23:37
323 查看
今天写了一个SDK程序,关闭程序时调用PostQuitMessage(WM_QUIT) ,程序没有结束,任务管理器显示其占了90%多的CPU,必须手动结束进程。
下面是退出程序Code:
LRESULT CALLBACK WindowProc (HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
完成的程序如下所示:
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
static TCHAR szAppName[] = TEXT ("Hello,World!");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wndclass.lpfnWndProc = (WNDPROC)WindowProc;
wndclass.cbClsExtra = 0;//窗口类附加内存
wndclass.cbWndExtra = 0;//窗口附加内存
wndclass.hInstance = hInstance;//实例句柄
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIcon = LoadIcon (NULL,IDI_APPLICATION);
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, "Failed to registerClass!", szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow (szAppName, TEXT("Hello,World!"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while (GetMessage (&msg, hwnd, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
经过查看资料,发现问题出在GetMessage的参数上,把 while (GetMessage (&msg,hwnd,0,0))
改成如下:
while (GetMessage (&msg, NULL, 0, 0))
即可。
MSDN
GetMessage
retrieves messages for any window that belongs to the calling thread and
thread messages posted to the calling thread using the PostThreadMessage
function.
中文翻译:GetMessage取得那些属于调用线程的窗口的消息和通过PostThreadMessage函数投递(发送)到调用线程的线程消息.
这样问题就明白了,
GetMessage需要检索到WM_QUIT返回一个FALSE结束消息循环, 而WM_QUIT是通过PostQuitMessage(0)发送, 属于线程消息, 而非普通的窗口消息.
如果在GetMessage中用hWnd而不是NULL, 虽然WM_QUIT 消息仍会出现在程序的消息队列中,但GetMessage却无法检索到,
而且此时窗口已经被销毁了, 如果还想取得hWnd的窗口消息, 只可能发生错误( cpu占用100%, 死循环? ).
也适用于
PeekMessage。
,
the return value is nonzero.
If the function retrieves the WM_QUIT
message, the
return value is zero.
If there is an error, the return value is -1. For example, the
function fails if hWnd
is an invalid window handle or lpMsg
is an invalid pointer. To get extended error information, call GetLastError
.
Warning
Because the return value can
be nonzero, zero, or -1, avoid code like this:
The possibility of a -1 return value means that such
code can lead to fatal application errors. Instead, use code like this:
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
下面是退出程序Code:
LRESULT CALLBACK WindowProc (HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
完成的程序如下所示:
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
static TCHAR szAppName[] = TEXT ("Hello,World!");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wndclass.lpfnWndProc = (WNDPROC)WindowProc;
wndclass.cbClsExtra = 0;//窗口类附加内存
wndclass.cbWndExtra = 0;//窗口附加内存
wndclass.hInstance = hInstance;//实例句柄
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIcon = LoadIcon (NULL,IDI_APPLICATION);
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, "Failed to registerClass!", szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow (szAppName, TEXT("Hello,World!"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while (GetMessage (&msg, hwnd, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
经过查看资料,发现问题出在GetMessage的参数上,把 while (GetMessage (&msg,hwnd,0,0))
改成如下:
while (GetMessage (&msg, NULL, 0, 0))
即可。
MSDN
GetMessage
retrieves messages for any window that belongs to the calling thread and
thread messages posted to the calling thread using the PostThreadMessage
function.
中文翻译:GetMessage取得那些属于调用线程的窗口的消息和通过PostThreadMessage函数投递(发送)到调用线程的线程消息.
这样问题就明白了,
GetMessage需要检索到WM_QUIT返回一个FALSE结束消息循环, 而WM_QUIT是通过PostQuitMessage(0)发送, 属于线程消息, 而非普通的窗口消息.
如果在GetMessage中用hWnd而不是NULL, 虽然WM_QUIT 消息仍会出现在程序的消息队列中,但GetMessage却无法检索到,
而且此时窗口已经被销毁了, 如果还想取得hWnd的窗口消息, 只可能发生错误( cpu占用100%, 死循环? ).
也适用于
PeekMessage。
Return Values
If the function retrieves a message other than WM_QUIT,
the return value is nonzero.
If the function retrieves the WM_QUIT
message, the
return value is zero.
If there is an error, the return value is -1. For example, the
function fails if hWnd
is an invalid window handle or lpMsg
is an invalid pointer. To get extended error information, call GetLastError
.
Warning
Because the return value can
be nonzero, zero, or -1, avoid code like this:
while (GetMessage( lpMsg, hWnd, 0, 0)) ...
The possibility of a -1 return value means that such
code can lead to fatal application errors. Instead, use code like this:
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
相关文章推荐
- PostQuitMessage(0)要慎用,经常会造成MFC程序退出时内存泄露,还是尽量使用MFC基类的退出函数比较好。
- PostQuitMessage, PostThreadMessage( WM_QUIT )
- PostQuitMessage(退出程序的一种方法)
- PostQuitMessage和PeekMessage的诡异行径
- Windows/MFC_三个退出程序消息:WM_CLOSE、WM_DESTROY、WM_QUIT
- Windows消息响应机制之四:PostQuitMessage和GetMessage函数 .
- MFC窗口程序三个退出程序消息:WM_CLOSE、WM_DESTROY、WM_QUIT
- 用SendMessage/PostMessage发送WM_SIZE消息
- PostQuitMessage(0)
- Windows消息响应机制之四:PostQuitMessage和GetMessage函数
- PostQuitMessage函数用法例解
- 关于PostQuitMessage()的探究
- Windows API一日一练(15)PostQuitMessage函数
- Windows API一日一练(15)PostQuitMessage函数
- PostQuitMessage(0);
- Windows API一日一练(15)PostQuitMessage函数
- WM_COPYATA 与 PostMessage/SendMessage;const 的变量通过指针修改后?;指针与数组名
- PostQuitMessage和ExitProcess的区别是什么?
- 三个退出程序消息:WM_CLOSE、WM_DESTROY、WM_QUIT
- 三个退出程序消息WM_CLOSE、WM_DESTROY、WM_QUIT