程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> VC++模態對話框和非模態對話框,vc模態對話框

VC++模態對話框和非模態對話框,vc模態對話框

編輯:C++入門知識

VC++模態對話框和非模態對話框,vc模態對話框


MFC中有兩種類型的對話框:模態對話框和非模態對話框。 

    模態對話框是指當其顯示時,程序會暫停執行,直到關閉這個模態對話框後,才能繼續執行程序中其他任務。非模態對話框是指當其顯示時,允許轉而執行程序中其他任務,而不用關閉這個對話框。 

模態對話框的創建:創建模態對話框需要調用CDialog類的成員函數:DoModal,該函數的功能是創建並顯示一個模態對話框,其返回值將作為CDialog類的另一個成員函數:EndDialog的參數,後者的功能是關閉模態對話框。一般顯示模態對話框的實現代碼如下:

void CASCEView::OnDialog() 
{
         CASCEDlg dlg; 
         dlg.DoModal(); 
}

非模態對話框的創建:要創建非模態對話框就需要利用CDialog類的Create成員函數,該函數有以下兩種形式的聲明:

virtual BOOL Create( 
   LPCTSTR lpszTemplateName, 
   CWnd* pParentWnd = NULL 
); 

virtual BOOL Create( 
   UINT nIDTemplate, 
   CWnd* pParentWnd = NULL 
);

    由上可知,CDialog::Create函數的第一個參數可以是對話框資源的ID(nIDTemplate),或者也可以是對話框模板的名稱(lpszTemplateName);而第二個參數指定了對話框的父窗口,如果其值是NULL,則對話框的父窗口就是主應用程序窗口。

當利用Create函數創建非模態對話框時,我們還需要接著調用ShowWindow函數來將這個對話框顯示出來;而利用DoModal創建的模態對話框之所以不用,是因為DoModal函數本身就有顯示模態對話框的作用。同時我們不能像模態對話框那樣將對話框定義成對象,如下代碼是顯示不出非模態對話框的:

void CASCEView::OnDialog() 
{ 
         CASCEDlg dlg; 
         dlg.Create(IDD_DIALOG1, this); 
         dlg.ShowWindow(SW_SHOW); 
}

因為這裡創建的非模態對話框對象dlg是一個局部對象,當程序執行時,會依次執行各條代碼,當OnDialog函數執行結束時,dlg這個對象的生命周期也就玩玩了,它就會銷毀與之相關聯的對話框資源,對話框自然就顯示不出來啦!而模態對話框之所以能夠顯示,是因為當執行到調用DoModal函數以顯示模態對話框時,程序就會暫停執行,直到模態對話框關閉之後,程序才繼續向下執行。而這之前,dlg還沒銷毀。

    因此,在創建非模態對話框時,不能將對話框對象定義成局部變量,解決方法有二:一是把對話框對象定義成CASCEView類的成員變量;二是把它定義成指針,在堆上分配內存,如下:

void CASCEView::OnDialog() 
{ 
         CASCEDlg *pDlg = new CASCEDlg; 
         pDlg->Create(IDD_DIALOG1, this); 
         pDlg->ShowWindow(SW_SHOW); 
}

    但是這又引入了新的問題:我們必須釋放pDlg占用的資源,否則會造成內存洩漏!況且這裡pDlg還是一個局部指針變量,當它的生命周期結束時,在程序中就無法再引用它所指向的那塊內存了。解決方法同樣有兩個:一是將pDlg定義成CASCEView類的成員變量,然後在CASCEView類的析構函數中調用delete函數釋放它指向的內存;二是在CASCEDlg類中重載PostNcDestroy虛函數,釋放this指針指向的內存:

void CASCEDlg::PostNcDestroy() 
{ 
         delete this; 
         CDialog::PostNcDestroy(); 
}

