Thread: system imagelist in listview. how?

  1. #1
    Madly in anger with you
    Join Date
    Nov 2005
    Posts
    211

    system imagelist in listview. how?

    EDIT: Ignore "system" in the title, I would not like it to display system icons, but infact the real icons for each file (that is, if the files have custom icons set for them, if they don't and just contain default Windows system icons then those would be displayed).

    well I coded a fully functional listview control (using the API, not MFC), which was my for my recent release of my program.

    anyways, the purpose of the listview control is to contain user supplied file data. it is an LVS_REPORT style listview, and I have a working dynamic popup menu with the options to add and remove files from the list. in version 1, the listview control does not use an imagelist, as in it doesn't display the icons for each file (small ones obviously) to the far left of each file entry.

    what I would like to do in version 2 is add an imagelist that will display the small icon for each added file to the far left of each row.

    I went searching through msdn and found the macros ListView_GetImageList and ListView_SetImageList. they appear to be (partially) what I am looking for, but when I take a look at their parameters, specifically HIMAGELIST, I am left clueless to the internal representation of this type. when I search msdn for HIMAGELIST, I get a bunch of irrelevant results, when really what I am looking for is a description of this type/structure. I know that I can get each added file's icon with SHGetFileInfo every time a new file is added, but I don't know where this icon data would be placed after that, basically what to do between SHGetFileInfo and ListView_SetImageList.

    could anyone here please tell me a little bit about how I could go about this? I am not looking for code, but just some guidance since there doesn't seem to be a whole lot of referances to this available that do not involve MFC (I code C, and strictly C, thus MFC is a no go for me, at least for the moment).

    any input is greatly appreciated. thank you in advance!
    Last edited by Bleech; 12-09-2006 at 03:07 AM.

    Intel Core 2 Quad Q6600 @ 2.40 GHz
    3072 MB PC2-5300 DDR2
    2 x 320 GB SATA (640 GB)
    NVIDIA GeForce 8400GS 256 MB PCI-E

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    You're on the right track. Calling SHGetFileInfo with SHGFI_SYSICONINDEX will cause it to return a handle to the system image list. This can be used with ListView_SetImageList. The index is also returned in the iIcon member and this is used when creating a listview item. Remember to use the LVS_SHAREIMAGELISTS style when creating the list-view.

    There is an example here.

  4. #4
    Madly in anger with you
    Join Date
    Nov 2005
    Posts
    211
    hmm. that does not seem to work. when I try it there is no icon added, there is no image added at all. here is my code for that section (almost identical to that on the blog entry at the link anonytmouse posted):

    Code:
    SHFILEINFO sfi;
    HIMAGELIST himl;
    
    hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
       return FALSE;
    else
       CloseHandle(hFile);
    
    himl = (HIMAGELIST)SHGetFileInfo(szFile, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
    if(!himl)
       return FALSE;
    
    ListView_SetImageList(hwndList, himl, LVSIL_NORMAL);
    
    lvItem.mask = LVIF_TEXT | LVIF_IMAGE;
    lvItem.cchTextMax = MAX_PATH;
    lvItem.iItem = iIndex;
    lvItem.iImage = sfi.iIcon;
    
    lvItem.iSubItem = 0;
    lvItem.pszText = szFile;
    
    ListView_InsertItem(hwndList, &lvItem);
    those first 2 structs are obviously declared with the set of local variables at the beginning of the dialog's callback function, I just added them here to show that nothing was wrong with them and they aren't being used for anything else. excuse the formatting, it got screwed up when I copy and pasted it here. and the listview control is created with the LVS_SHAREIMAGELISTS attribute. iIndex is an int that is incremented everytime an item is successfully added, and decremented every time one is removed (just to keep the items in the same order as they are added, also to keep track of the amount of items in the listview at all times), and szFile is the path to the file (obviously a valid file). the text gets added fine but the icon doesn't.

    could anyone please tell me why this isn't working? thank you in advance.
    Last edited by Bleech; 12-19-2006 at 04:23 AM.

    Intel Core 2 Quad Q6600 @ 2.40 GHz
    3072 MB PC2-5300 DDR2
    2 x 320 GB SATA (640 GB)
    NVIDIA GeForce 8400GS 256 MB PCI-E

  5. #5
    Madly in anger with you
    Join Date
    Nov 2005
    Posts
    211
    heh, after about 6 hours of fiddling with it just now I finally noticed something that didn't look right with my code. my listview control is an LVS_REPORT style listview, thus it uses small lines of text for each item.

    first this line:

    Code:
    ListView_SetImageList(hwndList, himl, LVSIL_NORMAL);
    I realized from some other open source code that there was an LVSIL_SMALL attribute, so I changed that line to:

    Code:
    ListView_SetImageList(hwndList, himl, LVSIL_NORMAL | LVSIL_SMALL);
    this was a major break through for the 6+ hours of unsuccess with trying different manipulations of my code. my listview was now displaying icons, but there was still a problem, they were large icons and looked inappropriate for the LVS_REPORT style listview. so I checked my call to SHGetFileInfo, and realized that I was using SHGFI_LARGEICON. so I changed that to:

    Code:
    himl = (HIMAGELIST)SHGetFileInfo(szFile, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_SMALLICON);
    compiled, and YAYYYYYYYY! it now works exactly how it should, displaying the small icons to the left of each list item.

    Intel Core 2 Quad Q6600 @ 2.40 GHz
    3072 MB PC2-5300 DDR2
    2 x 320 GB SATA (640 GB)
    NVIDIA GeForce 8400GS 256 MB PCI-E

  6. #6
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Good work. A possible issue I noticed is that you open the file with CreateFile with no sharing access before you get the icon. This might create a problem for files where the file must be read to get an icon (eg. exes). I suggest you use at least FILE_SHARE_READ when you open a file.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. File System Implementation
    By dodgeviper in forum C Programming
    Replies: 9
    Last Post: 11-16-2007, 01:04 PM
  2. Using system icons
    By @nthony in forum Windows Programming
    Replies: 1
    Last Post: 01-13-2007, 07:56 PM
  3. Linux database system needed
    By BobS0327 in forum Tech Board
    Replies: 7
    Last Post: 06-11-2006, 03:56 PM
  4. measuring system resources used by a function
    By Aran in forum C Programming
    Replies: 1
    Last Post: 03-13-2006, 05:35 PM
  5. BIOS system and memory allocation problem
    By beely in forum Tech Board
    Replies: 9
    Last Post: 11-25-2003, 07:12 AM