CListCtrlのヘッダー部分クリックによるソート機能
の実装をしたいのですが、どうして正しく動作しない
のかわかりません・・・。
 リソースエディタで、ダイアログに対してリストコン
トロールを貼り付け、ColumnClickイベント時にリスト
コントロールのSortItemsメソッドをコールしています。
MSDNを見る限りでは、ソートのコールバック関数は
  int CALLBACK CompareFunc(LPARAM lParam1,
              LPARAM lParam2, 
               LPARAM lParamSort);
の形で、現状正しいようなのですが、上記lParam1、
lParam2ともに0で毎回コールされます。
(コールされる回数は正しいです。)
 そのため、コールバック関数では0を返すために当然
ソートはされない結果となっています。
 リストコントロールのプロパティ等も見たのですが
該当するような変更箇所はないように思えます。
 どなたか、同様の現象に合った方、解決方法をご存知
の方がいらっしゃいましたら、回答お願い致します。
環境:Win2k
   VC++6.0Enterprise
   MSDN 2k April
らららです。
私は
void CXXXView::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    // pNMListView->iSubItemから何番目のカラムをクリックされたかを
    // 取得して、その項目でソート。しかし自作関数...
    *pResult = 0;
}
以下のようにすましてしまいました。
SortItemsメソッドを呼ぶだけで済むのでしょうか。
私も知りたいです。
Nakamuraです。
リストにデータを登録するときにSetItemData()を使って
データを設定していますか?
設定していないと、ソートされませんよ。
流れとしてはこんな感じになりますので参考にしてください。
※カラムが4個あってすべてについてソートさせる場合です。
・準備
 コールバック関数で使用する、リストコントロールのウインドウハンドルと
 各カラムの昇順/降順フラグをグローバル変数で定義する。
//昇順・降順判別で使用
#define UP	1
#define DOWN	0
//リストコントロールのウインドウハンドル設定
HWND m_hList;
//昇順・降順フラグ定義
int iItemSort[4];
※リストに登録するときには必ずSetItemData()関数を使用して
 ItemDataの登録を行うこと。(これを忘れるとソートまったく動作しない。)
・実装
//カラムクリック時のイベント取得
この関数では、並び替えようのサブ関数の呼び出しと、各カラムの
昇順/降順フラグの切り替えを行う。
void CMyListCtrl::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    int index = pNMListView->iSubItem;
    switch (index) {
	case 0:
  	    ListSort(0);
	    if (iItemSort[0] == UP) {
	        iItemSort[0] = DOWN;
	    } else {
	        iItemSort[0] = UP;
	    }
	    break;
	case 1:
	    ListSort(1);
	    if (iItemSort[1] == UP) {
	        iItemSort[1] = DOWN;
	    } else {
	        iItemSort[1] = UP;
	    }
	    break;
	case 2:	
	    ListSort(2);
	    if (iItemSort[2] == UP) {
	        iItemSort[2] = DOWN;
	    } else {
	        iItemSort[2] = UP;
	    }
	    break;
	case 3:
	    ListSort(3);
	    if (iItemSort[3] == UP) {
	        iItemSort[3] = DOWN;
	    } else {
	        iItemSort[3] = UP;
	    }
	    break;
	}
	*pResult = 0;
}
//並び替え実行の呼び出しを行う
引数には、カラムのインデックスが渡される。
void CMyListCtrl::ListSort(int col)
{
    SortItems(CompProc,col);
}
//並び替えのメイン処理
コールバック関数を使用して並び替えを行う。
int CALLBACK CompProc(LPARAM lp1, LPARAM lp2, LPARAM lp3)
{
    LV_FINDINFO lvf;
    int nItem1, nItem2;
    char buf1[1024], buf2[1024];
    lvf.flags = LVFI_PARAM;
    lvf.lParam = lp1;
    nItem1 = ListView_FindItem(m_hList, -1, &lvf);
    lvf.lParam = lp2;
    nItem2 = ListView_FindItem(m_hList, -1, &lvf);
    ListView_GetItemText(m_hList, nItem1, (int)lp3, buf1, sizeof(buf1));
    ListView_GetItemText(m_hList, nItem2, (int)lp3, buf2, sizeof(buf2));
    if (iItemSort[lp3] == UP) {
        return(strcmp(buf1, buf2));
    } else {
        return(strcmp(buf1, buf2) * -1);
    }
}
 SetItemDataでなく、InsertItemをした後、残りのカラム
にはSetItemTextをしています。
大まかな流れはNakamuraさんの内容と同様です。
 使うカラムは5つですが、昇順のみのソートすらできて
いないため、昇順降順切り替えまでは至っていない状況
です。参考になります・・・(^^;
 早速、SetItemDataを使い、かつNakamuraさんの記事内容
をもとに確認してみます。
 ありがとうございました。
解決「済」にするのを忘れました・・・。
Nakamuraです。
説明が悪かったようですが、InsertItem()とSetItemText()は必要無い
という意味ではなく、合わせてItemDataの登録が必要になるということ
ですのでお間違いなく。
InsertItem()とSetItemText()を使い、InsertItem()
のLVITEMのmaskにLVIF_PARAMをきちんと設定してやれば
SetItemData()を使わなくても動きました。
ItemDataの設定というのは、「アイテムに関連付ける
アプリケーション定義の32ビット値」イコールLVITEM
構造体のlParamメンバであり、それに値をセットする
ということだったわけですね。
これで全てつながりました。
要は、アイテムにLVIF_PARAMを関連付けてやらなくちゃ
いけないということですね。
ありがとうございました。

 
  
  
  
  
 
                        