CTreeCtrl Bug?



  • Hi!!

    Ich habe ein CTreeCtrl, wo ich häufiger die Daten ändere. Dabei lösche ich bei jeder Aktualisierung die Elemente per:

    m_tree.DeleteAllItems();
    

    und füge danach neue ein per:

    for(int i=0; i<anz; i++)
    {
            m_tree.InsertItem("String", TVI_ROOT, TVI_ROOT);
    }
    

    Aber: Es werden keine Elemente angezeigt!! Wenn ich davor das DeleteAllItems weglasse, werden die Elemente angezeigt - nur dann verlängert sich die Liste natürlich bei jeder Aktualisierung, da die veraltenen Elemente nicht gelöscht werden.

    Kann es angehen, dass DeleteAllItems irgendwie das Ctrl komplett deinitialisiert oder ähnliches??



  • m_tree.InsertItem("String", TVI_ROOT, TVI_LAST);

    der letzte parameter ist die Einfügeposition (TVI_LAST = als letzten eintrag unter dem angegebenen parent)
    TVI_ROOT ist dafür nicht gültig, da der ja nur "virtuell" die (nicht sichtbare) Wurzel des trees beschreibt



  • Hier ist ne Lösung:

    http://p2p.wrox.com/archive/visual_c_plus_plus/2002-07/23.asp

    Die funktioniert auch!

    Das darf sich doch Bug nennen, oder?



  • a) TVI_ROOT als letzter Parameter ist in jedem Fall falsch, liegt also nicht unbedingt am SetRedraw (geht's denn mit TVI_LAST statt dem zweiten TVI_ROOT ?)

    b) Diese Bug ist mir bisher noch nicht untergekommen, konnte auch nirgendwo was finden (welche comctl32 Version(en) etc.), auch nicht das "originale" Problem auf dem Wrox-Messageboard. Konservativ würde ich da den Fehler erstmal bei mir (bzw. in diesem Faslle dir 😉 ) suchen.

    Die Common Controls, speziell ListView und TreeView, haben relativ häufig ein Problem mit WM_SETREDRAW, so daß ich davon die Finger lassen würde (sicherer und "schnell genug" ist es, alle Items programmatisch zu collapsen, und die root items nacheinander zu löschen)



  • hier bin ich wieder! 😉

    ich verwende jetzt folgenden code:

    void ClistctrlDlg::RefreshListe(void)
    {
    	if(m_tree.m_hWnd)
    	{
    		HTREEITEM hCurrent = m_tree.GetNextItem(TVI_ROOT, TVGN_NEXT);
    
    		while (hCurrent != NULL)
    		{
    			// Get the text for the item. Notice we use TVIF_TEXT because
    			// we want to retrieve only the text, but also specify TVIF_HANDLE
    			// because we're getting the item by its handle.
    			TVITEM item;
    			TCHAR szText[1024];
    			item.hItem = hCurrent;
    			item.mask = TVIF_TEXT | TVIF_HANDLE;
    			item.pszText = szText;
    			item.cchTextMax = 1024;
    
    			BOOL bWorked = m_tree.GetItem(&item);
    
    			// Try to get the next item
    			hCurrent = m_tree.GetNextItem(hCurrent, TVGN_NEXT);
    
    			m_tree.DeleteItem(item.hItem);
    		}
    
    		for(int i=0; i<m_liste.GetSize(); i++)
    			m_tree.InsertItem(m_liste[i]);
    	}
    }
    

    der debugger hält allerdings mit einer fehlermeldung, wo das erste mal GetNextItem ausgeführt wird.

    Den Code habe ich fast 1 zu 1 aus der MSDN (CTreeCtrl::DeleteItem), da ich meinem eigenem Code, der das selbe tat nicht traute. Wie sich jetzt zeigt, wohl zu unrecht, da der MSDN eigene Code auch Fehler erzeugt 😕

    Hier die Debugger Meldung:
    Eine Ausnahme (erste Chance) bei 0x780d0790 in listctrl.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xffff0004.
    Unbehandelte Ausnahme bei 0x780d0790 in listctrl.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xffff0004.

    Hier hab ich nochmal ein Beispiel Projekt, dass nichts anderes tut, als den Fehler zu erzeugen!

    http://www.fheinemann.de/Downloads/listctrl.zip (Visual C++.Net)

    Übrigens: Zusammenhänge zu dem anderen Posting, dass ich in den letzten Tagen gemacht habe sind nicht zufällig 😉

    **
    EDIT: Der Fehler wird noch lustiger, wenn man in der Funktion statt der Lösch-Schleife

    m_tree.DeleteAllItems();
    
    for(int i=0; i<m_liste.GetSize(); i++)
    	m_tree.InsertItem(m_liste[i]);
    

    setzt!** Dann zeigt er nämlich keine Daten mehr an!!!

    Außer, wenn man die oben beschriebene Lösung nutzt:

    m_tree.SetRedraw(FALSE);
    m_tree.DeleteAllItems();
    
    for(int i=0; i<m_liste.GetSize(); i++)
    {
    	CString a = m_liste[i];
    	m_tree.InsertItem(a);
    }
    m_tree.SetRedraw(TRUE);
    

    Ich hab langsam das Gefühl ich bin zu blöde für die Welt - oder der VS C++.NET Compiler hat einen sehr großen Bug 🙄 (auch, wenn ich das nicht wirklich glaube)

    Ich nutze übrigens nicht die neue VS C++.NET 2003 Version sondern noch die "alte" .NET Version.

    Und der Fehler tritt sowohl in meiner Firma auf als auch bei mir zu Hause auf...


Anmelden zum Antworten