参考http://blog.csdn.net/Joany_yang/article/details/1640448中提出的:
MFC提供了SortItems来支持CListCtrl的排序,但没有提供设置排序标记(头三角)的功能。
 
如果有这样的需求就得自己实现。
方法一、在CHeaderCtrl的扩展类CHeaderCtrlEx中自己绘制三角(up/down state)
 void CHeaderCtrlEx :: DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
 //draw arrow up/down here
}
通过这种方式绘制的Header没有了xp style, 还需要你自己绘制xp风格。
 
方法二:插入图片(两幅图片的替换)
HDITEM hdrItem;
GetHeaderCtrl()->GetItem(m_iSortCol, & hdrItem);
hdrItem.mask = HDI_FORMAT | HDI_IMAGE;
hdrItem.iImage = nImageIndex; //index of up/down bitmap
 
pHeaderCtrl->SetItem(m_iSortCol, & hdrItem);
可以说这个方法工作代价最小。而且也没破坏xp风格。
不过不要忘了先GetHeaderCtrl()->SetImageList(&m_imageListSort)。其实就是CHeaderctrl中插入图片
我写了代码,不过出现错误,不知道是哪里错了,各位帮忙看看,小弟在此感激不尽    CImageList *ImgHeaders = new CImageList;
    ImgHeaders->Create(16,16,ILC_MASK,1,1);
    ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_UP));
    ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_DOWN)); CHeaderCtrl* m_HeaderCtrl=new CHeaderCtrl;
m_HeaderCtrl->SetImageList(ImgHeaders);
HDITEM hdrItem;
m_HeaderCtrl->GetItem(0, & hdrItem);
hdrItem.mask = HDI_FORMAT | HDI_IMAGE;
hdrItem.iImage = 0; //index of up/down bitmap
CHeaderCtrl xyz;
m_HeaderCtrl->SetItem(0,&hdrItem);

