SortListCtrl.cpp
上传用户:xuemeng126
上传日期:2022-07-05
资源大小:454k
文件大小:12k
源码类别:

系统编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "SortListCtrl.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #endif
  8. LPCTSTR g_pszSection = _T("ListCtrls");
  9. struct ItemData
  10. {
  11. public:
  12. ItemData() : arrpsz( NULL ), dwData( NULL ) {}
  13. LPTSTR* arrpsz;
  14. DWORD dwData;
  15. private:
  16. // ban copying.
  17. ItemData( const ItemData& );
  18. ItemData& operator=( const ItemData& );
  19. };
  20. CSortListCtrl::CSortListCtrl()
  21. : m_iNumColumns( 0 )
  22. , m_iSortColumn( -1 )
  23. , m_bSortAscending( TRUE )
  24. {
  25. }
  26. CSortListCtrl::~CSortListCtrl()
  27. {
  28. }
  29. BEGIN_MESSAGE_MAP(CSortListCtrl, CListCtrl)
  30. //{{AFX_MSG_MAP(CSortListCtrl)
  31. ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
  32. ON_WM_DESTROY()
  33. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
  34. //}}AFX_MSG_MAP
  35. END_MESSAGE_MAP()
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CSortListCtrl message handlers
  38. void CSortListCtrl::PreSubclassWindow()
  39. {
  40. // the list control must have the report style.
  41. ASSERT( GetStyle() & LVS_REPORT );
  42. CListCtrl::PreSubclassWindow();
  43. VERIFY( m_ctlHeader.SubclassWindow( GetHeaderCtrl()->GetSafeHwnd() ) );
  44. }
  45. BOOL CSortListCtrl::SetHeadings( UINT uiStringID )
  46. {
  47. CString strHeadings;
  48. VERIFY( strHeadings.LoadString( uiStringID ) );
  49. return SetHeadings( strHeadings );
  50. }
  51. // the heading text is in the format column 1 text,column 1 width;column 2 text,column 3 width;etc.
  52. BOOL CSortListCtrl::SetHeadings( const CString& strHeadings )
  53. {
  54. int iStart = 0;
  55. for( ;; )
  56. {
  57. const int iComma = strHeadings.Find( _T(','), iStart );
  58. if( iComma == -1 )
  59. break;
  60. const CString strHeading = strHeadings.Mid( iStart, iComma - iStart );
  61. iStart = iComma + 1;
  62. int iSemiColon = strHeadings.Find( _T(';'), iStart );
  63. if( iSemiColon == -1 )
  64. iSemiColon = strHeadings.GetLength();
  65. const int iWidth = atoi( strHeadings.Mid( iStart, iSemiColon - iStart ) );
  66. iStart = iSemiColon + 1;
  67. if( InsertColumn( m_iNumColumns++, strHeading, LVCFMT_LEFT, iWidth ) == -1 )
  68. return FALSE;
  69. }
  70. return TRUE;
  71. }
  72. int CSortListCtrl::AddItem( int j,LPCTSTR pszText, ... )
  73. {
  74. const int iIndex = InsertItem( GetItemCount(), pszText ,j);
  75. LPTSTR* arrpsz = new LPTSTR[ m_iNumColumns ];
  76. arrpsz[ 0 ] = new TCHAR[ lstrlen( pszText ) + 1 ];
  77. (void)lstrcpy( arrpsz[ 0 ], pszText );
  78.   va_list list;
  79. va_start( list, pszText );
  80. for( int iColumn = 1; iColumn < m_iNumColumns; iColumn++ )
  81. {
  82. pszText = va_arg( list, LPCTSTR );
  83. ASSERT_VALID_STRING( pszText );
  84. VERIFY( CListCtrl::SetItem( iIndex, iColumn, LVIF_TEXT, pszText, 0, 0, 0, 0 ) );
  85. arrpsz[ iColumn ] = new TCHAR[ lstrlen( pszText ) + 1 ];
  86. (void)lstrcpy( arrpsz[ iColumn ], pszText );
  87. }
  88. va_end( list );
  89. VERIFY( SetTextArray( iIndex, arrpsz ) );
  90. return iIndex;
  91. }
  92. void CSortListCtrl::FreeItemMemory( const int iItem )
  93. {
  94. ItemData* pid = reinterpret_cast<ItemData*>( CListCtrl::GetItemData( iItem ) );
  95. LPTSTR* arrpsz = pid->arrpsz;
  96. for( int i = 0; i < m_iNumColumns; i++ )
  97. delete[] arrpsz[ i ];
  98. delete[] arrpsz;
  99. delete pid;
  100. VERIFY( CListCtrl::SetItemData( iItem, NULL ) );
  101. }
  102. BOOL CSortListCtrl::DeleteItem( int iItem )
  103. {
  104. FreeItemMemory( iItem );
  105. return CListCtrl::DeleteItem( iItem );
  106. }
  107. BOOL CSortListCtrl::DeleteAllItems()
  108. {
  109. for( int iItem = 0; iItem < GetItemCount(); iItem ++ )
  110. FreeItemMemory( iItem );
  111. return CListCtrl::DeleteAllItems();
  112. }
  113. bool IsNumber( LPCTSTR pszText )
  114. {
  115. ASSERT_VALID_STRING( pszText );
  116. for( int i = 0; i < lstrlen( pszText ); i++ )
  117. if( !_istdigit( pszText[ i ] ) )
  118. return false;
  119. return true;
  120. }
  121. int NumberCompare( LPCTSTR pszNumber1, LPCTSTR pszNumber2 )
  122. {
  123. ASSERT_VALID_STRING( pszNumber1 );
  124. ASSERT_VALID_STRING( pszNumber2 );
  125. const int iNumber1 = atoi( pszNumber1 );
  126. const int iNumber2 = atoi( pszNumber2 );
  127. if( iNumber1 < iNumber2 )
  128. return -1;
  129. if( iNumber1 > iNumber2 )
  130. return 1;
  131. return 0;
  132. }
  133. bool IsDate( LPCTSTR pszText )
  134. {
  135. ASSERT_VALID_STRING( pszText );
  136. // format should be 99/99/9999.
  137. if( lstrlen( pszText ) != 10 )
  138. return false;
  139. return _istdigit( pszText[ 0 ] )
  140. && _istdigit( pszText[ 1 ] )
  141. && pszText[ 2 ] == _T('/')
  142. && _istdigit( pszText[ 3 ] )
  143. && _istdigit( pszText[ 4 ] )
  144. && pszText[ 5 ] == _T('/')
  145. && _istdigit( pszText[ 6 ] )
  146. && _istdigit( pszText[ 7 ] )
  147. && _istdigit( pszText[ 8 ] )
  148. && _istdigit( pszText[ 9 ] );
  149. }
  150. int DateCompare( const CString& strDate1, const CString& strDate2 )
  151. {
  152. const int iYear1 = atoi( strDate1.Mid( 6, 4 ) );
  153. const int iYear2 = atoi( strDate2.Mid( 6, 4 ) );
  154. if( iYear1 < iYear2 )
  155. return -1;
  156. if( iYear1 > iYear2 )
  157. return 1;
  158. const int iMonth1 = atoi( strDate1.Mid( 3, 2 ) );
  159. const int iMonth2 = atoi( strDate2.Mid( 3, 2 ) );
  160. if( iMonth1 < iMonth2 )
  161. return -1;
  162. if( iMonth1 > iMonth2 )
  163. return 1;
  164. const int iDay1 = atoi( strDate1.Mid( 0, 2 ) );
  165. const int iDay2 = atoi( strDate2.Mid( 0, 2 ) );
  166. if( iDay1 < iDay2 )
  167. return -1;
  168. if( iDay1 > iDay2 )
  169. return 1;
  170. return 0;
  171. }
  172. int CALLBACK CSortListCtrl::CompareFunction( LPARAM lParam1, LPARAM lParam2, LPARAM lParamData )
  173. {
  174. CSortListCtrl* pListCtrl = reinterpret_cast<CSortListCtrl*>( lParamData );
  175. ASSERT( pListCtrl->IsKindOf( RUNTIME_CLASS( CListCtrl ) ) );
  176. ItemData* pid1 = reinterpret_cast<ItemData*>( lParam1 );
  177. ItemData* pid2 = reinterpret_cast<ItemData*>( lParam2 );
  178. ASSERT( pid1 );
  179. ASSERT( pid2 );
  180. LPCTSTR pszText1 = pid1->arrpsz[ pListCtrl->m_iSortColumn ];
  181. LPCTSTR pszText2 = pid2->arrpsz[ pListCtrl->m_iSortColumn ];
  182. ASSERT_VALID_STRING( pszText1 );
  183. ASSERT_VALID_STRING( pszText2 );
  184. if( IsNumber( pszText1 ) )
  185. return pListCtrl->m_bSortAscending ? NumberCompare( pszText1, pszText2 ) : NumberCompare( pszText2, pszText1 );
  186. else if( IsDate( pszText1 ) )
  187. return pListCtrl->m_bSortAscending ? DateCompare( pszText1, pszText2 ) : DateCompare( pszText2, pszText1 );
  188. else
  189. // text.
  190. return pListCtrl->m_bSortAscending ? lstrcmp( pszText1, pszText2 ) : lstrcmp( pszText2, pszText1 );
  191. }
  192. void CSortListCtrl::OnColumnClick( NMHDR* pNMHDR, LRESULT* pResult )
  193. {
  194. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  195. const int iColumn = pNMListView->iSubItem;
  196. // if it's a second click on the same column then reverse the sort order,
  197. // otherwise sort the new column in ascending order.
  198. Sort( iColumn, iColumn == m_iSortColumn ? !m_bSortAscending : TRUE );
  199. *pResult = 0;
  200. }
  201. void CSortListCtrl::Sort( int iColumn, BOOL bAscending )
  202. {
  203. m_iSortColumn = iColumn;
  204. m_bSortAscending = bAscending;
  205. // show the appropriate arrow in the header control.
  206. m_ctlHeader.SetSortArrow( m_iSortColumn, m_bSortAscending );
  207. VERIFY( SortItems( CompareFunction, reinterpret_cast<DWORD>( this ) ) );
  208. }
  209. void CSortListCtrl::LoadColumnInfo()
  210. {
  211. // you must call this after setting the column headings.
  212. ASSERT( m_iNumColumns > 0 );
  213. CString strKey;
  214. strKey.Format( _T("%d"), GetDlgCtrlID() );
  215. UINT nBytes = 0;
  216. BYTE* buf = NULL;
  217. if( AfxGetApp()->GetProfileBinary( g_pszSection, strKey, &buf, &nBytes ) )
  218. {
  219. if( nBytes > 0 )
  220. {
  221. CMemFile memFile( buf, nBytes );
  222. CArchive ar( &memFile, CArchive::load );
  223. m_ctlHeader.Serialize( ar );
  224. ar.Close();
  225. m_ctlHeader.Invalidate();
  226. }
  227. delete[] buf;
  228. }
  229. }
  230. void CSortListCtrl::SaveColumnInfo()
  231. {
  232. ASSERT( m_iNumColumns > 0 );
  233. CString strKey;
  234. strKey.Format( _T("%d"), GetDlgCtrlID() );
  235. CMemFile memFile;
  236. CArchive ar( &memFile, CArchive::store );
  237. m_ctlHeader.Serialize( ar );
  238. ar.Close();
  239. DWORD dwLen = memFile.GetLength();
  240. BYTE* buf = memFile.Detach();
  241. VERIFY( AfxGetApp()->WriteProfileBinary( g_pszSection, strKey, buf, dwLen ) );
  242. free( buf );
  243. }
  244. void CSortListCtrl::OnDestroy() 
  245. {
  246. for( int iItem = 0; iItem < GetItemCount(); iItem ++ )
  247. FreeItemMemory( iItem );
  248. CListCtrl::OnDestroy();
  249. }
  250. BOOL CSortListCtrl::SetItemText( int nItem, int nSubItem, LPCTSTR lpszText )
  251. {
  252. if( !CListCtrl::SetItemText( nItem, nSubItem, lpszText ) )
  253. return FALSE;
  254. LPTSTR* arrpsz = GetTextArray( nItem );
  255. LPTSTR pszText = arrpsz[ nSubItem ];
  256. delete[] pszText;
  257. pszText = new TCHAR[ lstrlen( lpszText ) + 1 ];
  258. (void)lstrcpy( pszText, lpszText );
  259. arrpsz[ nSubItem ] = pszText;
  260. return TRUE;
  261. }
  262. BOOL CSortListCtrl::SetItemData( int nItem, DWORD dwData )
  263. {
  264. if( nItem >= GetItemCount() )
  265. return FALSE;
  266. ItemData* pid = reinterpret_cast<ItemData*>( CListCtrl::GetItemData( nItem ) );
  267. ASSERT( pid );
  268. pid->dwData = dwData;
  269. return TRUE;
  270. }
  271. DWORD CSortListCtrl::GetItemData( int nItem ) const
  272. {
  273. ASSERT( nItem < GetItemCount() );
  274. ItemData* pid = reinterpret_cast<ItemData*>( CListCtrl::GetItemData( nItem ) );
  275. ASSERT( pid );
  276. return pid->dwData;
  277. }
  278. BOOL CSortListCtrl::SetTextArray( int iItem, LPTSTR* arrpsz )
  279. {
  280. ASSERT( CListCtrl::GetItemData( iItem ) == NULL );
  281. ItemData* pid = new ItemData;
  282. pid->arrpsz = arrpsz;
  283. return CListCtrl::SetItemData( iItem, reinterpret_cast<DWORD>( pid ) );
  284. }
  285. LPTSTR* CSortListCtrl::GetTextArray( int iItem ) const
  286. {
  287. ASSERT( iItem < GetItemCount() );
  288. ItemData* pid = reinterpret_cast<ItemData*>( CListCtrl::GetItemData( iItem ) );
  289. return pid->arrpsz;
  290. }
  291. //  hook_API_info[hook_num++].nativeAPIname="NtRestoreKey";
  292. //  hook_API_info[hook_num++].nativeAPIname="NtOpenKey";
  293. //  hook_API_info[hook_num++].nativeAPIname="NtCreateKey";
  294. //  hook_API_info[hook_num++].nativeAPIname="NtQueryValueKey";
  295. //  hook_API_info[hook_num++].nativeAPIname="NtQueryKey";
  296. //  hook_API_info[hook_num++].nativeAPIname="NtDeleteKey";
  297. //  hook_API_info[hook_num++].nativeAPIname="NtDeleteValueKey";
  298. //  hook_API_info[hook_num++].nativeAPIname="NtSetValueKey";
  299. //  hook_API_info[hook_num++].nativeAPIname="NtEnumerateKey";
  300. //  hook_API_info[hook_num++].nativeAPIname="NtEnumerateValueKey";
  301. //  hook_API_info[hook_num++].nativeAPIname="NtOpenFile";
  302. //  hook_API_info[hook_num++].nativeAPIname="NtWriteFile";
  303. //  hook_API_info[hook_num++].nativeAPIname="NtCreateFile";
  304. //  hook_API_info[hook_num++].nativeAPIname="NtCreateProcess";
  305. //  hook_API_info[hook_num++].nativeAPIname="NtCreateProcessEx";
  306. //  hook_API_info[hook_num++].nativeAPIname="NtCreateSection";
  307. //  hook_API_info[hook_num++].nativeAPIname="NtOpenThread";
  308. //  hook_API_info[hook_num++].nativeAPIname="NtCreateThread";
  309. //  hook_API_info[hook_num++].nativeAPIname="NtOpenProcess";
  310. //  hook_API_info[hook_num++].nativeAPIname="NtOpenSection";
  311. //  hook_API_info[hook_num++].nativeAPIname="NtCreateSymbolicLinkObject";
  312. //  hook_API_info[hook_num++].nativeAPIname="NtSetSystemTime";
  313. void GetRowColor(char * NativeAPIName,COLORREF *pclrBk,COLORREF *pclrTxt)
  314. {
  315. CString funname=CString(NativeAPIName);
  316. if(funname.Find("Key")==funname.GetLength()-3)
  317. {
  318. *pclrBk=RGB(255,255,255);
  319. *pclrTxt=RGB(0x00,0x33,0xff);
  320. return;
  321. }
  322. if(funname.Find("File")==funname.GetLength()-4)
  323. {
  324. *pclrBk=RGB(255,255,255);
  325. *pclrTxt=RGB(0xcc,0x00,0xff);
  326. return;
  327. }
  328. if(funname.Find("Thread")==funname.GetLength()-6 
  329. || funname.Find("Process")==funname.GetLength()-7 
  330. || funname.Find("ProcessEx")==funname.GetLength()-9)
  331. {
  332. *pclrBk=RGB(255,255,255);
  333. *pclrTxt=RGB(0xff,0x00,0x00);
  334. return;
  335. }
  336. if(funname.Find("Section")==funname.GetLength()-7)
  337. {
  338. *pclrBk=RGB(255,255,255);
  339. *pclrTxt=RGB(0xff,0x33,0x00);
  340. return;
  341. }
  342. *pclrBk=RGB(255,255,255);
  343. *pclrTxt=RGB(0,0,0);
  344. }
  345. void CSortListCtrl::OnCustomDraw(NMHDR   *pnotify,   LRESULT   *result)   
  346. {                 
  347. LPNMLVCUSTOMDRAW     lplvcd   =   (LPNMLVCUSTOMDRAW)pnotify;   
  348. char NativeAPIName[32];
  349. if(lplvcd->nmcd.dwDrawStage   ==   CDDS_PREPAINT)       
  350. *result   =     CDRF_NOTIFYITEMDRAW;     
  351. if(lplvcd->nmcd.dwDrawStage   ==   CDDS_ITEMPREPAINT){   
  352. int   nItem=(int)(lplvcd->nmcd.dwItemSpec);   
  353. COLORREF   clrBk,clrTxt;     
  354. this->GetItemText(nItem,3,NativeAPIName,32);
  355. GetRowColor(NativeAPIName,&clrBk,&clrTxt);
  356. lplvcd->clrText   =   clrTxt;   
  357. lplvcd->clrTextBk   =   clrBk;     
  358. *result   =   CDRF_DODEFAULT;                       
  359. }     
  360. }