关于点击列头排序的问题~~~~~~~~~~~~~~~~~~~~~~~~~

warmValue 2005-07-22 05:03:40
我按照定式写好了公共的排序函数int CALLBACK MyListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)

但运行的结果是点击列头后只是把列表中的item按照从头到尾倒过来排一下,并没有按照数据的大小排序,而且要点击两次列头才能排,请问这是怎么回事呀,我觉得是那个公共排序函数前两个参数值没有传好,请大家帮帮忙,sortitem(),和公共排序函数的运行原理是怎样的?谢谢!
...全文
147 点赞 收藏 13
写回复
13 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
warmValue 2005-07-23
多谢masterz提供的代码,我现研究+学习一下!
回复
masterz 2005-07-23
//////////////////////////enable sort of the listctrl
void CViewPorts::OnLvnColumnclickProcList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pnmv = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
if( pnmv->iSubItem == nSortedCol )
bSortAscending = !bSortAscending;
else
bSortAscending = TRUE;
nSortedCol = pnmv->iSubItem;
SortTextItems( nSortedCol, bSortAscending );
// bHandled = 0;
*pResult = 0;
}
BOOL CViewPorts::SortTextItems( int nCol, BOOL bAscending,int low , int high )
{
HWND hHeaderCtrl = ListView_GetHeader(hwndListView);
if (!hHeaderCtrl) return -1;
int nColCount =(int)::SendMessage(hHeaderCtrl, HDM_GETITEMCOUNT, 0L, 0L);
#ifdef _DEBUG
TCHAR tmp_msg[1024];
if(bAscending)
wsprintf(tmp_msg,"SortTextItems(%d,TRUE,%d,%d), nColCount:%d",nCol,low,high,nColCount);
else
wsprintf(tmp_msg,"SortTextItems(%d,FALSE,%d,%d), nColCount:%d",nCol,low,high,nColCount);
OutputDebugString(tmp_msg);
#endif
if(nCol>=nColCount)
return FALSE;

int itemcount=ListView_GetItemCount(hwndListView);
if( high == -1 )
high = itemcount - 1;
int lo = low;
int hi = high;
if( hi <= lo ) return FALSE;
std::basic_string<TCHAR> midItem=GetItemText( (lo+hi)/2, nCol );
// loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
std::vector<std::basic_string<TCHAR> > rowText;
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
//while( ( lo < high ) && ( GetItemText(lo, nCol) < midItem ) )
while( ( lo < high ) && CompareItem( midItem,GetItemText(lo, nCol) ) )
++lo;
else
while( ( lo < high ) && CompareItem( GetItemText(lo, nCol) , midItem ) )
//while( ( lo < high ) && ( GetItemText(lo, nCol) > midItem ) )
++lo;
// find an element that is smaller than or equal to
// the partition element starting from the right Index.
if( bAscending )
while( ( hi > low ) && CompareItem( GetItemText(hi, nCol) , midItem ) )
//while( ( hi > low ) && ( GetItemText(hi, nCol) > midItem ) )
--hi;
else
while( ( hi > low ) && CompareItem( midItem,GetItemText(hi, nCol)) )
//while( ( hi > low ) && ( GetItemText(hi, nCol) < midItem ) )
--hi;
// if the indexes have not crossed, swap
// and if the items are not equal
if( lo <= hi )
{
// swap only if the items are not equal
if( GetItemText(lo, nCol) != GetItemText(hi, nCol))
{
// swap the rows
LV_ITEM lvitemlo, lvitemhi;
rowText.resize( nColCount );
int i;
for( i=0; i<nColCount; i++)
rowText[i] = GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED | LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;

lvitemhi = lvitemlo;
lvitemhi.iItem = hi;
ListView_GetItem(hwndListView,&lvitemlo);
ListView_GetItem(hwndListView,&lvitemhi);
for( i=0; i<nColCount; i++)
SetItemText(lo, i, GetItemText(hi, i));
lvitemhi.iItem = lo;
ListView_SetItem(hwndListView,&lvitemhi);

for( i=0; i<nColCount; i++)
SetItemText(hi, i, rowText[i]);
lvitemlo.iItem = hi;
ListView_SetItem(hwndListView,&lvitemlo);
}
++lo;
--hi;
}
}
// If the right index has not reached the left side of array
// must now sort the left partition.
if( low < hi )
SortTextItems( nCol, bAscending , low, hi);
// If the left index has not reached the right side of array
// must now sort the right partition.
if( lo < high )
SortTextItems( nCol, bAscending , lo, high );
return TRUE;
}

std::basic_string<TCHAR> CViewPorts::GetItemText(int nItem, int nSubItem)
{
TCHAR itembuf[256];
memset(itembuf,0,sizeof(itembuf));
ListView_GetItemText(hwndListView,nItem,nSubItem,itembuf,sizeof(itembuf)-1);
return std::basic_string<TCHAR>(itembuf);
}

void CViewPorts::SetItemText(int item, int subitem, std::basic_string<TCHAR> sdata)
{
TCHAR tmpbuf[256];
ZeroMemory(tmpbuf,sizeof(tmpbuf));
wsprintf(tmpbuf,_T("%s"),sdata.c_str());
ListView_SetItemText(hwndListView,item,subitem,tmpbuf);
}

bool CViewPorts::CompareItem(std::basic_string<TCHAR> &str1, std::basic_string<TCHAR> &str2)
{
if(IsNumberString(str1)&&IsNumberString(str2))
{
return _ttoi(str1.c_str()) > _ttoi(str2.c_str());
}
else
return str1>str2;
}

