Question : Using CListView

If anyone has an example of how to use the CListView, could you sent me a sample that will work in VC4 so that I can study it?

Answer : Using CListView

The simplest use of the CListView class is to
display a report style list.  The following
is all the code necessary to implement
your own CListView:

First, the CListView files:

// StatsListView.h : header file
//
//This class manage's DMDS_Pro's Statistics View display.
//
//5\7\1998  Mark Wallace     Added m_cslHeads and m_cslCols
//                           to store the views data in the
//                           case where the view is not
//                           displayed i.e. it doesn't have
//                           a window.  This was done when
//                           it was discovered that when
//                           the app was loaded as an OLE
//                           Automation object it didn't
//                           create a window.  This fact
//                           was discovered while developing
//                           DMDS_StatsViewer.exe, a simple
//                           SDI app used to view the StatsMngr.smd
//                           data file created by the profiler
//                           object.  
/////////////////////////////////////////////////////////////////////////////
// CStatsListView view

#ifndef StatsListViewDefined
#define StatsListViewDefined

#include "listvwex.h"
#include "ReportStyleListControl.h"
#include "StatsMngr.h"

#define MAX_STATS_COLS 2
class CStatsListView : public CListViewEx
{
public:
      CReportStyleListControl *m_pReportLstCtrl ;
      //UINT m_PlaStartIndex ;

      //Column Headers
      CStringList m_cslHeads ;

      //Column data
      CStringList m_cslCols [MAX_STATS_COLS];

      void AddColumn
              (int ColumnNumber,
               int ColumnWidth,
               char ColumnTitle []) ;
      void AddItem
            (int ItemNumber, int SubItemNumber, char Text []) ;


      void CStatsListView::IntlzDisplay () ;
      void UpdateDisplay (CStatsMngr *pStatsMngr) ;

protected:
      CStatsListView();           // protected constructor used by dynamic creation
      DECLARE_DYNCREATE(CStatsListView)

// Attributes
public:

// Operations
public:

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CStatsListView)
      public:
      virtual void OnInitialUpdate();
      protected:
      virtual void OnDraw(CDC* pDC);      // overridden to draw this view
      //}}AFX_VIRTUAL

// Implementation
protected:
      virtual ~CStatsListView();
#ifdef _DEBUG
      virtual void AssertValid() const;
      virtual void Dump(CDumpContext& dc) const;
#endif

      // Generated message map functions
protected:
      afx_msg void OnContextMenu(CWnd*, CPoint point);
      //{{AFX_MSG(CStatsListView)
      afx_msg void OnEditCopy();
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////
#endif

// StatsListView.cpp : implementation file
//

#include "stdafx.h"
#include "MDI_DMDS.h"
#include "StatsListView.h"
#include "resource.h"

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

/////////////////////////////////////////////////////////////////////////////
// CStatsListView

IMPLEMENT_DYNCREATE(CStatsListView, CListViewEx)

CStatsListView::CStatsListView()
{
#ifdef MESSAGE_BOX_TRACE_VIEW
      AfxMessageBox ("::CStatsListView()") ;
#endif

      m_pReportLstCtrl = NULL ;
      //m_PlaStartIndex = 0 ;

      //Initialize display buffers
      IntlzDisplay () ;
}

CStatsListView::~CStatsListView()
{
      if (m_pReportLstCtrl)
      {
            delete m_pReportLstCtrl ;
            m_pReportLstCtrl = NULL ;
      } ;

}
////////////////////////////////////////////////////////
//
void CStatsListView::AddColumn
      (int ColumnNumber,
         int ColumnWidth,
         char ColumnTitle [])
{
      m_cslHeads.AddTail (ColumnTitle) ;

      if (m_pReportLstCtrl)
      {
            m_pReportLstCtrl->AddColumn
                  (ColumnNumber, ColumnWidth, ColumnTitle) ;
      } ;

} ;
////////////////////////////////////////////////////////
//
void CStatsListView::AddItem
      (int ItemNumber, int SubItemNumber, char Text [])
{
      if (SubItemNumber + 1 > MAX_STATS_COLS)
      {
            ASSERT (FALSE) ;
            return ;
      } ;

      CString cst ;
      if (ItemNumber + 1 > m_cslCols[SubItemNumber].GetCount())
      {
            //Fill the list with dummies till we have enough
            //values i.e. fill with blank place holder strings.

            int iCur = m_cslCols[SubItemNumber].GetCount() ;
            while (m_cslCols[SubItemNumber].GetCount() < ItemNumber + 1)
            {
                  m_cslCols[SubItemNumber].AddTail(cst) ;
            } ;
      } ;

      //Now find the position specified by the index passed in
      //and put the data into it.
      POSITION pos = m_cslCols[SubItemNumber].FindIndex (ItemNumber) ;
      m_cslCols[SubItemNumber].SetAt(pos, Text) ;

      if (m_pReportLstCtrl)
      {
            m_pReportLstCtrl->AddItem
                  (ItemNumber, SubItemNumber, Text) ;
      } ;
      
} ;
////////////////////////////////////////////////////////
//
void CStatsListView::IntlzDisplay ()
{
      AddColumn (0, 300, "Statistic") ;
      AddColumn (1, 85, "Value") ;

/*Do the following every time updated:
      //temporary index
      UINT x ;

      x = 0 ;
      AddItem
            (x, 0, "Counters zeroed at") ;
      AddItem
            (x, 1, "0") ;

      x++ ;
      AddItem
            (x, 0, "Number of Messages Processed:") ;


      x++ ;
      AddItem
            (x, 0, "     From Disk") ;
      AddItem
            (x, 1, "0") ;

      x++ ;
      AddItem
            (x, 0, "     From Inbox") ;
      AddItem
            (x, 1, "0") ;

      x++ ;
      AddItem
            (x, 0, "     Reassembled Sectioned Messages") ;
      AddItem
            (x, 1, "0") ;

      x++ ;
      AddItem
            (x, 0, "          Total") ;
      AddItem
            (x, 1, "0") ;


      x++ ;
      AddItem
            (x, 0, "Number of:") ;

      x++ ;
      AddItem
            (x, 0, "     Messages Disseminated") ;
      AddItem
            (x, 1, "0") ;

      x++ ;
      AddItem
            (x, 0, "     Messages Not Disseminated") ;
      AddItem
            (x, 1, "0") ;

      x++ ;
      AddItem
            (x, 0, "     Sections Staged") ;
      AddItem
            (x, 1, "0") ;

      x++ ;
      AddItem
            (x, 0, "          Total") ;
      AddItem
            (x, 1, "0") ;

      x++ ;
      AddItem
            (x, 0, "") ;

      x++ ;
      AddItem
            (x, 0, "Dissemination breakdown by Profile Set Name:") ;

      x++ ;
      AddItem
            (x, 0, "") ;


      //TODO:  List all the recipients and the
      //number of message.  Might want
      //to implement a splitter window with
      //these.
      x++ ;
      m_PlaStartIndex = x ;
*/
} ;



