关于GETMESSAGE函数的一点疑问,麻烦高手给解释解释。

yiruirui0507 2010-11-30 12:59:57
#include<windows.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
static TCHAR szAppName[]=TEXT("HelloWin");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);

wndclass.hInstance=hInstance;
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR);
return 0;
}
hwnd=CreateWindow(szAppName,TEXT("The Hello Program"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);
BOOL bRet;
while((bRet=GetMessage(&msg,hwnd,0,0))!=0)
{
if(bRet==-1)
{

return -1;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(message)
{
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&rect);
DrawText(hdc,TEXT("Hello Windows 98!"),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hwnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}


问题如下:
BOOL bRet;
while((bRet=GetMessage(&msg,hwnd,0,0))!=0)
{
if(bRet==-1)
{

return -1;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
GetMessage(&msg,NULL,0,0) 就没有出现问题,MSDN中解释说,当为NULL的时候接受所有消息,还有什么线程消息等等。
当用hwnd的时候接受的是窗口的消息,
用hwnd的时候比如上面代码,关闭窗口之后进程中还有此进程,并没有结束。
我认为:窗口是销毁了,进程没结束,原因在于
当点关闭的时候会触发wm_destroy消息,这里跟WM_CLOSE有什么区别吗?还有一个WM_QUIT,这三个消息分别是什么意思?
触发WM_DESTROY消息,则OS把此消息插入到了当前应用程序的消息队列中,
然后应用程序从消息队列中取出WM_DESTROY消息,此时完成窗口的销毁,然而应用程序继续执行GETMESSAGE,此时的HWND已经是个无效的东西了,所以GETMESSAGE返回-1,于是出现死循环,-1也属于非0为真。

以上是分析,我的上述代码就是针对这个分析写的
我进行了判断,如果bRet=-1,就说明窗口被销毁了,直接返回。但是这个程序并没有退出啊,进程中仍然存在,请问这里该如何解释?到底是咋么回事?
...全文
145 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhlandwufei 2010-11-30
  • 打赏
  • 举报
回复
学习了~~~~
yiruirui0507 2010-11-30
  • 打赏
  • 举报
回复
当使用者按下系统功能表中的Close按钮,系统送出WM_Close,通常程序的窗口函数不拦截此消息,于是DefWindowProc处理它,DefWindowProc收到WM_Close后调用DestoryWindow把窗口清除,DestroyWindow本身会送出 WM_Destory.程序对WM_Destory的标准反应是调用PostQuitMessage,PostQuitMessage送出 WM_Quit,结束消息循环
Eleven 2010-11-30
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 yiruirui0507 的回复:]
引用 7 楼 visualeleven 的回复:
引用 3 楼 yiruirui0507 的回复:
查询结果:‘
WM_CLOSE 消息发出的时候,用户可以根据自己的意愿来选择到底是否关闭,WM_DESTORY 是真的关闭一个窗口。WM_QUIT是退出一个应用程序。
上面的正是属于窗口关闭了,应用程序还没退出的情况。

case WM_DESTROY:
PostQuitMessage……
[/Quote]
当使用者按下系统菜单中的Close 命令项,系统送出WM_CLOSE。通常程序
的窗口函数不栏截此消息,于是DefWindowProc 处理它。DefWindowProc收到WM_CLOSE 后, 调用DestroyWindow()把窗口清除。DestroyWindow()本身又会送出WM_DESTROY
wltg2001 2010-11-30
  • 打赏
  • 举报
回复
窗口的销毁是DefWindowProc在处理WM_CLOSE时销毁的,销毁之后才会产生WM_DESTROY消息的,所以当响应WM_DESTROY时,窗口已经没有了。
wltg2001 2010-11-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yiruirui0507 的回复:]
查询结果:‘
WM_CLOSE 消息发出的时候,用户可以根据自己的意愿来选择到底是否关闭,WM_DESTORY 是真的关闭一个窗口。WM_QUIT是退出一个应用程序。
上面的正是属于窗口关闭了,应用程序还没退出的情况。

case WM_DESTROY:
PostQuitMessage(0);
对于这句话的理解不知道该咋么弄?
当点关闭的时候发送的消息应该是 WM_DESTROY……
[/Quote]
你没有弄清楚这三个消息的顺序和来龙去脉。
当你点关闭时产生的是WM_CLOSE消息,而不是WM_DESTROY消息。对于WM_CLOSE消息,我们一般都不处理,于是就会交由默认的DefWindowProc来处理,DefWindowProc会产生WM_DESTROY消息,对于WM_DESTROY,我们会在程序中用PostQuitMessage(0);产生WM_QUIT消息,从而让GetMessage返回,退出循环。
wltg2001 2010-11-30
  • 打赏
  • 举报
回复
消息的顺序是WM_CLOSE->WM_DESTROY->WM_QUIT.
yiruirui0507 2010-11-30
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 visualeleven 的回复:]
引用 3 楼 yiruirui0507 的回复:
查询结果:‘
WM_CLOSE 消息发出的时候,用户可以根据自己的意愿来选择到底是否关闭,WM_DESTORY 是真的关闭一个窗口。WM_QUIT是退出一个应用程序。
上面的正是属于窗口关闭了,应用程序还没退出的情况。

case WM_DESTROY:
PostQuitMessage(0);
对于这句话的理解不知道该咋么弄?
当点……
[/Quote]
问题是DestryoWindow()这里并没有调用啊,就没出现。。。。。
wltg2001 2010-11-30
  • 打赏
  • 举报
回复
我认为:窗口是销毁了,进程没结束,原因在于
当点关闭的时候会触发wm_destroy消息,这里跟WM_CLOSE有什么区别吗?还有一个WM_QUIT,这三个消息分别是什么意思?
触发WM_DESTROY消息,则OS把此消息插入到了当前应用程序的消息队列中,
然后应用程序从消息队列中取出WM_DESTROY消息,此时完成窗口的销毁,然而应用程序继续执行GETMESSAGE,此时的HWND已经是个无效的东西了,所以GETMESSAGE返回-1,于是出现死循环,-1也属于非0为真。
===============
当点关闭时触发的是WM_CLOSE而不是WM_DESTROY,默认的窗口处理函数处理WM_CLOSE消息时发会送WM_DESTROY消息,窗口处理函数处理WM_DESTROY时会销毁窗口。此时hwnd应该失效了。所以GetMessage返回-1,造成while死循环。
Eleven 2010-11-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yiruirui0507 的回复:]
查询结果:‘
WM_CLOSE 消息发出的时候,用户可以根据自己的意愿来选择到底是否关闭,WM_DESTORY 是真的关闭一个窗口。WM_QUIT是退出一个应用程序。
上面的正是属于窗口关闭了,应用程序还没退出的情况。

case WM_DESTROY:
PostQuitMessage(0);
对于这句话的理解不知道该咋么弄?
当点关闭的时候发送的消息应该是 WM_DESTROY……
[/Quote]
DestroyWindow()来销毁窗口,PostQuitMessage送出WM_QUIT消息来退出消息循环,从而结束进程
Eleven 2010-11-30
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 yiruirui0507 的回复:]
引用 2 楼 visualeleven 的回复:
WM_CLOSE -> WM_DESTORY -> WM_QUIT


