MFC子窗口中退出程序

MFC编程 专栏收录该内容
44 篇文章 0 订阅
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窗口关闭销毁等相关知识时的一些总结。
  • 1
    点赞
  • 1
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值