BEGIN_MESSAGE_MAP(CStatsListView, CListViewEx)
      ON_WM_CONTEXTMENU()
      //{{AFX_MSG_MAP(CStatsListView)
      ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CStatsListView drawing

void CStatsListView::OnDraw(CDC* pDC)
{
      CDocument* pDoc = GetDocument();
      // TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CStatsListView diagnostics

#ifdef _DEBUG
void CStatsListView::AssertValid() const
{
      CListViewEx::AssertValid();
}

void CStatsListView::Dump(CDumpContext& dc) const
{
      CListViewEx::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CStatsListView message handlers

void CStatsListView::OnInitialUpdate()
{
#ifdef MESSAGE_BOX_TRACE_VIEW
      AfxMessageBox ("View::OnInitialUpdate()") ;
#endif

      CListViewEx::OnInitialUpdate();
      
      // TODO: Add your specialized code here and/or call the base class
      //Make a an object to manage this display
      //in report style.
      CReportStyleListControl *pListView
            = new CReportStyleListControl
                   ((class CView *)this);
      pListView->InitListControl() ;
      m_pReportLstCtrl = pListView ;
      ASSERT (m_pReportLstCtrl) ;

      //Initialize how the list control looks. i.e.
      //put the appropriate column headers.
      IntlzDisplay () ;
      
}
/////////////////////////////////////////////////////////////
//
void CStatsListView::UpdateDisplay
      (CStatsMngr *pStatsMngr)
{
      ASSERT (pStatsMngr) ;
      if (!pStatsMngr) return ;

      //Read the current stats for display.
      CStatsMngrData csd ;
      pStatsMngr->GetCurrentStats (&csd) ;

      UINT uiTotalFromInputPaths = 0 ;
      CString csTmp ;
      UINT x ;

      x = 0 ;
      AddItem
            (x, 0, "Counters zeroed at") ;
      csTmp = csd.m_Time.Format ("%j %H:%M:%S") ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      AddItem
            (x, 0, "Number of Messages Processed:") ;

      POSITION InCountPos
            = csd.m_cslInputPathCounts.GetHeadPosition() ;
      POSITION InPos = csd.m_InputPaths.GetHeadPosition() ;
      while (InPos)
      {
            x++ ;
            csTmp.Format ("     From %s",
                  csd.m_InputPaths.GetNext(InPos)->m_csPath) ;
            AddItem
                  (x, 0, csTmp.GetBuffer(0)) ;

            CString csInCount
                  = csd.m_cslInputPathCounts.GetNext (InCountPos) ;
            AddItem
                  (x,
                   1,
                   csInCount.GetBuffer(0)) ;

            //Update the count for the total
            uiTotalFromInputPaths += atoi (csInCount) ;      
      } ;
      
      x++ ;
      AddItem
            (x, 0, "     Reassembled Sectioned Messages") ;
      csTmp.Format("%d", csd.m_ulNumFromReassembledSections) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      AddItem
            (x, 0, "          Total") ;
      csTmp.Format
            ("%d",
                 uiTotalFromInputPaths
              +  csd.m_ulNumFromReassembledSections) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;


      x++ ;
      AddItem
            (x, 0, "Number of:") ;

      x++ ;
      AddItem
            (x, 0, "     Messages Disseminated") ;
      csTmp.Format ("%d", csd.m_ulNumRouted) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      AddItem
            (x, 0, "     Messages Not Disseminated") ;
      csTmp.Format ("%d", csd.m_ulNumNotRouted) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      AddItem
            (x, 0, "     Sections Staged") ;
      csTmp.Format ("%d", csd.m_ulNumSectionsStaged) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      AddItem
            (x, 0, "          Total") ;
      csTmp.Format
            ("%d",
                csd.m_ulNumRouted
              + csd.m_ulNumNotRouted
              + csd.m_ulNumSectionsStaged) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      AddItem
            (x, 0, "") ;

      x++ ;
      AddItem
            (x, 0, "Dissemination breakdown by Profile Set Name:") ;

      x++ ;
      AddItem
            (x, 0, "") ;

      x++ ;

      CString csName ;
      CString csCount ;
      UINT uIndex ;
      POSITION CountPos ;
      POSITION pos ;

      //Update the individual PLA\Recipient breakdown
      //display.

      uIndex = 0 ;
      CStringList *pcslReceiverCounts = &csd.m_cslReceiverCounts ;
      CStringList *pcslReceiverNames = &csd.m_cslReceiverNames ;
      ASSERT (pcslReceiverNames) ;
      pos = pcslReceiverNames->GetHeadPosition() ;
      while (pos)
      {
            csName = pcslReceiverNames->GetNext (pos) ;

            //Get the string representing the count
            //in the adjoining list.
            CountPos = pcslReceiverCounts->FindIndex (uIndex) ;
            csCount = pcslReceiverCounts->GetAt (CountPos) ;

            //Add this to the display
            AddItem
                  (x + uIndex, 0, csName.GetBuffer(0)) ;
            AddItem
                  (x + uIndex, 1, csCount.GetBuffer(0)) ;

            uIndex++ ;
      } ;

/*
      CString csTmp ;
      UINT x ;

      //Update the system startup time
      x = 0 ;
      csTmp = csd.m_Time.Format ("%j %H:%M:%S") ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      //Update the all around stats.
      x += 2 ;
      csTmp.Format("%d", csd.m_ulNumFromDisk) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      csTmp.Format("%d", csd.m_ulNumFromInbox) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      csTmp.Format("%d", csd.m_ulNumFromReassembledSections) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      csTmp.Format
            ("%d",
                 csd.m_ulNumFromDisk
              +  csd.m_ulNumFromInbox
              +  csd.m_ulNumFromReassembledSections) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x += 2 ;
      csTmp.Format ("%d", csd.m_ulNumRouted) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      csTmp.Format ("%d", csd.m_ulNumNotRouted) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      csTmp.Format ("%d", csd.m_ulNumSectionsStaged) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      x++ ;
      csTmp.Format
            ("%d",
                csd.m_ulNumRouted
              + csd.m_ulNumNotRouted
              + csd.m_ulNumSectionsStaged) ;
      AddItem
            (x, 1, csTmp.GetBuffer(0)) ;

      CString csName ;
      CString csCount ;
      UINT uIndex ;
      POSITION CountPos ;
      POSITION pos ;

      //Update the individual PLA\Recipient breakdown
      //display.

      uIndex = 0 ;
      CStringList *pcslReceiverCounts = &csd.m_cslReceiverCounts ;
      CStringList *pcslReceiverNames = &csd.m_cslReceiverNames ;
      ASSERT (pcslReceiverNames) ;
      pos = pcslReceiverNames->GetHeadPosition() ;
      while (pos)
      {
            csName = pcslReceiverNames->GetNext (pos) ;

            //Get the string representing the count
            //in the adjoining list.
            CountPos = pcslReceiverCounts->FindIndex (uIndex) ;
            csCount = pcslReceiverCounts->GetAt (CountPos) ;

            //Add this to the display
            AddItem
                  (m_PlaStartIndex + uIndex, 0, csName.GetBuffer(0)) ;
            AddItem
                  (m_PlaStartIndex + uIndex, 1, csCount.GetBuffer(0)) ;

            uIndex++ ;
      } ;
*/
} ;

void CStatsListView::OnContextMenu(CWnd*, CPoint point)
{

      // CG: This block was added by the Pop-up Menu component
      {
            if (point.x == -1 && point.y == -1){
                  //keystroke invocation
                  CRect rect;
                  GetClientRect(rect);
                  ClientToScreen(rect);

                  point = rect.TopLeft();
                  point.Offset(5, 5);
            }

            CMenu menu;
            VERIFY(menu.LoadMenu(CG_IDR_POPUP_LOG_VIEW));

            CMenu* pPopup = menu.GetSubMenu(0);
            //ASSERT(pPopup != NULL);
            if (!pPopup) return ;

            CWnd* pWndPopupOwner = this;

            while (pWndPopupOwner->GetStyle() & WS_CHILD)
                  pWndPopupOwner = pWndPopupOwner->GetParent();

            pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
                  pWndPopupOwner);
      }
}

void CStatsListView::OnEditCopy()
{
      if (!m_pReportLstCtrl) return ;

      //Copy all selected list control items to the
      //Clip board.
      m_pReportLstCtrl->CopyAllSelectedToClip () ;
      
}

////END StatsListView.cpp


// ListVwEx.h : interface of the CListViewEx class
//
// This class provedes a full row selection mode for the report
// mode list view control.
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#ifndef CListViewExDefined
#define CListViewExDefined

class CListViewEx : public CListView
{
      DECLARE_DYNCREATE(CListViewEx)

// Construction
public:
      //Set this to change the text color of certain specified
      //words.
      BOOL m_bHighLightFlagWords ;
      CListViewEx();

// Attributes
protected:
      BOOL m_bFullRowSel;

public:
      BOOL SetFullRowSel(BOOL bFillRowSel);
      BOOL GetFullRowSel();

      BOOL m_bClientWidthSel;

// Overrides
protected:
      virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CListViewEx)
      public:
      virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
      protected:
      //}}AFX_VIRTUAL

// Implementation
public:
      virtual ~CListViewEx();
#ifdef _DEBUG
      virtual void Dump(CDumpContext& dc) const;
#endif

protected:
      static LPCTSTR MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset);
      void RepaintSelectedItems();

