Для примеров Listview ничто не сравнится с четкостью Classic Sample !
Тем временем Google Translate вместе с Юникодом + небольшие модификации для спасения немецкой ссылки @ Alejadro для Listview - прямой перевод в результатах поиска не предлагается, так как страница не содержит соответствующий метатег . Отрезал немного для краткости:
Последующие изменения стилей
Стиль ListView можно изменить после создания. Для этого используются функции GetWindowLong и SetWindowLong. О масках можно определить разные стили.
Маска ................................. Стили в маске:
LVS_TYPEMASK .............. LVS_ICON, LVS_LIST, LVS_REPORT и LVS_SMALLICON
LVS_ALIGNMASK ............. LVS_ALIGNLEFT и LVS_ALIGNTOP
LVS_TYPESTYLEMASK ... LVS_ALIGNLEFT и LVS_ALIGNTOP, а также VS_NOCOLUMNHEADER и LVS_NOSORTHEADER
Для следующей последовательности dwView содержит используемый стиль, например LVS_REPORT or LVS_ICON
.
DWORD dwStyle = GetWindowLong(hwndLV, GWL_STYLE); // get current style
if ((dwStyle & LVS_TYPEMASK)! = dwView) // only on change
SetWindowLong(hwndLV, GWL_STYLE, (dwStyle & ~ LVS_TYPEMASK) | dwView); }
Элемент управления ListView
Создание списка
Представление списка создается с помощью функции CreateWindow. Класс окна использует константу WC_LISTVIEW
. Для этого должен быть включен общий заголовочный файл элемента управления.
#include "commctrl.h"
InitCommonControls();
hwndList = CreateWindow(WC_LISTVIEW, "",
WS_VISIBLE | WS_BORDER | WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
10, 10, 300, 100,
hWnd, (HMENU) ID_LIST, hInst, 0);
В диалоге это просто определяется в ресурсе.
Если есть неразрешенные внешние компоненты, следует проверить, включена ли библиотека для общих элементов управления (comctl32.lib).
Столбцы ListView
Прежде чем что-то вставить в REPORT
, столбцы должны быть определены. Столбец описывается структурой LVCOLUMN
. Следующая процедура создает столбец.
int CreateColumn(HWND hwndLV, int iCol, char * text, intwidth)
{
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = iWidth;
lvc.pszText = text;
lvc.iSubItem = iCol;
return ListView_InsertColumn(hwndLV, iCol, & lvc);
}
Столбцы могут быть изменены сообщениями в ListView или вызовом макросов, которые в конечном итоге выполнят SendMessage.
Message Macro call Function
LVM_INSERTCOLUMN ListView_InsertColumn(HWND, int, LVCOLUMN * ) Insert column
LVM_DELETECOLUMN ListView_DeleteColumn(HWND, int) Delete column
LVM_GETCOLUMN ListView_GetColumn(HWND, int, LVCOLUMN * ) Get properties of the column
LVM_SETCOLUMN ListView_SetColumn(HWND, int, LVCOLUMN * ) Change properties of the column
LVM_GETCOLUMNWIDTH ListView_GetColumnWidth(HWND, int) Determine column width
LVM_SETCOLUMNWIDTH ListView_SetColumnWidth(HWND, int, int) Set column width
Вставить строку
Элемент ListView описывается структурой LVITEMW
(см. Ниже). Каждый элемент может быть представлен как элемент ICON
, SMALLICON
, LIST
или как левый столбец строки REPORT
.
int CreateItem(HWND hwndList, wchar_t * text)
{
LVITEMW lvi = {0};
lvi.mask = LVIF_TEXT;
lvi.pszText = text;
return ListView_InsertItem(hwndList, & lvi);
}
Поле маски определяет, какие элементы структуры LVITEMW
действительно используются. Поскольку часто имеет смысл сохранять указатель на объект памяти, который содержит данные за объектом, поле lParam полезно. Чтобы это можно было использовать, LVIF_TEXT | LVIF_PARAM
должен быть установлен в качестве маски.
Константы маски и поля для их включения:
LVIF_IMAGE iImage
LVIF_INDENT iIndent
LVIF_PARAM lParam
LVIF_STATE состояние
LVIF_TEXT pszText
Следующие столбцы отчета
Сам элемент всегда остается в представлении отчета и доступен для выбора. Для заполнения дополнительных столбцов к элементу добавляется текст.
int Create2ColItem(HWND hwndList, wchar_t * Text1, wchar_t * Text2)
{
LVITEMW lvi = {0};
int Ret;
// Initialize LVITEMW members that are common to all items.
lvi.mask = LVIF_TEXT;
lvi.pszText = Text1;
Ret = ListView_InsertItem(hwndList, & lvi);
if (Ret >= 0)
{
ListView_SetItemText(hwndList, Ret, 1, Text2);
}
return Ret;
}
Вышеуказанное Create2ColItem
лучше всего демонстрируется чем-то вроде следующего утверждения:
LVHwnd = Your_Create_LV_Routine();
if (LVHwnd)
{
CreateColumn(LVHwnd, 0, ptrColHeaderString1, iColSize1);
CreateColumn(LVHwnd, 1, ptrColHeaderString2, iColSize2);
Create2ColItem(LVHwnd, ptrItemText1, ptrItemText2);
}
Структура LVITEMW
Структура LVITEMW
(в CommCtrl.h ) описывает элемент ListView. Наиболее важные элементы кратко описаны здесь. Первое определение:
typedef struct tagLVITEMW
{
UINT mask;
int iItem;
int iSubItem;
UINT state;
UINT stateMask;
LPWSTR pszText;
int cchTextMax;
int iImage;
LPARAM lParam;
#if (_WIN32_IE >= 0x0300) //historical note for IE3 users!
int iIndent;
#endif
#if (NTDDI_VERSION >= NTDDI_WINXP)
int iGroupId;
UINT cColumns; // tile view columns
PUINT puColumns;
#endif
#if (NTDDI_VERSION >= NTDDI_VISTA)
int* piColFmt;
int iGroup; // readonly. only valid for owner data.
#endif
} LVITEMW, *LPLVITEMW;
Сообщения LVM_GETITEMW
и LVM_SETITEMW
изменяют атрибуты элемента. В качестве параметра вы получаете указатель на структуру LVITEMW
рядом с HWND
в ListView, которая должна быть заполнена заранее.
Детали конструкции в деталях:
маска :
Определяет, какие элементы используются. Возможна комбинация следующих флагов:
LVIF_IMAGE iImage
LVIF_INDENT iIndent
LVIF_PARAM lParam
LVIF_STATE состояние
LVIF_TEXT pszText
iItem
Индекс (на основе 0) элемента, к которому относится структура.
iSubItem Индекс (на основе 1) подэлемента, к которому относится структура. 0, если структура ссылается на элемент, а не на подпункт.
pszText
указывает на строку с нулевым символом в конце. Если значение LPWSTR_TEXTCALLBACK
, это элемент обратного вызова. Если это изменится, pszText должен быть установлен в LPSTR_TEXTCALLBACK
, а ListView будет информирован LVM_SETITEMW
или LVM_SETITEMTEXT
pszText
не должен быть установлен в LPWSTR_TEXTCALLBACK
, если ListView имеет стиль LVS_SORTASCENDING
или LVS_SORTDESCENDING
.
cchTextMax
Размер буфера при чтении текста.
iImage
Индекс значка этого элемента из списка изображений.
LPARAM
32-разрядное значение, характерное для этого элемента.
Действия с элементами
LVM_INSERTITEM Вставка элемента
LVM_DELETEITEM Удалить элемент
LVM_DELETEALLITEMS Удалить все элементы
LVM_GETITEMW Считать свойства элемента
LVM_GETITEMTEXT Прочитать текст элемента
LVM_SETITEMW изменить
LVM_SETITEMTEXT Изменить на текст
Перед вставкой нескольких элементов в ListView будет отправлено сообщение LVM_SETITEMCOUNT
, указывающее, сколько элементов в конечном итоге будет содержаться. Это позволяет ListView оптимизировать распределение и освобождение памяти. Сколько элементов содержит ListView, можно определить с помощью LVM_GETITEMCOUNT
.
Редактирование выбранных элементов
int Pos = -1;
LVITEMW Item;
Pos = ListView_GetNextItem(hwndList, Pos, LVNI_SELECTED);
while (Pos> = 0)
{
Item.iItem = Pos;
Item.iSubItem = 0;
ListView_GetItem(hwndList, & Item);
TuWasMitElement((Element Type * ) Item.lParam);
Pos = ListView_GetNextItem(hwndList, Pos, LVNI_SELECTED);
}
События
ListView отправляет WM_NOTIFY
сообщений в родительское окно. Код может принимать следующие значения:
Сообщение ............ Описание
LVN_BEGINDRAG ............. Запустить действие перетаскивания
LVN_BEGINRDRAG .......... Запустить действие перетаскивания правой кнопкой мыши
LVN_BEGINLABELEDIT .... Начать редактирование метки
LVN_ENDLABELEDIT ....... Завершить редактирование метки
LVN_DELETEITEM .......... Сообщает, что элемент удален
LVN_DELETEALLITEMS... Сообщает, что все элементы удалены
LVN_COLUMNCLICK ...... Указывает, что пользователь щелкнул в заголовке отображения отчета
LVN_GETDISPINFO ....... Элемент управления запрашивает информацию о презентации из родительского окна
LVN_SETDISPINFO ........ Информация родительского окна для элемента должна быть обновлена
LVN_INSERTITEM .......... Указывает на вставку элемента
LVN_ITEMCHANGED ..... Указывает, что элемент был изменен
LVN_ITEMCHANGING .... Указывает на предполагаемое изменение элемента
LVN_KEYDOWN ............. Клавиша была нажата
Редактирование меток
Представление списка должно быть создано в стиле LVS_EDITLABELS
. Тогда на ярлык уже можно нажать и входные данные принимаются. Тем не менее, ввод отбрасывается сразу после этого. Чтобы разрешить изменения в метке, вам просто нужно перехватить WM_NOTIFY
и вернуть TRUE
. Чтобы получить доступ к введенному тексту между ними, осуществляется доступ к тексту элемента. В примере показан ввод в окне сообщения.
case WM_NOTIFY:
switch (((LPNMHDR) lParam) -> code)
{
case LVN_ENDLABELEDIT:
pItem = (NMLVDISPINFO) lParam;
MessageBox (hWnd, pItem-> item.pszText, "entry", MB_OK);
return TRUE;
Если редактирование было прервано, элемент pszText
будет равен 0.
Если вы хотите запретить редактирование, сообщение LVN_BEGINLABELEDIT
перехватывается и возвращается TRUE
. Здесь также можно получить доступ к элементу таким же образом через lParam
и, таким образом, например, можно исключить определенную группу элементов.
Щелкните заголовок столбца в ListView
case WM_NOTIFY:
switch (((LPNMHDR) lParam) -> code)
{
case LVN_COLUMNCLICK:
ColumnNr = ((LPNMLISTVIEW) lParam) -> iSubItem;
.....
Событие выбора
Событие LVN_ITEMACTIVATE
отправляется, когда пользователь активирует элемент. Как и в случае других событий ListView, он выполняет оконную функцию как часть сообщения WM_NOTIFY
.
case WM_NOTIFY:
switch (((LPNMHDR) lParam) -> code)
{
case LVN_ITEMACTIVATE:
HWND hwndFrom = (HWND) ((LPNMHDR) lParam) -> hwndFrom;MarkedItemIndex =
ListView_GetNextItem(hwndFrom, -1, LVNI_SELECTED);
.....
Сообщение LVM_GETSELECTEDCOUNT
может использоваться для определения количества элементов, которые были активированы. Сообщение LVM_GETNEXTITEM
отправляется с атрибутом LVNI_SELECTED
, и все элементы были отредактированы.