THeaderCtrlEx.cpp
上传用户:maicowu
上传日期:2007-01-02
资源大小:87k
文件大小:9k
源码类别:

TreeView控件

开发平台:

Visual C++

  1. /************************************
  2.   REVISION LOG ENTRY
  3.   Revision By: Mihai Filimon
  4.   Revised on 5/22/98 9:21:13 AM
  5.   Comments: THeaderCtrlEx.cpp : implementation file
  6.  ************************************/
  7. #include "stdafx.h"
  8. #include "THeaderCtrlEx.h"
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CTHeaderCtrlEx
  16. #define ORDERCOLUMN(b) ((BOOL)LOBYTE(b))
  17. #define POSITIONCOLUMN(b) ((int)HIBYTE(b))
  18. // Function name : CTHeaderCtrlEx::CTHeaderCtrlEx
  19. // Description     : constructor
  20. // Return type : -
  21. CTHeaderCtrlEx::CTHeaderCtrlEx()
  22. {
  23. m_nLastPosition = 0;
  24. }
  25. // Function name : CTHeaderCtrlEx::~CTHeaderCtrlEx
  26. // Description     : destructor
  27. // Return type : -
  28. CTHeaderCtrlEx::~CTHeaderCtrlEx()
  29. {
  30. }
  31. BEGIN_MESSAGE_MAP(CTHeaderCtrlEx, CHeaderCtrl)
  32. //{{AFX_MSG_MAP(CTHeaderCtrlEx)
  33. //}}AFX_MSG_MAP
  34. END_MESSAGE_MAP()
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CTHeaderCtrlEx message handlers
  37. // Function name : CTHeaderCtrlEx::SignMoreSortColumns
  38. // Description     : Called from DrawItem, If position<4 will mark header columns with their respective positions
  39. // Return type : void 
  40. // Argument         : CDC & dc
  41. // Argument         : int nPosition
  42. // Argument         : CRect& rectWhere
  43. void CTHeaderCtrlEx::SignMoreSortColumns(CDC & dc, int nPosition,  CRect& rectWhere)
  44. {
  45. if (nPosition < 4) 
  46. {
  47. const static dxSign = 1;
  48. const static dxSignDelay = 1;
  49. CRect sign = rectWhere;
  50. sign.right = sign.left + dxSign;
  51. sign.OffsetRect((rectWhere.Width() - (nPosition * dxSign + (nPosition - 1) * dxSignDelay)) / 2, 0);
  52. if (sign.left >=  rectWhere.left)
  53. {
  54. CBrush brush(RGB(0,0,0));
  55. for (int j = 0; j < nPosition; j++)
  56. {
  57. dc.FillRect(sign, &brush);
  58. sign.OffsetRect(dxSign + dxSignDelay, 0);
  59. }
  60. }
  61. }
  62. }
  63. // Function name : CTHeaderCtrlEx::DrawItem
  64. // Description     : Call for ownerdraw item.
  65. // Return type : void 
  66. // Argument         : LPDRAWITEMSTRUCT lpDrawItemStruct
  67. void CTHeaderCtrlEx::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
  68. {
  69. CDC dc;
  70. dc.Attach( lpDrawItemStruct->hDC );
  71. // Get the column rect
  72. CRect rcLabel( lpDrawItemStruct->rcItem );
  73. // Save DC
  74. int nSavedDC = dc.SaveDC();
  75. // Set clipping region to limit drawing within column
  76. CRgn rgn;
  77. rgn.CreateRectRgnIndirect( &rcLabel );
  78. dc.SelectObject( &rgn );
  79. rgn.DeleteObject();
  80. // Labels are offset by a certain amount  
  81. // This offset is related to the width of a space character
  82. int offset = dc.GetTextExtent(_T("X"), 1 ).cx * 1;
  83. // Get the column text and format
  84. TCHAR buf[256];
  85. HD_ITEM hditem;
  86. hditem.mask = HDI_TEXT | HDI_FORMAT;
  87. hditem.pszText = buf;
  88. hditem.cchTextMax = 255;
  89. GetItem( lpDrawItemStruct->itemID, &hditem );
  90. // Determine format for drawing column label
  91. UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER;
  92. if( hditem.fmt & HDF_CENTER)
  93. uFormat |= DT_CENTER;
  94. else if( hditem.fmt & HDF_RIGHT)
  95. uFormat |= DT_RIGHT;
  96. else
  97. uFormat |= DT_LEFT;
  98. // Adjust the rect if the mouse button is pressed on it
  99. if( lpDrawItemStruct->itemState == ODS_SELECTED )
  100. {
  101. rcLabel.left++;
  102. rcLabel.top += 2;
  103. rcLabel.right++;
  104. }
  105. BOOL bAsc = true;
  106. int nPosition = 0;
  107. BOOL bIsSortColumn = GetColumnOrder(lpDrawItemStruct->itemID, bAsc, nPosition);
  108. int dxRectArrow = bIsSortColumn ? 2*offset : 0;
  109. // Adjust the rect further if Sort arrow is to be displayed
  110. rcLabel.right -= dxRectArrow;
  111. rcLabel.left += offset;
  112. rcLabel.right -= offset;
  113. // Draw column label
  114. if( rcLabel.left < rcLabel.right )
  115. dc.DrawText(buf,-1,rcLabel, uFormat);
  116. // Draw the Sort arrow
  117. if( bIsSortColumn )
  118. {
  119. rcLabel.right += offset;
  120. CRect rectArrow = rcLabel;
  121. int dyRectArrow = (int)((double)rectArrow.Height() / 5 * 2);
  122. rectArrow.OffsetRect(0, (rectArrow.Height() - dyRectArrow) / 2);
  123. rectArrow.bottom = rectArrow.top + dyRectArrow;
  124. rectArrow.left = rcLabel.right;
  125. rectArrow.right = rectArrow.left + dyRectArrow;
  126. // Set up pens to use for drawing the triangle
  127. CPen penLight(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
  128. CPen penShadow(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
  129. CPen *pOldPen = dc.SelectObject( &penLight );
  130. CRect rectSign = rectArrow;
  131. if (rectSign.left > rcLabel.left)
  132. /* In this version do not exist SelectClipRgn, Wait for new version...*/
  133. {
  134. if (bAsc)
  135. for (int i = 0; i < 2; i++)
  136. {
  137. dc.MoveTo(rectArrow.TopLeft());
  138. dc.LineTo(rectArrow.right,rectArrow.top);
  139. dc.LineTo((rectArrow.left + rectArrow.right) / 2,rectArrow.bottom);
  140. dc.LineTo(rectArrow.TopLeft());
  141. dc.SelectObject( &penShadow );
  142. rectArrow.OffsetRect(-2,-1);
  143. }
  144. else
  145. for (int i = 0; i < 2; i++)
  146. {
  147. dc.MoveTo(rectArrow.left,rectArrow.bottom);
  148. dc.LineTo((rectArrow.left + rectArrow.right) / 2,rectArrow.top);
  149. dc.LineTo(rectArrow.BottomRight());
  150. dc.LineTo(rectArrow.left,rectArrow.bottom);
  151. dc.SelectObject( &penShadow );
  152. rectArrow.OffsetRect(-2,-1);
  153. }
  154. rectSign.left = (rectArrow.left + rectArrow.right) / 2 - offset;
  155. rectSign.right = rectSign.left + 2 * offset;
  156. rectSign.top = rectArrow.bottom;
  157. rectSign.bottom = rectSign.top + 4;
  158. if (m_mapSortColumns.GetCount() > 1)
  159. SignMoreSortColumns(dc, nPosition, rectSign);
  160. }
  161. // Restore the pen
  162. dc.SelectObject( pOldPen );
  163. }
  164. // Restore dc
  165. dc.RestoreDC( nSavedDC );
  166. // Detach the dc before returning
  167. dc.Detach();
  168. }
  169. // Function name : CTHeaderCtrlEx::SetColumnFormat
  170. // Description     : Set or reset format of item iColumn from header
  171. // Return type : void 
  172. // Argument         : int iColumn
  173. // Argument         : int format
  174. // Argument         : BOOL bOr
  175. void CTHeaderCtrlEx::SetColumnFormat(int iColumn, int format, BOOL bOr)
  176. {
  177. // Change the item to (not)owner drawn
  178. HD_ITEM hditem;
  179. hditem.mask = HDI_FORMAT;
  180. if (GetItem( iColumn, &hditem ))
  181. {
  182. hditem.fmt = bOr ? hditem.fmt | format : hditem.fmt & ~format;
  183. SetItem( iColumn, &hditem );
  184. }
  185. }
  186. // Function name : CTHeaderCtrlEx::GetPositionColumn
  187. // Description     : 
  188. // Return type : BOOL ; Return TRUE, if exist sort column with position nPosition
  189. // Argument         : int nPosition
  190. // Argument         : BOOL & bAsc ; Set bAsc and nColumn with sort column found.
  191. // Argument         : int & nColumn
  192. BOOL CTHeaderCtrlEx::GetPositionColumn(int nPosition, BOOL & bAsc, int & nColumn) const
  193. {
  194. POSITION position = m_mapSortColumns.GetStartPosition();
  195. while (position)
  196. {
  197. WORD value;
  198. m_mapSortColumns.GetNextAssoc(position, nColumn, value);
  199. if (POSITIONCOLUMN(value) == nPosition)
  200. {
  201. bAsc = ORDERCOLUMN(value);
  202. return TRUE;
  203. }
  204. }
  205. return FALSE;
  206. }
  207. // Function name : CTHeaderCtrlEx::GetColumnOrder
  208. // Description     : 
  209. // Return type : BOOL ; Return TRUE if sort column nColumn exist
  210. // Argument         : int nColumn 
  211. // Argument         : BOOL & bAsc ; sort column found
  212. // Argument         : int& nPosition
  213. BOOL CTHeaderCtrlEx::GetColumnOrder(int nColumn, BOOL & bAsc, int& nPosition) const
  214. {
  215. WORD value;
  216. BOOL result = m_mapSortColumns.Lookup(nColumn, value);
  217. if (result)
  218. {
  219. bAsc = ORDERCOLUMN(value);
  220. nPosition = POSITIONCOLUMN(value);
  221. }
  222. return result;
  223. }
  224. // Function name : CTHeaderCtrlEx::SetColumnOrder
  225. // Description     : Set column iColumn as sort column ascending or descending
  226. // Return type : BOOL ; always TRUE for now
  227. // Argument         : int iColumn ; column to set
  228. // Argument         : BOOL bAsc ; sorting direction: ascendent or descendent
  229. BOOL CTHeaderCtrlEx::SetColumnOrder(int iColumn, BOOL bAsc)
  230. {
  231. BYTE position = NULL;
  232. WORD value = NULL;
  233. if (m_mapSortColumns.Lookup(iColumn, value))
  234. position = POSITIONCOLUMN(value);
  235. else
  236. position = ++m_nLastPosition;
  237. m_mapSortColumns[iColumn] = MAKEWORD(bAsc, position);
  238. SetColumnFormat(iColumn, HDF_OWNERDRAW, SET);
  239. // Invalidate header control so that it gets redrawn
  240. Invalidate();
  241. return TRUE;
  242. }
  243. // Function name : CTHeaderCtrlEx::DeleteColumnOrder
  244. // Description     : Delete sort column iColumn
  245. // Return type : void 
  246. // Argument         : int iColumn ; column number
  247. void CTHeaderCtrlEx::DeleteColumnOrder(int iColumn)
  248. {
  249. SetColumnFormat(iColumn, HDF_OWNERDRAW, REMOVE);
  250. BOOL bAscRemove; int nPositionRemove;
  251. if (GetColumnOrder(iColumn, bAscRemove, nPositionRemove))
  252. {
  253. m_mapSortColumns.RemoveKey(iColumn);
  254. POSITION position = m_mapSortColumns.GetStartPosition();
  255. while (position)
  256. {
  257. WORD value;
  258. int column;
  259. m_mapSortColumns.GetNextAssoc(position, column, value);
  260. if (POSITIONCOLUMN(value) > nPositionRemove)
  261. m_mapSortColumns[column] = MAKEWORD(ORDERCOLUMN(value),POSITIONCOLUMN(value) - 1);
  262. }
  263. m_nLastPosition--;
  264. Invalidate();
  265. }
  266. }
  267. // Function name : CTHeaderCtrlEx::ResetSortColumns
  268. // Description     : Remove all sort columns
  269. // Return type : void 
  270. // Argument         : BOOL bInvalidate ; If TRUE force to invalidate header
  271. void CTHeaderCtrlEx::ResetSortColumns(BOOL bInvalidate)
  272. {
  273. m_mapSortColumns.RemoveAll();
  274. m_nLastPosition = 0;
  275. for (int i = 0; i < GetItemCount(); i++)
  276. SetColumnFormat(i,HDF_OWNERDRAW, REMOVE );
  277. if (bInvalidate)
  278. Invalidate();
  279. }