// Implementation - client area width
      int m_cxClient;

// Implementation - state icon width
      int m_cxStateImageOffset;
      afx_msg LRESULT OnSetImageList(WPARAM wParam, LPARAM lParam);

// Implementation - list view colors
      COLORREF m_clrText;
      COLORREF m_clrTextBk;
      COLORREF m_clrBkgnd;
      afx_msg LRESULT OnSetTextColor(WPARAM wParam, LPARAM lParam);
      afx_msg LRESULT OnSetTextBkColor(WPARAM wParam, LPARAM lParam);
      afx_msg LRESULT OnSetBkColor(WPARAM wParam, LPARAM lParam);

// Generated message map functions
protected:
      //{{AFX_MSG(CListViewEx)
      afx_msg void OnSize(UINT nType, int cx, int cy);
      afx_msg void OnPaint();
      afx_msg void OnSetFocus(CWnd* pOldWnd);
      afx_msg void OnKillFocus(CWnd* pNewWnd);
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};
#endif

/////////////////////////////////////////////////////////////////////////////


// ListVwEx.cpp : implementation of the CListViewEx class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "ListVwEx.h"

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

/////////////////////////////////////////////////////////////////////////////
// CListViewEx

IMPLEMENT_DYNCREATE(CListViewEx, CListView)

BEGIN_MESSAGE_MAP(CListViewEx, CListView)
      //{{AFX_MSG_MAP(CListViewEx)
      ON_WM_SIZE()
      ON_WM_PAINT()
      ON_WM_SETFOCUS()
      ON_WM_KILLFOCUS()
      //}}AFX_MSG_MAP
      ON_MESSAGE(LVM_SETIMAGELIST, OnSetImageList)
      ON_MESSAGE(LVM_SETTEXTCOLOR, OnSetTextColor)
      ON_MESSAGE(LVM_SETTEXTBKCOLOR, OnSetTextBkColor)
      ON_MESSAGE(LVM_SETBKCOLOR, OnSetBkColor)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CListViewEx construction/destruction

CListViewEx::CListViewEx()
{
      m_bHighLightFlagWords = FALSE ;
      m_bFullRowSel = FALSE;
      m_bClientWidthSel = TRUE;

      m_cxClient = 0;
      m_cxStateImageOffset = 0;

      m_clrText = ::GetSysColor(COLOR_WINDOWTEXT);
      m_clrTextBk = ::GetSysColor(COLOR_WINDOW);
      m_clrBkgnd = ::GetSysColor(COLOR_WINDOW);
}

CListViewEx::~CListViewEx()
{
}

BOOL CListViewEx::PreCreateWindow(CREATESTRUCT& cs)
{
      // default is report view and full row selection
      cs.style &= ~LVS_TYPEMASK;
      cs.style |= LVS_REPORT | LVS_OWNERDRAWFIXED;
      m_bFullRowSel = TRUE;

      return(CListView::PreCreateWindow(cs));
}