bool CViewPorts::IsNumberString(std::basic_string<TCHAR> &s_param)
{
int str_len = s_param.length();
if(str_len<1)
return false;
for(int i=0;i<str_len;i++)
{
if(!_istdigit(s_param.at(i)))
return false;
}
return true;
}
回复
masterz 2005-07-23
//sort the list control
HWND hwndListView;
int nSortedCol;
BOOL bSortAscending;
void SetItemText(int item,int subitem,std::basic_string<TCHAR> sdata);
std::basic_string<TCHAR> GetItemText(int nItem, int nSubItem);
BOOL SortTextItems( int nCol, BOOL bAscending,int low = 0, int high = -1);
bool IsNumberString(std::basic_string<TCHAR>& s_param);
bool CompareItem(std::basic_string<TCHAR>& str1,std::basic_string<TCHAR>& str2);
afx_msg void OnLvnColumnclickProcList(NMHDR *pNMHDR, LRESULT *pResult);
//sort listcontrol end
回复
warmValue 2005-07-23
我是在父窗口的头文件里这样声明的
// Dialog Data
//{{AFX_DATA(CBaseProtocol)
enum { IDD = IDD_DIALOG_pro };
CListCtrl m_result;
CString m_btime;
CString m_etime;
CString m_all;
CString m_spagenum;
CString m_sshowpage;
CSortCListCtrl m_yktlist;
//}}AFX_DATA
回复
warmValue 2005-07-23
我按照goodboyws(深夜不眠者)说的做了也不行,我试了一下m_yktlist.GetItemCount()取到的记录条数是0,难道是我对m_yktlist的声明不对么?
回复
vcmute 2005-07-22
http://www.vckbase.com/code/listcode.asp?mclsid=3&sclsid=323&page=3

把调用的代码贴出来看看?
回复
goodboyws 2005-07-22
SetItemData排序以后再调一遍
void CAuditingCertView::OnColumnclickListYkt(NMHDR* pNMHDR, LRESULT* pResult)
{

for (int i = 0; i < m_yktlist.GetItemCount(); ++i)
{
m_yktlist.SetItemData(i, i);//供排序使用的item编号
}

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

//设置排序方式
if( pNMListView->iSubItem ==m_yktlist.m_nSortedCol )
m_yktlist.m_fAsc = !m_yktlist.m_fAsc;
else
{
m_yktlist.m_fAsc = TRUE;
m_yktlist.m_nSortedCol = pNMListView->iSubItem;
}
//调用排序函数,此函数为CListCtrl定义好的,但是需要调用我们定义的函数才比较任意两个项目的值
m_yktlist.SortItems(MyListCompare, (LPARAM)&m_yktlist);
for (i = 0; i < m_yktlist.GetItemCount(); ++i)
{
m_yktlist.SetItemData(i, i);//供排序使用的item编号
}
*pResult = 0;
}
回复
warmValue 2005-07-22
公共的排序函数里前两个参数lParam1和lParam2可以直接用么?用不用给它们付值?
回复
warmValue 2005-07-22
主要是根据这个写的


定义可以排序的列表类
只需要多定义两个变量
class SortCListCtrl : public CListCtrl
{
// Construction
public:
SortCListCtrl();

// Attributes
public:
BOOL m_fAsc;//是否顺序排序
int m_nSortedCol;//当前排序的列
....
}
在使用可以排序列表时 实例化自己的变量
SortCListCtrl m_yktlist;


//响应点击列函数
void CAuditingCertView::OnColumnclickListYkt(NMHDR* pNMHDR, LRESULT* pResult)
{

for (int i = 0; i < m_yktlist.GetItemCount(); ++i)
{
m_yktlist.SetItemData(i, i);//供排序使用的item编号
}

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

//设置排序方式
if( pNMListView->iSubItem ==m_yktlist.m_nSortedCol )
m_yktlist.m_fAsc = !m_yktlist.m_fAsc;
else
{
m_yktlist.m_fAsc = TRUE;
m_yktlist.m_nSortedCol = pNMListView->iSubItem;
}
//调用排序函数,此函数为CListCtrl定义好的,但是需要调用我们定义的函数才比较任意两个项目的值
m_yktlist.SortItems(MyListCompare, (LPARAM)&m_yktlist);

*pResult = 0;
}

///全局函数,比较两个项目的依据
int CALLBACK MyListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
//通过传递的参数来得到CSortList对象指针,从而得到排序方式
SortCListCtrl * pV=(SortCListCtrl *)lParamSort;
//通过ItemData来确定数据
CString szComp1,szComp2;
int iCompRes;
szComp1=pV->GetItemText(lParam1,pV->m_nSortedCol);
szComp2=pV->GetItemText(lParam2,pV->m_nSortedCol);
switch(pV->m_nSortedCol)
{
case(0):
//以第一列为根据排序 编号
iCompRes=atof(szComp1)<=atof(szComp2)?-1:1;
break;
case(4):
//以第5列为根据排序 总次数
iCompRes=atof(szComp1)<=atof(szComp2)?-1:1;
break;
default:
iCompRes=szComp1.Compare(szComp2);
break;
}
//根据当前的排序方式进行调整
if(pV->m_fAsc)
return iCompRes;
else
return -iCompRes;



回复
warmValue 2005-07-22
我调试过,发现根本没有取到要比较的数据,我主要也是根据网上的例子写的!
回复
rick29 2005-07-22
仔细看看你的排序函数,F5跟踪一下,看看是否是的确根据需要排列的数据进行比对的。
回复
AntonlioX 2005-07-22
jf
回复
快乐鹦鹉 2005-07-22
网上下个例子。照着看一下。如果找不到的话,我手头有一个,很不错的。
回复
发帖
界面
创建于2007-09-28

1.5w+

社区成员

VC/MFC 界面
申请成为版主
帖子事件
创建了帖子
2005-07-22 05:03
社区公告
暂无公告