Операционная система Windows 95 для программиста© Александр Фролов, Григорий ФроловТом 22, М.: Диалог-МИФИ, 1993, 271 стр. 3.1. Создание органа управления List ViewДля использования органа управления List View ваше приложение должно выполнить несколько действий:
Теперь мы подробно расскажем вам о том, как выполнить перечисленные выше действия. Создание окна List ViewОкно органа управления List View создается функцией CreateWindowEx на базе класса окна WC_LISTVIEW , например так: hwndList = CreateWindowEx(0L, WC_LISTVIEW, "", WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT | LVS_EDITLABELS, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hWnd, (HMENU)IDC_LISTVIEW, hInst, NULL); Перед вызовом этой функции вы должны загрузить в память DLL-библиотеку COMCTL32.DLL , для чего следует вызвать функцию InitCommonControls без параметров. В дополнение к обычным стилям окна, таким как WS_VISIBLE, WS_CHILD и WS_BORDER, необходимо указать специальные стили с префиксом имени LVS_, определяющие внешний вид и поведение органа управления List View. Как минимум, следует указать один из следующих четырех стилей: LVS_REPORT , LVS_ICON, LVS_SMALLICON или LVS_LIST. Ниже мы привели краткое описание этих, а также
остальных стилей окна List View.
Как мы уже говорили, стили LVS_REPORT, LVS_ICON, LVS_SMALLICON и LVS_LIST определяют режим работы органа управления List View. При создании этого органа управления вы должны указать только один из перечисленных стилей. Однако в дальнейшем если появится необходимость изменить режим работы, это можно будет легко сделать при помощи функций GetWindowLong и SetWindowLong . Когда список отображается в виде окна со стандартными или уменьшенными пиктограммами, у вас есть возможность выбрать один из нескольких способов выравнивания пиктограмм во внутренней области этого окна. Для этого вы должны указать один из следующих стилей: LVS_ALIGNLEFT, LVS_ALIGNTOP или LVS_AUTOARRANGE. По умолчанию (если не указан стиль LVS_ALIGNLEFT) пиктограммы выравниваются по верхней границе окна. Такое поведение соответствует стилю LVS_ALIGNTOP. Вы можете также выровнять пиктограммы по левой границе окна, задав стиль LVS_ALIGNLEFT. Разумеется, стили LVS_ALIGNTOP и LVS_ALIGNLEFT несовместимы, поэтому вы можете использовать только один из них. Для пользователя будет удобнее, если при изменении размеров окна просмотра пиктограммы будут автоматически перемещаться таким образом, чтобы по возможности занимать всю полезную площадь окна. Вы можете организовать автоматическое размещение пиктограмм, указав стиль LVS_AUTOARRANGE. Без этого стиля пользователю придется работать с полосой просмотра (Scrollbar), что не всегда удобно. Иногда необходимо заблокировать возможность изменения размеров окна просмотра, исключив стиль WS_BORDER. Например, вы можете создать окно просмотра фиксированного размера, расположенное в диалоговой панели. В этом случае вы не должны указывать стиль LVS_NOSCROLL, так как иначе пользователь не получит доступа ко всем элементам списка. Списки изображенийИтак, вы создали окно органа управления List View, выбрав для него подходящий набор стилей. Теперь следует заняться наполнением этого окна изображениями и элементами списка. В зависимости от того, в каких режимах будет работать создаваемый вами орган управления List View, вы должны создать один, два или три списка из следующего набора:
Как выбрать нужные списки? Список стандартных пиктограмм нужен только в том случае, если вы будете использовать орган управления List View в режиме LVS_ICON (рис. 3.2 в разделе "Приложение List Application"). Список пиктограмм уменьшенного размера нужен для всех остальных режимов (рис. 3.1, 3.3, 3.4).
Для создания списка изображения вы должны вызвать функцию ImageList_Create : HIMAGELIST WINAPI ImageList_Create( int cx, // ширина изображения int cy, // высота изображения UINT flags, // тип изображения int cInitial, // первоначальное количество изображений int cGrow); // количество изображений, на которое // увеличится размер списка при добавлении новых изображений Параметры cx и cy определяют, соответственно, ширину и высоту добавляемых изображений. Если вы создаете список пиктограмм стандартного или уменьшенного размера, для определения значения этих параметров следует использовать функцию GetSystemMetrics , передав ей в первом случае параметры SM_CXICON и SM_CYICON , а во втором - параметры SM_CXSMICON и SM_CYSMICON . Функция GetSystemMetrics была нами описана в 11 томе "Библиотеки системного программиста". Параметр flags определяет тип изображений, из
которых состоит список. Вы можете создавать
список из пиктограмм, аппаратно-зависимых
битовых изображений DDB или аппаратно-независимых
битовых изображений DIB. Приведем список
возможных значений параметра flags:
При создании списка изображений из пиктограмм в SDK значение параметра flags рекомендуется указывать как TRUE, однако логичнее указать значение ILC_MASK. Параметр cInitial определяет размер блока памяти, выделяемого для хранения изображений, так как этот размер зависит от количества изображений. При добавлении в созданный список новых изображений сверх значения, указанного в этом параметре, происходит динамическое изменение размера заказанного блока памяти. Такое изменение выполняется в соответствии со значением параметра cGrow. Функция ImageList_Create при нормальном завершении возвращает идентификатор созданного списка изображений, который надо сохранить для дальнейшего использования. В случае ошибки возвращается значение NULL. Ниже приведен пример создания двух списков, в которые первоначально будет добавлено девять изображений: himlSmall = ImageList_Create( GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), ILC_MASK, 9, 1); himlLarge = ImageList_Create( GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_MASK, 9, 1); Заполнение списков изображенийМы только что создали списки изображений, однако пока они пустые и орган управления List View ничего о них "не знает". Для добавления изображений вы можете воспользоваться функцией ImageList_AddIcon : int WINAPI ImageList_AddIcon( HIMAGELIST himl, // идентификатор списка изображений HICON hicon // идентификатор добавляемого изображения ); Если вы добавляете в список пиктограммы, определенные в ресурсах приложения, вызов функции ImageList_AddIcon можно выполнять в цикле, загружая пиктограммы функцией LoadIcon : for(i = IDI_ICON1; i <= IDI_ICON9; i++) { hIcon = LoadIcon(hInst, MAKEINTRESOURCE(i)); ImageList_AddIcon(himlSmall, hIcon); ImageList_AddIcon(himlLarge, hIcon); } Заметьте, что после добавления пиктограммы не уничтожаются явным образом, так как при необходимости система сделает это автоматически. Подключение списков изображений к органу List ViewНа данном этапе мы создали и заполнили списки изображений. Теперь их надо подключить к органу управления List View, вызвав макрокоманду ListView_SetImageList : HIMAGELIST ListView_SetImageList( HWND hwnd, // идентификатор окна органа List View HIMAGELIST himl, // идентификатор подключаемого списка int iImageList); // тип изображений в списке Первые два параметра макрокоманды задают, соответственно, идентификатор окна органа List View и идентификатор подключаемого списка, который мы только что создали и заполнили. Параметр iImageList может иметь следующие значения:
Макрокоманда ListView_SetImageList посылает органу управления List View сообщение LVM_SETIMAGELIST и определена следующим образом: #define ListView_SetImageList(hwnd, himl, iImageList) \ (HIMAGELIST)(UINT)SendMessage((hwnd), LVM_SETIMAGELIST, \ (WPARAM)(iImageList), (LPARAM)(UINT)(HIMAGELIST)(himl)) Вы можете посылать сообщение LVM_SETIMAGELIST непосредственно, однако макрокомандой удобнее пользоваться. Вот соответствующий фрагмент исходного текста приложения, подключающий два списка: ListView_SetImageList(hwndList, himlSmall, LVSIL_SMALL); ListView_SetImageList(hwndList, himlLarge, LVSIL_NORMAL); Вставка столбцовЕсли вы собираетесь просматривать список в виде детального отчета (стиль LVS_REPORT), необходимо вставить нужное количество столбцов, а также определить для каждого столбца заголовок и ширину. Вставка столбцов выполняется макрокомандой ListView_InsertColumn , посылающей органу управления сообщение LVM_INSERTCOLUMN : int ListView_InsertColumn( HWND hwnd, // идентификатор органа List view int iCol, // номер столбца const LV_COLUMN FAR * pcol); // адрес структуры LV_COLUMN Нумерация столбцов начинается с нуля. Перед тем как вызывать макрокоманду ListView_InsertColumn, вы должны по очереди для каждого столбца заполнить структуру LV_COLUMN , определенную следующим образом: typedef struct _LV_COLUMN { UINT mask; // маска использования полей структуры LV_COLUMN int fmt; // тип выравнивания для столбца int cx; // ширина столбца в пикселах LPTSTR pszText; // адрес строки заголовка столбца int cchTextMax; // размер буфера, адрес которого // задан в pszText int iSubItem; // номер дополнительного элемента } LV_COLUMN; Поле маски mask определяет, какие из полей
структуры LV_COLUMN будут использованы. Ниже мы
перечислили возможные значения масок, которые
можно объединять при помощи логической операции
ИЛИ:
Поле fmt определяет тип выравнивания для столбца. Можно указывать одно из следующих значений: LVCFMT_LEFT, LVCFMT_RIGHT или LVCFMT_CENTER. Они задают, соответственно, выравнивание влево, вправо или по центру столбца. Ширина столбца в пикселах задается полем cx. Для того чтобы задать заголовок столбца, вы должны определить буфер и записать в него соответствующую текстовую строку, закрыв ее двоичным нулем. Размер буфера должен быть указан в поле cchTextMax (в байтах). Теперь о поле iSubItem. Как мы уже говорили раньше, список содержит элементы, каждый из которых имеет имя и связанную с ним пиктограмму (привязка пиктограммы выполняется на этапе добавления строк). Кроме того, для каждого элемента можно задать дополнительные элементы. В SDK элементы называются item, а дополнительные элементы - subitem. В режиме детального отчета пиктограмма и название элемента отображаются в самом левом столбце, имеющим номер 0. Дополнительные элементы, заданные в виде текстовых строк, отображаются в остальных столбцах детального отчета (с номерами 1, 2 и т. д.). В поле iSubItem вы должны записать номер дополнительного элемента, который будет связан с текущим столбцом отчета. Ниже приведен фрагмент кода, в котором выполняется вставка трех столбцов с номерами 0, 1 и 2: GetClientRect(hWnd, &rc); memset(&lvc, 0, sizeof(lvc)); lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.fmt = LVCFMT_LEFT; lvc.cx = (rc.right - rc.left) / 4; lvc.iSubItem = 0; lvc.pszText = "Application Name"; ListView_InsertColumn(hwndList, 0, &lvc); lvc.iSubItem = 1; lvc.pszText = "Icon Name"; ListView_InsertColumn(hwndList, 1, &lvc); lvc.iSubItem = 2; lvc.pszText = "Cost, USD"; ListView_InsertColumn(hwndList, 2, &lvc); ListView_SetColumnWidth(hwndList,2,(rc.right - rc.left) / 8); Ширина первого и второго столбца устанавливается равной четверти ширины главного окна приложения (которая в нашем случае равна ширине окна органа управления List View). Ширина третьего столбца устанавливается равной одной восьмой ширины окна, причем для разнообразия мы делаем это при помощи макрокоманды ListView_SetColumnWidth . Эта макрокоманда посылает органу List View сообщение LVM_SETCOLUMNWIDTH . Такую процедуру можно выполнять и позже, а не только в момент создания окна органа управления List View. Вставка элементов спискаНа последнем этапе вы должны вставить в список элементы. Проще всего это сделать с помощью макрокоманды ListView_InsertItem , посылающей органу управления List View сообщение LVM_INSERTITEM : int ListView_InsertItem( HWND hwnd, // идентификатор окна List View const LV_ITEM FAR * pitem); // адрес структуры LV_ITEM Перед тем как вставлять элемент, вы должны записать его атрибуты в структуру LV_ITEM , определенную следующим образом: typedef struct _LV_ITEM { UINT mask; // маска использования полей структуры LV_ITEM int iItem; // номер элемента int iSubItem; // номер дополнительного элемента UINT state; // текущее состояние элемента UINT stateMask; // маска состояния элемента LPTSTR pszText; // адрес текстового буфера int cchTextMax; // размер текстового буфера int iImage; // номер пиктограммы элемента LPARAM lParam;// 32-битовое значение, связанное с элементом } LV_ITEM; Поле маски mask определяет, какие из полей
структуры LV_ITEM будут использованы при добавлении
элементов. Возможны следующие значения масок (их
можно объединять при помощи логической операции
ИЛИ):
Ниже мы привели фрагмент исходного текста приложения List Application, в котором к созданному ранее списку добавляется 9 элементов: memset(&lvi, 0, sizeof(lvi)); lvi.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM; lvi.pszText = LPSTR_TEXTCALLBACK; for(i=0; i<9; i++) { lvi.iItem = i; lvi.iSubItem = 0; lvi.cchTextMax = 40; lvi.lParam = (LPARAM)&rgApplInfo[i]; lvi.iImage = i; ListView_InsertItem(hwndList, &lvi); lvi.iItem = i; lvi.iSubItem = 1; ListView_InsertItem(hwndList, &lvi); lvi.iItem = i; lvi.iSubItem = 2; ListView_InsertItem(hwndList, &lvi); } Так как в нашем примере пиктограммы состояния элементов не используются, мы не заполняем поля state и stateMask. В поле iItem мы записываем номер элемента, изменяя его в цикле от 0 до 9. Аналогичным образом мы поступаем и с полем iImage, записывая в него номер пиктограммы для элемента. Напомним, что в разных режимах работы органа управления List View будут использованы пиктограммы из разных списков (стандартного и уменьшенного размера). В поле pszText можно было бы записать адрес текстовой строки, соответствующей названию элемента или дополнительному элементу, однако мы занесли туда значение LPSTR_TEXTCALLBACK . В этом случае адрес нужной строки будет предоставляться при обработке соответствующего извещения, о чем речь еще впереди. На этом мы завершим описание процесса создания и наполнения органа управления List View. Из-за ограниченного объема книги мы не рассмотрели все особенности процесса. За более подробной информацией вы можете обратиться к справочной документации, которая поставляется вместе с SDK. |