還有一點需要注意的是:當單擊對話框上的默認OK按鈕時,兩種對話框都會消失。但對於模態對話框而言,此時對話框窗口對象被銷毀了;而對非模態對話框來說,對話框窗口對象並未被銷毀,只是隱藏起來而已。 

    在非模態對話框中單擊OK按鈕後,程序會調用基類CDialog的OnOK函數,這是一個虛函數,後者又會調用EndDialog函數,這個函數用於終止模態對話框,但對於非模態對話框,這個函數只是使對話框窗口不可見,並不銷毀它。因此,對非模態對話框來說,如果有一個ID值為IDOK的按鈕,就必須重寫基類的OnOK虛函數,並在重寫的函數中調用DestroyWindow函數,以完成銷毀對話框的工作,同時注意不要再調用基類的OnOK函數。同理,如果非模態對話框中有一個ID值為IDCANCEL的按鈕,也必須重寫基類的OnCancel虛函數,並在重寫的函數中調用DestroyWindow函數,銷毀對話框,同時注意不要再調用基類的OnCancel函數了。 

     非模態對話框相對於模態對話框,他的創建和銷毀過程和模態對話框有一定的區別

先看一下MSDN的原文: 

When   you   implement   a   modeless   dialog   box,   always   override   the   OnCancel   member   function   and   call   DestroyWindow   from   within   it.   Don’t   call   the   base   class   CDialog::OnCancel,   because   it   calls   EndDialog,   which   will   make   the   dialog   box   invisible   but   will   not   destroy   it.   You   should   also   override   PostNcDestroy   for   modeless   dialog   boxes   in   order   to   delete   this,   since   modeless   dialog   boxes   are   usually   allocated   with   new.   Modal   dialog   boxes   are   usually   constructed   on   the   frame   and   do   not   need   PostNcDestroy   cleanup. 

MS的指示:非模態對話框需要重載函數OnCanel,並且在這個函數中調用DestroyWindow。並且不能調用基類的OnCancel,因為基類的OnCancel調用了EndDialog這個函數,這個函數是針對模態對話框的。

還有一個必須重載的函數就是PostNcDestroy,這也是一個虛函數,通常的非模態對話框是用類的指針,通過new創建的,這就需要在PostNcDestroy函數中delete掉這個指針。 

了解了理論過後,下面我們就可以用代碼實現一下非模態對話框的創建和銷毀過程:

//建立

//主框架中:

CTestDlg *pDlg=new CTestDlg; 
pDlg->Create(IDD_TESTDLG,this); 
pDlg->ShowWindow(SW_SHOW);

//對話框中:

void CTestDlg::OnCancel() 
{ 
     DestroyWindow(); 
} 

void CTestDlg::PostNcDestroy() 
{ 
     CDialog::PostNcDestroy(); 
     delete this; 
}
如果要在點擊按鈕的情況下,銷毀非模態對話框,只需要把按鈕的事件映射到OnCancel函數即可。

以下是一點資料供參考: 

MFC應用程序中處理消息的順序

1.AfxWndProc()       該函數負責接收消息,找到消息所屬的CWnd對象,然後調用AfxCallWndProc 

2.AfxCallWndProc()   該函數負責保存消息(保存的內容主要是消息標識符和消息參數)供應用程序以後使用,然後調用WindowProc()函數 

3.WindowProc()       該函數負責發送消息到OnWndMsg()函數,如果未被處理,則調用DefWindowProc()函數 

4.OnWndMsg()         該函數的功能首先按字節對消息進行排序,對於WM_COMMAND消息,調用OnCommand()消息響應函數,對於WM_NOTIFY消息調用OnNotify()消息響應函數。任何被遺漏的消息將是一個窗口消息。OnWndMsg()函數搜索類的消息映像,以找到一個能處理任何窗口消息的處理函數。如果OnWndMsg()函數不能找到這樣的處理函數的話,則把消息返回到WindowProc()函數,由它將消息發送給DefWindowProc()函數 

5.OnCommand()       該函數查看這是不是一個控件通知(lParam參數不為NULL,如果lParam參數為空的話,說明該消息不是控件通知),如果它是,OnCommand()函數會試圖將消息映射到制造通知的控件;如果他不是一個控件通知(或者如果控件拒絕映射的消息)OnCommand()就會調用OnCmdMsg()函數 

6.OnCmdMsg()         根據接收消息的類,OnCmdMsg()函數將在一個稱為命令傳遞(Command Routing)的過程中潛在的傳遞命令消息和控件通知。例如:如果擁有該窗口的類是一個框架類,則命令和通知消息也被傳遞到視圖和文檔類,並為該類尋找一個消息處理函數 

MFC應用程序創建窗口的過程

1.PreCreateWindow()   該函數是一個重載函數,在窗口被創建前,可以在該重載函數中改變創建參數 (可以設置窗口風格等等) 

