CListCtrl上でソートを実現するには? – プログラミング – Home

CListCtrl上でソートを実現する...
 
通知
すべてクリア

[解決済] CListCtrl上でソートを実現するには?


あく
 あく
(@あく)
ゲスト
結合: 25年前
投稿: 5
Topic starter  

 CListCtrlのヘッダー部分クリックによるソート機能
の実装をしたいのですが、どうして正しく動作しない
のかわかりません・・・。

 リソースエディタで、ダイアログに対してリストコン
トロールを貼り付け、ColumnClickイベント時にリスト
コントロールのSortItemsメソッドをコールしています。

 MSDNを見る限りでは、ソートのコールバック関数は

  int CALLBACK CompareFunc(LPARAM lParam1,
              LPARAM lParam2,
            LPARAM lParamSort);

の形で、現状正しいようなのですが、上記lParam1、
lParam2ともに0で毎回コールされます。
(コールされる回数は正しいです。)

 そのため、コールバック関数では0を返すために当然
ソートはされない結果となっています。

 リストコントロールのプロパティ等も見たのですが
該当するような変更箇所はないように思えます。

 どなたか、同様の現象に合った方、解決方法をご存知
の方がいらっしゃいましたら、回答お願い致します。

環境:Win2k
   VC++6.0Enterprise
   MSDN 2k April


引用未解決
トピックタグ
ららら
(@admin-rarara)
メンバー Admin
結合: 5年前
投稿: 119
 

らららです。
私は
void CXXXView::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

// pNMListView->iSubItemから何番目のカラムをクリックされたかを
// 取得して、その項目でソート。しかし自作関数...

*pResult = 0;
}

以下のようにすましてしまいました。

SortItemsメソッドを呼ぶだけで済むのでしょうか。
私も知りたいです。


返信引用
Nakamura
 Nakamura
(@Nakamura)
ゲスト
結合: 25年前
投稿: 15
 

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);
}
}


返信引用
あく
 あく
(@あく)
ゲスト
結合: 25年前
投稿: 5
Topic starter  

 SetItemDataでなく、InsertItemをした後、残りのカラム
にはSetItemTextをしています。

 大まかな流れはNakamuraさんの内容と同様です。

 使うカラムは5つですが、昇順のみのソートすらできて
いないため、昇順降順切り替えまでは至っていない状況
です。参考になります・・・(^^;

 早速、SetItemDataを使い、かつNakamuraさんの記事内容
をもとに確認してみます。
 ありがとうございました。


返信引用
あく
 あく
(@あく)
ゲスト
結合: 25年前
投稿: 5
Topic starter  

解決「済」にするのを忘れました・・・。


返信引用
Nakamura
 Nakamura
(@Nakamura)
ゲスト
結合: 25年前
投稿: 15
 

Nakamuraです。
説明が悪かったようですが、InsertItem()とSetItemText()は必要無い
という意味ではなく、合わせてItemDataの登録が必要になるということ
ですのでお間違いなく。


返信引用
あく
 あく
(@あく)
ゲスト
結合: 25年前
投稿: 5
Topic starter  

InsertItem()とSetItemText()を使い、InsertItem()
のLVITEMのmaskにLVIF_PARAMをきちんと設定してやれば
SetItemData()を使わなくても動きました。

ItemDataの設定というのは、「アイテムに関連付ける
アプリケーション定義の32ビット値」イコールLVITEM
構造体のlParamメンバであり、それに値をセットする
ということだったわけですね。

これで全てつながりました。
要は、アイテムにLVIF_PARAMを関連付けてやらなくちゃ
いけないということですね。

ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました