




已閱讀5頁,還剩45頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第五章 對話框?qū)υ捒蚴且环N用戶界面,它的主要功能是輸出信息和接收用戶的輸入。對話框與控件是密不可分的,在每個(gè)對話框內(nèi)一般都有一些控件,對話框依靠這些控件與用戶進(jìn)行交互。一個(gè)典型的對話框例子是選擇了File-Open命令后彈出的文件對話框。5.1對話框和控件的基本概念5.1.1對話框的基本概念對話框(Dialog)實(shí)際上是一個(gè)窗口。在MFC中,對話框的功能被封裝在了CDialog類中,CDialog類是CWnd類的派生類。對話框分為模態(tài)對話框和非模態(tài)對話框兩種。大部分讀者都會(huì)有這樣的經(jīng)歷,當(dāng)你通過File-Open命令打開一個(gè)文件對話框后,再用鼠標(biāo)去選擇菜單將只會(huì)發(fā)出嘟嘟聲,這是因?yàn)槲募υ捒蚴且粋€(gè)模態(tài)對話框。模態(tài)對話框壟斷了用戶的輸入,當(dāng)一個(gè)模態(tài)對話框打開時(shí),用戶只能與該對話框進(jìn)行交互,而其它用戶界面對象收不到輸入信息。我們平時(shí)所遇到的大部分對話框都是模態(tài)對話框。非模態(tài)對話框的典型例子是Windows95提供的寫字板程序中的搜索對話框,搜索對話框不壟斷用戶的輸入,打開搜索對話框后,仍可與其它用戶界面對象進(jìn)行交互,用戶可以一邊搜索,一邊修改文章,這樣就大大方便了使用。本節(jié)主要介紹模態(tài)對話框,在第四節(jié)將介紹非模態(tài)對話框。從MFC編程的角度來看,一個(gè)對話框由兩部分組成:1.對話框模板資源。對話框模板用于指定對話框的控件及其分布,Windows根據(jù)對話框模板來創(chuàng)建并顯示對話框。2.對話框類。對話框類用來實(shí)現(xiàn)對話框的功能,由于對話框行使的功能各不相同,因此一般需要從CDialog類派生一個(gè)新類,以完成特定的功能。5.1.2控件的基本概念圖5.1對話框中的控件控件(Control)是獨(dú)立的小部件,在對話框與用戶的交互過程中,控件擔(dān)任著主要角色??丶姆N類較多,圖5.1顯示了對話框中的一些基本的控件。MFC的控件類封裝了控件的功能,表5.1介紹了一些常用的控件及其對應(yīng)的控件類。表5.1控件功能對應(yīng)控件類靜態(tài)正文(Static Text)顯示正文,一般不能接受輸入信息。CStatic圖片(Picture)顯式位圖、圖標(biāo)、方框和圖元文件,一般不能接受輸入信息。CStatic編輯框(Edit Box)輸入并編輯正文,支持單行和多行編輯。CEdit命令按鈕(Pushbutton)響應(yīng)用戶的輸入,觸發(fā)相應(yīng)的事件。CButton檢查框(Check Box)用作選擇標(biāo)記,可以有選中、不選中和不確定三種狀態(tài)。CButton單選按鈕(Radio Button)用來從兩個(gè)或多個(gè)選項(xiàng)中選中一項(xiàng)。CButton組框(Group Box)顯示正文和方框,主要用來將相關(guān)的一些控件聚成一組。CButton列表框(List Box)顯示一個(gè)列表,用戶可以從該列表中選擇一項(xiàng)或多項(xiàng)。CListBox組合框(Combo Box)是一個(gè)編輯框和一個(gè)列表框的組合。分為簡易式、下拉式和下拉列表式。CComboBox滾動(dòng)條(Scroll Bar)主要用來從一個(gè)預(yù)定義范圍值中迅速而有效地選取一個(gè)整數(shù)值。CScrollBar控件實(shí)際上都是窗口,所有的控件類都是CWnd類的派生類??丶ǔJ亲鳛閷υ捒虻淖哟翱诙鴦?chuàng)建的,控件也可以出現(xiàn)在視窗口,工具條和狀態(tài)條中。對話框的設(shè)計(jì)包括對話框模板的設(shè)計(jì)和對話框類的設(shè)計(jì)兩個(gè)主要方面。1.與對話框有關(guān)的消息主要包括WM_INITDIALOG消息和控件通知消息。在對話框創(chuàng)建時(shí),會(huì)收到WM_INITDIALOG消息,對話框?qū)υ撓⒌奶幚砗瘮?shù)是OnInitDialog 。2.OnInitDialog的主要用處是初始化對話框。對話框的控件會(huì)向?qū)υ捒虬l(fā)送控件通知消息,以表明控件的狀態(tài)發(fā)生了變化。5.2對話框模板的設(shè)計(jì)利用Developer Studio提供的可視化設(shè)計(jì)工具,用戶可以方便地設(shè)計(jì)對話框模板。請讀者按前面章節(jié)介紹的方法利用AppWizard建立一個(gè)名為Register的MFC應(yīng)用程序,并在進(jìn)入MFC AppWizard對話框后按下面幾步操作: 1. 在第1步中選中Single document以建立一個(gè)單文檔應(yīng)用程序。 2. 在第4步中使Docking toolbar項(xiàng)不選中,這樣AppWizard就不會(huì)創(chuàng)建工具條。 3. 在第6步中先選擇CRegisterView,然后在Base class欄中選擇CEditView,這樣CRegisterView將是CEditView的繼承類,從而使視圖具有了編輯功能。編譯并運(yùn)行Register,讀者會(huì)發(fā)現(xiàn)Register居然是個(gè)編輯器,它可以打開、編輯和保存文本文件。當(dāng)然,Register的目的不僅僅是個(gè)編輯器。假設(shè)要對某一地區(qū)的就業(yè)情況進(jìn)行調(diào)查,我們希望Register程序能夠登錄就業(yè)情況數(shù)據(jù)并將數(shù)據(jù)存儲(chǔ)起來。要登錄數(shù)據(jù),用對話框是再合適不過了。一個(gè)典型的就業(yè)情況登錄對話框如圖5.1所示,本節(jié)的任務(wù)就是設(shè)計(jì)如圖5.1的中文對話框模板。切換至資源視圖,選擇Insert-Resource命令,并在Insert Resource對話框中雙擊Dialog項(xiàng)。完成后在資源視圖中會(huì)出現(xiàn)一個(gè)名為IDD_DIALOG1的新的對話框模板資源。雙擊IDD_DIALOG1,則會(huì)打開該對話框模板的編輯窗口,如圖5.2所示。缺省的對話框模板有OK和Cancel兩個(gè)按鈕,在窗口的旁邊有一個(gè)控件面板,在控件面板上用鼠標(biāo)選擇一個(gè)控件,然后在對話框中點(diǎn)擊,則相應(yīng)的控件就被放置到了對話框模板中。圖5.3顯示了控件面板上的按鈕所代表的控件。讀者不用記憶圖5.3的內(nèi)容,如果不能確定控件的類型,可將鼠標(biāo)在某個(gè)控件按鈕上停留片刻,則會(huì)顯示一個(gè)工具提示,指出該按鈕所代表控件的名稱。圖5.2 缺省的對話框模板圖5.3 控件面板提示:若讀者看不到控件面板,請?jiān)贒eveloper Studio的工具條的空白處單擊鼠標(biāo)右鍵,并在隨之彈出的菜單中選中Controls。 讀者可以在對話框模板中隨意加幾個(gè)控件試試看。當(dāng)用鼠標(biāo)選擇對話框或控件時(shí),會(huì)出現(xiàn)一個(gè)圍繞它的虛框,拖動(dòng)虛框的邊界可以改變對話框或控件的大小,在Developer Studio的狀態(tài)條中會(huì)顯示出所選對象的坐標(biāo)和尺寸。控件可以被拖動(dòng),也可以按箭頭鍵來移動(dòng)選中的控件。在拖動(dòng)控件時(shí)若按住Ctrl鍵,則控件會(huì)被復(fù)制。用戶可以一次選擇多個(gè)控件,選擇的方法有兩個(gè):1。 在對話框的空白處拖動(dòng)鼠標(biāo),則拖動(dòng)出來的虛線框內(nèi)的控件將被選中。2。在選擇控件時(shí)按住Ctrl鍵,則可以多重選擇。選中控件或?qū)υ捒蚝蟀椿剀囨I,則會(huì)彈出一個(gè)屬性對話框,屬性對話框用來設(shè)置控件或?qū)υ捒虻母鞣N屬性。屬性對話框是標(biāo)簽式對話框,第一頁是常規(guī)屬性(General)。一個(gè)典型的控件屬性對話框如圖5.4所示。如果對屬性對話框中的選項(xiàng)的意思不明白,可以按F1鍵獲得幫助。圖5.4 控件屬性對話框在控件屬性對話框的常規(guī)屬性中,有一些控件共同的屬性: ID屬性。用于指定控件的標(biāo)識(shí)符,Windows依靠ID來區(qū)分不同的控件。 Caption(標(biāo)題)屬性。靜態(tài)正文、組框、按鈕、檢查框、單選按鈕等控件可以顯示標(biāo)題,用來對控件進(jìn)行文字說明??丶?biāo)題中的字符使緊跟其后的字符有下劃線,按Alt+下劃線將啟動(dòng)該控件。若控件是一個(gè)單選按鈕,則Alt+下劃線字符將選擇該按鈕;若是檢查框,則相當(dāng)于對該檢查框按空格鍵;若是按鈕,則將激活按鈕命令;若控件是一個(gè)靜態(tài)正文,則將激活按tab順序緊隨其后的下一個(gè)控件。 Visible屬性。用來指定控件是否是可見的。 Disable屬性。使控件允許或禁止,一個(gè)禁止的控件呈灰色顯示,不能接收任何輸入。 Tabstop屬性。用戶可以按Tab鍵移動(dòng)到具有Tabstop屬性的控件上。Tab移動(dòng)的順序可以由用戶指定。按Ctrl+D則Tab順序會(huì)顯示出來,如圖5.5,用戶可以用鼠標(biāo)來重新指定Tab順序。缺省的Tab順序是控件的創(chuàng)建次序。 Group屬性。用來指定一組控件,用戶可以用箭頭鍵在該組控件內(nèi)移動(dòng)。在同一組內(nèi)的單選按鈕具有互斥的特性,即在這些單選按鈕中只能有一個(gè)是選中的。如果一個(gè)控件具有Group屬性,則這個(gè)控件以及按Tab順序緊隨其后的所有控件都屬于一組的,直到遇到另一個(gè)有Group屬性的控件為止。 現(xiàn)在就開始進(jìn)行對話框模板的設(shè)計(jì)。首先,用鼠標(biāo)選中對話框,按回車鍵,在彈出的屬性對話框中將ID改為IDD_REGISTER并指定對話框的標(biāo)題為“登錄數(shù)據(jù)”。需要注意的是,由于要在對話框中顯示漢字,因此必須設(shè)定正確的語種和字體。請讀者在工作區(qū)資源視圖的Dialog類型中單擊鼠標(biāo)選中IDD_REGISTER項(xiàng),然后按Alt+Enter鍵,并在彈出的屬性對話框中的Language欄中選擇Chinese(P.R.C.)。接著,打開模板的屬性對話框,單擊Font.按鈕,并選擇“宋體”。接著,請將對話框模板上的所有控件刪除,刪除的辦法是選擇控件后按Del鍵。為了容納所有需要的控件,需將對話框的尺寸擴(kuò)大到280180。然后,請讀者按圖5.1和表5.2來設(shè)計(jì)對話框模板。提示:對話框的尺寸單位不是象素,而是與字體的大小有關(guān)。X方向上一個(gè)單位等于字符平均寬度的1/4,Y方向上一個(gè)單位等于字符平均高度的1/8。這樣,隨著字體的改變,對話框單位也會(huì)改變,對話框本身的總體比例保持不變。表5.2控件類型ID標(biāo)題(Caption)其它屬性組框(個(gè)人情況)缺省個(gè)人情況缺省組框(單位情況)缺省單位情況缺省靜態(tài)正文(姓名)缺省姓名缺省編輯框(姓名)IDC_NAME缺省檢查框(婚否)IDC_MARRIED婚否缺省靜態(tài)正文(年齡)缺省年齡缺省編輯框(年齡)IDC_AGE缺省組框(性別)缺省性別缺省單選按鈕(男)IDC_SEX男Group、Tabstop單選按鈕(女)缺省女缺省組框(就業(yè)狀況)缺省就業(yè)狀況缺省單選按鈕(在職)IDC_WORK在職Group、Tabstop單選按鈕(下崗)IDC_WORK1下崗缺省靜態(tài)正文(工作單位)缺省工作單位缺省編輯框(工作單位)IDC_UNIT缺省靜態(tài)正文(單位性質(zhì))缺省單位性質(zhì)缺省組合框(單位性質(zhì))IDC_KINDDrop List、不排序(不選中Sort風(fēng)格)、初始化列表項(xiàng)(見下文說明)靜態(tài)正文(工資收入)缺省工資收入缺省列表框(工資收入)IDC_INCOME不排序(不選中Sort)按鈕(確定)IDOK確定(&Y)缺省按鈕(取消)IDCANCEL取消(&C)缺省請注意組合框IDC_KIND的Drop List屬性,Drop List屬性是在屬性對話框的Styles(風(fēng)格)頁的Type欄中選擇的,這使得IDC_KIND成為一個(gè)下拉列表式組合框。組合框有簡易式(Simple)、下拉式(Dropdown)和下拉列表式(Drop List)三種。簡易式組合框包含一個(gè)編輯框和一個(gè)總是顯示的列表框。下拉式組合框同簡易式組合框的區(qū)別在于僅當(dāng)單擊下滾箭頭時(shí)才出現(xiàn)列表框。下拉列表式組合框也有一個(gè)下拉的列表框,但它的編輯框是只讀的,不能輸入字符。組合框IDC_KIND不要自動(dòng)排序,因此需在Styles頁中使Sort項(xiàng)不被選中。組合框的列表項(xiàng)可以在設(shè)計(jì)模板時(shí)初始化,而列表框的初始化只能在程序中進(jìn)行。請讀者在組合框IDC_KIND的屬性對話框的General頁中輸入以下幾個(gè)列表項(xiàng),以作為單位性質(zhì)的選項(xiàng)。輸入時(shí)要注意,換行時(shí)不要按回車鍵,而應(yīng)按Ctrl+回車鍵。國有企事業(yè)集體企業(yè)私有企業(yè)中外合資外商獨(dú)資組合框控件的一個(gè)與眾不同之處是它有兩個(gè)尺寸,一個(gè)是下拉前的尺寸,一個(gè)是下拉后的尺寸。當(dāng)用鼠標(biāo)點(diǎn)擊組合框上的箭頭后,可設(shè)定下拉后的尺寸??丶詈枚挤旁趯υ捒蚰0宓乃{(lán)色虛框內(nèi),控件之間的距離不要太近,否則有可能造成不正確的顯示。安置好控件之后,下一步的任務(wù)是指定Tab順序。按Ctrl+D鍵后,會(huì)顯示當(dāng)前的Tab順序,通過用鼠標(biāo)點(diǎn)擊控件可以設(shè)定新的Tab順序,如果想放棄本次修改,在對話框的空白處點(diǎn)擊一下即可。請讀者按圖5.5安排Tab順序。圖5.5 對話框的Tab順序最后,需要測試一下對話框。按Ctrl+T,則會(huì)彈出一個(gè)當(dāng)前模板的測試對話框,這個(gè)對話框的外觀和基本行為與程序中將要彈出的對話框一樣。這樣,讀者不用編譯運(yùn)行程序,通過測試對話框就可以評估對話框是否合乎要求。如果發(fā)現(xiàn)了錯(cuò)誤或不滿意的地方,可按ESC鍵退出測試對話框并重新修改對話框模板。至此,對話框模板的設(shè)計(jì)就完成了。5.3 對話框類的設(shè)計(jì)完成對話框模板的設(shè)計(jì)后,就需要設(shè)計(jì)一個(gè)對話框類以實(shí)現(xiàn)對話框的功能。設(shè)計(jì)對話框類主要包括下面幾步:創(chuàng)建對話框類。該類應(yīng)從CDialog類派生。為對話框類加入與控件相對應(yīng)的成員變量。為對話框進(jìn)行初始化工作。增加對控件通知消息的處理5.3.1對話框類的創(chuàng)建利用ClassWizard,程序員可以十分方便的創(chuàng)建MFC窗口類的派生類,對話框類也不例外。請讀者按以下幾步操作:打開IDD_REGISTER對話框模板,然后按Ctrl+W進(jìn)入ClassWizard。進(jìn)入ClassWizard后,ClassWizard發(fā)現(xiàn)IDD_REGISTER是一個(gè)新的對話框模板,于是它會(huì)詢問是否要為IDD_REGISTER創(chuàng)建一個(gè)對話框類。按OK鍵確認(rèn)。如圖5.6在Create New Class對話框中,在Name欄中輸入CRegisterDialog,在Base class欄中選擇CDialog,在Dialog ID欄中選擇IDD_REGISTER。按Create按鈕后,對話框類CRegisterDialog即被創(chuàng)建。圖5.6 Create New Class對話框ClassWizard自動(dòng)使類CRegesterDialog與IDD_REGISTER模板聯(lián)系起來。提示:只要想創(chuàng)建的類是某一MFC窗口類的派生類,一般都可以利用ClassWizard來自動(dòng)完成創(chuàng)建。創(chuàng)建的一般方法是:打開ClassWizard,選擇Add Class-New,然后在Create New Class對話框中輸入新類的類名,選擇其MFC基類,如果是對話框類,則還要選擇對話框的ID。5.3.2為對話框類加入成員變量 對話框的主要功能是輸出和輸入數(shù)據(jù),例子中的登錄數(shù)據(jù)對話框的任務(wù)就是輸入數(shù)據(jù)。對話框需要有一組成員變量來存儲(chǔ)數(shù)據(jù)。在對話框中,控件用來表示或輸入數(shù)據(jù),因此,存儲(chǔ)數(shù)據(jù)的成員變量應(yīng)該與控件相對應(yīng)。與控件對應(yīng)的成員變量即可以是一個(gè)數(shù)據(jù),也可以是一個(gè)控件對象,這將由具體需要來確定。例如,可以為一個(gè)編輯框控件指定一個(gè)數(shù)據(jù)變量,這樣就可以很方便地取得或設(shè)置編輯框控件所代表的數(shù)據(jù),如果想對編輯框控件進(jìn)行控制,則應(yīng)該為編輯框指定一個(gè)CEdit對象,通過CEdit對象,程序員可以控制控件的行為。需要指出的是,不同類的控件對應(yīng)的數(shù)據(jù)變量的類型往往是不一樣的,而且一個(gè)控件對應(yīng)的數(shù)據(jù)變量的類型也可能有多種。表5.3說明了控件的數(shù)據(jù)變量的類型。表5.3控件數(shù)據(jù)變量的類型編輯框CString, int, UINT, long, DWORD, float, double, short, BOOL, COleDateTime, COleCurrency普通檢查框BOOL(真表示被選中,假表示未選中)三態(tài)檢查框int(0表示未選中,1表示選中,2表示不確定狀態(tài))單選按鈕(組中的第一個(gè)按鈕)int(0表示選擇了組中第一個(gè)單選按鈕,1表示選擇了第二個(gè).,-1表示沒有一個(gè)被選中)不排序的列表框CString(為空則表示沒有一個(gè)列表項(xiàng)被選中), int(0表示選擇了第一項(xiàng),1表示選了第二項(xiàng),-1表示沒有一項(xiàng)被選中)下拉式組合框CString, int(含義同上)其它列表框和組合框CString(含義同上)利用ClassWizard可以很方便地為對話框類CRegisterDialog加入成員變量。請讀者按下列步驟操作。按Ctrl+W進(jìn)入ClassWizard。選擇ClassWizard上部的Member Variables標(biāo)簽,然后在Class name欄中選擇CRegisterDialog。這時(shí),在下面的變量列表中會(huì)出現(xiàn)對話框控件的ID,如圖5.7所示。圖5.7 ClassWizard對話框雙擊列表中的ID_AGE會(huì)彈出Add Member Variable對話框,如圖5.8所示。在Member variable name欄中輸入m_nAge,在Category欄中選擇Value,在Variable type欄中選擇UINT。按OK按鈕后,數(shù)據(jù)變量m_nAge就會(huì)被加入到變量列表中。仿照第3步和表5.4,為各個(gè)控件加入相應(yīng)的成員變量。將m_nAge的值限制在16到65之間。方法是先選擇m_nAge,然后在ClassWizard對話框的左下角輸入最大和最小值。m_nAge代表年齡,這里規(guī)定被調(diào)查的人的年齡應(yīng)在16歲以上,64歲以下。有了這個(gè)限制后,對話框會(huì)對輸入的年齡值進(jìn)行有效性檢查,若輸入的值不在限制范圍內(nèi),則對話框會(huì)提示用戶輸入有效的值。讀者會(huì)注意到控件IDC_INCOME居然有兩個(gè)變量,一個(gè)是CString型的,一個(gè)是CListBox型的,這是完全合法的,不會(huì)引起任何沖突。之所以要加入CListBox型的變量,是因?yàn)榱斜砜虻某跏蓟ㄟ^CListBox對象進(jìn)行。提示:在ClassWizard中可分別為一個(gè)控件指定一個(gè)數(shù)據(jù)變量和一個(gè)控件對象,這樣做的好處是即能方便地獲得數(shù)據(jù),又能方便地控制控件。圖5.8 Add Member Variable對話框表5.4控件ID變量類型變量名IDC_AGEUINTm_nAgeIDC_INCOMECStringm_strIncomeIDC_INCOMECListBoxm_ctrlIncomeIDC_KINDCStringm_strKindIDC_MARRIEDBOOLm_bMarriedIDC_NAMECStringm_strNameIDC_SEXintm_nSexIDC_UNITCStringm_strUnitIDC_WORKintm_nWork5.3.3對話框的初始化對話框的初始化工作一般在構(gòu)造函數(shù)和OnInitDialog函數(shù)中完成。在構(gòu)造函數(shù)中的初始化主要是針對對話框的數(shù)據(jù)成員。讀者可以找到CRegisterDialog的構(gòu)造函數(shù),如清單5.1所示。清單5.1 CRegisterDialog的構(gòu)造函數(shù)CRegisterDialog:CRegisterDialog(CWnd* pParent /*=NULL*/): CDialog(CRegisterDialog:IDD, pParent)/AFX_DATA_INIT(CRegisterDialog)m_nAge = 0;m_strIncome = _T();m_strKind = _T();m_bMarried = FALSE;m_strName = _T();m_nSex = -1;m_strUnit = _T();m_nWork = -1;/AFX_DATA_INIT可以看出,對數(shù)據(jù)成員的初始化是由ClassWizard自動(dòng)完成的。若讀者對初值的含義還不太清楚,請參看表5.3。在對話框創(chuàng)建時(shí),會(huì)收到WM_INITDIALOG消息,對話框?qū)υ撓⒌奶幚砗瘮?shù)是OnInitDialog。調(diào)用OnInitDialog時(shí),對話框已初步創(chuàng)建,對話框的窗口句柄也已有效,但對話框還未被顯示出來。因此,可以在OnInitDialog中做一些影響對話框外觀的初始化工作。OnInitDialog對對話框的作用與OnCreate對CMainFrame的作用類似。提示:MFC窗口的初始化工作一般在OnCreate成員函數(shù)中進(jìn)行,但對話框的初始化工作最好在OnInitDialog中進(jìn)行。OnInitDialog是WM_INITDIALOG消息的處理函數(shù),所以要用ClassWizard為RegisteritDialog類增加一個(gè)WM_INITDIALOG消息的處理函數(shù),增加的方法是進(jìn)入ClassWizard后,先選中MessageMaps標(biāo)簽,然后在Class name中選擇CRegisterDialog,在Object IDs欄中選擇CRegisterDialog,在Messages欄中找到WM_INITDIALOG并雙擊之,最后按OK按鈕退出ClassWizard。請讀者按清單5.2修改OnInitDialog函數(shù)。清單5.2 OnInitDialog函數(shù)BOOL CRegisterDialog:OnInitDialog() CDialog:OnInitDialog();/ TODO: Add extra initialization herem_ctrlIncome.AddString(500元以下);m_ctrlIncome.AddString(500-1000元);m_ctrlIncome.AddString(1000-2000元);m_ctrlIncome.AddString(2000元以上);return TRUE; / return TRUE unless you set the focus to a control/ EXCEPTION: OCX Property Pages should return FALSECRegisterDialog:OnInitDialog()的主要任務(wù)是對工資收入列表框的列表項(xiàng)進(jìn)行初始化。調(diào)用CListBox:AddString可將指定的字符串加入到列表框中。由于該列表是不自動(dòng)排序的,因此AddString將表項(xiàng)加在列表框的末尾。5.3.4對話框的數(shù)據(jù)交換機(jī)制對話框的數(shù)據(jù)成員變量存儲(chǔ)了與控件相對應(yīng)的數(shù)據(jù)。數(shù)據(jù)變量需要和控件交換數(shù)據(jù),以完成輸入或輸出功能。例如,一個(gè)編輯框即可以用來輸入,也可以用來輸出:用作輸入時(shí),用戶在其中輸入了字符后,對應(yīng)的數(shù)據(jù)成員應(yīng)該更新;用作輸出時(shí),應(yīng)及時(shí)刷新編輯框的內(nèi)容以反映相應(yīng)數(shù)據(jù)成員的變化。對話框需要一種機(jī)制來實(shí)現(xiàn)這種數(shù)據(jù)交換功能,這對對話框來說是至關(guān)重要的。MFC提供了類CDataExchange來實(shí)現(xiàn)對話框類與控件之間的數(shù)據(jù)交換(DDX),該類還提供了數(shù)據(jù)有效機(jī)制(DDV)。數(shù)據(jù)交換和數(shù)據(jù)有效機(jī)制適用于編輯框、檢查框、單選按鈕、列表框和組合框。數(shù)據(jù)交換的工作由CDialog:DoDataExchange來完成。讀者可以找到CRegisterDialog:DoDataExchange函數(shù),如清單5.3所示。清單5.3 DoDataExchange函數(shù)void CRegisterDialog:DoDataExchange(CDataExchange* pDX)CDialog:DoDataExchange(pDX);/AFX_DATA_MAP(CRegisterDialog)DDX_Control(pDX, IDC_INCOME, m_ctrlIncome);DDX_LBString(pDX, IDC_INCOME, m_strIncome);DDX_CBString(pDX, IDC_KIND, m_strKind);DDX_Check(pDX, IDC_MARRIED, m_bMarried);DDX_Text(pDX, IDC_NAME, m_strName);DDX_Radio(pDX, IDC_SEX, m_nSex);DDX_Text(pDX, IDC_UNIT, m_strUnit);DDX_Radio(pDX, IDC_WORK, m_nWork);DDX_Text(pDX, IDC_AGE, m_nAge);DDV_MinMaxUInt(pDX, m_nAge, 16, 65);/AFX_DATA_MAP讀者可以看出,該函數(shù)中的代碼是由ClassWizard自動(dòng)加入的。DoDataExchange只有一個(gè)參數(shù),即一個(gè)CDataExchange對象的指針pDX。在該函數(shù)中調(diào)用了DDX函數(shù)來完成數(shù)據(jù)交換,調(diào)用DDV函數(shù)來進(jìn)行數(shù)據(jù)有效檢查。當(dāng)程序需要交換數(shù)據(jù)時(shí),不要直接調(diào)用DoDataExchange函數(shù),而應(yīng)該調(diào)用CWnd:UpdateData。UpdataData函數(shù)內(nèi)部調(diào)用了DoDataExchange。該函數(shù)只有一個(gè)布爾型參數(shù),它決定了數(shù)據(jù)傳送的方向。調(diào)用UpdateData(TRUE)將數(shù)據(jù)從對話框的控件中傳送到對應(yīng)的數(shù)據(jù)成員中,調(diào)用UpdateData(FALSE)則將數(shù)據(jù)從數(shù)據(jù)成員中傳送給對應(yīng)的控件。在缺省的CDialog:OnInitDialog中調(diào)用了UpdateData(FALSE),這樣,在對話框創(chuàng)建時(shí),數(shù)據(jù)成員的初值就會(huì)反映到相應(yīng)的控件上。若用戶是按了OK(確定)按鈕退出對話框,則對話框認(rèn)為輸入有效,就會(huì)調(diào)用UpdataData(TRUE)將控件中的數(shù)據(jù)傳給數(shù)據(jù)成員。圖5.9描繪了對話框的這種數(shù)據(jù)交換機(jī)制。圖5.9 對話框的數(shù)據(jù)交換5.3.5對話框的運(yùn)行機(jī)制在程序中運(yùn)行模態(tài)對話框有兩個(gè)步驟:在堆棧上以變量的形式構(gòu)建一個(gè)對話框?qū)ο蟆U{(diào)用CDialog:DoModal ( )。DoModal負(fù)責(zé)對模態(tài)話框的創(chuàng)建和撤銷。在創(chuàng)建對話框時(shí),DoModal的任務(wù)包括載入對話框模板資源、調(diào)用OnInitDialog初始化對話框和將對話框顯示在屏幕上。完成對話框的創(chuàng)建后,DoModal啟動(dòng)一個(gè)消息循環(huán),以響應(yīng)用戶的輸入。由于該消息循環(huán)截獲了幾乎所有的輸入消息,使主消息循環(huán)收不到對對話框的輸入,致使用戶只能與模態(tài)對話框進(jìn)行交互,而其它用戶界面對象收不到輸入信息。若用戶在對話框內(nèi)點(diǎn)擊了ID為IDOK的按鈕(通常該按鈕的標(biāo)題是“確定”或“OK”),或按了回車鍵,則CDialog:OnOK將被調(diào)用。OnOK首先調(diào)用UpdateData(TRUE)將數(shù)據(jù)從控件傳給對話框成員變量,然后調(diào)用CDialog:EndDialog關(guān)閉對話框。關(guān)閉對話框后,DoModal會(huì)返回值IDOK。若用戶點(diǎn)擊了ID為IDCANCEL的按鈕(通常其標(biāo)題為“取消”或“Cancel”),或按了ESC鍵,則會(huì)導(dǎo)致CDialog:OnCancel的調(diào)用。該函數(shù)只調(diào)用CDialog:EndDialog關(guān)閉對話框。關(guān)閉對話框后,DoModal會(huì)返回值IDCANCEL。程序根據(jù)DoModal的返回值是IDOK還是IDCANCEL就可以判斷出用戶是確定還是取消了對對話框的操作。在弄清了對話框的運(yùn)行機(jī)制后,下面讓我們來就可以實(shí)現(xiàn)Register程序登錄數(shù)據(jù)的功能。首先,將Register工程的工作區(qū)切換至資源視圖。打開IDR_MAINFRAME菜單資源,在Edit菜單的底端加入一個(gè)名為“登錄數(shù)據(jù)”的新菜單項(xiàng),并令其ID為ID_EDIT_REGISTER(最好在該項(xiàng)之前加一條分隔線,以便和前面的菜單項(xiàng)分開)。注意不要忘了把菜單資源的語種設(shè)置成中文,否則菜單中將顯示不出中文來。設(shè)置的方法是先在工作區(qū)資源視圖中選擇IDR_MAINFRAME菜單資源,然后按Alt+Enter鍵,并在彈出的屬性對話框中的Language欄中選擇Chinese(P.R.C.)。接著,用ClassWizard為該菜單命令創(chuàng)建命令處理函數(shù)CRegisterView:OnEditRegister。注意,OnEditRegister是類CRegisterView的成員函數(shù),這是因?yàn)镃RegisterView要負(fù)責(zé)打開和關(guān)閉登錄數(shù)據(jù)對話框,并將從對話框中輸入的數(shù)據(jù)在視圖中輸出。然后,請讀者在RegisterView.cpp文件的開頭加入下面一行#include RegisterDialog.h最后,按清單5.4修改程序。清單5.4 OnEditRegister函數(shù)void CRegisterView:OnEditRegister() / TODO: Add your command handler code hereCRegisterDialog dlg;if(dlg.DoModal()=IDOK)CString str;/獲取編輯正文GetWindowText(str);/換行str+=rn;str+=姓名:;str+=dlg.m_strName;str+=rn;str+=性別:;str+=dlg.m_nSex?女:男;str+=rn;str+=年齡:;CString str1;/將數(shù)據(jù)格式輸出到字符串對象中str1.Format(%d,dlg.m_nAge);str+=str1;str+=rn;str+=婚否:;str+=dlg.m_bMarried?已婚:未婚;str+=rn;str+=就業(yè)狀況:;str+=dlg.m_nWork?下崗:在職;str+=rn;str+=工作單位:;str+=dlg.m_strUnit;str+=rn;str+=單位性質(zhì):;str+=dlg.m_strKind;str+=rn;str+=工資收入:;str+=dlg.m_strIncome;str+=rn;/更新編輯視圖中的正文SetWindowText(str);在OnEditRegister函數(shù)中,首先構(gòu)建了一個(gè)CRegisterDialog對象,然后調(diào)用CDialog:DoModal來實(shí)現(xiàn)模態(tài)對話框。如果DoModal返回IDOK,則說明用戶確認(rèn)了登錄數(shù)據(jù)的操作,程序需要將錄入的數(shù)據(jù)在編輯視圖中輸出。程序用一個(gè)CString對象來作為編輯正文的緩沖區(qū),CString是一個(gè)功能強(qiáng)大的字符串類,它的最大特點(diǎn)在于可以存儲(chǔ)動(dòng)態(tài)改變大小的字符串,這樣,用戶不必?fù)?dān)心字符串的長度超過緩沖區(qū)的大小, 使用十分方便。在輸出數(shù)據(jù)時(shí),程序首先調(diào)用CWnd:GetWindowText獲得編輯正文,這是一個(gè)多行的編輯正文。CWnd:GetWindowText用來獲取窗口的標(biāo)題,若該窗口是一個(gè)控件,則獲取的是控件內(nèi)的正文。CRegisterView是CEditView的繼承類,而CEditView實(shí)際上包含了一個(gè)編輯控件,因此在CRegisterView中調(diào)用GetWindowText獲得的是編輯正文。然后,程序在該編輯正文的末尾加入新的數(shù)據(jù)。在程序中大量使用了CString類的重載操作符“”,該操作符的功能是將操作符右側(cè)字符串添加到操作符左側(cè)的字符串的末尾。注意在多行編輯控件中每行末尾都有一對回車和換行符。在程序中還調(diào)用了CString:Format來將數(shù)據(jù)格式化輸出到字符串中,F(xiàn)ormat的功能與sprintf類似。最后,調(diào)用CWnd:SetWindowText來更新編輯視圖中的正文。編譯并運(yùn)行Register,打開登錄數(shù)據(jù)對話框,輸入一些數(shù)據(jù)試試。現(xiàn)在,Register已經(jīng)是一個(gè)簡易的數(shù)據(jù)庫應(yīng)用程序了,它可以將與就業(yè)情況有關(guān)的數(shù)據(jù)輸出到一個(gè)編輯視圖中。用戶可以編輯視圖中的正文,并將結(jié)果保存在文本文件中。5.3.6處理控件通知消息雖然Register已經(jīng)可以登錄數(shù)據(jù)了,但讀者會(huì)很快會(huì)發(fā)現(xiàn)該程序還有一些不完善的地方:登錄完一個(gè)人的數(shù)據(jù)后,對話框就關(guān)閉了,若用戶有很多人的數(shù)據(jù)要輸入,則必須頻繁地打開對話框,很不方便。在登錄數(shù)據(jù)時(shí),應(yīng)該使對話框一直處于打開狀態(tài)。登錄數(shù)據(jù)對話框分個(gè)人情況和單位情況兩組,若被調(diào)查人是下崗職工,則不必輸入單位情況。程序應(yīng)該能夠?qū)τ脩舻妮斎爰皶r(shí)地作出反應(yīng),即當(dāng)用戶選擇了“下崗”單選按鈕時(shí),應(yīng)使單位情況組中的控件禁止。一個(gè)禁止的控件呈灰色示,并且不能接收用戶的輸入。要解決上述問題,就必須對控件通知消息進(jìn)行處理。當(dāng)控件的狀態(tài)因?yàn)檩斎氲仍蚨l(fā)生變化時(shí),控件會(huì)向其父窗口發(fā)出控件通知消息。例如,如果用戶在登錄數(shù)據(jù)對話框中的某一按鈕(包括普通按鈕、檢查框和單選按鈕)上單擊鼠標(biāo),則該按鈕會(huì)向?qū)υ捒虬l(fā)送BN_CLICKED消息。對話框根據(jù)按鈕的ID激活相應(yīng)的BN_CLICKED消息處理函數(shù),以對單擊按鈕這一事件作出反應(yīng)。通過對按鈕的BN_CLICKED消息的處理,我們可以使登錄數(shù)據(jù)對話框的功能達(dá)到上述要求。首先,讓我們來解決第一個(gè)問題。我們的設(shè)想是修改原來的“確定(Y)”按鈕,使得當(dāng)用戶點(diǎn)擊該按鈕后,將數(shù)據(jù)輸出到視圖中,并且對話框不關(guān)閉,以便用戶輸入下一個(gè)數(shù)據(jù)。請讀者按下面幾步進(jìn)行修改。修改登錄數(shù)據(jù)對話框的“確定(Y)”按鈕,使該按鈕的標(biāo)題變?yōu)椤疤砑?&A)”,ID變?yōu)镮DC_ADD。這樣,當(dāng)用戶點(diǎn)擊該按鈕后,對話框會(huì)收到BN_CLICKED消息。由于這個(gè)BN_CLICKED消息對應(yīng)的按鈕ID不是IDOK,不會(huì)觸發(fā)OnOK消息處理函數(shù),因此不會(huì)關(guān)閉對話框。為按鈕IDC_ADD的BN_CLICKED消息創(chuàng)建消息處理函數(shù)。創(chuàng)建的方法是進(jìn)入ClassWizard后,選Message Maps頁并在Class name欄中選擇CRegisterDialog,然后在Object IDs欄中選擇IDC_ADD,在Messages欄中雙擊BN_CLICKED。在確認(rèn)使用缺省的消息處理函數(shù)名OnAdd后,按回車鍵退出ClassWizard。OnAdd要向編輯視圖輸出正文,就必須獲得一個(gè)指向CRegisterView對象的指針以訪問該對象。為此,請?jiān)贑RegisterDialog類的說明中加入下面一行Cwnd* m_pParent;注意不要加在AFX注釋對中。為實(shí)現(xiàn)IDC_ADD按鈕的功能,請按清單5.5和清單5.6修改程序。主要的改動(dòng)是把原來由CRegiserView:OnEditRegister完成的在視圖中輸出數(shù)據(jù)的任務(wù)交給CRegisterDialog:OnAdd來完成。清單5.5 CRegisterView:OnEditRegister函數(shù)void CRegisterView:OnEditRegister() / TODO: Add your command handler code hereCRegisterDialog dlg(this);dlg.DoModal();清單5.6 CRegisterDialog類的部分源代碼CRegisterDialog:CRegisterDialog(CWnd* pParent /*=NULL*/): CDialog(CRegisterDialog:IDD, pParent)/AFX_DATA_INIT(CRegisterDialog). . . . . ./AFX_DATA_INITm_pParent=pParent;void CRegisterDialog:OnAdd() / TODO: Add your control notification handler code here/更新數(shù)據(jù)UpdateData(TRUE);/檢查數(shù)據(jù)是否有效if(m_strName= | m_nSex0 | m_nWorkGetWindowText(str);/換行str+=rn;str+=姓名:;str+=m_strName;str+=rn;str+=性別:;str+=m_nSex?女:男;str+=rn;str+=年齡:;CString str1;/將數(shù)據(jù)格式輸出到字符串對象中str1.Format(%d,m_nAge);str+=str1;str+=rn;str+=婚否:;str+=m_bMarried?已婚:未婚;str+=rn;str+=就業(yè)狀況:;str+=m_nWork?下崗:在職;str+=rn;str+=工作單位:;str+=m_strUnit;str+=rn;str+=單位性質(zhì):;str+=m_strKind;str+=rn;str+=工資收入:;str+=m_strIncome;str+=rn;/更新編輯視圖中的正文m_pParent-SetWindowText(str);CRegisterDialog的構(gòu)造函數(shù)有一個(gè)參數(shù)pParent,該參數(shù)是一個(gè)指向CWnd對象的指針,用于指定對話框的父窗口或擁有者窗口。在CRegisterView: OnEditRegister函數(shù)中,在構(gòu)建CRegisterDialog對象時(shí)指定了this參數(shù),this指針指向CRegisterView對象本身。這樣在調(diào)用CRegisterDialog的構(gòu)造函數(shù)時(shí),this指針值被賦給了CRegisterDialog的成員m_pParent。OnAdd函數(shù)可利用m_pParent來訪問對話框的擁有者即CRegisterView對象。提示:術(shù)語父窗口(Parent)是相對于子窗口而言。若某一個(gè)窗口擁有一個(gè)子窗口(Child),則該窗口就被稱為子窗口的父窗口。子窗口就是具有WS_CHILD風(fēng)格的窗口,子窗口依賴于父窗口且完全被限制在父窗口內(nèi)部。擁有者窗口(owner)相對于被擁有者窗口而言。若某一個(gè)窗口擁有一個(gè)非子窗口,則該窗口被稱為擁有者窗口。被擁有窗口(owned)不具有WS_CHILD風(fēng)格,可在屏幕上任意移動(dòng)。當(dāng)用戶用鼠標(biāo)點(diǎn)擊IDC_ADD按鈕時(shí),該按鈕的BN_CLICKED消息處理函數(shù)CRegisterDialog:OnAdd將被調(diào)用。在OnAdd中,首先調(diào)用了UpdateData(TRUE)以把數(shù)據(jù)從控件傳給對話框的數(shù)據(jù)成員變量。然后,程序要對數(shù)據(jù)的有效性進(jìn)行檢查,如果輸入的數(shù)據(jù)不完全有效,則會(huì)顯示一個(gè)消息對話框,提示用戶輸入有效的數(shù)據(jù)。接下來進(jìn)行的工作是在視圖中輸出數(shù)據(jù),這部分代碼與清單5.4類似,讀者應(yīng)該比較熟悉了。完成上述工作后,登錄數(shù)據(jù)對話框就變得較為實(shí)用了。打開對話框后,用戶可以方便地輸入多人的數(shù)據(jù),只有按了取消按鈕后,對話框才會(huì)關(guān)閉。接下來讓我們來解決第二個(gè)問題。解決該問題的關(guān)鍵在于當(dāng)用戶點(diǎn)擊“在職”或“下崗”單選按鈕時(shí),程序要對收到的BN_CLICKED消息作出響應(yīng)。有些讀者可能會(huì)想到為兩個(gè)單選按鈕分別創(chuàng)建BN_CLICKED消息處理函數(shù),這在只有兩個(gè)單選按鈕的情況下是可以的,但如果一組內(nèi)有多個(gè)單選按鈕,則分別創(chuàng)建消息處理函數(shù)就比較麻煩了。利用MFC提供的消息映射宏ON_CONTROL_RANGE可以避免這種麻煩,該映射宏把多個(gè)ID連續(xù)的控件發(fā)出的消息映射到同一個(gè)處理函數(shù)上。這樣,我們只要編寫一個(gè)消息處理函數(shù),就可以對“在職”和“下崗”兩個(gè)單選按鈕的BN_CLICKED消息作出響應(yīng)。ClassWizard不支持ON_CONTROL_RANGE宏,所以我們必須手工創(chuàng)建單選按鈕的消息映射和消息處理函數(shù)。首先,在CRegisterDialog類的頭文件中加入消息處理函數(shù)的聲明,該函數(shù)名為OnWorkClicked,如清單5.7所示。清單5.7 BN_CLICKED消息處理函數(shù)OnWorkClicked的聲明protected:void OnWorkClicked(UINT nCmdID);/ Generated message map functions/AFX_MSG(CRegisterDialog)virtual BOOL OnInitDialog();afx_msg void OnAdd();/AFX_MSG然后,在CRegisterDialog類的消息映射中加入ON_CONTROL_RANGE映射,如清單5.8所示。ON_CONTROL_RANGE映射的形式是ON_CONTROL_RANGE清單5.8 在CRegisterDialog類的消息映射中加入ON_CONTROL_RANGE映射BEGIN_MESSAGE_MAP(CRegisterDialog, CDialog)/AFX_MSG_MAP(CRegisterDialog)ON_BN_CLICKED(IDC_ADD, OnAdd)/AFX_MSG_MAPON_CONTROL_RANGE(BN_CLICKED, IDC_WORK, IDC_WORK1, OnWorkClicked)END_MESSAGE_MAP()ON_CONTROL_RANGE消息映射宏的第一個(gè)參數(shù)是控件消息碼,第二和第三個(gè)參數(shù)分別指明了一組連續(xù)的控件ID中的頭一個(gè)和最后一個(gè)ID,最后一個(gè)參數(shù)是消息處理函數(shù)名。如果讀者是按表5.2的順序放置控件的則IDC_WORK和IDC_WORK1應(yīng)該是連續(xù)的。這樣,無論用戶是在IDC_WORK還是在IDC_WORK1單選按鈕上單擊,都會(huì)調(diào)用OnWorkClicked消息處理函數(shù)。提示:如果不能確定兩個(gè)ID是否是連續(xù)的,請用File-Open命令打開resource.h文件,在該文件中有對控
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 戀愛階段財(cái)產(chǎn)管理與婚姻規(guī)劃協(xié)議
- 出租車公司員工福利合作協(xié)議
- Brand KPIs for hotels:Fiesta Inn in Mexico-英文培訓(xùn)課件2025.5
- 2025年地質(zhì)與資源勘探考試試題及答案
- 2025年公共英語等級(jí)考試試題及答案
- 標(biāo)準(zhǔn)的研制與編制-廣東開放大學(xué)考試題庫及答案
- 2025年城市規(guī)劃專業(yè)研究生考試試題及答案
- 一年級(jí)數(shù)學(xué)教學(xué)方案(32篇)
- 企業(yè)常年財(cái)務(wù)顧問與內(nèi)部審計(jì)協(xié)議
- 餐飲行業(yè)供應(yīng)鏈保密合同模板
- 《向量加法運(yùn)算及其幾何意義》參考課件1
- 物業(yè)管理公司品質(zhì)管理手冊
- 儲(chǔ)備土地管護(hù)巡查方案
- 古代小說戲曲專題-形考任務(wù)2-國開-參考資料
- 24個(gè)專業(yè)105個(gè)病種中醫(yī)臨床路徑
- 校企合作技能培訓(xùn)協(xié)議
- 2024年江蘇省無錫市惠山區(qū)中考三??荚囄锢碓囶}
- 校服供貨服務(wù)方案
- 植物保護(hù)學(xué)II(園藝)智慧樹知到期末考試答案章節(jié)答案2024年浙江大學(xué)
- 19S406建筑排水管道安裝-塑料管道
- 化工施工安全技術(shù)交底
評論
0/150
提交評論