今天第一次用CListCtrl控件,遇到不少问题,查了许多资料,现将用到的一些东西总结如下:
以下未经说明,listctrl默认view 风格为report
相关类及处理函数
MFC:CListCtrl类
SDK:以 “ListView_”开头的一些宏。如 ListView_InsertColumn
????? LVS_ICON: 为每个item显示大图标 ????? LVS_SMALLICON: 为每个item显示小图标 ????? LVS_LIST: 显示一列带有小图标的item ????? LVS_REPORT: 显示item详细资料
????? 直观的理解:windows资源管理器,“查看”标签下的“大图标,小图标,列表,详细资料”
????? LONG lStyle; ????? lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口style ????? lStyle &= ~LVS_TYPEMASK; //清除显示方式位 ????? lStyle |= LVS_REPORT; //设置style ????? SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置style ????? DWORD dwStyle = m_list.GetExtendedStyle(); ????? dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl) ????? dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl) ????? dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件 ????? m_list.SetExtendedStyle(dwStyle); //设置扩展风格 ????? 注:listview的style请查阅msdn http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshellui5/html/wce50lrflistviewstyles.asp
????? m_list.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插入列 ????? m_list.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 ); ????? int nRow = m_list.InsertItem(0, “11”);//插入行 ????? m_list.SetItemText(nRow, 1, “jacky”);//设置数据
选中style中的Show selection always,或者在上面第2点中设置LVS_SHOWSELALWAYS
??? int nIndex = 0; ??? //选中 ??? m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); ??? //取消选中 ??? m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);
????? m_list.SetExtendedStyle(LVS_EX_CHECKBOXES); ????? CString str; ????? for(int i=0; i<m_list.GetItemCount(); i++) ????? { ?????????? if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i)) ?????????? { ??????????????? str.Format(_T("第%d行的checkbox为选中状态"), i); ??????????????? AfxMessageBox(str); ?????????? } ????? }
????? 方法一: ????? CString str; ????? for(int i=0; i<m_list.GetItemCount(); i++) ????? { ?????????? if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED ) ?????????? { ??????????????? str.Format(_T("选中了第%d行"), i); ??????????????? AfxMessageBox(str); ?????????? } ????? }
????? 方法二: ????? POSITION pos = m_list.GetFirstSelectedItemPosition(); ????? if (pos == NULL) ?????????? TRACE0("No items were selected!\n"); ????? else ????? { ?????????? while (pos) ?????????? { ??????????????? int nItem = m_list.GetNextSelectedItem(pos); ??????????????? TRACE1("Item %d was selected!\n", nItem); ??????????????? // you could do your own processing on nItem here ?????????? } ????? }
????? TCHAR szBuf[1024]; ????? LVITEM lvi; ????? lvi.iItem = nItemIndex; ????? lvi.iSubItem = 0; ????? lvi.mask = LVIF_TEXT; ????? lvi.pszText = szBuf; ????? lvi.cchTextMax = 1024; ????? m_list.GetItem(&lvi);
????? 关于得到设置item的状态,还可以参考msdn文章 ????? Q173242: Use Masks to Set/Get Item States in CListCtrl http://support.microsoft.com/kb/173242/en-us
????? LVCOLUMN lvcol; ????? char? str[256]; ????? int?? nColNum; ????? CString? strColumnName[4];//假如有4列
????? nColNum = 0; ????? lvcol.mask = LVCF_TEXT; ????? lvcol.pszText = str; ????? lvcol.cchTextMax = 256; ????? while(m_list.GetColumn(nColNum, &lvcol)) ????? { ?????????? strColumnName[nColNum] = lvcol.pszText; ?????????? nColNum++; ????? }
??? m_list.EnsureVisible(i, FALSE);
??? int nHeadNum = m_list.GetHeaderCtrl()->GetItemCount();
??? ? 方法一: ???? ??? while ( m_list.DeleteColumn (0)) ??? ?? 因为你删除了第一列后,后面的列会依次向上移动。
??? ? 方法二: ????? int nColumns = 4; ????? for (int i=nColumns-1; i>=0; i--) ????? ??? m_list.DeleteColumn (i);
????? 添加listctrl控件的NM_CLICK消息相应函数 ????? void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult) ????? { ?????????? // 方法一: ?????????? /* ?????????? DWORD dwPos = GetMessagePos(); ?????????? CPoint point( LOWORD(dwPos), HIWORD(dwPos) ); ?????????? m_list.ScreenToClient(&point); ?????????? LVHITTESTINFO lvinfo; ?????????? lvinfo.pt = point; ?????????? lvinfo.flags = LVHT_ABOVE; ?????????? int nItem = m_list.SubItemHitTest(&lvinfo); ?????????? if(nItem != -1) ?????????? { ??????????????? CString strtemp; ??????????????? strtemp.Format("单击的是第%d行第%d列", lvinfo.iItem, lvinfo.iSubItem); ??????????????? AfxMessageBox(strtemp); ?????????? } ????????? */ ????????? // 方法二: ????????? /* ?????????? NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; ?????????? if(pNMListView->iItem != -1) ?????????? { ??????????????? CString strtemp; ??????????????? strtemp.Format("单击的是第%d行第%d列", ??????????????????????????????? pNMListView->iItem, pNMListView->iSubItem); ??????????????? AfxMessageBox(strtemp); ?????????? } ????????? */ ?????????? *pResult = 0; ????? }
????? 添加listctrl控件的NM_CLICK消息相应函数 ????? void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult) ????? { ?????????? DWORD dwPos = GetMessagePos(); ?????????? CPoint point( LOWORD(dwPos), HIWORD(dwPos) ); ?????????? m_list.ScreenToClient(&point); ?????????? LVHITTESTINFO lvinfo; ?????????? lvinfo.pt = point; ?????????? lvinfo.flags = LVHT_ABOVE; ?????????? UINT nFlag; ?????????? int nItem = m_list.HitTest(point, &nFlag); ?????????? //判断是否点在checkbox上 ?????????? if(nFlag == LVHT_ONITEMSTATEICON) ?????????? { ??????????????? AfxMessageBox("点在listctrl的checkbox上"); ?????????? } ?????????? *pResult = 0; ????? }
????? 添加listctrl控件的NM_RCLICK消息相应函数 ????? void CTest6Dlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult) ????? { ?????????? NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; ?????????? if(pNMListView->iItem != -1) ?????????? { ??????????????? DWORD dwPos = GetMessagePos(); ??????????????? CPoint point( LOWORD(dwPos), HIWORD(dwPos) ); ??????????????? CMenu menu; ??????????????? VERIFY( menu.LoadMenu( IDR_MENU1 ) ); ??????????????? CMenu* popup = menu.GetSubMenu(0); ??????????????? ASSERT( popup != NULL ); ??????????????? popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this ); ?????????? } ?????????? *pResult = 0; ? }
????? 添加listctrl控件的LVN_ITEMCHANGED消息相应函数 ????? void CTest6Dlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult) ????? { ?????????? NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; ?????????? // TODO: Add your control notification handler code here ?????????? CString sTemp; ?????????? if((pNMListView->uOldState & LVIS_FOCUSED) == LVIS_FOCUSED && ??????????? (pNMListView->uNewState & LVIS_FOCUSED) == 0) ?????????? { ??????????????? sTemp.Format("%d losted focus",pNMListView->iItem); ?????????? } ?????????? else if((pNMListView->uOldState & LVIS_FOCUSED) == 0 && ?????????????? (pNMListView->uNewState & LVIS_FOCUSED) == LVIS_FOCUSED) ?????????? { ??????????????? sTemp.Format("%d got focus",pNMListView->iItem); ?????????? } ?????????? if((pNMListView->uOldState & LVIS_SELECTED) == LVIS_SELECTED && ??????????? (pNMListView->uNewState & LVIS_SELECTED) == 0) ?????????? { ??????????????? sTemp.Format("%d losted selected",pNMListView->iItem); ?????????? } ?????????? else if((pNMListView->uOldState & LVIS_SELECTED) == 0 && ??????????? (pNMListView->uNewState & LVIS_SELECTED) == LVIS_SELECTED) ?????????? { ??????????????? sTemp.Format("%d got selected",pNMListView->iItem); ?????????? } ?????????? *pResult = 0; ????? }
17. 改变选中行的颜色 首先是添加以下消息
ON_NOTIFY( NM_CUSTOMDRAW, IDC_LIST1, OnDrawColorForMyList )? //为改变颜色添加的消息
再添加类成员函数,就OK了:
//改变 m_List 控件单行的颜色
void CSSDTDlg::OnDrawColorForMyList( NMHDR *pNmHdr, LRESULT *pResult )
{
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNmHdr );
*pResult = CDRF_DODEFAULT;
if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
{
*pResult = CDRF_NOTIFYITEMDRAW;
}
else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
{
*pResult = CDRF_NOTIFYSUBITEMDRAW;
}
else if ( (CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage )
{
COLORREF clrNewTextColor, clrNewBkColor;
int nItem = static_cast<int>( pLVCD->nmcd.dwItemSpec );
//选中行显示字体为红色,否则为黑色
if(m_item == nItem) //设置为红色
{
clrNewTextColor = RGB( 255, 0, 0 );
}
else //设置为黑色
{
clrNewTextColor = RGB( 0, 0, 0 );
}
//设置背景色
if( nItem%2 ==0 )
{
clrNewBkColor = RGB( 240, 240, 240 ); //偶数行背景色为灰色
}
else
{
clrNewBkColor = RGB( 255, 255, 255 ); //奇数行背景色为白色
}
pLVCD->clrText = clrNewTextColor;
pLVCD->clrTextBk = clrNewBkColor;
*pResult = CDRF_DODEFAULT;
}
}
更多技巧参见以下链接: http://blog.csdn.net/danforn/archive/2008/06/03/2508070.aspx