ListCtrlEx.cpp
上传用户:lyghuaxia
上传日期:2007-01-02
资源大小:8k
文件大小:19k
源码类别:

ListView/ListBox

开发平台:

Visual C++

  1. // ListCtrlEx.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #undef THIS_FILE
  7. static char THIS_FILE[] = __FILE__;
  8. #endif
  9. /////////////////////////////////////////////////////////////////////////////
  10. // CHeaderCtrlEx
  11. CHeaderCtrlEx::CHeaderCtrlEx()
  12. : marker_rect(0,0,0,0)
  13. {
  14. m_pWidth = NULL;
  15. m_bDragging = FALSE;
  16. m_bCheckForDrag = FALSE;
  17. m_fpDragCol = NULL;
  18. m_pOwnerWnd = NULL;
  19. m_bDragEnable = false;
  20. }
  21. CHeaderCtrlEx::CHeaderCtrlEx(CWnd *pWnd, void (CWnd::*fpDragCol)(int, int))
  22. : marker_rect(0,0,0,0)
  23. {
  24. m_pWidth = NULL;
  25. m_bDragging = FALSE;
  26. m_bCheckForDrag = FALSE;
  27. m_fpDragCol = fpDragCol;
  28. m_pOwnerWnd = pWnd;
  29. m_bDragEnable = false;
  30. }
  31. CHeaderCtrlEx::~CHeaderCtrlEx()
  32. {
  33. }
  34. BEGIN_MESSAGE_MAP(CHeaderCtrlEx, CHeaderCtrl)
  35. //{{AFX_MSG_MAP(CHeaderCtrlEx)
  36. ON_WM_MOUSEMOVE()
  37. ON_WM_LBUTTONUP()
  38. ON_WM_LBUTTONDOWN()
  39. //}}AFX_MSG_MAP
  40. END_MESSAGE_MAP()
  41. /////////////////////////////////////////////////////////////////////////////
  42. // Public Properties
  43. //
  44. // EnableDrag(bool bDrag=true): Enable or disable column header dragging
  45. //
  46. /////////////////////////////////////////////////////////////////////////////
  47. bool CHeaderCtrlEx::EnableDrag(bool bDrag)
  48. {
  49. bool bOld = m_bDragEnable;
  50. m_bDragEnable = bDrag;
  51. return bOld;
  52. }
  53. //End Properties
  54. /////////////////////////////////////////////////////////////////////////////
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CHeaderCtrlEx message handlers
  57. void CHeaderCtrlEx::OnMouseMove(UINT nFlags, CPoint point)
  58. {
  59. if(m_bDragEnable) {
  60. if( (MK_LBUTTON & nFlags) == 0) {
  61. // The left mouse button is not pressed - so reset flags
  62. m_bCheckForDrag = FALSE;
  63. m_bDragging = FALSE;
  64. }
  65. else if( m_bDragging ) {
  66. // Get column number that falls under the mouse
  67. int i=0, cx = 0;
  68. if( point.x > 0 )
  69. for( i = 0; i < GetItemCount(); i++ ) {
  70. if( point.x >= cx && point.x < cx + m_pWidth[i] )
  71. break;
  72. cx += m_pWidth[i];
  73. }
  74. if( i != m_nDropPos ) {
  75. m_nDropPos = i;
  76. CRect rect;
  77. GetWindowRect( &rect );
  78. // Invalidate area occupied by previous marker
  79. InvalidateRect( &marker_rect );
  80. // Draw a new marker
  81. CClientDC dc(this);
  82. POINT pts[3];
  83. pts[0].x = cx;
  84. pts[1].x = cx - rect.Height()/4;
  85. pts[2].x = cx + rect.Height()/4;
  86. pts[0].y = rect.Height();
  87. pts[1].y = pts[2].y = rect.Height()/2;
  88. dc.Polygon( pts, 3 );
  89. // save marker information
  90. marker_rect.left = cx - (rect.Height()/4 + 1);
  91. marker_rect.top = rect.Height() - (rect.Height()/2 + 1);
  92. marker_rect.right = cx + (rect.Height()/4 + 1);
  93. marker_rect.bottom = rect.Height() + 1;
  94. }
  95. return;
  96. }
  97. else if( m_bCheckForDrag ) {
  98. // The mouse button was pressed over a column header
  99. // and now the mouse has moved - so start drag
  100. m_bCheckForDrag = FALSE;
  101. m_bDragging = TRUE;
  102. m_nDropPos = m_nDragCol;
  103. SetCapture();
  104. // Store information for later use
  105. int iCount = GetItemCount();
  106. HD_ITEM hd_item;
  107. m_pWidth = new int[iCount];
  108. for( int i = 0; i < iCount; i++ ) {
  109. hd_item.mask = HDI_WIDTH;
  110. GetItem( i, &hd_item );
  111. m_pWidth[i] = hd_item.cxy;
  112. }
  113. return;
  114. }
  115. }
  116. CHeaderCtrl::OnMouseMove(nFlags, point);
  117. }
  118. void CHeaderCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
  119. {
  120. if(m_bDragEnable) {
  121. // Determine if mouse was pressed over a column header
  122. HD_HITTESTINFO hd_hittestinfo;
  123. hd_hittestinfo.pt = point;
  124. SendMessage(HDM_HITTEST, 0, (LPARAM)(&hd_hittestinfo));
  125. if( hd_hittestinfo.flags == HHT_ONHEADER ) {
  126. m_nDragCol = hd_hittestinfo.iItem;
  127. m_bCheckForDrag = TRUE;
  128. }
  129. }
  130. CHeaderCtrl::OnLButtonDown(nFlags, point);
  131. }
  132. void CHeaderCtrlEx::OnLButtonUp(UINT nFlags, CPoint point)
  133. {
  134. if(m_bDragEnable) {
  135. ASSERT( m_pOwnerWnd != NULL && m_fpDragCol != NULL );
  136. if( m_bDragging ) {
  137. m_bDragging = FALSE;
  138. delete[] m_pWidth;
  139. ReleaseCapture();
  140. Invalidate();
  141. // Call the callback function.
  142. if( m_nDragCol != m_nDropPos && m_nDragCol != m_nDropPos -1 )
  143. (m_pOwnerWnd->*m_fpDragCol)( m_nDragCol, m_nDropPos );
  144. }
  145. }
  146. CHeaderCtrl::OnLButtonUp(nFlags, point);
  147. }
  148. void CHeaderCtrlEx::SetCallback( CWnd* pWnd, void (CWnd::*fpDragCol)(int, int) )
  149. {
  150. m_fpDragCol = fpDragCol;
  151. m_pOwnerWnd = pWnd;
  152. }
  153. //End CHeaderCtrlEx
  154. /////////////////////////////////////////////////////////////////////////////
  155. /////////////////////////////////////////////////////////////////////////////
  156. // CListCtrlEx
  157. //Constructor for the list data structure
  158. CListCtrlEx::ListData::ListData(const DWORD dwOld, const CString &strTxt, const COleDateTime Start)
  159. {
  160. dwOldData = dwOld;
  161. strText = strTxt;
  162. BaseTime = Start;
  163. }
  164. CListCtrlEx::CListCtrlEx()
  165. {
  166. nSortedCol = -1; 
  167. bSortAscending = TRUE;
  168. m_nNumCols = 0;
  169. m_pTypes = NULL;
  170. m_ctStart.SetStatus(COleDateTime::invalid);
  171. m_bSort = false;
  172. m_nHighlight = HIGHLIGHT_NORMAL;
  173. m_headerctrl.SetCallback( this, (void (CWnd::*)(int, int))DragColumn );
  174. }
  175. CListCtrlEx::~CListCtrlEx()
  176. {
  177. delete m_pTypes;
  178. }
  179. BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
  180. //{{AFX_MSG_MAP(CListCtrlEx)
  181. ON_WM_PAINT()
  182. ON_WM_SETFOCUS()
  183. ON_WM_KILLFOCUS()
  184. ON_WM_LBUTTONDOWN()
  185. ON_WM_LBUTTONUP()
  186. ON_WM_MOUSEMOVE()
  187. //}}AFX_MSG_MAP
  188. ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked) 
  189. ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
  190. END_MESSAGE_MAP()
  191. /////////////////////////////////////////////////////////////////////////////
  192. //Public Properties
  193. //
  194. // SetHighlightType(int hilite): Set highlight type
  195. // EnableSort(bool bSort=true): Enable sorting by column
  196. // SetColumnTypes(unsigned char* pColTypes, unsigned nColCnt):
  197. // Set the column sort types
  198. // EnableHeaderDrag(bool bDrag=true}: Enable column header dragging
  199. // SetBaseTime(CString strTime): Set the base time for 24hr clock
  200. //
  201. /////////////////////////////////////////////////////////////////////////////
  202. int CListCtrlEx::SetHighlightType(int hilite)
  203. {
  204. int oldhilite = m_nHighlight;
  205. if( hilite <= HIGHLIGHT_ROW )
  206. {
  207. m_nHighlight = hilite;
  208. //set to ownerdraw for full row highlighting
  209. if(hilite > HIGHLIGHT_NORMAL)
  210. ModifyStyle(0, LVS_OWNERDRAWFIXED);
  211. Invalidate();
  212. }
  213. return oldhilite;
  214. }
  215. bool CListCtrlEx::EnableSort(bool bSort)
  216. {
  217. bool bOldSort = m_bSort;
  218. m_bSort = bSort;
  219. return bOldSort;
  220. }
  221. bool CListCtrlEx::SetColumnTypes(unsigned char* pColTypes, unsigned nColCnt)
  222. {
  223. delete m_pTypes;
  224. m_pTypes = new unsigned char[nColCnt];
  225. if(m_pTypes == NULL) {
  226. m_nNumCols = 0;
  227. return false;
  228. }
  229. for(unsigned i=0; i<nColCnt; i++) {
  230. if(pColTypes[i] > LVEX_LAST) {
  231. m_nNumCols = 0;
  232. delete m_pTypes;
  233. return false;
  234. }
  235. m_pTypes[i] = pColTypes[i];
  236. }
  237. m_nNumCols = nColCnt;
  238. return true;
  239. }
  240. bool CListCtrlEx::EnableHeaderDrag(bool bDrag)
  241. {
  242. return m_headerctrl.EnableDrag(bDrag);
  243. }
  244. bool CListCtrlEx::SetBaseTime(CString strTime)
  245. {
  246. COleDateTime ctNew;
  247. //there can only be one base time for all columns
  248. //this function should only be called once
  249. ASSERT(m_ctStart.GetStatus() == COleDateTime::invalid);
  250. ctNew.ParseDateTime(strTime);
  251. if(ctNew.GetStatus() != COleDateTime::invalid) {
  252. m_ctStart = ctNew;
  253. return true;
  254. }
  255. return false;
  256. }
  257. //End Properties
  258. /////////////////////////////////////////////////////////////////////////////
  259. /////////////////////////////////////////////////////////////////////////////
  260. // Highlighting
  261. //
  262. /////////////////////////////////////////////////////////////////////////////
  263. void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  264. {
  265. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  266. CRect rcItem(lpDrawItemStruct->rcItem);
  267. int nItem = lpDrawItemStruct->itemID;
  268. CImageList* pImageList; // Save dc state
  269. int nSavedDC = pDC->SaveDC();
  270. CBrush WndBrush(::GetSysColor(COLOR_WINDOW));
  271. CBrush HltBrush(::GetSysColor(COLOR_HIGHLIGHT));
  272. // Get item image and state info
  273. LV_ITEM lvi;
  274. lvi.mask = LVIF_IMAGE | LVIF_STATE;
  275. lvi.iItem = nItem;
  276. lvi.iSubItem = 0;
  277. lvi.stateMask = 0xFFFF; // get all state flags
  278. GetItem(&lvi);
  279. // Should the item be highlighted
  280. BOOL bHighlight =((lvi.state & LVIS_DROPHILITED)
  281. || ( (lvi.state & LVIS_SELECTED)
  282. && ((GetFocus() == this)
  283. || (GetStyle() & LVS_SHOWSELALWAYS))));
  284. // Get rectangles for drawing
  285. CRect rcBounds, rcLabel, rcIcon;
  286. GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
  287. GetItemRect(nItem, rcLabel, LVIR_LABEL);
  288. GetItemRect(nItem, rcIcon, LVIR_ICON);
  289. CRect rcCol( rcBounds ); 
  290. CString sLabel = GetItemText( nItem, 0 );
  291. // Labels are offset by a certain amount  
  292. // This offset is related to the width of a space character
  293. int offset = pDC->GetTextExtent(_T(" "), 1 ).cx*2;
  294. CRect rcHighlight;
  295. CRect rcWnd;
  296. int nExt;
  297. switch(m_nHighlight) {
  298. case HIGHLIGHT_NORMAL: 
  299. nExt = pDC->GetOutputTextExtent(sLabel).cx + offset;
  300. rcHighlight = rcLabel;
  301. if( rcLabel.left + nExt < rcLabel.right )
  302. rcHighlight.right = rcLabel.left + nExt;
  303. break;
  304. case HIGHLIGHT_ALLCOLUMNS:
  305. rcHighlight = rcBounds;
  306. rcHighlight.left = rcLabel.left;
  307. break;
  308. case HIGHLIGHT_ROW:
  309. GetClientRect(&rcWnd);
  310. rcHighlight = rcBounds;
  311. rcHighlight.left = rcLabel.left;
  312. rcHighlight.right = rcWnd.right;
  313. break;
  314. default:
  315. rcHighlight = rcLabel;
  316. }
  317. // Draw the background color
  318. if( bHighlight ) {
  319. pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  320. pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
  321. pDC->FillRect(rcHighlight, &HltBrush);
  322. }
  323. else
  324. pDC->FillRect(rcHighlight, &WndBrush);
  325. // Set clip region
  326. rcCol.right = rcCol.left + GetColumnWidth(0);
  327. CRgn rgn;
  328. rgn.CreateRectRgnIndirect(&rcCol);
  329. pDC->SelectClipRgn(&rgn);
  330. rgn.DeleteObject();
  331. // Draw state icon
  332. if (lvi.state & LVIS_STATEIMAGEMASK) {
  333. int nImage = ((lvi.state & LVIS_STATEIMAGEMASK)>>12) - 1;
  334. pImageList = GetImageList(LVSIL_STATE);
  335. if (pImageList) {
  336. pImageList->Draw(pDC, nImage,
  337. CPoint(rcCol.left, rcCol.top), ILD_TRANSPARENT);
  338. }
  339. }
  340. // Draw normal and overlay icon
  341. pImageList = GetImageList(LVSIL_SMALL);
  342. if (pImageList) {
  343. UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK;
  344. pImageList->Draw(pDC, lvi.iImage, 
  345. CPoint(rcIcon.left, rcIcon.top),
  346. (bHighlight?ILD_BLEND50:0) | ILD_TRANSPARENT | nOvlImageMask );
  347. }
  348. // Draw item label - Column 0
  349. rcLabel.left += offset/2;
  350. rcLabel.right -= offset;
  351. pDC->DrawText(sLabel,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP 
  352. | DT_VCENTER | DT_END_ELLIPSIS);
  353. // Draw labels for remaining columns
  354. LV_COLUMN lvc;
  355. lvc.mask = LVCF_FMT | LVCF_WIDTH;
  356. if(m_nHighlight == HIGHLIGHT_NORMAL) // Highlight only first column
  357. {
  358. pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
  359. pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
  360. }
  361. rcBounds.right = rcHighlight.right > rcBounds.right ? rcHighlight.right :
  362. rcBounds.right; rgn.CreateRectRgnIndirect(&rcBounds);
  363. pDC->SelectClipRgn(&rgn);    
  364. for(int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++) {
  365. rcCol.left = rcCol.right;
  366. rcCol.right += lvc.cx;
  367. // Draw the background if needed
  368. if( m_nHighlight == HIGHLIGHT_NORMAL )
  369. pDC->FillRect(rcCol, &HltBrush);
  370. sLabel = GetItemText(nItem, nColumn);
  371. if (sLabel.GetLength() == 0)
  372. continue;
  373. // Get the text justification
  374. UINT nJustify = DT_LEFT;
  375. switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
  376. {
  377. case LVCFMT_RIGHT:
  378. nJustify = DT_RIGHT;
  379. break;
  380. case LVCFMT_CENTER:
  381. nJustify = DT_CENTER;
  382. break;
  383. default:
  384. break;
  385. }
  386. rcLabel = rcCol;
  387. rcLabel.left += offset;
  388. rcLabel.right -= offset;
  389. pDC->DrawText(sLabel, -1, rcLabel, nJustify | DT_SINGLELINE | 
  390. DT_NOPREFIX | DT_VCENTER | DT_END_ELLIPSIS);
  391. }
  392. // Draw focus rectangle if item has focus
  393. if (lvi.state & LVIS_FOCUSED && (GetFocus() == this))
  394. pDC->DrawFocusRect(rcHighlight);
  395. // Restore dc
  396. pDC->RestoreDC( nSavedDC );
  397. WndBrush.DeleteObject();
  398. HltBrush.DeleteObject();
  399. }
  400. void CListCtrlEx::OnPaint() 
  401. {
  402. // in full row select mode, we need to extend the clipping region
  403. // so we can paint a selection all the way to the right
  404. if (m_nHighlight == HIGHLIGHT_ROW &&
  405. (GetStyle() & LVS_TYPEMASK) == LVS_REPORT ) {
  406. CRect rcBounds;
  407. GetItemRect(0, rcBounds, LVIR_BOUNDS);
  408. CRect rcClient;
  409. GetClientRect(&rcClient);
  410. if(rcBounds.right < rcClient.right) {
  411. CPaintDC dc(this);
  412. CRect rcClip;
  413. dc.GetClipBox(rcClip);
  414. rcClip.left = min(rcBounds.right-1, rcClip.left);
  415. rcClip.right = rcClient.right;
  416. InvalidateRect(rcClip, FALSE);
  417. }
  418. }
  419. CListCtrl::OnPaint();
  420. }
  421. void CListCtrlEx::OnSetFocus(CWnd* pOldWnd) 
  422. {
  423. CListCtrl::OnSetFocus(pOldWnd);
  424. // check if we are getting focus from label edit box
  425. if(pOldWnd!=NULL && pOldWnd->GetParent()==this)
  426. return;
  427. // repaint items that should change appearance
  428. if((GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
  429. RepaintSelectedItems();
  430. }
  431. void CListCtrlEx::OnKillFocus(CWnd* pNewWnd) 
  432. {
  433. CListCtrl::OnKillFocus(pNewWnd);
  434. // check if we are losing focus to label edit box
  435. if(pNewWnd != NULL && pNewWnd->GetParent() == this)
  436. return;
  437. // repaint items that should change appearance
  438. if((GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
  439. RepaintSelectedItems();
  440. }
  441. void CListCtrlEx::RepaintSelectedItems()
  442. {
  443. CRect rcBounds, rcLabel;
  444. // Invalidate focused item so it can repaint 
  445. int nItem = GetNextItem(-1, LVNI_FOCUSED);
  446. if(nItem != -1)
  447. {
  448. GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
  449. GetItemRect(nItem, rcLabel, LVIR_LABEL);
  450. rcBounds.left = rcLabel.left;
  451. InvalidateRect(rcBounds, FALSE);
  452. }
  453. // Invalidate selected items depending on LVS_SHOWSELALWAYS
  454. if(!(GetStyle() & LVS_SHOWSELALWAYS))
  455. {
  456. for(nItem = GetNextItem(-1, LVNI_SELECTED);
  457. nItem != -1; nItem = GetNextItem(nItem, LVNI_SELECTED))
  458. {
  459. GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
  460. GetItemRect(nItem, rcLabel, LVIR_LABEL);
  461. rcBounds.left = rcLabel.left;
  462. InvalidateRect(rcBounds, FALSE);
  463. }
  464. }
  465. UpdateWindow();
  466. }
  467. //places check marks in state icon boxes when clicked
  468. void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point) 
  469. {
  470. UINT uFlags = 0;
  471. int nHitItem = HitTest(point, &uFlags);
  472. BOOL bHit = FALSE;
  473. if (uFlags & LVHT_ONITEMSTATEICON)
  474. bHit = TRUE;
  475. if (bHit) {
  476. UINT nState = GetItemState(nHitItem, LVIS_STATEIMAGEMASK);
  477. if(nState == INDEXTOSTATEIMAGEMASK(1))
  478. SetItemState(nHitItem, INDEXTOSTATEIMAGEMASK(2), LVIS_STATEIMAGEMASK);
  479. else
  480. SetItemState(nHitItem, INDEXTOSTATEIMAGEMASK(1), LVIS_STATEIMAGEMASK);
  481. }
  482. CListCtrl::OnLButtonDown(nFlags, point);
  483. }
  484. //End Hilighting
  485. //////////////////////////////////////////////////////////////////////
  486. //////////////////////////////////////////////////////////////////////
  487. //Sorting by columns
  488. //
  489. //////////////////////////////////////////////////////////////////////
  490. void CListCtrlEx::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
  491. {
  492. HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
  493. if(phdn->iButton == 0 && m_bSort)// Button is the left mouse button 
  494. {
  495. // User clicked on header using left mouse button
  496. if(phdn->iItem == nSortedCol)
  497. bSortAscending = !bSortAscending;
  498. else
  499. bSortAscending = TRUE;
  500. nSortedCol = phdn->iItem;
  501. int NumItems = GetItemCount();
  502. // replace Item data with pointer to ListData structure
  503. for (int i = 0; i < NumItems; i++) {
  504. DWORD dwData = GetItemData(i); // save current data to restore it later
  505. CString strText = GetItemText(i, nSortedCol);
  506. SetItemData(i, (DWORD)new ListData(dwData, strText, m_ctStart));
  507. }
  508. SortItems(Compare, bSortAscending | (m_pTypes[nSortedCol] << 8));
  509. for(i=0; i<NumItems; i++) {
  510. ListData* pData = (ListData*)GetItemData(i);
  511. SetItemData(i, pData->dwOldData);
  512. delete pData;
  513. }
  514. }
  515. *pResult = 0;
  516. }
  517. int CALLBACK CListCtrlEx::Compare(LPARAM lParam1, LPARAM lParam2, LPARAM 
  518.  lParSortAsc)
  519. {
  520. CString str1 = ((ListData*)lParam1)->strText;
  521. CString str2 = ((ListData*)lParam2)->strText;
  522. unsigned char Type = unsigned char(lParSortAsc >> 8);
  523. // restore data type and sort order from lParamSort
  524. // if lParamSort positive - ascending sort order, negative - descending
  525. int  sOrder = (lParSortAsc & 0xFF) ? 1 : -1; 
  526. COleDateTime t1, t2, bTime = ((ListData*)lParam1)->BaseTime;
  527. switch (Type) {
  528. //Date time column(s) with 24 hr base time
  529. case  LVEX_TIME_BASE://most people will never use this
  530. if (t1.ParseDateTime(str1) && t2.ParseDateTime(str2))
  531. {
  532. if(bTime.GetStatus() != COleDateTime::invalid && 
  533. t1 < bTime)
  534. {
  535. t1 += COleDateTimeSpan(1, 0, 0, 0);
  536. }
  537. if(bTime.GetStatus() != COleDateTime::invalid &&
  538. t2 < bTime)
  539. {
  540. t2 += COleDateTimeSpan(1, 0, 0, 0);
  541. }
  542. return (t1 < t2 ? -1 : 1 )*sOrder;
  543. }
  544. else
  545. return 0;
  546. //Date time column(s) no base time
  547. case  LVEX_TIME:
  548. if (t1.ParseDateTime(str1) && t2.ParseDateTime(str2))
  549. return (t1 < t2 ? -1 : 1 )*sOrder;
  550. else
  551. return 0;
  552. //integer number columns
  553. case  LVEX_NUM:
  554. return (atol(str1) - atol(str2))*sOrder;
  555. //float number columns
  556. case  LVEX_NUM_FLOAT:
  557. return (atof(str1) < atof(str2) ? -1 : 1)*sOrder;
  558. //text columns (no case)
  559. case  LVEX_NOCASE:
  560. return str1.CompareNoCase(str2)*sOrder;
  561. //text columns (case sensitive)
  562. case LVEX_CASE:
  563. return (str1.Compare(str2))*sOrder;
  564. }
  565. return 0;
  566. }
  567. //End Sorting
  568. //////////////////////////////////////////////////////////////////////////
  569. //////////////////////////////////////////////////////////////////////
  570. //Drag Column Headers
  571. //
  572. //////////////////////////////////////////////////////////////////////
  573. void CListCtrlEx::DragColumn(int source, int dest)
  574. {
  575. TCHAR sColText[160];
  576. // Insert a column at dest
  577. LV_COLUMN lv_col;
  578. lv_col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  579. lv_col.pszText = sColText;
  580. lv_col.cchTextMax = 159;
  581. GetColumn( source, &lv_col );
  582. lv_col.iSubItem = dest;
  583. InsertColumn( dest, &lv_col );
  584. // Adjust source col number since it might have changed