BOOL CListViewEx::SetFullRowSel(BOOL bFullRowSel)
{
      // no painting during change
      LockWindowUpdate();

      m_bFullRowSel = bFullRowSel;

      BOOL bRet;

      if (m_bFullRowSel)
            bRet = ModifyStyle(0L, LVS_OWNERDRAWFIXED);
      else
            bRet = ModifyStyle(LVS_OWNERDRAWFIXED, 0L);

      // repaint window if we are not changing view type
      if (bRet && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
            Invalidate();

      // repaint changes
      UnlockWindowUpdate();

      return(bRet);
}

BOOL CListViewEx::GetFullRowSel()
{
      return(m_bFullRowSel);
}

/////////////////////////////////////////////////////////////////////////////
// CListViewEx drawing

const COLORREF RED = RGB(255,0,0);   //red
const COLORREF BLUE = RGB(0,0,255);  //blue
const COLORREF GREEN = RGB(0,255,0); //green

// offsets for first and other columns
#define OFFSET_FIRST      2
#define OFFSET_OTHER      6

void CListViewEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
      CListCtrl& ListCtrl=GetListCtrl();
      CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
      CRect rcItem(lpDrawItemStruct->rcItem);
      UINT uiFlags = ILD_TRANSPARENT;
      CImageList* pImageList;
      int nItem = lpDrawItemStruct->itemID;
      BOOL bFocus = (GetFocus() == this);
      COLORREF clrTextSave, clrBkSave;
      COLORREF clrImage = m_clrBkgnd;
      static _TCHAR szBuff[MAX_PATH];
      LPCTSTR pszText;

// get item data

      LV_ITEM lvi;
      lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
      lvi.iItem = nItem;
      lvi.iSubItem = 0;
      lvi.pszText = szBuff;
      lvi.cchTextMax = sizeof(szBuff);
      lvi.stateMask = 0xFFFF;            // get all state flags
      ListCtrl.GetItem(&lvi);

      BOOL bSelected = (bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED;
      bSelected = bSelected || (lvi.state & LVIS_DROPHILITED);

// set colors if item is selected

      CRect rcAllLabels;
      ListCtrl.GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS);

      CRect rcLabel;
      ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL);

      rcAllLabels.left = rcLabel.left;
      if (m_bClientWidthSel && rcAllLabels.rightnt)
            rcAllLabels.right = m_cxClient;

      if (bSelected)
      {
            clrTextSave = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
            clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));

            pDC->FillRect(rcAllLabels, &CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
      }
      else
            pDC->FillRect(rcAllLabels, &CBrush(m_clrTextBk));

// set color and mask for the icon

      if (lvi.state & LVIS_CUT)
      {
            clrImage = m_clrBkgnd;
            uiFlags |= ILD_BLEND50;
      }
      else if (bSelected)
      {
            clrImage = ::GetSysColor(COLOR_HIGHLIGHT);
            uiFlags |= ILD_BLEND50;
      }

// draw state icon

      UINT nStateImageMask = lvi.state & LVIS_STATEIMAGEMASK;
      if (nStateImageMask)
      {
            int nImage = (nStateImageMask>>12) - 1;
            pImageList = ListCtrl.GetImageList(LVSIL_STATE);
            if (pImageList)
            {
                  pImageList->Draw(pDC, nImage,
                        CPoint(rcItem.left, rcItem.top), ILD_TRANSPARENT);
            }
      }

// draw normal and overlay icon

      CRect rcIcon;
      ListCtrl.GetItemRect(nItem, rcIcon, LVIR_ICON);

      pImageList = ListCtrl.GetImageList(LVSIL_SMALL);
      if (pImageList)
      {
            UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK;
            if (rcItem.left1)
            {
                  ImageList_DrawEx(pImageList->m_hImageList, lvi.iImage,
                              pDC->m_hDC,rcIcon.left,rcIcon.top, 16, 16,
                              m_clrBkgnd, clrImage, uiFlags | nOvlImageMask);
            }
      }

// draw item label

      ListCtrl.GetItemRect(nItem, rcItem, LVIR_LABEL);
      rcItem.right -= m_cxStateImageOffset;

      pszText = MakeShortString(pDC, szBuff,
                        rcItem.right-rcItem.left, 2*OFFSET_FIRST);

      rcLabel = rcItem;
      rcLabel.left += OFFSET_FIRST;
      rcLabel.right -= OFFSET_FIRST;

      pDC->DrawText(pszText,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);

// draw labels for extra columns

      LV_COLUMN lvc;
      lvc.mask = LVCF_FMT | LVCF_WIDTH;
                           
      for(int nColumn = 1; ListCtrl.GetColumn(nColumn, &lvc); nColumn++)
      {
            rcItem.left = rcItem.right;
            rcItem.right += lvc.cx;

            int nRetLen = ListCtrl.GetItemText(nItem, nColumn,
                                    szBuff, sizeof(szBuff));
            if (nRetLen == 0)
                  continue;

            pszText = MakeShortString(pDC, szBuff,
                  rcItem.right - rcItem.left, 2*OFFSET_OTHER);

            UINT nJustify = DT_LEFT;

            if(pszText == szBuff)
            {
                  switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
                  {
                  case LVCFMT_RIGHT:
                        nJustify = DT_RIGHT;
                        break;
                  case LVCFMT_CENTER:
                        nJustify = DT_CENTER;
                        break;
                  default:
                        break;
                  }
            }

            rcLabel = rcItem;
            rcLabel.left += OFFSET_OTHER;
            rcLabel.right -= OFFSET_OTHER;

            COLORREF HoldColor = pDC->GetTextColor() ;
            if (m_bHighLightFlagWords)
            {
                  //See if this field contains text we
                  //should highlight.
                  CString csTmp = pszText ;
                  csTmp.TrimRight (" ") ;
                  if (csTmp=="ERR")
                  {
                        pDC->SetTextColor (RED) ;
                  }
                  else
                  if (csTmp=="ACC")
                  {
                        pDC->SetTextColor (GREEN) ;
                  }
                  else
                  if (csTmp=="ACT")
                  {
                        pDC->SetTextColor (BLUE) ;
                  } ;

            } ;

            pDC->DrawText(pszText, -1, rcLabel,
                  nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);

            //Put original color back.
            pDC->SetTextColor (HoldColor) ;

      }

// draw focus rectangle if item has focus

      if (lvi.state & LVIS_FOCUSED && bFocus)
            pDC->DrawFocusRect(rcAllLabels);

// set original colors if item was selected

      if (m_bHighLightFlagWords)
      {
      } ;

      if (bSelected)
      {
        pDC->SetTextColor(clrTextSave);
            pDC->SetBkColor(clrBkSave);
      }
}

