Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

ListView LV_ITEM display & ImageList Icons

Posted on 1998-10-28
2
1,154 Views
Last Modified: 2008-03-06
I am writing a Windows Explorer type utility using VC++ 5.0 in Windows 98, to display disk folders & files with FileName, FileSize, ftCreationTime & ftLastWriteTime in LVS_REPORT mode.

I cannot persuade the LV_ITEM to insert the sub-items - I only get the FileName.  

Also, I have succeeded in displaying folder icons for folders, but how do I display the individual file icons?

Here is the View file:

// Lc6View.cpp : implementation of the CLc6View class

#include "stdafx.h"
#include "Lc6.h"
#include "Lc6Doc.h"
#include "Lc6View.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

HICON hIcon;
int firstclick;
/////////////////////////////////////////////////////////////////////////////
// CLc6View

IMPLEMENT_DYNCREATE(CLc6View, CListView)

BEGIN_MESSAGE_MAP(CLc6View, CListView)
      //{{AFX_MSG_MAP(CLc6View)
      ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
      ON_WM_DESTROY()
      //}}AFX_MSG_MAP
      // Standard printing commands
      ON_COMMAND(ID_FILE_PRINT, CListView::OnFilePrint)
      ON_COMMAND(ID_FILE_PRINT_DIRECT, CListView::OnFilePrint)
      ON_COMMAND(ID_FILE_PRINT_PREVIEW, CListView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLc6View construction/destruction

CLc6View::CLc6View()
{
      // TODO: add construction code here

}

CLc6View::~CLc6View()
{
}

BOOL CLc6View::PreCreateWindow(CREATESTRUCT& cs)
{
      // TODO: Modify the Window class or styles here by modifying
      //  the CREATESTRUCT cs

      return CListView::PreCreateWindow(cs);
}

void CLc6View::OnInitialUpdate()
{
      CListView::OnInitialUpdate();

      // TODO: You may populate your ListView with items by directly accessing
      //  its list control through a call to GetListCtrl().

      ModifyStyle(LVS_TYPEMASK, LVS_REPORT);                                                // Report view;

      GetListCtrl().InsertColumn(0, "File Name", LVCFMT_LEFT, 192);            // insert column headers
      GetListCtrl().InsertColumn(1, "Size", LVCFMT_RIGHT, 125);                  //
      GetListCtrl().InsertColumn(2, "Created", LVCFMT_CENTER, 128);            //
      GetListCtrl().InsertColumn(3, "Last Modified", LVCFMT_CENTER, 128);      //

      m_smlImageList.Create(16, 16, ILC_COLOR4, 1, 0);                                          // Create ImageList controls
      hIcon = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_FOLDER));      // add image to ImageList
      GetListCtrl().SetImageList(&m_smlImageList, LVSIL_SMALL);                              // Create ListView control

      FindFile();                                                                                          // find folders & files on disk
}
/////////////////////////////////////////////////////////////////////////////
// CLc6View message handlers

void CLc6View::FindFile()
{
      char szPath[MAX_PATH];                  // Get path to C:\*.* (all files)
      szPath[0] = 'C';                        //
      szPath[1] = ':';                        //
      szPath[2] = '\\';                        //
      szPath[3] = '*';                        //
      szPath[4] = '.';                        //
      szPath[5] = '*';                        //
      szPath[6] = 0;                              //

         WIN32_FIND_DATA fd;                        // Enumerate the files in the directory and add items to the list view

    HANDLE hFind = ::FindFirstFile(szPath, &fd);      // find 1st item
      if(hFind == INVALID_HANDLE_VALUE)
            return;
      else
            AddItem(fd);                                                // add 1st item

      while(::FindNextFile(hFind, &fd))                        // find remaining items
      {
            if(hFind == INVALID_HANDLE_VALUE)
                  return;
            else
                  AddItem(fd);                                          // add remaining items
      }
      ::FindClose (hFind);
}

