質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

7500閲覧

VisualStadio2005 MFC のリストコントロールでソートの方法

izuki_y

総合スコア65

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2015/02/12 16:08

MFCのリストコントロールでソート処理を行いたいのですが、以下の様に作りましたがソートが行われません。
コールバック関数の引数LPARAM lParam1, LPARAM lParam2,は共に0が入ったままになっています。
わかる人がいましたらぜひ教えて下さい。

lang

1// フォルダ内からOutput_xxxx_xxxx.binファイルを探してリストに登録 2void CSampleDlg::OnEnChangeEdit1() 3{ 4 BOOL bContinue; 5 CFileFind cFind; 6 CString strFile; 7 CString strFolder = szDisplayName; 8 CString strExtension; 9 LVITEM lvi; 10 11 if(strFolder.Right(1) != "\"){ 12 strFolder += "\Output*.bin"; 13 } 14 strFolder += strExtension; 15 16 bContinue = cFind.FindFile(strFolder); 17// 要検証 18 while(bContinue){ 19 int i=0; 20 21 bContinue = cFind.FindNextFile(); 22 23 if(cFind.IsDirectory() == FALSE) 24 { 25 INT i=0, index ; 26 27 strFile = cFind.GetFileName(); 28 29 int f = strFile.Find('_'); 30 int l = strFile.ReverseFind('_'); 31 int e = strFile.ReverseFind('.'); 32 33 // Mid(offset, length) 34 CString csSeq = strFile.Mid(f+1, l-(f+1)); 35 CString csLen = strFile.Mid(l+1, e-(l+1)); 36 37 lvi.mask = LVIF_TEXT; 38 lvi.iItem = i++; 39 lvi.iSubItem = 0; 40 lvi.pszText = (LPTSTR)(LPCTSTR)strFile; 41 if (index = m_xcList.InsertItem(&lvi) == -1) break; 42 43 lvi.iItem = index; 44 lvi.iSubItem = 1; 45 lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(csSeq)); 46 if (!m_xcList.SetItem(&lvi)) break; 47 48 lvi.iItem = index; 49 lvi.iSubItem = 2; 50 lvi.pszText = (LPTSTR)(LPCTSTR)csLen; 51 if (!m_xcList.SetItem(&lvi)) break; 52 53 CString sum; 54 sum.Format("%lu", (strtoul(csSeq,NULL,10))+atol(csLen)); 55 lvi.iItem = index; 56 lvi.iSubItem = 3; 57 lvi.pszText = (LPTSTR)(LPCTSTR)sum; 58 if (!m_xcList.SetItem(&lvi)) break; 59 60 } 61 } 62} 63 64// コールバック関数 クラス内に定義する場合はStaticを付ける事 65int CALLBACK CSampleDlg::CompareData(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 66 67 68// カラムクリックイベント 69void CBinUnitDlg::OnLvnColumnclickList2(NMHDR *pNMHDR, LRESULT *pResult) 70{ 71 LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // <LPNMLISTVIEW>が必要 72 m_xcList.SortItems( &CBinUnitDlg::CompareData, pNMLV->iSubItem); 73 74 // フラグを逆にする 75 flag = !flag; 76 77} 78 79// ソート 80int CALLBACK CSampleDlg::CompareData(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 81{ 82 LV_FINDINFO lvf; 83 int idx1 , idx2; 84 TCHAR szBuf1[256],szBuf2[256]; 85 86 87 lvf.flags = LVFI_PARAM ; 88 lvf.lParam = lParam1 ; 89 idx1 = m_xcList.FindItem(&lvf,-1) ; 90 lvf.lParam = lParam2 ; 91 idx2 = m_xcList.FindItem(&lvf,-1) ; 92 memset(szBuf1,0x00,sizeof(szBuf1)); 93 memset(szBuf2,0x00,sizeof(szBuf2)); 94 m_xcList.GetItemText( idx1 , (int)lParamSort , szBuf1 , sizeof(szBuf1)) ; 95 m_xcList.GetItemText( idx2 , (int)lParamSort , szBuf2 , sizeof(szBuf2)) ; 96 97 98 if(flag==TRUE) 99 return(_tcscmp(szBuf1,szBuf2)) ; 100 else 101 return(_tcscmp(szBuf1,szBuf2)* -1) ; 102 103 104} 105

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

