SortHeaderCtrl.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #include "stdafx.h"
  2. #include "SortHeaderCtrl.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #endif
  8. CSortHeaderCtrl::CSortHeaderCtrl()
  9. : m_iSortColumn( -1 )
  10. , m_bSortAscending( TRUE )
  11. {
  12. }
  13. CSortHeaderCtrl::~CSortHeaderCtrl()
  14. {
  15. }
  16. BEGIN_MESSAGE_MAP(CSortHeaderCtrl, CHeaderCtrl)
  17. //{{AFX_MSG_MAP(CSortHeaderCtrl)
  18. // NOTE - the ClassWizard will add and remove mapping macros here.
  19. //}}AFX_MSG_MAP
  20. END_MESSAGE_MAP()
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CSortHeaderCtrl message handlers
  23. void CSortHeaderCtrl::SetSortArrow( const int iSortColumn, const BOOL bSortAscending )
  24. {
  25. m_iSortColumn = iSortColumn;
  26. m_bSortAscending = bSortAscending;
  27. // change the item to owner drawn.
  28. HD_ITEM hditem;
  29. hditem.mask = HDI_FORMAT;
  30. VERIFY( GetItem( iSortColumn, &hditem ) );
  31. hditem.fmt |= HDF_OWNERDRAW;
  32. VERIFY( SetItem( iSortColumn, &hditem ) );
  33. // invalidate the header control so it gets redrawn
  34. Invalidate();
  35. }
  36. void CSortHeaderCtrl::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
  37. {
  38. // attath to the device context.
  39. CDC dc;
  40. VERIFY( dc.Attach( lpDrawItemStruct->hDC ) );
  41. // save the device context.
  42. const int iSavedDC = dc.SaveDC();
  43. // get the column rect.
  44. CRect rc( lpDrawItemStruct->rcItem );
  45. // set the clipping region to limit drawing within the column.
  46. CRgn rgn;
  47. VERIFY( rgn.CreateRectRgnIndirect( &rc ) );
  48. (void)dc.SelectObject( &rgn );
  49. VERIFY( rgn.DeleteObject() );
  50. // draw the background,
  51. CBrush brush( GetSysColor( COLOR_3DFACE ) );
  52. dc.FillRect( rc, &brush );
  53. // get the column text and format.
  54. TCHAR szText[ 256 ];
  55. HD_ITEM hditem;
  56. hditem.mask = HDI_TEXT | HDI_FORMAT;
  57. hditem.pszText = szText;
  58. hditem.cchTextMax = 255;
  59. VERIFY( GetItem( lpDrawItemStruct->itemID, &hditem ) );
  60. // determine the format for drawing the column label.
  61. UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_END_ELLIPSIS ;
  62. if( hditem.fmt & HDF_CENTER)
  63. uFormat |= DT_CENTER;
  64. else if( hditem.fmt & HDF_RIGHT)
  65. uFormat |= DT_RIGHT;
  66. else
  67. uFormat |= DT_LEFT;
  68. // adjust the rect if the mouse button is pressed on it.
  69. if( lpDrawItemStruct->itemState == ODS_SELECTED )
  70. {
  71. rc.left++;
  72. rc.top += 2;
  73. rc.right++;
  74. }
  75. CRect rcIcon( lpDrawItemStruct->rcItem );
  76. const int iOffset = ( rcIcon.bottom - rcIcon.top ) / 4;
  77. // adjust the rect further if the sort arrow is to be displayed.
  78. if( lpDrawItemStruct->itemID == (UINT)m_iSortColumn )
  79. rc.right -= 3 * iOffset;
  80. rc.left += iOffset;
  81. rc.right -= iOffset;
  82. // draw the column label.
  83. if( rc.left < rc.right )
  84. (void)dc.DrawText( szText, -1, rc, uFormat );
  85. // draw the sort arrow.
  86. if( lpDrawItemStruct->itemID == (UINT)m_iSortColumn )
  87. {
  88. // set up the pens to use for drawing the arrow.
  89. CPen penLight( PS_SOLID, 1, GetSysColor( COLOR_3DHILIGHT ) );
  90. CPen penShadow( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW ) );
  91. CPen* pOldPen = dc.SelectObject( &penLight );
  92. if( m_bSortAscending )
  93. {
  94. // draw the arrow pointing upwards.
  95. dc.MoveTo( rcIcon.right - 2 * iOffset, iOffset);
  96. dc.LineTo( rcIcon.right - iOffset, rcIcon.bottom - iOffset - 1 );
  97. dc.LineTo( rcIcon.right - 3 * iOffset - 2, rcIcon.bottom - iOffset - 1 );
  98. (void)dc.SelectObject( &penShadow );
  99. dc.MoveTo( rcIcon.right - 3 * iOffset - 1, rcIcon.bottom - iOffset - 1 );
  100. dc.LineTo( rcIcon.right - 2 * iOffset, iOffset - 1);
  101. }
  102. else
  103. {
  104. // draw the arrow pointing downwards.
  105. dc.MoveTo( rcIcon.right - iOffset - 1, iOffset );
  106. dc.LineTo( rcIcon.right - 2 * iOffset - 1, rcIcon.bottom - iOffset );
  107. (void)dc.SelectObject( &penShadow );
  108. dc.MoveTo( rcIcon.right - 2 * iOffset - 2, rcIcon.bottom - iOffset );
  109. dc.LineTo( rcIcon.right - 3 * iOffset - 1, iOffset );
  110. dc.LineTo( rcIcon.right - iOffset - 1, iOffset );
  111. }
  112. // restore the pen.
  113. (void)dc.SelectObject( pOldPen );
  114. DeleteObject( penLight );
  115. DeleteObject( penShadow );
  116. }
  117. // restore the previous device context.
  118. VERIFY( dc.RestoreDC( iSavedDC ) );
  119. // detach the device context before returning.
  120. (void)dc.Detach();
  121. //2011-10-31 add
  122. ReleaseDC( &dc );
  123. DeleteObject( brush );
  124. }
  125. void CSortHeaderCtrl::Serialize( CArchive& ar )
  126. {
  127. if( ar.IsStoring() )
  128. {
  129. const int iItemCount = GetItemCount();
  130. if( iItemCount != -1 )
  131. {
  132. ar << iItemCount;
  133. HD_ITEM hdItem = { 0 };
  134. hdItem.mask = HDI_WIDTH;
  135. for( int i = 0; i < iItemCount; i++ )
  136. {
  137. VERIFY( GetItem( i, &hdItem ) );
  138. ar << hdItem.cxy;
  139. }
  140. }
  141. }
  142. else
  143. {
  144. int iItemCount;
  145. ar >> iItemCount;
  146. if( GetItemCount() != iItemCount )
  147. TRACE0( _T("Different number of columns in registry.") );
  148. else
  149. {
  150. HD_ITEM hdItem = { 0 };
  151. hdItem.mask = HDI_WIDTH;
  152. for( int i = 0; i < iItemCount; i++ )
  153. {
  154. ar >> hdItem.cxy;
  155. VERIFY( SetItem( i, &hdItem ) );
  156. }
  157. }
  158. }
  159. }