解决方案 »

  1.   

        CImageList *ImgHeaders = new CImageList;
        ImgHeaders->Create(16,16,ILC_MASK,1,1);
        ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_UP));
        ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_DOWN));
        m_HeaderCtrl->SetImageList(ImgHeaders);
    //兄弟,一定要注意释放资源!!!!!!!!!!!!!!
    ImgHeaders->Detach();//经验告诉我,脱离掉才能显示出图片来!
    ImgHeaders->DeleteImageList();
    //不需要了就加个delete ImgHeaders

        HDITEM hdrItem;
        m_HeaderCtrl->GetItem(0, & hdrItem);
        hdrItem.mask = HDI_FORMAT | HDI_IMAGE;
        hdrItem.iImage = 0; //index of up/down bitmap
        CHeaderCtrl xyz;
        m_HeaderCtrl->SetItem(0,&hdrItem);
      

  2.   

    你喜欢New一个object出来,还得要随时删除。
    CHeaderCtrl* m_HeaderCtrl=new CHeaderCtrl;
    不如改为:
    CHeaderCtrl *m_HeaderCtrl= m_ListCtrl.GetHeaderCtrl();
    试了试,CHeaderCtrl->SetItem(Column,&Hditem)加载图标。
    似乎HDITEM .mask = HDI_IMAGE | HDI_FORMAT | HDI_TEXT更容易成功
    我的代码如下:
    void CMyDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码 /* 若当前排序列与点击列相同,则更改增、减序的排序方式。
    若点击列与当前排序列不同的列,则改变排序序,并将排序方式改为增序。*/
    enum   { sizeOfBuffer = 256 };
    TCHAR  lpBuffer[sizeOfBuffer];
    HDITEM hdi;
    hdi.pszText = lpBuffer;
    hdi.cchTextMax = sizeOfBuffer; CHeaderCtrl *pHdCtrl = m_ListCtrl.GetHeaderCtrl();
    int count = pHdCtrl->GetItemCount();
    for (int i=0; i <  count; i++)
    {
    hdi.mask = HDI_TEXT | HDI_IMAGE;
    pHdCtrl->GetItem(i, &hdi);
    if (i == pNMLV->iSubItem)//当前所选列
    {
    hdi.iImage = (hdi.iImage+1) %2;
    nSortOrder = hdi.iImage==0?1:-1; //nSortOrder  -1为降序,1表示升序。
    }
    else
    if (hdi.iImage==-1)
    continue;
    else
    hdi.iImage=-1; //-1为无图标
    hdi.mask = HDI_IMAGE | HDI_FORMAT | HDI_TEXT/* | HDI_WIDTH*/;
    hdi.fmt = HDF_LEFT | HDF_IMAGE | HDF_STRING;
    pHdCtrl->SetItem( i, &hdi );
    } Item mItem;
    mItem.mlist = &m_ListCtrl;
    mItem.Isub = pNMLV->iSubItem;
    for(int i=0;i < m_ListCtrl.GetItemCount();i++)
    {  
    m_ListCtrl.SetItemData(i,i);
    }
    m_ListCtrl.SortItems(CompareFunc,(LPARAM)&mItem);
    *pResult = 0;
    }// CMyDlg.h : 头文件
    //
    #pragma once
    #include "resource.h"
    typedef struct _Item
    {
    CListCtrl *mlist;
    int Isub;     //排序列
    }Item;
    static int nSortOrder=1;      // 排序的方式,1升序,-1降序。// CTpsOpDbDlg 对话框
    class CTpsOpDbDlg : public CPropertyPage
    {
    DECLARE_DYNAMIC(CTpsOpDbDlg)
    // 构造
    public:
    CTpsOpDbDlg(CWnd* pParent = NULL); // 标准构造函数
    // 对话框数据
    enum { IDD = IDD_TPSOPDB_DIALOG };
    protected:
    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
    // 实现
    protected:
    HICON m_hIcon; // 生成的消息映射函数
    virtual BOOL OnInitDialog();
    DECLARE_MESSAGE_MAP()
    public:
    int citem;
    CString ActiveID;
    CListCtrl m_ListCtrl;
    //排序的回调函数如下:
    static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 

    // 得到排序方式
    Item* pV=(Item*)lParamSort;   
    // 需要的排序参数比较
    CString sz1 = pV->mlist->GetItemText(lParam1,pV->Isub);
    CString sz2 = pV->mlist->GetItemText(lParam2,pV->Isub);
    if(nSortOrder == 1)
    return sz1.Compare(sz2);
    else
    return -sz1.Compare(sz2);

    afx_msg void OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult);
    };
      

  3.   

    你喜欢New一个object出来,还得要随时删除。
    CHeaderCtrl* m_HeaderCtrl=new CHeaderCtrl;
    不如改为:
    CHeaderCtrl *m_HeaderCtrl= m_ListCtrl.GetHeaderCtrl();
    试了试,CHeaderCtrl->SetItem(Column,&Hditem)加载图标。
    似乎HDITEM .mask = HDI_IMAGE | HDI_FORMAT | HDI_TEXT更容易成功我的代码如下:
    void CMyDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)
    {
            LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
            // TODO: 在此添加控件通知处理程序代码
            enum   { sizeOfBuffer = 256 };
            TCHAR  lpBuffer[sizeOfBuffer];
            HDITEM hdi;
            hdi.pszText = lpBuffer;
            hdi.cchTextMax = sizeOfBuffer;        CHeaderCtrl *pHdCtrl = m_ListCtrl.GetHeaderCtrl();
            int count = pHdCtrl->GetItemCount();
            for (int i=0; i <  count; i++)
            {
                    hdi.mask = HDI_TEXT | HDI_IMAGE;
                    pHdCtrl->GetItem(i, &hdi);
                    if (i == pNMLV->iSubItem)//当前所选列
                    {
                            hdi.iImage = (hdi.iImage+1) %2;
                            nSortOrder = hdi.iImage==0?1:-1; //nSortOrder -1为降序,1表示升序。
                    }
                    else
                            if (hdi.iImage==-1)
                                    continue;
                            else
                                    hdi.iImage=-1;        //-1为无图标
                    hdi.mask = HDI_IMAGE | HDI_FORMAT | HDI_TEXT/* | HDI_WIDTH*/;
                    hdi.fmt = HDF_LEFT | HDF_IMAGE | HDF_STRING;
                    pHdCtrl->SetItem( i, &hdi );
            }
            //排序
            Item mItem;
            mItem.mlist = &m_ListCtrl;
            mItem.Isub = pNMLV->iSubItem;
            for(int i=0;i < m_ListCtrl.GetItemCount();i++)
            {  
                    m_ListCtrl.SetItemData(i,i);
            }
            m_ListCtrl.SortItems(CompareFunc,(LPARAM)&mItem);
            *pResult = 0;
    }// CMyDlg.h : 头文件
    //
    #pragma once
    #include "resource.h"
    typedef struct _Item
    {
            CListCtrl *mlist;
            int Isub;     //排序列
    }Item;
    static int nSortOrder=1;      // 排序的方式,1升序,-1降序。// CTpsOpDbDlg 对话框
    class CTpsOpDbDlg : public CPropertyPage
    {
            DECLARE_DYNAMIC(CTpsOpDbDlg)
    // 构造
    public:
            CTpsOpDbDlg(CWnd* pParent = NULL);        // 标准构造函数
    // 对话框数据
            enum { IDD = IDD_TPSOPDB_DIALOG };
            protected:
            virtual void DoDataExchange(CDataExchange* pDX);        // DDX/DDV 支持
    // 实现
    protected:
            HICON m_hIcon;        // 生成的消息映射函数
            virtual BOOL OnInitDialog();
            DECLARE_MESSAGE_MAP()
    public:
            int citem;
            CString ActiveID;
            CListCtrl m_ListCtrl;
            //排序的回调函数如下:
            static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 
            { 
                    // 得到排序方式
                    Item* pV=(Item*)lParamSort;   
                    // 需要的排序参数比较
                    CString sz1 = pV->mlist->GetItemText(lParam1,pV->Isub);
                    CString sz2 = pV->mlist->GetItemText(lParam2,pV->Isub);
                    if(nSortOrder == 1)
                            return sz1.Compare(sz2);
                    else
                            return -sz1.Compare(sz2);
            } 
            afx_msg void OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult);
    };
      

  4.   

    表头那里有位置留空,但是没有图 //设置ListCtrl头
    m_rList.SetExtendedStyle( LVS_EX_FULLROWSELECT );
    m_rList.InsertColumn( 0, _T("网址"), LVCFMT_LEFT, 300 );
    m_rList.InsertColumn( 1, _T("说明"), LVCFMT_LEFT, 230 );
    m_rList.InsertColumn( 3, _T("耗时"), LVCFMT_LEFT, 80 );
    //添加ListCtrl数据
    int nRet;
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/index.asp") );
    //设置一个唯一的Item数据,否则无法排序
    m_rList.SetItemData( nRet, 0 );
    m_rList.SetItemText( nRet, 1, _T("天使知识授理厂") );
    m_rList.SetItemText( nRet, 2, _T("100") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?classID=789") );
    m_rList.SetItemData( nRet, 1 );
    m_rList.SetItemText( nRet, 1, _T("Android") );
    m_rList.SetItemText( nRet, 2, _T("20") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?classID=645") );
    m_rList.SetItemData( nRet, 2 );
    m_rList.SetItemText( nRet, 1, _T("Windows Mobile") );
    m_rList.SetItemText( nRet, 2, _T("300") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?classID=643") );
    m_rList.SetItemData( nRet, 3 );
    m_rList.SetItemText( nRet, 1, _T("iPhone") );
    m_rList.SetItemText( nRet, 2, _T("99") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?classID=644") );
    m_rList.SetItemData( nRet, 4 );
    m_rList.SetItemText( nRet, 1, _T("Symbian") );
    m_rList.SetItemText( nRet, 2, _T("20") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?ClassID=799") );
    m_rList.SetItemData( nRet, 5 );
    m_rList.SetItemText( nRet, 1, _T("嵌入式") );
    m_rList.SetItemText( nRet, 2, _T("111") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/About.asp") );
    m_rList.SetItemData( nRet, 6 );
    m_rList.SetItemText( nRet, 1, _T("关于我们") );
    m_rList.SetItemText( nRet, 2, _T("222") ); CImageList *ImgHeaders = new CImageList;
        ImgHeaders->Create(16,16,ILC_MASK,1,1);
        ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_UP));
        ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_DOWN)); enum   { sizeOfBuffer = 256 };
    TCHAR  lpBuffer[sizeOfBuffer];
    HDITEM hdi;
    hdi.pszText = lpBuffer;
    hdi.cchTextMax = sizeOfBuffer;
    CHeaderCtrl *pHdCtrl = m_rList.GetHeaderCtrl();
    int count = pHdCtrl->GetItemCount();
    for (int i=0; i <  count; i++)
    {
    hdi.mask = HDI_TEXT | HDI_IMAGE;
    pHdCtrl->GetItem(i, &hdi);
    //ImgHeaders->Detach();//经验告诉我,脱离掉才能显示出图片来!
    //ImgHeaders->DeleteImageList();
    hdi.iImage=1;
    hdi.mask = HDI_IMAGE | HDI_FORMAT | HDI_TEXT/* | HDI_WIDTH*/;
    hdi.fmt = HDF_LEFT | HDF_IMAGE | HDF_STRING;
    pHdCtrl->SetItem( i, &hdi );
    }
      

  5.   

    Quote: 引用 4 楼 popppig 的回复:

    表头那里有位置留空,但是没有图帮你添加3句!!!!
    //设置ListCtrl头
    m_rList.SetExtendedStyle( LVS_EX_FULLROWSELECT );
    m_rList.InsertColumn( 0, _T("网址"), LVCFMT_LEFT, 300 );
    m_rList.InsertColumn( 1, _T("说明"), LVCFMT_LEFT, 230 );
    m_rList.InsertColumn( 3, _T("耗时"), LVCFMT_LEFT, 80 );
    //添加ListCtrl数据
    int nRet;
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/index.asp") );
    //设置一个唯一的Item数据,否则无法排序
    m_rList.SetItemData( nRet, 0 );
    m_rList.SetItemText( nRet, 1, _T("天使知识授理厂") );
    m_rList.SetItemText( nRet, 2, _T("100") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?classID=789") );
    m_rList.SetItemData( nRet, 1 );
    m_rList.SetItemText( nRet, 1, _T("Android") );
    m_rList.SetItemText( nRet, 2, _T("20") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?classID=645") );
    m_rList.SetItemData( nRet, 2 );
    m_rList.SetItemText( nRet, 1, _T("Windows Mobile") );
    m_rList.SetItemText( nRet, 2, _T("300") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?classID=643") );
    m_rList.SetItemData( nRet, 3 );
    m_rList.SetItemText( nRet, 1, _T("iPhone") );
    m_rList.SetItemText( nRet, 2, _T("99") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?classID=644") );
    m_rList.SetItemData( nRet, 4 );
    m_rList.SetItemText( nRet, 1, _T("Symbian") );
    m_rList.SetItemText( nRet, 2, _T("20") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/Info_More.asp?ClassID=799") );
    m_rList.SetItemData( nRet, 5 );
    m_rList.SetItemText( nRet, 1, _T("嵌入式") );
    m_rList.SetItemText( nRet, 2, _T("111") );
    nRet = m_rList.InsertItem( m_rList.GetItemCount( ), _T("http://www.a3gs.com/About.asp") );
    m_rList.SetItemData( nRet, 6 );
    m_rList.SetItemText( nRet, 1, _T("关于我们") );
    m_rList.SetItemText( nRet, 2, _T("222") ); CImageList *ImgHeaders = new CImageList;
        ImgHeaders->Create(16,16,ILC_MASK,1,1);
        ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_UP));
        ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_DOWN));
    enum   { sizeOfBuffer = 256 };
    TCHAR  lpBuffer[sizeOfBuffer];
    HDITEM hdi;
    hdi.pszText = lpBuffer;
    hdi.cchTextMax = sizeOfBuffer;
    CHeaderCtrl *pHdCtrl = m_rList.GetHeaderCtrl();
    //有空格提示已经成功了,,图片没有是因为还没有SetImageList!!!!!!!!帮你加上!!!!!!!!!!!!!!!,
        pHdCtrl->SetImageList(&m_TypeImgList);  
    ImgHeaders->Detach();//经验告诉我,脱离掉才能显示出图片来!
    ImgHeaders->DeleteImageList();
    //帮你补上这3句 int count = pHdCtrl->GetItemCount();
    for (int i=0; i <  count; i++)
    {
    hdi.mask = HDI_TEXT | HDI_IMAGE;
    pHdCtrl->GetItem(i, &hdi); hdi.iImage=1;
    hdi.mask = HDI_IMAGE | HDI_FORMAT | HDI_TEXT/* | HDI_WIDTH*/;
    hdi.fmt = HDF_LEFT | HDF_IMAGE | HDF_STRING;
    pHdCtrl->SetItem( i, &hdi );
    }
      

  6.   

    不好意思!是这三句!
        CHeaderCtrl *pHdCtrl = m_rList.GetHeaderCtrl();
    //++++——————————————————————————————————————————————
        pHdCtrl->SetImageList(&m_TypeImgList);  
        m_TypeImgList->Detach();
        m_TypeImgList->DeleteImageList(); 
    //——————————————————————————————
        int count = pHdCtrl->GetItemCount();