取りあえず動くようにするならリスト明細を登録しているのループの最後に

item.mask = LVIF_PARAM;
item.lParam= idx;
_pList->SetItem( &item );

とすれば lp1とlp2に希望の値が入ってくると思います。

投稿2015/02/20 23:13

lazy_tsan

総合スコア51

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

izuki_y

2015/02/23 10:35

回答ありがとうございました。 教えて頂いた構文を追加してみた所、for文の末端だと上手くいきませんでしたが、 InsertItem の 後に記載すると上手くいきました。 やはり原因はアイテムにLVIF_PARAMを関連付けてない事だった様で無事ソートされる事を確認したしました。 ありがとうございました。 参考 http://rarara.cafe.coocan.jp/cgi-bin/lng/vc/vclng.cgi?print+200006/00060030.txt // リストのヘッダ _pList->InsertColumn(0, _T("ファイル名"), LVCFMT_LEFT,50, -1); _pList->InsertColumn(1, _T("SEQ"), LVCFMT_LEFT, 100, -1); _pList->InsertColumn(2, _T("Len"), LVCFMT_LEFT, 50, -1); // リストの明細 LV_ITEM item; for(short idx=0;idx < 4 ; idx++){ item.iItem = idx; item.mask = LVIF_TEXT; item.pszText = info[idx].file; item.iSubItem = 0; _pList->InsertItem( &item ) ; // ここに入れるとソートされる(2015/02/23) item.mask = LVIF_PARAM; item.lParam= idx; _pList->SetItem( &item ); item.mask= LVIF_TEXT; item.pszText = info[idx].seq; item.iSubItem = 1 ; _pList->SetItem( &item ) ; item.pszText = info[idx].len; item.iSubItem = 2 ; _pList->SetItem( &item ) ; // ここだとソートが反映されない(2015/02/23) // item.mask = LVIF_PARAM; // item.lParam= idx; // _pList->SetItem( &item ); } return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。 }
guest

0

SortItems() に渡す関数、及びパラメータの意味を勘違いしていると思います。
lParam1,lParam2 はLVITEM内の lParam の値が渡されますが、提示されているソースには設定されているようすがありません。
適切な値を LVITEM内のlParam に設定すれば lParam1,lParam2 に渡ってくるはずです。

あと CompareData() は静的メンバ関数なのでクラス内のメンバ変数にはアクセス出来ないはずですが、このソースコンパイル通りますか?

投稿2015/02/18 13:06

lazy_tsan

総合スコア51

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

izuki_y

2015/02/20 16:04

