CListView常用用法

CListView是界面中非常常用的视图类,前段时间给可视化平台换脸的时候,平台的输出不仅包括直观的图像显示,用户还希望直观地得到每帧图像的一些相关的参数信息、统计信息等,这时候我就选择在CListView中滚动地显示相关信息,并将窗口进行切分,将CListView的窗口放在整个主窗口的最底端,在需要的时候显示,不需要的时候隐藏。但是,我对CListView的用法不是很熟悉,在查MSDN和从网上查相关用法的时候,要不就是零星地介绍,要不就是只介绍CListCtrl的用法,这让我走了很多弯路,为此,我将从网上查到的用法,结合我的实际应用,简单介绍下CListView的使用,希望对像我一样对CListView不熟悉或刚接触MFC编程的人有所帮助,对一些编程老手、高手来说,这些自然不在话下。

CListView中内置了CListCtrl,所以对CListView的操作实际上就是对内置CListCtrl的操作。下面就从新建一个CListView的子类开始,我从工程中新建了一个叫做CInfoView的类,基类选择CListView。

1、初始化CListView,设置风格,背景和字体颜色,初始化行列。该项工作在OnInitialUpdate()中完成,如下所示。

void CInfoView::OnInitialUpdate()
{
    CListView::OnInitialUpdate();

    CListCtrl& m_list = GetListCtrl();//得到内置的listctrl引用
    LONG lStyle;
    lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口风格
    lStyle &= ~LVS_TYPEMASK; //清除显示方式位
    lStyle |= LVS_REPORT; //设置报表风格
    SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle); //设置窗口风格
    DWORD dwStyle = m_list.GetExtendedStyle();

    //选中某行使整行高亮(只适用于报表风格的listctrl)
    dwStyle |= LVS_EX_FULLROWSELECT;
    dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与报表风格的listctrl)
    m_list.SetExtendedStyle(dwStyle); //设置扩展风格
    m_list.SetBkColor(RGB(200, 200, 200)); //设置背景颜色
    m_list.SetTextBkColor(RGB(200, 200, 200)); //设置文本背景颜色
    m_list.SetTextColor(RGB(10, 10, 80)); //设置文本颜色
    //插入列的标题,为了简单起见,我只插入三列
    m_list.InsertColumn( 0, "图像帧号", LVCFMT_CENTER, 80 );
    m_list.InsertColumn( 1, "可见性判断", LVCFMT_CENTER, 110 );
    m_list.InsertColumn( 2, "置信度结果", LVCFMT_CENTER, 110 );
}


2、插入一行数据。一般在实际应用中,都是在程序运行中,插入一行数据,这时候,需要在当前的程序语境中得到CInfoView的指针,然后进行插入数据的操作。在我的应用中,我把CinfoView作为拆分窗口的一个子窗口,所以具体操作如下:
CListView*listview=(CListView*)(((CMainFrame*)theApp.GetMainWnd())->m_wndSplitter1.GetPane(1,0));//得到ListView的指针
CListCtrl& list = listview->GetListCtrl();//得到listview内置listctrl的引用
CString strId, strCo;//图像帧号,置信度
CString strVb = "Y"; //可见性
if(fConfid[nIndex] <= 0)
{
    strVb = "N";
}
strId.Format("%d", nIndex+1);
strCo.Format("% .4f", fConfid[nIndex]);
//插入一行数据,始终在顶端插入新的数据
int nRow = list.InsertItem(0, strId);
list.SetItemText(nRow, 1, strVb);
list.SetItemText(nRow, 2, strCo);
3、右键单击弹出浮动菜单。在我的应用中,右键弹出的浮动菜单,只有一项:“删除所有内容”。要弹出浮动菜单,首先先要在“资源”的“Menu”中新建一个Menu,ID命名为IDR_POPMENU,然后在该Menu中添加一个主菜单“操作”,在“操作”下添加一个子菜单“删除所有内容”,ID命名为“ID_DELETE_ALL”,通过向导在CInfoView中给ID_DELETE_ALL添加消息响应函数OnDeleteAll(),如下:
void CInfoView::OnDeleteAll()
{
 CListCtrl &m_list = GetListCtrl();
 m_list.DeleteAllItems();
}
然后通过向导在CInfoView中添加右键单击响应函数=NM_RCLICK,如下:
void CInfoView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
{
    CListCtrl &m_list = GetListCtrl(); //获取当前列表控件的指针
    CMenu menu, *pSubMenu; //定义下面要用到的cmenu对象
    menu.LoadMenu(IDR_POPMENU); //装载自定义的右键菜单
    pSubMenu = menu.GetSubMenu(0); //获取第一个弹出菜单
    CPoint oPoint; //定义一个用于确定光标位置的位置
    GetCursorPos(&oPoint); //获取当前光标的位置

    //在指定位置显示弹出菜单
    pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, oPoint.x, oPoint.y, this);
}
4、添加消息响应函数OnCustomDraw(),为ClistCtrl的每个Item设置不同的颜色,在该应用中,为单数和偶数的Item项设置两种不同的颜色。具体步骤如下:
首先在InfoView.h的AFX_MSG之间添加消息函数声明:
afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
然后在InfoView.cpp的BEGIN_MESSAGE_MAP之间添加消息映射:
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
最后在InfoView.cpp中添加函数实现:
void CInfoView::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pNMHDR;
    switch(lplvcd->nmcd.dwDrawStage)
    {
        int iRow;
        case CDDS_PREPAINT:
            *pResult = CDRF_NOTIFYITEMDRAW;
            break;
        case CDDS_ITEMPREPAINT:
            *pResult = CDRF_DODEFAULT;
            iRow= lplvcd->nmcd.dwItemSpec;
            if(iRow & 1)
            {
                lplvcd->clrTextBk = RGB(230, 230, 230);
                //lplvcd->clrText = RGB(255, 255, 0);
                *pResult = CDRF_NEWFONT;
            }
            break;
        default:
            *pResult = CDRF_DODEFAULT;
    }
}