LPCTSTR CListViewEx::MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset)
{
      static const _TCHAR szThreeDots[] = _T("...");

      int nStringLen = lstrlen(lpszLong);

      if(nStringLen == 0 ||
            (pDC->GetTextExtent(lpszLong, nStringLen).cx + nOffset) <= nColumnLen)
      {
            return(lpszLong);
      }

      static _TCHAR szShort[MAX_PATH];

      lstrcpy(szShort,lpszLong);
      int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;

      for(int i = nStringLen-1; i > 0; i--)
      {
            szShort[i] = 0;
            if((pDC->GetTextExtent(szShort, i).cx + nOffset + nAddLen)
                  <= nColumnLen)
            {
                  break;
            }
      }

      lstrcat(szShort, szThreeDots);
      return(szShort);
}

void CListViewEx::RepaintSelectedItems()
{
      CListCtrl& ListCtrl = GetListCtrl();
      CRect rcItem, rcLabel;

// invalidate focused item so it can repaint properly

      int nItem = ListCtrl.GetNextItem(-1, LVNI_FOCUSED);

      if(nItem != -1)
      {
            ListCtrl.GetItemRect(nItem, rcItem, LVIR_BOUNDS);
            ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL);
            rcItem.left = rcLabel.left;

            InvalidateRect(rcItem, FALSE);
      }

// if selected items should not be preserved, invalidate them

      if(!(GetStyle() & LVS_SHOWSELALWAYS))
      {
            for(nItem = ListCtrl.GetNextItem(-1, LVNI_SELECTED);
                  nItem != -1; nItem = ListCtrl.GetNextItem(nItem, LVNI_SELECTED))
            {
                  ListCtrl.GetItemRect(nItem, rcItem, LVIR_BOUNDS);
                  ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL);
                  rcItem.left = rcLabel.left;

                  InvalidateRect(rcItem, FALSE);
            }
      }

// update changes

      UpdateWindow();
}

/////////////////////////////////////////////////////////////////////////////
// CListViewEx diagnostics

#ifdef _DEBUG

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

      dc << "m_bFullRowSel = " << (UINT)m_bFullRowSel;
      dc << "\n";
      dc << "m_cxStateImageOffset = " << m_cxStateImageOffset;
      dc << "\n";
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CListViewEx message handlers

LRESULT CListViewEx::OnSetImageList(WPARAM wParam, LPARAM lParam)
{
      if( (int) wParam == LVSIL_STATE)
      {
            int cx, cy;

            if(::ImageList_GetIconSize((HIMAGELIST)lParam, &cx, &cy))
                  m_cxStateImageOffset = cx;
            else
                  m_cxStateImageOffset = 0;
      }

      return(Default());
}

LRESULT CListViewEx::OnSetTextColor(WPARAM wParam, LPARAM lParam)
{
      m_clrText = (COLORREF)lParam;
      return(Default());
}

LRESULT CListViewEx::OnSetTextBkColor(WPARAM wParam, LPARAM lParam)
{
      m_clrTextBk = (COLORREF)lParam;
      return(Default());
}

LRESULT CListViewEx::OnSetBkColor(WPARAM wParam, LPARAM lParam)
{
      m_clrBkgnd = (COLORREF)lParam;
      return(Default());
}

void CListViewEx::OnSize(UINT nType, int cx, int cy)
{
      m_cxClient = cx;
      CListView::OnSize(nType, cx, cy);
}

void CListViewEx::OnPaint()
{
      // in full row select mode, we need to extend the clipping region
      // so we can paint a selection all the way to the right
      if (m_bClientWidthSel &&
            (GetStyle() & LVS_TYPEMASK) == LVS_REPORT &&
            GetFullRowSel())
      {
            CRect rcAllLabels;
            GetListCtrl().GetItemRect(0, rcAllLabels, LVIR_BOUNDS);

            if(rcAllLabels.right < m_cxClient)
            {
                  // need to call BeginPaint (in CPaintDC c-tor)
                  // to get correct clipping rect
                  CPaintDC dc(this);

                  CRect rcClip;
                  dc.GetClipBox(rcClip);

                  rcClip.left = min(rcAllLabels.right-1, rcClip.left);
                  rcClip.right = m_cxClient;

                  InvalidateRect(rcClip, FALSE);
                  // EndPaint will be called in CPaintDC d-tor
            }
      }

      CListView::OnPaint();
}

void CListViewEx::OnSetFocus(CWnd* pOldWnd)
{
      CListView::OnSetFocus(pOldWnd);

      // check if we are getting focus from label edit box
      if(pOldWnd!=NULL && pOldWnd->GetParent()==this)
            return;

      // repaint items that should change appearance
      if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
            RepaintSelectedItems();
}

void CListViewEx::OnKillFocus(CWnd* pNewWnd)
{
      CListView::OnKillFocus(pNewWnd);

      // check if we are losing focus to label edit box
      if(pNewWnd != NULL && pNewWnd->GetParent() == this)
            return;

      // repaint items that should change appearance
      if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
            RepaintSelectedItems();
}


//ReportStyleListControl.h
//
//Object to wrap managing a List Control
//resource on a dialog surface.
//
//Example using:
//
//
/*
      //Make a list control object
      CReportStyleListControl *l ;
      l = new CReportStyleListControl (IDC_LIST3, this) ;
      m_ListCtrl = (void *)l ;
      l->InitListControl() ;

      //Set the columns we want
      l->AddColumn (0, 100, "Sender") ;
      l->AddColumn (1, 100, "Subject") ;

      //Add some items to the columns

    //item 1
      l->AddItem (0, 0, "Test Sender 1") ;
      l->AddItem (0, 1, "Test Subject 1") ;

    //item 2
      l->AddItem (1, 0, "Test Sender 2") ;
      l->AddItem (1, 1, "Test Subject 2") ;

    //item 3, etc....
      l->AddItem (2, 0, "Test Sender 3") ;
      l->AddItem (2, 1, "Test Subject 3") ;

*/

#ifndef CReportStyleListControlDefined
#define CReportStyleListControlDefined

#include "afxcoll.h"

#define MAXLOGS 1000

class CReportStyleListControl
{
public:
      //constructor, needs a pointer to
      //the main CListView.
      CReportStyleListControl
                  (CView *ViewPtr,
                   int CtrlId = 0) ;
      CReportStyleListControl (CListCtrl *pListCtrl) ;

      CListCtrl *pGetListCtrl () ;

      //Find the zero based index of the first
      //matching log line.
      int FindNext (CString SearchStr, DWORD Flags) ;


