#include <Windows.h>
#include <CommCtrl.h>
#include <windowsx.h>
#include "resource.h"
/**
通用控件 需要捕获notify消息
WM_NOTIFY 消息
当事件发生或控件需要一些信息时,由公共控件发送到其父窗口。
参数
wParam
发送消息的公共控件的标识符。 不保证此标识符是唯一的。
应用程序应使用 NMHDR 结构的 hwndFrom 或 idFrom 成员 (作为 lParam 参数传递) 来标识控件。
lParam
指向包含通知代码和其他信息的 NMHDR 结构的指针。 对于某些通知消息,此参数指向将 NMHDR
结构作为其第一个成员的较大结构。
扩展:获取更详细的列表通知信息 LVM_GETITEMTEXTW
当通知码是LVN_xxx(列表专属)时,lParam可强转为NMLISTVIEW结构体(包含项索引、列索引、状态等):
typedef struct tagNMLISTVIEW {
NMHDR hdr; // 基础NMHDR结构体
int iItem; // 项索引(-1表示无)
int iSubItem; // 列索引
UINT uNewState; // 新状态
UINT uOldState; // 旧状态
UINT uChanged; // 变化的状态类型
POINT ptAction; // 操作的坐标
LPARAM lParam; // 项关联的自定义数据
} NMLISTVIEW, *LPNMLISTVIEW;
*/
void CenterWindow(HWND hWnd);
void SetWindowG(HWND hwnd, int width, int height);
INT_PTR CALLBACK Dlgproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL InsertColum(HWND hwnd,int nIDDlgItem,int nColum,LPWSTR columName, int columWidth);
BOOL InsertItem(HWND hwnd, int nIDDlgItem, int nRow);
BOOL SetListItemText(HWND hwnd, int nIDDlgItem, int nRow, int nColumn, LPWSTR columnName);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_DIALOG1), NULL, Dlgproc);
return 0;
}
INT_PTR CALLBACK Dlgproc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
SetWindowG(hwnd, 800, 530);
ListView_SetExtendedListViewStyle(GetDlgItem(hwnd,IDC_LIST1),LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
InsertColum(hwnd, IDC_LIST1, 0, (LPWSTR)L"", 0);
InsertColum(hwnd, IDC_LIST1, 1, (LPWSTR)L"映像名称", 80);
InsertColum(hwnd, IDC_LIST1, 2, (LPWSTR)L"用户名", 120);
InsertColum(hwnd, IDC_LIST1, 3, (LPWSTR)L"CPU", 120);
InsertColum(hwnd, IDC_LIST1, 4, (LPWSTR)L"描述", 120);
//插入一行
InsertItem(hwnd, IDC_LIST1, 0);
SetListItemText(hwnd, IDC_LIST1, 0,0,(LPWSTR)L"");
SetListItemText(hwnd, IDC_LIST1, 0, 1, (LPWSTR)L"11");
SetListItemText(hwnd, IDC_LIST1, 0, 2, (LPWSTR)L"22");
SetListItemText(hwnd, IDC_LIST1, 0, 3, (LPWSTR)L"33");
InsertItem(hwnd, IDC_LIST1, 1);
SetListItemText(hwnd, IDC_LIST1, 1, 0, (LPWSTR)L"");
SetListItemText(hwnd, IDC_LIST1, 1, 1, (LPWSTR)L"1111");
SetListItemText(hwnd, IDC_LIST1, 1, 2, (LPWSTR)L"2222");
SetListItemText(hwnd, IDC_LIST1, 1, 3, (LPWSTR)L"3333");
//LVITEMW lvitem = { LVIF_TEXT,0 };
////lvitem.iItem = 0;
//lvitem.pszText = (LPWSTR)L"123.EXE";
//SendDlgItemMessageW(hwnd, IDC_LIST1, LVM_INSERTITEM,0, (LONG)&lvitem);
/*lvitem.iSubItem = 1;
lvitem.pszText = (LPWSTR)L"3333123.EXE";
SendDlgItemMessageW(hwnd, IDC_LIST1, LVM_SETITEMTEXTW, 0, (LONG)&lvitem);
lvitem.iSubItem = 2;
lvitem.pszText = (LPWSTR)L"7777123.EXE";
SendDlgItemMessageW(hwnd, IDC_LIST1, LVM_SETITEMTEXTW, 0, (LONG)&lvitem);*/
break;
}
case WM_NOTIFY:
{
/**
WM_NOTIFY的lParam并非控件句柄,而是指向NMHDR结构体的指针(包含通知源、通知类型等核心信息),
你直接用(HWND)lParam判断控件句柄会导致逻辑完全错误。
typedef struct tagNMHDR {
HWND hwndFrom; // 发送通知的控件句柄(对应IDC_LIST1)
UINT idFrom; // 发送通知的控件ID(IDC_LIST1)
UINT code; // 具体的通知码(如列表控件的LVN_ITEMCHANGED、NM_CLICK等)
} NMHDR, *LPNMHDR;
如果消息来源是list控件,那么lparam 指向的是一个完整的结构体指针
*/
// 第一步:取出NMHDR结构体指针(核心)
LPNMHDR pNmhdr = (LPNMHDR)lParam;
// 第二步:判断通知是否来自IDC_LIST1
/*if (pNmhdr->hwndFrom == GetDlgItem(hwnd, IDC_LIST1)) {*/
NMLISTVIEW* lNmlistView = (NMLISTVIEW*)lParam;
if (wParam == IDC_LIST1 && lNmlistView->iItem != -1) {
// 第三步:根据不同通知码处理具体逻辑
switch (pNmhdr->code) {
// 示例1:列表项被点击
case NM_CLICK:
{
//MessageBoxW(hwnd, L"列表控件被点击", L"提示", MB_OK);
WCHAR buff[100] = { 0 };
LVITEMW lvitem = { 0 };
lvitem.iSubItem = lNmlistView->iSubItem;
lvitem.pszText = buff;
lvitem.cchTextMax = 100;
SendDlgItemMessageW(hwnd, wParam, LVM_GETITEMTEXTW, lNmlistView->iItem, (LPARAM)&lvitem);
MessageBoxW(hwnd, lvitem.pszText, L"提示", MB_OK);
break;
}
case NM_RCLICK: {
POINT point = {0};
GetCursorPos(&point);
HMENU hMenu = LoadMenuW(GetModuleHandleW(0), MAKEINTRESOURCE(IDR_MENU1));
HMENU hSubMenu = GetSubMenu(hMenu,0);
TrackPopupMenu(hSubMenu, TPM_LEFTALIGN,point.x, point.y,0,hwnd,NULL);
break;
}
default:
break;
}
}
break;
}
case WM_HSCROLL:
{
break;
}
case WM_VSCROLL:
{
break;
}
case WM_CLOSE:
EndDialog(hwnd, 0);
break;
default:
return FALSE;
break;
}
return TRUE;
}
// 居中函数
void CenterWindow(HWND hWnd)
{
RECT rc;
GetWindowRect(hWnd, &rc);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
SetWindowPos(hWnd, NULL,
(screenWidth - width) / 2,
(screenHeight - height) / 2,
0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
void SetWindowG(HWND hwnd, int width, int height)
{
// DPI自适应
UINT dpi = GetDpiForWindow(hwnd);
int baseWidth = width;
int baseHeight = height;
int scaledWidth = MulDiv(baseWidth, dpi, 96);
int scaledHeight = MulDiv(baseHeight, dpi, 96);
SetWindowPos(hwnd, NULL, 0, 0, scaledWidth, scaledHeight,
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
// 居中显示
CenterWindow(hwnd);
}
BOOL InsertColum(HWND hwnd, int nIDDlgItem, int nColum, LPWSTR columName,int columWidth)
{
LVCOLUMNW lvColum = {
LVCF_FMT | LVCF_WIDTH | LVCF_TEXT
};
lvColum.fmt = LVCFMT_CENTER;
lvColum.cx = columWidth;
lvColum.pszText = columName;
SendDlgItemMessageW(hwnd, nIDDlgItem, LVM_INSERTCOLUMN, nColum, (LONG)&lvColum);
return TRUE;
}
BOOL InsertItem(HWND hwnd, int nIDDlgItem, int nRow)
{
LVITEMW lvitem = { LVIF_TEXT,nRow };
//lvitem.iItem = 0;
lvitem.pszText = (LPWSTR)L"";
SendDlgItemMessageW(hwnd, nIDDlgItem, LVM_INSERTITEM, nRow, (LONG)&lvitem);
return TRUE;
}
BOOL SetListItemText(HWND hwnd, int nIDDlgItem, int nRow, int nColumn, LPWSTR columnName)
{
LVITEMW lvitem = { LVIF_TEXT,nRow,nColumn };
//lvitem.iSubItem = nColumn;
lvitem.pszText = columnName;
SendDlgItemMessageW(hwnd, nIDDlgItem, LVM_SETITEMTEXTW, nRow, (LONG)&lvitem);
return TRUE;
}