5、为CInfoView添加点击列的标题进行排序的消息响应函数,在添加该消息响应函数之前,先要定义实现排序的回调函数。在该应用中,第一列是图像帧号,按自然数排序,其他列都按字串进行排列,所以定义两个比较的回调函数。
在InfoView.h中声明两个静态的回调函数:
static int CALLBACK ListViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);//按字串排序
static int CALLBACK ListViewCompareIntFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);//按自然数排序
在InfoView.cpp中实现两个静态的回调函数:
int CALLBACK CInfoView::ListViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    // 得到排序方式
    int *pisortorder = (int *)lParamSort;

    // 得到两个列的排序信息
    TCHAR *sz1 = (TCHAR *)lParam1;
    TCHAR *sz2 = (TCHAR *)lParam2;

    // 比较列的信息并返回比较结果。
    // 若为减序,则将比较结果乘上-1。
    if (*pisortorder == LVS_SORTASCENDING)
        return lstrcmp(sz1, sz2);
    else
        return lstrcmp(sz1, sz2) * (-1);
}

int CALLBACK CInfoView::ListViewCompareIntFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    // 得到排序方式
    int *pisortorder = (int *)lParamSort;

    // 得到两个列的排序信息
    TCHAR *sz1 = (TCHAR *)lParam1;
    TCHAR *sz2 = (TCHAR *)lParam2;
    int n1 = _ttoi(sz1);
    int n2 = _ttoi(sz2);

    // 比较列的信息并返回比较结果。
    // 若为减序,则将比较结果乘上-1。
    if(*pisortorder == LVS_SORTASCENDING)
    {
        if(n1 - n2 > 0) return 1;
        else if(n1 -n2 == 0) return 0;
        else return -1;
    }
    else
    {
        if(n1 - n2 > 0) return -1;
        else if(n1 -n2 == 0) return 0;
        else return 1;
    }
}
5、为CInfoView添加点击列的标题进行排序的消息响应函数,在添加该消息响应函数之前,先要定义实现排序的回调函数。在该应用中,第一列是图像帧号,按自然数排序,其他列都按字串进行排列,所以定义两个比较的回调函数。

在InfoView.h中声明两个静态的回调函数:
static int CALLBACK ListViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);//按字串排序
static int CALLBACK ListViewCompareIntFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);//按自然数排序
在InfoView.cpp中实现两个静态的回调函数:
int CALLBACK CInfoView::ListViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    // 得到排序方式
    int *pisortorder = (int *)lParamSort;
   
    // 得到两个列的排序信息
    TCHAR *sz1 = (TCHAR *)lParam1;
    TCHAR *sz2 = (TCHAR *)lParam2;
   
    // 比较列的信息并返回比较结果。
    // 若为减序,则将比较结果乘上-1。
    if (*pisortorder == LVS_SORTASCENDING)
        return lstrcmp(sz1, sz2);
    else
        return lstrcmp(sz1, sz2) * (-1);
}

