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視窗關閉銷毀等相關知識時的一些總結。