//----------------------------------------------------------------------------- // ProgList.h //----------------------------------------------------------------------------- #ifndef _PROGLIST_H #define _PROGLIST_H //----------------------------------------------------------------------------- // state of the item //----------------------------------------------------------------------------- typedef enum { IS_NONE = 0, // the item hasn't been run yet IS_SUCCEEDED, // the item succeeded IS_FAILED // the item failed } ItemState; //----------------------------------------------------------------------------- // an entry in the list //----------------------------------------------------------------------------- class CProgressItem { public: CProgressItem() : m_strText(_T("")), m_bActive(FALSE), m_eState(IS_NONE), m_lData(0) { } TSTRING m_strText; // display string of the item BOOL m_bActive; // is the item active / currently processing ItemState m_eState; // state of the item LPARAM m_lData; // misc item data }; // class CProgressItem //----------------------------------------------------------------------------- // the list itself //----------------------------------------------------------------------------- class CProgressList : public CWindowImpl< CProgressList, CListViewCtrl > { //----------------------------------------------------------------------------- // functions //----------------------------------------------------------------------------- public: BEGIN_MSG_MAP(CProgressList) END_MSG_MAP() typedef CWindowImpl< CProgressList, CListViewCtrl > BC; VOID Attach( HWND h ) { // call the base class to attach to the control BC::Attach( h ); // initialize the background of the control SetBkColor( GetSysColor(COLOR_BTNFACE) ); // create the fonts for the control HFONT hf; LOGFONT lf; ZeroMemory( &lf, sizeof(lf) ); hf = GetFont(); ::GetObject( hf, sizeof(lf), &lf ); // create the normal/text font from the current font m_hfText = CreateFontIndirect( &lf ); // create the bold font lf.lfWeight = FW_BOLD; m_hfBoldText = CreateFontIndirect( &lf ); // make the symbol font lf.lfHeight = min( GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYVSCROLL) ) - 4; lf.lfHeight = MulDiv( lf.lfHeight, 3, 2 ); lf.lfWeight = FW_NORMAL; lf.lfCharSet = SYMBOL_CHARSET; _tcscpy( lf.lfFaceName, _T("Marlett") ); m_hfSymbol = CreateFontIndirect( &lf ); // need to use a larger font for one of the symbols lf.lfHeight -= ( lf.lfHeight / 4 ); m_hfLargeSymbol = CreateFontIndirect( &lf ); // add a column that is the width of the control RECT rc; GetWindowRect( &rc ); LVCOLUMN lvC; lvC.mask = LVCF_TEXT | LVCF_WIDTH; lvC.cx = (rc.right - rc.left) - GetSystemMetrics(SM_CXVSCROLL) - 2; lvC.pszText = _T(""); InsertColumn( 0, &lvC ); } INT AddItem( TSTRING strText ) { // create a new progress item and insert into the list control and internal list CProgressItem* pItem = new CProgressItem(); if( !pItem ) return -1; pItem->m_strText = strText; m_lItems.push_back( pItem ); LVITEM lvI; ZeroMemory( &lvI, sizeof(lvI) ); lvI.mask = LVIF_PARAM; lvI.iItem = GetItemCount(); lvI.lParam = (LPARAM)pItem; return InsertItem( &lvI ); } VOID OnMeasureItem( LPARAM lParam ) { MEASUREITEMSTRUCT* p = (MEASUREITEMSTRUCT*)lParam; if( !p ) return; HDC hDC = GetDC(); TEXTMETRIC tm; GetTextMetrics( hDC, &tm ); p->itemWidth = 0; p->itemHeight = tm.tmHeight + 2; ReleaseDC( hDC ); } VOID OnDrawItem( LPARAM lParam ) { // get the data we need and stop redrawing DRAWITEMSTRUCT* p = (DRAWITEMSTRUCT*)lParam; if( !p ) return; CProgressItem* pI = (CProgressItem*)p->itemData; if( !pI ) return; SetRedraw( FALSE ); // get the symbol to draw next to the item TCHAR ch = 0; COLORREF crText = GetSysColor( COLOR_WINDOWTEXT ); HFONT hfSymbol = m_hfSymbol; if( pI->m_bActive ) { ch = _T('4'); } else if( pI->m_eState == IS_SUCCEEDED ) { ch = _T('a'); crText = RGB( 0, 128, 0 ); } else if( pI->m_eState == IS_FAILED ) { ch = _T('r'); crText = RGB( 128, 0, 0 ); hfSymbol = m_hfLargeSymbol; } // setup the text and draw the symbol if there is one if( ch ) { HFONT hfPre = (HFONT)SelectObject( p->hDC, hfSymbol ); COLORREF crPre = ::SetTextColor( p->hDC, crText ); DrawText( p->hDC, &ch, 1, &p->rcItem, DT_SINGLELINE | DT_VCENTER ); SelectObject( p->hDC, hfPre ); ::SetTextColor( p->hDC, crPre ); } // draw the item text, inc the RECT for the symbol p->rcItem.left += 20; HFONT hfPre = (HFONT)SelectObject( p->hDC, ch == _T('4') ? m_hfBoldText : m_hfText ); COLORREF crPre = ::SetTextColor( p->hDC, GetSysColor(COLOR_WINDOWTEXT) ); DrawText( p->hDC, pI->m_strText.c_str(), pI->m_strText.length(), &p->rcItem, DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX ); SelectObject( p->hDC, hfPre ); ::SetTextColor( p->hDC, crPre ); // allow the redraws to happen SetRedraw( TRUE ); } VOID SetItemState( INT iIndex, ItemState eState, BOOL bRedraw = TRUE ) { // get the CProgressItem and set the state CProgressItem* pI = GetProgressItem( iIndex ); if( pI ) { pI->m_eState = eState; } if( bRedraw ) { SendMessage( LVM_REDRAWITEMS, iIndex, iIndex ); UpdateWindow(); } } VOID ToggleActive( INT iIndex, BOOL bRedraw = TRUE ) { // get the CProgress Item and toggle it's 'active' flag CProgressItem* pI = GetProgressItem( iIndex ); if( pI ) { pI->m_bActive = !pI->m_bActive; } if( bRedraw ) { SendMessage( LVM_REDRAWITEMS, iIndex, iIndex ); UpdateWindow(); } } CProgressItem* GetProgressItem( INT iIndex ) { LVITEM lvI; ZeroMemory( &lvI, sizeof(lvI) ); lvI.mask = LVIF_PARAM; lvI.iItem = iIndex; if( !SendMessage(LVM_GETITEM, 0, (LPARAM)&lvI) ) { return NULL; } return (CProgressItem*)lvI.lParam; } CProgressList() : m_hfText(NULL), m_hfBoldText(NULL), m_hfSymbol(NULL), m_hfLargeSymbol(NULL) { } ~CProgressList() { if( m_hfText ) DeleteObject( m_hfText ); if( m_hfBoldText ) DeleteObject( m_hfBoldText ); if( m_hfSymbol ) DeleteObject( m_hfSymbol ); if( m_hfLargeSymbol ) DeleteObject( m_hfLargeSymbol ); EmptyList(); } VOID EmptyList( VOID ) { // cleanup the progress list items for( list::iterator it = m_lItems.begin(); it != m_lItems.end(); ++it ) { delete (*it); } m_lItems.clear(); } BOOL DeleteAllItems( VOID ) { EmptyList(); return BC::DeleteAllItems(); } private: //----------------------------------------------------------------------------- // variables //----------------------------------------------------------------------------- public: private: HFONT m_hfText; HFONT m_hfBoldText; HFONT m_hfSymbol; HFONT m_hfLargeSymbol; list< CProgressItem* > m_lItems; }; // class CProgressList #endif // _PROGLIST_H