|
@@ -0,0 +1,358 @@
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#include "stdafx.h"
|
|
|
+#include "ListSortCtrl.h"
|
|
|
+
|
|
|
+#include <strsafe.h>
|
|
|
+
|
|
|
+
|
|
|
+bool CListSortCtrl::IsNumber( LPCTSTR pszText )
|
|
|
+{
|
|
|
+ ASSERT_VALID_STRING( pszText );
|
|
|
+ for( int i = 0; i < lstrlen( pszText ); i++ )
|
|
|
+ if( ! (_istdigit( pszText[ i ] )||pszText[ i ]=='.'||pszText[ i ]=='-') )
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+int CListSortCtrl::NumberCompare( LPCTSTR pszNumber1, LPCTSTR pszNumber2 )
|
|
|
+{
|
|
|
+ ASSERT_VALID_STRING( pszNumber1 );
|
|
|
+ ASSERT_VALID_STRING( pszNumber2 );
|
|
|
+
|
|
|
+ const float iNumber1 = _tstof( pszNumber1 );
|
|
|
+ const float iNumber2 = _tstof( pszNumber2 );
|
|
|
+
|
|
|
+ if( iNumber1 < iNumber2 )
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if( iNumber1 > iNumber2 )
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+bool CListSortCtrl::IsDate( LPCTSTR pszText )
|
|
|
+{
|
|
|
+ ASSERT_VALID_STRING( pszText );
|
|
|
+
|
|
|
+ if( lstrlen( pszText ) != 10 )
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return _istdigit( pszText[ 0 ] )
|
|
|
+ && _istdigit( pszText[ 1 ] )
|
|
|
+ && _istdigit( pszText[ 2 ] )
|
|
|
+ && _istdigit( pszText[ 3 ] )
|
|
|
+ && pszText[ 4 ] == _T('-')
|
|
|
+ && _istdigit( pszText[ 5 ] )
|
|
|
+ && _istdigit( pszText[ 6 ] )
|
|
|
+ && pszText[ 7 ] == _T('-')
|
|
|
+ && _istdigit( pszText[ 8 ] )
|
|
|
+ && _istdigit( pszText[ 9 ] );
|
|
|
+}
|
|
|
+
|
|
|
+int CListSortCtrl::DateCompare( const CString& strDate1, const CString& strDate2 )
|
|
|
+{
|
|
|
+ if(strDate1.GetLength ()!=10)return -1;
|
|
|
+ if(strDate2.GetLength ()!=10)return -1;
|
|
|
+ const int iYear1 = _tstoi( strDate1.Mid( 0, 4 ) );
|
|
|
+ const int iYear2 = _tstoi( strDate2.Mid( 0, 4 ) );
|
|
|
+
|
|
|
+ if( iYear1 < iYear2 )
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if( iYear1 > iYear2 )
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ const int iMonth1 = _tstoi( strDate1.Mid( 5, 2 ) );
|
|
|
+ const int iMonth2 = _tstoi( strDate2.Mid( 5, 2 ) );
|
|
|
+
|
|
|
+ if( iMonth1 < iMonth2 )
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if( iMonth1 > iMonth2 )
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ const int iDay1 = _tstoi( strDate1.Mid( 8, 2 ) );
|
|
|
+ const int iDay2 = _tstoi( strDate2.Mid( 8, 2 ) );
|
|
|
+
|
|
|
+ if( iDay1 < iDay2 )
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if( iDay1 > iDay2 )
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int CListSortCtrl::CompareByLabel( const void *elem1, const void *elem2)
|
|
|
+{
|
|
|
+ CStringArray *p1 = (CStringArray*)elem1;
|
|
|
+ CStringArray *p2 = (CStringArray*)elem2;
|
|
|
+
|
|
|
+ if( IsDate( p1->ElementAt (CListSortCtrl::m_nCompareColumn) ) )
|
|
|
+ return CListSortCtrl::m_bSortAscending ? DateCompare( p1->ElementAt (CListSortCtrl::m_nCompareColumn), p2->ElementAt (CListSortCtrl::m_nCompareColumn) ) : DateCompare( p2->ElementAt (CListSortCtrl::m_nCompareColumn), p1->ElementAt (CListSortCtrl::m_nCompareColumn) );
|
|
|
+ else if( IsNumber( p1->ElementAt (CListSortCtrl::m_nCompareColumn) ) )
|
|
|
+ return CListSortCtrl::m_bSortAscending ? NumberCompare( p1->ElementAt (CListSortCtrl::m_nCompareColumn), p2->ElementAt (CListSortCtrl::m_nCompareColumn) ) : NumberCompare( p2->ElementAt (CListSortCtrl::m_nCompareColumn), p1->ElementAt (CListSortCtrl::m_nCompareColumn) );
|
|
|
+ else
|
|
|
+
|
|
|
+ return CListSortCtrl::m_bSortAscending ? lstrcmp( p1->ElementAt (CListSortCtrl::m_nCompareColumn), p2->ElementAt (CListSortCtrl::m_nCompareColumn) ) : lstrcmp( p2->ElementAt (CListSortCtrl::m_nCompareColumn), p1->ElementAt (CListSortCtrl::m_nCompareColumn) );
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+INT CListSortCtrl::m_nCompareColumn = 0;
|
|
|
+BOOL CListSortCtrl::m_bSortAscending = FALSE;
|
|
|
+
|
|
|
+IMPLEMENT_DYNAMIC(CListSortCtrl, CListCtrl)
|
|
|
+
|
|
|
+CListSortCtrl::CListSortCtrl()
|
|
|
+:m_bSortSupport(TRUE)
|
|
|
+,m_nSortColumns(-1)
|
|
|
+,m_strSection(_T(""))
|
|
|
+,m_nNumColumns(0)
|
|
|
+,m_clrLightGrid(RGB(204,204,204))
|
|
|
+,m_clrDarkGrid(RGB(190,190,190))
|
|
|
+{
|
|
|
+ m_strSection = _T("");
|
|
|
+ m_nCompareColumn = -1;
|
|
|
+}
|
|
|
+
|
|
|
+CListSortCtrl::~CListSortCtrl()
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+BEGIN_MESSAGE_MAP(CListSortCtrl, CListCtrl)
|
|
|
+ ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, &CListSortCtrl::OnLvnColumnclick)
|
|
|
+ ON_NOTIFY_REFLECT(LVN_GETDISPINFO, &CListSortCtrl::OnLvnGetdispinfo)
|
|
|
+#ifndef __LIST_DRAW__
|
|
|
+ ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CListSortCtrl::OnNMCustomdraw)
|
|
|
+#endif
|
|
|
+ ON_WM_DESTROY()
|
|
|
+END_MESSAGE_MAP()
|
|
|
+
|
|
|
+
|
|
|
+void CListSortCtrl::PreSubclassWindow()
|
|
|
+{
|
|
|
+
|
|
|
+ ASSERT( GetStyle() & LVS_REPORT );
|
|
|
+ CListCtrl::PreSubclassWindow();
|
|
|
+ VERIFY( m_Ctrlheader.SubclassWindow( GetHeaderCtrl()->GetSafeHwnd() ) );
|
|
|
+}
|
|
|
+
|
|
|
+void CListSortCtrl::RemoveAll()
|
|
|
+{
|
|
|
+ DeleteAllItems();
|
|
|
+ for ( int i = 0; i < m_AryList.GetSize(); i++)
|
|
|
+ {
|
|
|
+ m_AryList.ElementAt(i).RemoveAll();
|
|
|
+ }
|
|
|
+ m_AryList.RemoveAll();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+BOOL CListSortCtrl::SetHeadings( IN LPCTSTR pszText, ... )
|
|
|
+{
|
|
|
+ if ( pszText == NULL ) return FALSE;
|
|
|
+
|
|
|
+ va_list list;
|
|
|
+ INT nCommaPos = 0;
|
|
|
+ CString strColumn = _T("");
|
|
|
+ va_start( list, pszText );
|
|
|
+ do
|
|
|
+ {
|
|
|
+ strColumn = pszText;
|
|
|
+ if ( -1 != (nCommaPos = strColumn.Find(_T(","))))
|
|
|
+ {
|
|
|
+ m_strSection += strColumn.Left(nCommaPos);
|
|
|
+ if( InsertColumn( m_nNumColumns++, strColumn.Left(nCommaPos), LVCFMT_LEFT, _tstoi( strColumn.Mid( nCommaPos + 1) ) ) == -1 )
|
|
|
+ {
|
|
|
+ va_end( list );
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pszText = va_arg( list, LPCTSTR );
|
|
|
+ } while (pszText != NULL);
|
|
|
+
|
|
|
+ va_end( list );
|
|
|
+
|
|
|
+ LoadColumnInfo();
|
|
|
+ SetExtendedStyle(LVS_EX_FLATSB|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP);
|
|
|
+
|
|
|
+ SetListFont(_T("宋体"), 11);
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void CListSortCtrl::SetListFont(IN CString strFontName, IN int nFontSize, IN BOOL bBold, IN BOOL bItalic)
|
|
|
+{
|
|
|
+ LOGFONT lf;
|
|
|
+ CClientDC dc(this);
|
|
|
+ int dpy = GetDeviceCaps(dc, LOGPIXELSY);
|
|
|
+ lf.lfHeight = -MulDiv(nFontSize, dpy, 72);
|
|
|
+ lf.lfWeight = 0;
|
|
|
+ lf.lfEscapement = 0;
|
|
|
+ lf.lfOrientation = 0;
|
|
|
+ if (bBold)
|
|
|
+ lf.lfWeight = FW_BLACK;
|
|
|
+ else
|
|
|
+ lf.lfWeight = FW_NORMAL;
|
|
|
+ lf.lfItalic = bItalic;
|
|
|
+ lf.lfUnderline = FALSE;
|
|
|
+ lf.lfStrikeOut = 0;
|
|
|
+ lf.lfCharSet = ANSI_CHARSET;
|
|
|
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
|
|
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
|
|
+ lf.lfQuality = DEFAULT_QUALITY;
|
|
|
+ lf.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN;
|
|
|
+
|
|
|
+ _tcscpy_s(lf.lfFaceName, strFontName);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ VERIFY(m_cfont.CreateFontIndirect(&lf));
|
|
|
+
|
|
|
+ this->SetFont(&m_cfont);
|
|
|
+}
|
|
|
+
|
|
|
+void CListSortCtrl::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)
|
|
|
+{
|
|
|
+
|
|
|
+ if ( !m_bSortSupport || m_AryList.GetSize() == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
|
|
|
+ m_bSortAscending = !m_bSortAscending;
|
|
|
+ for (int i = 0; i < m_nNumColumns; i++)
|
|
|
+ {
|
|
|
+ if( i == pNMLV->iSubItem )
|
|
|
+ {
|
|
|
+ SortByCol(i);
|
|
|
+ m_Ctrlheader.SetSortArrow( i, m_bSortAscending );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Invalidate();
|
|
|
+
|
|
|
+ *pResult = 0;
|
|
|
+}
|
|
|
+
|
|
|
+void CListSortCtrl::OnLvnGetdispinfo(NMHDR *pNMHDR, LRESULT *pResult)
|
|
|
+{
|
|
|
+ NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
|
|
|
+ LV_ITEM *pItem = &pDispInfo->item;
|
|
|
+ ASSERT(pItem);
|
|
|
+ if (m_AryList.GetSize() > pItem->iItem && (pItem->mask & LVIF_TEXT) )
|
|
|
+ {
|
|
|
+
|
|
|
+ StringCbCopy(pItem->pszText, pItem->cchTextMax, m_AryList.ElementAt(pItem->iItem).ElementAt(pItem->iSubItem));
|
|
|
+ }
|
|
|
+ *pResult = 0;
|
|
|
+}
|
|
|
+
|
|
|
+#ifndef __LIST_DRAW__
|
|
|
+void CListSortCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
|
|
|
+{
|
|
|
+ NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
|
|
|
+ *pResult = 0;
|
|
|
+ if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
|
|
|
+ {
|
|
|
+ *pResult = CDRF_NOTIFYITEMDRAW;
|
|
|
+ }
|
|
|
+ else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
|
|
|
+ {
|
|
|
+ INT npos = pLVCD->nmcd.dwItemSpec;
|
|
|
+ if ( npos % 2 )
|
|
|
+ pLVCD->clrTextBk = m_clrLightGrid;
|
|
|
+ else
|
|
|
+ pLVCD->clrTextBk = m_clrDarkGrid;
|
|
|
+
|
|
|
+ *pResult = CDRF_DODEFAULT;
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+void CListSortCtrl::SortByCol(IN const int nColIndex)
|
|
|
+{
|
|
|
+ m_nCompareColumn = nColIndex;
|
|
|
+ ::AfxGetApp()->DoWaitCursor(TRUE);
|
|
|
+ qsort( static_cast<void*>(&m_AryList[0]), m_AryList.GetSize(), sizeof(m_AryList[nColIndex]), CompareByLabel);
|
|
|
+ ::AfxGetApp()->DoWaitCursor(FALSE);
|
|
|
+}
|
|
|
+
|
|
|
+void CListSortCtrl::LoadColumnInfo()
|
|
|
+{
|
|
|
+ ASSERT( m_nNumColumns > 0 );
|
|
|
+ UINT nBytes = 0;
|
|
|
+ BYTE* buf = NULL;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if( AfxGetApp()->GetProfileBinary( _T("sortlist"), m_strSection, &buf, &nBytes ) )
|
|
|
+ {
|
|
|
+ if( nBytes > 0 )
|
|
|
+ {
|
|
|
+ CMemFile memFile( buf, nBytes );
|
|
|
+ CArchive ar( &memFile, CArchive::load );
|
|
|
+ m_Ctrlheader.Serialize( ar );
|
|
|
+ ar.Close();
|
|
|
+ m_Ctrlheader.Invalidate();
|
|
|
+ }
|
|
|
+ delete[] buf;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void CListSortCtrl::SaveColumnInfo()
|
|
|
+{
|
|
|
+ ASSERT( m_nNumColumns > 0 );
|
|
|
+ CMemFile memFile;
|
|
|
+ CArchive ar( &memFile, CArchive::store );
|
|
|
+ m_Ctrlheader.Serialize( ar );
|
|
|
+ ar.Close();
|
|
|
+ DWORD dwLen = memFile.GetLength();
|
|
|
+ BYTE* buf = memFile.Detach();
|
|
|
+ VERIFY( AfxGetApp()->WriteProfileBinary( _T("sortlist"), m_strSection, buf, dwLen ) );
|
|
|
+ free( buf );
|
|
|
+}
|
|
|
+
|
|
|
+void CListSortCtrl::OnDestroy()
|
|
|
+{
|
|
|
+ SaveColumnInfo();
|
|
|
+ CListCtrl::OnDestroy();
|
|
|
+}
|