还在用老方法显示数据?手把手教你用MFC的CListCtrl打造一个带图标的学生信息查询系统
实战MFC用CListCtrl构建可视化学生管理系统在桌面应用开发领域数据展示一直是用户体验的核心环节。传统的表格控件虽然能完成基本功能但缺乏视觉层次和交互灵活性。MFC中的CListCtrl控件提供了四种视图模式特别适合需要同时呈现图标和结构化数据的场景。本文将带你从零构建一个完整的学生信息管理系统重点解决图标适配、视图切换和控件联动等实际问题。1. 环境准备与基础配置1.1 创建MFC对话框项目使用Visual Studio新建MFC对话框项目命名为StudentInfoSystem。在资源视图中打开主对话框删除默认控件添加以下元素两个CListCtrl控件ID分别设置为IDC_LIST_STUDENTS和IDC_LIST_DETAILS两个按钮控件查询IDC_BTN_QUERY清空IDC_BTN_CLEAR一个静态文本控件作为标题// 对话框类声明 class CStudentInfoDlg : public CDialogEx { CImageList m_imgListLarge; CImageList m_imgListSmall; CListCtrl* m_pListStudents; CListCtrl* m_pListDetails; CString m_strSelectedID; }1.2 准备图标资源创建7个32x32和16x16的学生头像图标IDI_STUDENT1到IDI_STUDENT7建议使用透明背景PNG格式。在资源文件中添加如下定义IDI_STUDENT1 ICON res\\student1.ico IDI_STUDENT2 ICON res\\student2.ico ...2. 初始化列表控件2.1 配置图像列表在OnInitDialog()中初始化两种尺寸的图像列表// 大图标列表(32x32) m_imgListLarge.Create(32, 32, ILC_COLOR32 | ILC_MASK, 7, 1); // 小图标列表(16x16) m_imgListSmall.Create(16, 16, ILC_COLOR32 | ILC_MASK, 7, 1); for(int i0; i7; i) { HICON hIcon AfxGetApp()-LoadIcon(IDI_STUDENT1i); m_imgListLarge.Add(hIcon); m_imgListSmall.Add(hIcon); DestroyIcon(hIcon); }2.2 设置学生列表视图配置左侧列表为图标视图显示学生基本信息m_pListStudents (CListCtrl*)GetDlgItem(IDC_LIST_STUDENTS); m_pListStudents-SetImageList(m_imgListLarge, LVSIL_NORMAL); m_pListStudents-SetExtendedStyle(LVS_EX_BORDERSELECT); // 添加测试数据 CString strID; for(int i0; i7; i) { strID.Format(_T(S%04d), 1000i); m_pListStudents-InsertItem(i, strID, i); }2.3 配置详细信息报表视图右侧列表采用报表视图展示完整信息m_pListDetails (CListCtrl*)GetDlgItem(IDC_LIST_DETAILS); m_pListDetails-SetImageList(m_imgListSmall, LVSIL_SMALL); m_pListDetails-SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); // 添加列 static struct { LPCTSTR name; int width; } columns[] { {_T(学号), 80}, {_T(姓名), 100}, {_T(班级), 120}, {_T(入学日期), 100}, {_T(联系方式), 150} }; for(int i0; i_countof(columns); i) { m_pListDetails-InsertColumn(i, columns[i].name, LVCFMT_LEFT, columns[i].width); }3. 实现核心交互逻辑3.1 学生选择事件处理为左侧列表添加NM_CLICK消息处理void CStudentInfoDlg::OnClickListStudents(NMHDR* pNMHDR, LRESULT* pResult) { LPNMITEMACTIVATE pNMIA reinterpret_castLPNMITEMACTIVATE(pNMHDR); int nItem pNMIA-iItem; if(nItem 0) { m_strSelectedID m_pListStudents-GetItemText(nItem, 0); GetDlgItem(IDC_BTN_QUERY)-EnableWindow(TRUE); } *pResult 0; }3.2 查询按钮实现点击查询按钮时根据选择显示详细信息void CStudentInfoDlg::OnBnClickedQuery() { if(m_strSelectedID.IsEmpty()) return; // 清空现有数据 m_pListDetails-DeleteAllItems(); // 模拟数据库查询 CString strName, strClass, strDate, strPhone; int nID _ttoi(m_strSelectedID.Mid(1)); switch(nID % 7) { case 0: strName _T(张三); strClass _T(计算机2020-1班); break; // 其他case分支... } // 添加新记录 int nIndex m_pListDetails-InsertItem(0, m_strSelectedID, nID % 7); m_pListDetails-SetItemText(nIndex, 1, strName); m_pListDetails-SetItemText(nIndex, 2, strClass); m_pListDetails-SetItemText(nIndex, 3, _T(2020-09-01)); m_pListDetails-SetItemText(nIndex, 4, _T(13800138000)); }3.3 清空功能实现清空按钮的事件处理void CStudentInfoDlg::OnBnClickedClear() { m_pListDetails-DeleteAllItems(); m_strSelectedID.Empty(); GetDlgItem(IDC_BTN_QUERY)-EnableWindow(FALSE); }4. 高级功能扩展4.1 实现视图动态切换添加菜单或按钮允许用户切换显示模式void CStudentInfoDlg::SwitchViewMode(int nMode) { DWORD dwStyle m_pListStudents-GetStyle(); dwStyle ~LVS_TYPEMASK; switch(nMode) { case 0: dwStyle | LVS_ICON; break; case 1: dwStyle | LVS_SMALLICON; break; case 2: dwStyle | LVS_LIST; break; case 3: dwStyle | LVS_REPORT; break; } m_pListStudents-ModifyStyle(LVS_TYPEMASK, dwStyle); // 切换图像列表 m_pListStudents-SetImageList( (nMode 2) ? m_imgListLarge : m_imgListSmall, LVSIL_NORMAL); }4.2 添加排序功能实现按列排序的比较函数static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { CListCtrl* pList (CListCtrl*)lParamSort; CString strItem1 pList-GetItemText(lParam1, 0); CString strItem2 pList-GetItemText(lParam2, 0); return strItem1.Compare(strItem2); } void CStudentInfoDlg::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult) { LPNMLISTVIEW pNMLV reinterpret_castLPNMLISTVIEW(pNMHDR); m_pListDetails-SortItems(CompareFunc, (DWORD_PTR)m_pListDetails); *pResult 0; }4.3 优化显示效果添加自定义绘制处理改善视觉效果void CStudentInfoDlg::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { NMLVCUSTOMDRAW* pLVCD reinterpret_castNMLVCUSTOMDRAW*(pNMHDR); switch(pLVCD-nmcd.dwDrawStage) { case CDDS_PREPAINT: *pResult CDRF_NOTIFYITEMDRAW; break; case CDDS_ITEMPREPAINT: if(pLVCD-nmcd.dwItemSpec % 2 0) { pLVCD-clrTextBk RGB(240, 240, 255); } *pResult CDRF_DODEFAULT; break; } }5. 项目实战技巧5.1 处理大量数据当数据量较大时使用虚拟列表技术// 在初始化时设置 m_pListDetails-SetItemCount(10000); m_pListDetails-SetCallbackMask(LVIF_TEXT | LVIF_IMAGE); // 处理LVN_GETDISPINFO消息 void CStudentInfoDlg::OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult) { NMLVDISPINFO* pDispInfo reinterpret_castNMLVDISPINFO*(pNMHDR); if(pDispInfo-item.mask LVIF_TEXT) { switch(pDispInfo-item.iSubItem) { case 0: _stprintf_s(pDispInfo-item.pszText, pDispInfo-item.cchTextMax, _T(S%04d), pDispInfo-item.iItem 1000); break; // 其他列处理... } } }5.2 添加右键菜单实现列表项的上下文菜单void CStudentInfoDlg::OnContextMenu(CWnd* pWnd, CPoint point) { if(pWnd-GetDlgCtrlID() IDC_LIST_DETAILS) { CMenu menu; menu.LoadMenu(IDR_DETAIL_MENU); CMenu* pPopup menu.GetSubMenu(0); pPopup-TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); } }5.3 数据持久化添加导出到CSV文件功能void CStudentInfoDlg::ExportToCSV(LPCTSTR lpszFileName) { CStdioFile file; if(file.Open(lpszFileName, CFile::modeCreate | CFile::modeWrite)) { // 写入列标题 CString strLine; for(int i0; im_pListDetails-GetHeaderCtrl()-GetItemCount(); i) { TCHAR szText[256]; HDITEM hdi {HDI_TEXT, 0, szText, 256}; m_pListDetails-GetHeaderCtrl()-GetItem(i, hdi); strLine szText; strLine (i m_pListDetails-GetHeaderCtrl()-GetItemCount()-1) ? _T(,) : _T(\n); } file.WriteString(strLine); // 写入数据行 for(int i0; im_pListDetails-GetItemCount(); i) { strLine.Empty(); for(int j0; jm_pListDetails-GetHeaderCtrl()-GetItemCount(); j) { strLine m_pListDetails-GetItemText(i, j); strLine (j m_pListDetails-GetHeaderCtrl()-GetItemCount()-1) ? _T(,) : _T(\n); } file.WriteString(strLine); } } }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2471475.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!