// CEXVirtualListDlg.cpp: 实现文件 // #include "stdafx.h" #include "PluginDriver.h" #include "CEXVirtualListCtrl.h" #include "afxdialogex.h" #include #include #include //控件ID只需要在当前窗口中唯一,这里随便写一个就好 #define ID_VIRTUAL_LIST_CTRL (1987) IMPLEMENT_DYNAMIC(CEXVirtualListCtrl, CListCtrl) CEXVirtualListCtrl::CEXVirtualListCtrl() { m_pQueueData = NULL; m_lOldCount = 0; } CEXVirtualListCtrl::~CEXVirtualListCtrl() { } BEGIN_MESSAGE_MAP(CEXVirtualListCtrl, CListCtrl) ON_NOTIFY_REFLECT(LVN_GETDISPINFO, &CEXVirtualListCtrl::OnLvnGetdispinfo) ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CEXVirtualListCtrl::OnNMCustomdraw) ON_WM_ERASEBKGND() ON_WM_TIMER() END_MESSAGE_MAP() /* void CEXVirtualListCtrl::Initialize() { SetExtendedStyle(GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_OWNERDATA); // 确保设置了虚拟大小样式 SetItemCountEx((int)0); // 添加列(这里假设列是固定的,可以在构造函数中或这里添加) InsertColumn(0, _T("ID"), LVCFMT_LEFT, 80); InsertColumn(1, _T("Value1"), LVCFMT_LEFT, 120); InsertColumn(2, _T("Value2"), LVCFMT_LEFT, 100); } */ void CEXVirtualListCtrl::SetData(CEXMemFileQueue* pQueue) { m_pQueueData = pQueue; SetItemCountEx((int)m_pQueueData->GetItemCount()); } std::string getSubString(const char* input, int index) { std::vector substrings; std::stringstream ss(input); std::string item; // 使用逗号作为分隔符分割字符串 while (std::getline(ss, item, ',')) { substrings.push_back(item); } // 检查索引是否有效 if (index < 0 || index >= substrings.size()) { return ""; } // 返回对应的子串 return substrings[index]; } void CEXVirtualListCtrl::OnLvnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult) { NMLVDISPINFO* pDispInfo = reinterpret_cast(pNMHDR); LV_ITEM* pItem = &(pDispInfo)->item; if (pItem->iItem >= 0 && pItem->iItem < static_cast(m_pQueueData->GetItemCount())) { char acTemp[DATA_LINE_SIZE + 1] = { 0 }; int lIndex = m_pQueueData->ReadItem(acTemp, pItem->iItem); //pItem->iItem为行序号,即数据索引 if (pItem->mask & LVIF_TEXT) { CString str; int lTempValue = 0; switch (pItem->iSubItem) //pItem->iSubItem为列编号,可以逐单元格设置内容; { case 0://acSeq[10]; str= getSubString(acTemp, 0).c_str(); break; case 1://acTime[12]; str = getSubString(acTemp, 1).c_str(); break; case 2://cIndex; // 0或1 str = getSubString(acTemp, 2).c_str(); break; case 3://acTxRx; // 0:send, 1:recv lTempValue = atoi(getSubString(acTemp, 3).c_str()); str = lTempValue == 0 ? "send" : lTempValue == 1 ? "recv" : "-"; break; case 4://acID[10]; str = getSubString(acTemp, 4).c_str(); break; case 5://acFrame;//0:data, 1:remote lTempValue = atoi(getSubString(acTemp, 5).c_str()); str = lTempValue == 0 ? "data" : lTempValue == 1 ? "remote" : "-"; break; case 6:////0:standard, 1:extend lTempValue = atoi(getSubString(acTemp, 6).c_str()); str = lTempValue == 0 ? "standard" : lTempValue == 1 ? "extend" : "-"; break; case 7://cDlc; str = getSubString(acTemp, 7).c_str(); break; case 8://acData[32]; str = getSubString(acTemp, 8).c_str(); break; } lstrcpy(pItem->pszText, str); } } *pResult = 0; } void CEXVirtualListCtrl::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult) { LPNMLVCUSTOMDRAW pLVCD = reinterpret_cast(pNMHDR); *pResult = CDRF_DODEFAULT; switch (pLVCD->nmcd.dwDrawStage) { case CDDS_PREPAINT: *pResult = CDRF_NOTIFYITEMDRAW; break; case CDDS_ITEMPREPAINT: { // 获取当前项和子项的索引 int nItem = static_cast(pLVCD->nmcd.dwItemSpec); char acTemp[DATA_LINE_SIZE + 1] = { 0 }; m_pQueueData->ReadItem(acTemp, nItem); int lId = atoi(acTemp);//测试数据每条数据的最前面是10进制的ID,所以这里直接使用atoi了 // 根据需要修改颜色 if (lId % 10 == 0) // 根据需要设定行颜色 { pLVCD->clrText = RGB(255, 0, 0); // 红色文本 pLVCD->clrTextBk = RGB(200, 200, 255); // 浅蓝色背景 //*pResult = CDRF_NEWFONT | CDRF_SKIPDEFAULT; *pResult = CDRF_NOTIFYITEMDRAW; } } break; default: break; } } BOOL CEXVirtualListCtrl::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //return TRUE; //避免闪烁 return CListCtrl::OnEraseBkgnd(pDC); } #define TIMER_REFRESH_LIST_ID (18989) void CEXVirtualListCtrl::StartAutoRefresh(int lMSecond) { SetTimer(TIMER_REFRESH_LIST_ID, lMSecond, NULL); } void CEXVirtualListCtrl::StopAutoRefresh() { KillTimer(TIMER_REFRESH_LIST_ID); } void CEXVirtualListCtrl::RefreshShow() { int lItemCount = m_pQueueData->GetItemCount(); if (m_lOldCount == lItemCount) { return; } SetItemCountEx(lItemCount, LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL); EnsureVisible(lItemCount - 1, FALSE); m_lOldCount = lItemCount; } void CEXVirtualListCtrl::OnTimer(UINT_PTR nIDEvent) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (TIMER_REFRESH_LIST_ID == nIDEvent) { if (NULL != m_pQueueData) { RefreshShow(); } } else { //自定义定时器,无需调用基类OnTimer,否则定时器会被强制结束 CListCtrl::OnTimer(nIDEvent); } } #if 0 // CEXVirtualListDlg 对话框 IMPLEMENT_DYNAMIC(CEXVirtualListDlg, CDialogEx) CEXVirtualListDlg::CEXVirtualListDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_CEXVirtualListDlg, pParent) { m_pstVirtualList = new CEXVirtualListCtrl(); } CEXVirtualListDlg::~CEXVirtualListDlg() { } void CEXVirtualListDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); //DDX_Control(pDX, ID_VIRTUAL_LIST_CTRL, *m_pstVirtualList); } BEGIN_MESSAGE_MAP(CEXVirtualListDlg, CDialogEx) ON_BN_CLICKED(IDOK, &CEXVirtualListDlg::OnBnClickedOk) ON_BN_CLICKED(IDCANCEL, &CEXVirtualListDlg::OnBnClickedCancel) ON_WM_SIZE() END_MESSAGE_MAP() // CEXVirtualListDlg 消息处理程序 void CEXVirtualListDlg::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 //CDialogEx::OnOK(); //屏蔽按下回车导致列表隐藏 } void CEXVirtualListDlg::OnBnClickedCancel() { // TODO: 在此添加控件通知处理程序代码 //CDialogEx::OnCancel(); //屏蔽按下ESC导致列表隐藏 } void CEXVirtualListDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 if (NULL != m_pstVirtualList && NULL != m_pstVirtualList->m_hWnd) { m_pstVirtualList->MoveWindow(0, 0, cx, cy); } } BOOL CEXVirtualListDlg::OnInitDialog() { CDialogEx::OnInitDialog(); if (!m_pstVirtualList->Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_OWNERDATA | LVS_EX_DOUBLEBUFFER, CRect(0, 0, 0, 0), this, ID_VIRTUAL_LIST_CTRL)) { TRACE0("Failed to create MyVirtualListCtrl\n"); delete m_pstVirtualList; m_pstVirtualList = nullptr; return FALSE; // 返回 FALSE 以使框架知道未成功初始化 } // 设置控件的扩展样式和其他属性:整行选中、 m_pstVirtualList->SetExtendedStyle(LVS_EX_GRIDLINES | LVS_REPORT/*LVS_EX_VIRTUALSIZE*/); m_pstVirtualList->Initialize(); return TRUE; } void CEXVirtualListDlg::SetData(CEXMemFileQueue* pQueue) { m_pstVirtualList->SetData(pQueue); } #endif BOOL CEXVirtualListCtrl::PreCreateWindow(CREATESTRUCT& cs) { // TODO: 在此添加专用代码和/或调用基类 return CListCtrl::PreCreateWindow(cs); } BOOL CEXVirtualListCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) { // TODO: 在此添加专用代码和/或调用基类 BOOL bRet = CListCtrl::Create(dwStyle, rect, pParentWnd, nID); SetExtendedStyle(LVS_EX_GRIDLINES | LVS_REPORT/*LVS_EX_VIRTUALSIZE*/); SetExtendedStyle(GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_OWNERDATA); // 确保设置了虚拟大小样式 SetItemCountEx((int)0); return bRet; }