// ListSortCtrl.cpp : 实现文件 // #include "stdafx.h" #include "ListSortCtrl.h" #include "..\MD5\MD5.h" #include // CListSortCtrl 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 ); // format should be 99/99/9999. 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 // text. 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() // CListSortCtrl 消息处理程序 void CListSortCtrl::PreSubclassWindow() { // TODO: 在此添加专用代码和/或调用基类 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(); } /************************************************************************/ /* 函数:[10/21/2016 IT]; /* 描述:; /* 参数:; /* [IN] :; /* [OUT] :; /* [IN/OUT] :; /* 返回:void; /* 注意:最后一个参数,必须以NULL结尾(请看示例); /* 示例:CListSortCtrl::SetHeadings(_T("示例1,100"),_T("示例2,100"),NULL); /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ 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; } /************************************************************************/ /* 函数:SetTextFont[3/6/2017 Jeff]; /* 描述:设置文本字体; /* 参数:; /* [IN] nTextFontSize:字体大小; /* [IN] bBold:是否粗体; /* [IN] bItalic:是否斜体; /* [IN] strTextFontName:字体名称,如楷体; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ 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); // Pixel per inch 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); // 创建字体; //m_cfont = GetFont();// 局部变量会导致字体设置失败,必须是全局或成员变量; 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(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(pNMHDR); LV_ITEM *pItem = &pDispInfo->item; ASSERT(pItem); if (m_AryList.GetSize() > pItem->iItem && (pItem->mask & LVIF_TEXT) )//valid text buffer? { //_tcscpy_s(pItem->pszText, pItem->cchTextMax, m_AryList.ElementAt(pItem->iItem).ElementAt(pItem->iSubItem)); 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( 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(&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; CMD5 md5; md5.SetBYTEText((BYTE*)m_strSection.GetString(), m_strSection.GetLength()*sizeof(TCHAR)); m_strSection = md5.GetMD5Digest(); 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(); }