Solved

ListView LV_ITEM display & ImageList Icons

Posted on 1998-10-28
2
1,116 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
Comment Utility
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
Comment Utility
First class!  Thank you - it worked like a dream.

chrisrobinson
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

771 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now