XTHeaderCtrl.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:18k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTHeaderCtrl.cpp : implementation of the CXTHeaderCtrl class.
  2. //
  3. // This file is a part of the XTREME CONTROLS MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/XTPResourceManager.h"
  22. #include "Common/XTPWinThemeWrapper.h"
  23. #include "Common/XTPColorManager.h"
  24. #include "Common/XTPDrawHelpers.h"
  25. #include "Common/XTPImageManager.h"
  26. #include "XTGlobal.h"
  27. #include "Resource.h"
  28. #include "XTVC50Helpers.h"
  29. #include "XTHeaderCtrlTheme.h"
  30. #include "XTHeaderCtrl.h"
  31. #include "XTFunctions.h"
  32. #ifdef _DEBUG
  33. #define new DEBUG_NEW
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37. IMPLEMENT_THEME_HOST(CXTHeaderCtrl)
  38. IMPLEMENT_THEME_REFRESH(CXTHeaderCtrl, CHeaderCtrl)
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CXTHeaderCtrl
  41. CXTHeaderCtrl::CXTHeaderCtrl()
  42. : CXTThemeManagerStyleHost(GetThemeFactoryClass())
  43. , m_iMinSize(0)
  44. , m_nPos(0)
  45. , m_iOverIndex(-1)
  46. , m_nSortedCol(-1)
  47. , m_bRTL(DetermineRTL())
  48. , m_bAutoSize(false)
  49. , m_bEnableMenus(TRUE)
  50. , m_bAscending(TRUE)
  51. , m_bLBtnDown(FALSE)
  52. , m_bPainted(FALSE)
  53. , m_popupMenuID(0)
  54. , m_pt(CPoint(0, 0))
  55. {
  56. m_pImageManager = NULL;
  57. }
  58. CXTHeaderCtrl::~CXTHeaderCtrl()
  59. {
  60. CMDTARGET_RELEASE(m_pImageManager);
  61. }
  62. void CXTHeaderCtrl::SetImageManager(CXTPImageManager* pImageManager)
  63. {
  64. CMDTARGET_RELEASE(m_pImageManager);
  65. m_pImageManager = pImageManager;
  66. }
  67. BEGIN_MESSAGE_MAP(CXTHeaderCtrl, CHeaderCtrl)
  68. //{{AFX_MSG_MAP(CXTHeaderCtrl)
  69. ON_WM_WINDOWPOSCHANGING()
  70. ON_WM_SETCURSOR()
  71. ON_WM_PAINT()
  72. ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
  73. ON_WM_ERASEBKGND()
  74. ON_WM_LBUTTONDOWN()
  75. ON_WM_LBUTTONUP()
  76. ON_WM_MOUSEMOVE()
  77. ON_WM_TIMER()
  78. ON_WM_DESTROY()
  79. ON_WM_RBUTTONDOWN()
  80. ON_NOTIFY_REFLECT_EX(HDN_ITEMCHANGING, OnItemchanging)
  81. ON_COMMAND(XT_IDC_SORTASC, OnSortAsc)
  82. ON_COMMAND(XT_IDC_SORTDSC, OnSortDsc)
  83. ON_COMMAND(XT_IDC_ALIGNLEFT, OnAlignLeft)
  84. ON_COMMAND(XT_IDC_ALIGNCENTER, OnAlignCenter)
  85. ON_COMMAND(XT_IDC_ALIGNRIGHT, OnAlignRight)
  86. ON_MESSAGE(HDM_LAYOUT, OnLayout)
  87. //}}AFX_MSG_MAP
  88. END_MESSAGE_MAP()
  89. IMPLEMENT_DYNAMIC(CXTHeaderCtrl, CHeaderCtrl)
  90. /////////////////////////////////////////////////////////////////////////////
  91. // CXTHeaderCtrl message handlers
  92. void CXTHeaderCtrl::OnThemeChanged()
  93. {
  94. RecalcLayout();
  95. }
  96. BOOL CXTHeaderCtrl::IsThemeValid() const
  97. {
  98. return (GetTheme() != NULL);
  99. }
  100. void CXTHeaderCtrl::ApplyFieldWidths(int iNewWidth)
  101. {
  102. CListCtrl* pListCtrl = (CListCtrl*)GetParent();
  103. ASSERT_VALID(pListCtrl);
  104. int iItemCount = GetItemCount();
  105. int iFrozenCount = (int)m_arFrozenCols.GetCount();
  106. int iThawedCount = iItemCount - iFrozenCount;
  107. if (iThawedCount <= 0)
  108. return;
  109. int iWidth = iNewWidth/iThawedCount;
  110. int iItem;
  111. for (iItem = 0; iItem < iItemCount; iItem++)
  112. {
  113. if (IsColFrozen(iItem))
  114. continue;
  115. if (iWidth > m_iMinSize)
  116. pListCtrl->SetColumnWidth(iItem, iWidth);
  117. iNewWidth -= iWidth;
  118. }
  119. }
  120. void CXTHeaderCtrl::ResizeColumnsToFit()
  121. {
  122. FitFieldWidths(0);
  123. }
  124. void CXTHeaderCtrl::FitFieldWidths(int iNewWidth)
  125. {
  126. if (iNewWidth <= 0)
  127. {
  128. CXTPWindowRect rc(this);
  129. iNewWidth = rc.Width();
  130. }
  131. // adjust for vertical scroll bar.
  132. DWORD dwStyle = ::GetWindowLong(::GetParent(m_hWnd), GWL_STYLE);
  133. if ((dwStyle & WS_VSCROLL) == WS_VSCROLL)
  134. iNewWidth -= ::GetSystemMetrics(SM_CXVSCROLL);
  135. // adjust for frozen columns.
  136. iNewWidth -= GetFrozenColWidth();
  137. ApplyFieldWidths(iNewWidth);
  138. }
  139. void CXTHeaderCtrl::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
  140. {
  141. if (m_bAutoSize)
  142. {
  143. int iCount = GetItemCount();
  144. if (iCount > 0)
  145. {
  146. if (GetCapture() != GetParent()) // indicates scrolling
  147. {
  148. // is the window size changing?
  149. CXTPWindowRect rc(this);
  150. if (rc.Width() != lpwndpos->cx)
  151. {
  152. FitFieldWidths(lpwndpos->cx);
  153. }
  154. }
  155. }
  156. }
  157. else
  158. {
  159. CHeaderCtrl::OnWindowPosChanging(lpwndpos);
  160. }
  161. }
  162. void CXTHeaderCtrl::EnableAutoSize(bool bEnable/*=true*/)
  163. {
  164. m_bAutoSize = bEnable;
  165. }
  166. void CXTHeaderCtrl::FreezeColumn(int iCol)
  167. {
  168. m_arFrozenCols.AddTail(iCol);
  169. }
  170. void CXTHeaderCtrl::ThawColumn(int iCol)
  171. {
  172. for (POSITION pos = m_arFrozenCols.GetHeadPosition(); pos; m_arFrozenCols.GetNext(pos))
  173. {
  174. int iNext = m_arFrozenCols.GetAt(pos);
  175. if (iNext == iCol)
  176. {
  177. m_arFrozenCols.RemoveAt(pos);
  178. break;
  179. }
  180. }
  181. }
  182. void CXTHeaderCtrl::ThawAllColumns()
  183. {
  184. m_arFrozenCols.RemoveAll();
  185. }
  186. BOOL CXTHeaderCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  187. {
  188. if (m_arFrozenCols.GetCount())
  189. {
  190. CPoint pt;
  191. ::GetCursorPos(&pt);
  192. CPoint ptClient = pt;
  193. ScreenToClient(&ptClient);
  194. HDHITTESTINFO hti;
  195. ::ZeroMemory(&hti, sizeof(hti));
  196. hti.pt.x = ptClient.x;
  197. hti.pt.y = ptClient.y;
  198. int nIndex = (int)::SendMessage(GetSafeHwnd(),
  199. HDM_HITTEST, 0L, (LPARAM)&hti);
  200. if (nIndex > -1)
  201. {
  202. // if we are over one of the frozen columns, we can stop
  203. if (IsColFrozen(nIndex))
  204. {
  205. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  206. return TRUE;
  207. }
  208. else
  209. {
  210. // determine if the current index is adjacent to a frozen column index.
  211. // if columns are resized by dragging to the right, test for the frozen column on the left.
  212. // if columns are resized by dragging to the left, test for the frozen column on the right.
  213. int iAdjIndex = nIndex + (m_bRTL ? 1 : -1);
  214. if ((iAdjIndex > -1) && IsColFrozen(iAdjIndex))
  215. {
  216. CRect r;
  217. Header_GetItemRect(m_hWnd, nIndex, &r);
  218. int nMidPoint = (r.left + (r.Width()/2));
  219. // if columns resize to the right and the point is the right half of the header item...
  220. if (!m_bRTL && (ptClient.x <= nMidPoint))
  221. {
  222. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  223. return TRUE;
  224. }
  225. // if columns resize to the left and the point is the left half of the header item...
  226. else if (m_bRTL && (ptClient.x >= nMidPoint))
  227. {
  228. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  229. return TRUE;
  230. }
  231. }
  232. }
  233. }
  234. }
  235. return CHeaderCtrl::OnSetCursor(pWnd, nHitTest, message);
  236. }
  237. BOOL CXTHeaderCtrl::OnItemchanging(NMHDR* pNMHDR, LRESULT* pResult)
  238. {
  239. HD_NOTIFY* pHDN = (HD_NOTIFY*)pNMHDR;
  240. *pResult = FALSE;
  241. if (pHDN && (pHDN->pitem->mask & HDI_WIDTH) != 0)
  242. {
  243. // if sizing is disabled for this column, keep the user from resizing
  244. if (m_arFrozenCols.GetCount() && IsColFrozen(pHDN->iItem))
  245. *pResult = TRUE;
  246. // if the column is smaller than the minimum size, keep the user from resizing
  247. if (pHDN->pitem->mask & HDI_WIDTH && pHDN->pitem->cxy < m_iMinSize)
  248. *pResult = TRUE;
  249. }
  250. return BOOL(*pResult);
  251. }
  252. bool CXTHeaderCtrl::IsColFrozen(int iCol)
  253. {
  254. for (POSITION pos = m_arFrozenCols.GetHeadPosition(); pos; m_arFrozenCols.GetNext(pos))
  255. {
  256. int iNext = m_arFrozenCols.GetAt(pos);
  257. if (iNext == iCol)
  258. {
  259. return true;
  260. }
  261. }
  262. return false;
  263. }
  264. bool CXTHeaderCtrl::DetermineRTL()
  265. {
  266. CWindowDC dc(NULL);
  267. // determine if columns are resized by dragging them right (most languages) or
  268. // left (RTL languages like Arabic & Hebrew).
  269. UINT nAlign = dc.GetTextAlign();
  270. ASSERT(nAlign != GDI_ERROR);
  271. // will only be true for RTL languages, text is laid out right to left and
  272. // columns resize to the left
  273. if ((nAlign != GDI_ERROR) && (nAlign & TA_RTLREADING))
  274. {
  275. return true;
  276. }
  277. return false;
  278. }
  279. int CXTHeaderCtrl::GetFrozenColWidth()
  280. {
  281. int iFrozenWidth = 0;
  282. for (POSITION pos = m_arFrozenCols.GetHeadPosition(); pos; m_arFrozenCols.GetNext(pos))
  283. {
  284. int iCol = m_arFrozenCols.GetAt(pos);
  285. CRect r;
  286. Header_GetItemRect(m_hWnd, iCol, &r);
  287. iFrozenWidth += r.Width();
  288. }
  289. return iFrozenWidth;
  290. }
  291. void CXTHeaderCtrl::SetMinSize(int iMinSize)
  292. {
  293. m_iMinSize = iMinSize;
  294. }
  295. void CXTHeaderCtrl::OnPaint()
  296. {
  297. CPaintDC dc(this);
  298. if (IsThemeValid())
  299. {
  300. CXTPBufferDC memDC(dc);
  301. GetTheme()->DrawHeader(&memDC, this);
  302. }
  303. else
  304. {
  305. CHeaderCtrl::DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, 0);
  306. }
  307. }
  308. LRESULT CXTHeaderCtrl::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
  309. {
  310. CDC* pDC = CDC::FromHandle((HDC)wParam);
  311. if (pDC && IsThemeValid())
  312. {
  313. GetTheme()->DrawHeader(pDC, this);
  314. return TRUE;
  315. }
  316. return Default();
  317. }
  318. BOOL CXTHeaderCtrl::OnEraseBkgnd(CDC* /*pDC*/)
  319. {
  320. return TRUE;
  321. }
  322. void CXTHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
  323. {
  324. m_bLBtnDown = TRUE;
  325. CHeaderCtrl::OnLButtonDown(nFlags, point);
  326. }
  327. void CXTHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
  328. {
  329. m_bLBtnDown = FALSE;
  330. CHeaderCtrl::OnLButtonUp(nFlags, point);
  331. }
  332. void CXTHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)
  333. {
  334. if (IsThemeValid() && GetTheme()->UseWinXPThemes(this))
  335. {
  336. SetTimer(1, 10, NULL);
  337. }
  338. CHeaderCtrl::OnMouseMove(nFlags, point);
  339. }
  340. int CXTHeaderCtrl::HitTest(CPoint pt, UINT* pFlags/*=NULL*/) const
  341. {
  342. HDHITTESTINFO hti;
  343. hti.pt.x = pt.x;
  344. hti.pt.y = pt.y;
  345. int iItem = (int)::SendMessage(m_hWnd, HDM_HITTEST, 0, (LPARAM)(&hti));
  346. if (pFlags != NULL)
  347. *pFlags = hti.flags;
  348. return iItem;
  349. }
  350. BOOL CXTHeaderCtrl::ItemPressed(int iItem)
  351. {
  352. if (m_bLBtnDown)
  353. {
  354. CPoint point;
  355. ::GetCursorPos(&point);
  356. ScreenToClient(&point);
  357. UINT uFlags;
  358. if (HitTest(point, &uFlags) == iItem)
  359. return ((uFlags & HHT_ONHEADER) == HHT_ONHEADER);
  360. }
  361. return FALSE;
  362. }
  363. void CXTHeaderCtrl::OnTimer(UINT_PTR nIDEvent)
  364. {
  365. if (nIDEvent == 1)
  366. {
  367. CPoint pt;
  368. ::GetCursorPos(&pt);
  369. ScreenToClient(&pt);
  370. int iOverIndex = HitTest(pt);
  371. if (iOverIndex == -1)
  372. {
  373. KillTimer(1);
  374. if (m_bPainted == TRUE)
  375. {
  376. RedrawWindow();
  377. }
  378. m_bPainted = false;
  379. return;
  380. }
  381. if (iOverIndex != m_iOverIndex)
  382. {
  383. m_iOverIndex = iOverIndex;
  384. m_bPainted = false;
  385. }
  386. if (!m_bPainted)
  387. {
  388. RedrawWindow();
  389. m_bPainted = true;
  390. }
  391. }
  392. CHeaderCtrl::OnTimer(nIDEvent);
  393. }
  394. LRESULT CXTHeaderCtrl::OnLayout(WPARAM wParam, LPARAM lParam)
  395. {
  396. if (IsThemeValid())
  397. {
  398. return (LRESULT)GetTheme()->Layout(
  399. (LPHDLAYOUT)lParam, this);
  400. }
  401. return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, wParam, lParam);
  402. }
  403. int CXTHeaderCtrl::SetSortImage(int iSortCol, BOOL bSortAsc)
  404. {
  405. ASSERT(iSortCol < GetItemCount());
  406. int nPrevCol = m_nSortedCol;
  407. m_nSortedCol = iSortCol;
  408. m_bAscending = bSortAsc;
  409. RedrawWindow();
  410. return nPrevCol;
  411. }
  412. int CXTHeaderCtrl::GetSortedCol(BOOL* pbSortAsc/*=NULL*/)
  413. {
  414. if (pbSortAsc)
  415. *pbSortAsc = m_bAscending;
  416. return m_nSortedCol;
  417. }
  418. BOOL CXTHeaderCtrl::RecalcLayout()
  419. {
  420. if (!::IsWindow(m_hWnd))
  421. return FALSE;
  422. HD_LAYOUT hdl;
  423. CXTPClientRect rcClient(this);
  424. hdl.prc = &rcClient;
  425. WINDOWPOS wp;
  426. ZeroMemory(&wp, sizeof(WINDOWPOS));
  427. hdl.pwpos = &wp;
  428. if (!Header_Layout(m_hWnd, &hdl))
  429. return FALSE;
  430. // Set the size, position, and visibility of the header window.
  431. ::SetWindowPos(m_hWnd, wp.hwndInsertAfter, wp.x, wp.y,
  432. wp.cx, wp.cy, wp.flags | SWP_FRAMECHANGED);
  433. CWnd* pWndParent = GetParent();
  434. if (!::IsWindow(pWndParent->GetSafeHwnd()))
  435. return FALSE;
  436. // Force list control to recalculate it's layout.
  437. CXTPWindowRect rcWindow(pWndParent);
  438. const int cx = rcWindow.Width();
  439. const int cy = rcWindow.Height();
  440. pWndParent->SetWindowPos(NULL, 0, 0, cx, cy+1,
  441. SWP_NOMOVE | SWP_FRAMECHANGED);
  442. pWndParent->SetWindowPos(NULL, 0, 0, cx, cy,
  443. SWP_NOMOVE | SWP_FRAMECHANGED);
  444. return TRUE;
  445. }
  446. void CXTHeaderCtrl::OnDestroy()
  447. {
  448. if (IsThemeValid())
  449. GetTheme()->CleanUp(this);
  450. CHeaderCtrl::OnDestroy();
  451. }
  452. void CXTHeaderCtrl::SetBitmap(int iCol, UINT uBitmapID, DWORD dwRemove/*=NULL*/)
  453. {
  454. if (dwRemove)
  455. {
  456. HD_ITEM hdi;
  457. hdi.mask = HDI_FORMAT;
  458. GetItem(iCol, &hdi);
  459. hdi.fmt &= ~dwRemove;
  460. SetItem(iCol, &hdi);
  461. }
  462. SetBitmap(iCol, uBitmapID, FALSE, RGB(192, 192, 192));
  463. }
  464. void CXTHeaderCtrl::SetBitmap(int iCol, UINT uBitmapID, BOOL bRemove, COLORREF crMask)
  465. {
  466. if (IsThemeValid())
  467. {
  468. GetTheme()->SetBitmap(iCol, uBitmapID, bRemove, crMask, this);
  469. }
  470. }
  471. void CXTHeaderCtrl::InitializeHeader(BOOL bBoldFont)
  472. {
  473. SetFont(bBoldFont ? &XTAuxData().fontBold : &XTAuxData().font);
  474. RedrawWindow();
  475. }
  476. void CXTHeaderCtrl::OnRButtonDown(UINT nFlags, CPoint point)
  477. {
  478. CPoint pt = m_pt = point;
  479. ClientToScreen(&pt);
  480. // If no sort headers are defined for the parent control or popup menus
  481. // has been disabled, call the base class and return.
  482. CWnd* pParentWnd = GetParent();
  483. if (pParentWnd->GetStyle() & LVS_NOSORTHEADER || m_bEnableMenus == FALSE)
  484. {
  485. CHeaderCtrl::OnRButtonDown(nFlags, point);
  486. return;
  487. }
  488. // No menu was defined use default
  489. if (!m_popupMenuID)
  490. {
  491. // Get the index to the header item under the cursor.
  492. int iIndex = HitTest(m_pt);
  493. if (iIndex != -1)
  494. {
  495. CMenu menu;
  496. VERIFY(XTPResourceManager()->LoadMenu(&menu, XT_IDM_POPUP));
  497. CMenu* pPopup = menu.GetSubMenu(2);
  498. ASSERT(pPopup != NULL);
  499. if (!pPopup)
  500. return;
  501. if (m_nSortedCol == iIndex && m_bAscending == TRUE)
  502. pPopup->CheckMenuItem(XT_IDC_SORTASC, MF_CHECKED | MF_BYCOMMAND);
  503. else if (m_nSortedCol == iIndex && m_bAscending == FALSE)
  504. pPopup->CheckMenuItem(XT_IDC_SORTDSC, MF_CHECKED | MF_BYCOMMAND);
  505. if (pParentWnd && (
  506. pParentWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) ||
  507. pParentWnd->IsKindOf(RUNTIME_CLASS(CListView))))
  508. {
  509. LVCOLUMN lvc;
  510. lvc.mask = LVCF_FMT;
  511. ListView_GetColumn(pParentWnd->m_hWnd, iIndex, &lvc);
  512. switch (lvc.fmt & LVCFMT_JUSTIFYMASK)
  513. {
  514. case LVCFMT_LEFT:
  515. pPopup->CheckMenuItem(XT_IDC_ALIGNLEFT, MF_CHECKED | MF_BYCOMMAND);
  516. break;
  517. case LVCFMT_CENTER:
  518. pPopup->CheckMenuItem(XT_IDC_ALIGNCENTER, MF_CHECKED | MF_BYCOMMAND);
  519. break;
  520. case LVCFMT_RIGHT:
  521. pPopup->CheckMenuItem(XT_IDC_ALIGNRIGHT, MF_CHECKED | MF_BYCOMMAND);
  522. break;
  523. }
  524. }
  525. XTFuncContextMenu(pPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this, XT_IDR_TBAR_HDR);
  526. }
  527. }
  528. else
  529. {
  530. CMenu menu;
  531. VERIFY(menu.LoadMenu(m_popupMenuID));
  532. CMenu* pPopup = menu.GetSubMenu(m_nPos);
  533. ASSERT(pPopup != NULL);
  534. if (!pPopup)
  535. return;
  536. pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  537. pt.x, pt.y, GetOwner());
  538. }
  539. }
  540. void CXTHeaderCtrl::SetMenuID(UINT popupMenuID, int nPos)
  541. {
  542. m_popupMenuID = popupMenuID;
  543. m_nPos = nPos;
  544. }
  545. void CXTHeaderCtrl::SendNotify(int iIndex)
  546. {
  547. CWnd* pParentWnd = GetParent();
  548. if (!pParentWnd || !::IsWindow(pParentWnd->m_hWnd))
  549. return;
  550. if (pParentWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) ||
  551. pParentWnd->IsKindOf(RUNTIME_CLASS(CListView)))
  552. {
  553. TCHAR  lpBuffer[256];
  554. HDITEM hdi;
  555. hdi.mask = HDI_TEXT | HDI_BITMAP | HDI_FORMAT | HDI_IMAGE | HDI_LPARAM | HDI_ORDER | HDI_WIDTH;
  556. hdi.pszText = lpBuffer;
  557. hdi.cchTextMax = 256;
  558. GetItem(iIndex, &hdi);
  559. NMHEADER nmh;
  560. nmh.hdr.hwndFrom = m_hWnd;
  561. nmh.hdr.idFrom = GetDlgCtrlID();
  562. nmh.hdr.code = HDN_ITEMCLICK;
  563. nmh.iItem = iIndex;
  564. nmh.iButton = 1;
  565. nmh.pitem = &hdi;
  566. // send message to the parent's owner window.
  567. pParentWnd->SendMessage(WM_NOTIFY,
  568. (WPARAM)(int)nmh.hdr.idFrom, (LPARAM)(NMHEADER*)&nmh);
  569. // then forward to the descendants.
  570. pParentWnd->SendMessageToDescendants(WM_NOTIFY,
  571. (WPARAM)(int)nmh.hdr.idFrom, (LPARAM)(NMHEADER*)&nmh);
  572. }
  573. }
  574. void CXTHeaderCtrl::OnSortAsc()
  575. {
  576. int iIndex = HitTest(m_pt);
  577. if (iIndex != -1)
  578. {
  579. if (m_nSortedCol != iIndex || m_bAscending == FALSE)
  580. {
  581. m_bAscending = TRUE;
  582. m_nSortedCol = iIndex;
  583. SendNotify(iIndex);
  584. }
  585. }
  586. }
  587. void CXTHeaderCtrl::OnSortDsc()
  588. {
  589. int iIndex = HitTest(m_pt);
  590. if (iIndex != -1)
  591. {
  592. if (m_nSortedCol != iIndex || m_bAscending == TRUE)
  593. {
  594. m_bAscending = FALSE;
  595. m_nSortedCol = iIndex;
  596. SendNotify(iIndex);
  597. }
  598. }
  599. }
  600. BOOL CXTHeaderCtrl::SetAlingment(int nFlag)
  601. {
  602. int iIndex = HitTest(m_pt);
  603. if (iIndex != -1)
  604. {
  605. CWnd* pParentWnd = GetParent();
  606. if (pParentWnd && (
  607. pParentWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) ||
  608. pParentWnd->IsKindOf(RUNTIME_CLASS(CListView))))
  609. {
  610. LVCOLUMN lvc;
  611. lvc.mask = LVCF_FMT;
  612. ListView_GetColumn(pParentWnd->m_hWnd, iIndex, &lvc);
  613. lvc.fmt &= ~LVCFMT_JUSTIFYMASK;
  614. lvc.fmt |= nFlag;
  615. ListView_SetColumn(pParentWnd->m_hWnd, iIndex, &lvc);
  616. ListView_SetWorkAreas(pParentWnd->m_hWnd, 0, NULL);
  617. }
  618. }
  619. return FALSE;
  620. }
  621. void CXTHeaderCtrl::OnAlignLeft()
  622. {
  623. SetAlingment(LVCFMT_LEFT);
  624. }
  625. void CXTHeaderCtrl::OnAlignCenter()
  626. {
  627. SetAlingment(LVCFMT_CENTER);
  628. }
  629. void CXTHeaderCtrl::OnAlignRight()
  630. {
  631. SetAlingment(LVCFMT_RIGHT);
  632. }
  633. BOOL CXTHeaderCtrl::HasSortArrow()
  634. {
  635. if (IsThemeValid())
  636. return GetTheme()->HasSortArrow();
  637. return FALSE;
  638. }
  639. void CXTHeaderCtrl::ShowSortArrow(BOOL bSortArrow)
  640. {
  641. if (IsThemeValid())
  642. {
  643. DWORD dwStyle = GetTheme()->GetDrawStyle() & ~XTTHEME_SORTARROW;
  644. if (bSortArrow)
  645. dwStyle |= XTTHEME_SORTARROW;
  646. GetTheme()->SetDrawStyle(dwStyle, this);
  647. }
  648. }
  649. void CXTHeaderCtrl::SetFontBold(BOOL bBoldFont)
  650. {
  651. ASSERT(::IsWindow(m_hWnd));
  652. SetFont(bBoldFont ? &XTAuxData().fontBold : &XTAuxData().font);
  653. }
  654. /////////////////////////////////////////////////////////////////////////////
  655. // CXTFlatHeaderCtrl
  656. IMPLEMENT_DYNAMIC(CXTFlatHeaderCtrl, CXTHeaderCtrl)
  657. CXTFlatHeaderCtrl::CXTFlatHeaderCtrl()
  658. {
  659. SetTheme(new CXTHeaderCtrlThemeOfficeXP());
  660. }
  661. CXTFlatHeaderCtrl::~CXTFlatHeaderCtrl()
  662. {
  663. }