2.PreSubclassWindow() 這也是一個重載函數,允許首先子分類一個窗口 

3.OnGetMinMaxInfo()   該函數為消息響應函數,響應的是WM_GETMINMAXINFO消息,允許設置窗口的最大或者最小尺寸 

4.OnNcCreate()         該函數也是一個消息響應函數,響應WM_NCCREATE消息,發送消息以告訴窗口的客戶區即將被創建 

5.OnNcCalcSize()       該函數也是消息響應函數,響應WM_NCCALCSIZE消息,作用是允許改變窗口客戶區大小 

6.OnCreate()           該函數也是一個消息響應函數,響應WM_CREATE消息,發送消息告訴一個窗口已經被創建 

7.OnSize()             該函數也是一個消息響應函數,響應WM_SIZE消息,發送該消息以告訴該窗口大小已經發生變化 

8.OnMove()             消息響應函數,響應WM_MOVE消息,發送此消息說明窗口在移動 

9.OnChildNotify()     該函數為重載函數,作為部分消息映射被調用,告訴父窗口即將被告知一個窗口剛剛被創建 

MFC應用程序關閉窗口的順序(非模態窗口)

1.OnClose()       消息響應函數,響應窗口的WM_CLOSE消息,當關閉按鈕被單擊的時候發送此消息 

2.OnDestroy()     消息響應函數,響應窗口的WM_DESTROY消息,當一個窗口將被銷毀時,發送此消息 

3.OnNcDestroy()   消息響應函數,響應窗口的WM_NCDESTROY消息,當一個窗口被銷毀後發送此消息 

4.PostNcDestroy() 重載函數,作為處理OnNcDestroy()函數的最後動作,被CWnd調用 

MFC應用程序中打開模式對話框的函數調用順序

1.DoModal()             重載函數,重載DoModal()成員函數 

2.PreSubclassWindow()    重載函數,允許首先子分類一個窗口 

3.OnCreate()             消息響應函數,響應WM_CREATE消息,發送此消息以告訴一個窗口已經被創建 

4.OnSize()               消息響應函數,響應WM_SIZE消息,發送此消息以告訴窗口大小發生變化 

5.OnMove()               消息響應函數,響應WM_MOVE消息,發送此消息,以告訴窗口正在移動 

6.OnSetFont()           消息響應函數,響應WM_SETFONT消息,發送此消息,以允許改變對話框中控件的字體 

7.OnInitDialog()         消息響應函數,響應WM_INITDIALOG消息,發送此消息以允許初始化對話框中的控件,或者是創建新控件 

8.OnShowWindow()         消息響應函數,響應WM_SHOWWINDOW消息,該函數被ShowWindow()函數調用 

9.OnCtlColor()           消息響應函數,響應WM_CTLCOLOR消息,被父窗口發送已改變對話框或對話框上面控件的顏色 

10. OnChildNotify()     重載函數,作為WM_CTLCOLOR消息的結果發送 

MFC應用程序中關閉模式對話框的順序

1.OnClose()         消息響應函數,響應WM_CLOSE消息,當"關閉"按鈕被單擊的時候,該函數被調用 

2.OnKillFocus()     消息響應函數,響應WM_KILLFOCUS消息,當一個窗口即將失去鍵盤輸入焦點以前被發送 

3.OnDestroy()       消息響應函數,響應WM_DESTROY消息,當一個窗口即將被銷毀時,被發送 

4.OnNcDestroy()     消息響應函數,響應WM_NCDESTROY消息,當一個窗口被銷毀以後被發送 

5.PostNcDestroy()   重載函數,作為處理OnNcDestroy()函數的最後動作被CWnd調用 

打開無模式對話框的順序

1.PreSubclassWindow()     重載函數,允許用戶首先子分類一個窗口 

2.OnCreate()             消息響應函數,響應WM_CREATE消息,發送此消息以告訴一個窗口已經被創建 

3.OnSize()               消息響應函數,響應WM_SIZE消息,發送此消息以告訴窗口大小發生變化 

4.OnMove()               消息響應函數,響應WM_MOVE消息,發送此消息以告訴窗口正在移動 

5.OnSetFont()             消息響應函數,響應WM_SETFONT消息,發送此消息以允許改變對話框中控件的字體 

以上這些的執行都是按給定的順序執行!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved