ListControl + sort



  • ich versuche verzweifelt mein
    listcontrol dazu zu bekommen, dass es nach einer
    spalte sortiert. in der listcontrol mehrere werte.
    die vergleichsfunktion wird auch mehrmals aufgerufen,
    seltsamerweise sind die parameter lParam1 und lParam2 immer 0
    (bei jedem aufruf, dh. es wird nicht sortiert):

    void KlasseX::OnLvnColumnclickmeinListControl(NMHDR *pNMHDR, LRESULT *pResult)
    {
      meinListControl.SortItems( list_compare, (LPARAM)&meinListControl );
    }
    
    // ...
    // die callback funktion wird mehrere male aufgerufen immer mit
    // lParam1 und lParam2 == 0
    int CALLBACK
    	list_compare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
    	// lParamSort contains a pointer to the list view control.
       CListCtrl* pListCtrl = (CListCtrl*) lParamSort;
    
       // LParam1 und lParam2 sind IMMER 0
       // strItem hat den korrekten inhalt von zeile 0 und SPALTE_1
       CString    strItem1 = pListCtrl->GetItemText( lParam1, SPALTE_1 );
       CString    strItem2 = pListCtrl->GetItemText( lParam2, SPALTE_1 );
    
       return strcmp(strItem2, strItem1);
    }
    


  • In lParam1 und lParam2 stehen nicht die Indices der zu vergleichenden Einträge.

    Siehe FAQ:
    http://www.c-plusplus.net/forum/viewtopic.php?t=39109



  • danke, jetzt hab ich es hinbekommen 🙂
    ich habe aber eine einfachere loesung genommen.
    fuer alle, die sich nicht stundenlang durch die mengen der
    quelltexte wuehlen wollen hier meine loesung:

    - zuerst muesst ihr beim hinzufuegen eines items noch zusaetzlich
    den data-wert des items setzen
    (dieser wird der sortier-funktion als LPARAM p1 und p2 uebergeben)

    long index = m_ctrlBannedPlayers.GetItemCount();
    m_ctrlBannedPlayers.InsertItem( index , "" ); // item hinzufuegen
    // als daten einfach nochmal den index uebergeben
    m_ctrlBannedPlayers.SetItemData( index , index );
    
    // ....
    
    // das setzen der funktion zum sortieren und sortieren
    // im ereignis: LVN_COLUMNCLICK
    if ( listControl.SortItems( list_compare, (LPARAM)&listControl) == 0 )
      MessageBox( "Sortieren nicht moeglich", "Liste" );
    

    die sortierfunktion:

    int CALLBACK list_compare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
    	// lParamSort contains a pointer to the list view control.
    	CListCtrl* pListCtrl = reinterpret_cast<CListCtrl*>( lParamSort );
    
    	LVFINDINFO info;
    
            // den index der items bestimmen
    	info.flags = LVFI_PARAM;
    	info.lParam = lParam1;
    	int i1 = pListCtrl->FindItem( &info );
    	info.lParam = lParam2;
    	int i2 = pListCtrl->FindItem( &info );
    
            // den inhalt der items holen
    	CString    strItem1 = pListCtrl->GetItemText( i1, LIST_COLUMNS_BANNED_PLAYERS_NAME );
    	CString    strItem2 = pListCtrl->GetItemText( i2, LIST_COLUMNS_BANNED_PLAYERS_NAME );
    
    	return strItem1.CompareNoCase( strItem2 );
    }
    


  • Es reicht in den meisten Fällen nicht aus, den ItemData-Wert nur beim Hinzufügen zu setzen. Du musst bei dieser Lösung vor jedem Sort-Aufruf die Indices in die ItemData-Werte neu reinschreiben, weil sich beim Sortieren, Einfügen oder Löschen die Indices der Items ändern, die ItemData-Werte aber nicht.



  • MFK schrieb:

    Es reicht in den meisten Fällen nicht aus, den ItemData-Wert nur beim Hinzufügen zu setzen. Du musst bei dieser Lösung vor jedem Sort-Aufruf die Indices in die ItemData-Werte neu reinschreiben, weil sich beim Sortieren, Einfügen oder Löschen die Indices der Items ändern, die ItemData-Werte aber nicht.

    nein. das macht die FindItem-methode. die sucht zu einem ItemData-wert
    den passenden index.



  • entelechie schrieb:

    nein. das macht die FindItem-methode. die sucht zu einem ItemData-wert den passenden index.

    Jo, hast Recht, hatte ich übersehen.



  • und habe malk das beispiel von oben genommen beim kompilieren bekomme ich diese Meldung,... ich weiss aber nicht zu tun mit ihr 😞

    schaut mal:
    error C2664: 'SortItems' : cannot convert parameter 1 from 'int (long,long,long)' to 'int (__stdcall *)(long,long,long)'
    None of the functions with this name in scope match the target type



  • Hallo,

    hast du das CALLBACK vergessen? Und Deklaration nicht vergessen, wenn der Aufruf vor der Definition stattfindet:

    Deklaration
    [cpp]
    int CALLBACK
    list_compare(LPARAM, LPARAM, LPARAM);
    [/cpp]

    Definition

    int CALLBACK list_compare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
        // lParamSort contains a pointer to the list view control.
        CListCtrl* pListCtrl = reinterpret_cast<CListCtrl*>( lParamSort );
    
        LVFINDINFO info;
    
            // den index der items bestimmen
        info.flags = LVFI_PARAM;
        info.lParam = lParam1;
        int i1 = pListCtrl->FindItem( &info );
        info.lParam = lParam2;
        int i2 = pListCtrl->FindItem( &info );
    
            // den inhalt der items holen
        CString    strItem1 = pListCtrl->GetItemText( i1, LIST_COLUMNS_BANNED_PLAYERS_NAME );
        CString    strItem2 = pListCtrl->GetItemText( i2, LIST_COLUMNS_BANNED_PLAYERS_NAME );
    
        return strItem1.CompareNoCase( strItem2 );
    }
    

    MfG


Anmelden zum Antworten