MFC子窗口中退出程序
在子窗口中退出程序应使用PostQuitMessage(0);函数实现。
函数GetMessage里是使用一个循环不断地检测消息,周止复始的,是不可能出现死亡的,但它会检测到消息WM_QUIT就退出来。那现在问题是谁发送WM_QUIT消息出来呢?这就是PostQuitMessage函数所做的工作。当你点击窗口右上角的关闭时,Windows就会把窗口从系统里删除,这时就会发出消息WM_DESTROY给窗口消息处理函数WindowProc,WindowProc收到这条消息后,最需要做的一件事情就是调用PostQuitMessage发出退出消息,让消息循环结束。
函数PostQuitMessage声明如下:
WINUSERAPI
VOID
WINAPI
PostQuitMessage(
__in int nExitCode);
nExitCode是退出标识码,它被放到WM_QUIT消息的参数wParam里。
VC关闭窗口退出 http://www.cnblogs.com/carekee/articles/2006715.html
1、OnOK()或OnCancel()//只对窗口程序有用
2、PostQuitMessage(0);//最常用
3、ExitProcess(0);
4、发送WM_CLOSE消息,如:
SendMessage(WM_CLOSE, 0, 0);
5、TerminateProcess
6、CDialog.Destroy()
7、exit(0);
8、 void CMainFrame::OnClose()
{
// TODO: Add your message handler code here and/or call default
if (MessageBox("确定要退出吗?","提示",MB_YESNO|MB_DEFBUTTON2)==IDYES)
{
CFrameWnd::OnClose();
}
}
如果是关闭其它程序
// 一种方法,通过窗口文字
HWND hWnd = ::FindWindow(NULL, _T("MSDN Library Visual Studio 6.0")); // 注: 这个是窗口的标题文字
if (NULL != hWnd) {
::SendMessage(hWnd, WM_CLOSE, 0, 0);
}
//另外一种方法,进程ID
DWORD id_num;
HWND hWnd = ::FindWindow(NULL, _T("MSDN Library Visual Studio 6.0"));
GetWindowThreadProcessId(hWnd, &id_num); //注意:第二个参数是进程的ID,返回值是线程的ID。
HANDLE hd = OpenProcess(PROCESS_ALL_ACCESS,FALSE, id_num);
TerminateProcess(hd, 0);
如果窗口文字是会变的,可以使用FindWindow的第一个参数:应用程序的类名。
可以通过VC提供的Spy++这个软件获得ClassName。
从开始菜单->MS 6.0 Tools->spy++,找出你要关闭的程序,比如说spy++,双击它,看Class选项的Class Name是Afx:400000:8:10011:0:15503db。
然后:
HWND hWnd = ::FindWindow(_T("Afx:400000:8:10011:0:15503db"), NULL);
GetWindowThreadProcessId(hWnd, &id_num); //注意:第二个参数是进程的ID,返回值是线程的ID。
HANDLE hd = OpenProcess(PROCESS_ALL_ACCESS,FALSE, id_num);
TerminateProcess(hd, 0);
窗口关闭过程http://blog.sina.com.cn/s/blog_48ab47450100lrib.html
——OnOK(),OnCancel(),OnClose(),EndDialog(),DestroyWindow(),OnDestroy(),OnNcDestroy()
一、对于非模态窗口,必须重载OnCancel函数,在函数中调用DestroyWindows()方法,且不能调用基类的函数。因为基类函数中调用的是 EndDialog()方法。而OnClose()也会调用OnCancel()方法。另外想通过OnOK关闭对话框,也必须同样处理,不能直接用默认方法。
1 、只有点击标题栏的叉号图标、在桌面任务栏右键-关闭、Alt+F4、标题栏最左边图标上单击-关闭,发送WM_CLOSE消息,触发 OnClose()。
所以对于非模态窗口,其关闭过程
OnClose()->OnCancel()->DestroyWindow()->OnDestroy()->OnNcDestroy() , ->仅表示时间先后而已
而OnNcDestroy()最后又调用了PostNcDestroy()
2、回车、ESC、点击“确定”或“取消”,都不会调用OnClose()
一般来说,OnOK是对ID_OK的响应, OnCancel是对IDCANCEL的响应. 前者对应键盘的Enter, 后者对应Esc。
OnCancel()->DestroyWindow()->OnDestroy()->OnNcDestroy()
OnOK()->DestroyWindow()->OnDestroy()->OnNcDestroy()
OnNcDestroy()最后又调用了PostNcDestroy()
OnOK()与OnCancel()
如前面所述,OnOK是对ID_OK的响应, OnCancel是对IDCANCEL的响应. 前者对应键盘的Enter, 后者对应Esc。
OnOK()和OnCancel()都调用了EndDialog().OnOK调用了UpdateData(TRUE)而OnCacel()没有调用。
在OnOK()结束刚进入DestroyWindow时,其实窗口并未关闭,依然可以用ShowWindow显示出来
模态的对话框可以用EndDialog来销毁, 非模态的对话框要用DestroyWindow来销毁
见《OnOK与OnCancel》http://ponymaggie.blog.sohu.com/135823530.html
EndDialog()
该函数清除一个模态对话框,并使系统中止对对话框的任何处理
对于DoModal出来的窗口,可以使用默认的OnOk()和OnCancel()来处理。其基类方法中会调用EndDialog()方法。
它只能在对话框的消息处理函数里使用,并且这个函数调用之后,没有立即就删除对话框的,而是设置了操作系统里的结束标志。当操作系统查检到有这个标志时,就去删除对话框的消息循环,同时也去释放对话框占用的资源。其实对话框的生命周期是这样的,先由函数DialogBox创建对话框,这样函数 DialogBox完成创建对话框但还没有显示前会发出消息WM_INITDIALOG,让对话框有机会初始化上面所有窗口或控件的显示,比如设置文本框的字符串等。最后当用户点出确定或者取消的按钮,就收到两个命令IDOK或IDCANCEL,这时就可以调用函数EndDialog来结束对话框的生命。
见《Windows API一日一练(18)EndDialog函数》http://blog.csdn.net/caimouse/archive/2007/07/30/1716140.aspx
DestroyWindows()
CWnd::DestroyWindow销毁m_hWnd(必须非空),同时销毁其菜单、定时器,以及完成其他清理工作。
::DestroyWindow使将被销毁的窗口失去激活、失去输入焦点,并发送WM_DESTROY、WM_NCDESTROY消息到该窗口及其各级子窗口。如果被销毁的窗口是子窗口且没有设置WM_NOPARENTNOTFIY风格,则给其父窗口发送WM_PARENTNOFITY消息。
CWnd::OnDestroy() 和 CWnd::OnNcDestroy() 以及 CWnd::PostNcDestroy()
CWnd::OnDestroy() 调用缺省处理函数Default()。
CWnd::OnNcDestroy() 首先判断当前线程的主窗口是否是该窗口,如果是且模块非DLL,则发送WM_QUIT消息,使得程序结束;
然后,判断当前线程的活动窗口是否是该窗口,如果是则设置活动窗口为NULL;
接着,清理Tooltip窗口,调用Default由 Windows缺省处理WM_NCDESTROY消息,UNSUBCLASS,把窗口句柄和MFC
窗口对象分离(Detach);
最后,调用虚函数PostNcDestoy()。
见《MFC教程_应用程序的退出》http://www.vczx.com/tutorial/mfc/mfc6.php
总结一下的话,DestroyWindows可以理解成是主动的,OnDestroy是被动的.
用户主动调用DestroyWindows来关闭窗口,而当窗口被关闭时OnDestroy函数被调用!
你调用DestroyWindow(),那么系统就会发一个WM_DESTROY的消息,这个消息会调用OnDestroy()函数.
DestroyWindow() ------> WM_DESTROY + WM_NCDESTROY ------>OnDestroy()
发消息 响应消息映射
另外,如果要在退出时提示用户,应在 OnClose()或OnOK()、OnCancel()中作出处理,而不能在响应WM_DESTROY时处理
,因为那是窗口已经销毁了(但应用程序并没有退出)。在处理WM_DESTROY消息时,系统会调用
PostQuitMessage()向消息队里投递WM_QUIT消息,结束消息循环。(见《VC++深入详解》P18)
最后注意一个问题,通常我们创建一个非模态窗口时,可能会这样写
{
CDialog * pWnd = new CMyDialog();
pWnd->Create(……);
pWnd->ShowWindow(SW_SHOW);
}
很肯能是在一个模块或者一个函数中创建窗口,但是却无法知道什么时候关闭窗口。而pWnd也只是作为一个局部变量。那么如何对它进行析构呢?
通常这样是重载虚函数PostNcDestroy()来实现
void CMyDialog::PostNcDestroy()
{
CDialog::PostNcDestroy();
delete this;
}
为什么把对话框类的delete this放在PostNcDestroy中而不是OnNcDestroy?
这是因为OnNcDestroy只被已建立的窗口调用。如果建立窗口失败(如PreCreateWindow), 则没有窗口处来发送
WM_NCDESTROY消息。PostNcDestroy是在对象窗口被完全删除, 在OnNcDestroy后,甚至在窗口建立失败之后
调用的。
以上是学习MFC窗口关闭销毁等相关知识时的一些总结。
在子窗口中退出程序应使用PostQuitMessage(0);函数实现。
函数GetMessage里是使用一个循环不断地检测消息,周止复始的,是不可能出现死亡的,但它会检测到消息WM_QUIT就退出来。那现在问题是谁发送WM_QUIT消息出来呢?这就是PostQuitMessage函数所做的工作。当你点击窗口右上角的关闭时,Windows就会把窗口从系统里删除,这时就会发出消息WM_DESTROY给窗口消息处理函数WindowProc,WindowProc收到这条消息后,最需要做的一件事情就是调用PostQuitMessage发出退出消息,让消息循环结束。
函数PostQuitMessage声明如下:
WINUSERAPI
VOID
WINAPI
PostQuitMessage(
__in int nExitCode);
nExitCode是退出标识码,它被放到WM_QUIT消息的参数wParam里。
VC关闭窗口退出 http://www.cnblogs.com/carekee/articles/2006715.html
1、OnOK()或OnCancel()//只对窗口程序有用
2、PostQuitMessage(0);//最常用
3、ExitProcess(0);
4、发送WM_CLOSE消息,如:
SendMessage(WM_CLOSE, 0, 0);
5、TerminateProcess
6、CDialog.Destroy()
7、exit(0);
8、 void CMainFrame::OnClose()
{
// TODO: Add your message handler code here and/or call default
if (MessageBox("确定要退出吗?","提示",MB_YESNO|MB_DEFBUTTON2)==IDYES)
{
CFrameWnd::OnClose();
}
}
如果是关闭其它程序
// 一种方法,通过窗口文字
HWND hWnd = ::FindWindow(NULL, _T("MSDN Library Visual Studio 6.0")); // 注: 这个是窗口的标题文字
if (NULL != hWnd) {
::SendMessage(hWnd, WM_CLOSE, 0, 0);
}
//另外一种方法,进程ID
DWORD id_num;
HWND hWnd = ::FindWindow(NULL, _T("MSDN Library Visual Studio 6.0"));
GetWindowThreadProcessId(hWnd, &id_num); //注意:第二个参数是进程的ID,返回值是线程的ID。
HANDLE hd = OpenProcess(PROCESS_ALL_ACCESS,FALSE, id_num);
TerminateProcess(hd, 0);
如果窗口文字是会变的,可以使用FindWindow的第一个参数:应用程序的类名。
可以通过VC提供的Spy++这个软件获得ClassName。
从开始菜单->MS 6.0 Tools->spy++,找出你要关闭的程序,比如说spy++,双击它,看Class选项的Class Name是Afx:400000:8:10011:0:15503db。
然后:
HWND hWnd = ::FindWindow(_T("Afx:400000:8:10011:0:15503db"), NULL);
GetWindowThreadProcessId(hWnd, &id_num); //注意:第二个参数是进程的ID,返回值是线程的ID。
HANDLE hd = OpenProcess(PROCESS_ALL_ACCESS,FALSE, id_num);
TerminateProcess(hd, 0);
窗口关闭过程http://blog.sina.com.cn/s/blog_48ab47450100lrib.html
——OnOK(),OnCancel(),OnClose(),EndDialog(),DestroyWindow(),OnDestroy(),OnNcDestroy()
一、对于非模态窗口,必须重载OnCancel函数,在函数中调用DestroyWindows()方法,且不能调用基类的函数。因为基类函数中调用的是 EndDialog()方法。而OnClose()也会调用OnCancel()方法。另外想通过OnOK关闭对话框,也必须同样处理,不能直接用默认方法。
1 、只有点击标题栏的叉号图标、在桌面任务栏右键-关闭、Alt+F4、标题栏最左边图标上单击-关闭,发送WM_CLOSE消息,触发 OnClose()。
所以对于非模态窗口,其关闭过程
OnClose()->OnCancel()->DestroyWindow()->OnDestroy()->OnNcDestroy() , ->仅表示时间先后而已
而OnNcDestroy()最后又调用了PostNcDestroy()
2、回车、ESC、点击“确定”或“取消”,都不会调用OnClose()
一般来说,OnOK是对ID_OK的响应, OnCancel是对IDCANCEL的响应. 前者对应键盘的Enter, 后者对应Esc。
OnCancel()->DestroyWindow()->OnDestroy()->OnNcDestroy()
OnOK()->DestroyWindow()->OnDestroy()->OnNcDestroy()
OnNcDestroy()最后又调用了PostNcDestroy()
OnOK()与OnCancel()
如前面所述,OnOK是对ID_OK的响应, OnCancel是对IDCANCEL的响应. 前者对应键盘的Enter, 后者对应Esc。
OnOK()和OnCancel()都调用了EndDialog().OnOK调用了UpdateData(TRUE)而OnCacel()没有调用。
在OnOK()结束刚进入DestroyWindow时,其实窗口并未关闭,依然可以用ShowWindow显示出来
模态的对话框可以用EndDialog来销毁, 非模态的对话框要用DestroyWindow来销毁
见《OnOK与OnCancel》http://ponymaggie.blog.sohu.com/135823530.html
EndDialog()
该函数清除一个模态对话框,并使系统中止对对话框的任何处理
对于DoModal出来的窗口,可以使用默认的OnOk()和OnCancel()来处理。其基类方法中会调用EndDialog()方法。
它只能在对话框的消息处理函数里使用,并且这个函数调用之后,没有立即就删除对话框的,而是设置了操作系统里的结束标志。当操作系统查检到有这个标志时,就去删除对话框的消息循环,同时也去释放对话框占用的资源。其实对话框的生命周期是这样的,先由函数DialogBox创建对话框,这样函数 DialogBox完成创建对话框但还没有显示前会发出消息WM_INITDIALOG,让对话框有机会初始化上面所有窗口或控件的显示,比如设置文本框的字符串等。最后当用户点出确定或者取消的按钮,就收到两个命令IDOK或IDCANCEL,这时就可以调用函数EndDialog来结束对话框的生命。
见《Windows API一日一练(18)EndDialog函数》http://blog.csdn.net/caimouse/archive/2007/07/30/1716140.aspx
DestroyWindows()
CWnd::DestroyWindow销毁m_hWnd(必须非空),同时销毁其菜单、定时器,以及完成其他清理工作。
::DestroyWindow使将被销毁的窗口失去激活、失去输入焦点,并发送WM_DESTROY、WM_NCDESTROY消息到该窗口及其各级子窗口。如果被销毁的窗口是子窗口且没有设置WM_NOPARENTNOTFIY风格,则给其父窗口发送WM_PARENTNOFITY消息。
CWnd::OnDestroy() 和 CWnd::OnNcDestroy() 以及 CWnd::PostNcDestroy()
CWnd::OnDestroy() 调用缺省处理函数Default()。
CWnd::OnNcDestroy() 首先判断当前线程的主窗口是否是该窗口,如果是且模块非DLL,则发送WM_QUIT消息,使得程序结束;
然后,判断当前线程的活动窗口是否是该窗口,如果是则设置活动窗口为NULL;
接着,清理Tooltip窗口,调用Default由 Windows缺省处理WM_NCDESTROY消息,UNSUBCLASS,把窗口句柄和MFC
窗口对象分离(Detach);
最后,调用虚函数PostNcDestoy()。
见《MFC教程_应用程序的退出》http://www.vczx.com/tutorial/mfc/mfc6.php
总结一下的话,DestroyWindows可以理解成是主动的,OnDestroy是被动的.
用户主动调用DestroyWindows来关闭窗口,而当窗口被关闭时OnDestroy函数被调用!
你调用DestroyWindow(),那么系统就会发一个WM_DESTROY的消息,这个消息会调用OnDestroy()函数.
DestroyWindow() ------> WM_DESTROY + WM_NCDESTROY ------>OnDestroy()
发消息 响应消息映射
另外,如果要在退出时提示用户,应在 OnClose()或OnOK()、OnCancel()中作出处理,而不能在响应WM_DESTROY时处理
,因为那是窗口已经销毁了(但应用程序并没有退出)。在处理WM_DESTROY消息时,系统会调用
PostQuitMessage()向消息队里投递WM_QUIT消息,结束消息循环。(见《VC++深入详解》P18)
最后注意一个问题,通常我们创建一个非模态窗口时,可能会这样写
{
CDialog * pWnd = new CMyDialog();
pWnd->Create(……);
pWnd->ShowWindow(SW_SHOW);
}
很肯能是在一个模块或者一个函数中创建窗口,但是却无法知道什么时候关闭窗口。而pWnd也只是作为一个局部变量。那么如何对它进行析构呢?
通常这样是重载虚函数PostNcDestroy()来实现
void CMyDialog::PostNcDestroy()
{
CDialog::PostNcDestroy();
delete this;
}
为什么把对话框类的delete this放在PostNcDestroy中而不是OnNcDestroy?
这是因为OnNcDestroy只被已建立的窗口调用。如果建立窗口失败(如PreCreateWindow), 则没有窗口处来发送
WM_NCDESTROY消息。PostNcDestroy是在对象窗口被完全删除, 在OnNcDestroy后,甚至在窗口建立失败之后
调用的。
以上是学习MFC窗口关闭销毁等相关知识时的一些总结。