CListViewのソート

原理としては、比較用のコールバック関数を自作して
ハンドラからSortItemsに渡す。SortItemsはその関数を使って
アイテムを一つ一つ比較して並べ替えを行う。

比較用コールバック関数と作業用バッファの定義
 

char buf[ 1024 ];
int column = -1;
int sort = -1;
 
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
//メインダイアログの取得
CKdyDlg* d = (CKdyDlg*)AfxGetMainWnd();
ASSERT_VALID( d );
 
LV_ITEM lvi;
CString str1;
CString str2;
 
lvi.mask = LVIF_TEXT;
lvi.iSubItem = lParamSort;
lvi.pszText = buf;
lvi.cchTextMax = sizeof( buf );
 
lvi.iItem = lParam1;
//この関数が静的関数のため、メインフレームから情報を取得
d->m_List1.GetItem( &lvi );
str1 = buf;
lvi.iItem = lParam2;
//この関数が静的関数のため、メインフレームから情報を取得
d->m_List1.GetItem( &lvi );
str2 = buf;
 
// ソートの本体。カラムによって比較の仕方を変える
int a,b;
switch(lParamSort){ // 何番目のカラムをソートするか
// 商品コードの場合(数値比較)
case 0: a = atoi(str1.GetBuffer(4));
 b = atoi(str2.GetBuffer(4));
 if(sort==0){
  return a<b;
 } else {
  return a>b;
 }
 break;
// 価格の場合(数値比較)
case 3: a = atoi(str1.GetBuffer(4));
 b = atoi(str2.GetBuffer(4));
 if(sort==0){
  return a<b;
 } else {
  return a>b;
 }
 break;
// その他(商品名、個数などの場合、文字列比較)
default: return sort ? str1 < str2 : str1 > str2;
 break;
}
}
 
// 作業用関数(番号を振る)
void CDlg::ReNumberItems()
{
LV_ITEM lvi; // リスト ビュー アイテムの属性
lvi.mask = LVIF_PARAM;
int count = m_List1.GetItemCount();
 
for( int i = 0; i < count; i++ ){
lvi.iItem = i;
lvi.lParam = i;
for ( int j = 0; j < 3; j++ ){
lvi.iSubItem = j;
//
m_List1.SetItem( &lvi );
}
}
}
 
// カラムをクリックしたときのハンドラ
void CDlg::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
 
int sub = pNMListView->iSubItem;
 
sort = ( column == sub ? !sort : 0 );
column = sub;
 
ReNumberItems();
m_List1.SortItems( CompareFunc, sub );
 
*pResult = 0;
}