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

对话框与窗口

开发平台:

Visual C++

  1. // XTPReportHeader.cpp : implementation of the CXTPReportHeader class.
  2. //
  3. // This file is a part of the XTREME REPORTCONTROL 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 "Resource.h"
  22. #include "Common/Resource.h"
  23. #include "Common/XTPDrawHelpers.h"
  24. #include "Common/XTPPropExchange.h"
  25. #include "Common/XTPToolTipContext.h"
  26. #include "Common/XTPResourceManager.h"
  27. #include "XTPReportColumn.h"
  28. #include "XTPReportColumns.h"
  29. #include "XTPReportRecordItem.h"
  30. #include "XTPReportControl.h"
  31. #include "XTPReportPaintManager.h"
  32. #include "XTPReportSubListControl.h"
  33. #include "XTPReportFilterEditControl.h"
  34. #include "XTPReportDragDrop.h"
  35. #include "XTPReportInplaceControls.h"
  36. #include "XTPReportHeader.h"
  37. #ifdef _DEBUG
  38. #define new DEBUG_NEW
  39. #undef THIS_FILE
  40. static char THIS_FILE[] = __FILE__;
  41. #endif
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CXTPReportHeader
  44. int CXTPReportHeader::s_nMinAutoScrollStep = 3;
  45. BOOL CXTPReportHeader::s_bShowItemsInGroupsPXDefault = TRUE;
  46. BOOL CXTPReportHeader::s_bSendContextMenuForWholeHeaderArea = FALSE;
  47. CXTPReportHeader::CXTPReportHeader(CXTPReportControl* pControl, CXTPReportColumns* pColumns)
  48. : m_pColumns(pColumns), m_pControl(pControl)
  49. {
  50. m_nResizeCaptureRange = 3;
  51. m_pSubList = NULL;
  52. m_pFilterEdit = NULL;
  53. m_dragMode = dragNothing;
  54. m_nDropIndex = -1;
  55. m_rcHeader.SetRect(0, 0, 0, 0);
  56. m_pDropWnd = NULL;
  57. m_pDragWnd = NULL;
  58. m_pHotTrackingColumn = NULL;
  59. m_bAllowColumnResize = TRUE;
  60. m_bAllowColumnRemove = TRUE;
  61. m_bAllowColumnReorder = TRUE;
  62. m_bAllowColumnSort = TRUE;
  63. m_pDragColumn = NULL;
  64. m_hResizeCursor = XTPResourceManager()->LoadCursor(XTP_IDC_VRESIZE);
  65. m_hDontDropCursor = XTPResourceManager()->LoadCursor(XTP_IDC_REPORT_NODROP);
  66. m_bShowItemsInGroups = FALSE;
  67. m_bDragHeader = m_bDragGroupBox = FALSE;
  68. m_nIndentLevel = 0;
  69. m_bAutoColumnSizing = TRUE;
  70. m_nHeaderWidth = 0;
  71. }
  72. CXTPReportHeader::~CXTPReportHeader()
  73. {
  74. DestroyDropWnd();
  75. if (m_pDragWnd)
  76. m_pDragWnd->DestroyWindow();
  77. }
  78. CXTPReportPaintManager* CXTPReportHeader::GetPaintManager() const
  79. {
  80. return m_pControl->GetPaintManager();
  81. }
  82. void CXTPReportHeader::Draw(CDC* pDC, CRect rcHeader, int nLeftOffset)
  83. {
  84. int nFreezeCols = GetControl()->m_nFreezeColumnsCount;
  85. rcHeader.OffsetRect(-nLeftOffset, 0);
  86. m_rcHeader = rcHeader;
  87. // draw background
  88. CXTPClientRect rcHeaderClientArea(m_pControl);
  89. rcHeaderClientArea.top = rcHeader.top;
  90. rcHeaderClientArea.bottom = rcHeader.bottom;
  91. GetPaintManager()->FillHeaderControl(pDC, rcHeaderClientArea);
  92. int x = rcHeader.left;
  93. // draw items
  94. int nColumnsCount = m_pColumns->GetCount(), nColumn;
  95. for (nColumn = 0; nColumn < nColumnsCount; nColumn++)
  96. {
  97. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  98. if (pColumn && pColumn->IsVisible())
  99. {
  100. CRect rcItem(x, rcHeader.top, x + pColumn->GetWidth(), rcHeader.bottom);
  101. pColumn->m_rcColumn = rcItem;
  102. if (rcItem.Height() > 0 && CRect().IntersectRect(rcHeaderClientArea, rcItem))
  103. {
  104. GetPaintManager()->DrawColumn(pDC, pColumn, this, rcItem);
  105. }
  106. x += rcItem.Width();
  107. pColumn->m_nMaxItemWidth = 0;
  108. }
  109. }
  110. int xFreeze = 0;
  111. // draw freeze items
  112. for (nColumn = 0; nFreezeCols > 0 && nColumn < nColumnsCount; nColumn++)
  113. {
  114. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  115. if (pColumn && pColumn->IsVisible())
  116. {
  117. CRect rcItem(xFreeze, rcHeader.top, xFreeze + pColumn->GetWidth(), rcHeader.bottom);
  118. pColumn->m_rcColumn = rcItem;
  119. if (rcItem.Height() > 0 && CRect().IntersectRect(rcHeaderClientArea, rcItem))
  120. {
  121. GetPaintManager()->FillHeaderControl(pDC, pColumn->m_rcColumn);
  122. GetPaintManager()->DrawColumn(pDC, pColumn, this, rcItem);
  123. if (nFreezeCols == 1 &&
  124. (GetPaintManager()->GetFreezeColsDividerStyle() & xtpReportFreezeColsDividerHeader))
  125. GetPaintManager()->DrawFreezeColsDivider(pDC, rcItem, GetControl());
  126. }
  127. xFreeze += rcItem.Width();
  128. nFreezeCols--;
  129. }
  130. }
  131. // draw empty column to fill free header area
  132. if (x < rcHeaderClientArea.right)
  133. {
  134. CRect rcEmptyColumn = rcHeaderClientArea;
  135. rcEmptyColumn.left = x;
  136. rcEmptyColumn.right += 10;
  137. CXTPReportColumn colEmpty(0, _T(""), rcEmptyColumn.Width(), FALSE,
  138. XTP_REPORT_NOICON, FALSE, TRUE);
  139. ASSERT(m_pColumns);
  140. colEmpty.m_pColumns = m_pColumns;
  141. GetPaintManager()->DrawColumn(pDC, &colEmpty, this, rcEmptyColumn);
  142. }
  143. }
  144. void CXTPReportHeader::CancelMouseMode()
  145. {
  146. if (m_pControl->GetMouseMode() != xtpReportMouseNothing)
  147. {
  148. m_pControl->SetMouseMode(xtpReportMouseNothing);
  149. m_pDragColumn = NULL;
  150. SetHotDivider(-1);
  151. // Drag wnd cleanup
  152. if (m_pDragWnd != NULL)
  153. {
  154. m_pDragWnd->DestroyWindow();
  155. m_pDragWnd = NULL;
  156. }
  157. if (CWnd::GetCapture() == m_pControl)
  158. ReleaseCapture();
  159. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  160. m_bDragGroupBox = FALSE;
  161. m_bDragHeader = FALSE;
  162. m_pControl->RedrawControl();
  163. }
  164. }
  165. void CXTPReportHeader::SetAutoColumnSizing(BOOL bAutoColumnSizing)
  166. {
  167. m_bAutoColumnSizing = bAutoColumnSizing;
  168. m_pControl->m_nLeftOffset = 0;
  169. if (m_bAutoColumnSizing && m_pControl->m_hWnd)
  170. {
  171. m_pControl->EnableScrollBarCtrl(SB_HORZ, FALSE);
  172. }
  173. AdjustColumnsWidth(m_pControl->m_rcHeaderArea.Width());
  174. m_pControl->RedrawControl();
  175. }
  176. void CXTPReportHeader::OnColumnsChanged(BOOL bGroupOrderChanged)
  177. {
  178. AdjustColumnsWidth(m_pControl->m_rcHeaderArea.Width());
  179. if (!GetPaintManager()->IsFixedRowHeight())
  180. m_pControl->AdjustScrollBars();
  181. m_pControl->UpdateSubList();
  182. m_pControl->RedrawControl();
  183. m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNORDERCHANGED);
  184. if(bGroupOrderChanged)
  185. m_pControl->SendNotifyMessage(XTP_NM_REPORT_GROUPORDERCHANGED);
  186. }
  187. void CXTPReportHeader::TrackColumn(CXTPReportColumn* pColumn, CPoint point)
  188. {
  189. CXTPClientRect rcControl(m_pControl);
  190. m_pControl->ClientToScreen(&point);
  191. CRect rcColumn(pColumn->GetRect());
  192. rcColumn.bottom = rcControl.bottom;
  193. m_pControl->ClientToScreen(&rcColumn);
  194. int nBottomMax = rcColumn.bottom;
  195. CDC* pDC = m_pControl->GetDC();
  196. if (pDC)
  197. {
  198. CRect rcVisible;
  199. UINT uRes = pDC->GetBoundsRect(&rcVisible, 0);
  200. m_pControl->ReleaseDC(pDC);
  201. pDC = NULL;
  202. if ((uRes & DCB_SET) == DCB_SET)
  203. {
  204. m_pControl->ClientToScreen(&rcVisible);
  205. nBottomMax = min(rcVisible.bottom, nBottomMax);
  206. }
  207. }
  208. int nMaxAvailWidth = GetMaxAvailWidth(pColumn);
  209. int nMinWidth = pColumn->GetMinWidth();
  210. CRect rcAvail(rcColumn.left + nMinWidth, rcColumn.top,
  211. rcColumn.left + nMaxAvailWidth, nBottomMax);
  212. CRect rcTracker(rcColumn.right, rcColumn.top, rcColumn.right + 1, nBottomMax);
  213. CRect rcBound(rcColumn.left - 1, rcColumn.top, rcColumn.left, nBottomMax);
  214. BOOL bLayoutRTL = m_pControl->GetExStyle() & WS_EX_LAYOUTRTL;
  215. if (bLayoutRTL)
  216. {
  217. rcAvail.SetRect(rcColumn.left - nMaxAvailWidth, rcColumn.top,
  218. rcColumn.right - nMinWidth, nBottomMax);
  219. }
  220. CXTPSplitterTracker tracker(TRUE);
  221. tracker.SetBoundRect(bLayoutRTL ? rcTracker : rcBound);
  222. if (tracker.Track(m_pControl, rcAvail, bLayoutRTL ? rcBound : rcTracker, point, TRUE))
  223. {
  224. ResizeColumn(pColumn, rcTracker.left - rcBound.right);
  225. m_pControl->RedrawControl();
  226. }
  227. }
  228. void CXTPReportHeader::OnLButtonDblClk(CPoint ptClick)
  229. {
  230. if (m_pControl->GetMouseMode() == xtpReportMouseOverColumnDivide)
  231. {
  232. CPoint ptLeftColumn(ptClick);
  233. ptLeftColumn.x -= m_nResizeCaptureRange + 1;
  234. CXTPReportColumn* pColumn = HitTest(ptLeftColumn);
  235. if (pColumn != NULL)
  236. {
  237. BestFit(pColumn);
  238. }
  239. }
  240. }
  241. void CXTPReportHeader::OnLButtonDown(CPoint ptClick)
  242. {
  243. m_pControl->SetCapture();
  244. if (m_pControl->GetMouseMode() == xtpReportMouseOverColumnDivide)
  245. {
  246. CXTPReportColumn* pColumn = MouseOverColumnResizeArea(ptClick);
  247. if (pColumn != NULL && pColumn->IsResizable() && m_bAllowColumnResize)
  248. {
  249. if (!m_bAutoColumnSizing || (!IsLastResizebleColumn(pColumn) && !IsLastVisibleColumn(pColumn)))
  250. {
  251. m_pControl->SetMouseMode(xtpReportMouseNothing);
  252. TrackColumn(pColumn, ptClick);
  253. return;
  254. }
  255. }
  256. }
  257. if (m_pControl->GetMouseMode() == xtpReportMouseNothing)
  258. {
  259. BOOL bDragHeader = FALSE;
  260. CXTPReportColumn* pColumn = NULL;
  261. if (m_rcHeader.PtInRect(ptClick))
  262. {
  263. int nColumn = HitTestHeaderColumnIndex(ptClick);
  264. pColumn = m_pColumns->GetAt(nColumn);
  265. bDragHeader = TRUE;
  266. }
  267. else if (m_rcGroupBy.PtInRect(ptClick))
  268. {
  269. int nColumn = FindGroupByColumn(ptClick, TRUE);
  270. pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
  271. }
  272. if (pColumn != NULL)
  273. {
  274. StartDragging(pColumn, bDragHeader);
  275. m_ptMouse = ptClick;
  276. m_pControl->SetMouseMode(xtpReportMousePrepareDragColumn);
  277. m_pControl->RedrawControl();
  278. }
  279. }
  280. }
  281. void CXTPReportHeader::AdjustColumnsWidth(int nTotalWidth, int nFirstIndex)
  282. {
  283. if (m_bAutoColumnSizing)
  284. {
  285. int nColumnsWidth = 0;
  286. CXTPReportColumn* pLastAutoColumn = NULL;
  287. int nColumn;
  288. for (nColumn = nFirstIndex; nColumn < m_pColumns->GetCount(); nColumn++)
  289. {
  290. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  291. if (!pColumn->IsVisible())
  292. continue;
  293. if (pColumn->m_bAutoSize)
  294. {
  295. pLastAutoColumn = pColumn;
  296. nColumnsWidth += pColumn->m_nColumnAutoWidth;
  297. }
  298. else
  299. {
  300. nTotalWidth -= pColumn->GetWidth();
  301. }
  302. }
  303. if (pLastAutoColumn && nTotalWidth > 0)
  304. {
  305. for (nColumn = nFirstIndex; nColumn < m_pColumns->GetCount(); nColumn++)
  306. {
  307. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  308. if (!pColumn->IsVisible())
  309. continue;
  310. if (pColumn->m_bAutoSize)
  311. {
  312. if (pColumn == pLastAutoColumn)
  313. {
  314. pColumn->m_nColumnStaticWidth = max(nTotalWidth, pColumn->GetMinWidth());
  315. if(pColumn->m_nColumnStaticWidth != pColumn->m_nColumnAutoWidth)
  316. {
  317. XTP_NM_REPORTCOLUMNRESIZE nmData;
  318. nmData.pColumn = pColumn;
  319. nmData.nPrevWidth = pColumn->m_nColumnAutoWidth;
  320. nmData.nNewWidth = pColumn->m_nColumnStaticWidth;
  321. m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
  322. }
  323. }
  324. else
  325. {
  326. nColumnsWidth = max(1, nColumnsWidth);
  327. pColumn->m_nColumnStaticWidth =
  328. max(int(pColumn->m_nColumnAutoWidth * nTotalWidth / nColumnsWidth), pColumn->GetMinWidth());
  329. if(pColumn->m_nColumnStaticWidth != pColumn->m_nColumnAutoWidth)
  330. {
  331. XTP_NM_REPORTCOLUMNRESIZE nmData;
  332. nmData.pColumn = pColumn;
  333. nmData.nPrevWidth = pColumn->m_nColumnAutoWidth;
  334. nmData.nNewWidth = pColumn->m_nColumnStaticWidth;
  335. m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
  336. }
  337. nTotalWidth -= pColumn->m_nColumnStaticWidth;
  338. nColumnsWidth -= pColumn->m_nColumnAutoWidth;
  339. }
  340. }
  341. }
  342. }
  343. m_nHeaderWidth = m_pControl->m_rcHeaderArea.Width();
  344. }
  345. else
  346. {
  347. m_nHeaderWidth = 0;
  348. for (int nColumn = 0; nColumn < m_pColumns->GetCount(); nColumn++)
  349. {
  350. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  351. if (pColumn && pColumn->IsVisible())
  352. m_nHeaderWidth += pColumn->GetWidth();
  353. }
  354. if (m_nHeaderWidth == 0)
  355. {
  356. m_nHeaderWidth = nTotalWidth;
  357. }
  358. m_pControl->AdjustScrollBars();
  359. }
  360. XTP_NM_REPORTCOLUMNRESIZE nmData;
  361. ZeroMemory(&nmData, sizeof(nmData));
  362. m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
  363. }
  364. void CXTPReportHeader::ResizeColumn(CXTPReportColumn* pColumnResize, int nWidth)
  365. {
  366. int nResizeIndex = 0;
  367. int nColumn;
  368. int nTotalWidth = 0;
  369. ASSERT(pColumnResize->IsResizable());
  370. for (nColumn = 0; nColumn < m_pColumns->GetCount(); nColumn++)
  371. {
  372. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  373. if (!pColumn->IsVisible())
  374. continue;
  375. if (nResizeIndex > 0)
  376. nTotalWidth += pColumn->m_nColumnStaticWidth;
  377. if (pColumnResize == pColumn)
  378. {
  379. int nDelta = pColumn->GetWidth() - nWidth;
  380. nResizeIndex = nColumn + 1;
  381. nTotalWidth = - nWidth + pColumn->GetWidth();
  382. pColumn->m_nColumnStaticWidth = nWidth;
  383. if (m_bAutoColumnSizing)
  384. {
  385. // if next column is "last resizeble" but not "auto size" column - resize it too.
  386. CXTPReportColumn* pColNext = CXTPReportHeader::GetNextVisibleColumn(nColumn, 1);
  387. if (pColNext && !pColNext->IsAutoSize() && pColNext->IsResizable() &&
  388. IsLastResizebleColumn(pColNext))
  389. {
  390. pColNext->m_nColumnStaticWidth += nDelta;
  391. if(pColNext->m_nColumnStaticWidth != pColNext->m_nColumnAutoWidth)
  392. {
  393. XTP_NM_REPORTCOLUMNRESIZE nmData;
  394. nmData.pColumn = pColNext;
  395. nmData.nPrevWidth = pColNext->m_nColumnAutoWidth;
  396. nmData.nNewWidth = pColNext->m_nColumnStaticWidth;
  397. m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
  398. }
  399. }
  400. }
  401. }
  402. if(pColumn->m_nColumnStaticWidth != pColumn->m_nColumnAutoWidth)
  403. {
  404. XTP_NM_REPORTCOLUMNRESIZE nmData;
  405. nmData.pColumn = pColumn;
  406. nmData.nPrevWidth = pColumn->m_nColumnAutoWidth;
  407. nmData.nNewWidth = pColumn->m_nColumnStaticWidth;
  408. m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
  409. }
  410. pColumn->m_nColumnAutoWidth = pColumn->m_nColumnStaticWidth;
  411. }
  412. AdjustColumnsWidth(nTotalWidth, nResizeIndex);
  413. for (nColumn = 0; nColumn < m_pColumns->GetCount(); nColumn++)
  414. {
  415. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  416. pColumn->m_nColumnAutoWidth = pColumn->m_nColumnStaticWidth;
  417. }
  418. AdjustColumnsWidth(m_rcHeader.Width());
  419. if (!GetPaintManager()->IsFixedRowHeight())
  420. m_pControl->AdjustScrollBars();
  421. }
  422. void CXTPReportHeader::OnLButtonUp(UINT nFlags, CPoint ptClick)
  423. {
  424. XTPReportMouseMode mouseMode = m_pControl->GetMouseMode();
  425. m_pControl->SetMouseMode(xtpReportMouseNothing);
  426. ReleaseCapture();
  427. if (mouseMode == xtpReportMouseDraggingColumn)
  428. {
  429. // End dragging column
  430. CXTPReportColumn* pDragColumn = m_pDragColumn;
  431. ASSERT(pDragColumn);
  432. if (!pDragColumn)
  433. return;
  434. BOOL bGroupOrderChanged = FALSE;
  435. // Drop column - change position
  436. if (m_dragMode == dragOutTarget || m_dragMode == dragFieldChooser)
  437. {
  438. if (m_bAllowColumnRemove && pDragColumn->m_bAllowRemove)
  439. {
  440. if (m_bDragHeader)
  441. {
  442. XTP_TRACE(_T("Removing columnn"));
  443. pDragColumn->SetVisible(FALSE);
  444. }
  445. else if (m_bDragGroupBox)
  446. {
  447. m_pColumns->GetGroupsOrder()->Remove(pDragColumn);
  448. bGroupOrderChanged = TRUE;
  449. m_pControl->Populate();
  450. }
  451. }
  452. }
  453. else if (((m_dragMode & dragInTarget) != 0) && m_nDropIndex >= 0)
  454. {
  455. XTP_TRACE(_T("Changing column position to %dn"), m_nDropIndex);
  456. CXTPClientRect rcClient(m_pControl);
  457. CRect rcHeaderFull = m_rcHeader;
  458. rcHeaderFull.right = rcClient.right;
  459. if (rcHeaderFull.PtInRect(ptClick))
  460. {
  461. int nDragIndex = m_pColumns->IndexOf(pDragColumn);
  462. pDragColumn->SetVisible();
  463. m_pColumns->ChangeColumnOrder(m_nDropIndex, nDragIndex);
  464. if (m_bDragGroupBox && ((nFlags & MK_CONTROL) == 0))
  465. {
  466. m_pColumns->GetGroupsOrder()->Remove(pDragColumn);
  467. bGroupOrderChanged = TRUE;
  468. m_pControl->Populate();
  469. }
  470. }
  471. else if (m_rcGroupBy.PtInRect(ptClick))
  472. {
  473. // set grouping by
  474. m_pColumns->GetGroupsOrder()->InsertAt(m_nDropIndex, pDragColumn);
  475. bGroupOrderChanged = TRUE;
  476. if (m_bDragHeader && ((nFlags & MK_CONTROL) == 0))
  477. {
  478. pDragColumn->SetVisible(FALSE);
  479. }
  480. m_pControl->Populate();
  481. }
  482. }
  483. m_dragMode = dragNothing;
  484. OnColumnsChanged(bGroupOrderChanged);
  485. SetHotDivider(-1);
  486. m_pDragColumn = NULL;
  487. // Drag wnd cleanup
  488. if (m_pDragWnd != NULL)
  489. {
  490. m_pDragWnd->DestroyWindow();
  491. m_pDragWnd = NULL;
  492. }
  493. m_bDragHeader = m_bDragGroupBox = FALSE;
  494. return; // Stop message processing
  495. }
  496. if (m_pDragColumn && m_pDragColumn == HitTest(ptClick))
  497. {
  498. m_pControl->SendMessageToParent(NULL, NULL, m_pDragColumn, NM_CLICK, &ptClick);
  499. }
  500. // End holding left mouse button - change sort order for the column
  501. if (mouseMode == xtpReportMousePrepareDragColumn)
  502. {
  503. if (!m_pDragColumn)
  504. return;
  505. CXTPReportColumn* pColumn = m_pDragColumn;
  506. m_pDragColumn = NULL;
  507. // change sort order
  508. if (pColumn->IsSortable() && m_bAllowColumnSort)
  509. {
  510. BOOL bGroupOrderChanged = FALSE;
  511. // do not reset sort order if clicked on the column header from the Group By area
  512. if (m_bDragHeader)
  513. {
  514. CXTPReportColumnOrder* pColumnOrder = m_bShowItemsInGroups && pColumn->IsGroupable() ?
  515. m_pColumns->GetGroupsOrder(): m_pColumns->GetSortOrder();
  516. BOOL bColumnFound = pColumnOrder->IndexOf(pColumn) >= 0;
  517. if (GetKeyState(VK_SHIFT) >= 0)
  518. {
  519. if (m_bShowItemsInGroups && !IsAllowColumnRemove())
  520. {
  521. for (int i = 0; i < pColumnOrder->GetCount(); i++)
  522. {
  523. pColumnOrder->GetAt(i)->SetVisible();
  524. }
  525. }
  526. pColumnOrder->Clear();
  527. pColumnOrder->Add(pColumn);
  528. bGroupOrderChanged = m_bShowItemsInGroups;
  529. }
  530. else if (!bColumnFound)
  531. {
  532. pColumnOrder->Add(pColumn);
  533. bGroupOrderChanged = m_bShowItemsInGroups;
  534. }
  535. if (bColumnFound)
  536. {
  537. pColumn->m_bSortIncreasing = !pColumn->m_bSortIncreasing;
  538. }
  539. }
  540. else
  541. {
  542. pColumn->m_bSortIncreasing = !pColumn->m_bSortIncreasing;
  543. }
  544. m_pControl->SendNotifyMessage(XTP_NM_REPORT_PRESORTORDERCHANGED);
  545. if (bGroupOrderChanged)
  546. m_pControl->Populate();
  547. else
  548. m_pControl->ReSortRows();
  549. m_pControl->SendNotifyMessage(XTP_NM_REPORT_SORTORDERCHANGED);
  550. if (bGroupOrderChanged)
  551. {
  552. OnColumnsChanged(bGroupOrderChanged);
  553. }
  554. }
  555. else
  556. {
  557. // redraw
  558. m_pControl->RedrawControl();
  559. }
  560. m_bDragHeader = m_bDragGroupBox = FALSE;
  561. }
  562. }
  563. CXTPReportColumn* CXTPReportHeader::HitTest(CPoint ptPoint) const
  564. {
  565. int nIndex = HitTestHeaderColumnIndex(ptPoint);
  566. if (nIndex < 0 || m_pColumns == NULL)
  567. return NULL;
  568. return m_pColumns->GetAt(nIndex);
  569. }
  570. int CXTPReportHeader::HitTestHeaderColumnIndex(CPoint ptPoint) const
  571. {
  572. if (!m_pControl->m_rcHeaderArea.PtInRect(ptPoint))
  573. return -1;
  574. int x = m_rcHeader.left;
  575. int nFreezeCols = GetControl()->m_nFreezeColumnsCount;
  576. // enumerate items
  577. int nColumnCount = m_pColumns->GetCount();
  578. for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
  579. {
  580. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  581. if (pColumn && pColumn->IsVisible())
  582. {
  583. x += pColumn->GetWidth();
  584. if (ptPoint.x < x - (nFreezeCols > 0 ? m_rcHeader.left : 0))
  585. {
  586. return nColumn;
  587. }
  588. nFreezeCols--;
  589. }
  590. }
  591. return -1;
  592. }
  593. int CXTPReportHeader::GetFulColScrollInfo(CXTPReportColumn*& rpPrev, CXTPReportColumn*& rpCurr, CXTPReportColumn*& rpNext,
  594.   int& rnScrollPos, int& rnScrollMax) const
  595. {
  596. int x = m_rcHeader.left;
  597. int nLBorderX = 0;
  598. rnScrollPos = -1;
  599. rnScrollMax = 0;
  600. rpPrev = rpCurr = rpNext = NULL;
  601. BOOL bFind = FALSE;
  602. int nFreezeCols = GetControl()->m_nFreezeColumnsCount;
  603. // enumerate items
  604. int nColumnCount = m_pColumns->GetCount();
  605. for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
  606. {
  607. CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
  608. if (pColumn && pColumn->IsVisible())
  609. {
  610. if (nFreezeCols <= 0)
  611. rnScrollMax++;
  612. if (!bFind)
  613. {
  614. if (nFreezeCols <= 0)
  615. rnScrollPos++;
  616. rpPrev = rpCurr;
  617. rpCurr = pColumn;
  618. x += pColumn->GetWidth();
  619. if (nFreezeCols > 0)
  620. {
  621. nLBorderX += pColumn->GetWidth();
  622. nFreezeCols--;
  623. }
  624. else
  625. {
  626. if (nLBorderX + 1 < x)
  627. {
  628. bFind = TRUE;
  629. }
  630. }
  631. }
  632. else if (!rpNext)
  633. {
  634. rpNext = pColumn;
  635. }
  636. }
  637. }
  638. return nLBorderX;
  639. }
  640. CXTPReportColumn* CXTPReportHeader::MouseOverColumnResizeArea(CPoint ptPoint)
  641. {
  642. if (ptPoint.y >= m_rcHeader.bottom ||
  643. ptPoint.y <= m_rcHeader.top)
  644. {
  645. return NULL;
  646. }
  647. // enumerate columns
  648. int nVisColCount = m_pColumns->GetVisibleColumnsCount() - (m_bAutoColumnSizing ? 1 : 0);
  649. int nFreezeCols = min(GetControl()->m_nFreezeColumnsCount, nVisColCount);
  650. int xMaxFreezeR = 0;
  651. for (int nColumn = 0; nColumn < nVisColCount; nColumn++)
  652. {
  653. BOOL bFreezeCol = nColumn < nFreezeCols;
  654. int nColIdx = bFreezeCol ? nColumn : nVisColCount + nFreezeCols - 1 - nColumn;
  655. CXTPReportColumn* pColumn = m_pColumns->GetVisibleAt(nColIdx);
  656. ASSERT(pColumn->IsVisible());
  657. if (!pColumn->IsResizable())
  658. continue;
  659. int xBorderR = pColumn->GetRect().right;
  660. if (bFreezeCol)
  661. {
  662. xMaxFreezeR = max(xMaxFreezeR, xBorderR);
  663. }
  664. else if (xBorderR <= xMaxFreezeR)
  665. {
  666. return NULL;
  667. }
  668. if (abs(ptPoint.x - xBorderR) <= m_nResizeCaptureRange)
  669. {
  670. if (!m_bAutoColumnSizing ||
  671. (!IsLastResizebleColumn(pColumn) && !IsLastVisibleColumn(pColumn)))
  672. {
  673. return pColumn;
  674. }
  675. }
  676. }
  677. return NULL;
  678. }
  679. int CXTPReportHeader::FindHeaderColumn(CPoint ptPoint) const
  680. {
  681. // Find column in header
  682. CXTPClientRect rcClient(m_pControl);
  683. CRect rcLastEmptyCol = m_rcHeader;
  684. rcLastEmptyCol.left = m_rcHeader.right;
  685. rcLastEmptyCol.right = rcClient.right;
  686. int nCount = m_pColumns->GetCount();
  687. int nVisColCount = m_pColumns->GetVisibleColumnsCount();
  688. if (rcLastEmptyCol.PtInRect(ptPoint))
  689. {
  690. return nCount;
  691. }
  692. if (!m_pControl->m_rcHeaderArea.PtInRect(ptPoint))
  693. return -1;
  694. int nFreezeCols = min(GetControl()->m_nFreezeColumnsCount, nVisColCount);
  695. int xMaxFreezeR = 0;
  696. for (int nColumn = 0; nColumn < nVisColCount; nColumn++)
  697. {
  698. BOOL bFreezeCol = nColumn < nFreezeCols;
  699. int nColIdx = bFreezeCol ? nColumn : nVisColCount + nFreezeCols - 1 - nColumn;
  700. BOOL bLastFreezeCol = nColumn + 1 == nFreezeCols;
  701. CXTPReportColumn* pColumn = m_pColumns->GetVisibleAt(nColIdx);
  702. ASSERT(pColumn->IsVisible());
  703. int xBorderR = pColumn->GetRect().right;
  704. if (bFreezeCol)
  705. {
  706. xMaxFreezeR = max(xMaxFreezeR, xBorderR);
  707. }
  708. else if (xBorderR <= xMaxFreezeR)
  709. {
  710. return -1;
  711. }
  712. CRect rcTest0 = pColumn->GetRect();
  713. if (!bFreezeCol)
  714. {
  715. rcTest0.left = max(xMaxFreezeR, rcTest0.left);
  716. }
  717. CRect rcTest1 = rcTest0;
  718. if (rcTest0.left != pColumn->GetRect().left)
  719. {
  720. rcTest0.SetRect(0, 0, 0, 0);
  721. }
  722. else if (rcTest0.right > rcClient.right)
  723. {
  724. rcTest1.SetRect(0, 0, 0, 0);
  725. }
  726. else
  727. {
  728. rcTest0.right -= rcTest0.Width()/2;
  729. rcTest1.left += rcTest0.Width()/2;
  730. }
  731. if (rcTest0.PtInRect(ptPoint))
  732. {
  733. return pColumn->GetIndex();
  734. }
  735. if (rcTest1.PtInRect(ptPoint))
  736. {
  737. if (bLastFreezeCol && GetControl()->m_nLeftOffset != 0)
  738. {
  739. return pColumn->GetIndex();
  740. }
  741. else
  742. {
  743. return pColumn->GetIndex() + 1;
  744. }
  745. }
  746. }
  747. return 0;
  748. }
  749. int CXTPReportHeader::FindGroupByColumn(CPoint ptPoint, BOOL bExactSearch) const
  750. {
  751. // Find column in Group By area
  752. if (m_rcGroupBy.PtInRect(ptPoint))
  753. {
  754. CXTPReportPaintManager* pPaintManager = GetPaintManager();
  755. int nHeaderHeight = pPaintManager->GetHeaderHeight();
  756. if (bExactSearch)
  757. {
  758. int x = m_rcGroupBy.left + 9;
  759. int y = m_rcGroupBy.top + 7;
  760. //int nTargetColumn = -1;
  761. CXTPReportColumn* pColumn = NULL;
  762. // draw items
  763. int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
  764. for (int nColumn = 0; nColumn < nColumnsCount; nColumn++)
  765. {
  766. pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
  767. if (pColumn)
  768. {
  769. CRect rcItem(x, y, x + pColumn->m_rcGroupBy.Width(), y + nHeaderHeight - 3);
  770. if (rcItem.PtInRect(ptPoint))
  771. return nColumn;
  772. // next column
  773. x = rcItem.right + 5;
  774. y = rcItem.top + rcItem.Height() / 2;
  775. }
  776. }
  777. return nColumnsCount;
  778. }
  779. else
  780. {
  781. int xLeft = m_rcGroupBy.left + 9;
  782. int xRight;
  783. //int nTargetColumn = -1;
  784. CXTPReportColumn* pColumn = NULL;
  785. // draw items
  786. int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
  787. for (int nColumn = 0; nColumn < nColumnsCount; nColumn++)
  788. {
  789. pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
  790. if (pColumn)
  791. {
  792. xRight = xLeft + pColumn->m_rcGroupBy.Width();
  793. if (ptPoint.x <= xRight)
  794. {
  795. if (ptPoint.x <= (xLeft + xRight) / 2)
  796. return nColumn;
  797. return nColumn + 1;
  798. }
  799. // next column
  800. xLeft = xRight + 5;
  801. }
  802. }
  803. return nColumnsCount;
  804. }
  805. }
  806. return -1;
  807. }
  808. void CXTPReportHeader::DestroyDropWnd()
  809. {
  810. if (m_pDropWnd != NULL)
  811. {
  812. m_pDropWnd->DestroyWindow();
  813. m_pDropWnd = NULL;
  814. }
  815. }
  816. int CXTPReportHeader::SetHotDivider(int nIndex, BOOL bHeader)
  817. {
  818. m_nDropIndex = nIndex;
  819. if (nIndex < 0)
  820. {
  821. DestroyDropWnd();
  822. return nIndex;
  823. }
  824. CXTPReportPaintManager* pPaintManager = GetPaintManager();
  825. int nHeaderHeight = pPaintManager->GetHeaderHeight();
  826. // compare hot divider left and right columns with dragging column
  827. //  and do not show hot divider near dragging column
  828. CXTPReportColumn* pDraggingColumn = GetDraggingColumn();
  829. CPoint pt;
  830. if (bHeader)
  831. {
  832. if (pDraggingColumn)
  833. {
  834. // find column following hot divider column
  835. CXTPReportColumn* pLeftColumn = NULL;
  836. CXTPReportColumn* pRightColumn = NULL;
  837. int nTotalColumnCount = m_pColumns->GetCount();
  838. // find left visible column
  839. for (int nLeftColumnIndex = nIndex - 1; nLeftColumnIndex >= 0; nLeftColumnIndex--)
  840. {
  841. if (nLeftColumnIndex < nTotalColumnCount)
  842. {
  843. pLeftColumn = m_pColumns->GetAt(nLeftColumnIndex);
  844. if (pLeftColumn->IsVisible())
  845. break;
  846. pLeftColumn = NULL;
  847. }
  848. }
  849. // find right visible column
  850. for (int nRightColumnIndex = nIndex; nRightColumnIndex < nTotalColumnCount; nRightColumnIndex++)
  851. {
  852. pRightColumn = m_pColumns->GetAt(nRightColumnIndex);
  853. if (pRightColumn->IsVisible())
  854. break;
  855. pRightColumn = NULL;
  856. }
  857. // compare
  858. if ((pDraggingColumn == pLeftColumn) || (pDraggingColumn == pRightColumn))
  859. {
  860. DestroyDropWnd();
  861. return -1;
  862. }
  863. }
  864. pt.y = m_rcHeader.CenterPoint().y;
  865. pt.x = m_rcHeader.left;
  866. if (nIndex < m_pColumns->GetCount())
  867. {
  868. CXTPReportColumn* pColumnL = m_pColumns->GetAt(nIndex);
  869. if (pColumnL->IsVisible())
  870. {
  871. pt.x = pColumnL->GetRect().left;
  872. }
  873. else
  874. {
  875. if (nIndex > 0 && m_pColumns->GetAt(nIndex-1))
  876. {
  877. CXTPReportColumn* pColumnR = m_pColumns->GetAt(nIndex-1);
  878. ASSERT(pColumnR->IsVisible());
  879. pt.x = pColumnR->GetRect().right;
  880. }
  881. }
  882. }
  883. else
  884. {
  885. pt.x = m_rcHeader.right;
  886. }
  887. if (pt.x < 0)
  888. {
  889. DestroyDropWnd();
  890. return -1;
  891. }
  892. }
  893. else
  894. {
  895. int nDraggingIndex = m_pColumns->GetGroupsOrder()->IndexOf(pDraggingColumn);
  896. if (nDraggingIndex != -1 && (nDraggingIndex == nIndex || nDraggingIndex == nIndex - 1))
  897. {
  898. DestroyDropWnd();
  899. return -1;
  900. }
  901. pt.x = m_rcGroupBy.left + 9;
  902. pt.y = m_rcGroupBy.top + 6 + nHeaderHeight / 2;
  903. int nColumnCount = m_pColumns->GetGroupsOrder()->GetCount();
  904. int nLastColumn = min(nColumnCount, nIndex);
  905. for (int nColumn = 0; nColumn < nLastColumn; nColumn++)
  906. {
  907. CXTPReportColumn* pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
  908. if (pColumn)
  909. {
  910. pt.x += pColumn->m_rcGroupBy.Width();
  911. if (nColumn < nColumnCount - 1)
  912. {
  913. pt.x += 5;
  914. pt.y += (nHeaderHeight - 3) / 2 ;
  915. }
  916. }
  917. }
  918. }
  919. if (m_pDropWnd == NULL)
  920. {
  921. m_pDropWnd = new CXTPReportHeaderDropWnd(pPaintManager->m_clrHotDivider);
  922. if (m_pDropWnd)
  923. m_pDropWnd->Create(nHeaderHeight);
  924. }
  925. if (m_pDropWnd)
  926. {
  927. m_pControl->ClientToScreen(&pt);
  928. m_pDropWnd->SetWindowPos(pt.x, pt.y);
  929. }
  930. return nIndex;
  931. }
  932. int CXTPReportHeader::GetMaxAvailWidth(CXTPReportColumn* pColumnCheck)
  933. {
  934. int nTotalWidth = m_pControl->m_rcHeaderArea.Width();
  935. if (!m_bAutoColumnSizing)
  936. return 32000;
  937. int nWidth = 0;
  938. for (int i = 0; i < m_pColumns->GetCount(); i++)
  939. {
  940. CXTPReportColumn* pColumn = m_pColumns->GetAt(i);
  941. if (!pColumn->IsVisible())
  942. continue;
  943. if (nWidth > 0)
  944. {
  945. nWidth -= pColumn->GetMinWidth();
  946. }
  947. if (pColumn == pColumnCheck)
  948. {
  949. nWidth = nTotalWidth - pColumnCheck->GetRect().left;
  950. }
  951. }
  952. return nWidth;
  953. }
  954. CXTPReportColumn* CXTPReportHeader::GetHotTrackingColumn() const
  955. {
  956. return m_pDragColumn && IsDragHeader() ? m_pDragColumn : m_pHotTrackingColumn;
  957. }
  958. void CXTPReportHeader::SetHotTrackingColumn(CXTPReportColumn* pColumn)
  959. {
  960. if (!GetPaintManager()->IsColumHotTrackingEnabled())
  961. pColumn = NULL;
  962. if (m_pHotTrackingColumn != pColumn)
  963. {
  964. m_pHotTrackingColumn = pColumn;
  965. m_pControl->RedrawControl();
  966. if (!CWnd::GetCapture())
  967. {
  968. TRACKMOUSEEVENT tme =
  969. {
  970. sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_pControl->GetSafeHwnd(), 0
  971. };
  972. _TrackMouseEvent (&tme);
  973. }
  974. }
  975. }
  976. void CXTPReportHeader::OnMouseMove(UINT /*nFlags*/, CPoint point)
  977. {
  978. XTPReportMouseMode mouseMode = m_pControl->GetMouseMode();
  979. SetHotTrackingColumn(HitTest(point));
  980. if (m_bAllowColumnResize && (mouseMode == xtpReportMouseNothing || mouseMode == xtpReportMouseOverColumnDivide)
  981. && MouseOverColumnResizeArea(point))
  982. {
  983. if (mouseMode == xtpReportMouseNothing)
  984. SetCursor(m_hResizeCursor);
  985. m_pControl->SetMouseMode(xtpReportMouseOverColumnDivide);
  986. return;
  987. }
  988. if (mouseMode == xtpReportMousePrepareDragColumn)
  989. {
  990. CXTPReportColumn* pColumn = GetDraggingColumn();
  991. if (!pColumn)
  992. return;
  993. if (!m_bAllowColumnReorder && (!m_bAllowColumnRemove || !pColumn->m_bAllowRemove) && !m_pControl->IsGroupByVisible())
  994. return;
  995. if (abs (point.x - m_ptMouse.x) + abs (point.y - m_ptMouse.y) < 4)
  996. return;
  997. if (!(pColumn->IsAllowDragging() && pColumn->GetIndex() >= m_pControl->GetDisableReorderColumnsCount()))
  998. {
  999. m_pDragColumn = NULL;
  1000. m_pControl->SetMouseMode(xtpReportMouseNothing);
  1001. m_pControl->RedrawControl();
  1002. }
  1003. else
  1004. {
  1005. m_pControl->SetMouseMode(xtpReportMouseDraggingColumn);
  1006. m_dragMode = m_bDragHeader ? dragInHeader : dragInGroupBox;
  1007. // set dragging cursor
  1008. ASSERT(m_pDragWnd == NULL);
  1009. m_pDragWnd = new CXTPReportHeaderDragWnd();
  1010. CRect rcItem(pColumn->GetRect());
  1011. if (!m_bDragHeader)
  1012. {
  1013. // set sizes as drawing external
  1014. rcItem.right = rcItem.left + pColumn->m_rcGroupBy.Width();
  1015. }
  1016. m_pControl->ClientToScreen(&rcItem);
  1017. m_pDragWnd->Create(rcItem, this, GetPaintManager(), pColumn);
  1018. return;
  1019. }
  1020. }
  1021. if (mouseMode == xtpReportMouseDraggingColumn)
  1022. {
  1023. if (!m_pDragColumn)
  1024. return;
  1025. CPoint ptScreen = point;
  1026. m_pControl->ClientToScreen(&ptScreen);
  1027. if (m_pDragWnd)
  1028. {
  1029. CRect rcWnd;
  1030. m_pDragWnd->GetWindowRect(&rcWnd);
  1031. CPoint pt(ptScreen);
  1032. pt.Offset(-(rcWnd.Width() >> 1), -(rcWnd.Height() >> 1));
  1033. m_pDragWnd->SetWindowPos(&CWnd::wndTop,
  1034. pt.x, pt.y, 0, 0,
  1035. SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
  1036. }
  1037. if (m_pSubList && m_pSubList->GetSafeHwnd() && m_pSubList->IsWindowVisible() &&
  1038. CXTPWindowRect(m_pSubList).PtInRect(ptScreen))
  1039. {
  1040. if (m_dragMode == dragFieldChooser)
  1041. return;
  1042. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  1043. SetHotDivider(-1);
  1044. m_dragMode = dragFieldChooser;
  1045. return;
  1046. }
  1047. CXTPClientRect rcClient(m_pControl);
  1048. CRect rcDropTarget(m_rcHeader);
  1049. if (m_pDragColumn->IsGroupable())
  1050. rcDropTarget.UnionRect(m_rcHeader, m_rcGroupBy);
  1051. rcDropTarget.right = rcClient.right;
  1052. if (rcDropTarget.PtInRect(point))
  1053. {
  1054. CRect rcHeaderFull = m_rcHeader;
  1055. rcHeaderFull.right = rcClient.right;
  1056. BOOL bHeaderPoint = rcHeaderFull.PtInRect(point);
  1057. // change dropping place
  1058. int nDropPos = bHeaderPoint ? FindHeaderColumn(point) : FindGroupByColumn(point);
  1059. if (bHeaderPoint && !(m_bAllowColumnReorder && nDropPos > (m_pControl->GetDisableReorderColumnsCount() - 1)) && m_bDragHeader)
  1060. nDropPos = -1;
  1061. XTP_TRACE(_T("nDropPos = %i, m_nDropIndex = %in"), nDropPos, m_nDropIndex);
  1062. ReportDraggingMode dragMode = bHeaderPoint ? dragInHeader : dragInGroupBox;
  1063. // dropping will change order
  1064. if ((m_dragMode & dragInTarget) == 0)
  1065. {
  1066. // Change drag mode
  1067. XTP_TRACE(_T("Switch INn"));
  1068. XTP_TRACE(_T("point = %d %dt"), point.x, point.y);
  1069. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  1070. }
  1071. // redraw control with new arrows if dropping place changed
  1072. //if (nDropPos != m_nDropIndex || m_dragMode != dragMode)
  1073. {
  1074. SetHotDivider(nDropPos, bHeaderPoint);
  1075. }
  1076. m_dragMode = dragMode;
  1077. }
  1078. else
  1079. {
  1080. // dropping will remove the column
  1081. if (m_dragMode != dragOutTarget)
  1082. {
  1083. // change drag mode
  1084. XTP_TRACE(_T("Switch OUTn"));
  1085. XTP_TRACE(_T("point = %d %dt"), point.x, point.y);
  1086. if (m_bAllowColumnRemove && m_pDragColumn->m_bAllowRemove)
  1087. {
  1088. SetCursor(m_hDontDropCursor);
  1089. }
  1090. SetHotDivider(-1);
  1091. m_dragMode = dragOutTarget;
  1092. }
  1093. }
  1094. return;
  1095. }
  1096. if (mouseMode != xtpReportMouseNothing)
  1097. {
  1098. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  1099. m_pControl->SetMouseMode(xtpReportMouseNothing);
  1100. return;
  1101. }
  1102. }
  1103. void CXTPReportHeader::StartDragging(CXTPReportColumn* pColumn, BOOL bHeader)
  1104. {
  1105. ASSERT(pColumn);
  1106. m_pDragColumn = pColumn;
  1107. m_bDragHeader = bHeader;
  1108. m_bDragGroupBox = !bHeader;
  1109. m_nDropIndex = -1;
  1110. }
  1111. CXTPReportColumn* CXTPReportHeader::GetDraggingColumn() const
  1112. {
  1113. return m_pDragColumn;
  1114. }
  1115. BOOL CXTPReportHeader::SetSubListCtrl(CXTPReportSubListControl* pSubList)
  1116. {
  1117. m_pSubList = pSubList;
  1118. if (!pSubList)
  1119. return FALSE;
  1120. m_pSubList->SetReportCtrl(m_pControl);
  1121. return TRUE;
  1122. }
  1123. BOOL CXTPReportHeader::SetFilterEditCtrl(CXTPReportFilterEditControl* pFilterEdit)
  1124. {
  1125. if (!pFilterEdit)
  1126. return FALSE;
  1127. m_pFilterEdit = pFilterEdit;
  1128. m_pFilterEdit->SetReportCtrl(m_pControl);
  1129. return TRUE;
  1130. }
  1131. void CXTPReportHeader::OnContextMenu(CPoint ptClick)
  1132. {
  1133. CPoint ptClient(ptClick);
  1134. if (!m_pControl || !m_pControl->m_rcHeaderArea.PtInRect(ptClient))
  1135. return;
  1136. if (m_pControl->GetMouseMode() == xtpReportMouseNothing)
  1137. {
  1138. // mark the column as clicked at by the dragging
  1139. CXTPReportColumn* pColumn = HitTest(ptClient);
  1140. if (pColumn || s_bSendContextMenuForWholeHeaderArea)
  1141. {
  1142. m_pControl->ClientToScreen(&ptClick);
  1143. // send process notification to the user and wait for the reaction
  1144. m_pControl->SendMessageToParent(NULL, NULL, pColumn, XTP_NM_REPORT_HEADER_RCLICK, &ptClick);
  1145. m_pControl->RedrawControl();
  1146. }
  1147. }
  1148. }
  1149. void CXTPReportHeader::DrawFooter(CDC* pDC, CRect& rcFooter, int nLeftOffset)
  1150. {
  1151. UNREFERENCED_PARAMETER(nLeftOffset);
  1152. // draw background
  1153. GetPaintManager()->FillFooter(pDC, rcFooter);
  1154. // draw items
  1155. int nVisColCount = m_pColumns->GetVisibleColumnsCount();
  1156. int nFreezeCols = min(GetControl()->m_nFreezeColumnsCount, nVisColCount);
  1157. for (int nColumn = nVisColCount-1; nColumn >= 0; nColumn--)
  1158. {
  1159. BOOL bFreezeCol = nColumn < nFreezeCols;
  1160. int nColIdx = bFreezeCol ? nFreezeCols - 1 - nColumn : nColumn;
  1161. CXTPReportColumn* pColumn = m_pColumns->GetVisibleAt(nColIdx);
  1162. ASSERT(pColumn && pColumn->IsVisible());
  1163. if (pColumn)
  1164. {
  1165. CRect rcItem = pColumn->GetRect();
  1166. rcItem.top = rcFooter.top;
  1167. rcItem.bottom = rcFooter.bottom;
  1168. if (rcItem.Height() > 0)
  1169. {
  1170. if (bFreezeCol)
  1171. {
  1172. GetPaintManager()->FillFooter(pDC, rcItem);
  1173. }
  1174. GetPaintManager()->DrawColumnFooter(pDC, pColumn, this, rcItem);
  1175. }
  1176. }
  1177. }
  1178. }
  1179. void CXTPReportHeader::DrawGroupByControl(CDC* pDC, CRect& rcGroupBy)
  1180. {
  1181. m_rcGroupBy = rcGroupBy;
  1182. if (rcGroupBy.Height() <= 0)
  1183. return;
  1184. CXTPReportPaintManager* pPaintManager = GetPaintManager();
  1185. pPaintManager->FillGroupByControl(pDC, rcGroupBy);
  1186. CXTPFontDC font(pDC, &pPaintManager->m_fontCaption);
  1187. int x = m_rcGroupBy.left + 9;
  1188. int y = m_rcGroupBy.top + 7;
  1189. int nHeaderHeight = pPaintManager->GetHeaderHeight();
  1190. // draw items
  1191. int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
  1192. for (int nColumn = 0; nColumn < nColumnsCount; nColumn++)
  1193. {
  1194. CXTPReportColumn* pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
  1195. if (pColumn /*&& pColumn->IsVisible()*/)
  1196. {
  1197. CRect rcItem(x, y, x + pColumn->GetCaptionWidth(pDC) + 50, y + nHeaderHeight - 3);
  1198. pColumn->m_rcGroupBy = rcItem;
  1199. // draw background
  1200. GetPaintManager()->FillHeaderControl(pDC, rcItem);
  1201. // draw column
  1202. GetPaintManager()->DrawColumn(pDC, pColumn, this, rcItem, TRUE);
  1203. // next column
  1204. x = rcItem.right + 5;
  1205. y = rcItem.top + rcItem.Height() / 2;
  1206. // draw connector
  1207. if (nColumn < nColumnsCount - 1)
  1208. GetPaintManager()->DrawConnector(pDC, CPoint(rcItem.right - 5, rcItem.bottom), CPoint(x, rcItem.bottom + 4));
  1209. }
  1210. }
  1211. // draw default dragging text if no items there
  1212. if (nColumnsCount == 0)
  1213. {
  1214. CRect rcItem(x, y, x, y + nHeaderHeight - 3);
  1215. GetPaintManager()->DrawNoGroupByText(pDC, rcItem);
  1216. }
  1217. }
  1218. int CXTPReportHeader::GetGroupByHeight() const
  1219. {
  1220. CXTPReportPaintManager* pPaintManager = GetPaintManager();
  1221. int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
  1222. int nHeaderHeight = pPaintManager->GetHeaderHeight();
  1223. int nHeight = 8 + ((nHeaderHeight - 3) / 2) * (nColumnsCount + 1) + 7;
  1224. if (!nColumnsCount)
  1225. nHeight += (nHeaderHeight - 3) / 2;
  1226. return nHeight;
  1227. }
  1228. void CXTPReportHeader::BestFit(CXTPReportColumn* pColumn)
  1229. {
  1230. if (pColumn->IsResizable() && m_bAllowColumnResize)
  1231. if (!m_bAutoColumnSizing || (!IsLastResizebleColumn(pColumn) && !IsLastVisibleColumn(pColumn)))
  1232. {
  1233. int nMaxAvailWidth = GetMaxAvailWidth(pColumn);
  1234. int nMinWidth = pColumn->GetMinWidth();
  1235. int nMaxItemWidth = min(pColumn->GetBestFitWidth(), nMaxAvailWidth);
  1236. if (nMaxItemWidth > nMinWidth)
  1237. {
  1238. ResizeColumn(pColumn, nMaxItemWidth);
  1239. m_pControl->RedrawControl();
  1240. }
  1241. }
  1242. }
  1243. BOOL CXTPReportHeader::IsLastVisibleColumn(CXTPReportColumn* pColumn) const
  1244. {
  1245. int nColumnCount = m_pColumns->GetCount();
  1246. for (int nColumn = m_pColumns->IndexOf(pColumn) + 1; nColumn < nColumnCount; nColumn++)
  1247. {
  1248. CXTPReportColumn* pCol = m_pColumns->GetAt(nColumn);
  1249. if (pCol && pCol->IsVisible())
  1250. return FALSE;
  1251. }
  1252. return TRUE;
  1253. }
  1254. BOOL CXTPReportHeader::IsLastResizebleColumn(CXTPReportColumn* pColumn) const
  1255. {
  1256. int nColumnCount = m_pColumns->GetCount();
  1257. for (int nColumn = m_pColumns->IndexOf(pColumn) + 1; nColumn < nColumnCount; nColumn++)
  1258. {
  1259. CXTPReportColumn* pCol = m_pColumns->GetAt(nColumn);
  1260. if (pCol && pCol->IsVisible() && pCol->IsResizable())
  1261. return FALSE;
  1262. }
  1263. return TRUE;
  1264. }
  1265. void CXTPReportHeader::ShowItemsInGroups(BOOL bShowInGroups)
  1266. {
  1267. m_bShowItemsInGroups = bShowInGroups;
  1268. if (m_bShowItemsInGroups)
  1269. {
  1270. m_pColumns->GetGroupsOrder()->Clear();
  1271. if (m_pColumns->GetSortOrder()->GetCount() > 0)
  1272. {
  1273. m_pColumns->GetGroupsOrder()->Add(m_pColumns->GetSortOrder()->GetAt(0));
  1274. m_pColumns->GetSortOrder()->Clear();
  1275. }
  1276. m_pControl->Populate();
  1277. OnColumnsChanged(TRUE);
  1278. }
  1279. }
  1280. CXTPReportColumn* CXTPReportHeader::GetNextVisibleColumn(int nIndex, int nDirection)
  1281. {
  1282. if (nDirection == 1)
  1283. {
  1284. int nColumnCount = m_pColumns->GetCount();
  1285. for (int nColumn = nIndex + 1; nColumn < nColumnCount; nColumn++)
  1286. {
  1287. CXTPReportColumn* pCol = m_pColumns->GetAt(nColumn);
  1288. if (pCol && pCol->IsVisible())
  1289. return pCol;
  1290. }
  1291. }
  1292. if (nDirection == -1)
  1293. {
  1294. for (int nColumn = nIndex - 1; nColumn >= 0; nColumn--)
  1295. {
  1296. CXTPReportColumn* pCol = m_pColumns->GetAt(nColumn);
  1297. if (pCol && pCol->IsVisible())
  1298. return pCol;
  1299. }
  1300. }
  1301. return NULL;
  1302. }
  1303. INT_PTR CXTPReportHeader::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
  1304. {
  1305. CXTPReportColumn* pColumn = HitTest(point);
  1306. if (!pColumn)
  1307. return -1;
  1308. INT_PTR nHit = (INT_PTR)pColumn;
  1309. CString strTip = pColumn->GetTooltip();
  1310. if (strTip.IsEmpty())
  1311. {
  1312. CXTPReportPaintManager* pPaintManager = GetPaintManager();
  1313. strTip = pColumn->GetCaption();
  1314. if (pColumn->IsSortable() && m_bAllowColumnSort)
  1315. {
  1316. strTip = pPaintManager->m_strSortBy + strTip;
  1317. }
  1318. }
  1319. if (strTip.GetLength() == 0)
  1320. return -1;
  1321. CXTPToolTipContext::FillInToolInfo(pTI, m_pControl->m_hWnd, pColumn->GetRect(),
  1322. nHit, strTip);
  1323. return nHit;
  1324. }
  1325. void CXTPReportHeader::DoPropExchange(CXTPPropExchange* pPX)
  1326. {
  1327. PX_Bool(pPX, _T("AllowColumnRemove"), m_bAllowColumnRemove, TRUE);
  1328. PX_Bool(pPX, _T("AllowColumnResize"), m_bAllowColumnResize, TRUE);
  1329. PX_Bool(pPX, _T("AllowColumnReorder"), m_bAllowColumnReorder, TRUE);
  1330. PX_Bool(pPX, _T("AllowColumnSort"), m_bAllowColumnSort, TRUE);
  1331. PX_Bool(pPX, _T("AutoColumnSizing"), m_bAutoColumnSizing, TRUE);
  1332. PX_Bool(pPX, _T("ShowItemsInGroups"), m_bShowItemsInGroups, s_bShowItemsInGroupsPXDefault);
  1333. }