你的,什么意思的干活?
[/Quote]
消息的发送的顺序的干活
Abcix 2010-11-30
  • 打赏
  • 举报
回复
GetMesssge只接收与参数hWnd标识的窗口或子窗口相联系的消息,子窗口由函数IsChild决定,消息值的范围由参数wMsgFilterMin和wMsgFilterMax给出。如果hWnd为NULL,则 GetMessage接收属于调用线程的窗口的消息,线程消息由函数PostThreadMessage寄送给调用线程。GetMessage不接收属于其他线程或其他线程的窗口的消息,即使hWnd为NULL。由PostThreadMessage寄送的线程消息,其消息hWnd值为NULL。如果 wMsgFilterMin和MsgFilterMax都为零,GetMessage返回所有可得的消息(即,无范围过滤)
yiruirui0507 2010-11-30
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 visualeleven 的回复:]
WM_CLOSE -> WM_DESTORY -> WM_QUIT
[/Quote]

你的,什么意思的干活?
yiruirui0507 2010-11-30
  • 打赏
  • 举报
回复
查询结果:‘
WM_CLOSE 消息发出的时候,用户可以根据自己的意愿来选择到底是否关闭,WM_DESTORY 是真的关闭一个窗口。WM_QUIT是退出一个应用程序。
上面的正是属于窗口关闭了,应用程序还没退出的情况。

case WM_DESTROY:
PostQuitMessage(0);
对于这句话的理解不知道该咋么弄?
当点关闭的时候发送的消息应该是 WM_DESTROY没任何疑问(因为这里并没有涉及到WM_CLOSE),但是对这个消息的处理就糊涂啦,直接调用PostQuitMessage,
PostQuitMessage寄送一个WM_QUIT消息给线程的消息队列并立即返回;此函数向系统表明有个线程请求在随后的某一时间终止。
问题再次出现:这里对窗口的销毁是谁实现的?难道PostQuitMessage既负责销毁窗口又负责退出进程?
那它也太能干了吧???(哈哈,不可能是这样吧)
Eleven 2010-11-30
  • 打赏
  • 举报
回复
WM_CLOSE -> WM_DESTORY -> WM_QUIT
Eleven 2010-11-30
  • 打赏
  • 举报
回复
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, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