我一直在网上搜索关于win32 API的不同内容,但似乎所有关于它的信息都相当稀疏。
我希望创建一个显示项目列表的简单窗口,但是我希望以表格式格式显示每个项目的不同数据列,在这种格式中,可能允许用户调整其他列的大小宽度。
如果可能的话,我还希望能够在代码中更改不同行的背景颜色,只需要一般的白色,红色,黄色或绿色。
用户也可以右键单击不同的行,并能够调用它们上的函数,或者将数据复制到剪贴板(但这部分是另一个故事)。
现在,我找到了可以放在窗口,按钮和右键菜单中的list-viewer对象(?)......但是我无法弄清楚如何使用Win32 API来创建表。除了窗口本身之外,我甚至都没有真正阅读过背景颜色。
我应该使用不同的,更好的框架,还是有一些我一直缺少的功能或项目?关于这个想法的所有帮助或指导将不胜感激......
我正在使用MSVC ++做我正在处理的所有事情。
答案 0 :(得分:10)
Windows提供了一个相当基本的内置控件集合,列出了here。
如果你想要更复杂的东西,你的选择是:
如果你坚持使用VC ++,The Grid Control和The Ultimate Grid是基于MFC的。
如果您没有使用MFC,则BABYGRID或The Win32 SDK Data Grid。
如果它们都不合适,那么搜索“grid”而不是“table”会更幸运。
答案 1 :(得分:8)
使用Windows API和标准控件ListView,您可以使用LVS_REPORT样式执行表格
文档链接 - 不幸的是没有代码:( -
我找到了这篇好文章Windows Programmierung: List View 解释是用德语,但谷歌翻译与代码应该足以理解它。从文章中,创建窗口:
#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)
等...
答案 2 :(得分:0)
对于Listview示例,没有什么比Classic Sample!
更清晰与此同时,谷歌翻译以及Unicode +微小的修改以拯救Listview的@ Alejadro德语链接 - 搜索结果中没有提供直接翻译作为页面不包含相应的meta tag。为了简洁起见,略微剪了一下:
后续的样式更改
创建后可以更改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);
}
mask字段确定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
消息会更改元素的属性。作为参数,您将获得指向ListView的LVITEMW
旁边的HWND
结构的指针,该结构必须提前填充。
详细结构要素:
面膜: 指定使用哪些元素。可以使用以下标志的组合:
LVIF_IMAGE iImage
LVIF_INDENT iIndent
LVIF_PARAM lParam
LVIF_STATE状态
LVIF_TEXT pszText
的iItem 与结构相关的项目的索引(从0开始)。
iSubItem 结构所涉及的子项的索引(从1开始)。如果结构引用的是项而不是子项,则为0。
pszText
指向以null结尾的字符串。如果值为LPWSTR_TEXTCALLBACK
,则为回调项。如果此更改,则必须将pszText设置为LPSTR_TEXTCALLBACK
,并通过LVM_SETITEMW
或LVM_SETITEMTEXT
通知ListView。
如果ListView的样式为pszText
或LPWSTR_TEXTCALLBACK
,则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优化其内存分配和释放。可以使用LVM_GETITEMCOUNT
确定ListView包含的元素数量。
编辑所选元素
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..Reports删除所有项目 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
属性一起发送,所有项目都已编辑。