SortHeaderCtrl.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. #include "stdafx.h"
  2. #include "SortHeaderCtrl.h"
  3. CSortHeaderCtrl::CSortHeaderCtrl(): m_nSortColumn( -1 ), m_bSortAscending( TRUE )
  4. {
  5. m_bPressMoused = FALSE;
  6. //m_clrColumText = RGB(255,255,255);
  7. //m_clr3DHighLight = RGB(220, 220, 220); //::GetSysColor(COLOR_3DHIGHLIGHT);
  8. //m_clr3DShadow = RGB(35, 35, 35); //::GetSysColor(COLOR_3DSHADOW);
  9. //m_clr3DFace = RGB(128, 128, 128); //::GetSysColor(COLOR_3DFACE);
  10. m_clrColumText = RGB(7,30,129);
  11. m_clr3DHighLight = RGB(107, 201, 255); //::GetSysColor(COLOR_3DHIGHLIGHT);
  12. m_clr3DShadow = RGB(37, 121, 176); //::GetSysColor(COLOR_3DSHADOW);
  13. m_clr3DFace = RGB(105, 201, 255); //::GetSysColor(COLOR_3DFACE);
  14. }
  15. CSortHeaderCtrl::~CSortHeaderCtrl()
  16. {
  17. }
  18. BEGIN_MESSAGE_MAP(CSortHeaderCtrl, CHeaderCtrl)
  19. ON_WM_PAINT()
  20. ON_WM_ERASEBKGND()
  21. END_MESSAGE_MAP()
  22. /************************************************************************/
  23. /* 函数:SetSortArrow[10/20/2016 IT];
  24. /* 描述:设置要排序的列以及排序方式(升序或降序);
  25. /* 参数:;
  26. /* [IN] :;
  27. /* [OUT] :;
  28. /* [IN/OUT] :;
  29. /* 返回:void;
  30. /* 注意:;
  31. /* 示例:;
  32. /*
  33. /* 修改:;
  34. /* 日期:;
  35. /* 内容:;
  36. /************************************************************************/
  37. void CSortHeaderCtrl::SetSortArrow( IN const int nSortColumn, IN const BOOL bSortAscending )
  38. {
  39. m_nSortColumn = nSortColumn;
  40. m_bSortAscending = bSortAscending;
  41. // 设置项自绘风格;
  42. HD_ITEM hditem;
  43. hditem.mask = HDI_FORMAT;
  44. // 获取列信息;
  45. VERIFY( GetItem( nSortColumn, &hditem ) );
  46. // 设置自绘风格;
  47. hditem.fmt |= HDF_OWNERDRAW;
  48. // 设置列信息;
  49. VERIFY( SetItem( nSortColumn, &hditem ) );
  50. // 更新表头以便重绘;
  51. Invalidate();
  52. }
  53. BOOL CSortHeaderCtrl::OnEraseBkgnd(CDC* pDC)
  54. {
  55. return TRUE;
  56. }
  57. void CSortHeaderCtrl::OnPaint()
  58. {
  59. CPaintDC dc(this); // device context for painting
  60. int nItems = GetItemCount();
  61. ASSERT(nItems >= 0);
  62. dc.SetBkColor(m_clr3DFace);
  63. dc.SetTextColor(m_clrColumText);
  64. CRect rectClip;
  65. if (dc.GetClipBox(&rectClip) == ERROR)
  66. return;
  67. dc.FillSolidRect(rectClip, m_clr3DFace);
  68. // 获取当前鼠标位置;
  69. POINT point;
  70. GetCursorPos(&point);
  71. ScreenToClient(&point);
  72. CRect rectItem;
  73. for(int i = 0; i < nItems; i++)
  74. {
  75. TCHAR szText[256];
  76. HD_ITEM hditem;
  77. hditem.mask = HDI_TEXT | HDI_FORMAT | HDI_ORDER;
  78. hditem.pszText = szText;
  79. hditem.cchTextMax = 255;
  80. GetItem( i, &hditem );
  81. DRAWITEMSTRUCT DrawItemStruct;
  82. GetItemRect(i, &rectItem);
  83. DrawItemStruct.CtlType = ODT_BUTTON;
  84. DrawItemStruct.hDC = dc.GetSafeHdc();
  85. DrawItemStruct.itemAction = ODA_DRAWENTIRE;
  86. DrawItemStruct.hwndItem = GetSafeHwnd();
  87. DrawItemStruct.rcItem = rectItem;
  88. DrawItemStruct.itemID = i;
  89. if ( rectItem.PtInRect(point) && m_bPressMoused )
  90. DrawItemStruct.itemState = ODS_SELECTED;
  91. DrawItemEx(&DrawItemStruct);
  92. }
  93. }
  94. /************************************************************************/
  95. /* 函数:DrawItemEx[10/19/2016 IT];
  96. /* 描述:自绘函数;
  97. /* 参数:;
  98. /* [IN] :;
  99. /* [OUT] :;
  100. /* [IN/OUT] :;
  101. /* 返回:void;
  102. /* 注意:;
  103. /* 示例:;
  104. /*
  105. /* 修改:;
  106. /* 日期:;
  107. /* 内容:;
  108. /************************************************************************/
  109. void CSortHeaderCtrl::DrawItemEx( IN LPDRAWITEMSTRUCT lpDrawItemStruct )
  110. {
  111. // 定义设备上下文;
  112. CDC dc;
  113. // 附加设备上下文句柄;
  114. VERIFY( dc.Attach( lpDrawItemStruct->hDC ) );
  115. // 保存设备上下文;
  116. const int nSavedDC = dc.SaveDC();
  117. // 获取当前列区域;
  118. CRect rc( lpDrawItemStruct->rcItem );
  119. // 实现列单元格3D效果;
  120. dc.Draw3dRect(rc, m_clr3DHighLight, m_clr3DShadow);
  121. rc.InflateRect(-1,-1);
  122. dc.FillSolidRect(rc, m_clr3DFace);
  123. dc.SetBkMode(TRANSPARENT);
  124. // 设置文本颜色;
  125. dc.SetTextColor(m_clrColumText);
  126. // 恢复原大小;
  127. rc = lpDrawItemStruct->rcItem;
  128. // 获取当前的列的项目信息;
  129. TCHAR szText[ 256 ];
  130. HD_ITEM hditem;
  131. hditem.mask = HDI_TEXT | HDI_FORMAT;
  132. hditem.pszText = szText;
  133. hditem.cchTextMax = 255;
  134. VERIFY( GetItem( lpDrawItemStruct->itemID, &hditem ) );
  135. // 设置列的文本绘制格式;
  136. UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_END_ELLIPSIS ;
  137. if( hditem.fmt & HDF_CENTER)
  138. uFormat |= DT_CENTER;
  139. else if( hditem.fmt & HDF_RIGHT)
  140. uFormat |= DT_RIGHT;
  141. else
  142. uFormat |= DT_LEFT;
  143. // 如果鼠标在列区域按下,则重新调整列区域;
  144. if( lpDrawItemStruct->itemState == ODS_SELECTED )
  145. {
  146. rc.left++;
  147. rc.top += 2;
  148. rc.right++;
  149. // 释放鼠标按下标志;
  150. m_bPressMoused = FALSE;
  151. }
  152. // 箭头图标区域(rcIcon);
  153. CRect rcIcon( lpDrawItemStruct->rcItem );
  154. const int nOffset = ( rcIcon.bottom - rcIcon.top ) / 4;
  155. // adjust the rect further if the sort arrow is to be displayed.
  156. if( lpDrawItemStruct->itemID == (UINT)m_nSortColumn )
  157. rc.right -= 3 * nOffset;
  158. rc.left += nOffset;
  159. rc.right -= nOffset;
  160. // 绘制列文本;
  161. if( rc.left < rc.right )
  162. dc.DrawText( szText, -1, rc, uFormat );
  163. // 绘制排序箭头;
  164. if( lpDrawItemStruct->itemID == (UINT)m_nSortColumn )
  165. {
  166. // 定义绘制箭头的画笔;
  167. CPen penLight( PS_SOLID, 1, GetSysColor( COLOR_3DHILIGHT ) );
  168. CPen penShadow( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW ) );
  169. CPen* pOldPen = dc.SelectObject( &penLight );
  170. if( m_bSortAscending )
  171. {
  172. // 绘制向上的箭头;
  173. dc.MoveTo( rcIcon.right - 2 * nOffset, nOffset);
  174. dc.LineTo( rcIcon.right - nOffset, rcIcon.bottom - nOffset - 1 );
  175. dc.LineTo( rcIcon.right - 3 * nOffset - 2, rcIcon.bottom - nOffset - 1 );
  176. dc.SelectObject( &penShadow );
  177. dc.MoveTo( rcIcon.right - 3 * nOffset - 1, rcIcon.bottom - nOffset - 1 );
  178. dc.LineTo( rcIcon.right - 2 * nOffset, nOffset - 1);
  179. }
  180. else
  181. {
  182. // 绘制向下的箭头;
  183. dc.MoveTo( rcIcon.right - nOffset - 1, nOffset );
  184. dc.LineTo( rcIcon.right - 2 * nOffset - 1, rcIcon.bottom - nOffset );
  185. dc.SelectObject( &penShadow );
  186. dc.MoveTo( rcIcon.right - 2 * nOffset - 2, rcIcon.bottom - nOffset );
  187. dc.LineTo( rcIcon.right - 3 * nOffset - 1, nOffset );
  188. dc.LineTo( rcIcon.right - nOffset - 1, nOffset );
  189. }
  190. // 恢复原来选择的画笔;
  191. dc.SelectObject( pOldPen );
  192. }
  193. // 恢复之前的设备上下文;
  194. VERIFY( dc.RestoreDC( nSavedDC ) );
  195. // 返回之前,分离设备上下文句柄;
  196. dc.Detach();
  197. }
  198. /************************************************************************/
  199. /* 函数:[10/20/2016 IT];
  200. /* 描述:;
  201. /* 参数:;
  202. /* [IN] :;
  203. /* [OUT] :;
  204. /* [IN/OUT] :;
  205. /* 返回:void;
  206. /* 注意:;
  207. /* 示例:;
  208. /*
  209. /* 修改:;
  210. /* 日期:;
  211. /* 内容:;
  212. /************************************************************************/
  213. void CSortHeaderCtrl::Serialize( CArchive& ar )
  214. {
  215. try
  216. {
  217. if( ar.IsStoring() )
  218. {
  219. const int nItemCount = GetItemCount();
  220. if( nItemCount != -1 )
  221. {
  222. ar << nItemCount;
  223. HD_ITEM hdItem = { 0 };
  224. hdItem.mask = HDI_WIDTH | HDI_ORDER;
  225. for( int i = 0; i < nItemCount; i++ )
  226. {
  227. VERIFY( GetItem( i, &hdItem ) );
  228. ar << hdItem.cxy;
  229. ar << hdItem.iOrder;
  230. }
  231. }
  232. }
  233. else
  234. {
  235. int nItemCount;
  236. ar >> nItemCount;
  237. if( GetItemCount() != nItemCount )
  238. TRACE( _T("Different number of columns in registry.") );
  239. else
  240. {
  241. HD_ITEM hdItem = { 0 };
  242. hdItem.mask = HDI_WIDTH | HDI_ORDER;
  243. for( int i = 0; i < nItemCount; i++ )
  244. {
  245. ar >> hdItem.cxy;
  246. ar >> hdItem.iOrder;
  247. VERIFY( SetItem( i, &hdItem ) );
  248. }
  249. }
  250. }
  251. }
  252. catch(...)
  253. {
  254. }
  255. }
  256. BOOL CSortHeaderCtrl::PreTranslateMessage(MSG* pMsg)
  257. {
  258. // TODO: 在此添加专用代码和/或调用基类
  259. if ( pMsg->message == WM_LBUTTONDOWN )
  260. {
  261. m_bPressMoused = TRUE;
  262. }
  263. return CHeaderCtrl::PreTranslateMessage(pMsg);
  264. }
  265. /************************************************************************/
  266. /* 函数:SetTextFont[3/6/2017 Jeff];
  267. /* 描述:设置文本字体;
  268. /* 参数:;
  269. /* [IN] nTextFontSize:字体大小;
  270. /* [IN] bBold:是否粗体;
  271. /* [IN] bItalic:是否斜体;
  272. /* [IN] strTextFontName:字体名称,如楷体;
  273. /* 返回:void;
  274. /* 注意:;
  275. /* 示例:;
  276. /*
  277. /* 修改:;
  278. /* 日期:;
  279. /* 内容:;
  280. /************************************************************************/
  281. void CSortHeaderCtrl::SetListFont(IN CString strFontName, IN int nFontSize, IN BOOL bBold, IN BOOL bItalic)
  282. {
  283. LOGFONT lf;
  284. CClientDC dc(this);
  285. int dpy = GetDeviceCaps(dc, LOGPIXELSY); // Pixel per inch
  286. lf.lfHeight = -MulDiv(nFontSize, dpy, 72);
  287. lf.lfWeight = 0;
  288. lf.lfEscapement = 0;
  289. lf.lfOrientation = 0;
  290. if (bBold)
  291. lf.lfWeight = FW_BLACK;
  292. else
  293. lf.lfWeight = FW_NORMAL;
  294. lf.lfItalic = bItalic;
  295. lf.lfUnderline = FALSE;
  296. lf.lfStrikeOut = 0;
  297. lf.lfCharSet = ANSI_CHARSET;
  298. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  299. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  300. lf.lfQuality = DEFAULT_QUALITY;
  301. lf.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN;
  302. _tcscpy_s(lf.lfFaceName, strFontName);
  303. // 创建字体;
  304. //m_cfont = GetFont();// 局部变量会导致字体设置失败,必须是全局或成员变量;
  305. VERIFY(m_cfont.CreateFontIndirect(&lf));
  306. // 选入字体;
  307. this->SetFont(&m_cfont);
  308. }