Windows api c language lvitem structure как заполнять listview

Обновлено: 06.07.2024

Второй день бьюсь над простейшим вопросом. Есть элемент управления listview32 — список, режим "отчёт" (таблица). В нём — две колонки (как добавлять туда колонки, я сообразил почти сразу). Теперь надо добавить хотя бы одну строчку. В интернете — тонны примеров, на их основе я сваял следующий код:

Вроде и ошибиться-то негде, а — не работает. Подскажите, куда рыть-то дальше?

Здравствуйте, TheMaster, Вы писали:

TM>

Глобальная-то глобальная, а что в ней?

Здравствуйте, VladFein, Вы писали:

VF>Здравствуйте, TheMaster, Вы писали:

TM>>

VF>Глобальная-то глобальная, а что в ней?

Да всё очень просто, куда уж проще:

Я, собсно, потому это даже и не писал.

Здравствуйте, TheMaster, Вы писали:

TM>Подскажите, куда рыть-то дальше?

— кодировка в проекте UNICODE? Лучше, чтоб не путаться, использовать TCHAR(и TEXT/_T макросы) вместо char и wchar_t (если это MS VC++, конечно)
— а если вместо глобальной строки поставить константу? Локальную переменную?
— после LVM_SETITEM посмотреть GetLastError(), предварительно сбросив до вызова её SetLastError(0)
— под дебагом посмотреть, что указатель из LVITEM указывает именно на строку.
— а если потом LVM_GETITEM вызвать и посмотреть, что вернётся в тексте?

Поколупал ещё немного — чудеса какие-то получаются.
Взял пример, где ListView создаётся динамически. Там всё замечательно, всё работает. У меня — это статический control, прописанный в ресурсах.
Поэтому — через define создаю два варианта "развития событий": динамический и статический.
В инициализации диалогового окна:

Функция создания ListView у меня выглядит следующим образом:

Вся разница между вариантами — в одном случае у меня GetDlgItem, а в другом — CreateWindow.
На всякий случай приведу выдержку из файла ресурсов:

Флаги у меня строго такие же, как и у "динамического" режима.
А вот теперь — привожу код функции добавления строчек:

В функции представляют интерес две строчки. Первая вставляет первую колонку (item), вторая — все остальные (subitem'ы). Так вот, первая строчка всегда работает как надо. А вторая — творит чудеса: во время первого вызова при инициализации она отрабатывает правильно, а вот во время второго (и всех последующих) вызовов — не делает ничего! Она выполняется нужное количество раз, но — не добавляет эти самые subitem'ы. В статическом режиме; в динамическом — всё в порядке.
В примере добавлена функциональность чтения item'ов и subitem'ов: тыкаешь их мышкой, их величина отображается ниже списка. В динамическом режиме — всё работает. В статическом режиме — работает только первая строчка, в остальных строчках subitem'ы не отображаются (с item'ами всё в порядке). Ума не приложу, что за колдунство?

Здравствуйте, TheMaster, Вы писали:

TM>LVS_REPORT|WS_CHILD|LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT, 05, 05, 190, 175

Возможно, эти стили совпадают с какими-то иными стилями, которые дают нежелательны эффект.

Здравствуйте, TheMaster, Вы писали:

TM>На всякий случай приведу выдержку из файла ресурсов:

Так мельзя устанавливать extended styles; смотрите CONTROL

Вы просто добавляете значение LVS_EX_FULLROWSELECT (0х20) к стилю, что совпадает LVS_SORTDESCENDING.

Таким образом лист у Вас — сортирован, и новый элемент вставляется не туда, куда Вы думаете; потом Вы продолжаете устанавливать текст совсем другому элементу.

Создаю на WinApi ListView

WS_REPORT|WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|LVS_AUTOARRANGE,

Пытаюсь создать колонки

В итоге колонки создаются но текст в них не отображается. Подскажите в чем проблема?

lvColumn.pszText =TEXT("Name");
ListView_InsertColumn(hWnd,0, &lvColumn);

Насколько я понимаю после этого должен отобразиться заголовок столбца но его нету. есть только сам столбец