BOOL CLc6View::AddItem(WIN32_FIND_DATA &fd)
{
      // Allocate an ITEMINFO structure to hold the item's data.
      ITEMINFO* pItem;
      try
      {
            pItem = new ITEMINFO;
      }
      catch(CMemoryException* e)
      {
            e->Delete();
            return FALSE;
      }

      CString s(fd.cFileName);                                                      // cjr - force Sentence case filenames
      s.MakeLower();                                                                        //
      strcpy(fd.cFileName, s);                                                      //
      if((fd.cFileName[0] >= 0x61) && (fd.cFileName[0] <= 0x7a))      // if 1st char: a-z convert to A-Z
            fd.cFileName[0] -= 0x20;                                                //

      // Initialize the ITEMINFO structure's fields.
      pItem->strFileName = fd.cFileName;    
      pItem->dwFileSize = fd.nFileSizeLow;
      pItem->ftCreationTime = fd.ftCreationTime;
      pItem->ftLastWriteTime = fd.ftLastWriteTime;

      // Add an item to the list view control, and set the item's lParam
      // equal to the address of the corresponding ITEMINFO structure.
      LV_ITEM lvi;
      lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
      if((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // folder?
      {                                                                        
            m_smlImageList.Add(hIcon);                              // use folder icon
            lvi.iItem = 0;                                                //
            lvi.iSubItem = 0;                                          //
            lvi.state = 0;                                                //
            lvi.stateMask = 0;                                          //
            lvi.pszText = fd.cFileName;                              // display folder name
            lvi.cchTextMax = 0;                                          //
            lvi.iImage = 0;                                                // controls whether or not icon shows - wanted here
            lvi.lParam = (LPARAM)pItem;                              // this is needed for the sort
      }
      else                                                                  // must be file
      {
//            m_smlImageList.Add(hIcon2);                              // use file icon - not wanted here
            lvi.iItem = 0;                                                //
            lvi.iSubItem = 0;                                          //
            lvi.state = 0;                                                //
            lvi.stateMask = 0;                                          //
            lvi.pszText = fd.cFileName;                              // display filename
            lvi.cchTextMax = 0;                                          //
//            lvi.iImage = 0;                                                // controls whether or not icon shows - not wanted here
            lvi.lParam = (LPARAM)pItem;                              // this is needed for the sort
      }

      if(GetListCtrl().InsertItem(&lvi) == -1)
            return FALSE;
      return TRUE;
}

void CLc6View::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)
{
      // TODO: Add your control notification handler code here
    // When a header button is clicked, call the list view's SortItems
    // function to sort the data in the column. The column number passed
    // in SortItem's second parameter becomes the lParamSort parameter
    // passed to the comparison function.
      NM_LISTVIEW* pNMListView = (NM_LISTVIEW*) pNMHDR;
      if(firstclick == 0)
      {
            firstclick = 1;
      }
      else
            firstclick = 0;
      GetListCtrl().SortItems(CompareFunc, pNMListView->iSubItem);
      *pResult = 0;
}

/////////////////////////////////////////////////////////////////////////////
// Callback function for sorting

int CALLBACK CLc6View::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
      ITEMINFO* pItem1 = (ITEMINFO*) lParam1;
      ITEMINFO* pItem2 = (ITEMINFO*) lParam2;
    int nResult;

    switch (lParamSort)
      { // lParamSort == Column number (0-3)

    case 0: // File name
            if(firstclick == 1)
            {
                  nResult = pItem1->strFileName.CompareNoCase(pItem2->strFileName);
            }
            else
            {
                  nResult = pItem2->strFileName.CompareNoCase(pItem1->strFileName);
            }
        break;

    case 1: // File size
            if(firstclick == 1)
            {
              nResult = pItem1->dwFileSize - pItem2->dwFileSize;
            }
            else
            {
              nResult = pItem2->dwFileSize - pItem1->dwFileSize;
            }
        break;

    case 2: // Date and time created
            if(firstclick == 1)
            {
                  nResult = ::CompareFileTime(&pItem1->ftCreationTime, &pItem2->ftCreationTime);
            }
            else
            {
                  nResult = ::CompareFileTime(&pItem2->ftCreationTime, &pItem1->ftCreationTime);
            }
        break;

    case 3: // Date and time modified
            if(firstclick == 1)
            {
                  nResult = ::CompareFileTime (&pItem1->ftLastWriteTime, &pItem2->ftLastWriteTime);
            }
            else
            {
                  nResult = ::CompareFileTime (&pItem2->ftLastWriteTime, &pItem1->ftLastWriteTime);
            }
        break;
    }
      return nResult;
}

void CLc6View::OnDestroy()
{
      CListView::OnDestroy();
      
      // TODO: Add your message handler code here
      FreeItems();
}

void CLc6View::FreeItems()
{
    // Delete the ITEMINFO structures allocated when the control was created.
    int nCount = GetListCtrl().GetItemCount();
    if (nCount)
      {
        for(int i=0; i<nCount; i++)
            delete(ITEMINFO*)GetListCtrl().GetItemData(i);
    }
}

/////////////////////////////////////////////////////////////////////////////
// CLc6View diagnostics

#ifdef _DEBUG
void CLc6View::AssertValid() const
{
      CListView::AssertValid();
}

void CLc6View::Dump(CDumpContext& dc) const
{
      CListView::Dump(dc);
}

CLc6Doc* CLc6View::GetDocument() // non-debug version is inline
{
      ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CLc6Doc)));
      return (CLc6Doc*)m_pDocument;
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CLc6View drawing

void CLc6View::OnDraw(CDC* pDC)
{
      CLc6Doc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);

      // TODO: add draw code for native data here
}
0
Comment
Question by:chrisrobinson
2 Comments
 

Accepted Solution

by:
despote earned 100 total points
ID: 1176438
CLc6View::CLc6View()
{
//  Get System icon list for all files registred
    SHFILEINFO  sfi;
//  m_ImageList (CImageList) is global to the class
    m_ImageList.Attach((HIMAGELIST)SHGetFileInfo( "C:\\", 0, &sfi, sizeof(SHFILEINFO),SHGFI_SYSICONINDEX | SHGFI_SMALLICON));
}

CLc6View::~CLc6View()
{
//  dont forget to detach imagelist at the end of the program
    m_ImageList.Detach();
}


//  Now to use your iconlist
    SHFILEINFO sfi;
    LV_ITEM    lvi;
    lvi.mask    = LVIF_TEXT|LVIF_IMAGE;
    lvi.iItem      = 0;
//  Get File icon
    SHGetFileInfo( (char*)filename, 0, &sfi,
        sizeof(SHFILEINFO),
        SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
    CString Tx ="test";
    lvi.iSubItem = 0;
    lvi.pszText = (LPSTR)(LPCSTR)Tx;
    lvi.cchTextMax = strlen( lvi.pszText);
    lvi.iImage = sfi.iIcon;
    int row = m_CtrlList.InsertItem(&lvi);
    m_CtrlList.SetItemText(lvi.iItem, 1, Tx);
    m_CtrlList.SetItemText(lvi.iItem, 2, "mytext"));

0
 

Author Comment

by:chrisrobinson
ID: 1176439
First class!  Thank you - it worked like a dream.

chrisrobinson
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

837 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question