Я искал сеть для разных вещей о win32 API, но, похоже, вся информация о ней довольно скудная.
Я хочу создать простое окно, которое отображает список элементов, однако я хочу отображать разные столбцы данных для каждого элемента в формате табличного стиля, где пользователю может быть позволено изменять размер столбца ширина.
Если это вообще возможно, я также хотел бы изменить цвета фона разных строк в коде между просто общим белым, красным, желтым или зеленым цветом.
И пользователю также будет позволено щелкнуть правой кнопкой мыши по разным строкам и иметь возможность вызвать на них функцию или скопировать данные в буфер обмена (но эта часть - другая история).
Теперь я нашел объекты list-viewer (?), которые можно поместить в окно, кнопки и контекстные меню... но я не могу понять, как сделать таблицу, используя API Win32. Я даже не читал цвета фона для чего-либо, кроме самого окна.
Есть ли другая, лучшая структура, которую я должен использовать для этого, или есть некоторые функции или элементы, которые мне не хватало? Вся помощь или руководство по этой идее будут оценены...
Я использую MSVС++, чтобы сделать... все, над чем я работаю.
Ответ 3
Для примеров Listview ничто не сравнится с ясностью Классический пример!
Тем временем, Google Translate with Unicode + крошечные модификации для спасения для ссылки @Alejadro German для 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. Класс window использует константу 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
, и все элементы были отредактированы.