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-Schleifem_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...