Hi,我写的一个AP,dialog中有List Control,我选择的属性\Style中View: Report,Sort:升序。List Control有3个栏位。
我发现,我实际上给List Control填记录的次序,如果并不符合List Control首个栏位的顺序时,比如大部分记录顺序追加,在最后追加一个按字母顺序本应该更靠前的记录,show出来时,就会出现List Control自动将所有记录,以首个栏位顺序排列了。
糟糕的问题是,其它栏位的内容有丢失或者对应混乱的情况发生。有意思的是,我将List Control的Sort style设为None时,一切正常;即show出来的记录次序与我写入的次序相同,更重要的是,也没有某记录的非首个栏位内容错乱的情况。虽然问题绕过去了,但是我想与高手探究一下究竟为什么?
不知道我把问题描述清楚了吗?大侠可以很快地写个实验程序试试看。谢谢!

解决方案 »

  1.   

    在ListCtrl中进行排序 
    闻怡洋 [email protected] http://www.vchelp.net/  列表控件(CListCtrl)的顶部有一排按钮,用户可以通过选择不同的列来对记录进行排序。但是 CListCtrl并没有自动排序的功能,我们需要自己添加一个用于排序的回调函数来比较两个数据的大小,此外还需要响应排序按钮被点击的消息。下面讲述一下具体的做法。CListCtrl提供了用于排序的函数,函数原型为:BOOL CListCtrl::SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData )。其中第一个参数为全局排序函数的地址,第二个参数为用户数据,你可以根据你的需要传递一个数据或是指针。该函数返回-1代表第一项排应在第二项前面,返回1代表第一项排应在第二项后面,返回0代表两项相等。用于排序的函数原形为:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),其中第三个参数为调用者传递的数据(即调用SortItems时的第二个参数dwData)。第一和第二个参数为用于比较的两项的ItemData,你可以通过DWORD CListCtrl::GetItemData( int nItem )/BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )来对每一项的ItemData进行存取。在添加项时选用特定的CListCtrl::InsertItem也可以设置该值。由于你在排序时只能通过该值来确定项的位置所以你应该比较明确的确定该值的含义。最后一点,我们需要知道什么时候需要排序,实现这点可以在父窗口中对LVN_COLUMNCLICK消息进行处理来实现。 下面我们看一个例子,这个例子是一个派生类,并支持顺序/倒序两种方式排序。为了简单我对全局数据进行排序,而在实际应用中会有多组需要排序的数据,所以需要通过传递参数的方式来告诉派序函数需要对什么数据进行排序。
    //全局数据
    struct DEMO_DATA
    {
    char szName[20];
    int iAge;
    }strAllData[5]={{"王某",30},{"张某",40},{"武某",32},{"陈某",20},{"李某",36}};//CListCtrl派生类定义
    class CSortList : public CListCtrl
    {
    // Construction
    public:
    CSortList();
    BOOL m_fAsc;//是否顺序排序
    int m_nSortedCol;//当前排序的列
    protected:
    //{{AFX_MSG(CSortList)
    //}}AFX_MSG
    ...
    };//父窗口中包含该CListCtrl派生类对象
    class CSort_in_list_ctrlDlg : public CDialog
    {
    // Construction
    public:
    CSort_in_list_ctrlDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data
    //{{AFX_DATA(CSort_in_list_ctrlDlg)
    enum { IDD = IDD_SORT_IN_LIST_CTRL_DIALOG };
    CSortList m_listTest;
    //}}AFX_DATA
    }//在父窗口中定义LVN_COLUMNCLICK消息映射
    BEGIN_MESSAGE_MAP(CSort_in_list_ctrlDlg, CDialog)
    //{{AFX_MSG_MAP(CSort_in_list_ctrlDlg)
    ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, OnColumnclickList1)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()//初始化数据
    BOOL CSort_in_list_ctrlDlg::OnInitDialog()
    {
    CDialog::OnInitDialog(); //初始化ListCtrl中数据列表
    m_listTest.InsertColumn(0,"姓名");
    m_listTest.InsertColumn(1,"年龄");
    m_listTest.SetColumnWidth(0,80);
    m_listTest.SetColumnWidth(1,80);
    for(int i=0;i<5;i++)
    {
    m_listTest.InsertItem(i,strAllData[i].szName);
    char szAge[10];
    sprintf(szAge,"%d",strAllData[i].iAge);
    m_listTest.SetItemText(i,1,szAge);
    //设置每项的ItemData为数组中数据的索引
    //在排序函数中通过该ItemData来确定数据
    m_listTest.SetItemData(i,i);
    }
    return TRUE;  // return TRUE  unless you set the focus to a control
    }//处理消息
    void CSort_in_list_ctrlDlg::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    //设置排序方式
    if( pNMListView->iSubItem == m_listTest.m_nSortedCol )
    m_listTest.m_fAsc = !m_listTest.m_fAsc;
    else
    {
    m_listTest.m_fAsc = TRUE;
    m_listTest.m_nSortedCol = pNMListView->iSubItem;
    }
    //调用排序函数
    m_listTest.SortItems( ListCompare, (DWORD)&m_listTest );        
    *pResult = 0;
    }//排序函数实现
    int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
    //通过传递的参数来得到CSortList对象指针,从而得到排序方式
    CSortList* pV=(CSortList*)lParamSort;

    //通过ItemData来确定数据
    DEMO_DATA* pInfo1=strAllData+lParam1;
    DEMO_DATA* pInfo2=strAllData+lParam2;
    CString szComp1,szComp2;
    int iCompRes;
    switch(pV->m_nSortedCol)
    {
    case(0):
    //以第一列为根据排序
    szComp1=pInfo1->szName;
    szComp2=pInfo2->szName;
    iCompRes=szComp1.Compare(szComp2);
    break;
    case(1):
    //以第二列为根据排序
    if(pInfo1->iAge == pInfo2->iAge)
    iCompRes = 0;
    else
    iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
    break;
    default:
    ASSERT(0);
    break;
    }
    //根据当前的排序方式进行调整
    if(pV->m_fAsc)
    return iCompRes;
    else
    return iCompRes*-1;
    }