CTRL_LISTVIEW
風格選項
LVS_TREEVIEW 以樹型的方式來顯示列表項
LVS_UPNOTIFY 指定鼠標點擊操作的響應方式,默認情況下,如果沒有指定 LVS_UPNOTIFY 風 格,列表型控件將在鼠標按下時發出通知消息;如果指定了該風格,控件將在鼠標抬起時發出通知消息
數據結構
列
typedef struct _LVCOLUMN
{
int nCols; // 新增列的位置,如果小於0或者超出列次序范圍則添加為最后一列
int width; // 列寬
char *pszHeadText; // 列的標題
int nTextMax; // 列標題的最大長度
DWORD image; // 列表頭的圖像,3.0為保留字段
PFNLVCOMPARE pfnCompare; // 用於列排序的比較函數
DWORD colFlags; // 列標志,LVCF_LEFTALIGN、LVCF_RIGHTALIGN 和 LVCF_CENTERALIGN,分別代表中文左對齊、居中、右對齊
} LVCOLUMN;
typedef LVCOLUMN *PLVCOLUMN;
列表項比較函數
typedef int (*PFNLVCOMPARE) (int nItem1, int nItem2, PLVSORTDATA sortData); // sortData在3.0中沒有意義
自定義字符串比較函數
typedef int (*STRCMP) (const char* s1, const char* s2, size_t n);
列表項
typedef struct _LVITEM
{
int nItem; // 新增列表項的位置索引值,如果該值超出索引值范圍的話,新增的項將被添加到列表的最后,如果 LVM_ADDITEM 消息 的 wParam 參數指定了新添節點的
// 父節點,nItem 項所表示的位置值指的是新添節點在父節點中的位置
int nItemHeight; // 列表項的高度
DWORD itemData; // 列表項的附加數據
DWORD dwFlags; // 列表項的狀態, LVIF_FOLD,列表項可折疊
} LVITEM;
列表子項
typedef struct _LVSUBITEM
{
DWORD flags; // 子項的標志,LVFLAG_BITMAP 和 LVFLAG_ICON
int nItem; // 子項的垂直索引值
int subItem; // 子項的水平索引值
char *pszText; // 子項的文字內容
int nTextMax; // 子項的文字長度
int nTextColor; // 子項的文字顏色
DWORD image; // 子項的圖像
} LVSUBITEM;
typedef LVSUBITEM *PLVSUBITEM;
列表項查找信息
typedef struct _LVFINDINFO
{
DWORD flags; // 查找標志,LVFF_TEXT和(或)LVFF_ADDDATA
int iStart; // 查找的開始索引
int nCols; // 表示匹配的列表項中前nCols列子項的文字內容要和pszInfo中的字符串一致
char **pszInfo; // 查找的多個子項文字內容
DWORD addData; // 列表項附加數據
int nItem; // The found item's row, reserved
int nSubitem; // The found subitem's column, reserved
} LVFINDINFO;
typedef LVFINDINFO *PLVFINDINFO;
消息
1. 列的操作
添加列: LVCOLUMN p; SendMessage (hwndListView, LVM_ADDCOLUMN, 0, (LPARAM)&p);設置修改列屬性:LVCOLUMN p; SendMessage (hwndListView, LVM_SETCOLUMN, 0, (LPARAM)&p);設置列表頭標題:LVCOLUMN p; SendMessage (hwndListView, LVM_MODIFYHEAD, 0, (LPARAM)&p); // 只需給出 nCols 和 pszHeadText 項的值獲取列屬性:LVCOLUMN p; int nCols; SendMessage (hwndListView, LVM_GETCOLUMN, nCols, (LPARAM)&p);獲取列寬度:int width; int nCols; width = SendMessage (hwndListView, LVM_GETCOLUMNWIDTH, nCols, 0);獲取列數量:int count; count = SendMessage (hwndListView, LVM_GETCOLUMNCOUNT, 0, 0);刪除列:int nCols; SendMessage (hwndListView, LVM_DELCOLUMN, nCols, 0);設置列表頭高度:int newHeight; SendMessage (hwndListView, LVM_SETHEADHEIGHT, newHeight, 0);
2. 列表項操作
添加列表項:HLVITEM hItem; HLVITEM hParent; LVITEM lvItem; hItem = SendMessage (hwndListView, LVM_ADDITEM, hParent, (LPARAM)&lvItem);
獲取列表項:LVITEM lvItem; HLVITEM hItem; SendMessage (hwndListView, LVM_GETITEM, hItem, (LPARAM)&lvItem); // hItem 為目標列表型的句柄,如果 hItem 為 0,lvItem 結構的 nItem 域應該預設為所要獲取的列表項的索引值
獲取列表項數量:int count; count = SendMessage (hwndListView, LVM_GETITEMCOUNT, 0, 0);
獲取列表項附加數據:DWORD addData; int nItem; HLVITEM hItem; addData = SendMessage (hwndListView, LVM_GETITEMADDDATA, nItem, hItem);
設置列表項附加數據:HLVITEM hItem; DWORD addData; SendMessage (hwndListView, LVM_SETITEMADDDATA, hItem, (LPARAM)addData); // 如果設置成功,返回 LV_OKAY,否則返回 LV_ERR
設置列表項高度:HLVITEM hItem; int newHeight; SendMessage (hwndListView, LVM_SETITEMHEIGHT, hItem, newHeight); // 如果設置成功,返回 TRUE,否則返 回 FALSE
刪除一個列表項:HLVITEM hItem; int nItem; SendMessage (hwndListView, LVM_DELITEM, nItem, hItem);
刪除所有列表項:SendMessage (hwndListView, LVM_DELALLITEM, 0, 0);
設置子項屬性:LVSUBITEM subItem; HLVITEM hItem; SendMessage (hwndListView, LVM_SETSUBITEM, hItem, (LPARAM)&subItem);獲取子項文字:LVSUBITEM subItem; HLVITEM hItem; SendMessage (hwndListView, LVM_GETSUBITEMTEXT, hItem, (LPARAM)&subItem);設置子項文字:LVSUBITEM subItem; HLVITEM hItem; SendMessage (hwndListView, LVM_SETSUBITEMTEXT, hItem, (LPARAM)&subItem);獲取子項文字長度:LVSUBITEM subItem; HLVITEM hItem; int len; len = SendMessage (hwndListView, LVM_GETSUBITEMLEN, hItem, (LPARAM)&subItem);選擇列表項:int nItem; HLVITEM hItem; SendMessage (hwndListView, LVM_SELECTITEM, nItem, hItem); // 選擇的列表項不一定可見獲取被選中的列表項:HLVITEM hItemSelected; hItemSelected = SendMessage (hwndListView, LVM_GETSELECTEDITEM, 0, 0);使列表項可見:HLVITEM hItem; int nItem; SendMessage (hwndListView, LVM_SHOWITEM, nItem, hItem); // 成為可見區域中的第一個或最后一個可見條目,而且是 完全可見的選中並使列表項可見:int nItem; HHLVITEM hItem; SendMessage (hwndListView, LVM_CHOOSEITEM, nItem, hItem);查找列表項:HLVITEM hFound; HLVITEM hParent; LVFINDINFO findInfo; hFound = SendMessage (hwndListView, LVM_FINDITEM, hParent, (LPARAM)&findInfo);對列表項排序:SendMessage (hwndListView, LVM_SORTITEMS, 0, (LPARAM)pfnCompare); // pfnCompare指向一個PFNLVCOMPARE類型的函數依據某一列排序:int nCol; SendMessage (hwndListView, LVM_COLSORT, nCol, 0);設置自定義字符串比較函數:SendMessage (hwndListView, LVM_SETSTRCMPFUNC, 0, (LPARAM)pfnStrCmp); // 默認字符串比較函數是strcasecmp,pfnStrCmp指向STRCMP類型的函數
3. 樹型節點的操作
獲取相關節點:int related; HLVITEM hItem; HLVITEM hRelatedItem; hRelatedItem = SendMessage (hwndListView, LVM_GETRELATEDITEM, related, hItem);/*related 指定相關節點和目標節點的關系,包括:• LVIR_PARENT:獲取父節點• LVIR_FIRSTCHILD:獲取第一個子節點• LVIR_NEXTSIBLING:獲取下一個兄弟節點• LVIR_PREVSIBLING:獲取前一個兄弟節點*/折疊或者展開一個包含子節點的節點項:HLVITEM hItem; BOOL bFold; SendMessage (hwndListView, LVM_FOLDITEM, bFold, hItem); // bFold為TRUE的話折疊節點項,否則展開節點項
通知
1. 具有 LVS_NOTIFY 風格的列表框可能產生的通知消息
LVN_ITEMRDOWN:用戶鼠標右鍵在列表項上按下
LVN_ITEMRUP:用戶鼠標右鍵在列表項上抬起
LVN_HEADRDOWN:用戶鼠標右鍵在表頭上按下
LVN_HEADRUP:用戶鼠標右鍵在表頭上抬起
LVN_KEYDOWN:鍵按下
LVN_ITEMDBCLK:用戶雙擊某個列表項
LVN_ITEMCLK:用戶單擊某個列表項(保留)
LVN_SELCHANGE:當前選擇的列表項改變
LVN_FOLDED:用戶鼠標點擊某個列表項,使之折疊
LVN_UNFOLDED:用戶鼠標點擊某個列表項,使之展開
當用戶鼠標右鍵在列表項上按下時,該項將被選中,並且產生LVN_SELCHANGE和LVN_ITEMRDOWN兩個通知碼
2. 使用SetNotificationCallback函數注冊一個自定義的通知消息處理函數
mg-samples的列表型控件示例
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/stat.h> 5 #include <sys/types.h> 6 7 #include <minigui/common.h> 8 #include <minigui/minigui.h> 9 #include <minigui/gdi.h> 10 #include <minigui/window.h> 11 #include <minigui/control.h> 12 13 #define IDC_LISTVIEW 10 14 #define IDC_CTRL1 20 15 #define IDC_CTRL2 30 16 17 #define SUB_NUM 3 18 19 #define COL_NR TABLESIZE(caption) 20 #define SCORE_NUM TABLESIZE(scores) 21 22 #define everage_score "Everage score" 23 #define getting_the_average_score "Getting the average score" 24 25 typedef struct _SCORE 26 { 27 char *name; 28 int scr[SUB_NUM]; 29 } SCORE; 30 31 static char * caption [] = 32 { 33 "Name", "Chinese", "Math", "English" 34 }; 35 36 static char *classes [] = 37 { 38 "Grade 1", "Grade 2", "Grade 3" 39 }; 40 41 static SCORE scores[] = 42 { 43 {"Tom", {81, 96, 75}}, 44 {"Jack", {98, 62, 84}}, 45 {"Merry", {79, 88, 89}}, 46 {"Bob", {79, 88, 89}}, 47 }; 48 49 static GHANDLE add_class_item (HWND hlist, PLVITEM lvItem, GHANDLE classent) 50 { 51 LVSUBITEM subdata; 52 GHANDLE item = SendMessage (hlist, LVM_ADDITEM, classent, (LPARAM)lvItem); 53 54 subdata.nItem = lvItem->nItem; 55 subdata.subItem = 0; 56 subdata.pszText = classes[lvItem->nItem];; 57 subdata.nTextColor = PIXEL_black; 58 subdata.flags = 0; 59 subdata.image = 0; 60 SendMessage (hlist, LVM_SETSUBITEM, item, (LPARAM) & subdata); 61 62 return item; 63 } 64 65 static GHANDLE add_score_item (HWND hlist, PLVITEM lvItem, GHANDLE classent) 66 { 67 char buff[20]; 68 LVSUBITEM subdata; 69 GHANDLE item = SendMessage (hlist, LVM_ADDITEM, classent, (LPARAM)lvItem); 70 int i = lvItem->nItem; 71 int j; 72 73 subdata.flags = 0; 74 subdata.image = 0; 75 subdata.nItem = lvItem->nItem; 76 77 for (j = 0; j < 4; j ++) { 78 subdata.subItem = j; 79 if (j == 0) { 80 subdata.pszText = scores[i].name; 81 subdata.nTextColor = PIXEL_black; 82 } 83 else { 84 sprintf (buff, "%d", scores[i].scr[j-1]); 85 subdata.pszText = buff; 86 if (scores[i].scr[j-1] > 90) 87 subdata.nTextColor = PIXEL_red; 88 else 89 subdata.nTextColor = PIXEL_black; 90 } 91 SendMessage (hlist, LVM_SETSUBITEM, item, (LPARAM) & subdata); 92 } 93 94 return item; 95 } 96 97 //#define CUSTOM_DRAW 98 99 #ifdef CUSTOM_DRAW 100 101 static void my_draw_hdr_bk (HWND hWnd, HLVHDR hlvhdr, HDC hdc, RECT *rcDraw) 102 { 103 SetBrushColor (hdc, PIXEL_yellow); 104 FillBox (hdc, rcDraw->left, rcDraw->top, RECTWP(rcDraw), RECTHP(rcDraw)); 105 } 106 107 static void my_draw_hdr_item (HWND hWnd, int idx, HDC hdc, RECT *rcDraw) 108 { 109 Rectangle (hdc, rcDraw->left, rcDraw->top, rcDraw->right, rcDraw->bottom); 110 SetBkMode (hdc, BM_TRANSPARENT); 111 TextOut (hdc, rcDraw->left+4, rcDraw->top+4, caption[idx]); 112 } 113 #endif 114 115 static int 116 ScoreProc (HWND hDlg, int message, WPARAM wParam, LPARAM lParam) 117 { 118 HWND hListView; 119 hListView = GetDlgItem (hDlg, IDC_LISTVIEW); 120 121 switch (message) 122 { 123 124 case MSG_INITDIALOG: 125 { 126 int i, j; 127 LVITEM item; 128 LVCOLUMN lvcol; 129 GHANDLE hitem; 130 #ifdef CUSTOM_DRAW 131 LVCUSTOMDRAWFUNCS myfuncs = {my_draw_hdr_bk, my_draw_hdr_item}; 132 133 SendMessage (hListView, LVM_SETCUSTOMDRAW, 0, (LPARAM) &myfuncs); 134 #endif 135 136 for (i = 0; i < COL_NR; i++) { 137 lvcol.nCols = i; 138 lvcol.pszHeadText = caption[i]; 139 lvcol.width = 75; 140 lvcol.pfnCompare = NULL; 141 lvcol.colFlags = 0; 142 SendMessage (hListView, LVM_ADDCOLUMN, 0, (LPARAM) &lvcol); 143 } 144 145 item.dwFlags &= ~LVIF_FOLD; 146 item.nItemHeight = 25; 147 148 SendMessage (hListView, MSG_FREEZECTRL, TRUE, 0); 149 hitem = 0; 150 for (i = 0; i < 3; i++) { 151 item.nItem = i; 152 hitem = add_class_item (hListView, &item, 0); 153 154 for (j = 0; j < SCORE_NUM; j++) { 155 item.nItem = j; 156 add_score_item (hListView, &item, hitem); 157 } 158 159 } 160 161 SendMessage (hListView, MSG_FREEZECTRL, FALSE, 0); 162 break; 163 } 164 165 case MSG_COMMAND: 166 { 167 int id = LOWORD (wParam); 168 int i, j; 169 170 if (id == IDC_CTRL2) { 171 float average = 0; 172 char buff[20]; 173 for (i = 0; i < SCORE_NUM; i++) { 174 for (j = 0; j < SUB_NUM; j++) { 175 average += scores[i].scr[j]; 176 } 177 } 178 average = average / (SCORE_NUM * SUB_NUM); 179 180 sprintf (buff, "%4.1f", average); 181 SendDlgItemMessage (hDlg, IDC_CTRL1, MSG_SETTEXT, 0, (LPARAM)buff); 182 printf("selected column%d\n", SendDlgItemMessage(hDlg, IDC_LISTVIEW, LVM_GETSELECTEDCOLUMN, 0,0)); 183 } 184 break; 185 } 186 187 case MSG_CLOSE: 188 { 189 EndDialog (hDlg, 0); 190 break; 191 } 192 193 } 194 195 return DefaultDialogProc (hDlg, message, wParam, lParam); 196 } 197 198 static CTRLDATA CtrlScore[] = 199 { 200 { 201 "button", 202 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 203 110, 255, 100, 30, 204 IDC_CTRL2, 205 everage_score, 206 0 207 }, 208 { 209 "edit", 210 WS_CHILD | WS_VISIBLE | WS_BORDER, 211 10, 260, 50, 20, 212 IDC_CTRL1, 213 "", 214 0 215 }, 216 { 217 "listview", 218 /*WS_BORDER |*/ WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | LVS_TREEVIEW, 219 10, 10, 320, 220, 220 IDC_LISTVIEW, 221 "score table", 222 0 223 }, 224 }; 225 226 static DLGTEMPLATE DlgScore = 227 { 228 WS_BORDER | WS_CAPTION, 229 WS_EX_NONE, 230 0, 0, 350, 340, 231 getting_the_average_score, 232 0, 0, 233 0, NULL, 234 0 235 }; 236 237 int MiniGUIMain (int argc, const char* argv[]) 238 { 239 #ifdef _MGRM_PROCESSES 240 JoinLayer(NAME_DEF_LAYER , "listview" , 0 , 0); 241 #endif 242 243 DlgScore.controls = CtrlScore; 244 DlgScore.controlnr = TABLESIZE(CtrlScore); 245 246 DialogBoxIndirectParam (&DlgScore, HWND_DESKTOP, ScoreProc, 0L); 247 248 return 0; 249 } 250 251 #ifdef _MGRM_THREADS 252 #include <minigui/dti.c> 253 #endif