#include <Windows.h>
#include <Windowsx.h>
#include <CommCtrl.h>
#include "resource.h"
#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif
// 向指定列表的指定位置添加指定列元素
VOID InsertColumn(HWND hList, int nIndex, int nWidth = 0, LPCWSTR lpText = L"", int nFmt = LVCFMT_CENTER)
{
// 需要定义一个添加列必须用到的结构体,并[初始化其第一个字段 mask],表示哪一些字段是有效的
LV_COLUMN lvColumn = { LVCF_FMT | LVCF_TEXT | LVCF_WIDTH };
// 将用户传入的参数设置到结构体的指定字段中,对于添加的第一列数据,无论指定
// 什么对齐方式,始终都是左对齐的,如果希望全部居中,可以先添加一个空列。
lvColumn.fmt = nFmt;
lvColumn.cx = nWidth;
lvColumn.pszText = (LPWSTR)lpText;
// 通过宏 ListView_InsertColumn 添加列
ListView_InsertColumn(hList, nIndex, &lvColumn);
}
// 向指定的列表中指定的行添加相应内容
VOID InsertItem(HWND hList, int nRow, LPCWSTR lpName, LPCWSTR lpAge, LPCWSTR lpSchool)
{
// 初始化一个结构体,并设置第一个成员为想要应用的字段类型
LV_ITEM lvItem = { LVIF_TEXT };
// 设置当前需要添加到的是哪一个位置
lvItem.iItem = nRow;
lvItem.iSubItem = 0;
lvItem.pszText = (LPWSTR)L"";
// 想要设置一行中字段的信息,必须要先添加一行
ListView_InsertItem(hList, &lvItem);
// 在单独的使用宏 ListView_SetItemText 设置每一行中每一列的内容
ListView_SetItemText(hList, nRow, 1, (LPWSTR)lpName);
ListView_SetItemText(hList, nRow, 2, (LPWSTR)lpAge);
ListView_SetItemText(hList, nRow, 3, (LPWSTR)lpSchool);
}
// 对话框的回调函数,消息处理了返回 TRUE,没有处理返回 FALSE
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
// 当用户点击了关闭按钮时产生的消息,对话框要求必须使用 EndDialog 退出
case WM_CLOSE:
{
EndDialog(hDlg, 0);
break;
}
// 对话框的初始化消息是 WM_INITDIALOG,常用于进行控件的初始化
case WM_INITDIALOG:
{
// 获取到列表控件的句柄
HWND hList = GetDlgItem(hDlg, IDC_LIST1);
// 为列表添加扩展风格,支持更多操作
ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
// 对于列表控件的报表风格,想要添加内容,最少需要有一列数据,所以先添加列
InsertColumn(hList, 0);
InsertColumn(hList, 1, 120, L"姓名", LVCFMT_CENTER);
InsertColumn(hList, 2, 50, L"年龄", LVCFMT_CENTER);
InsertColumn(hList, 3, 250, L"学校", LVCFMT_CENTER);
// 在添加了列之后,添加每一行的信息
InsertItem(hList, 0, L"小明", L"18", L"北京大学");
InsertItem(hList, 1, L"小红", L"17", L"清华大学");
InsertItem(hList, 2, L"小刚", L"19", L"野鸡大学");
break;
}
// 列表控件是一个通用控件,需要通过 WM_NOTIFY 进行相应
case WM_NOTIFY:
{
// WM_NOTIFY 的附加参数 lParam 指向的是结构体 NMHDR,保存了更多内容
auto pNmhdr = (LPNMHDR)lParam;
// 判断当前的消息是不是由列表控件产生的
if (pNmhdr->idFrom == IDC_LIST1)
{
// 如果当前是列表控件,那么 lParam 指向的实际上是 NMLISTVIEW
auto pNmListView = (LPNMLISTVIEW)lParam;
// 筛选行为,只有在鼠标左键点击的时候才相应,弹出点击的内容
if (pNmhdr->code == NM_CLICK && pNmListView->iItem != -1)
{
WCHAR lpBuffer[0x100]{};
ListView_GetItemText(pNmhdr->hwndFrom,
pNmListView->iItem,
pNmListView->iSubItem,
lpBuffer,
0x100);
MessageBox(hDlg, lpBuffer, lpBuffer, MB_OK);
}
// 筛选行为,只有在鼠标右键点击的时候才相应,弹出点击的内容
if (pNmhdr->code == NM_RCLICK && pNmListView->iItem != -1)
{
// 1. 获取当前光标的位置,获取的是相对屏幕的,不用转换
POINT Point{};
GetCursorPos(&Point);
// 2. 找到菜单资源
HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU1));
HMENU hSubMenu = GetSubMenu(hMenu, 0);
// 3. 弹出菜单
TrackPopupMenu(hSubMenu, TPM_LEFTALIGN, Point.x, Point.y, 0, hDlg, NULL);
}
}
break;
}
default:
{
return FALSE;
}
}
return TRUE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// 1. 是实例句柄,用于标识资源所在的位置
// 2. 资源的ID,大多数时候会使用 MAKEINTRESOURCE 进行转换
// 3. 对话框的父窗口,NULL 表示桌面
// 4. 回调函数,用于响应对话框产生的所有消息
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
return 0;
}
