Dan
Dan

Reputation: 221

C++ ListView hide item

I have created pretty much standard ListView.

    RECT rec;
    GetClientRect(hwnd, &rec);
    ListView = CreateWindow(WC_LISTVIEW, (LPCSTR)L"", (WS_CHILD | WS_VISIBLE | LVS_REPORT), 0, 0, rec.right, rec.bottom-23, hwnd, (HMENU)8553, GetModuleHandle(NULL), NULL);
    SendMessage(ListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); // Set style

Now I insert few columns like that:

    LVCOLUMNW listColumnW = { 0 };
    listColumnW.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
    listColumnW.pszText = L"Column1";
    listColumnW.cx = 150;
    listColumnW.fmt = LVCFMT_LEFT;
    SendMessage(ListView,LVM_INSERTCOLUMNW, 0, (LPARAM)&listColumnW);

after that I instert items and subitems

    LVITEMW lisW = { 0 };
    lisW.mask = LVIF_TEXT | LVIF_PARAM;
    lisW.pszText = item_text[i];
    lisW.iItem = i;
    lisW.lParam = i;
    SendMessage(ListView, LVM_INSERTITEMW, 0, (LPARAM)&lisW);

Now I'd like to implement some kind of search / filtering. I see many people suggest to delete/reinsert items, however as there are quite a number of items in my listview that isn't the best solution. While googling I learned that it should be possible to set groupid and set state of item (hide it). However I'm not sure exactly how to do that, lets say I have 10 items in my listview and I want to hide some items, how exactly do I do that?

EDIT:

I have set LVM_ENABLEGROUPVIEW and created two groups, one is supposed to be shown and other one hidden.

    LVGROUP group = { 0 };
    group.cbSize = sizeof(LVGROUP);
    group.mask = LVGF_GROUPID;
    group.iGroupId = 10;//shown
    ListView_InsertGroup(ListView, -1, &group);
    group.iGroupId = 11;//hidden
    group.mask = LVGF_GROUPID | LVGF_STATE;
    group.stateMask = LVGS_HIDDEN;
    group.state = LVGS_HIDDEN;
    ListView_InsertGroup(ListView, -1, &group);

Now I have added some items to both groups, only problem is I can see them both (they are separated), while the other one is supposed to be hidden.

Upvotes: 2

Views: 2576

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595887

Use LVM_SETITEM to assign a list item to a specific group via the LVITEM::iGroupId member:

LVITEMW lisW = { 0 };
lisW.mask = ... | LVIF_GROUPID;
...
lisW.iItem = ...;
lisW.iGroupId = ...;
SendMessage(ListView, 0, (LPARAM)&lisW);

You can use LVM_INSERTGROUP to insert a hidden group, or use LVM_SETGROUPINFO to hide an existing group, by setting its LVGROUP::state member to LVGS_HIDDEN:

LVGROUP grp = { 0 };
grp.cbSize = sizeof(grp);
grp.mask = LVGF_STATE;
grp.iGroupId = ...;
grp.stateMask = LVGS_HIDDEN | LVGS_NOHEADER | LVGS_COLLAPSED;
grp.state = LVGS_HIDDEN | LVGS_NOHEADER | LVGS_COLLAPSED;

SendMessage(ListView, LVM_INSERTGROUP, -1, (LPARAM)&grp);
or:
SendMessage(ListView, LVM_SETGROUPINFO, grp.iGroupId, (LPARAM)&grp);

Make sure you have enabled groups via LVM_ENABLEGROUPVIEW beforehand:

SendMessage(ListView, LVM_ENABLEGROUPVIEW, TRUE, 0);

That being said, when you have lots of items to display/search/filter in a ListView, you are usually better off using the ListView in virtual mode instead. You can pre-filter your data as needed, then use LVM_SETITEMCOUNT to specify the number of items you want to display, and then handle LVN_GETDISPINFO to retrieve data for specific items when the ListView requests them from you. This way, you can do all of your searching/filtering within your datasource directly (in memory, in a database, etc), then simply invalidate the portions of the ListView that need to be refreshed onscreen using LVM_REDRAWITEMS when you have new data to display. When you have items to add/remove, you simply re-send LVM_SETITEMCOUNT. This is a much faster and flexible way to handle lots of list items.

Using virtual lists

Upvotes: 7

Related Questions