如下是我從其餘網站中學的內容,後有相應的網站學習連接地址,可供學習html
1.選擇菜單項File->New->Project,彈出「New Project」對話框。編程
2.左側面板中Installed Templated的Visual C++下選擇MFC,中間窗口中選擇MFC Application,而後在下面的Name編輯框中鍵入工程名稱,本例取名「Addition」,在Location編輯框中設置工程的保存路徑。點「OK」。
app
3.點「Next」到「Application Type」對話框,在Application type下選擇Dialog based,其餘使用默認設置,點「Finish」。
框架
咱們能夠在Solution Explorer視圖中看到,此工程的文件要比單文檔應用程序少的多,在Class View中主要有三個類:CAboutDlg、CAdditionApp和CAdditionDlg。CAboutDlg是應用程序的「關於」對話框類,CAdditionApp是由CWinApp派生的類,CAdditionDlg是主對話框類,主對話框也就是此應用程序運行後顯示的主要界面。
ide
在Resource View視圖中能夠看到工程Addition的資源樹,展開Addition.rc,下面有四個子項:Dialog(對話框)、Icon(圖標)、String Table(字符串表)和Version(版本)。而後展開Dialog項,下面有兩個對話框模板,其ID分別爲:IDD_ABOUTBOX和IDD_ADDITION_DIALOG,前者是「關於」對話框的模板,後者是主對話框的模板。ID是資源的惟一標識,本質上是一個無符號整數,通常ID表明的整數值由系統定義,咱們無需干涉。
函數
可見對於主對話框來講,建立對話框第一步中的建立新的對話框模板已經由系統自動完成了。而若是是再添加對話框須要建立新的對話框模板時,須要在Resource View的「Dialog」節點上點右鍵,在右鍵菜單中選擇「Insert Dialog」,就會生成新的對話框模板,而且會自動分配ID。
工具
在Resource View的資源樹中雙擊某個ID,可在中間區域內顯示相應的資源界面。雙擊IDD_ADDITION_DIALOG時,中間區域就會顯示Addition對話框模板。以下圖:佈局
在Addition對話框模板上點右鍵,而後在右鍵菜單中選擇Properties,則在右側面板中會顯示對話框的屬性列表。以下圖:
學習
1.ID:對話框ID,惟一標識對話框資源,能夠修改。此處爲IDD_ADDITION_DIALOG,咱們不修改它。測試
2.Caption:對話框標題。此處默認爲Addition,咱們將其修改成「加法計算器」。
3.Border:邊框類型。有四種類型:None、Thin、Resizing和Dialog Frame。咱們使用默認的Dialog Frame。
4.Maximize:是否使用最大化按鈕。咱們使用默認的False。
5.Minimize:是否使用最小化按鈕。一樣咱們使用默認的False。
6.Style:對話框類型。有三種類型:Overlapped(重疊窗口)、Popup(彈出式窗口)和Child(子窗口)。彈出式窗口比較常見。咱們使用默認的Popup類型。
7.System Menu:是否帶有標題欄左上角的系統菜單,包括移動、關閉等菜單項。咱們使用默認的True。
8.Title Bar:是否帶有標題欄。咱們使用默認的True。
9.Font(Size):字體類型和字體大小。若是將其修改成非系統字體,則Use System自動改成False。而若是Use System原來爲False,將其修改成True,則Font(Size)自動設置爲系統字體。這裏咱們使用默認的系統字體。
根據以上說明,其實咱們只修改了標題屬性。這時咱們運行此程序後的界面以下:
1.爲對話框添加一個靜態文本框(Static Text),用於顯示字符串--「被加數」。
對於自動添加的一個標題爲「TODO:Place dialog controls here.」的靜態文本框,這裏將它刪掉,繼續添加新的靜態文本框。
刪除控件時,可使用鼠標左鍵點擊選中它,選中後控件的周圍會出現虛線框,而後按Delete鍵就能夠將其刪除了。在「Addition」工程的Resource View中打開上一講中建立的對話框模板IDD_ADDITION_DIALOG,自動添加的靜態文本框就可使用這種方法刪除。
在添加新的靜態文本框之前,先看看Toolbox視圖是否顯示了,若是沒有顯示,在菜單欄上點擊View->Toolbox便可。Toolbox視圖以下圖:
Toolbox中列出了一些經常使用控件,其中有一個是Static Text,便是咱們要添加的控件。在Toolbox中的Static Text上點下鼠標左鍵不放開,並拖到IDD_ADDITION_DIALOG對話框模板上,模板上會出現一個虛線框,咱們找到合適的位置鬆開鼠標左鍵放下它。
用鼠標左鍵選中控件後周圍出現虛線框,而後鼠標移到虛線框上幾個黑點的位置會變成雙向箭頭的形狀,此時就能夠按下鼠標左鍵並拖動來改變控件大小了。咱們能夠這樣改變新添加的靜態文本框控件的大小,以更好的顯示標題。固然,整個對話框模板也能夠用這種方法改變大小。
接下來就該修改靜態文本框的文字了。鼠標右鍵點擊靜態文本框,在右鍵菜單中選擇「Properties」,Properties面板就會顯示出來,在面板上修改Caption屬性爲「被加數」,ID修改成IDC_SUMMAND_STATIC。此時模板以下圖:
2.爲對話框添加一個編輯框(Edit Control),用來輸入被加數。
添加編輯框的過程與靜態文本框相似,在Toolbox中選中Edit Control控件拖到對話框模板上,並使其與以前的靜態文本框水平對齊(爲了美觀),而後調整其大小使之適合被加數的輸入。
在編輯框上點右鍵,仍然在右鍵菜單中選擇「Properties」顯示出屬性(Properties)面板,修改其ID爲IDC_SUMMAND_EDIT。此時模板以下圖:
3.按照1的方法添加一個標題爲「加數」的靜態文本框,用於顯示字符串--「加數」。並將其ID改成IDC_ADDEND_STATIC。
4.按照2的方法添加一個ID爲IDC_ADDEND_EDIT的編輯框,用來輸入加數。
5.按照1的方法添加一個標題爲「和」的靜態文本框,用於顯示文字--「和」。並修改其ID爲IDC_SUM_STATIC。
6.按照2的方法添加一個ID爲IDC_SUM_EDIT的編輯框,用來顯示最終的加和。
7.相似的添加按鈕(Button)控件到對話框模板,用於在被點擊後觸發加法計算。修改其標題爲「計算」,ID爲IDC_ADD_BUTTON。
到此,對話框模板如圖:
8.刪除OK按鈕。打開Cancel按鈕的屬性面板,將標題改成「退出」,並使其與「計算」按鈕水平對齊。
9.根據控件的佈局,適當調整整個對話框模板的大小,使其相對控件佈局來講大小合適,界面美觀。
這樣在對話框模板中就把咱們在本例中須要用到的控件就添加完了。最終效果以下:
由於例程Addition是基於對話框的程序,因此程序自動建立了對話框模板IDD_ADDITION_DIALOG,並自動生成了對話框類CAdditionDlg,它是從CDialogEx類派生的。你們用過VC++ 6.0的可能記得,咱們定義的對話框類都是從CDialog類派生的,但在VS2010中,通常對話框類都是繼承自CDialogEx類。
建立對話框類
若是是本身新添加的對話框模板,怎樣爲它建立對話框類呢?
1.在Resource View的「Dialog」節點上右鍵,而後在右鍵菜單中選擇「Insert Dialog」建立一個新的對話框模板,ID就使用默認的IDD_DIALOG1。
2.在中間區域會顯示新建的對話框模板,而後選中此對話框模板,點右鍵,在右鍵菜單中選擇Add Class。
3.選擇「Add Class」後會彈出一個對話框,在對話框中「Class name」下的編輯框中寫入自定義的類名就能夠了,例如CMyDialog。
4.最後點「Finish」完成。
最終你就能夠在Class View中看到新生成的對話框類CMyDialog了,而且在Solution Explorer中有相應的MyDialog.h頭文件和MyDialog.cpp源文件生成。CMyDialog類一樣派生於CDialogEx類。
注意,通常類名都以C打頭,又好比,CTestDlg。
爲對話框中的控件添加變量
在上一講中爲對話框添加了幾個控件,包括三個靜態文本框,三個編輯框,一個按鈕控件。程序自動生成的Cancel按鈕保留,做爲退出按鈕,而OK按鈕刪除掉了。
靜態文本框只是爲了說明後面緊跟的編輯框中數據的意義,是被加數、加數仍是和,因此它們是不會變的,咱們就不爲它們添加變量了。按鈕控件是用來操做的,這裏也不爲它們添加變量。編輯框中的數據可能會常常變化,有必要爲它們每一個控件關聯一個變量。
首先爲被加數的編輯框IDC_SUMMAND_EDIT添加變量。
1.在編輯框上點右鍵,在右鍵菜單中選擇「Add Variable」。彈出添加成員變量的嚮導對話框。
2.咱們想爲其添加值變量而不是控件變量,因此對話框中「Category」下的組合框中選擇Value。
3.「Variable type」下的組合框此時默認選中的是「CString」,CString是字符串類,顯然不能進行加法運算。咱們能夠選擇double、float、int等。這裏咱們選擇double,即編輯框關聯一個double類型的變量。
4.在「Variable name」中寫入自定義的變量名。雞啄米爲其取名m_editSummand。
5.點「Finish」完成。
注意,類的成員變量名通常以m_打頭,以標識它是一個成員變量。
參照此方法,再分別爲加數的編輯框IDD_ADDEND_EDIT添加double型變量m_editAddend、和的編輯框IDD_SUM_EDIT添加double型變量m_editSum。
對話框類的數據交換和檢驗
在程序運行界面中,用戶每每會改變控件的屬性,例如,在編輯框中輸入字符串,或者改變組合框的選中項,又或者改變複選框的選中狀態等。控件的屬性改變後MFC會相應修改控件關聯變量的值。這種同步的改變是經過MFC爲對話框類自動生成的成員函數DoDataExchange()來實現的,這也叫作對話框的數據交換和檢驗機制。
咱們爲三個編輯框添加了變量之後,在AdditionDlg.cpp中CAdditionDlg的DoDataExchange()函數的函數體中多了三條DDX_Text調用語句。下面是函數體代碼和雞啄米添加的註釋。
- void CAdditionDlg::DoDataExchange(CDataExchange* pDX)
- {
- // 處理MFC默認的數據交換
- CDialogEx::DoDataExchange(pDX);
- // 處理控件IDC_SUMMAND_EDIT和變量m_editSummand之間的數據交換
- DDX_Text(pDX, IDC_SUMMAND_EDIT, m_editSummand);
- // 處理控件IDC_ADDEND_EDIT和變量m_editAddend之間的數據交換
- DDX_Text(pDX, IDC_ADDEND_EDIT, m_editAddend);
- // 處理控件IDC_SUM_EDIT和變量m_editSum之間的數據交換
- DDX_Text(pDX, IDC_SUM_EDIT, m_editSum);
- }
再以Addition程序爲例簡單說下數據交換機制。若是咱們在程序運行界面中輸入被加數,則經過CAddition的DoDataExchange()函數能夠將輸入的值保存到m_editSummand變量中,反之若是程序運行中修改了變量m_editSummand的值,則經過CAddition的DoDataExchange()函數也能夠將新的變量值顯示到被加數的編輯框中。
可是這種數據交換機制中,DoDataExchange()並非被自動調用的,而是須要咱們在程序中調用CDialogEx::UpdateData()函數,由UpdateData()函數再去自動調用DoDataExchange()的。
CDialogEx::UpdateData()函數的原型爲:
BOOL UpdateData(BOOL bSaveAndValidate = TRUE);
參數:bSaveAndValidate用於指示數據傳輸的方向,TRUE表示從控件傳給變量,FALSE表示從變量傳給控件。默認值是TRUE,即從控件傳給變量。
返回值:CDialogEx::UpdateData()函數的返回值表示操做是否成功,成功則返回TRUE,不然返回FALSE。
在下一講中將具體演示CDialogEx::UpdateData()函數如何使用。
雞啄米本節主要講的是新建對話框類和添加控件變量,控件的消息處理函數將在下一講詳細介紹。
*********************************************************************************************************************************************************************
建立對話框類和添加控件變量在上一講中已經講過,這一講的主要內容是如何爲控件添加消息處理函數。
MFC爲對話框和控件等定義了諸多消息,咱們對它們操做時會觸發消息,這些消息最終由消息處理函數處理。好比咱們點擊按鈕時就會產生BN_CLICKED消息,修改編輯框內容時會產生EN_CHANGE消息等。通常爲了讓某種操做達到效果,咱們只須要實現某個消息的消息處理函數。
一.添加消息處理函數
雞啄米仍之前面的加法計算器的程序爲例,說明怎樣爲「計算」按鈕控件添加消息處理函數。添加方法列出4種:
1.使用Class Wizard添加消息處理函數
用過的VC++ 6.0的朋友應該對Class Wizard很熟悉了,添加類、消息處理函數等常常會用到它,能夠說是一個很核心的功能。但從VS2002開始就見不到Class Wizard了,大部分功能都集成到對話框和控件等的屬性中了,使用很方便。到VS2010,久違的Class Wizard又回來了。但雞啄米已經習慣了使用屬性中的功能了,對於從VC++ 6.0直接轉VS2010的朋友可能以爲仍是使用Class Wizard比較習慣。
你們應該記得,「計算」按鈕的ID爲IDC_ADD_BUTTON,上圖中Commands標籤下,Oject IDs列表中有此ID,由於咱們是想實現點擊按鈕後的消息處理函數,因此在Messages列表中選擇BN_CLICKED消息,而後點右上方的Add Handler就能夠添加BN_CLICKED消息處理函數OnClickedAddButton了。固然你也能夠更名,但通常用的默認的就能夠。
2.經過「Add Event Handler...」添加消息處理函數
在「計算」按鈕上點右鍵,而後在右鍵菜單中選擇菜單項「Add Event Handler...」,彈出「Event Handler Wizard」對話框,以下圖:
可見「Message type」中默認選中的就是BN_CLICKED消息,函數名和所在類都已經自動給出,直接點「Add and Edit」就能夠了。
3.在按鈕的屬性視圖中添加消息處理函數
上面說過,從VS2002開始就主要從屬性視圖添加消息處理函數了。咱們在「計算」按鈕上點右鍵,在右鍵菜單中選擇「Properties」,右側面板中會顯示按鈕的屬性視圖。
咱們能夠像上圖中那樣,點屬性視圖的「Control Events」按鈕(相似閃電標誌),下面列出了「計算」按鈕的全部消息。咱們要處理的是BN_CLICKED消息,點其右側空白列表項,會出現一個帶下箭頭的按鈕,再點此按鈕會出現「<Add> OnBnClickedAddButton」選項,最後選中這個選項就會自動添加BN_CLICKED處理函數了。
4.雙擊按鈕添加消息處理函數
最直接最簡單的方法就是,雙擊「計算」按鈕,MFC會自動爲其在CAdditionDlg類中添加BN_CLICKED消息的處理函數OnBnClickedAddButton()。
二.在消息處理函數中添加自定義功能
在咱們使用任意一種方法添加了消息處理函數之後,都只能獲得一個空的OnBnClickedAddButton()函數的函數體,要實現咱們想要的功能,還須要在函數體中加入自定義功能代碼。
在加法計算器程序中,咱們想要「計算」按鈕實現的功能是,獲取被加數和加數的數值,而後計算它們的和並顯示到和的編輯框裏。那麼,OnBnClickedAddButton()的函數體就應修改成:
- void CAdditionDlg::OnBnClickedAddButton()
- {
- // TODO: Add your control notification handler code here
- // 將各控件中的數據保存到相應的變量
- UpdateData(TRUE);
- // 將被加數和加數的加和賦值給m_editSum
- m_editSum = m_editSummand + m_editAddend;
- // 根據各變量的值更新相應的控件。和的編輯框會顯示m_editSum的值
- UpdateData(FALSE);
- }
雞啄米在上面的代碼中已經添加註釋,你們應該很容易理解了。對於UpdateData()函數的說明在上一講中已經介紹過,若是忘了能夠再回上一講了解了解。
接下來咱們運行下此應用程序。在運行結果界面中,輸入被加數5.1,加數2.3,而後點「計算」:
在上圖中能夠看到,點「計算」按鈕後,和的編輯框中顯示了正確結果:7.4。
雞啄米簡單分析下運行過程:輸入被加數和加數,點「計算」按鈕後產生點擊消息,從而調用OnBnClickedAddButton()函數。進入此函數後,首先由UpdateData(TRUE)函數將被加數的值5.1和加數的值2.3分別保存到變量m_editSummand和m_editAddend,而後經過語句m_editSum = m_editSummand + m_editAddend;計算出被加數和加數的和爲7.4,並把7.4賦值給m_editSum。最後調用UpdateData(FALSE)根據被加數、加數、和的值更新三個編輯框的顯示值,就獲得了上圖中的結果。
到此,一個具備簡單的加法運算功能的加法計算器應用程序就基本完成了。
************************************************************************************************************************************************************************
本節主要講對話框上控件的Tab順序如何調整。
上一講爲「計算」按鈕添加了消息處理函數後,加法計算器已經可以進行浮點數的加法運算。可是還有個遺留的小問題,就是對話框控件的Tab順序問題。
運行加法計算器程序,顯示對話框後不進行任何操做,直接按回車,能夠看到對話框退出了。這是由於「退出」按鈕是Tab順序爲1的控件,也就是第一個接受用戶輸入的控件。可是按照咱們的輸入習慣,應該是被加數的編輯框首先接受用戶輸入,而後是加數編輯框,再接下來是「計算」按鈕,最後纔是「退出」按鈕。
咱們先來直觀的看看各個控件的Tab順序吧。打開「Resource View」視圖,而後在資源中找到對話框IDD_ADDITION_DIALOG,雙擊ID後中間客戶區域出現其模板視圖。在主菜單中選擇「Format」->"Tab Order",或者按快捷鍵Ctrl+D,對話框模板上就會顯示各個控件的Tab順序數字。以下圖:
上圖中每一個控件左上角都有一個數字,這就是它的Tab響應順序。對話框剛打開時輸入焦點就在Tab順序爲1的「退出」按鈕上,不作任何操做按下Tab鍵,輸入焦點就會轉移到Tab順序爲2的「被加數」靜態文本框上,可是由於靜態文本框不接受任何輸入,因此輸入焦點繼續自動轉移到Tab順序爲3的被加數編輯框,再按Tab鍵,輸入焦點又會轉移到Tab順序爲4的「加數」靜態文本框上,一樣因爲它是靜態文本框,輸入焦點不停留繼續轉移到加數編輯框,後面的控件同理。
咱們認爲這個順序不合理,那怎麼修改呢?很簡單,從本身認爲Tab順序應該爲1的控件開始依次單擊,隨着單擊的完成,各控件的Tab響應順序也按咱們的想法設置好了。
例如,此例中咱們能夠依次單擊被加數編輯框、「被加數」靜態文本框、加數編輯框、「加數」靜態文本框、和編輯框、「和」靜態文本框、「計算」按鈕和「退出」按鈕。設置完後以下圖:
最後按ESC鍵,確認設置並退出對話框模板的Tab順序設置狀態。
如今咱們再運行程序,能夠看到對話框打開後最初的輸入焦點在被加數編輯框上,而後咱們按Tab鍵,輸入焦點移到加數編輯框上,繼續屢次按Tab鍵時,輸入焦點會按「和編輯框--‘計算’按鈕--‘退出’按鈕--被加數編輯框--加數編輯框--和編輯框......」的順序循環轉移。這樣就達到了咱們的目的。
*******************************************************************************************************************************************************************************************
加法計算器對話框程序你們照着作一遍後,相信對基於對話框的程序有些瞭解了,有個好的開始對於之後的學習大有裨益。趁熱打鐵,雞啄米這一節講講什麼是模態對話框和非模態對話框,以及模態對話框怎樣彈出。
一.模態對話框和非模態對話框
Windows對話框分爲兩類:模態對話框和非模態對話框。
模態對話框是這樣的對話框,當它彈出後,本應用程序其餘窗口將再也不接受用戶輸入,只有該對話框響應用戶輸入,在對它進行相應操做退出後,其餘窗口才能繼續與用戶交互。
非模態對話框則是,它彈出後,本程序其餘窗口仍能響應用戶輸入。非模態對話框通常用來顯示提示信息等。
你們對Windows系統很瞭解,相信這兩種對話框應該都遇到過。以前的加法計算器對話框其實就是模態對話框。
二.模態對話框是怎樣彈出的
畢竟加法計算器程序大部分都是MFC自動生成的,對話框怎麼彈出來的你們可能還不是很清楚。雞啄米下面簡單說說它是在哪裏彈出來的,再從新建一個新的對話框並彈出它,這樣你們實踐之後就能更靈活的使用模態對話框了。
你們打開Addition.cpp文件,能夠看到CAdditionApp類有個InitInstance()函數,在MFC應用程序框架分析中提到過此函數,不過那是單文檔應用程序App類中的,函數體不太相同,但都是進行App類實例的初始化工做。
InitInstance()函數的後半部分有一段代碼就是定義對話框對象並彈出對話框的,雞啄米下面給出這段代碼並加以註釋:
- CAdditionDlg dlg; // 定義對話框類CAdditionDlg的對象dlg
- m_pMainWnd = &dlg; // 將dlg設爲主窗口
- INT_PTR nResponse = dlg.DoModal(); // 彈出對話框dlg,並將DoModal函數的返回值(退出時點擊按鈕的ID)賦值給nResponse
- if (nResponse == IDOK) // 判斷返回值是否爲OK按鈕(其ID爲IDOK,雞啄米已經將它刪除)
- {
- // TODO: Place code here to handle when the dialog is
- // dismissed with OK
- }
- else if (nResponse == IDCANCEL) // 判斷返回值是否爲Cancel按鈕(其ID爲IDCANCEL,雞啄米將它的Caption改成了「退出」)
- {
- // TODO: Place code here to handle when the dialog is
- // dismissed with Cancel
- }
彈出對話框比較關鍵的一個函數,就是對話框類的DoModal()函數。CDialog::DoModal()函數的原型爲:
virtual INT_PTR DoModal();
返回值:整數值,指定了傳遞給CDialog::EndDialog(該函數用於關閉對話框)的nResult參數值。若是函數不能建立對話框,則返回-1;若是出現其它錯誤,則返回IDABORT。
調用了它對話框就會彈出,返回值是退出對話框時所點的按鈕的ID,好比,咱們點了「退出」按鈕,那麼DoModal返回值爲IDCANCEL。
三.添加一個新對話框並彈出它
雞啄米再爲加法計算器程序添加一個對話框,以在計算以前詢問用戶是否肯定要進行計算。你們能夠完整的看下對話框的添加和彈出過程。
1.在Resource View中的「Dialog」上點右鍵選擇「Insert Dialog」,建立一個新的對話框模板,修改其ID爲IDD_TIP_DIALOG,Caption改成「提示」,而後參考「爲對話框添加控件」中所講,在對話框模板上添加一個靜態文本框(static text),Caption改成「您肯定要進行加法計算嗎?」,接下來修改OK按鈕的Caption爲「肯定」,Cancel按鈕的Caption爲「取消」,最後調整各個控件的位置和對話框的大小。最終的對話框模板以下圖:
2.根據「建立對話框類和添加控件變量」中建立對話框類的方法,在對話框模板上點右鍵選擇「Add Class...」,彈出添加類的對話框,設置「Class name」爲CTipDlg,點「OK」。在Solution Explorer中能夠看到生成了CTipDlg類的頭文件TipDlg.h和源文件TipDlg.cpp。
3.咱們要在點「計算」按鈕以後彈出此提示對話框,那麼就要在「計算」按鈕的消息處理函數OnBnClickedAddButton()中訪問提示對話框類,因此爲了訪問CTipDlg類,在AdditionDlg.cpp中包含CTipDlg的頭文件:#include "TipDlg.h"。
4.修改OnBnClickedAddButton()的函數體,在全部代碼前,構造CTipDlg類的對象tipDlg,並經過語句tipDlg.DoModal();彈出對話框,最後判斷DoModal()函數的返回值是IDOK仍是IDCANCEL來肯定是否繼續進行計算。OnBnClickedAddButton()函數修改後以下:
- void CAdditionDlg::OnBnClickedAddButton()
- {
- // TODO: Add your control notification handler code here
- INT_PTR nRes; // 用於保存DoModal函數的返回值
- CTipDlg tipDlg; // 構造對話框類CTipDlg的實例
- nRes = tipDlg.DoModal(); // 彈出對話框
- if (IDCANCEL == nRes) // 判斷對話框退出後返回值是否爲IDCANCEL,若是是則return,不然繼續向下執行
- return;
- // 將各控件中的數據保存到相應的變量
- UpdateData(TRUE);
- // 將被加數和加數的加和賦值給m_editSum
- m_editSum = m_editSummand + m_editAddend;
- // 根據各變量的值更新相應的控件。和的編輯框會顯示m_editSum的值
- UpdateData(FALSE);
- }
5.測試。編譯運行程序後,在對話框上輸入被加數和加數,點「計算」,彈出提示對話框詢問是否進行計算,若是選擇「肯定」,則提示對話框退出,並在主對話框上顯示被加數和加數的和,而若是選擇「取消」,則提示對話框也會退出,但主對話框顯示的和不變,即沒有進行加法計算。
**********************************************************************************************************************************************************************
本節接着講另外一種對話框--非模態對話框的建立及顯示。
雞啄米已經說過,非模態對話框顯示後,程序其餘窗口仍能正常運行,能夠響應用戶輸入,還能夠相互切換。雞啄米會將上一講中建立的Tip模態對話框改成非模態對話框,讓你們看下效果。
實際上,模態對話框和非模態對話框在建立對話框資源和生成對話框類上是沒有區別的,因此上一講中建立的IDD_TIP_DIALOG對話框資源和CTipDlg類都不須要修改。
建立及顯示非模態對話框的步驟
須要修改的是,對話框類實例的建立和顯示,也就是以前在CAdditionDlg::OnBnClickedAddButton()函數體中添加的對話框顯示代碼。下面是具體步驟:
1.在AdditionDlg.h中包含CTipDlg頭文件並定義CTipDlg類型的指針成員變量。詳細操做方法是,在AdditionDlg.cpp中刪除以前添加的#include "TipDlg.h",而在AdditionDlg.h中添加#include "TipDlg.h",這是由於咱們須要在AdditionDlg.h中定義CTipDlg類型的指針變量,因此要先包含它的頭文件;而後在AdditionDlg.h中爲CAdditionDlg類添加private成員變量CTipDlg *m_pTipDlg;。
2.在CAdditionDlg類的構造函數中初始化成員變量m_pTipDlg。若是cpp文件中函數太多,咱們能夠在Class View上半個視圖中找到CAdditionDlg類,再在下半個視圖中找到其構造函數雙擊,中間客戶區域便可立刻切到構造函數的實現處。在構造函數體中添加m_pTipDlg = NULL;,這是個好習慣,雞啄米在C++編程入門系列的指針的賦值和指針運算中說到過,在任何指針變量使用前都初始化,能夠避免因誤訪問重要內存地址而破壞此地址的數據。
3.將上一講中添加的模態對話框顯示代碼註釋或刪除掉,添加非模態對話框的建立和顯示代碼。VC++中註釋單行代碼使用「//」,註釋多行代碼能夠在需註釋的代碼開始處添加「/*」,結束處添加「*/」。修改後的CAdditionDlg::OnBnClickedAddButton()函數以下:
- void CAdditionDlg::OnBnClickedAddButton()
- {
- // TODO: Add your control notification handler code here
- /*INT_PTR nRes; // 用於保存DoModal函數的返回值
- CTipDlg tipDlg; // 構造對話框類CTipDlg的實例
- nRes = tipDlg.DoModal(); // 彈出對話框
- if (IDCANCEL == nRes) // 判斷對話框退出後返回值是否爲IDCANCEL,若是是則return,不然繼續向下執行
- return;*/
- // 若是指針變量m_pTipDlg的值爲NULL,則對話框還未建立,須要動態建立
- if (NULL == m_pTipDlg)
- {
- // 建立非模態對話框實例
- m_pTipDlg = new CTipDlg();
- m_pTipDlg->Create(IDD_TIP_DIALOG, this);
- }
- // 顯示非模態對話框
- m_pTipDlg->ShowWindow(SW_SHOW);
- // 將各控件中的數據保存到相應的變量
- UpdateData(TRUE);
- // 將被加數和加數的加和賦值給m_editSum
- m_editSum = m_editSummand + m_editAddend;
- // 根據各變量的值更新相應的控件。和的編輯框會顯示m_editSum的值
- UpdateData(FALSE);
- }
4.由於此非模態對話框實例是動態建立的,因此須要手動刪除此動態對象來銷燬對話框。咱們在CAdditionDlg類的析構函數中添加刪除代碼,可是MFC並無自動給出析構函數,這時須要咱們手動添加,在對話框對象析構時就會調用咱們自定義的析構函數了。在AdditionDlg.h文件中爲CAdditionDlg添加析構函數聲明:~CAdditionDlg();,而後在AdditionDlg.cpp文件中添加析構函數的實現,函數體以下:
- CAdditionDlg::~CAdditionDlg()
- {
- // 若是非模態對話框已經建立則刪除它
- if (NULL != m_pTipDlg)
- {
- // 刪除非模態對話框對象
- delete m_pTipDlg;
- }
- }
這樣,非模態對話框建立和顯示的代碼就添加修改完了。讓咱們運行下看看效果吧。
在加法計算器對話框上輸入被加數和加數,而後點「計算」按鈕,依然像上節同樣彈出了提示對話框,可是先不要關閉它,你能夠拖動它後面的加法計算器對話框試試,咱們發現加法計算器對話框居然能夠拖動了,並且「和」編輯框裏已經顯示了運算結果,這代表提示對話框顯示之後尚未關閉,OnBnClickedAddButton() 就繼續向下執行了,不只如此,加法計算器的每一個編輯框還均可以響應輸入。
這只是一個簡單的例子,非模態對話框的用處有不少,之後你們在軟件開發中會用到。
本節教程就到這裏了,相信你們對對話框的使用更上了一個臺階了,在不一樣的狀況下能夠選擇使用模態對話框和非模態對話框了。雞啄米歡迎你們留言討論。
***************************************************************************************************************************************************************************
前面講了模態對話框和非模態對話框,本節開始雞啄米講一種特殊的對話框--屬性頁對話框。另外,本套教程所講大部分對VC++各個版本都可適用或者稍做修改便可,但考慮到終究仍是基於VS2010版本的,因此將《VC++/MFC編程入門》改成《VS2010/MFC編程入門》。
屬性頁對話框的分類
屬性頁對話框想必你們並不陌生,XP系統中桌面右鍵點屬性,彈出的就是屬性頁對話框,它經過標籤切換各個頁面。另外,咱們在建立MFC工程時使用的嚮導對話框也屬於屬性頁對話框,它經過點擊「Next」等按鈕來切換頁面。
屬性頁對話框就是包含通常屬性頁對話框和嚮導對話框兩類。它將多個對話框集成於一身,經過標籤或按鈕來切換頁面。
屬性頁對話框相關類
咱們使用屬性頁對話框時,用到的類主要有兩個:CPropertyPage類和CPropertySheet類。
1.CPropertyPage類
CPropertyPage類繼承自CDialog類,它被用於處理某單個的屬性頁,因此要爲每一個屬性頁都建立一個繼承自CPropertyPage的子類。你們能夠在VS2010的MSDN中查找CPropertyPage類以及它的成員的詳細說明。下面雞啄米就爲你們講解MSDN中列出的CPropertyPage類的部分主要成員函數。
(1)構造函數
這裏講三個CProperty類的構造函數,函數原型爲:
CPropertyPage( );
explicit CPropertyPage(
UINT nIDTemplate,
UINT nIDCaption = 0,
DWORD dwSize = sizeof(PROPSHEETPAGE)
);
explicit CPropertyPage(
LPCTSTR lpszTemplateName,
UINT nIDCaption = 0,
DWORD dwSize = sizeof(PROPSHEETPAGE)
);
第一個是沒有任何參數的構造函數。
第二個構造函數中,參數nIDTemplate是屬性頁的對話框資源ID,參數nIDCaption是屬性頁對話框選項卡的標題所用字符串資源的ID,若設爲0,則選項卡標題就使用該屬性頁的對話框資源的標題。
第三個構造函數中,參數lpszTemplateName爲屬性頁的對話框資源的名稱字符串,不能爲NULL。參數nIDCaption同上。
(2)CancelToClose()函數
在模態屬性頁對話框的屬性頁進行了某不可恢復的操做後,使用CancelToClose()函數將「OK」按鈕改成「Close」按鈕,並禁用「Cancel」按鈕。函數原型爲:
void CancelToClose( );
(3)SetModified()函數
調用此函數可激活或禁用「Apply」按鈕,函數原型爲:
void SetModified(BOOL bChanged = TRUE);
(4)可重載函數
CPropertyPage類提供了一些消息處理函數,來響應屬性頁對話框的各類消息。咱們重載這些消息處理函數,就能夠自定義對屬性頁對話框操做的處理。可重載的消息處理函數包括:
OnApply:處理屬性頁的「Apply」按鈕被單擊的消息
OnCancel:處理屬性頁的「Cancel」按鈕被單擊的消息
OnKillActive:處理屬性頁當前活動狀態被切換的消息,經常使用於數據驗證
OnOK:處理屬性頁的「OK」按鈕、「Apply」按鈕或者「Close」按鈕被單擊的消息
OnQueryCancel:處理屬性頁的「Cancel」按鈕被單擊前發出的消息
OnReset:處理屬性頁的「Reset」按鈕被單擊的消息
OnSetActive:處理屬性頁被切換爲當前活動頁的消息
OnWizardBack:處理屬性頁的「Back」按鈕被單擊的消息,僅在嚮導對話框中有效
OnWizardFinish:處理屬性頁的「Finish」按鈕被單擊的消息,僅在嚮導對話框中有效
OnWizardNext:處理屬性頁的「Next」按鈕被單擊的消息,僅在嚮導對話框中有效
2.CPropertySheet類
CPropertySheet類繼承自CWnd類,它是屬性表類,負責加載、打開或刪除屬性頁,並能夠在屬性頁對話框中切換屬性頁。它跟對話框相似,也有模態和非模態兩種。下面雞啄米就講解CPropertySheet類的部分紅員函數。
(1)構造函數
這裏依然列出CPropertySheet類的三個構造函數:
CPropertySheet( );
explicit CPropertySheet(
UINT nIDCaption,
CWnd* pParentWnd = NULL,
UINT iSelectPage = 0
);
explicit CPropertySheet(
LPCTSTR pszCaption,
CWnd* pParentWnd = NULL,
UINT iSelectPage = 0
);
參數nIDCaption:標題的字符串資源的ID。
參數pParentWnd:屬性頁對話框的父窗口,若設爲NULL,則父窗口爲應用程序的主窗口。
參數iSelectPage:初始狀態時,活動屬性頁的索引,默認爲第一個添加到屬性表的屬性頁。
參數pszCaption:標題字符串。
(2)GetActiveIndex()函數
獲取當前活動屬性頁的索引。函數原型爲:
int GetActiveIndex( ) const;
返回值:當前活動屬性頁的索引。
(3)GetActivePage()函數
獲取當前活動屬性頁對象。函數原型爲:
CPropertyPage* GetActivePage( ) const;
返回值:當前活動屬性頁對象的指針。
(4)GetPage()函數
獲取某個屬性頁對象。函數原型爲:
CPropertyPage* GetPage(int nPage) const;
參數nPage:目標屬性頁的索引。
返回值:目標屬性頁對象的指針。
(5)GetPageCount()函數
獲取屬性頁的數量。函數原型爲:
int GetPageCount( ) const;
返回值:屬性頁的數量。
(6)GetPageIndex()函數
獲取某屬性頁在屬性頁對話框中的索引。函數原型爲:
int GetPageIndex(CPropertyPage* pPage);
參數pPage:要獲取索引的屬性頁對象的指針。
返回值:屬性頁對象在屬性頁對話框中的索引。
(7)SetActivePage()函數
設置某個屬性頁爲活動屬性頁。函數原型爲:
BOOL SetActivePage(
int nPage
);
BOOL SetActivePage(
CPropertyPage* pPage
);
參數nPage:要設置爲活動屬性頁的索引。
參數pPage:要設置爲活動屬性頁的對象指針。
(8)SetWizardButtons()函數
在嚮導對話框上啓用或禁用Back、Next或Finish按鈕,應在調用DoModal以前調用此函數。函數原型爲:
void SetWizardButtons(
DWORD dwFlags
);
參數dwFlags:設置嚮導按鈕的外觀和功能屬性。能夠是如下值的組合:
PSWIZB_BACK 啓用「Back」按鈕,若是不包含此值則禁用「Back」按鈕。
PSWIZB_NEXT 啓用「Next」按鈕,若是不包含此值則禁用「Next」按鈕。
PSWIZB_FINISH 啓用「Finish」按鈕。
PSWIZB_DISABLEDFINISH 顯示禁用的「Finish」按鈕。
(9)SetWizardMode()函數
設置屬性頁對話框爲嚮導對話框模式,應在調用DoModal以前調用此函數。函數原型爲:
void SetWizardMode( );
(10)SetTitle()函數
設置屬性對話框的標題。函數原型爲:
void SetTitle(
LPCTSTR lpszText,
UINT nStyle = 0
);
參數lpszText:標題字符串。
參數nStyle:指定屬性表標題的風格。應當爲0或PSH_PROPTITLE。若是設爲PSH_PROPTITLE,則單詞「Properties」會出如今指定標題以後。例如,SetTitle("Simple",PSH_PROPTITLE)這種調用會使得屬性表標題爲「Simple Properties」。
(11)AddPage()函數
爲屬性對話框添加新的屬性頁。函數原型爲:
void AddPage(
CPropertyPage *pPage
);
參數pPage:要添加的新的屬性頁的對象指針。
(12)PressButton()函數
模擬按下某指定的按鈕。函數原型爲:
void PressButton(
int nButton
);
參數nButton:要模擬按下的按鈕,它能夠是下列值之一:
PSBTN_BACK 選擇「Back」按鈕。
PSBTN_NEXT 選擇「Next」按鈕。
PSBTN_FINISH 選擇「Finish」按鈕。
PSBTN_OK 選擇「OK」按鈕。
PSBTN_APPLYNOW 選擇「Apply」按鈕。
PSBTN_CANCEL 選擇「Cancel」按鈕。
PSBTN_HELP 選擇「幫助」按鈕。
(13)RemovePage()函數
刪除某屬性頁。函數原型爲:
void RemovePage(
CPropertyPage *pPage
);
void RemovePage(
int nPage
);
參數pPage:要刪除的屬性頁的對象指針。
參數nPage:要刪除的屬性頁的索引。
屬性對話框和相關的兩個類雞啄米就先介紹到這,主要是爲後面使用屬性頁對話框作準備。有問題能夠到雞啄米博客交流。謝謝。
*************************************************************************************************************************************************************************
上一講雞啄米講了屬性頁對話框和相關的兩個類CPropertyPage類和CPropertySheet類,對使用屬性頁對話框作準備。本節將爲你們演示如何建立嚮導對話框。
仍然之前面的「加法計算器」的例子爲基礎,在其中加入嚮導對話框,咱們能夠用它來講明加法計算器的使用方法,一步一步引導用戶操做,這也是比較常見的用法。
加法計算器使用時大概能夠分爲三步:輸入被加數、輸入加數、點「計算」按鈕。
雞啄米就詳細說明嚮導對話框的建立步驟:
1.建立屬性頁對話框資源
根據建立對話框模板和修改對話框屬性中所講方法,在「Resource View」的Dialog」節點上點右鍵,而後在右鍵菜單中選擇「Insert Dialog」建立第一個對話框模板,對話框的ID屬性設置爲IDD_SUMMAND_PAGE,Caption屬性改成「被加數頁」,Style屬性在下拉列表中選擇「Child」,Border屬性在下拉列表中選擇「Thin」。
刪除「OK」和「Cancel」按鈕,再按照爲對話框添加控件中所講方法,添加一個靜態文本框,並修改靜態文本框的Caption屬性爲「請先輸入double型被加數」。
按照上述步驟,繼續添加第二個和第三個對話框資源。第二個對話框模板的ID設爲IDD_ADDEND_PAGE,Caption屬性改成「加數頁」,也添加一個靜態文本框,Caption設爲「請繼續輸入double型加數」,其餘屬性同第一個對話框。第三個對話框模板的ID設爲IDD_ADD_PAGE,Caption屬性改成「計算頁」,添加靜態文本框的Caption屬性改成「最後請按下「計算」按鈕」,其餘屬性也第一個對話框同樣。
2.建立屬性頁類
按照建立對話框類和添加控件變量中的方法,在第一個對話框模板上點右鍵,在右鍵菜單中選擇「Add Class」,彈出類嚮導對話框,在「Class name」編輯框中輸入類名「CSummandPage」,與以前不一樣的是,由於屬性頁類都應繼承於CPropertyPage類,因此要修改下面「Base class」的選項,在下拉列表中選擇「CPropertyPage」。
由於是第一個屬性頁,因此它應該有一個「下一步」按鈕,在哪裏添加呢?上一講CPropertyPage類的可重載函數中提到,OnSetActive函數用於處理屬性頁被切換爲當前活動頁的消息,因此咱們能夠在OnSetActive函數中進行相關設置。
那怎樣重載OnSetActive函數呢?咱們能夠在「Class View」中找到「CSummandPage」節點,點右鍵彈出右鍵菜單,選擇「Properties」,而後VS2010右側面板上會顯示對話框的屬性列表,屬性列表的工具欄上有個tip信息爲「Overrides」的按鈕,按下它,下方列表中就列出了重載函數,找到「OnSetActive」,點其右側空白列表項出現向下箭頭,再點箭頭就在下面出現了「<Add>OnSetActive」的選項,選擇它就會自動在CSummandPage類中添加函數OnSetActive。
咱們只需在OnSetActive函數體中添加相關代碼就能夠實現添加「下一步」按鈕的效果了。新的函數體以下:
- BOOL CSummandPage::OnSetActive()
- {
- // TODO: Add your specialized code here and/or call the base class
- // 得到父窗口,即屬性表CPropertySheet類
- CPropertySheet* psheet = (CPropertySheet*) GetParent();
- // 設置屬性表只有「下一步」按鈕
- psheet->SetWizardButtons(PSWIZB_NEXT);
- return CPropertyPage::OnSetActive();
- }
爲第二個和第三個對話框也分別添加屬性頁類CAddendPage和CAddPage。但第二個對話框的屬性頁不須要重載OnSetActive函數。第三個對話框是最後一個對話框,因此不須要「下一步」按鈕,而應該換成「完成」按鈕,因此也須要重載OnSetActive函數設置「完成」按鈕。重載後的OnSetActive以下:
- BOOL CAddPage::OnSetActive()
- {
- // TODO: Add your specialized code here and/or call the base class
- // 得到父窗口,即屬性表CPropertySheet類
- CPropertySheet* psheet = (CPropertySheet*) GetParent();
- //設置屬性表只有「完成」按鈕
- psheet->SetFinishText(_T("完成"));
- return CPropertyPage::OnSetActive();
- }
上面的代碼段中,字符串「完成」前加了個_T,這是由於本工程建立的時候用的默認的Unicode字符集,而若是「完成」前不加_T就是ASCII字符串。_T其實是一個宏,工程的字符集選擇爲Unicode時字符串就轉爲Unicode字符串,選擇爲Muli-Byte時就轉爲ASCII字符串。咱們能夠在Solution Explorer的Addition根節點上點右鍵,在右鍵菜單上選擇「Properties」,彈出工程的屬性對話框,Configuration Properties->General右側列表中的Character Set就顯示選擇的字符集。
那點了第三個屬性頁上的「完成」按鈕咱們想進行某些處理的話,就重載OnWizardFinish函數,方法同OnSetActive函數。重載後的OnWizardFinish函數以下:
- BOOL CAddPage::OnWizardFinish()
- {
- // TODO: Add your specialized code here and/or call the base class
- // 提示嚮導完成
- MessageBox(_T("使用說明嚮導已閱讀完!"));
- return CPropertyPage::OnWizardFinish();
- }
3.建立屬性表類
屬性頁資源和屬性頁類建立完之後,還不能生成嚮導對話框,咱們還須要一個屬性表類,來容納這些屬性頁。
在Solution Explorer視圖中的根節點「Addition」上點右鍵,在右鍵菜單中選擇Add->Class,彈出「Add Class」對話框,而後在中間區域中選擇「MFC Class」,點「Add」按鈕,彈出另外一個類嚮導對話框,設置Class name爲CAddSheet,Base class選擇「CPropertySheet」,點「Finish」按鈕,這樣就屬性表類就建好了。
接下來,在新生成的AddSheet.h中包含三個屬性頁類的頭文件:
#include "SummandPage.h"
#include "AddendPage.h"
#include "AddPage.h"
以後在AddSheet.h中添加private變量:
CSummandPage m_summandPage;C
CAddendPage m_addendPage;
CAddPage m_addPage;
而後在AddSheet.cpp文件中修改CAddSheet的兩個構造函數爲:
- CAddSheet::CAddSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
- :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
- {
- // 添加三個屬性頁到屬性表
- AddPage(&m_summandPage);
- AddPage(&m_addendPage);
- AddPage(&m_addPage);
- }
- CAddSheet::CAddSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
- :CPropertySheet(pszCaption, pParentWnd, iSelectPage)
- {
- // 添加三個屬性頁到屬性表
- AddPage(&m_summandPage);
- AddPage(&m_addendPage);
- AddPage(&m_addPage);
- }
4.顯示嚮導對話框
咱們在加法計算器對話框上添加一個按鈕,點擊它就打開向導對話框。此按鈕的ID設爲IDC_INSTRUCT_BUTTON,Caption屬性設爲「使用說明」。
按照爲控件添加消息處理函數中所講方法,爲IDC_INSTRUCT_BUTTON按鈕在CAdditionDlg類中添加點擊消息的處理函數OnBnClickedInstructButton。而後在AdditionDlg.cpp文件中包含CAddSheet的頭文件:#include "AddSheet.h"。最後修改OnBnClickedInstructButton函數以下:
- void CAdditionDlg::OnBnClickedInstructButton()
- {
- // TODO: Add your control notification handler code here
- // 建立屬性表對象
- CAddSheet sheet(_T(""));
- // 設置屬性對話框爲嚮導對話框
- sheet.SetWizardMode();
- // 打開模態嚮導對話框
- sheet.DoModal();
- }
到此,嚮導對話框就完整的建立完成了,並能夠在加法計算器對話框上點「使用說明」按鈕顯示出來。咱們來看看效果吧:
上圖只是被加數頁的效果,點其上「下一步」按鈕就能夠繼續顯示後面的兩個頁面。
是否是嚮導對話框沒有之前想象的那般複雜了?你們能夠發揮想象,進行更復雜的修改,實現更完善的功能。依然歡迎朋友們到雞啄米博客來交流學習。
**********************************************************************************************************************************************************************************
屬性頁對話框包括嚮導對話框和通常屬性頁對話框兩類,上一節雞啄米講了如何建立並顯示嚮導對話框,本節將繼續介紹通常屬性頁對話框的建立和顯示。
實際上,通常屬性頁對話框的建立和顯示過程和嚮導對話框是很相似的。雞啄米將上一節中的嚮導對話框進行少許修改,使其成爲通常屬性頁對話框。
通常屬性頁對話框的建立步驟:
1.建立屬性頁對話框資源
屬性頁對話框資源的建立方法同向導對話框是同樣的,上一講中的對話框資源不需進行任何修改。
2.建立屬性頁類
屬性頁類的建立和嚮導對話框的屬性頁類也基本同樣,只是通常屬性頁對話框中不須要「下一步」和「完成」等按鈕,因此上一講中屬性頁類的OnSetActive和OnWizardFinish等重載函數能夠去掉。即CSummandPage類中的OnSetActive函數、CAddPage類中的OnSetActive函數和OnWizardFinish函數能夠刪除或註釋掉。其餘部分不需做任何修改。
3.建立屬性表類
建立屬性表類的過程同向導對話框屬性表類也是同樣的,因此上一講中的CAddSheet類不需修改。
4.顯示通常屬性頁對話框
上一講嚮導對話框的顯示是在OnBnClickedInstructButton函數中實現的,其中語句sheet.SetWizardMode();旨在設置屬性表爲嚮導對話框模式,因此顯示通常屬性頁對話框時不需調用SetWizardMode成員函數。另外,咱們能夠將屬性頁對話框的標題設爲「使用說明」,在構造屬性表對象時將此字符串做爲構造函數的參數傳入。OnBnClickedInstructButton函數修改以下:
- void CAdditionDlg::OnBnClickedInstructButton()
- {
- // TODO: Add your control notification handler code here
- // 建立屬性表對象
- CAddSheet sheet(_T("使用說明"));
- // 打開模態通常屬性頁對話框
- sheet.DoModal();
- }
這樣通常屬性頁對話框的建立和顯示就講完了,咱們運行下程序,在結果對話框上點「使用說明」按鈕看看效果吧:
再總結下,通常屬性頁對話框和嚮導對話框的建立和顯示的不一樣包括,是否須要OnSetActive和OnWizardFinish等重載函數,是否須要調用屬性表類的SetWizardMode函數設置爲嚮導對話框模式。