Насколько я понимаю после этого должен отобразиться заголовок столбца но его нету. есть только сам столбец

Здравтствуйте всем.
У меня тоже проблемы из этой же области.
Колонки создаются, но никак не могу добавить элемент в ListView (состоящий из 3 колонок), подскажите, пож., что не так?

void SetColumnStructure(LVCOLUMN* Column, int Width, TCHAR* Caption, int CaptionSize, int SubItemIndex) hList = GetDlgItem(hwndDlg, IDC_L_DEV); // IDC_L_DEV - индентификатор ресурса SetColumnStructure(&ColumnStruct, D_ObjAdressColLength, SetColumnStructure(&ColumnStruct, D_DevAdressColLength, SetColumnStructure(&ColumnStruct, D_IpAdressColLength, return false; //-в этом месте прога стреляется, т. е. ListView_SetItem возвращает false

ТАк с добавлением item-ов я разобрался, теперь другая проблема
При нажатии на элемент в лист-вью выделяется только содержимое первой колонки..
А как сделать так, чтобы при нажатии на элемент (в любой колонке) в цвет выделения окрашивался весь элемент (вся строка ListView)? Или хотя бы окрашивались всё содержимое колонок для данного элемента?

А как через SendMessage или SendItemMessage или ещё как?

Я просто мож чё не понимаю. Я с листом через ресурс работаю и CALLBACK функцию.

Или этот стиль ставится для листа в CreateWindow функции? Я её не использую. И если это так, то я понимаю, что его добавление после того как лист был создан на диалоге никаких изменений не вызовет? Т. е. надо будет создавать лист через CreateWindow и уже там вносить все изменения для свойств и настроек данного листа?

Через редактор ресурсов Visual Stidio 2010 Ultimate создал диалоговое окно, содержащее окно типа ListView. Далее на C++ с помощью Win32 API добавил три колонки в ListView и два элемента. Сделал это я так:

Получилось вот что:

Изображение

В данный момент меня интересуют три вопроса, именно связанных с ListView.

ВОПРОС №1
Сейчас элементы в списке выбираются только если я буду щёлкать мышкой на поле имени, и то не в любом месте поля, а только там, где содержится текст. То есть так:

Изображение

А как сделать так, чтобы у меня элемент выбирался если я щёлкну в любом месте строчки и чтобы помечалась выделенной вся строка элемента?

ВОПРОС №2
Как сделать так, чтобы значения в определённом поле выравнивались вправо? Именно нужно сделать так, чтобы только значение в поле выравнивалось, а не так, чтобы выравнивалось имя самого столбца, что само собой приведёт к выравниваю значения элемента. Нужно сделать так, чтобы имя поля было выравнено влево, а значение всех элементов данного поля было выравнено вправо. Это мне нужно для поля Размер.

ВОПРОС №3
Я решил поменять цвета. Вот что получилось в коде:

И вот что получилось:

Изображение

А если я выделю, то получается так:

Изображение

Если Вы мне дадите ответ на мой первый вопрос, тогда я смогу сделать чтобы выделялась вся строка. Но данный вопрос в другом. Как можно изменить цвет фона выделенного элемента и как можно изменить цвет текста выделенного элемента?

Собираюсь делать что-то типа Total Commander, только который будет работать с моей файловой системой.

Как использовать TreeView:(В режиме просмотра деталей)
1. Создайте заголовок TreeView.
2. Создайте элемент TreeView
3. Создайте вложенный элемент в элементе TreeView.

Если метод разделения каждой части:
1. Создайте заголовок TreeView.
2. Создать элемент
3. Создайте вложенный элемент
4. Добавить вложенный элемент в элемент
5. Добавить элемент в TreeView

Примечание.
В режиме View.Details элемент Item эквивалентен созданию данных в основной строке; SubItem эквивалентен созданию данных в других строках.
В других режимах создавать SubItem не нужно.

Давайте воспользуемся примерами для изучения. Например, реализация следующей функции.


namespace ListViewExercise
public partial class Form1 : Form
public Form1()
InitializeComponent();
ListViewSet();
CreateViewItemMethodOne();
// CreateViewItemMethodTow();
>

