1. #include <Windows.h>
    2. #include <Windowsx.h>
    3. #include <CommCtrl.h>
    4. #include "resource.h"
    5. #ifdef _UNICODE
    6. #if defined _M_IX86
    7. #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
    8. #elif defined _M_X64
    9. #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
    10. #else
    11. #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    12. #endif
    13. #endif
    14. // 向指定列表的指定位置添加指定列元素
    15. VOID InsertColumn(HWND hList, int nIndex, int nWidth = 0, LPCWSTR lpText = L"", int nFmt = LVCFMT_CENTER)
    16. {
    17. // 需要定义一个添加列必须用到的结构体,并[初始化其第一个字段 mask],表示哪一些字段是有效的
    18. LV_COLUMN lvColumn = { LVCF_FMT | LVCF_TEXT | LVCF_WIDTH };
    19. // 将用户传入的参数设置到结构体的指定字段中,对于添加的第一列数据,无论指定
    20. // 什么对齐方式,始终都是左对齐的,如果希望全部居中,可以先添加一个空列。
    21. lvColumn.fmt = nFmt;
    22. lvColumn.cx = nWidth;
    23. lvColumn.pszText = (LPWSTR)lpText;
    24. // 通过宏 ListView_InsertColumn 添加列
    25. ListView_InsertColumn(hList, nIndex, &lvColumn);
    26. }
    27. // 向指定的列表中指定的行添加相应内容
    28. VOID InsertItem(HWND hList, int nRow, LPCWSTR lpName, LPCWSTR lpAge, LPCWSTR lpSchool)
    29. {
    30. // 初始化一个结构体,并设置第一个成员为想要应用的字段类型
    31. LV_ITEM lvItem = { LVIF_TEXT };
    32. // 设置当前需要添加到的是哪一个位置
    33. lvItem.iItem = nRow;
    34. lvItem.iSubItem = 0;
    35. lvItem.pszText = (LPWSTR)L"";
    36. // 想要设置一行中字段的信息,必须要先添加一行
    37. ListView_InsertItem(hList, &lvItem);
    38. // 在单独的使用宏 ListView_SetItemText 设置每一行中每一列的内容
    39. ListView_SetItemText(hList, nRow, 1, (LPWSTR)lpName);
    40. ListView_SetItemText(hList, nRow, 2, (LPWSTR)lpAge);
    41. ListView_SetItemText(hList, nRow, 3, (LPWSTR)lpSchool);
    42. }
    43. // 对话框的回调函数,消息处理了返回 TRUE,没有处理返回 FALSE
    44. INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    45. {
    46. switch (uMsg)
    47. {
    48. // 当用户点击了关闭按钮时产生的消息,对话框要求必须使用 EndDialog 退出
    49. case WM_CLOSE:
    50. {
    51. EndDialog(hDlg, 0);
    52. break;
    53. }
    54. // 对话框的初始化消息是 WM_INITDIALOG,常用于进行控件的初始化
    55. case WM_INITDIALOG:
    56. {
    57. // 获取到列表控件的句柄
    58. HWND hList = GetDlgItem(hDlg, IDC_LIST1);
    59. // 为列表添加扩展风格,支持更多操作
    60. ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
    61. // 对于列表控件的报表风格,想要添加内容,最少需要有一列数据,所以先添加列
    62. InsertColumn(hList, 0);
    63. InsertColumn(hList, 1, 120, L"姓名", LVCFMT_CENTER);
    64. InsertColumn(hList, 2, 50, L"年龄", LVCFMT_CENTER);
    65. InsertColumn(hList, 3, 250, L"学校", LVCFMT_CENTER);
    66. // 在添加了列之后,添加每一行的信息
    67. InsertItem(hList, 0, L"小明", L"18", L"北京大学");
    68. InsertItem(hList, 1, L"小红", L"17", L"清华大学");
    69. InsertItem(hList, 2, L"小刚", L"19", L"野鸡大学");
    70. break;
    71. }
    72. // 列表控件是一个通用控件,需要通过 WM_NOTIFY 进行相应
    73. case WM_NOTIFY:
    74. {
    75. // WM_NOTIFY 的附加参数 lParam 指向的是结构体 NMHDR,保存了更多内容
    76. auto pNmhdr = (LPNMHDR)lParam;
    77. // 判断当前的消息是不是由列表控件产生的
    78. if (pNmhdr->idFrom == IDC_LIST1)
    79. {
    80. // 如果当前是列表控件,那么 lParam 指向的实际上是 NMLISTVIEW
    81. auto pNmListView = (LPNMLISTVIEW)lParam;
    82. // 筛选行为,只有在鼠标左键点击的时候才相应,弹出点击的内容
    83. if (pNmhdr->code == NM_CLICK && pNmListView->iItem != -1)
    84. {
    85. WCHAR lpBuffer[0x100]{};
    86. ListView_GetItemText(pNmhdr->hwndFrom,
    87. pNmListView->iItem,
    88. pNmListView->iSubItem,
    89. lpBuffer,
    90. 0x100);
    91. MessageBox(hDlg, lpBuffer, lpBuffer, MB_OK);
    92. }
    93. // 筛选行为,只有在鼠标右键点击的时候才相应,弹出点击的内容
    94. if (pNmhdr->code == NM_RCLICK && pNmListView->iItem != -1)
    95. {
    96. // 1. 获取当前光标的位置,获取的是相对屏幕的,不用转换
    97. POINT Point{};
    98. GetCursorPos(&Point);
    99. // 2. 找到菜单资源
    100. HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU1));
    101. HMENU hSubMenu = GetSubMenu(hMenu, 0);
    102. // 3. 弹出菜单
    103. TrackPopupMenu(hSubMenu, TPM_LEFTALIGN, Point.x, Point.y, 0, hDlg, NULL);
    104. }
    105. }
    106. break;
    107. }
    108. default:
    109. {
    110. return FALSE;
    111. }
    112. }
    113. return TRUE;
    114. }
    115. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    116. {
    117. // 1. 是实例句柄,用于标识资源所在的位置
    118. // 2. 资源的ID,大多数时候会使用 MAKEINTRESOURCE 进行转换
    119. // 3. 对话框的父窗口,NULL 表示桌面
    120. // 4. 回调函数,用于响应对话框产生的所有消息
    121. DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
    122. return 0;
    123. }

    image.png