2016-12-09 57 views
1

を仕分けしながら、私は 仮想メソッドを実装する必要がドキュメント読んで、ソートをサポートCMFCListCtrlのサブクラスを持っている:奇妙な行動CMFCListCtrl

lParam1とlParam2はある種ののparamsある
virtual int OnCompareItems(LPARAM lParam1, LPARAM lParam2, int nColumn); 

を、リストコントロールが作成されたときに指定されます。

は私がこのように私の行を挿入したアルファベット順のソート必要があるので:この時点で

item.mask = LVIF_COLFMT | LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT; 
for (nI = 0; nI ....) 
{ 
    // UMASK, ITEM IDX, TEXT, STATE 1, STATE 2, IMAGE IDX, LPARAM 
    m_lstMateriali.InsertItem(item.mask, nI, _T(" "), 0, 0, SelezionaIcona(itIM->m_bSelez, itIM->m_eStatus), nI); 
    strQnt.Format(_T("%d"), itIM->m_nIdBolla); 
    m_lstMateriali.SetItemText(nI, 1, strQnt); 
    m_lstMateriali.SetItemText(nI, 2, itIM->m_strCodMater); 
    m_lstMateriali.SetItemText(nI, 3, itIM->m_strDescrMater); 
    m_lstMateriali.SetItemText(nI, 4, itIM->m_strColore); 
    strQnt.Format(_T("%d"), itIM->m_nDaTag); 
    m_lstMateriali.SetItemText(nI, 5, strQnt); 
    m_lstMateriali.SetItemData(nI, nI); 
} 

、私のサブクラスのソート方法を:

virtual int OnCompareItems(LPARAM lParam1, LPARAM lParam2, int nColumn) 
{ 
    int  nCol_1;    ///< 
    int  nCol_2;    ///< 
    CString strCol_1;   ///< 
    CString strCol_2;   ///< 

    strCol_1 = GetItemText(lParam1, nColumn); 
    strCol_2 = GetItemText(lParam2, nColumn); 
    switch (nColumn) 
    { 
    case 2: 
     return strCol_1.Compare(strCol_2); 
    } 
} 

が大幅に動作します。しかし、今はソートのために、私のLPARAMは行番号を表しているので正しくありません。 私はその後、ソート後をたまたまヘッダのクリック通知、取り扱い:

void CEliCUTK2SceltaMaterialiDlg::OnHdnItemclickLstSmListapezzi(NMHDR * pNMHDR, LRESULT * pResult) 
{ 
    int   nNumRig; 
    CString  strCodMat; 
    LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR); 
    LVITEM  item; 

    nNumRig = m_lstMateriali.GetItemCount(); 
    memset(&item, 0, sizeof(LVITEM)); 
    item.mask = LVIF_PARAM; 
    for (int nI = 0; nI < nNumRig; nI++) 
    { 
     item.iItem = nI; 
     item.lParam = nI; 
     m_lstMateriali.SetItem(&item); // (1) 
     strCodMat = m_lstMateriali.GetItemText(nI, 2); 
     // bla bla about item data 
    } 
    *pResult = 0; 
} 

を、それは最悪の練習かもしれませんが、今のところ、それはかなり良い作品:私は 新しい行に応じて新しいLPARAMsを設定数字。私も右の 行を更新したかどうかをチェックするために、ポイント(1)の前と後のテキストを取り上げました。すべてがうまく見えます:古いparamと新しいparamを取得しました。

今のところ、行ヘッダーで別の時間をクリックして降順で並べ替えると何が得られますか?すべてが不安定になった。 私はいくつかのものをチェックすることを決めたと、私は次のコードを追加:

void CEliCUTK2SceltaMaterialiDlg::OnLvnItemchangedLstSmListapezzi(NMHDR * pNMHDR, LRESULT * pResult) 
{ 
    int    nSot, nTip; 
    CString   strID; 
    DWORD_PTR  dwID; 
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); 
    LVITEM   item; 

    if (pNMLV->uNewState == 3) 
    { 
     dwID = m_lstMateriali.GetItemData(pNMLV->iItem); 
     memset(&item, 0, sizeof(LVITEM)); 
     item.mask = LVIF_PARAM; 
     item.iItem = pNMLV->iItem; 
     m_lstMateriali.GetItem(&item); 
     strID.Format(_T("PARAM: %ld."), item.lParam); 
     AfxMessageBox(strID); 
    } 
    *pResult = 0; 
} 

は、プログラムを再起動し、再びリストをソートし、(新しいLPARAMsが正しいことを再度確認した後)最初行をクリック 私は私が取得する必要がありながら

PARAM: 10. 

PARAM: 0. 

をメッセージが表示されました10は古い位置です。どこかで行方不明のものがありますか?

答えて

1

一般に、lParamに格納したいものは、リストを作成するために使用したデータ、または比較するデータを含む構造体へのポインタに戻ることができるものです。並列CListまたはstd :: listコレクション(またはCArrayまたはstd :: vector)がCListCtrlの存続期間中に順序を変更しない場合は、インデックスを配置することができます。

物事がソートされたり挿入されたりした後、リストの項目10には例のlParamが2になることがあります。元のデータソース(CList、CArray、レコードセットなど)にインデックスを付けるために「2」を使用し、そこでデータを取得し、元のデータに対して比較を使用したいとします。ソートすると、lParamのインデックスはCListCtrl(またはCMFCListCtrl)のインデックスと同じではないためです。

比較に必要なすべてのデータの構造を割り当てて、lParamメンバーに格納することができます。 (一部のMFCクラスではSetItemDataPtrを使用します)。データをクリーンアップするには、LVN_DELETEITEMメッセージを処理します。それは

Iがメンバーでデータを更新
// bla bla about item data 

であった:解決

+0

これは私がこれに似た別のクラスで行ったことです。とにかく、lParamを設定すると、アイテムを削除して戻さない限り、それを変更する方法はありません。 – IssamTP

+0

あなたはそれを変更して、何でもしても構いません。しかし、私はあなたがそれを変更する必要はないと思う。私は一度設定して元のデータを何とか参照してから、比較関数でlParamを使って元のデータを参照し、元のデータとの比較に基づいて値を返すべきだと思います。 –

+0

これでいいですが、変更することができれば(最高または最悪の練習は気にしません)なぜ0に設定すれば10にリセットされるのですか? – IssamTP