      //Rebuild the contents of the list control based
      //on the filter
      bRebuildListControlFromFilter
               ( CString csFilter,
                   DWORD dFlags ) ;

      void InitListControl () ;

      //Call this once for each column of the
      //list control.
      void AddColumn
              (int ColumnNumber,
               int ColumnWidth,
               char ColumnTitle []) ;

      void RemoveItem (int ItemNumber) ;
      void AddItem (int ItemNumber, int SubItemNumber, char Text []) ;

      BOOL DeleteItem( int nItem );


      BOOL DeleteAllItems();

      BOOL EnsureVisible( int nItem, BOOL bPartialOK );

      void GetSelectedItemList
            (CUIntArray &uiaSelectedIndices) ;
      int GetSelectedItem () ;
      int SetSelectedItem (int index) ;

      //Routine to retrieve a specified item and subitem.
      BOOL bGetItemStrVal
              ( int iItem,
                  int iSubItem,
                  CString &csItemStrVal ) ;

      BOOL bGetAllItemStrVal
      ( int iItem,
            CString &csItemStrVal ) ;

      void CopyAllSelectedToClip () ;

private:
      CListCtrl *m_pProvidedListCtrl ;
      int m_ListCtrlId ;
      CView *m_View ;
      int m_NumSubItems ;

      CListCtrl *m_ListCtrl ;
      

      void SetViewState () ;

      BOOL bStrMatches
              (CString StrChecking,
               CString SearchStr,
               ULONG Flags ) ;

      BOOL bItemMatches
              ( int iIndex,
                  CString csSearchStr,
                  DWORD dFlags ) ;

      
} ;


#endif


//ReportStyleListControl.cpp

#include "stdafx.h"
#include "AfxCView.h"
#include "ReportStyleListControl.h"
#include "Filter.h"


