使用資源--對(duì)話框--在對(duì)話框中使用子窗口控件
8、使用列表框
列表框提供一個(gè)可供用戶選擇的列表,用戶可以一次選擇一個(gè)項(xiàng)目,也可以同時(shí)選中多個(gè)項(xiàng)目。
//Listbox.rc
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <resource.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define ICO_MAIN 0x1000 //圖標(biāo)
#define DLG_MAIN 1
#define IDC_LISTBOX1 101
#define IDC_LISTBOX2 102
#define IDC_SEL1 103
#define IDC_RESET 104
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN ICON "Main.ico"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN DIALOG 163, 160, 190, 108
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "列表框控件示例"
FONT 9, "宋體"
{
LISTBOX IDC_LISTBOX1, 6, 5, 55, 86, LBS_STANDARD
LISTBOX IDC_LISTBOX2, 68, 5, 115, 86, LBS_STANDARD | LBS_MULTIPLESEL
LTEXT "", IDC_SEL1, 6, 93, 55, 8
PUSHBUTTON "復(fù)位(&R)", IDC_RESET, 89, 90, 45, 14
DEFPUSHBUTTON "查看(&S)", IDOK, 139, 90, 45, 14, WS_DISABLED
}
//Listbox.asm
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定義
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ等值定義
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000h
DLG_MAIN equ 1
IDC_LISTBOX1 equ 101
IDC_LISTBOX2 equ 102
IDC_SEL1 equ 103
IDC_RESET equ 104
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 數(shù)據(jù)段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
.const
szText1 db '項(xiàng)目1',0
szText2 db '項(xiàng)目2',0
szText3 db '項(xiàng)目3',0
szPath db '*.*',0
szMessage db '選擇結(jié)果:%s',0
szTitle db '您的選擇',0
szSelect db '您選擇了以下的項(xiàng)目:'
szReturn db 0dh,0ah,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代碼段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain proc uses ebx edi esi hWnd, wMsg, wParam, lParam
local @szBuffer[128]:byte
local @szBuffer1[128]:byte
local @szTextBuff[2048]:byte
local @dwCount
mov eax, wMsg
.if eax == WM_CLOSE
invoke EndDialog, hWnd, NULL
.elseif eax == WM_INITDIALOG
invoke LoadIcon, hInstance, ICO_MAIN
invoke SendMessage, hWnd, WM_SETICON, ICON_BIG, eax
;********************************************************************************
; 初始化列表框
;********************************************************************************
invoke SendDlgItemMessage, hWnd, IDC_LISTBOX1, LB_ADDSTRING, 0, addr szText1
invoke SendDlgItemMessage, hWnd, IDC_LISTBOX1, LB_ADDSTRING, 0, addr szText2
invoke SendDlgItemMessage, hWnd, IDC_LISTBOX1, LB_ADDSTRING, 0, addr szText3
invoke SendDlgItemMessage, hWnd, IDC_LISTBOX2, LB_DIR, DDL_ARCHIVE or DDL_DRIVES or DDL_DIRECTORY, addr szPath
;********************************************************************************
.elseif eax == WM_COMMAND
mov eax, wParam
.if ax == IDOK
invoke SendDlgItemMessage, hWnd, IDC_LISTBOX2, LB_GETSELCOUNT, 0, 0
mov @dwCount, eax
invoke SendDlgItemMessage, hWnd, IDC_LISTBOX2, LB_GETSELITEMS, 128/4, addr @szBuffer
invoke lstrcpy, addr @szTextBuff, addr szSelect
lea esi, @szBuffer
.while @dwCount
lodsd
lea ecx, @szBuffer1
invoke SendDlgItemMessage, hWnd, IDC_LISTBOX2, LB_GETTEXT, eax, ecx
invoke lstrcat, addr @szTextBuff, addr szReturn
invoke lstrcat, addr @szTextBuff, addr @szBuffer1
dec @dwCount
.endw
invoke MessageBox, hWnd, addr @szTextBuff, addr szTitle, MB_OK
.elseif ax == IDC_RESET
invoke SendDlgItemMessage, hWnd, IDC_LISTBOX2, LB_SETSEL, FALSE, -1
.elseif ax == IDC_LISTBOX1
shr eax, 16
.if ax == LBN_SELCHANGE
;********************************************************************************
; 將鼠標(biāo)點(diǎn)擊結(jié)果顯示在文本框中
;********************************************************************************
invoke SendMessage, lParam, LB_GETCURSEL, 0, 0
lea ecx, @szBuffer
invoke SendMessage, lParam, LB_GETTEXT, eax, ecx
invoke SetDlgItemText, hWnd, IDC_SEL1, addr @szBuffer
;********************************************************************************
; 雙擊項(xiàng)目則彈出對(duì)話框
;********************************************************************************
.elseif ax == LBN_DBLCLK
invoke SendMessage, lParam, LB_GETCURSEL, 0, 0
lea ecx, @szBuffer
invoke SendMessage, lParam, LB_GETTEXT, eax, ecx
invoke wsprintf, addr @szBuffer1, addr szMessage, addr @szBuffer
invoke MessageBox, hWnd, addr @szBuffer1, addr szTitle, MB_OK
.endif
;********************************************************************************
.elseif ax == IDC_LISTBOX2
shr eax, 16
.if ax == LBN_SELCHANGE
invoke SendMessage, lParam, LB_GETSELCOUNT, 0, 0
mov ebx, eax
invoke GetDlgItem, hWnd, IDOK
invoke EnableWindow, eax, ebx
.endif
.endif
.else
mov eax, FALSE
ret
.endif
mov eax, TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke DialogBoxParam, hInstance, DLG_MAIN, NULL, offset _ProcDlgMain, NULL
invoke ExitProcess, NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
程序中總共定義了兩個(gè)列表框。左邊列表框?yàn)?/span>IDC_LISTBOX1,這是一個(gè)單選的列表框,選擇一個(gè)項(xiàng)目的時(shí)候下面的文本會(huì)顯示出選擇的項(xiàng)目,雙擊某個(gè)項(xiàng)目的時(shí)候會(huì)彈出消息框,顯示所選中的項(xiàng)目。右邊的列表框是IDC_LISTBOX2,是一個(gè)多選的列表框,選擇完畢可以用“查看”按鈕彈出消息框,消息框中顯示了所有選中的項(xiàng)目。按下“復(fù)位”按鈕清除列表框的選擇。
列表框可以使用的風(fēng)格
風(fēng)格
|
說明
|
LBS_DISABLENOSCROLL
|
在不需滾動(dòng)的時(shí)候也顯示垂直滾動(dòng)條
|
LBS_EXTENDEDSEL
|
在多選列表框中允許按住Shitf鍵同時(shí)選中一個(gè)范圍
|
LBS_MULTIPLESEL
|
允許多選,如果不定義的話則是單選列表框
|
LBS_NOSEL
|
列表框項(xiàng)目只能查看不能選擇
|
LBS_NOTIFY
|
用戶點(diǎn)擊或雙擊項(xiàng)目時(shí)向父窗口發(fā)送WM_COMMAND消息
|
LBS_SORT
|
自動(dòng)按字母順序排序插入的項(xiàng)目
|
LBS_USETABSTOPS
|
列表框項(xiàng)目的文本中允許將Tab字符的位置展開
|
LBS_STANDARD
|
組合LBS_NOTIFY, LBS_SORT, WS_VSCROLL和WS_BORDER
|
一般單選列表框只需定義LBS_STANDARD就可以了。
列表框使用說明:
當(dāng)列表框有 LBS——NOTIFY風(fēng)格的時(shí)候,用戶有所動(dòng)作時(shí)列表框會(huì)向父窗口發(fā)送WM_COMMAND,同時(shí)在wParam的高16位中指定通知碼,列表框的通知碼種類很少,基本上就是以下幾種:
l LBN_DBLCLK 用戶雙擊了一個(gè)項(xiàng)目。
l LBN_ERRSPACE 插入項(xiàng)目時(shí)無法申請(qǐng)到足夠的內(nèi)存。
l LBN_KILLFOCUS 輸入焦點(diǎn)被切換到其他控件中,列表框丟失了焦點(diǎn)。
l LBN_SELCANCEL 用戶撤銷了一個(gè)選擇。
l LBN_SELCHANGE 選定狀態(tài)改變。
l LBN_SETFOCUS 列表框得到輸入焦點(diǎn)。
我們最關(guān)心的是LBN_DBLCLK和LBN_SELCHANGE通知碼,在單選列表框中,如果程序用雙擊來選擇項(xiàng)目,那么就要處理LBN_DBLCLK通知,例子程序中當(dāng)用戶雙擊IDC_LISTBOX1時(shí)彈出一個(gè)消息框,讀者可以查看其使用方法。在多選列表框中,由于用戶可能選擇了多個(gè)項(xiàng)目,所以一般不用雙擊的方法選定:如果收到LBN_SELCHANGE通知的話,可以得知用戶有一個(gè)選擇動(dòng)作,在這里可以進(jìn)行相應(yīng)的操作。
列表框通知父窗口是通過發(fā)送WM_COMMAND消息,而程序控制列表框的時(shí)候是通過向列表框發(fā)送消息來完成的。
常用的列表框消息如下表所示:
消息
|
wParam
|
lParam
|
說明
|
LB_ADDSTRING
|
0
|
字符串地址
|
添加一個(gè)項(xiàng)目,返回加入后的索引。
|
LB_DELETESTRING
|
位置索引
|
0
|
刪除一個(gè)項(xiàng)目,返回剩余的項(xiàng)數(shù)。
|
LB_FINDSTRING
|
開始索引
|
字符串地址
|
查找以字符串開頭的項(xiàng)目,找到則返回位置索引,未找到則返回LB_ERR。
|
LB_FINDSTRINGEXACT
|
開始索引
|
字符串地址
|
精確查找一個(gè)項(xiàng)目,返回值同上。
|
LB_GETANCHORINGEX
|
0
|
0
|
返回多選列表框多選時(shí)的起始位置。
|
LB_GETCARETINGEX
|
0
|
0
|
多選列表框中的當(dāng)前焦點(diǎn)項(xiàng)目位置。
|
LB_GETCOUNT
|
0
|
0
|
返回列表框中的項(xiàng)目總數(shù)
|
LB_GETCURSEL
|
0
|
0
|
返回單選列表框當(dāng)前選中的項(xiàng)目。
|
LB_GETSEL
|
位置索引
|
0
|
檢測(cè)指定項(xiàng)目的選中狀態(tài),返回非0為選中,返回0為未選中。
|
LB_GETSELCOUNT
|
0
|
0
|
返回多選列表框選中項(xiàng)目的總數(shù)
|
LB_GETSELITEMS
|
最大項(xiàng)數(shù)
|
緩沖區(qū)地址
|
返回多選列表框的選中項(xiàng)目索引列表到緩沖區(qū)中
|
LB_GETTEXT
|
位置索引
|
緩沖區(qū)地址
|
返回某個(gè)項(xiàng)目的字符串
|
LB_GETTEXTLEN
|
位置索引
|
0
|
返回某個(gè)項(xiàng)目的字符串長度
|
LB_GETTOPINDEX
|
0
|
0
|
返回當(dāng)前可見的第一個(gè)項(xiàng)目位置
|
LB_INSERTSTRING
|
插入位置
|
字符串地址
|
在指定位置插入一個(gè)項(xiàng)目
|
LB_RESETCONTENT
|
0
|
0
|
刪除所有項(xiàng)目
|
LB_SELECTSTRING
|
開始位置
|
字符串地址
|
將以指定字符串開頭的項(xiàng)目選中
|
LB_SELITEMRANGE
|
選擇狀態(tài)
|
范圍
|
在多選框中將一個(gè)范圍選中或清除
|
LB_SETCURSEL
|
位置索引
|
0
|
在單選列表框中選中一個(gè)項(xiàng)目
|
LB_SETSEL
|
選擇狀態(tài)
|
位置索引
|
在多選框中將一個(gè)項(xiàng)目選中或清除
|
LB_SETTOPINDEX
|
位置索引
|
0
|
滾動(dòng)顯示到指定的項(xiàng)目
|
LB_DIR
|
屬性
|
文件通配符
|
搜索目錄并將符合文件通配符的文件名加入到列表框中
|
這些消息中LB_DIR是個(gè)比較有趣的消息,它可以將指定目錄中的文件名自動(dòng)列出來并加入列表框中,如例子中用*.*將當(dāng)前目錄中的全部文件名加到列表框中。LB_DIR消息中wParam參數(shù)可以指定的屬性可以是是以下值的組合:
DDL_ARCHIVE 加入歸檔屬性的文件。
DDL_DIRECTORY 加入目錄。
DDL_DRIVES 加入驅(qū)動(dòng)器名。
DDL_HIDDEN 包含隱含文件。
DDL_READONLY 包含只讀文件。
DDL_READWRITE 包含可讀寫的文件。
DDL_SYSTEM 包含系統(tǒng)文件。
在列表框中初始化時(shí)加入項(xiàng)目可以使用LB_ADDSTRING和LB_INSERTSTRING消息,刪除項(xiàng)目可以用LB_DELETESTRING消息,刪除全部項(xiàng)目用LB_RESETCONTENT消息。
對(duì)于單選列表框,要獲取選中項(xiàng)目可以發(fā)送LB_GETCURSEL消息,要得到這個(gè)項(xiàng)目的字符串需要用索引值通過LB_GETTEXT消息獲取,讀者可以查看例子中處理LBN_DBLCLK通知碼的部分代碼。
對(duì)于多選列表框,需要用LB_GETSELITEMS消息獲取全部選中項(xiàng)目,這個(gè)消息返回的是一個(gè)列表,所有選中項(xiàng)目的索引按順序排列返回到緩沖區(qū)中,所以在例子中處理“查看”按鈕消息(IDOK)的時(shí)候,程序先發(fā)送LB_GETSELCOUNT消息得到選中的項(xiàng)目數(shù),以便在下面用一個(gè)循環(huán)獲取所有的項(xiàng)目,得到數(shù)目數(shù)后,再用LB_GETSELITEMS將選中項(xiàng)目的索引取到@szBuffer中,接下來進(jìn)入一個(gè)循環(huán),循環(huán)的次數(shù)就是LB_GETSELCOUNT得到的數(shù)值,在循環(huán)中,程序從@szBuffer中將索引值逐個(gè)取出并用LB_GETTEXT消息獲取每一項(xiàng)的字符串,最后用一個(gè)MessageBox顯示出來。