0

I've got a treeview listing files that are dropped upon it.

When I make a new treeview item, I'd like to store the address of the file as a string in that item, and retrieve it for various nefarious purposes at a later point in time.

Looking at the TVITEM structure in Microsoft docs, apparently LPARAM is the place to store a value:

lParam

Type: LPARAM

A value to associate with the item.

So, I have gone ahead and done that:

TVITEM tvi;
tvi.mask = TVIF_TEXT;
tvi.pszText = const_cast<char *> (str0.c_str());
tvi.cchTextMax = sizeof(tvi.pszText);
tvi.lParam = (LPARAM) foo;  // SETTING LPARAM HERE, foo IS A const char * 

TVINSERTSTRUCT tvis;
tvis.item = tvi;
tvis.hInsertAfter = 0;
tvis.hParent = hti0;

// Send message to update tree, and return tree item.
return TreeView_InsertItem(tvw_filelist_, &tvis);

Then, when I try to retrieve my value...

HTREEITEM htiSel = TreeView_GetSelection(tvw_filelist_);

TVITEM tvItem;
tvItem.hItem = htiSel;

TreeView_GetItem(tvw_filelist_, &tvItem);
const char * info = (const char *) tvItem.lParam;
MessageBox(NULL, info, "Alert", MB_OK);

...I just get garbage, indicating my pointer went out of scope or is taking a nap or something. The size of that pointer is always 4.

Is this the right way to do what I'm trying to do? If so, what's going on?

Ben
  • 54,723
  • 49
  • 178
  • 224
  • Well, it depends on what foo is. Your code seems a little odd - if foo is a pointer to some text, then you're storing the address of that pointer, as opposed to the address of the data it points to. (the pointer's value) – enhzflep Nov 08 '12 at 08:34
  • Yeah, that was fluctuating around in my various experiments...thanks and sorry. Editing code now. Turns out that wasn't the main problem :) – Ben Nov 08 '12 at 08:35

2 Answers2

2

Of course, take the time to post a question after a long time trying to figure it out, and the answer shows up in seconds.

Turns out the TVITEM mask needs to include TVIF_PARAM, similar to this question.

If I change the above code to:

tvi.mask = TVIF_TEXT | TVIF_PARAM;

it works as expected.

I'm still not sure if this is the recommended use for LPARAM, though.

Community
  • 1
  • 1
Ben
  • 54,723
  • 49
  • 178
  • 224
  • 1
    Yeah, you an use it for anything you like that fits into 32 bits. If it's 4 chars or an int - great, just put em in. If it's anything larger, just store a pointer to the data there. LParam is for anything you please. I've used it in the past to hold structs that represent the material used to render a 3d ball, displayed as the image for each item in the list. This then allows me to use a custom sort function to sort on Hue, Sat or Lum - or of course anything else I like. :) glad you got it sorted. – enhzflep Nov 08 '12 at 08:43
  • I think you should "wrap" you text string into the structure, and store a pointer to it in `LPARAM` - instead of string itself. This can be useful in future then you decide to expand your custom data with some new params. – eraxillan Nov 08 '12 at 08:49
  • @Axilles - you can do that?!!!! Something to try out tomorrow (already 8 hours today, eyes bleeding). – Ben Nov 08 '12 at 08:51
  • @Steve Sure. See my answer below. – eraxillan Nov 08 '12 at 08:55
  • 1
    @enhzflep: *"you [c]an use [`lParam`] for anything you like that fits into 32 bits"* - The `LPARAM` data type is pointer-sized, i.e. 32 bits on a 32-bit system, 64 bits on a 64-bit system. This is an important detail. As written, your comment suggests, that you could store a pointer into *lParam* on 32-bit systems only. – IInspectable Aug 25 '16 at 11:41
  • @IInspectable - thanks for the correction for everyone else's sake. I'd long since forgotten giving that piece of unclear/misleading advice. – enhzflep Aug 26 '16 at 13:02
2
struct CustomTreeData
{
    LPSTR str;   // or even std::string to forget about memory managment
    // TODO: any other data you need
};
...
TVITEM tvi;
tvi.mask = TVIF_TEXT | TVIF_PARAM;

CustomTreeData* myDataPtr = new CustomTreeData;   // the memory should be free later
myDataPtr->str = stringWhatIWant;   // And don't forget to alloc memory for str!
tvi.lParam = (LPARAM) myDataPtr;

I don't check this code, but it should work. Happy coding :)

eraxillan
  • 1,552
  • 1
  • 19
  • 40
  • Sorry to accept my own answer when you were so helpful, but my answer answers the original question :) Thanks though +1 – Ben Nov 11 '12 at 05:30