////////////////////////////////////////////////
//constructor for the list control logger.
//
//Construct with a control id of a list control
//and a pointer to the view were its at.
//
CReportStyleListControl::CReportStyleListControl
                                          (CView *ViewPtr, int CtrlId )
{
      m_ListCtrlId = CtrlId;
      m_View = ViewPtr;
      m_NumSubItems = 0 ;
      m_pProvidedListCtrl = NULL ;
      InitListControl() ;
} ;
///////////////////////////////////////////////////
//Construct with a list control object.
//
CReportStyleListControl::CReportStyleListControl
      (CListCtrl *pListCtrl)
{
      m_ListCtrlId = 0;
      m_View = NULL;
      m_NumSubItems = 0 ;
      m_pProvidedListCtrl = pListCtrl ;
      InitListControl() ;
} ;
///////////////////////////////////////////////////
//
CListCtrl *CReportStyleListControl::pGetListCtrl ()
{
      if (m_pProvidedListCtrl) return m_pProvidedListCtrl ;

      ASSERT (m_View) ;
      if (!m_View) return NULL;

      if (m_ListCtrlId)
      {
            return (CListCtrl *)m_View->GetDlgItem (m_ListCtrlId) ;
      }
      else
      {
            //Assume we are operating on a list control view.
            CListView *pLstView = (CListView *)m_View;
            CListCtrl *pLstCtrl ;
            CListCtrl &LstCtrl = pLstView->GetListCtrl() ;
            pLstCtrl = &LstCtrl ;
            return pLstCtrl ;
      } ;

      return NULL ;
} ;
//////////////////////////////////////////////////
//
BOOL CReportStyleListControl::DeleteAllItems()
{
      m_ListCtrl = pGetListCtrl () ;
      return m_ListCtrl->DeleteAllItems() ;
} ;
//////////////////////////////////////////////////
//
BOOL CReportStyleListControl::DeleteItem( int nItem )
{
      m_ListCtrl = pGetListCtrl () ;
      return m_ListCtrl->DeleteItem (nItem) ;
} ;
//////////////////////////////////////////////////
//
BOOL CReportStyleListControl::EnsureVisible( int nItem, BOOL bPartialOK )
{
      m_ListCtrl = pGetListCtrl () ;

      return m_ListCtrl->EnsureVisible(nItem, bPartialOK) ;
} ;
//////////////////////////////////////////////////
//Set View state.  Specifically, make sure
//the list control is in the LVS_REPORT state.
//
//
void CReportStyleListControl::SetViewState ()
{
      m_ListCtrl = pGetListCtrl () ;

      //Ensure that the view has the LVS_REPORT
      //bit on.

      // SetView - sets a list view's window style to change the view.  
      // hwndLV - handle of the list view control
      // dwView - value specifying a view style

    // Get the current window style.
    DWORD dwStyle
       = GetWindowLong
          (*m_ListCtrl,
           GWL_STYLE);
 
    // Only set the window style if the view bits have changed.
    if ((dwStyle & LVS_TYPEMASK) != LVS_REPORT)
        SetWindowLong(*m_ListCtrl, GWL_STYLE,
            (dwStyle & ~LVS_TYPEMASK) | LVS_REPORT);

} ;
//////////////////////////////////////////////////
//Add a column.
void CReportStyleListControl::AddColumn
      (int ColumnNumber,
         int ColumnWidth,
         char ColumnTitle [])
{

      m_ListCtrl = pGetListCtrl () ;

    LV_COLUMN lvc;

    // Initialize the LV_COLUMN structure.
    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
    lvc.fmt = LVCFMT_LEFT;
    lvc.cx = ColumnWidth ;

      //Set the title/caption of the column
    lvc.pszText = ColumnTitle;
 
      //Make 1 column
      lvc.iSubItem = ColumnNumber ;

    m_ListCtrl->InsertColumn (ColumnNumber, &lvc) ;

} ;
//////////////////////////////////////////////////
//Initialize List control.
//
//This routine is used to initialize the
//columns to be used by our list control.
//
void CReportStyleListControl::InitListControl ()
{
      m_ListCtrl = pGetListCtrl () ;

      //Make sure the list control is in
      //the LVS_REPORT state.
      SetViewState () ;

} ;
//////////////////////////////////////////////////
//Fill a provided integer array with all the
//selected indices.
//
void CReportStyleListControl::GetSelectedItemList
      (CUIntArray &uiaSelectedIndices)
{
      uiaSelectedIndices.RemoveAll() ;
      m_ListCtrl = pGetListCtrl () ;

      int NumItems = m_ListCtrl->GetItemCount() ;
      int x ;
      UINT state ;

      for (x=0; x      {
            //See if the item is selected
            state = m_ListCtrl->GetItemState (x, LVIS_SELECTED) ;

            if ((state & LVIS_SELECTED) != 0)
            {
                  uiaSelectedIndices.Add (x) ;
            } ;
      } ;
      return;
} ;
//////////////////////////////////////////////////
//return the 0 based index of the first
//selected item.
//
//return -1 if none selected.
//
int CReportStyleListControl::GetSelectedItem ()
{

      m_ListCtrl = pGetListCtrl () ;

      int NumItems = m_ListCtrl->GetItemCount() ;
      int x ;
      UINT state ;

      for (x=0; x      {
            //See if the item is selected
            state = m_ListCtrl->GetItemState (x, LVIS_SELECTED) ;

            if ((state & LVIS_SELECTED) != 0)
            {
                  return x ;
            } ;
      } ;

      return -1 ;
} ;
//////////////////////////////////////////////////
//Select the specified list control item.
//
int CReportStyleListControl::SetSelectedItem (int index)
{
      m_ListCtrl = pGetListCtrl () ;

      int CurrentSelected = GetSelectedItem() ;

      int NumItems = m_ListCtrl->GetItemCount() ;

      //BOOL GetItem( LV_ITEM* pItem ) const;

      if (CurrentSelected >= 0)
      {
            //BOOL SetItemState( int nItem, UINT nState, UINT nMask );
            m_ListCtrl->SetItemState
                  (CurrentSelected,
                   (UINT)~LVIS_SELECTED,
                   (UINT)LVIS_SELECTED) ;

      } ;

      //Set the item specified as being selected
      BOOL result ;
/*
      result = m_ListCtrl->SetItemState
            (index,
             (UINT)LVIS_SELECTED,
             (UINT)LVIS_SELECTED) ;
*/

      LV_ITEM i ;
      i.mask = LVIF_STATE ;
      i.iItem = index ;
      i.iSubItem = 0 ;
      i.state = LVIS_SELECTED ;
      i.stateMask = LVIS_SELECTED ;
      i.pszText = NULL ;
      i.cchTextMax = 0 ;
      i.iImage = NULL ;
      i.lParam = 0 ;
      result = m_ListCtrl->SetItem (&i) ;

/*You can't make a subitem highlighted!!!! I guess???
      i.mask = LVIF_STATE ;
      i.iItem = index ;
      i.iSubItem = 1 ;
      i.state = LVIS_SELECTED ;
      i.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
      i.pszText = NULL ;
      i.cchTextMax = 0 ;
      i.iImage = NULL ;
      i.lParam = 0 ;
      result
            = m_ListCtrl->SetItem (&i) ;
*/

      return ((int)result) ;
} ;

//////////////////////////////////////////////////
//
void CReportStyleListControl::RemoveItem (int ItemNumber)
{
      m_ListCtrl = pGetListCtrl () ;
      m_ListCtrl->DeleteItem (ItemNumber) ;
} ;
//////////////////////////////////////////////////
//Add item to list control entree.
//
void CReportStyleListControl::AddItem (int ItemNumber, int SubItemNumber, char Text [])
{
      m_ListCtrl = pGetListCtrl () ;

      LV_ITEM lvItem;
      lvItem.mask = LVIF_TEXT;
      lvItem.iItem = ItemNumber ;
      lvItem.iSubItem = SubItemNumber;

      //Keep tract of the number of subitems.
      if (SubItemNumber > m_NumSubItems)
      {
            m_NumSubItems = SubItemNumber ;
      } ;

      lvItem.pszText = (LPTSTR)Text;

      //if (SubItemNumber == 0)
      if (SubItemNumber == 0
            && ItemNumber > (m_ListCtrl->GetItemCount() - 1) )
      {
            //This is the first item of the entree
            m_ListCtrl->InsertItem(&lvItem);
            m_ListCtrl->EnsureVisible (lvItem.iItem, TRUE) ;
      }
      else
      {
            //This is an additionl subitem.
            m_ListCtrl->SetItem(&lvItem);
      } ;

} ;
//////////////////////////////////////////////////
//
BOOL CReportStyleListControl::bStrMatches
      (CString StrChecking,
         CString SearchStr,
         ULONG Flags )
{
      CFilter TextFilter ;
      CString csFilter ;

      if ((Flags & FR_WHOLEWORD) != 0)
      {
            csFilter.Format ("'%s' IS FOUND",
                  SearchStr.GetBuffer(0)) ;
      }
      else
      {
            //Just find any occurance of the text
            //string
            csFilter.Format ("\"%s\" IS FOUND",
                  SearchStr.GetBuffer(0)) ;
      } ;

      if ((Flags & FR_MATCHCASE) == 0)
      {
            csFilter.MakeUpper() ;
            StrChecking.MakeUpper() ;
      } ;

      return TextFilter.StrMatchesFilter
            ( csFilter,
              StrChecking,
              Flags & FR_MATCHCASE) ;
} ;
///////////////////////////////////////////////////
//Routine to retrieve the string value that
//is present at a specifed index and subindes.
//
BOOL CReportStyleListControl::bGetItemStrVal
      ( int iItem,
          int iSubItem,
            CString &csItemStrVal )
{
      m_ListCtrl = pGetListCtrl () ;
      CString csTmp ;

      CHAR cRcvBuf [500] ;

      if (iItem + 1 > m_ListCtrl->GetItemCount())
      {
            //Item requested is out of range
            return FALSE ;
      } ;

      if (iSubItem > m_NumSubItems)
      {
            //SubItem is out of range.
            return FALSE ;
      } ;

      //Set up a structure to read the string control item
      LV_ITEM i ;
      i.iItem = iItem ;
      i.iSubItem = iSubItem ;
      i.mask = LVIF_TEXT ;
      i.pszText = cRcvBuf ;
      i.cchTextMax = sizeof(cRcvBuf) ;

      //Read it.
      if (!m_ListCtrl->GetItem (&i))
      {
            return FALSE ;
      } ;

      //Save the value return in the
      //caller's CString object.
      csItemStrVal = i.pszText ;

      return TRUE ;
} ;
//////////////////////////////////////////////////
//Method to fill a provided CString object
//with text from all columns of the specfied
//row.
//
BOOL CReportStyleListControl::bGetAllItemStrVal
      ( int iItem,
            CString &csItemStrVal )
{
      csItemStrVal = "" ;
      CString csTmp ;

      for (int x=0; x<=m_NumSubItems; x++)
      {
            if (!bGetItemStrVal
                  ( iItem,
                    x,
                    csTmp ))
            {
                  return FALSE ;
            } ;

            csItemStrVal += csTmp ;
            csItemStrVal += " " ;
      } ;

      return TRUE ;
} ;
//////////////////////////////////////////////////
//
void CReportStyleListControl::CopyAllSelectedToClip ()
{
      //Copy all selected list control items to the
      //Clip board.
      CListCtrl *pListCtrl = pGetListCtrl() ;
      ASSERT (pListCtrl) ;
      
      int iNumItemsSelected = pListCtrl->GetSelectedCount() ;
      if (iNumItemsSelected <= 0) return ;

      CString csSelectedText ;
      CString csTmp ;
      int iNumAdded = 0 ;

      int iItemIndex = pListCtrl->GetNextItem
                (-1,
                   LVNI_SELECTED) ;
      while (iItemIndex != -1)
      {
            bGetAllItemStrVal
                  (iItemIndex,
                   csTmp) ;
            iNumAdded++ ;

            if (iNumAdded > 1)
            {
                  csSelectedText += "\r\n" ;
            } ;
            csSelectedText += csTmp ;

            //Get the next item, if any.
            iItemIndex = pListCtrl->GetNextItem
                        (iItemIndex,
                         LVNI_SELECTED) ;

      } ;

      //Copy the text to the clipboard.
      if ( !pListCtrl->OpenClipboard() )
      {
            AfxMessageBox( "Cannot open the Clipboard" );
            return;
      }
      // Remove the current Clipboard contents
      EmptyClipboard() ;

      // ...
      // Get the currently selected data
      // ...
      // For the appropriate data formats...
      CString csItemText = csSelectedText ;

      ULONG ulDataSize = csItemText.GetLength() + 1 ;
      HANDLE hData = GlobalAlloc
            ( GMEM_MOVEABLE & GMEM_DDESHARE,
              ulDataSize) ;
      LPSTR lpszTmp = (LPSTR)GlobalLock (hData) ;
      strcpy
            ( lpszTmp,
              csItemText.GetBuffer(0)) ;
      GlobalUnlock (hData) ;

             
      if ( ::SetClipboardData
             ( CF_TEXT,
               hData ) == NULL )
      {
            AfxMessageBox( "Unable to set Clipboard data" );
            CloseClipboard();
            return;
      }

      // ...
      CloseClipboard();

} ;
//////////////////////////////////////////////////
//See if the indexed item matches the specified
//search criteria.
//
BOOL CReportStyleListControl::bItemMatches
        ( int iIndex,
            CString csSearchStr,
            DWORD dFlags )
{
      m_ListCtrl = pGetListCtrl () ;
      CString csTmp ;

      CHAR cRcvBuf [500] ;

      LV_ITEM i ;
      i.iItem = iIndex ;
      i.mask = LVIF_TEXT ;
      i.pszText = cRcvBuf ;
      i.cchTextMax = sizeof(cRcvBuf) ;

      //Search the items for a match
      i.iSubItem = -1 ;
      while (1)
      {
            i.iSubItem++ ;
            if (i.iSubItem > m_NumSubItems)
            {
                  return FALSE ;
            } ;

            if (!m_ListCtrl->GetItem (&i))
            {
                  return FALSE ;
            } ;

            //See if this field matches the search
            csTmp = i.pszText ;
            if (bStrMatches (csTmp, csSearchStr, dFlags))
            {
                  return TRUE ;
            } ;

      };//while searching items

      return FALSE;
} ;
//////////////////////////////////////////////////
//Find the first log in the list that matches
//the search criteria passed in.
//If a match is found, return the 0 based index of
//the item, it NOT, return -1.
//
//In addition, make the item found visible and
//selected.
//
int CReportStyleListControl::FindNext (CString SearchStr, DWORD Flags)
{
      int iresult = -1 ;
      m_ListCtrl = pGetListCtrl () ;
      int iStartIndex ;

      if (m_ListCtrl->GetItemCount() <= 0)
      {
            //No elements in list, get out
            return iresult ;
      } ;

      if (m_ListCtrl->GetSelectedCount() <= 0)
      {
            //No items selected, start at the top
            iStartIndex = 0 ;
      }
      else
      {
            //Find the first selected item.
            iStartIndex = GetSelectedItem () ;

            //Start on the next element for the
            //search.
            if (iStartIndex + 1 == m_ListCtrl->GetItemCount())
            {
                  iStartIndex = 0 ;
            }
            else
            {
                  iStartIndex++ ;
            } ;

      } ;

      //better not be -1 when get here
      ASSERT (iStartIndex != -1) ;

      //Now, starting the next item down, loop through
      //the list looking for a match until we completely
      //loop or a match is found.
      //
      //Watch out for if 1 item in list.
      int NumItems = m_ListCtrl->GetItemCount() ;

      //Mark the starting index, starting 1 down
      //from the selected item.
      int x = iStartIndex;

      while (1)
      {
            //Check this item and see if it matches.
            if (bItemMatches
                   ( x,
                     SearchStr,
                     Flags ) )
            {
                  //found a match
                  iresult = x ;
                  break ;
            } ;
            
            //Look at the next element
            if ( x == NumItems - 1 )
            {
                  x = 0 ;
            }
            else
            {
                  x++ ;
            } ;

            if (x == iStartIndex)
            {
                  //search went all the way around without
                  //a match, get out.
                  break ;
            } ;
            
      };//while looking for match

      if (iresult != -1)
      {
            //selected the item.
            SetSelectedItem (iresult) ;
            m_ListCtrl->EnsureVisible (iresult, TRUE) ;
      } ;
      return iresult ;
} ;
////////////////////////////////////////////////////////////////////
//Rebuild the list control, only including those lines that
//match a specified criteria passed in.
//
BOOL CReportStyleListControl::bRebuildListControlFromFilter
               ( CString csFilter,
                   DWORD dFlags )
{
      m_ListCtrl = pGetListCtrl () ;

      if (m_ListCtrl->GetItemCount() <= 0)
      {
            //No elements in list, get out
            return TRUE ;
      } ;

      //Start at the top of the list and pluck out any
      //entry that doesn't match the filter.
      int x = 0;
      while (1)
      {
            //Check this item and see if it matches.
            if (bItemMatches
                   ( x,
                     csFilter,
                     dFlags ) == FALSE)
            {
                  //line doesn't match, delete from list
                  RemoveItem (x) ;
            }
            else
            {
                  x++ ;
            } ;
            
            if (x >= m_ListCtrl->GetItemCount())
            {
                  //done looking, get out
                  break ;
            } ;
      };//while looking for match

      return TRUE;
} ;


Random Solutions  
 
programming4us programming4us