I have following structure:
struct Tournaments
{
unsigned int id;
unsigned int itemid;
};
struct Tournaments Tournament;
I assign values to Tournament:
Tournament.id = 1;
Tournament.itemid = 2;
...in the code I insert this structure in my treeview.lParam item:
tvinsert.hParent = hParent;
Before = hParent;
tvinsert.hInsertAfter = TVI_LAST;
tvinsert.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvinsert.item.pszText = szEventName;
tvinsert.item.lParam = (LPARAM) &Tournament;
tvinsert.item.iImage = 9;
tvinsert.item.iSelectedImage = 9;
Parent = (HTREEITEM) SendMessage(g_hwndTreeview, TVM_INSERTITEM, 0, (LPARAM) &tvinsert);
...and in the Notify code I retrieve the item back:
tvi.mask = TVIF_PARAM | TVIF_TEXT;
SendMessage(g_hwndTreeview, TVM_GETITEM, 0, (LPARAM) &tvi);
Assuming tvi holds the structure previously inserted, how can I get hold of
the structure items id & itemid ??
If necessary I can provide the whole code...
You could try something like this:
Tournament* TreeView_GetTournament(HWND hTree, HTREEITEM hItem)
{
TVITEM tv = { 0 };
tv.mask = TVIF_PARAM | TVIF_HANDLE;
tv.hItem = hItem;
if (TreeView_GetItem(hTree, &tv))
{
return (Tournament*)tv.lParam;
}
return NULL;
}
BOOL TreeView_OnNotify(LPNMHDR pnm)
{
HITEM hItem = ((LPNMTREEVIEW)pnm)->itemNew.hItem
Tournament *lpTournament = TreeView_GetTournament(hTree, hItem);
if(NULL != lpTournament)
{
unsigned int id = lpTournament->id;
unsigned int itemid = lpTournament->itemid;
//
//Do calculations etc....
//
}
return FALSE;
}
Thanks,
I will give it a go... I think I even forgot the TVIF_HANDLE in the tvi.mask part.
@DMac or anybody else :-):
I am now able to store items in the treeview and retrieving them.
However when I add a new item (from a listbox) to the treeview and selecting that item by clicking it or leftmouse-clicking returns the wrong address of the tournament pointer.
I traced the insert routine to see if the tournament structure is correctly added to the lParam of the treeview item and that seems correct.
Since all this is a bit difficult to explain in text I have added the source code.
Would you mind having a look at it and maybe tell me what I did wrong ?
You can add an item by right-clicking a tournament and then an contextmenu will popup. (add eventitem)
Check this in line 92static TOURNAMENT tournaments[512][64] = {0};
Perhaps using global variable and dynamically allocated space could be better.
Thanks for the reply!
This is what i did (for the people who are interested) and it works like a charm!
TOURNAMENT * p;
Each time I add an item to the treeview I allocate memory:
p = malloc(sizeof(TOURNAMENT));
p->id = iEventId;
p->item = iEventItem;
...and in the TV_INSERTSTRUCT :
tvis.item.lParam = (LPARAM) p;
after filling the treeview I free the memory.
free(p);
For the edification of any who might read this thread:
When using heap allocated data structures in a treeview be sure to free the pointer only after the data structure is no longer needed. That is when the tree node is deleted or the treeview itself is deleted.
The treeview provides a notification for this very purpose. The TVN_DELETEITEM notification is sent to the treeview's parent control (dialog or main window) via the WM_NOTIFY message.
static BOOL TreeView_FreeItemInfo(HWND hTree, HTREEITEM hItem)
{
TVITEM tv = { 0 };
tv.mask = TVIF_PARAM | TVIF_HANDLE;
tv.hItem = hItem;
if (TreeView_GetItem(hTree, &tv))
{
free((TOURNAMENT *)tv.lParam);
return TRUE;
}
return FALSE;
}
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case TVN_DELETEITEM:
TreeView_FreeItemInfo(((LPNMHDR)lParam)->hwndFrom,
(LPNMTREEVIEW)lParam)->itemOld.hItem);
break;
... // More cases on WM_NOTIFY switch.
break;
}
... // More cases on message switch.
}
return FALSE;
}
Nice one DMac!
I was freeing the memory after creation of the treeview.
I will implement freeing the memory when an item is removed from the treeview, as you suggested.
Thank u.