Link to home
Start Free TrialLog in
Avatar of chrisrobinson
chrisrobinson

asked on

ListView LV_ITEM display & ImageList Icons

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
}
ASKER CERTIFIED SOLUTION
Avatar of despote
despote

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of chrisrobinson
chrisrobinson

ASKER

First class!  Thank you - it worked like a dream.

chrisrobinson