int CALLBACK CInfoView::ListViewCompareIntFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    // 得到排序方式
    int *pisortorder = (int *)lParamSort;
   
    // 得到两个列的排序信息
    TCHAR *sz1 = (TCHAR *)lParam1;
    TCHAR *sz2 = (TCHAR *)lParam2;
    int n1 = _ttoi(sz1);
    int n2 = _ttoi(sz2);
   
    // 比较列的信息并返回比较结果。
    // 若为减序,则将比较结果乘上-1。
    if(*pisortorder == LVS_SORTASCENDING)
    {
        if(n1 - n2 > 0) return 1;
        else if(n1 -n2 == 0) return 0;
        else return -1;
    }
    else
    {
        if(n1 - n2 > 0) return -1;
        else if(n1 -n2 == 0) return 0;
        else return 1;
    }
}
然后通过向导为事件LVN_COLUMNCLICK添加消息响应函数OnColumnclick(),在该函数中调用上面的回调函数
void CInfoView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)
{
    // TODO: Add your control notification handler code here
    static int ncurSortCol = -1; // 保存当前的排序列。
    // 一开始表示为-1,表示尚未按任何列排序。
   
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
   
    CListCtrl* lc = &GetListCtrl();
    LONG ws = GetWindowLong(lc->m_hWnd, GWL_STYLE);
    int nSortOrder; // 排序的方式
   
    // 若点击列与当前排序列不同的列,则改变排序序,并将排序方式改为增序。
    // 若当前排序列与点击列相同,则更改增、减序的排序方式
    if (ncurSortCol == pNMListView->iSubItem)
    {
        if (ws & LVS_SORTASCENDING)
        {
            ws ^= LVS_SORTASCENDING;
            nSortOrder = LVS_SORTDESCENDING;
        }
        else
        {
            ws ^= LVS_SORTDESCENDING;
            nSortOrder = LVS_SORTASCENDING;
        }
    }
    else
    {
        if (ws & LVS_SORTASCENDING)
        {
            nSortOrder = LVS_SORTDESCENDING;
            ncurSortCol = pNMListView->iSubItem;
        }
        else
        {
            nSortOrder = LVS_SORTASCENDING;
            ncurSortCol = pNMListView->iSubItem;
        }
    }
   
    // 将当前的排序信息保存在窗口Style中,供以后使用
    ws |= nSortOrder;
    SetWindowLong(lc->m_hWnd, GWL_STYLE, ws);
   
    // 将各ITEM的LPARAM用新排序列的内容替换
    LVITEM li;
    li.mask = LVIF_PARAM|LVIF_TEXT;
    TCHAR szItemText[1024];
    for (int i = 0; i < lc->GetItemCount(); i++)
    {
        li.iItem = i;
        li.iSubItem = ncurSortCol;
        li.cchTextMax = 1024;
        li.pszText = szItemText;
        lc->GetItem(&li);
        TCHAR * szlparam = (TCHAR *)li.lParam;
        // 删除以前的信息,释放空间
        // 添加List Item时应注意将lParam初始化NULL
        if (szlparam != NULL)
            delete szlparam;
       
        // 复制当前列的szItemText到Item的lParam中
        szlparam = new TCHAR[lstrlen(szItemText) + 1];
        lstrcpy(szlparam, szItemText);
            lc->SetItemData(i, DWORD(szlparam));   
    }
   
    // 开始排序
    if(ncurSortCol == 0)//第一列按整数排序
    {
        GetListCtrl().SortItems(ListViewCompareIntFunc,(LPARAM)(&nSortOrder));
    }
    else
        GetListCtrl().SortItems(ListViewCompareFunc,(LPARAM)(&nSortOrder));
    *pResult = 0;
}


非常好用的CListCtrl加强版。 从CListCtrl继承,完全兼容CListCtrl. 它有以下特性: • The background of the sorted column can be displayed in a different color (like the detailed view of Windows XP Explorer). • The header of the sorted column can display an arrow that indicates the sort direction (like the detailed view of Windows XP Explorer). • You can give the user the opportunity to hide or redisplay selected columns by just clicking on the header control with the right mouse button (see picture below). • You can hide or redisplay a selected column entirely. • In contrast to the original list view control, the first column can have the LVCFMT_CENTER or LVCFMT_RIGHT style, too. For this feature, the list view control must have the LVS_OWNERDRAWFIXED style. • The label attributes state icon, small icon, and selection can always be shown in the leftmost column, independent of the order of the columns. For this feature, the listview control must have the LVS_OWNERDRAWFIXED style. • You can supply tooltips not only for the whole item, but also for the small icon, the state icon, and each subitem label. • The extended styles LVS_EX_CHECKBOXES, LVS_EX_ONECLICKACTIVATE, LVS_EX_SUBITEMIMAGES, LVS_EX_TWOCLICKACTIVATE, and LVS_EX_UNDERLINEHOT will be supported even if the list view control has the LVS_OWNERDRAWFIXED style. • If the LVS_EX_CHECKBOXES style has been applied and a selected item will be checked/unchecked, all other selected items will be checked/unchecked, too. • If the LVS_EX_LABELTIP style has been applied, not only the partially hidden text of the item label will be unfolded but also the partially hidden text of each subitem label. Note: The LVS_EX_LABELTIP style will be supported under all operating systems. • Tooltips and expanded labels can be displayed simultaneously. • The current state of the list view control (column widths, column order, hidden columns, and sort column and direction) can be saved and restored.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值