ListSortCtrl.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. // ListSortCtrl.cpp : 实现文件
  2. //
  3. #include "stdafx.h"
  4. #include "ListSortCtrl.h"
  5. #include "..\MD5\MD5.h"
  6. #include <strsafe.h>
  7. // CListSortCtrl
  8. bool CListSortCtrl::IsNumber( LPCTSTR pszText )
  9. {
  10. ASSERT_VALID_STRING( pszText );
  11. for( int i = 0; i < lstrlen( pszText ); i++ )
  12. if( ! (_istdigit( pszText[ i ] )||pszText[ i ]=='.'||pszText[ i ]=='-') )
  13. return false;
  14. return true;
  15. }
  16. int CListSortCtrl::NumberCompare( LPCTSTR pszNumber1, LPCTSTR pszNumber2 )
  17. {
  18. ASSERT_VALID_STRING( pszNumber1 );
  19. ASSERT_VALID_STRING( pszNumber2 );
  20. const float iNumber1 = _tstof( pszNumber1 );
  21. const float iNumber2 = _tstof( pszNumber2 );
  22. if( iNumber1 < iNumber2 )
  23. return -1;
  24. if( iNumber1 > iNumber2 )
  25. return 1;
  26. return 0;
  27. }
  28. bool CListSortCtrl::IsDate( LPCTSTR pszText )
  29. {
  30. ASSERT_VALID_STRING( pszText );
  31. // format should be 99/99/9999.
  32. if( lstrlen( pszText ) != 10 )
  33. return false;
  34. return _istdigit( pszText[ 0 ] )
  35. && _istdigit( pszText[ 1 ] )
  36. && _istdigit( pszText[ 2 ] )
  37. && _istdigit( pszText[ 3 ] )
  38. && pszText[ 4 ] == _T('-')
  39. && _istdigit( pszText[ 5 ] )
  40. && _istdigit( pszText[ 6 ] )
  41. && pszText[ 7 ] == _T('-')
  42. && _istdigit( pszText[ 8 ] )
  43. && _istdigit( pszText[ 9 ] );
  44. }
  45. int CListSortCtrl::DateCompare( const CString& strDate1, const CString& strDate2 )
  46. {
  47. if(strDate1.GetLength ()!=10)return -1;
  48. if(strDate2.GetLength ()!=10)return -1;
  49. const int iYear1 = _tstoi( strDate1.Mid( 0, 4 ) );
  50. const int iYear2 = _tstoi( strDate2.Mid( 0, 4 ) );
  51. if( iYear1 < iYear2 )
  52. return -1;
  53. if( iYear1 > iYear2 )
  54. return 1;
  55. const int iMonth1 = _tstoi( strDate1.Mid( 5, 2 ) );
  56. const int iMonth2 = _tstoi( strDate2.Mid( 5, 2 ) );
  57. if( iMonth1 < iMonth2 )
  58. return -1;
  59. if( iMonth1 > iMonth2 )
  60. return 1;
  61. const int iDay1 = _tstoi( strDate1.Mid( 8, 2 ) );
  62. const int iDay2 = _tstoi( strDate2.Mid( 8, 2 ) );
  63. if( iDay1 < iDay2 )
  64. return -1;
  65. if( iDay1 > iDay2 )
  66. return 1;
  67. return 0;
  68. }
  69. int CListSortCtrl::CompareByLabel( const void *elem1, const void *elem2)
  70. {
  71. CStringArray *p1 = (CStringArray*)elem1;
  72. CStringArray *p2 = (CStringArray*)elem2;
  73. if( IsDate( p1->ElementAt (CListSortCtrl::m_nCompareColumn) ) )
  74. 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) );
  75. else if( IsNumber( p1->ElementAt (CListSortCtrl::m_nCompareColumn) ) )
  76. 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) );
  77. else
  78. // text.
  79. 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) );
  80. return true;
  81. }
  82. //////////////////////////////////////////////////////////////////////////
  83. // 静态变量;
  84. INT CListSortCtrl::m_nCompareColumn = 0;
  85. BOOL CListSortCtrl::m_bSortAscending = FALSE;
  86. IMPLEMENT_DYNAMIC(CListSortCtrl, CListCtrl)
  87. CListSortCtrl::CListSortCtrl()
  88. :m_bSortSupport(TRUE)
  89. ,m_nSortColumns(-1)
  90. ,m_strSection(_T(""))
  91. ,m_nNumColumns(0)
  92. ,m_clrLightGrid(RGB(204,204,204))
  93. ,m_clrDarkGrid(RGB(190,190,190))
  94. {
  95. m_strSection = _T("");
  96. m_nCompareColumn = -1;
  97. }
  98. CListSortCtrl::~CListSortCtrl()
  99. {
  100. }
  101. BEGIN_MESSAGE_MAP(CListSortCtrl, CListCtrl)
  102. ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, &CListSortCtrl::OnLvnColumnclick)
  103. ON_NOTIFY_REFLECT(LVN_GETDISPINFO, &CListSortCtrl::OnLvnGetdispinfo)
  104. #ifndef __LIST_DRAW__
  105. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CListSortCtrl::OnNMCustomdraw)
  106. #endif
  107. ON_WM_DESTROY()
  108. END_MESSAGE_MAP()
  109. // CListSortCtrl 消息处理程序
  110. void CListSortCtrl::PreSubclassWindow()
  111. {
  112. // TODO: 在此添加专用代码和/或调用基类
  113. ASSERT( GetStyle() & LVS_REPORT );
  114. CListCtrl::PreSubclassWindow();
  115. VERIFY( m_Ctrlheader.SubclassWindow( GetHeaderCtrl()->GetSafeHwnd() ) );
  116. }
  117. void CListSortCtrl::RemoveAll()
  118. {
  119. DeleteAllItems();
  120. for ( int i = 0; i < m_AryList.GetSize(); i++)
  121. {
  122. m_AryList.ElementAt(i).RemoveAll();
  123. }
  124. m_AryList.RemoveAll();
  125. }
  126. /************************************************************************/
  127. /* 函数:[10/21/2016 IT];
  128. /* 描述:;
  129. /* 参数:;
  130. /* [IN] :;
  131. /* [OUT] :;
  132. /* [IN/OUT] :;
  133. /* 返回:void;
  134. /* 注意:最后一个参数,必须以NULL结尾(请看示例);
  135. /* 示例:CListSortCtrl::SetHeadings(_T("示例1,100"),_T("示例2,100"),NULL);
  136. /*
  137. /* 修改:;
  138. /* 日期:;
  139. /* 内容:;
  140. /************************************************************************/
  141. BOOL CListSortCtrl::SetHeadings( IN LPCTSTR pszText, ... )
  142. {
  143. if ( pszText == NULL ) return FALSE;
  144. va_list list;
  145. INT nCommaPos = 0; // 逗号位置;
  146. CString strColumn = _T("");
  147. va_start( list, pszText );
  148. do
  149. {
  150. strColumn = pszText;
  151. if ( -1 != (nCommaPos = strColumn.Find(_T(","))))
  152. {
  153. m_strSection += strColumn.Left(nCommaPos);
  154. if( InsertColumn( m_nNumColumns++, strColumn.Left(nCommaPos), LVCFMT_LEFT, _tstoi( strColumn.Mid( nCommaPos + 1) ) ) == -1 )
  155. {
  156. va_end( list );
  157. return FALSE;
  158. }
  159. }
  160. pszText = va_arg( list, LPCTSTR );
  161. } while (pszText != NULL);
  162. va_end( list );
  163. LoadColumnInfo();
  164. SetExtendedStyle(LVS_EX_FLATSB|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP);
  165. SetListFont(_T("宋体"), 11);
  166. return TRUE;
  167. }
  168. /************************************************************************/
  169. /* 函数:SetTextFont[3/6/2017 Jeff];
  170. /* 描述:设置文本字体;
  171. /* 参数:;
  172. /* [IN] nTextFontSize:字体大小;
  173. /* [IN] bBold:是否粗体;
  174. /* [IN] bItalic:是否斜体;
  175. /* [IN] strTextFontName:字体名称,如楷体;
  176. /* 返回:void;
  177. /* 注意:;
  178. /* 示例:;
  179. /*
  180. /* 修改:;
  181. /* 日期:;
  182. /* 内容:;
  183. /************************************************************************/
  184. void CListSortCtrl::SetListFont(IN CString strFontName, IN int nFontSize, IN BOOL bBold, IN BOOL bItalic)
  185. {
  186. LOGFONT lf;
  187. CClientDC dc(this);
  188. int dpy = GetDeviceCaps(dc, LOGPIXELSY); // Pixel per inch
  189. lf.lfHeight = -MulDiv(nFontSize, dpy, 72);
  190. lf.lfWeight = 0;
  191. lf.lfEscapement = 0;
  192. lf.lfOrientation = 0;
  193. if (bBold)
  194. lf.lfWeight = FW_BLACK;
  195. else
  196. lf.lfWeight = FW_NORMAL;
  197. lf.lfItalic = bItalic;
  198. lf.lfUnderline = FALSE;
  199. lf.lfStrikeOut = 0;
  200. lf.lfCharSet = ANSI_CHARSET;
  201. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  202. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  203. lf.lfQuality = DEFAULT_QUALITY;
  204. lf.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN;
  205. _tcscpy_s(lf.lfFaceName, strFontName);
  206. // 创建字体;
  207. //m_cfont = GetFont();// 局部变量会导致字体设置失败,必须是全局或成员变量;
  208. VERIFY(m_cfont.CreateFontIndirect(&lf));
  209. // 选入字体;
  210. this->SetFont(&m_cfont);
  211. }
  212. void CListSortCtrl::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)
  213. {
  214. // 不排序或无数据时退出;
  215. if ( !m_bSortSupport || m_AryList.GetSize() == 0)
  216. return;
  217. LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  218. m_bSortAscending = !m_bSortAscending;
  219. for (int i = 0; i < m_nNumColumns; i++)
  220. {
  221. if( i == pNMLV->iSubItem )
  222. {
  223. SortByCol(i);
  224. m_Ctrlheader.SetSortArrow( i, m_bSortAscending );
  225. }
  226. }
  227. Invalidate();
  228. *pResult = 0;
  229. }
  230. void CListSortCtrl::OnLvnGetdispinfo(NMHDR *pNMHDR, LRESULT *pResult)
  231. {
  232. NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
  233. LV_ITEM *pItem = &pDispInfo->item;
  234. ASSERT(pItem);
  235. if (m_AryList.GetSize() > pItem->iItem && (pItem->mask & LVIF_TEXT) )//valid text buffer?
  236. {
  237. //_tcscpy_s(pItem->pszText, pItem->cchTextMax, m_AryList.ElementAt(pItem->iItem).ElementAt(pItem->iSubItem));
  238. StringCbCopy(pItem->pszText, pItem->cchTextMax, m_AryList.ElementAt(pItem->iItem).ElementAt(pItem->iSubItem));
  239. }
  240. *pResult = 0;
  241. }
  242. #ifndef __LIST_DRAW__
  243. void CListSortCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
  244. {
  245. NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
  246. *pResult = 0;
  247. if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
  248. {
  249. *pResult = CDRF_NOTIFYITEMDRAW;
  250. }
  251. else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
  252. {
  253. INT npos = pLVCD->nmcd.dwItemSpec;
  254. if ( npos % 2 )
  255. pLVCD->clrTextBk = m_clrLightGrid;
  256. else
  257. pLVCD->clrTextBk = m_clrDarkGrid;
  258. *pResult = CDRF_DODEFAULT;
  259. }
  260. }
  261. #endif
  262. void CListSortCtrl::SortByCol(IN const int nColIndex)
  263. {
  264. m_nCompareColumn = nColIndex;
  265. ::AfxGetApp()->DoWaitCursor(TRUE);
  266. qsort( static_cast<void*>(&m_AryList[0]), m_AryList.GetSize(), sizeof(m_AryList[nColIndex]), CompareByLabel);
  267. ::AfxGetApp()->DoWaitCursor(FALSE);
  268. }
  269. void CListSortCtrl::LoadColumnInfo()
  270. {
  271. ASSERT( m_nNumColumns > 0 );
  272. UINT nBytes = 0;
  273. BYTE* buf = NULL;
  274. CMD5 md5;
  275. md5.SetBYTEText((BYTE*)m_strSection.GetString(), m_strSection.GetLength()*sizeof(TCHAR));
  276. m_strSection = md5.GetMD5Digest();
  277. if( AfxGetApp()->GetProfileBinary( _T("sortlist"), m_strSection, &buf, &nBytes ) )
  278. {
  279. if( nBytes > 0 )
  280. {
  281. CMemFile memFile( buf, nBytes );
  282. CArchive ar( &memFile, CArchive::load );
  283. m_Ctrlheader.Serialize( ar );
  284. ar.Close();
  285. m_Ctrlheader.Invalidate();
  286. }
  287. delete[] buf;
  288. }
  289. }
  290. void CListSortCtrl::SaveColumnInfo()
  291. {
  292. ASSERT( m_nNumColumns > 0 );
  293. CMemFile memFile;
  294. CArchive ar( &memFile, CArchive::store );
  295. m_Ctrlheader.Serialize( ar );
  296. ar.Close();
  297. DWORD dwLen = memFile.GetLength();
  298. BYTE* buf = memFile.Detach();
  299. VERIFY( AfxGetApp()->WriteProfileBinary( _T("sortlist"), m_strSection, buf, dwLen ) );
  300. free( buf );
  301. }
  302. void CListSortCtrl::OnDestroy()
  303. {
  304. SaveColumnInfo();
  305. CListCtrl::OnDestroy();
  306. }