在上一個例子中,我們只用到了ListView的Report視圖,也就是詳細視圖。本文我們再把上一篇文章中所用的例子進行一下擴展,例子源碼可以到俺的資源區下載。
我們為ListView中顯示的數據加上圖標,并且允許用戶選擇顯示哪種視圖,如大圖標,小圖標,詳細信息等。
因為代碼還比較長,我也不希望把代碼全部放出來,在寫完本文后,我會將源碼上傳到資源中。當然了,我也不可能說每一行代碼都解釋一遍,那也不現實,而且,這樣也不好,我不能主觀地去懷疑讀者的領悟能力。
## 一、準備圖標
既然要用到圖標,為了簡單方便,就用VS的資源編輯器隨便畫幾下就有圖標了,我們要準備兩個圖標,為什么呢?第一個圖標是給EXE文件用的,而第二個圖標是用在ListView中的。因為在生成的.exe文件的圖標是選用我們最先添加到資源中的圖標,為了使.EXE文件的圖標和我們在ListView中用的圖標不要一樣(這樣不好看),所以我們還是準備兩個圖標好一點。
圖標中具備兩個尺寸就夠了——16*16和32*32,如果可能盡量用24位圖,這樣你能用更多的顏色。
## 二、如何切換視圖
改變ListView的視圖,可以使用ListView_SetView宏,發送LVM_SETVIEW消息也可以,不過使用宏更方便。它的第一個參數指定LV控件的句柄,第二個參數是設置用哪個視圖。
LV_VIEW_DETAILS——詳細視圖。
LV_VIEW_ICON——大圖標列表。
LV_VIEW_LIST——列表視圖。
LV_VIEW_SMALLICON——小圖標。
LV_VIEW_TILE——平鋪,如果我沒記錯的話,這個視圖是在XP時引入的。
## 三、ComboBox控件使用
為了可以讓用戶選擇一個視圖,自然要提供對應的操作界面,這是一種多選一的方式,用單選按鈕和下拉拉表框都可以,不過,單選按鈕要占用更多地方而且處理的消息更多,相對麻煩,所以,還是ComboBox好一些。
用ComboBox_AddString宏就可以向ComboBox中添加項,比如本例。
~~~
// 初始化ComboBox,以選擇視圖
hcbb = GetDlgItem(hDlg, IDC_CBVIEW);
ComboBox_AddString(hcbb, L"大圖標");
ComboBox_AddString(hcbb, L"小圖標");
ComboBox_AddString(hcbb, L"列表");
ComboBox_AddString(hcbb, L"詳細");
~~~
當用戶操作了ComboBox,它同樣會發送一條WM_COMMAND消息,而我們之前已經響應過這條消息,看看例子,我們前面有一個“添加”按鈕和一個“清除”按鈕,它被點擊后也會發送WM_COMMAND消息。因此,我們要做更詳細的處理。
還記得吧,WM_COMMAND的wParam參數的低字節位表示發送該消息的控件的ID,高字節位表示“通知碼”。lParam是控件的句柄。我們判斷ID知道用戶操作的是ComboBox控件還不夠,因為我不知道用戶對這個控件做了哪些操作,是彈出下拉列表?還是收起下拉列表?或者選擇了另一個項?
而我們這里要做的是,看用戶選擇了哪個視圖,我們的ListView控件就顯示哪種視圖,顯然,在通知碼中,我們是對CBN_SELCHANGE感興趣,因為選擇的索引值一旦改變,就會收到這個通知碼。
~~~
case IDC_CBVIEW:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
// 當前選擇項的索引
int index = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
// 根據選擇設置視圖
DWORD lvView;
switch (index)
{
case 0:
lvView = LV_VIEW_ICON;
break;
case 1:
lvView = LV_VIEW_SMALLICON;
break;
case 2:
lvView = LV_VIEW_LIST;
break;
case 3:
lvView = LV_VIEW_DETAILS;
break;
default:
lvView = LV_VIEW_DETAILS;
break;
}
ListView_SetView(GetDlgItem(hDlg, IDC_LV), lvView);
}
break;
}
~~~
發送CB_GETCURSEL消息,可以得到ComboBox中當前選定項的索引值。
## 四、向ListView添加圖標
先用ImageList_Create創建圖像列表,然后用ImageList_AddIcon宏向列表中添加圖標。因為我們要用大圖標和小圖標,所以要創建兩個圖像列表,一個放置大圖標,另一種放置小圖標,因為同一個Image List中放置的所有圖像的尺寸必須相同。
~~~
// 初始化ImageList
hImgListSm = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_MASK,1,0);
hImgListLg = ImageList_Create(GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),ILC_MASK,1,0);
hicon = LoadIcon(hgAppInst,MAKEINTRESOURCE(IDI_ITE));
// 添加圖標
ImageList_AddIcon(hImgListSm, hicon);
ImageList_AddIcon(hImgListLg, hicon);
DestroyIcon(hicon);
~~~
接著,用ListView_SetImageList把Image List和ListView關聯起來。
~~~
// 將ListView與ImageList關聯
ListView_SetImageList(hListview, hImgListLg, LVSIL_NORMAL);
ListView_SetImageList(hListview, hImgListSm, LVSIL_SMALL);
~~~
在向ListView添加項時,設置LVITEM結構體的iImage字段為圖像列表中對應圖像的索引,因為我們只添加了一個圖標,所以,索引是0.
~~~
LVITEM vitem;
vitem.mask = LVIF_TEXT | LVIF_IMAGE;
vitem.iImage = 0;
~~~
ImageList_Create返回的是一個句柄,它也是一種資源,所以,在不需要它了,就得記得把它銷毀。在我們的對話框發生WM_DESTROY的同時將其銷毀。
~~~
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE)
{
// 銷毀ImageList
ImageList_Destroy(hImgListLg);
ImageList_Destroy(hImgListSm);
DestroyWindow(hListview);//不再需要
DestroyWindow(hDlg);
}
return 0;
~~~
另外,補充一個小知識,要得到對話框中某個控件的句柄,可以調用GetDlgItem函數,這也是我們為什么要為控件設置ID值的原因。
程序運行后,就可以通過選擇下拉列表來動態改變ListView的視圖了。




好了,要過年了,這是新年前最后一篇博文,過完年后,我們繼續。我也希望,后續能與大家一起分享更多的知識和編程技巧。
===================================
**祝大家**
**新春快樂,生活愉快,身體健康,工作順利,明年更有成就。**
**祝各位以及各位的親朋好友們,新年快樂。**
- 前言
- (1):關于C++的幾個要點
- (2):完整的開發流程
- (3):窗口的重繪
- (4):創建菜單
- (5):具有單選標記的菜單
- (6):創建右鍵菜單
- (7):多邊形窗口
- (8):繪圖(A)
- (9):繪圖(B)
- (10):繪圖(C)
- (11):使用控件——先來耍一下按鈕
- (12):使用控件——單選按鈕
- (13):握手對話框
- (14):用對話框作為主窗口
- (15):ListView控件
- (16):ListView的多個視圖
- (17):啟動和結束進程
- (18):使用對話框的兩個技巧
- (19):瀏覽和打開文件
- (20):瀏覽文件夾
- (21):復制&粘貼&剪貼板操作
- (22):抓取屏幕
- (23):漸變顏色填充
- (24):計時器
- (25):監視剪貼板