傳統(tǒng)控件的用法: .1.1 傳統(tǒng)控件的控件通知消息 控件通過向父窗口發(fā)送控件通知消息來表明發(fā)生了某種事件.例如,當(dāng)用戶在按鈕上單擊鼠標(biāo)時,按鈕控件會向父窗口發(fā)送BN_CLICKED消息.傳統(tǒng)控件的通知消息實際上是通過WM_COMMAND消息發(fā)給父窗口的(滾動條除外),在該消息的wParam中含有通知消息碼(如BN_CLICKED)和控件的ID,在lParam中則包含了控件的句柄. 利用ClassWizard可以很容易地為控件通知消息加入消息映射和消息處理函數(shù),這在上一章中已經(jīng)演示過了.傳統(tǒng)控件的消息映射宏是ON_XXXX,其中XXXX表示通知消息碼,如BN_CLICKED.ON_XXXX消息映射如下所示,該宏有兩個參數(shù),一個是控件的ID,一個是消息處理函數(shù)名. ON_XXXX(nID, memberFxn) 消息處理函數(shù)的聲明應(yīng)該有如下形式: afx_msg void memberFxn( ); 例如,某按鈕的BN_CLICKED消息的消息映射及其處理函數(shù)的聲明如下所示 ON_BN_CLICKED(IDC_ADD,OnAdd) afx_msg void OnAdd( ); 有時,為了處理方便,需要把多個ID連續(xù)的控件發(fā)出的相同消息映射到同一個處理函數(shù)上.這就要用到ON_CONTROL_RANGE宏.ON_CONTROL_RANGE消息映射宏的第一個參數(shù)是控件消息碼,第二和第三個參數(shù)分別指明了一組連續(xù)的控件ID中的頭一個和最后一個ID,最后一個參數(shù)是消息處理函數(shù)名。例如,要處理一組單選按鈕發(fā)出的BN_CLICKED消息,相應(yīng)的消息映射如下所示: ON_CONTROL_RANGE(BN_CLICKED, IDC_FIRST, IDC_LAST, OnRadioClicked) 函數(shù)OnRadioClicked的聲明如下,該函數(shù)比上面的OnAdd多了一個參數(shù)nID以說明發(fā)送通知消息的控件ID. afx_msg void OnRadioClicked(UINT nID); ClassWizard不支持ON_CONTROL_RANGE宏,所以需要手工建立消息映射和消息處理函數(shù). 提示:事實上,在使用ClassWizard時只要運用一個小小的技巧,就可以把不同控件的通知消息映射到同一個處理函數(shù)上,也可以把一個控件的不同通知消息映射到同一個處理函數(shù)上.這個技巧就是在用ClassWizard創(chuàng)建消息處理函數(shù)時,指定相同的函數(shù)名即可.此方法的優(yōu)點在于控件的ID不必是連續(xù)的,缺點是處理函數(shù)沒有nID參數(shù),因而不能確定是哪一個控件發(fā)送的消息. 6.1.2 靜態(tài)控件 靜態(tài)控件包括靜態(tài)正文(Static Text)和圖片控件(Picture)。靜態(tài)正文控件用來顯示正文。圖片控件可以顯示位圖、圖標(biāo)、方框和圖元文件,在圖片控件中顯示圖片的好處是不必操心圖片的重繪問題。靜態(tài)控件不能接收用戶的輸入。在上一章中,讀者已經(jīng)用過靜態(tài)正文和組框控件。圖片控件的例子可以在AppWizard創(chuàng)建的IDD_ABOUTBOX對話框模板中找到,在該模板中有一個圖片控件用來顯示圖標(biāo)。 靜態(tài)控件的主要起說明和裝飾作用。MFC的CStatic類封裝了靜態(tài)控件。CStatic類的成員函數(shù)Create負責(zé)創(chuàng)建靜態(tài)控件,該函數(shù)的聲明為 BOOL Create( LPCTSTR lpszText, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID = 0xffff ); 參數(shù)lpszText指定了控件顯示的正文。dwStyle指定了靜態(tài)控件的風(fēng)格,表6.1顯示了靜態(tài)控件的各種風(fēng)格,dwStyle可將這些風(fēng)格組合起來。rect是一個對RECT或CRect結(jié)構(gòu)的引用,用來說明控件的位置和尺寸。pParentWnd指向父窗口,該參數(shù)不能為NULL。nID則說明了控件的ID。如果創(chuàng)建成功,該函數(shù)返回TRUE,否則返回FALSE. 表6.1 靜態(tài)控件的風(fēng)格 控件風(fēng)格 含義 SS_BLACKFRAME 指定一個具有與窗口邊界同色的框(缺省為黑色)。 SS_BLACKRECT 指定一個具有與窗口邊界同色的實矩形(缺省為黑色)。 SS_CENTER 使顯示的正文居中對齊,正文可以回繞。 SS_GRAYFRAME 指定一個具有與屏幕背景同色的邊框。 SS_GRAYRECT 指定一個具有與屏幕背景同色的實矩形。 SS_ICON 使控件顯示一個在資源中定義的圖標(biāo),圖標(biāo)的名字有Create函數(shù)的lpszText參數(shù)指定。 SS_LEFT 左對齊正文,正文能回繞。 SS_LEFTNOWORDWRAP 左對齊正文,正文不能回繞。 SS_NOPREFIX 使靜態(tài)正文串中的&不是一個熱鍵提示符。 SS_NOTIFY 使控件能向父窗口發(fā)送鼠標(biāo)事件消息。 SS_RIGHT 右對齊正文,可以回繞。 SS_SIMPLE 使靜態(tài)正文在運行時不能被改變并使正文顯示在單行中。 SS_USERITEM 指定一個用戶定義項。 SS_WHITEFRAME 指定一個具有與窗口背景同色的框(缺省為白色)。 SS_WHITERECT 指定一個具有與窗口背景同色的實心矩形(缺省為白色)。 除了上表中的風(fēng)格外,一般還要為控件指定WS_CHILD和WS_VISIBLE窗口風(fēng)格。一個典型的靜態(tài)正文控件的風(fēng)格為WS_CHILD|WS_VISIBLE|SS_LEFT。 對于用對話框模板編輯器創(chuàng)建的靜態(tài)控件,可以在控件的屬性對話框中指定表6.1中列出的控件風(fēng)格。例如,可以在靜態(tài)正文控件的屬性對話框中選擇Simple,這相當(dāng)于指定了SS_SIMPLE風(fēng)格。 Cstatic類主要的成員函數(shù)在表6.2中列出??梢岳肅Wnd類的成員函數(shù)GetWindowText,SetWindowText和GetWindowTextLength等函數(shù)來查詢和設(shè)置靜態(tài)控件中顯示的正文. 表6.2 CStatic類的主要成員函數(shù) 函數(shù)聲明 用途 HBITMAP SetBitmap( HBITMAP hBitmap ); 指定要顯示的位圖。 HBITMAP GetBitmap( ) const; 獲取由SetBitmap指定的位圖。 HICON SetIcon( HICON hIcon ); 指定要顯示的圖標(biāo)。 HICON GetIcon( ) const; 獲取由SetIcon指定的圖標(biāo)。 HCURSOR SetCursor( HCURSOR hCursor ); 指定要顯示的光標(biāo)圖片。 HCURSOR GetCursor( ); 獲取由SetCursor指定的光標(biāo)。 HENHMETAFILE SetEnhMetaFile( HENHMETAFILE hMetaFile ); 指定要顯示的增強圖元文件。 HENHMETAFILE GetEnhMetaFile( ) const; 獲取由SetEnhMetaFile指定的圖元文件。 靜態(tài)控件較簡單,故這里就不舉例說明了。 6.1.3 按鈕控件 按鈕是指可以響應(yīng)鼠標(biāo)點擊的小矩形子窗口。按鈕控件包括命令按鈕(Pushbutton)、檢查框(Check Box)、單選按鈕(Radio Button)、組框(Group Box)和自繪式按鈕(Owner-draw Button)。命令按鈕的作用是對用戶的鼠標(biāo)單擊作出反應(yīng)并觸發(fā)相應(yīng)的事件,在按鈕中既可以顯示正文,也可以顯示位圖。選擇框控件可作為一種選擇標(biāo)記,可以有選中、不選中和不確定三種狀態(tài)。單選按鈕控件一般都是成組出現(xiàn)的,具有互斥的性質(zhì),即同組單選按鈕中只能有一個是被選中的。組框用來將相關(guān)的一些控件聚成一組.自繪式按鈕是指由程序而不是系統(tǒng)負責(zé)重繪的按鈕。 按鈕主要是指命令按鈕、選擇框和單選按鈕。后二者實際上是一種特殊的按鈕,它們有選擇和未選擇狀態(tài)。當(dāng)一個選擇框處于選擇狀態(tài)時,在小方框內(nèi)會出現(xiàn)一個“√”,當(dāng)單選按鈕處于選擇狀態(tài)時,會在圓圈中顯示一個黑色實心圓。此外,檢查框還有一種不確定狀態(tài),這時檢查框呈灰色顯示,不能接受用戶的輸入,以表明控件是無效的或無意義的。 按鈕控件會向父窗口發(fā)出如表6.3所示的控件通知消息。 表6.3 按鈕控件的通知消息 消息 含義 BN_CLICKED 用戶在按鈕上單擊了鼠標(biāo)。 BN_DOUBLECLICKED 用戶在按鈕上雙擊了鼠標(biāo)。 FC的CButton類封裝了按鈕控件。CButton類的成員函數(shù)Create負責(zé)創(chuàng)建按鈕控件,該函數(shù)的聲明為 BOOL Create( LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 參數(shù)lpszCaption指定了按鈕顯示的正文。dwStyle指定了按鈕的風(fēng)格,如表6.4所示,dwStyle可以是這些風(fēng)格的組合。rect說明了按鈕的位置和尺寸。pParentWnd指向父窗口,該參數(shù)不能為NULL。nID是按鈕的ID。如果創(chuàng)建成功,該函數(shù)返回TRUE,否則返回FALSE. 表6.4 按鈕的風(fēng)格 控件風(fēng)格 含義 BS_AUTOCHECKBOX 同BS_CHECKBOX,不過單擊鼠標(biāo)時按鈕會自動反轉(zhuǎn)。 BS_AUTORADIOBUTTON 同BS_RADIOBUTTON,不過單擊鼠標(biāo)時按鈕會自動反轉(zhuǎn)。 BS_AUTO3STATE 同BS_3STATE,不過單擊按鈕時會改變狀態(tài)。 BS_CHECKBOX 指定在矩形按鈕右側(cè)帶有標(biāo)題的選擇框。 BS_DEFPUSHBUTTON 指定缺省的命令按鈕,這種按鈕的周圍有一個黑框,用戶可以按回車鍵來快速選擇該按鈕。 BS_GROUPBOX 指定一個組框。 BS_LEFTTEXT 使控件的標(biāo)題顯示在按鈕的左邊。 BS_OWNERDRAW 指定一個自繪式按鈕。 BS_PUSHBUTTON 指定一個命令按鈕。 BS_RADIOBUTTON 指定一個單選按鈕,在圓按鈕的右邊顯示正文。 BS_3STATE 同BS_CHECKBOX,不過控件有三種狀態(tài):選擇、未選擇和變灰。 除了上表中的風(fēng)格外,一般還要為控件指定WS_CHILD、WS_VISIBLE和WS_TABSTOP窗口風(fēng)格,WS_TABSTOP使控件具有Tabstop屬性。創(chuàng)建一個普通按鈕應(yīng)指定的風(fēng)格為WS_CHILD|WS_VISIBLE|WS_TABSTOP。創(chuàng)建一個普通檢查框應(yīng)指定風(fēng)格WS_CHILD|WS_VISIBLE|WS_TABSTOP| BS_AUTOCHECKBOX。創(chuàng)建組中第一個單選按鈕應(yīng)指定風(fēng)格WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_GROUP| BS_AUTORADIOBUTTON,組中其它單選按鈕應(yīng)指定風(fēng)格則不應(yīng)該包括WS_TABSTOP和WS_GROUP。 對于用對話框模板編輯器創(chuàng)建的按鈕控件,可以在控件的屬性對話框中指定表6.4中列出的控件風(fēng)格。例如,在命令按鈕的屬性對話框中選擇Default button,相當(dāng)于指定了BS_DEFPUSHBUTTON。 CButton類的主要的成員函數(shù)有: UINT GetState( ) const; 該函數(shù)返回按鈕控件的各種狀態(tài)??梢杂孟铝衅帘沃蹬c函數(shù)的返回值相與,以獲得各種信息。 0x0003。用來獲取檢查框或單選按鈕的狀態(tài)。0表示未選中,1表示被選中,2表示不確定狀態(tài)(僅用于檢查框)。 0x0004。用來判斷按鈕是否是高亮度顯示的。非零值意味著按鈕是高亮度顯示的。當(dāng)用戶點擊了按鈕并按主鼠標(biāo)左鍵時,按鈕會呈高亮度顯示。 0x0008。非零值表示按鈕擁有輸入焦點。 void SetState( BOOL bHighlight ); 當(dāng)參數(shù)bHeightlight值為TRUE時,該函數(shù)將按鈕設(shè)置為高亮度狀態(tài),否則,去除按鈕的高亮度狀態(tài)。 int GetCheck( ) const; 返回檢查框或單選按鈕的選擇狀態(tài)。返回值0表示按鈕未被選擇,1表示按鈕被選擇,2表示按鈕處于不確定狀態(tài)(僅用于檢查框)。 void SetCheck( int nCheck ); 設(shè)置檢查框或單選按鈕的選擇狀態(tài)。參數(shù)nCheck值的含義與GetCheck返回值相同。 UINT GetButtonStyle( ) const; 獲得按鈕控件的BS_XXXX風(fēng)格。 void SetButtonStyle( UINT nStyle, BOOL bRedraw = TRUE ); 設(shè)置按鈕的風(fēng)格。參數(shù)nStyle指定了按鈕的風(fēng)格。bRedraw為TRUE則重繪按鈕,否則就不重繪。 HBITMAP SetBitmap( HBITMAP hBitmap ); 設(shè)置按鈕顯示的位圖。參數(shù)hBitmap指定了位圖的句柄。該函數(shù)還會返回按鈕原來的位圖。 HBITMAP GetBitmap( ) const; 返回以前用SetBitmap設(shè)置的按鈕位圖。 HICON SetIcon( HICON hIcon ); 設(shè)置按鈕顯示的圖標(biāo)。參數(shù)hIcon指定了圖標(biāo)的句柄。該函數(shù)還會返回按鈕原來的圖標(biāo)。 HICON GetIcon( ) const; 返回以前用SetIcon設(shè)置的按鈕圖標(biāo)。 HCURSOR SetCursor( HCURSOR hCursor ); 設(shè)置按鈕顯示的光標(biāo)圖。參數(shù)hCursor指定了光標(biāo)的句柄。該函數(shù)還會返回按鈕原來的光標(biāo)。 HCURSOR GetCursor( ); 返回以前用GetCursor設(shè)置的光標(biāo)。 另外,可以使用下列的一些與按鈕控件有關(guān)的CWnd成員函數(shù)來設(shè)置或查詢按鈕的狀態(tài)。用這些函數(shù)的好處在于不必構(gòu)建按鈕控件對象,只要知道按鈕的ID,就可以直接設(shè)置或查詢按鈕。 void CheckDlgButton( int nIDButton, UINT nCheck ); 用來設(shè)置按鈕的選擇狀態(tài)。參數(shù)nIDButton指定了按鈕的ID。nCheck的值0表示按鈕未被選擇,1表示按鈕被選擇,2表示按鈕處于不確定狀態(tài)。 void CheckRadioButton( int nIDFirstButton, int nIDLastButton, int nIDCheckButton ); 用來選擇組中的一個單選按鈕。參數(shù)nIDFirstButton指定了組中第一個按鈕的ID,nIDLastButton指定了組中最后一個按鈕的ID,nIDCheckButton指定了要選擇的按鈕的ID。 int GetCheckedRadioButton( int nIDFirstButton, int nIDLastButton ); 該函數(shù)用來獲得一組單選按鈕中被選中按鈕的ID。參數(shù)nIDFirstButton說明了組中第一個按鈕的ID,nIDLastButton說明了組中最后一個按鈕的ID。 UINT IsDlgButtonChecked( int nIDButton ) const; 返回檢查框或單選按鈕的選擇狀態(tài)。返回值0表示按鈕未被選擇,1表示按鈕被選擇,2表示按鈕處于不確定狀態(tài)(僅用于檢查框)。 可以調(diào)用CWnd成員函數(shù)GetWindowText,GetWindowTextLength和SetWindowText來查詢或設(shè)置按鈕中顯示的正文. MFC還提供了CButton的派生類CBitmapButton。利用該類可以創(chuàng)建一個擁有四幅位圖的命令按鈕,按鈕在不同狀態(tài)時會顯示不同的位圖,這樣可以使界面顯得生動活潑。如果讀者對CBitmapButton感興趣,可以參看VC5.0隨盤提供的MFC例子CTRLTEST。 在上一章的Register例子中已演示了各種按鈕控件的使用,故這里就不再舉例了。 6.1.4 編輯框控件 編輯框(Edit Box)控件實際上是一個簡易的正文編輯器,用戶可以在編輯框中輸入并編輯正文。編輯框既可以是單行的,也可以是多行的,多行編輯框是從零開始編行號的.在一個多行編輯框中,除了最后一行外,每一行的結(jié)尾處都有一對回車換行符(用"\r\n"表示).這對回車換行符是正文換行的標(biāo)志,在屏幕上是不可見的. 編輯框控件會向父窗口發(fā)出如表6.5所示的控件通知消息。 表6.5 消息 含義 EN_CHANGE 編輯框的內(nèi)容被用戶改變了。與EN_UPDATE不同,該消息是在編輯框顯示的正文被刷新后才發(fā)出的。 EN_ERRSPACE 編輯框控件無法申請足夠的動態(tài)內(nèi)存來滿足需要。 EN_HSCROLL 用戶在水平滾動條上單擊鼠標(biāo)。 EN_KILLFOCUS 編輯框失去輸入焦點。 EN_MAXTEXT 輸入的字符超過了規(guī)定的最大字符數(shù)。在沒有ES_AUTOHSCROLL或ES_AUTOVSCROLL的編輯框中,當(dāng)正文超出了編輯框的邊框時也會發(fā)出該消息。 EN_SETFOCUS 編輯框獲得輸入焦點。 EN_UPDATE 在編輯框準(zhǔn)備顯示改變了的正文時發(fā)送該消息。 EN_VSCROLL 用戶在垂直滾動條上單擊鼠標(biāo)。 MFC的CEdit類封裝了編輯框控件。CEdit類的成員函數(shù)Create負責(zé)創(chuàng)建按鈕控件,該函數(shù)的聲明為 BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 參數(shù)dwStyle指定了編輯框控件風(fēng)格,如表6.6所示,dwStyle可以是這些風(fēng)格的組合。rect指定了編輯框的位置和尺寸。pParentWnd指定了父窗口,不能為NULL。編輯框的ID由nID指定。如果創(chuàng)建成功,該函數(shù)返回TRUE,否則返回FALSE. 表6.6 編輯框控件的風(fēng)格 控件風(fēng)格 含義 ES_AUTOHSCROLL 當(dāng)用戶在行尾鍵入一個字符時,正文將自動向右滾動10個字符,當(dāng)用戶按回車鍵時,正文總是滾向左邊。 ES_AUTOVSCROLL 當(dāng)用戶在最后一個可見行按回車鍵時,正文向上滾動一頁。 ES_CENTER 在多行編輯框中使正文居中。 ES_LEFT 左對齊正文。 ES_LOWERCASE 把用戶輸入的字母統(tǒng)統(tǒng)轉(zhuǎn)換成小寫字母。 ES_MULTILINE 指定一個多行編輯器。若多行編輯器不指定ES_AUTOHSCROLL風(fēng)格,則會自動換行,若不指定ES_AUTOVSCROLL,則多行編輯器會在窗口中正文裝滿時發(fā)出警告聲響。 ES_NOHIDESEL 缺省時,當(dāng)編輯框失去輸入焦點后會隱藏所選的正文,當(dāng)獲得輸入焦點時又顯示出來。設(shè)置該風(fēng)格可禁止這種缺省行為。 ES_OEMCONVERT 使編輯框中的正文可以在ANSI字符集和OEM字符集之間相互轉(zhuǎn)換。這在編輯框中包含文件名時是很有用的。 ES_PASSWORD 使所有鍵入的字符都用“*”來顯示。 ES_RIGHT 右對齊正文。 ES_UPPERCASE 把用戶輸入的字母統(tǒng)統(tǒng)轉(zhuǎn)換成大寫字母。 ES_READONLY 將編輯框設(shè)置成只讀的。 ES_WANTRETURN 使多行編輯器接收回車鍵輸入并換行。如果不指定該風(fēng)格,按回車鍵會選擇缺省的命令按鈕,這往往會導(dǎo)致對話框的關(guān)閉。 除了上表中的風(fēng)格外,一般還要為控件指定WS_CHILD、WS_VISIBLE、WS_TABSTOP和WS_BORDER窗口風(fēng)格,WS_BORDER使控件帶邊框。創(chuàng)建一個普通的單行編輯框應(yīng)指定風(fēng)格為WS_CHILD|WS_VISIBLE|WS_TABSTOP |WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,這將創(chuàng)建一個帶邊框、左對齊正文、可水平滾動的單行編輯器。要創(chuàng)建一個普通多行編輯框,還要附加ES_MULTILINE|ES_WANTRETURN|ES_AUTOVSCROLL |WS_HSCROLL| WS_VSCROLL風(fēng)格,這將創(chuàng)建一個可水平和垂直滾動的,帶有水平和垂直滾動條的多行編輯器。 對于用對話框模板編輯器創(chuàng)建的編輯框控件,可以在控件的屬性對話框中指定表6.6中列出的控件風(fēng)格。例如,在屬性對話框中選擇Multi-line項,相當(dāng)與指定了ES_MULTILINE風(fēng)格。 編輯框支持剪貼板操作。CEdit類提供了一些與剪貼板有關(guān)的成員函數(shù),如表6.7所示。 表6.7 與剪切板有關(guān)的CEdit成員函數(shù) 函數(shù)聲明 用途 void Clear( ) 清除編輯框中被選擇的正文。 void Copy( ) 把在編輯框中選擇的正文拷貝到剪貼板中。 void Cut( ) 清除編輯框中被選擇的正文并把這些正文拷貝到剪貼板中。 void Paste( ) 將剪貼板中的正文插入到編輯框的當(dāng)前插入符處。 BOOL Undo( ) 撤消上一次鍵入。對于單行編輯框,該函數(shù)總返回TRUE,對于多行編輯框,返回TRUE表明操作成功,否則返回FALSE。 可以用下列CEdit或CWnd類的成員函數(shù)來查詢編輯框。在學(xué)習(xí)下面的函數(shù)時,讀者會經(jīng)常遇到術(shù)語字符索引.字符的字符索引是指從編輯框的開頭字符開始的字符編號,它是從零開始編號的.也就是說,字符索引實際上是指當(dāng)把整個編輯正文看作一個字符串?dāng)?shù)組時,該字符所在的數(shù)組元素的下標(biāo). int GetWindowText( LPTSTR lpszStringBuf, int nMaxCount ) const; void GetWindowText( CString& rString ) const; 這兩個函數(shù)均是CWnd類的成員函數(shù),可用來獲得窗口的標(biāo)題或控件中的正文。第一個版本的函數(shù)用lpszStringBuf參數(shù)指向的字符串?dāng)?shù)組作為拷貝正文的緩沖區(qū),參數(shù)nMaxCount可以拷貝到緩沖區(qū)中的最大字符數(shù),該函數(shù)返回以字節(jié)為單位的實際拷貝字符數(shù)(不包括結(jié)尾的空字節(jié))。第二個版本的函數(shù)用一個CString對象作為緩沖區(qū)。 int GetWindowTextLength( ) const; CWnd的成員函數(shù),可用來獲得窗口的標(biāo)題或控件中的正文的長度。 DWORD GetSel( ) const; void GetSel( int& nStartChar, int& nEndChar ) const; 兩個函數(shù)都是CEdit的成員函數(shù),用來獲得所選正文的位置。GetSel的第一個版本返回一個DWORD值,其中低位字說明了被選擇的正文開始處的字符索引,高位字說明了選擇的正文結(jié)束處的后面一個字符的字符索引,如果沒有正文被選擇,那么返回的低位和高位字節(jié)都是當(dāng)前插入符所在字符的字符索引。GetSel的第二個版本的兩個參數(shù)是兩個引用,其含義與第一個版本函數(shù)返回值的低位和高位字相同。 int LineFromChar( int nIndex = –1 ) const; CEdit的成員函數(shù),僅用于多行編輯框,用來返回指定字符索引所在行的行索引(從零開始編號)。參數(shù)nIndex指定了一個字符索引,如果nIndex是-1,那么函數(shù)將返回選擇正文的第一個字符所在行的行號,若沒有正文被選擇,則該函數(shù)會返回當(dāng)前的插入符所在行的行號。 int LineIndex( int nLine = –1 ) const; CEdit的成員函數(shù),僅用于多行編輯框,用來獲得指定行的開頭字符的字符索引,如果指定行超過了編輯框中的最大行數(shù),該函數(shù)將返回-1。參數(shù)nLine是指定了從零開始的行索引,如果它的值為-1,則函數(shù)返回當(dāng)前的插入符所在行的字符索引。 int GetLineCount( ) const; CEdit的成員函數(shù),僅用于多行編輯框,用來獲得正文的行數(shù)。如果編輯框是空的,那么該函數(shù)的返回值是1。 int LineLength( int nLine = –1 ) const; CEdit的成員函數(shù),用于獲取指定字符索引所在行的字節(jié)長度(行尾的回車和換行符不計算在內(nèi))。參數(shù)nLine說明了字符索引.如果nLine的值為-1,則函數(shù)返回當(dāng)前行的長度(假如沒有正文被選擇),或選擇正文占據(jù)的行的字符總數(shù)減去選擇正文的字符數(shù)(假如有正文被選擇)。若用于單行編輯框,則函數(shù)返回整個正文的長度。 int GetLine( int nIndex, LPTSTR lpszBuffer ) const; int GetLine( int nIndex, LPTSTR lpszBuffer, int nMaxLength ) const; CEdit的成員函數(shù),僅用于多行編輯框,用來獲得指定行的正文(不包括行尾的回車和換行符)。參數(shù)nIndex是行號,lpszBuffer指向存放正文的緩沖區(qū),nMaxLength規(guī)定了拷貝的最大字節(jié)數(shù),若。函數(shù)返回實際拷貝的字節(jié)數(shù),若指定的行號大于編輯框的實際行數(shù),則函數(shù)返回0。需要注意的是,GetLine函數(shù)不會在緩沖區(qū)中字符串的末尾加字符串結(jié)束符(NULL). 下列CWnd或CEdit類的成員函數(shù)可用來修改編輯框控件。 void SetWindowText( LPCTSTR lpszString ); CWnd的成員函數(shù),可用來設(shè)置窗口的標(biāo)題或控件中的正文。參數(shù)lpszString可以是一個CString對象,或是一個指向字符串的指針。 void SetSel( DWORD dwSelection, BOOL bNoScroll = FALSE ); void SetSel( int nStartChar, int nEndChar, BOOL bNoScroll = FALSE ); CEdit的成員函數(shù),用來選擇編輯框中的正文。參數(shù)dwSelection的低位字說明了選擇開始處的字符索引,高位字說明了選擇結(jié)束處的字符索引。如果低位字為0且高位字節(jié)為-1,那么就選擇所有的正文,如果低位字節(jié)為-1,則取消所有的選擇.參數(shù)bNoScroll的值如果是FALSE,則滾動插入符并使之可見,否則就不滾動.參數(shù)nStartChar和nEndChar的含義與參數(shù)dwSelection的低位字和高位字相同. void ReplaceSel( LPCTSTR lpszNewText, BOOL bCanUndo = FALSE ); CEdit的成員函數(shù),用來將所選正文替換成指定的正文.參數(shù)lpszNewText指向用來替換的字符串.參數(shù)bCanUndo的值為TRUE說明替換是否可以被撤消的. 在調(diào)用上述函數(shù)時,如果涉及的是一個多行編輯框,那么除了LineLength和GetLine函數(shù)外,都要把回車和換行符考慮在內(nèi).例如,假設(shè)在編輯框中有如下幾行正文: abcd efg ij 那么字母"e"的字符索引是6而不是4,因為"abcd"后面還有一對回車換行符.調(diào)用LineLength(7)會返回第二行的長度3.調(diào)用LineIndex(2)會得到11.調(diào)用LineFromChar(8)會返回1.如果沒有選擇任何正文,并且插入符在字母"e"上,那么調(diào)用GetSel返回值的低位和高位字都是6. 通過分析上述函數(shù),我們可以總結(jié)出一些查詢和設(shè)置編輯框的方法. 調(diào)用CWnd的成員函數(shù)GetWindowText和SetWindowText可以查詢和設(shè)置編輯框的整個正文,在上一章的Register程序中,我們就使用過這兩個函數(shù). 如果想對多行編輯框逐行查詢,那么應(yīng)該先調(diào)用GetLineCount獲得總行數(shù),然后再調(diào)用GetLine來獲取每一行的正文.下面一段代碼演示了如何對多行編輯框進行逐行查詢. char buf[40]; int total=MyEdit.GetLineCount(); int i,length; for(i=0;i<total;i++) { length=MyEdit.GetLine(i,buf,39); buf[length]=0; //加字符串結(jié)束符 . . . . . . } 可以利用LineIndex和LineFromChar來在字符索引和字符的行列坐標(biāo)之間相互轉(zhuǎn)換.下列代碼演示了在已知字符索引的情況下,如何獲得對應(yīng)的行列坐標(biāo): int row,column; row=MyEdit.LineFromChar(charIndex); column=charIndex-MyEdit.LineIndex(row); 下列代碼演示了在已知字符的行列坐標(biāo)的情況下,如何獲得對應(yīng)的字符索引: int charIndex; charIndex=MyEdit.LineIndex(row)+column; 不難看出字符索引與對應(yīng)的行列坐標(biāo)的關(guān)系是:字符索引=LineIndex(行坐標(biāo))+列坐標(biāo). 對于選擇正文的查詢和設(shè)置,應(yīng)該利用函數(shù)GetSel、SetSel和ReplaceSel. 可以利用GetSel和SetSel來查詢和設(shè)置插入符的位置.SetSel可以使編輯框滾動到插入符的新位置. 要獲取插入符的行列坐標(biāo),可用下面的代碼實現(xiàn): MyEdit.SetSel(-1,0); //取消正文的選擇 int start,end,row,column; MyEdit.GetSel(start,end); //start或end的值就是插入符的字符索引 row=MyEdit.LineFromChar(start); //獲取插入符的行坐標(biāo) column=start-MyEdit.LineIndex(row); //獲取插入符的列坐標(biāo) 下面的代碼演示了如何把插入符移到指定的行和列: MyEdit.SetSel(-1,0); //取消正文的選擇 int charIndex=MyEdit.LineIndex(row)+column; MyEdit.SetSel(charIndex,charIndex); 可以利用ReplaceSel函數(shù)在 插入符處插入正文,典型的代碼如下所示: MyEdit.SetSel(-1,0); //取消正文的選擇 MyEdit.ReplaceSel(“......”); 可以利用ReplaceSel清除編輯框中的正文,典型的代碼如下所示: MyEdit.SetSel(0,-1); //選擇全部正文 MyEdit.ReplaceSel(“”); 在后面的小節(jié)中,讀者將會看到使用編輯框的例子. .1.5 滾動條控件 滾動條(Scroll Bar)主要用來從某一預(yù)定義值范圍內(nèi)快速有效地進行選擇.滾動條分垂直滾動條和水平滾動條兩種.在滾動條內(nèi)有一個滾動框,用來表示當(dāng)前的值.用鼠標(biāo)單擊滾動條,可以使?jié)L動框移動一頁或一行,也可以直接拖動滾動框.滾動條既可以作為一個獨立控件存在,也可以作為窗口、列表框和組合框的一部分.Windows 95的滾動條支持比例滾動框,即用滾動框的大小來反映頁相對于整個范圍的大?。甒indows 3.x使用單獨的滾動條控件來調(diào)整調(diào)色板、鍵盤速度以及鼠標(biāo)靈敏度,在Windows 95中,滾動條控件被軌道條取代(參見6.2.3)不提倡使用單獨的滾動條控件. 需要指出的是,從性質(zhì)上劃分,滾動條可分為標(biāo)準(zhǔn)滾動條和滾動條控件兩種.標(biāo)準(zhǔn)滾動條是由WS_HSCROLL或WS_VSCROLL風(fēng)格指定的,它不是一個實際的窗口,而是窗口的一個組成部分(例如列表框中的滾動條),只能位于窗口的右側(cè)(垂直滾動條)或底端(水平滾動條).標(biāo)準(zhǔn)滾動條是在窗口的非客戶區(qū)中創(chuàng)建的.與之相反,滾動條控件并不是窗口的一個零件,而是一個實際的窗口,可以放置在窗口客戶區(qū)的任意地方,它既可以獨立存在,也可以與某一個窗口組合,行使?jié)L動窗口的職能.由于滾動條控件是一個獨立窗口,因此可以擁有輸入焦點,可以響應(yīng)光標(biāo)控制鍵,如PgUp、PgDown、Home和End. MFC的CScrollBar類封裝了滾動條控件.CScrollBar類的Create成員函數(shù)負責(zé)創(chuàng)建控件,該函數(shù)的聲明為 BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 參數(shù)dwStyle指定了控件的風(fēng)格.rect說明了控件的位置和尺寸.pParentWnd指向父窗口,該參數(shù)不能為NULL。nID則說明了控件的ID。如果創(chuàng)建成功,該函數(shù)返回TRUE,否則返回FALSE. 要創(chuàng)建一個普通的水平滾動條控件,應(yīng)指定風(fēng)格WS_CHILD|WS_VISIBLE|BS_HORZ.要創(chuàng)建一個普通的垂直滾動條控件,應(yīng)指定風(fēng)格WS_CHILD|WS_VISIBLE|BS_VERT. 主要的CScrollBar類成員函數(shù)如下所示: int GetScrollPos( ) const; 該函數(shù)返回滾動框的當(dāng)前位置.若操作失敗則返回0. int SetScrollPos( int nPos, BOOL bRedraw = TRUE ); 該函數(shù)將滾動框移動到指定位置.參數(shù)nPos指定了新的位置.參數(shù)bRedraw表示是否需要重繪滾動條,如果為TRUE,則重繪之.函數(shù)返回滾動框原來的位置.若操作失敗則返回0. void GetScrollRange( LPINT lpMinPos, LPINT lpMaxPos ) const; 該函數(shù)對滾動條的滾動范圍進行查詢.參數(shù)lpMinPos和lpMaxPos分別指向滾動范圍的最小最大值. void SetScrollRange( int nMinPos, int nMaxPos, BOOL bRedraw = TRUE ); 該函數(shù)用于指定滾動條的滾動范圍.參數(shù)nMinPos和nMaxPos分別指定了滾動范圍的最小最大值.由這兩者指定的滾動范圍不得超過32767.當(dāng)兩者都為0時,滾動條將被隱藏.參數(shù)bRedraw表示是否需要重繪滾動條,如果為TRUE,則重繪之. BOOL GetScrollInfo( LPSCROLLINFO lpScrollInfo, UINT nMask ); 該函數(shù)用來獲取滾動條的各種狀態(tài),包括滾動范圍、滾動框的位置和頁尺寸.參數(shù)lpScrollInfo指向一個SCROLLINFO結(jié)構(gòu),該結(jié)構(gòu)如下所示: typedef struct tagSCROLLINFO { UINT cbSize; //結(jié)構(gòu)的尺寸(字節(jié)為單位) UINT fMask; /*說明結(jié)構(gòu)中的哪些參數(shù)是有效的,可以是屏蔽值的組合, 如SIF_POS|SIF_PAGE,若為SIF_ALL則整個結(jié)構(gòu)都有效*/ int nMin; //滾動范圍最大值,當(dāng)fMask中包含SIF_RANGE時有效 int nMax; //滾動范圍最小值,當(dāng)fMask中包含SIF_RANGE時有效 UINT nPage; /*頁尺寸,用來確定比例滾動框的大小,當(dāng)fMask中包含 SIF_PAGE時有效*/ int nPos; //滾動框的位置,當(dāng)fMask中包含SIF_POS有效 int nTrackPos; /*拖動時滾動框的位置,當(dāng)fMask中包含 SIF_TRACKPOS時有效,該參數(shù)只能查詢,不能設(shè) 置,最好不要用該參數(shù)來查詢拖動時滾動框的位置*/ } SCROLLINFO; typedef SCROLLINFO FAR *LPSCROLLINFO; 參數(shù)nMask的意義與SCROLLINFO結(jié)構(gòu)中的fMask相同.函數(shù)在獲得有效值后返回TRUE,否則返回FALSE. BOOL SetScrollInfo( LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE ); 該函數(shù)用于設(shè)置滾動條的各種狀態(tài),一個重要用途是設(shè)定頁尺寸從而實現(xiàn)比例滾動框.參數(shù)lpScrollInfo指向一個SCROLLINFO結(jié)構(gòu),參數(shù)bRedraw表示是否需要重繪滾動條,如果為TRUE,則重繪之.若操作成功,該函數(shù)返回TRUE,否則返回FALSE. CWnd類也提供了一些函數(shù)來查詢和設(shè)置所屬的標(biāo)準(zhǔn)滾動條.這些函數(shù)與CScrollBar類的函數(shù)同名,且功能相同,但每個函數(shù)都多了一個參數(shù),用來選擇滾動條.例如,CWnd:: GetScrollPos 的聲明為 int GetScrollPos( int nBar ) const; 參數(shù)nBar用來選擇滾動條,可以為下列值: SB_HORZ //指定水平滾動條 SB_VERT //指定垂直滾動條 無論是標(biāo)準(zhǔn)滾動條,還是滾動條控件,滾動條的通知消息都是用WM_HSCROLL和WM_VSCROLL消息發(fā)送出去的.對這兩個消息的確省處理函數(shù)是CWnd::OnHScroll和CWnd::OnVScroll,它們幾乎什么也不做.一般需要在派生類中對這兩個函數(shù)從新設(shè)計,以實現(xiàn)滾動功能.這兩個函數(shù)的聲明為 afx_msg void OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ); afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ); 參數(shù)nSBCode是通知消息碼,如表6.8所示.nPos是滾動框的位置,只有在nSBCode為SB_THUMBPOSITION或SB_THUMBTRACK時,該參數(shù)才有意義.如果通知消息是滾動條控件發(fā)來的,那么pScrollBar是指向該控件的指針,如果是標(biāo)準(zhǔn)滾動條發(fā)來的,則pScrollBar為NULL. 表6.8 滾動條的通知消息碼 消息 含義 SB_BOTTOM / SB_RIGHT(二者的消息碼是一樣的,因此可以混用,下同) 滾動到底端(右端). SB_TOP / SB_LEFT 滾動到頂端(左端). SB_LINEDOWN / SB_LINERIGHT 向下(向右)滾動一行(列). SB_LINEUP / SB_LINELEFT 向上(向左)滾動一行(列). SB_PAGEDOWN / SB_PAGERIGHT 向下(向右)滾動一頁. SB_PAGEUP / SB_PAGELEFT 向上(向左)滾動一頁. SB_THUMBPOSITION 滾動到指定位置. SB_THUMBTRACK 滾動框被拖動.可利用該消息來跟蹤對滾動框的拖動. SB_ENDSCROLL 滾動結(jié)束. 6.1.8小節(jié)的例子中,讀者將學(xué)會如何使用滾動條以及如何編寫自己的OnHScroll函數(shù). 6.1.6 列表框控件 列表框主要用于輸入,它允許用戶從所列出的表項中進行單項或多項選擇,被選擇的項呈高亮度顯示.列表框具有邊框,并且一般帶有一個垂直滾動條.列表框分單選列表框和多重選擇列表框兩種.單選列表框一次只能選擇一個列表項,而多重選擇列表框可以進行多重選擇.對于列表項的選擇,微軟公司有如下建議: 單擊鼠標(biāo)選擇一個列表項,單擊一個按鈕來處理選擇的項. 雙擊鼠標(biāo)選擇一個列表項是處理選擇項的快捷方法. 列表框會向父窗口發(fā)送如表6.9所示的通知消息. 表6.9 列表框控件的通知消息 消息 含義 LBN_DBLCLK 用戶用鼠標(biāo)雙擊了一列表項.只有具有LBS_NOTIFY的列表框才能發(fā)送該消息. LBN_ERRSPACE 列表框不能申請足夠的動態(tài)內(nèi)存來滿足需要. LBN_KILLFOCUS 列表框失去輸入焦點. LBN_SELCANCEL 當(dāng)前的選擇被取消.只有具有LBS_NOTIFY的列表框才能發(fā)送該消息. LBN_SELCHANGE 單擊鼠標(biāo)選擇了一列表項.只有具有LBS_NOTIFY的列表框才能發(fā)送該消息. LBN_SETFOCUS 列表框獲得輸入焦點. WM_CHARTOITEM 當(dāng)列表框收到WM_CHAR消息后,向父窗口發(fā)送該消息.只有具有LBS_WANTKEYBOARDINPUT風(fēng)格的列表框才會發(fā)送該消息. WM_VKEYTOITEM 當(dāng)列表框收到WM_KEYDOWN消息后,向父窗口發(fā)送該消息.只有具有LBS_WANTKEYBOARDINPUT風(fēng)格的列表框才會發(fā)送該消息. MFC的CListBox類封裝了列表框.CListBox類的Create成員函數(shù)負責(zé)列表框的創(chuàng)建,該函數(shù)的聲明是 BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 參數(shù)dwStyle指定了列表框控件的風(fēng)格,如表6.10所示,dwStyle可以是這些風(fēng)格的組合.rect說明了控件的位置和尺寸.pParentWnd指向父窗口,該參數(shù)不能為NULL。nID則說明了控件的ID。如果創(chuàng)建成功,該函數(shù)返回TRUE,否則返回FALSE. 表6.10 列表框控件的風(fēng)格 控件風(fēng)格 含義 LBS_EXTENDEDSEL 支持多重選擇.在點擊列表項時按住Shift鍵或Ctrl鍵即可選擇多個 項. LBS_HASSTRINGS 指定一個含有字符串的自繪式列表框. LBS_MULTICOLUMN 指定一個水平滾動的多列列表框,通過調(diào)用CListBox::SetColumnWidth來設(shè)置每列的寬度. LBS_MULTIPLESEL 支持多重選擇.列表項的選擇狀態(tài)隨著用戶對該項單擊或雙擊鼠標(biāo)而翻轉(zhuǎn). LBS_NOINTEGRALHEIGHT 列表框的尺寸由應(yīng)用程序而不是Windows指定.通常,Windows指定尺寸會使列表項的某些部分隱藏起來. LBS_NOREDRAW 當(dāng)選擇發(fā)生變化時防止列表框被更新,可發(fā)送WM_SETREDRAW來改變該風(fēng)格. LBS_NOTIFY 當(dāng)用戶單擊或雙擊鼠標(biāo)時通知父窗口. LBS_OWNERDRAWFIXED 指定自繪式列表框,即由父窗口負責(zé)繪制列表框的內(nèi)容,并且列表項有相同的高度. LBS_OWNERDRAWVARIABLE 指定自繪式列表框,并且列表項有不同的高度. LBS_SORT 使插入列表框中的項按升序排列. LBS_STANDARD 相當(dāng)于指定了WS_BORDER|WS_VSCROLL|LBS_SORT |LBS_NOTIFY. LBS_USETABSTOPS 使列表框在顯示列表項時識別并擴展制表符(‘\t’),缺省的制表寬度是32個對話框單位. LBS_WANTKEYBOARDINPUT 允許列表框的父窗口接收WM_VKEYTOITEM和WM_CHARTOITEM消息,以響應(yīng)鍵盤輸入. LBS_DISABLENOSCROLL 使列表框在不需要滾動時顯示一個禁止的垂直滾動條. 除了上表中的風(fēng)格外,一般還要為列表框控件指定WS_CHILD、WS_VISIBLE、WS_TABSTOP、WS_BORDER和WS_VSCROLL風(fēng)格.要創(chuàng)建一個普通的單選擇列表框,應(yīng)指定的風(fēng)格為WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_STANDARD.要創(chuàng)建一個多重選擇列表框,應(yīng)該在單選擇列表框風(fēng)格的基礎(chǔ)上再加上 LBS_MULTIPLESEL或LBS_ EXTENDEDSEL.如果不希望列表框排序,就不能使用LBS_STANDARD風(fēng)格. 對于用對話框模板編輯器創(chuàng)建的列表框控件,可以在控件的屬性對話框中指定表6.10中列出的控件風(fēng)格。例如,在屬性對話框中選擇Sort項,相當(dāng)與指定了LBS_SORT風(fēng)格。 CListBox類的成員函數(shù)有數(shù)十個之多.我們可以把一些常用的函數(shù)分為三類,在下面列出.需要說明的是,可以用索引來指定列表項,索引是從零開始的. 首先,CListBox成員函數(shù)提供了下列函數(shù)用于插入和刪除列表項. int AddString( LPCTSTR lpszItem ); 該函數(shù)用來往列表框中加入字符串,其中參數(shù)lpszItem指定了要添加的字符串.函數(shù)的返回值是加入的字符串在列表框中的位置,如果發(fā)生錯誤,會返回LB_ERR或LB_ERRSPACE(內(nèi)存不夠).如果列表框未設(shè)置LBS_SORT風(fēng)格,那么字符串將被添加到列表的末尾,如果設(shè)置了LBS_SORT風(fēng)格,字符串會按排序規(guī)律插入到列表中. int InsertString( int nIndex, LPCTSTR lpszItem ); 該函數(shù)用來在列表框中的指定位置插入字符串.參數(shù)nIndex給出了插入位置(索引),如果值為-1,則字符串將被添加到列表的末尾.參數(shù)lpszItem指定了要插入的字符串.函數(shù)返回實際的插入位置,若發(fā)生錯誤,會返回LB_ERR或LB_ERRSPACE.與AddString函數(shù)不同,InsertString函數(shù)不會導(dǎo)致LBS_SORT風(fēng)格的列表框重新排序.不要在具有LBS_SORT風(fēng)格的列表框中使用InsertString函數(shù),以免破壞列表項的次序. int DeleteString( UINT nIndex ); 該函數(shù)用于刪除指定的列表項,其中參數(shù)nIndex指定了要刪除項的索引.函數(shù)的返回值為剩下的表項數(shù)目,如果nIndex超過了實際的表項總數(shù),則返回LB_ERR. void ResetContent( ); 該函數(shù)用于清除所有列表項. int Dir( UINT attr, LPCTSTR lpszWildCard ); 該函數(shù)用來向列表項中加入所有與指定通配符相匹配的文件名或驅(qū)動器名.參數(shù)attr為文件類型的組合,如表6.11所示.參數(shù)lpszWildCard指定了通配符(如*.cpp,*.*等). 表6.11 Dir函數(shù)attr參數(shù)的含義 值 含義 0x0000 普通文件(可讀寫的文件). 0x0001 只讀文件. 0x0002 隱藏文件. 0x0004 系統(tǒng)文件. 0x0010 目錄. 0x0020 文件的歸檔位已被設(shè)置. 0x4000 包括了所有與通配符相匹配的驅(qū)動器. 0x8000 排除標(biāo)志.若指定該標(biāo)志,則只列出指定類型的文件名,否則,先要列出普通文件,然后再列出指定的文件. 下列的CListBox成員函數(shù)用于搜索、查詢和設(shè)置列表框. int GetCount( ) const; 該函數(shù)返回列表項的總數(shù),若出錯則返回LB_ERR. int FindString( int nStartAfter, LPCTSTR lpszItem ) const; 該函數(shù)用于對列表項進行與大小寫無關(guān)的搜索.參數(shù)nStartAfter指定了開始搜索的位置, 合理指定nStartAfter可以加快搜索速度,若nStartAfter為-1,則從頭開始搜索整個列表.參數(shù)lpszItem指定了要搜索的字符串.函數(shù)返回與lpszItem指定的字符串相匹配的列表項的索引,若沒有找到匹配項或發(fā)生了錯誤,函數(shù)會返回LB_ERR.FindString函數(shù)先從nStartAfter指定的位置開始搜索,若沒有找到匹配項,則會從頭開始搜索列表.只有找到匹配項,或?qū)φ麄€列表搜索完一遍后,搜索過程才會停止,所以不必擔(dān)心會漏掉要搜索的列表項. int GetText( int nIndex, LPTSTR lpszBuffer ) const; void GetText( int nIndex, CString& rString ) const; 用于獲取指定列表項的字符串.參數(shù)nIndex指定了列表項的索引.參數(shù)lpszBuffer指向一個接收字符串的緩沖區(qū).引用參數(shù)rString則指定了接收字符串的CString對象.第一個版本的函數(shù)會返回獲得的字符串的長度,若出錯,則返回LB_ERR. int GetTextLen( int nIndex ) const; 該函數(shù)返回指定列表項的字符串的字節(jié)長度.參數(shù)nIndex指定了列表項的索引.若出錯則返回LB_ERR. DWORD GetItemData( int nIndex ) const; 每個列表項都有一個32位的附加數(shù)據(jù).該函數(shù)返回指定列表項的附加數(shù)據(jù),參數(shù)nIndex指定了列表項的索引.若出錯則函數(shù)返回LB_ERR. int SetItemData( int nIndex, DWORD dwItemData ); 該函數(shù)用來指定某一列表項的32位附加數(shù)據(jù).參數(shù)nIndex指定了列表項的索引.dwItemData是要設(shè)置的附加數(shù)據(jù)值. 提示:列表項的32位附加數(shù)據(jù)可用來存儲與列表項相關(guān)的數(shù)據(jù),也可以放置指向相關(guān)數(shù)據(jù)的指針.這樣,當(dāng)用戶選擇了一個列表項時,程序可以從附加數(shù)據(jù)中快速方便地獲得與列表項相關(guān)的數(shù)據(jù). int GetTopIndex( ) const; 該函數(shù)返回列表框中第一個可見項的索引,若出錯則返回LB_ERR. int SetTopIndex( int nIndex ); 用來將指定的列表項設(shè)置為列表框的第一個可見項,該函數(shù)會將列表框滾動到合適的位置.參數(shù)nIndex指定了列表項的索引.若操作成功,函數(shù)返回0值,否則返回LB_ERR. 提示:由于列表項的內(nèi)容一般是不變的,故CListBox未提供更新列表項字符串的函數(shù).如果要改變某列表項的內(nèi)容,可以先調(diào)用DeleteString刪除該項,然后再用InsertString或AddString將更新后的內(nèi)容插入到原來的位置. 下列CListBox的成員函數(shù)與列表項的選擇有關(guān). int GetSel( int nIndex ) const; 該函數(shù)返回指定列表項的狀態(tài).參數(shù)nIndex指定了列表項的索引.如果查詢的列表項被選擇了,函數(shù)返回一個正值,否則返回0,若出錯則返回LB_ERR. int GetCurSel( ) const; 該函數(shù)僅適用于單選擇列表框,用來返回當(dāng)前被選擇項的索引,如果沒有列表項被選擇或有錯誤發(fā)生,則函數(shù)返回LB_ERR. int SetCurSel( int nSelect ); 該函數(shù)僅適用于單選擇列表框,用來選擇指定的列表項.該函數(shù)會滾動列表框以使選擇項可見.參數(shù)nIndex指定了列表項的索引,若為-1,那么將清除列表框中的選擇.若出錯函數(shù)返回LB_ERR. int SelectString( int nStartAfter, LPCTSTR lpszItem ); 該函數(shù)僅適用于單選擇列表框,用來選擇與指定字符串相匹配的列表項.該函數(shù)會滾動列表框以使選擇項可見.參數(shù)的意義及搜索的方法與函數(shù)FindString類似.如果找到了匹配的項,函數(shù)返回該項的索引,如果沒有匹配的項,函數(shù)返回LB_ERR并且當(dāng)前的選擇不被改變. int GetSelCount( ) const; 該函數(shù)僅用于多重選擇列表框,它返回選擇項的數(shù)目,若出錯函數(shù)返回LB_ERR. int SetSel( int nIndex, BOOL bSelect = TRUE ); 該函數(shù)僅適用于多重選擇列表框,它使指定的列表項選中或落選.參數(shù)nIndex指定了列表項的索引,若為-1,則相當(dāng)于指定了所有的項.參數(shù)bSelect為TRUE時選中列表項,否則使之落選.若出錯則返回LB_ERR. int GetSelItems( int nMaxItems, LPINT rgIndex ) const; 該函數(shù)僅用于多重選擇列表框,用來獲得選中的項的數(shù)目及位置.參數(shù)nMaxItems說明了參數(shù)rgIndex指向的數(shù)組的大?。畢?shù)rgIndex指向一個緩沖區(qū),該數(shù)組是一個整型數(shù)組,用來存放選中的列表項的索引.函數(shù)返回放在緩沖區(qū)中的選擇項的實際數(shù)目,若出錯函數(shù)返回LB_ERR. int SelItemRange( BOOL bSelect, int nFirstItem, int nLastItem ); 該函數(shù)僅用于多重選擇列表框,用來使指定范圍內(nèi)的列表項選中或落選.參數(shù)nFirstItem和nLastItem指定了列表項索引的范圍.如果參數(shù)bSelect為TRUE,那么就選擇這些列表項,否則就使它們落選.若出錯函數(shù)返回LB_ERR. 在6.1.8小節(jié)的例子中,讀者將會看到對列表框的測試. 6.1.7 組合框控件 組合框把一個編輯框和一個單選擇列表框結(jié)合在了一起.用戶既可以在編輯框中輸入,也可以從列表框中選擇一個列表項來完成輸入.如上一章所提到的,組合框分為簡易式(Simple)、下拉式(Dropdown)和下拉列表式(Drop List)三種.簡易式組合框包含一個編輯框和一個總是顯示的列表框。下拉式組合框同簡易式組合框類似,二者的區(qū)別在于僅當(dāng)單擊下滾箭頭后列表框才會彈出。下拉列表式組合框也有一個下拉的列表框,但它的編輯框是只讀的,不能輸入字符。 Windows中比較常用的是下拉式和下拉列表式組合框,在Developer Studio中就大量使用了這兩種組合框.二者都具有占地小的特點,這在界面日益復(fù)雜的今天是十分重要的.下拉列表式組合框的功能與列表框類似.下拉式組合框的典型應(yīng)用是作為記事列表框使用,既把用戶在編輯框中敲入的東西存儲到列表框組件中,這樣當(dāng)用戶要重復(fù)同樣的輸入時,可以從列表框組件中選取而不必在編輯框組件中從新輸入.在Developer Studio中的Find對話框中就可以找到一個典型的下拉式組合框. 要設(shè)計一個記事列表框,應(yīng)采取下列原則: 在創(chuàng)建組合框時指定CBS_DROPDOWNLIST風(fēng)格. 要限制列表項的數(shù)目,以防止內(nèi)存不夠. 如果在編輯框中輸入的字符串不能與列表框組件中的列表項匹配,那么應(yīng)該把該字符串插入到列表框中的0位置處.最老的項處于列表的末尾.如果列表項的數(shù)目超出了限制,則應(yīng)把最老的項刪除. 如果在編輯框中輸入的字符串可以與列表框組件中的某一項完全匹配,則應(yīng)該先把該項從列表的當(dāng)前位置刪除,然后在將其插入道列表的0位置處. 組合框控件會向父窗口發(fā)送表6.12所示的通知消息. 表6.12 組合框控件的通知消息 消息 含義 CBN_CLOSEUP 組合框的列表框組件被關(guān)閉.簡易式組合框不會發(fā)出該消息. CBN_DBLCLK 用戶在某列表項上雙擊鼠標(biāo).只有簡易式組合框才會發(fā)出該消息. CBN_DROPDOWN 組合框的列表框組件下拉.簡易式組合框不會發(fā)出該消息. CBN_EDITCHANGE 編輯框的內(nèi)容被用戶改變了。與CBN_EDITUPDATE不同,該消息是在編輯框顯示的正文被刷新后才發(fā)出的。下拉列表式組合框不會發(fā)出該消息. CBN_EDITUPDATE 在編輯框準(zhǔn)備顯示改變了的正文時發(fā)送該消息。下拉列表式組合框不會發(fā)出該消息. CBN_ERRSPACE 組合框無法申請足夠的內(nèi)存來容納列表項. CBN_SELENDCANCEL 表明用戶的選擇應(yīng)該取消.當(dāng)用戶在列表框中選擇了一項,然后又在組合框控件外單擊鼠標(biāo)時就會導(dǎo)致該消息的發(fā)送. CBN_SELENDOK 用戶選擇了一項,然后按了回車鍵或單擊了下滾箭頭.該消息表明用戶確認了自己所作的選擇. CBN_KILLFOCUS 組合框失去了輸入焦點. CBN_SELCHANGE 用戶通過點擊或移動箭頭鍵改變了列表的選擇. CBN_SETFOCUS 組合框獲得了輸入焦點. MFC的CComboBox類封裝了組合框.需要指出的是,雖然組合框是編輯框和列表框的選擇,但是CComboBox類并不是CEdit類和CListBox類的派生類,而是CWnd類的派生類. CComboBox的成員函數(shù)Create負責(zé)創(chuàng)建組合框,該函數(shù)的說明如下: BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 參數(shù)dwStyle指定了組合框控件的風(fēng)格,如表6.10所示,dwStyle可以是這些風(fēng)格的組合.rect說明的是列表框組件下拉后組合框的位置和尺寸.pParentWnd指向父窗口,該參數(shù)不能為NULL。nID則說明了控件的ID。如果創(chuàng)建成功,該函數(shù)返回TRUE,否則返回FALSE. 提示:在用Create函數(shù)創(chuàng)建組合框時,參數(shù)rect說明的是包括列表框組件在內(nèi)的組合框的位置和尺寸,而不是列表框組件隱藏時的編輯框組件尺寸.要設(shè)置編輯框組件的高度,可以調(diào)用成員函數(shù)SetItemHeight(-1,cyItemHeight),其中參數(shù)cyItemHeight指定了編輯框的高度(以像素為單位). 表6.13 組合框的風(fēng)格 控件風(fēng)格 含義 CBS_AUTOHSCROLL 使編輯框組件具有水平滾動的風(fēng)格. CBS_DROPDOWN 指定一個下拉式組合框. CBS_DROPDOWNLIST 指定一個下拉列表式組合框. CBS_HASSTRINGS 指定一個含有字符串的自繪式組合框. CBS_OEMCONVERT 使編輯框組件中的正文可以在ANSI字符集和OEM字符集之間相互轉(zhuǎn)換。這在編輯框中包含文件名時是很有用的。 CBS_OWNERDRAWFIXED 指定自繪式組合框,即由父窗口負責(zé)繪制列表框的內(nèi)容,并且列表項有相同的高度. CBS_OWNERDRAWVARIABLE 指定自繪式組合框,并且列表項有不同的高度. CBS_SIIMPLE 指定一個簡易式組合框. CBS_SORT 自動對列表框組件中的項進行排序. CBS_DISABLENOSCROLL 使列表框在不需要滾動時顯示一個禁止的垂直滾動條. CBS_NOINTEGRALHEIGHT 組合框的尺寸由應(yīng)用程序而不是Windows指定.通常,由Windows指定尺寸會使列表項的某些部分隱藏起來. CBS_SIMPLE、CBS_DROPDOWN和CBS_DROPDOWNLIST分別用來將組合框指定為簡易式、下拉式和下拉列表式.一般還要為組合框指定WS_CHILD、WS_VISIBLE、WS_TABSTOP、WS_VSCROLL和CBS_AUTOHSCROLL風(fēng)格.如果要求自動排序,還應(yīng)指定CBS_SORT風(fēng)格. 對于用對話框模板編輯器創(chuàng)建的組合框控件,可以在控件的屬性對話框中指定上表中列出的控件風(fēng)格。例如,在屬性對話框中選擇Dropdown,相當(dāng)于指定了CBS_DROPDOWN. CComboBox類的成員函數(shù)較多.其中常用的函數(shù)可粗分為兩類,分別針對編輯框組件和列表框組件.可以想象,這些函數(shù)與CEdit類和CListBox類的成員函數(shù)肯定有很多類似之處,但它們也會有一些不同的特點.如果讀者能從"組合框是由編輯框和列表框組成"這一概念出發(fā),就能夠很快的掌握CComboBox的主要成員函數(shù). 事實上,絕大部分CComboBox的成員函數(shù)都可以看成是CEdit或CListBox成員函數(shù)的翻版.函數(shù)的功能,函數(shù)名,甚至函數(shù)的參數(shù)都是類似的.為了方便學(xué)習(xí),在下面列出CComboBox類的成員函數(shù)時,采用了與對應(yīng)的CEdit或CListBox成員函數(shù)相比較的做法.在成員函數(shù)的列表中,分別列出了成員函數(shù)名,對應(yīng)的CEdit或CListBox成員函數(shù),以及二者之間的不同之處.不同之處是指函數(shù)的功能、參數(shù)以及返回值有什么差別. 針對編輯框組件的主要成員函數(shù)如表6.14所示.該表的前三個函數(shù)實際上是CWnd類的成員函數(shù),可用來查詢和設(shè)置編輯框組件. 表6.14 針對編輯框組件的CComboBox成員函數(shù) 成員函數(shù)名 對應(yīng)的CEdit成員函數(shù) 與CEdit成員函數(shù)的不同之處 CWnd::GetWindowText CWnd::GetWindowText 無. CWnd::SetWindowText CWnd::SetWindowText 無. CWnd::GetWindowTextLength CWnd::GetWindowTextLength GetEditSel GetSel的第一個版本 僅函數(shù)名不同. SetEditSel SetSel的第二個版本 函數(shù)名不同,且無bNoScroll參數(shù). Clear Clear 無. Copy Copy 無. Cut Cut 無. Paste Paste 無. 與CListBox的成員函數(shù)類似,針對列表框組件的CComboBox成員函數(shù)也可以分為三類.表6.15列出了用于插入和刪除列表項的成員函數(shù),表6.16列出了用于搜索、查詢和設(shè)置列表框的成員函數(shù),與列表項的選擇有關(guān)的成員函數(shù)在表6.17中列出.需要指出的是,如果這些函數(shù)出錯,則反回CB_ERR,而不是LB_ERR.另外,排序的組合框具有的是CBS_SORT風(fēng)格,而不是LBS_SORT. 6.15 用于插入和刪除列表項的CComboBox成員函數(shù) 成員函數(shù)名 對應(yīng)的CListBox成員函數(shù) 與CListBox成員函數(shù)的不同之處 AddString AddString 無. InsertString InsertString 無. DeleteString DeleteString 無. ResetContent ResetContent 無. Dir Dir 無. 6.16 用于搜索、查詢和設(shè)置列表框的CComboBox成員函數(shù) 成員函數(shù)名 對應(yīng)的CListBox成員函數(shù) 與CListBox成員函數(shù)的不同之處 GetCount GetCount 無. FindString FindString 無. GetLBText GetText 僅函數(shù)名不同. GetLBTextLen GetTextLen 僅函數(shù)名不同. GetItemData GetItemData 無. SetItemData SetItemData 無. GetTopIndex GetTopIndex 無. SetTopIndex SetTopIndex 無. 表6.17 與列表項的選擇有關(guān)的CComboBox成員函數(shù) 成員函數(shù)名 對應(yīng)的CListBox成員函數(shù) 與CListBox成員函數(shù)的不同之處 GetCurSel GetCurSel 無. SetCurSel SetCurSel 新選的列表項的內(nèi)容會被拷貝到編輯框組件中. SelectString SelectString 新選的列表項的內(nèi)容會被拷貝到編輯框組件中. 另外,CComboBox的ShowDropDown成員函數(shù)專門負責(zé)顯示或隱藏列表框組件,該函數(shù)的聲明為 void ShowDropDown( BOOL bShowIt = TRUE ); 如果參數(shù)bShowIt的值為TRUE,那么將顯示列表框組件,否則,就隱藏之.該函數(shù)對簡易式組合框沒有作用. |