Создание таблицы с помощью Win32 API
Я искал в сети разные вещи об API win32, но, похоже, вся информация об этом довольно разрежена.
Я ищу, чтобы создать простое окно, которое показывает список элементов, однако я хочу отображать разные столбцы данных для каждого элемента в формате таблицы, где пользователю, возможно,будет разрешено изменять ширину столбцов.
Если это вообще возможно, я хотел бы также иметь возможность изменять цвета фона разных строки, в коде, между общим белым, красным, желтым или зеленым.
и пользователю также будет разрешено щелкнуть правой кнопкой мыши разные строки и иметь возможность вызвать функцию на них или скопировать данные в буфер обмена (но эта часть-другая история).
теперь я нашел объекты просмотра списка (?), которые могут быть размещены в окне, кнопках и меню правой кнопкой мыши... но я не могу понять, как сделать таблицу, используя Win32 API. Я даже толком не читал цвета фона для всего, кроме самого окна.
есть ли другая, лучшая структура, которую я должен использовать для этого, или есть некоторые функции или элементы, которые я пропустил? Любая помощь или руководство по этой идее будут оценены...
Я использую MSVC++ для этого... все, над чем я работаю.
3 ответов
Windows предоставляет довольно простую коллекцию встроенных элементов управления, перечисленных здесь.
Если вы хотите что-то более изощренное ваши варианты:
- код сам. Вы должны нарисовать его сами, обрабатывать все пользовательское взаимодействие, прокрутку и т. д. Это большая работа.
- найти существующую реализацию.
- отказаться от VC++ и использовать WinForms или WPF.
Если вы застряли с VC++, в Элемент Управления Grid и Конечная Сетка основаны на MFC.
Если вы не используете MFC, есть BABYGRID или сетка данных Win32 SDK.
Если ни один из них не подходит, вам больше повезет в поиске "сетки", чем "таблицы".
используя Windows API и стандартный элемент управления ListView вы можете сделать таблицу, используя стиль LVS_REPORT
ссылка на документацию-к сожалению, без кода : ( -
О Списке-Просмотр Элементов Управления
Я нашел эту хорошую статью Windows Programmierung: Просмотр Списка объяснение на немецком языке, но перевод google вместе с кодом должно быть достаточно, чтобы понять его. Из статьи, чтобы создать окно:
#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);
затем объясняется, как создать столбцы в методе
int CreateColumn(HWND hwndLV, int iCol, char *Text, int iWidth)
как вставить элемент (одну колонку)
int CreateItem(HWND hwndList, char *Text)
или вставить элемент с двумя колонками
int Create2ColItem(HWND hwndList, char *Text1, char *Text2)
etc...
для примеров Listview ничто не сравнится с ясностью Классический Пример!
тем временем, Google Translate вместе с Unicode + крошечные модификации для спасения немецкой ссылки @Alejadro для ListView с - нет прямого перевода на предложение из результатов поиска, поскольку страница не содержит соответствующего мета-тег. Коротко для краткости:--55-->
последующие изменения стили
стиль 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
. Для этого файл заголовка common control должен быть включенный.
#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.Либ) включен.
столбцы 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 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
(in 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-based) подэлемента, к которому структура взаимосвязана. 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 изменить на текст
перед вставкой нескольких элементов,LVM_SETITEMCOUNT
в ListView будет отправлено сообщение, указывающее, сколько элементов в конечном итоге будет содержаться. Это позволяет 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......Указывает, что пользователь нажал в заголовке отчета display
О 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
сообщение может использоваться для определения количества активированных элементов. The LVM_GETNEXTITEM
сообщение отправлено с LVNI_SELECTED
атрибут и все элементы были отредактированы.