回答ありがとうございました。 >あと CompareData() は静的メンバ関数なのでクラス内のメンバ変数にはアクセス出来ないはずですが、このソースコンパイル通りますか? うっかりしていました、確かにその通りです。 クラス内に定義していないのにスコープ演算子を使って定義していました。 紛らわしくて申し訳ありませんでした。 もう一度リストコントロールの処理のみに焦点を置いてMFCダイアログベースで 作り直してみましたが、やはりソートされません。 もしよろしければ確認をお願い致します。 // CtrlviewListSampleDlg.cpp : 実装ファイル // ...前略..... // ソートデータ #define LIST_SIZE 5 typedef struct __tagListinfo{ TCHAR file[50]; TCHAR seq[50]; TCHAR len[50]; } LISTINFO; LISTINFO info[LIST_SIZE]; // ソートフラグ(降順、昇順) #define UP 1 #define DOWN 2 int sortFlg[]={UP,UP,UP,UP} ; // コールバック関数 int CALLBACK MyListComp(LPARAM ,LPARAM ,LPARAM ); // リストコントロール CListCtrl* _pList; ....中略...... // CCtrlviewListSampleDlg ダイアログ CCtrlviewListSampleDlg::CCtrlviewListSampleDlg(CWnd* pParent /*=NULL*/) : CDialog(CCtrlviewListSampleDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); _tcscpy(info[0].file,_T("Output_0001.bin")); _tcscpy(info[0].seq,_T("1000")); _tcscpy(info[0].len,_T("100")); _tcscpy(info[1].file,_T("Output_0002.bin")); _tcscpy(info[1].seq,_T("1100")); _tcscpy(info[1].len,_T("100")); _tcscpy(info[2].file,_T("Output_0003.bin")); _tcscpy(info[2].seq,_T("1200")); _tcscpy(info[2].len,_T("100")); _tcscpy(info[3].file,_T("Output_0004.bin")); _tcscpy(info[3].seq,_T("1300")); _tcscpy(info[3].len,_T("100")); _tcscpy(info[4].file,_T("Output_0005.bin")); _tcscpy(info[4].seq,_T("1400")); _tcscpy(info[4].len,_T("100")); } void CCtrlviewListSampleDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, Ctrllist); } BEGIN_MESSAGE_MAP(CCtrlviewListSampleDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, &CCtrlviewListSampleDlg::OnLvnColumnclickList1) END_MESSAGE_MAP() // CCtrlviewListSampleDlg メッセージ ハンドラ BOOL CCtrlviewListSampleDlg::OnInitDialog() { CDialog::OnInitDialog(); .....中略..... // TODO: 初期化をここに追加します。 _pList = &Ctrllist; // リストのスタイル(レポート、1行選択等) _pList->SetExtendedStyle(_pList->GetExtendedStyle()|LVS_EX_SUBITEMIMAGES|LVS_EX_FULLROWSELECT); _pList->ModifyStyle(NULL,LVS_REPORT); // カラムの削除 if(_pList->GetHeaderCtrl()){ int cnt = _pList->GetHeaderCtrl()->GetItemCount(); for (int i=0;i < cnt;i++) _pList->DeleteColumn(0); } // リストのヘッダ _pList->InsertColumn(0, _T("ファイル名"), LVCFMT_LEFT,50, -1); _pList->InsertColumn(1, _T("SEQ"), LVCFMT_LEFT, 100, -1); _pList->InsertColumn(2, _T("Len"), LVCFMT_LEFT, 50, -1); // リストの明細 LV_ITEM item; for(short idx=0;idx < 4 ; idx++){ item.iItem = idx; item.mask = LVIF_TEXT; item.pszText = info[idx].file; item.iSubItem = 0; _pList->InsertItem( &item ) ; item.mask= LVIF_TEXT; item.pszText = info[idx].seq; item.iSubItem = 1 ; _pList->SetItem( &item ) ; item.pszText = info[idx].len; item.iSubItem = 2 ; _pList->SetItem( &item ) ; } return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。 } ..中略... void CCtrlviewListSampleDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult) { UpdateData(); LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // フラグを逆にする if (sortFlg[pNMLV->iSubItem] == UP){ sortFlg[pNMLV->iSubItem] = DOWN ; } else{ sortFlg[pNMLV->iSubItem] = UP ; } // ソート処理 _pList->SortItems( MyListComp , pNMLV->iSubItem ); *pResult = 0; } // コールバック int CALLBACK MyListComp( LPARAM lp1 ,LPARAM lp2, LPARAM lp3 ) { LV_FINDINFO lvf; int idx1 , idx2; TCHAR szBuf1[256],szBuf2[256]; lvf.flags = LVFI_PARAM ; lvf.lParam = lp1 ; idx1 = _pList->FindItem(&lvf,-1) ; lvf.lParam = lp2 ; idx2 = _pList->FindItem(&lvf,-1) ; _pList->GetItemText( idx1 , (int)lp3 , szBuf1 , sizeof(szBuf1)) ; _pList->GetItemText( idx2 , (int)lp3 , szBuf2 , sizeof(szBuf2)) ; if(sortFlg[(int)lp3]==UP) return(_tcscmp(szBuf1,szBuf2)) ; else return(_tcscmp(szBuf1,szBuf2)* -1) ; }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問