/// <summary>
/// Настройки ListView
/// </summary>
private void ListViewSet()
// Режим отображения ListView
listViewControl.View = View.Details;
>

// 2、 Добавьте первый элемент в режиме View.Details, как значение в первом столбце
listViewControl.Items.Add( " folder1 " , " Папка 1 " , 0 );
// 3、 Добавьте первый вложенный элемент первого элемента в режиме View.Details, как значение в первом столбце
listViewControl.Items[ " folder1 " ].SubItems.Add( " 11 " );
// Добавьте второй SubItem первого Item в режиме View.Details, немного похожий на значение в первом столбце
listViewControl.Items[ " folder1 " ].SubItems.Add( " 20080114 " );

listViewControl.Items.Add( " folder2 " , " Папка 2 " , 0 );
listViewControl.Items[ " folder2 " ].SubItems.Add( " 21 " );
listViewControl.Items[ " folder2 " ].SubItems.Add( " 20080115 " );

listViewControl.Items.Add( " Папка 3 " );
listViewControl.Items.Add( " Папка 4 " );

// Реализуйте элемент в режиме View.Details, что немного похоже на добавление первого значения первой строки
lvItem = new ListViewItem();
// Отображаемый текст элемента
lvItem.Text = " Папка 1 " ;
// 4、 Элемент добавляется в элемент управления ListView, то есть добавляется первая строка. В режиме View.Details это немного похоже на добавление первого значения первого столбца первого элемента.
listViewControl.Items.Add(lvItem);

// Создать экземпляр SubItem
lvSubItem = new ListViewItem.ListViewSubItem();
lvSubItem.Text = " 10 " ;
// 5、 Добавить SubItem к первому элементу. В режиме View.Details это немного похоже на добавление первого значения второго столбца первого элемента.
lvItem.SubItems.Add(lvSubItem);


Пример 2:
Получить список папок и имен файлов в указанной папке. Как показано ниже:


namespace ListViewExercise
public partial class Form1 : Form
public Form1()
InitializeComponent();
ListViewSet();
GetFolderTreeView( @" c:\ " );
>

/// <summary>
/// Настройки ListView
/// </summary>
private void ListViewSet()
// Режим отображения ListView
listViewControl.View = View.Details;


// Событие двойного щелчка по элементу
listViewControl.ItemActivate += new EventHandler(listViewControl_ItemActivate);
// Событие кнопки возврата
btnReturn.Click += new EventHandler(btnReturn_Click);
>

// Начать обновление
listViewControl.BeginUpdate();

DirectoryInfo diInfo = new DirectoryInfo(asPath);
DirectoryInfo[] dirs = diInfo.GetDirectories();
FileInfo[] fiInfo = diInfo.GetFiles();

ListViewItem lviItem;
ListViewItem.ListViewSubItem lviSubItem;

foreach (DirectoryInfo di in dirs)
lviItem = new ListViewItem();
lviItem.Text = di.Name;
// Получить путь к папке
lviItem.Tag = di.FullName;

lviSubItem = new ListViewItem.ListViewSubItem();
// Папка не имеет размера
lviSubItem.Text = "" ;
lviItem.SubItems.Add(lviSubItem);

lviSubItem = new ListViewItem.ListViewSubItem();
lviSubItem.Text = di.CreationTime.ToString();
lviItem.SubItems.Add(lviSubItem);

foreach (FileInfo fi in fiInfo)
lviItem = new ListViewItem();
lviItem.Text = fi.Name;

lviSubItem = new ListViewItem.ListViewSubItem();
lviSubItem.Text = fi.Length.ToString();
lviItem.SubItems.Add(lviSubItem);

lviSubItem = new ListViewItem.ListViewSubItem();
lviSubItem.Text = fi.CreationTime.ToString();
lviItem.SubItems.Add(lviSubItem);

listViewControl.Items.Add(lviItem);
>
// Конец обновления
listViewControl.EndUpdate();
>


/// <summary>
/// Определите путь хранения переменных
/// </summary>
string sfileName = "" ;

Читайте также: