XHeaderCtrl.cpp
上传用户:dfzycw
上传日期:2010-01-10
资源大小:66k
文件大小:10k
源码类别:

进程与线程

开发平台:

Visual C++

  1. // XHeaderCtrl.cpp
  2. //
  3. // Author:  Hans Dietrich
  4. //          hdietrich2@hotmail.com
  5. //
  6. // This code is based on "Outlook 98-Style FlatHeader Control" 
  7. // by Maarten Hoeben.
  8. //
  9. // See http://www.codeguru.com/listview/FlatHeader.shtml
  10. //
  11. // This software is released into the public domain.
  12. // You are free to use it in any way you like.
  13. //
  14. // This software is provided "as is" with no expressed
  15. // or implied warranty.  I accept no liability for any
  16. // damage or loss of business that this software may cause.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "XHeaderCtrl.h"
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CXHeaderCtrl
  28. IMPLEMENT_DYNCREATE(CXHeaderCtrl, CHeaderCtrl)
  29. BEGIN_MESSAGE_MAP(CXHeaderCtrl, CHeaderCtrl)
  30. //{{AFX_MSG_MAP(CXHeaderCtrl)
  31. ON_MESSAGE(HDM_INSERTITEMA, OnInsertItem)
  32. ON_MESSAGE(HDM_INSERTITEMW, OnInsertItem)
  33. ON_MESSAGE(HDM_DELETEITEM, OnDeleteItem)
  34. ON_MESSAGE(HDM_SETIMAGELIST, OnSetImageList)
  35. ON_MESSAGE(HDM_LAYOUT, OnLayout)
  36. ON_WM_PAINT()
  37. ON_WM_SYSCOLORCHANGE()
  38. ON_WM_ERASEBKGND()
  39. //}}AFX_MSG_MAP
  40. END_MESSAGE_MAP()
  41. ///////////////////////////////////////////////////////////////////////////////
  42. // ctor
  43. CXHeaderCtrl::CXHeaderCtrl()
  44. {
  45. m_bDoubleBuffer = TRUE;
  46. m_iSpacing = 6;
  47. m_sizeArrow.cx = 8;
  48. m_sizeArrow.cy = 8;
  49. m_sizeImage.cx = 0;
  50. m_sizeImage.cy = 0;
  51. m_bStaticBorder = FALSE;
  52. m_nDontDropCursor = 0;
  53. m_bResizing = FALSE;
  54. m_nClickFlags = 0;
  55. m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
  56. m_cr3DShadow    = ::GetSysColor(COLOR_3DSHADOW);
  57. m_cr3DFace      = ::GetSysColor(COLOR_3DFACE);
  58. m_crBtnText     = ::GetSysColor(COLOR_BTNTEXT);
  59. }
  60. ///////////////////////////////////////////////////////////////////////////////
  61. // dtor
  62. CXHeaderCtrl::~CXHeaderCtrl()
  63. {
  64. }
  65. ///////////////////////////////////////////////////////////////////////////////
  66. // ModifyProperty
  67. BOOL CXHeaderCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam)
  68. {
  69. switch(wParam)
  70. {
  71. case FH_PROPERTY_SPACING:
  72. m_iSpacing = (int)lParam;
  73. break;
  74. case FH_PROPERTY_ARROW:
  75. m_sizeArrow.cx = LOWORD(lParam);
  76. m_sizeArrow.cy = HIWORD(lParam);
  77. break;
  78. case FH_PROPERTY_STATICBORDER:
  79. m_bStaticBorder = (BOOL)lParam;
  80. break;
  81. case FH_PROPERTY_DONTDROPCURSOR:
  82. m_nDontDropCursor = (UINT)lParam;
  83. break;
  84. default:
  85. return FALSE;
  86. }
  87. Invalidate();
  88. return TRUE;
  89. }
  90. ///////////////////////////////////////////////////////////////////////////////
  91. // DrawCtrl
  92. void CXHeaderCtrl::DrawCtrl(CDC* pDC)
  93. {
  94. CRect rectClip;
  95. if (pDC->GetClipBox(&rectClip) == ERROR)
  96. return;
  97. CRect rectClient, rectItem;
  98. GetClientRect(&rectClient);
  99.     pDC->FillSolidRect(rectClip, m_cr3DFace);
  100. int iItems = GetItemCount();
  101. ASSERT(iItems >= 0);
  102. CPen penHighLight(PS_SOLID, 1, m_cr3DHighLight);
  103. CPen penShadow(PS_SOLID, 1, m_cr3DShadow);
  104. CPen* pPen = pDC->GetCurrentPen();
  105. CFont* pFont = pDC->SelectObject(GetFont());
  106. pDC->SetBkColor(m_cr3DFace);
  107. pDC->SetTextColor(m_crBtnText);
  108. int iWidth = 0;
  109. for (int i = 0; i < iItems; i++)
  110. {
  111. int iItem = OrderToIndex(i);
  112. TCHAR szText[FLATHEADER_TEXT_MAX];
  113. HDITEM hditem;
  114. hditem.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP;
  115. hditem.pszText = szText;
  116. hditem.cchTextMax = sizeof(szText);
  117. VERIFY(GetItem(iItem, &hditem));
  118. VERIFY(GetItemRect(iItem, rectItem));
  119. if (rectItem.right >= rectClip.left || rectItem.left <= rectClip.right)
  120. {
  121. if (hditem.fmt & HDF_OWNERDRAW)
  122. {
  123. DRAWITEMSTRUCT disItem;
  124. disItem.CtlType = ODT_BUTTON;
  125. disItem.CtlID = GetDlgCtrlID();
  126. disItem.itemID = iItem;
  127. disItem.itemAction = ODA_DRAWENTIRE;
  128. disItem.itemState = 0;
  129. disItem.hwndItem = m_hWnd;
  130. disItem.hDC = pDC->m_hDC;
  131. disItem.rcItem = rectItem;
  132. disItem.itemData = 0;
  133. DrawItem(&disItem);
  134. }
  135. else
  136. {
  137. rectItem.DeflateRect(m_iSpacing, 0);
  138. DrawItem(pDC, rectItem, &hditem);
  139. rectItem.InflateRect(m_iSpacing, 0);
  140. //if (m_nClickFlags & MK_LBUTTON && m_iHotIndex == iItem && m_hdhtiHotItem.flags & HHT_ONHEADER)
  141. // pDC->InvertRect(rectItem);
  142. }
  143. if (i < iItems-1)
  144. {
  145. pDC->SelectObject(&penShadow);
  146. pDC->MoveTo(rectItem.right-1, rectItem.top+2);
  147. pDC->LineTo(rectItem.right-1, rectItem.bottom-2);
  148. pDC->SelectObject(&penHighLight);
  149. pDC->MoveTo(rectItem.right, rectItem.top+2);
  150. pDC->LineTo(rectItem.right, rectItem.bottom-2);
  151. }
  152. }
  153. iWidth += hditem.cxy;
  154. }
  155. if (iWidth > 0)
  156. {
  157. rectClient.right = rectClient.left + iWidth;
  158. pDC->Draw3dRect(rectClient, m_cr3DHighLight, m_cr3DShadow);
  159. }
  160. pDC->SelectObject(pFont);
  161. pDC->SelectObject(pPen);
  162. penHighLight.DeleteObject();
  163. penShadow.DeleteObject();
  164. }
  165. ///////////////////////////////////////////////////////////////////////////////
  166. // DrawItem
  167. void CXHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT)
  168. {
  169. ASSERT(FALSE);  // must override for self draw header controls
  170. }
  171. ///////////////////////////////////////////////////////////////////////////////
  172. // DrawItem
  173. void CXHeaderCtrl::DrawItem(CDC* pDC, CRect rect, LPHDITEM lphdi)
  174. {
  175. ASSERT(lphdi->mask & HDI_FORMAT);
  176. int iWidth = 0;
  177. CBitmap* pBitmap = NULL;
  178. BITMAP BitmapInfo;
  179. if (lphdi->fmt & HDF_BITMAP)
  180. {
  181. ASSERT(lphdi->mask & HDI_BITMAP);
  182. ASSERT(lphdi->hbm);
  183. pBitmap = CBitmap::FromHandle(lphdi->hbm);
  184. if (pBitmap)
  185. VERIFY(pBitmap->GetObject(sizeof(BITMAP), &BitmapInfo));
  186. }
  187. rect.left += ((iWidth = DrawImage(pDC, rect, lphdi, FALSE)) != 0) ? iWidth + m_iSpacing : 0;
  188. rect.right -= ((iWidth = DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE)) != 0) ? 
  189. iWidth + m_iSpacing : 0;
  190. DrawText(pDC, rect, lphdi);
  191. }
  192. ///////////////////////////////////////////////////////////////////////////////
  193. // DrawImage
  194. int CXHeaderCtrl::DrawImage(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bRight)
  195. {
  196. CImageList* pImageList = GetImageList();
  197. int iWidth = 0;
  198. if (lphdi->iImage != XHEADERCTRL_NO_IMAGE)
  199. {
  200. if (pImageList)
  201. {
  202. if (rect.Width() > 0)
  203. {
  204. POINT point;
  205. point.y = rect.CenterPoint().y - (m_sizeImage.cy >> 1);
  206. if (bRight)
  207. point.x = rect.right - m_sizeImage.cx;
  208. else
  209. point.x = rect.left;
  210. SIZE size;
  211. size.cx = rect.Width()<m_sizeImage.cx ? rect.Width():m_sizeImage.cx;
  212. size.cy = m_sizeImage.cy;
  213. // save image list background color
  214. COLORREF rgb = pImageList->GetBkColor();
  215. // set image list background color to same as header control
  216. pImageList->SetBkColor(pDC->GetBkColor());
  217. pImageList->DrawIndirect(pDC, lphdi->iImage, point, size, CPoint(0, 0));
  218. pImageList->SetBkColor(rgb);
  219. iWidth = m_sizeImage.cx;
  220. }
  221. }
  222. }
  223. return iWidth;
  224. }
  225. ///////////////////////////////////////////////////////////////////////////////
  226. // DrawBitmap
  227. int CXHeaderCtrl::DrawBitmap(CDC* pDC, 
  228. CRect rect, 
  229. LPHDITEM lphdi, 
  230. CBitmap* pBitmap, 
  231. BITMAP* pBitmapInfo, 
  232. BOOL bRight)
  233. {
  234. UNUSED_ALWAYS(lphdi);
  235. int iWidth = 0;
  236. if (pBitmap)
  237. {
  238. iWidth = pBitmapInfo->bmWidth;
  239. if (iWidth <= rect.Width() && rect.Width() > 0)
  240. {
  241. POINT point;
  242. point.y = rect.CenterPoint().y - (pBitmapInfo->bmHeight >> 1);
  243. if (bRight)
  244. point.x = rect.right - iWidth;
  245. else
  246. point.x = rect.left;
  247. CDC dc;
  248. if (dc.CreateCompatibleDC(pDC) == TRUE) 
  249. {
  250. VERIFY(dc.SelectObject(pBitmap));
  251. iWidth = pDC->BitBlt(
  252. point.x, point.y, 
  253. pBitmapInfo->bmWidth, pBitmapInfo->bmHeight, 
  254. &dc, 
  255. 0, 0, 
  256. SRCCOPY
  257. ) ? iWidth:0;
  258. }
  259. else 
  260. iWidth = 0;
  261. }
  262. else
  263. iWidth = 0;
  264. }
  265. return iWidth;
  266. }
  267. ///////////////////////////////////////////////////////////////////////////////
  268. // DrawText
  269. int CXHeaderCtrl::DrawText(CDC* pDC, CRect rect, LPHDITEM lphdi)
  270. {
  271. CSize size;
  272. pDC->SetTextColor(RGB(0,0,255));
  273. if (rect.Width() > 0 && lphdi->mask & HDI_TEXT && lphdi->fmt & HDF_STRING)
  274. {
  275. size = pDC->GetTextExtent(lphdi->pszText);
  276. // always center column headers
  277. pDC->DrawText(lphdi->pszText, -1, rect, 
  278. DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
  279. }
  280. size.cx = rect.Width()>size.cx ? size.cx:rect.Width();
  281. return size.cx>0 ? size.cx:0;
  282. }
  283. ///////////////////////////////////////////////////////////////////////////////
  284. // OnInsertItem
  285. LRESULT CXHeaderCtrl::OnInsertItem(WPARAM, LPARAM)
  286. {
  287. return Default();
  288. }
  289. ///////////////////////////////////////////////////////////////////////////////
  290. // OnDeleteItem
  291. LRESULT CXHeaderCtrl::OnDeleteItem(WPARAM, LPARAM)
  292. {
  293. return Default();
  294. }
  295. ///////////////////////////////////////////////////////////////////////////////
  296. // OnSetImageList
  297. LRESULT CXHeaderCtrl::OnSetImageList(WPARAM, LPARAM lParam)
  298. {
  299. CImageList* pImageList;
  300. pImageList = CImageList::FromHandle((HIMAGELIST)lParam);
  301. IMAGEINFO info;
  302. if (pImageList->GetImageInfo(0, &info))
  303. {
  304. m_sizeImage.cx = info.rcImage.right - info.rcImage.left;
  305. m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top;
  306. }
  307. return Default();
  308. }
  309. ///////////////////////////////////////////////////////////////////////////////
  310. // OnLayout
  311. LRESULT CXHeaderCtrl::OnLayout(WPARAM, LPARAM lParam)
  312. {
  313. LPHDLAYOUT lphdlayout = (LPHDLAYOUT)lParam;
  314. if (m_bStaticBorder)
  315. lphdlayout->prc->right += GetSystemMetrics(SM_CXBORDER)*2;
  316. return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
  317. }
  318. ///////////////////////////////////////////////////////////////////////////////
  319. // OnSysColorChange
  320. void CXHeaderCtrl::OnSysColorChange() 
  321. {
  322. TRACE(_T("in CXHeaderCtrl::OnSysColorChangen"));
  323. CHeaderCtrl::OnSysColorChange();
  324. m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
  325. m_cr3DShadow    = ::GetSysColor(COLOR_3DSHADOW);
  326. m_cr3DFace      = ::GetSysColor(COLOR_3DFACE);
  327. m_crBtnText     = ::GetSysColor(COLOR_BTNTEXT);
  328. }
  329. ///////////////////////////////////////////////////////////////////////////////
  330. // OnEraseBkgnd
  331. BOOL CXHeaderCtrl::OnEraseBkgnd(CDC* pDC) 
  332. {
  333. UNUSED_ALWAYS(pDC);
  334. return TRUE;
  335. }
  336. ///////////////////////////////////////////////////////////////////////////////
  337. // OnPaint
  338. void CXHeaderCtrl::OnPaint() 
  339. {
  340.     CPaintDC dc(this);
  341.     if (m_bDoubleBuffer)
  342.     {
  343.         CMemDC MemDC(&dc);
  344.         DrawCtrl(&MemDC);
  345.     }
  346.     else
  347.         DrawCtrl(&dc);
  348. }