Treeview SelectItem
-
> 1. Bau doch nur eine Liste mit einem entsprechenden paar HTREEITEM, DString. Dann musst Du nicht zwei vectoren verwalten.
und wie soll ich dann an die namen kommen ?> 2. Warum hast Du überhaupt diesen vector?
a. ich kann alle items durchlaufen und ggf. vergleichen
b. ich hab direkten zugriff auf die namen der items> Ich arbeite immer nur mit der GUI. D.h. wenn jetzt was zu suchen ist durchlaufe ich den TreeView. Die daten sind doch redundant.
die gesammte liste durchlaufen ? mit allen subitems und items ?zb. ich sage "SelectItem(std::wstring StringName)"
das selektiert dann das item mit diesen angegebenen namen
wenn ich die GUI liste durchlaufen will muss ich ja zuerst erstes item holen, dann irgendwie den namen auslesen, dann vergleichen und wenn nichts ist das naechste item,
so brauch ich nur meinen zweiten vector nach dem namen durchsuchen, und hab dann die position wo ich dann in der ersten vectorliste sagen kann welche selektiert werden kannich hab bisher diese funktionen erfolgreich implementiert:
private: std::vector<HTREEITEM>m_Items; std::vector<DString>m_ItemsText; UINT GetItemNumber(std::wstring Name); std::wstring GetItemText(HTREEITEM Item); public: BOOL AddElement(std::wstring Name, std::wstring Parent = _T("")); BOOL SelectItem(std::wstring Name); void Deselect(); void Clear(); void Expand(std::wstring Name = _T("")); UINT GetSelectedItemNumber(); BOOL DeleteItem(std::wstring Item); BOOL DeleteSelectedItem(); std::wstring GetSelectedItemText(); std::wstring GetParentItem(std::wstring Child); std::vector<DString> GetChildItems(std::wstring Parent); std::vector<DString> GetRootItems(); BOOL SetSelectedItemText(std::wstring Text); BOOL SetItemText(std::wstring OldName, std::wstring NewName);also komplette steuerung der items nur anhand der namen {o; und darum gings mir (wenn ein string default auf _T("") steht bedeutet das root)
-
Ich habe mich auch mal intensiver mit dem TreeView beschäftigt und diese Frage bezüglich der Position usw. auch gefragt. Ich weis nicht ob ich deins direkt Verstanden habe. Aber ich finde die Lösung (so wie ich sie Verstanden habe) mit den Namen nicht so gut. Das ist doch nicht eindeutig! Oder? Was ist wenn du 2 mal den selben Namen hast?
Da ich bei meinem TreeView genau wusste wie viele SubItems ein Parent haben konnte hab ich mir ne struct alastruct TreeViewPos { int Parent; int FirstChild; int SecondChild; int ThirdChild; int FourthChild; };Naja war auch nicht die beste Lösung aber damals hat es gefunzt

> 1. Bau doch nur eine Liste mit einem entsprechenden paar HTREEITEM, DString. Dann musst Du nicht zwei vectoren verwalten.
und wie soll ich dann an die namen kommen ?Wenn du ein HTREEITEM hast kannst du doch ganz einfach den Namen herausbekommen

MfG schirrmie
-
Mr Evil schrieb:
> 1. Bau doch nur eine Liste mit einem entsprechenden paar HTREEITEM, DString. Dann musst Du nicht zwei vectoren verwalten.
und wie soll ich dann an die namen kommen ?Ich verstehe die Frage nicht. Ob Du nun 2 Arrays hast oder einen Array mit einer struct oder einem pair, Du kommst genau gleich an den Namen!
Nr Evil schrieb:
> 2. Warum hast Du überhaupt diesen vector?
a. ich kann alle items durchlaufen und ggf. vergleichen
b. ich hab direkten zugriff auf die namen der itemsUnd warum brauchst Du das? Entweder hat der Tree die Kontrolle oder nicht. Alles andere ist überflüssiger Verwaltungsaufwand.
Ich Speichere meine Daten im Baum unter einem Text. Einen entsprechenden Zeiger auf weitere Daten oder eine ID kommen in das lparam Feld des Tree-Items.Wenn ich einen Konten in meinem Baum Suche, dann traversiere ich den Baum.
Nr Evil schrieb:
zb. ich sage "SelectItem(std::wstring StringName)"
das selektiert dann das item mit diesen angegebenen namen
wenn ich die GUI liste durchlaufen will muss ich ja zuerst erstes item holen, dann irgendwie den namen auslesen, dann vergleichen und wenn nichts ist das naechste item,
so brauch ich nur meinen zweiten vector nach dem namen durchsuchen, und hab dann die position wo ich dann in der ersten vectorliste sagen kann welche selektiert werden kannDafür hast Du doppelte Datenhaltung. Wenn Du jetzt mit einem Drag&Drop anfängst, oder mit Sortieren der Unterknoten oder sonstigen netten Spielereien kannst Du Dir den vector schenken.
Als Grundsatz habe ich mir angewöhnt:
1. Daten gibt es nur an einer Stelle.
2. Alles was die Daten representiert hat einen Verweis auf diese Daten.
3. Eine 1:1 Verknüpfung von GUI (sprich Darstellung) zur Datenhaltung ist möglichst zu vermeiden, da dies nur Probleme mit Sortieren Drag&Drop etc bringt.Just my 2 cents!
-
und wie soll ich aus nem HTREEITEM den namen bekommen ?
ich hab google abgestoebert, auch die MSDN rauf und runter - nirgends find ich informationen wie ich den namen eines items aus TREEITEM auslesen kann - das ist ja die ganze zeit schon die problematik
-
Na wenns weiter nix ist

Mit nem HTREEITEM kannst du an sich alles machen wie mit nem HITEM.void TreeView::GetItem(HTREEITEM htitem, TVITEM *tvi) { char Buffer[2001] = ""; //Hole den Namen des TreeviewItem's tvi->mask = TVIF_HANDLE | TVIF_TEXT; tvi->hItem = htitem; tvi->pszText = Buffer; tvi->cchTextMax = 2000; TreeView_GetItem(Hwnd, tvi); } char * TreeView::GetItemText(HTREEITEM htitem) { TVITEM Tvi; char Buffer[5000] = ""; GetItem(htitem, &Tvi); Tvi.mask = TVIF_TEXT; Tvi.pszText = Buffer; TreeView_GetItem(Hwnd, &Tvi); return Buffer; }MfG schirrmie
-
vor ein paar minuten hatte ichs endlich hinbekommen
std::wstring CTreeview::GetItemText(HTREEITEM Item){
TVITEM item;
item.hItem = Item;
item.mask = TVIF_TEXT;
std::wstring str;
item.pszText = (LPTSTR)str.c_str();
item.cchTextMax = (int)str.capacity();
::SendMessage(m_Handle, TVM_GETITEM, NULL, (LPARAM)&item);
return str.c_str();
}ps. mit macros arbeite ich nicht, makros doof und boese #gg
bin grad dabei meine methoden neu zu implementieren - also alles neu aufzubauen ohne die listen - nicht so einfach den gesammten baum zu durchsuchen - und wie ich doppelte namen handel weiss ich noch nicht {wenn ich sag add item und den string das parent angeb, das ich weiss zu welchem item es added werden soll}
-
Ist das mit den Makros auf mein Code bezogen? Da sind keine Makros drinne.
Ja das mein ich ja mit den Namen das ist ne schlechte Implementierung weil du nix eindeutiges hast. Mach es wie einer meiner Vorredner gesagt hat und nimm das LPARAM vom ITEM da kannst ja soviele Informationen reinpacken wie du willst.MfG schirrmie
-
Doch TreeView_GetItem ist ein Makro!
Allerdings kann ich diese Meinung nicht teilen. Diese Art Makros helfen immens beim korrekten Umgang mit den entsprechenden Fensterklassen!
-
Achso stimmt ja daran hab ich garnicht gedacht. Naja ob da nun nen SendMessage oder nen Makro steht ist mir Relativ. Ich find die Makros nur übersichtlicher beim lesen. Beim Überfliegen erkennt man halt sofort was gemacht wird was bei SendMessage meist nicht sooo schnell der Fall ist aber naja das ist geschmackssache.
MfG schirrmie
-
Martin Richter schrieb:
Allerdings kann ich diese Meinung nicht teilen. Diese Art Makros helfen immens beim korrekten Umgang mit den entsprechenden Fensterklassen!
das ist bei mir ein vorurteil wo ich keine lust habe das abzulegen - hast schon recht aber egal #gg
das mit den namen - mein ziel ist ja das man das tree nur mit namen handeln kann, das man spaeter beim benutzen die id oder soetwas nicht kennen braucht
wie ich "AddItem(std::wstring Name, std::wstring Parent)" implementiere sobald ein name mehrmals auftaucht weiss ich noch nicht, denk da schon den ganzen tag drueber nach
-
Mr Evil schrieb:
ps. mit macros arbeite ich nicht, makros doof und boese #gg
Kann ich unterstützen, ABER wenn Du schon keine Makros nutzt (wie das in C++ ja üblich ist), dann nimm doch auch C++ Casts und keine C - Casts
.
-
ja ich weiss, bloede angewohnheit - komme wie so viele aus der c schiene und bin da vorbelastet
bei den casts
reinterpret_cast<>()
dynamic_cast<>()
static_cast<>()und welche es noch gibt {?} blick ich zZt nicht ganz durch welches wann am besten zu gebrauchen ist
-
Ich denke ohne eine Entsprechende Id oder so wirst du nicht weit kommen oder du legst fest das ein Name nur einmal vorkommen darf aber ka was du vor hast und es so gehen kann?
Versteh aber nicht ganz dein Problem mit den Namen. Wenn ein User in nem TreeView später was selektiert oder so da brauchst du doch keine Namen oder so dann hast doch das Item also ich versteh dein Problem nicht wirklich. Was hast du denn mit dem TreeView vor das es Nur über Namen ansprechbar sein soll? Also ich hab bis jetzt immer mit der Maus draufgeklickt oder mit der Tastatur navigiert und nich Probleme gehabt
MfG schirrmie
-
es geht darum das man durch den code auch items hinzufuegen kann ohne das man vorher was selectieren muss oder aehnliches
ich hab mir das nu so gedacht das man bei add noch die id uebergibt und wenn man es nicht weiss kann man holen, mit der bedingung das wenn man die id holt immer das erste vorkommende item benutzt wird - also
BOOL AddItem(std::wstring Name, int ParentId=-1);
.
.
.// add auf root
BOOL ret = m_TreeView.AddItem(_T("First"));
subitem auf "First"
ret = m_TreeView.AddItem(_T("Next"), 1);
wenn man die ID des objektes nicht kennt
ret = m_TreeView.AddItem(_T("Next"), m_TreeView.GetItemId(_T("First")));ob die objekt id und parent id uebergeben wird, oder nur das parent, da muss ich noch ueberlegen wie ich das loes, ich denk mir das ich wahrscheinlich beides uebergeben lass also
BOOL AddItem(std::wstring Name, UINT ItemId, int ParentId=-1);
-
Also ähm, hab mal ne kleine Übersicht gemacht
:[u][b]static_cast<>():[/b][/u] 1. Type << static_cast<Type>(OtherType); // einfacher Typ-Cast 2. Type* << static_cast<Type*>(OtherType*); // nur wenn sicher, sonst dynamic_cast [u][b]reinterpret_cast<>():[/b][/u] 1. Type << static_cast<Type>(OtherType); // aber dann lieber static_cast 2. Type* << static_cast<Type*>(OtherType); // sollte man aber vermeiden [u][b]dynamic_cast<>():[/b][/u] Prüft, ob eine Konvertierung gültig ist. Beispiel: class CBase { public: int GetWas(); /* ... */ }; class CDerived : CBase { public: int GetNochWas(); /* ... */ }; CBase* pbManage = new CDerived(...); int iResult; if(dynamic_cast<CDerived*>(pbManage)) iResult = dynamic_cast<CDerived*>(pbManage)->GetNochWas(); [u][b]const_cast<>():[/b][/u] Damit lassen sich die Schlüsselworte [i]const[/i], oder [i]volatile[/i] (und [i]__unaligned[/i])(weg-)casten. Sowas sollte man aber gründsätzlich vermeiden (bz. nur durchführen wenn es sicher ist)!Hier hast Du nochmal ne genauere Übersicht mit Erklärungen und Beispielen:
Casting Operators
.
-
hei vielen dank, sehr nett {=
-
jetzt hab ich erstmal das problem
HTREEITEM CTreeview::GetItem(UINT id){ TVITEM item; item.mask = TVIF_HANDLE|TVIF_TEXT|TVIF_PARAM; item.lParam = id; ::SendMessage(m_Handle, TVM_GETITEM, NULL, reinterpret_cast<LPARAM>(static_cast<TV_ITEM *>(&item))); return NULL; }wie komme ich an das HTREEITEM wenn ich nur die id (lParam) habe,
-
Ich denke da bleibt dir nichts anderes übrig als alle Items durchzugehen und zu Prüfen ob sie die gesuchte Id hat. Wenn ja hast du ja so gut wie das HTREEITEM.
MfG schirrmie
-
das problem ist - GetItem moechte ein TV_ITEM - ich kann eines erstellen welches ich die id zuweise, dann der aufruf, aber ich erhalte nichts wirklich zurueck
HTREEITEM CTreeview::GetItem(UINT id){ TVITEM item; item.mask = TVIF_HANDLE|TVIF_TEXT|TVIF_PARAM; item.lParam = id; ::SendMessage(m_Handle, TVM_GETITEM, NULL, reinterpret_cast<LPARAM>(static_cast<TV_ITEM *>(&item))); return NULL; }
-
Falsche Anwendung!
hItem mit Item Handle füllen.
pszText mit Zeiger setzen.
Größe nach cchTextMax.
mask auf TVIF_HANDLE|TVIF_TEXT!