ReportCtrl.cpp
上传用户:zhenhuadz
上传日期:2007-01-07
资源大小:1511k
文件大小:58k
源码类别:

远程控制编程

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////////////////
  2. // File: CReportCtrl.cpp
  3. // Version: 1.0.1.0
  4. //
  5. // Author: Maarten Hoeben
  6. // E-mail: hoeben@nwn.com
  7. //
  8. // Implementation of the CReportCtrl and associated classes.
  9. //
  10. // You are free to use, distribute or modify this code
  11. // as long as the header is not removed or modified.
  12. //
  13. // Version history
  14. //
  15. // 1.0.1.0 - Initial release
  16. ////////////////////////////////////////////////////////////////////////////
  17. // ReportCtrl.cpp : implementation file
  18. //
  19. #include "stdafx.h"
  20. #include "ReportCtrl.h"
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26. TCHAR* g_szSeparator = _T("|");
  27. /////////////////////////////////////////////////////////////////////////////
  28. // CReportData
  29. CReportData::CReportData()
  30. {
  31. }
  32. CReportData::~CReportData()
  33. {
  34. }
  35. BOOL CReportData::New(INT iSubItems)
  36. {
  37. for(INT i=0;i<iSubItems;i++)
  38. {
  39. CString str;
  40. str.Format(_T("(-1,-1,-1)%s"), g_szSeparator);
  41. *this += str;
  42. }
  43. return TRUE;
  44. }
  45. BOOL CReportData::GetSubItem(INT iSubItem, LPINT lpiImage, LPINT lpiCheck, LPINT lpiColor, LPTSTR lpszText, INT iTextMax)
  46. {
  47. INT i, iPos;
  48. for(i=0,iPos=0;i<iSubItem&&iPos>=0;i++,iPos++)
  49. iPos = Find(g_szSeparator, iPos);
  50. if(iPos<0)
  51. return FALSE;
  52. LPTSTR lpsz = GetBuffer(0);
  53. lpsz = &lpsz[iPos];
  54. VERIFY(_stscanf(lpsz, _T("(%d,%d,%d)"), lpiImage, lpiCheck, lpiColor));
  55. lpsz = _tcspbrk(lpsz, _T(")"))+1;
  56. if(lpsz && lpszText)
  57. {
  58. for(INT iTextSize=0;iTextSize<iTextMax-1 && *lpsz!=g_szSeparator[0];iTextSize++)
  59. lpszText[iTextSize] = *lpsz++;
  60. lpszText[iTextSize] = 0;
  61. }
  62. return TRUE;
  63. }
  64. BOOL CReportData::SetSubItem(INT iSubItem, INT iImage, INT iCheck, INT iColor, LPCTSTR lpszText)
  65. {
  66. if(!InsertSubItem(iSubItem, iImage, iCheck, iColor, lpszText))
  67. return FALSE;
  68. if(!DeleteSubItem(iSubItem+1))
  69. return FALSE;
  70. return TRUE;
  71. }
  72. BOOL CReportData::InsertSubItem(INT iSubItem, INT iImage, INT iCheck, INT iColor, LPCTSTR lpszText)
  73. {
  74. INT i, iPos;
  75. for(i=0,iPos=0;i<iSubItem&&iPos>=0;i++,iPos++)
  76. iPos = Find(g_szSeparator, iPos);
  77. if(iPos<0)
  78. return FALSE;
  79. lpszText = lpszText ? lpszText:_T("");
  80. CString str;
  81. str.Format("(%d,%d,%d)%s%s", iImage, iCheck, iColor, lpszText, g_szSeparator);
  82. Insert(iPos, str);
  83. return TRUE;
  84. }
  85. BOOL CReportData::DeleteSubItem(INT iSubItem)
  86. {
  87. INT i, iPos1, iPos2;
  88. for(i=0,iPos1=0;i<iSubItem&&iPos1>=0;i++,iPos1++)
  89. iPos1 = Find(g_szSeparator, iPos1);
  90. if(iPos1<0)
  91. return FALSE;
  92. iPos2 = Find(g_szSeparator, iPos1);
  93. if(iPos2++<0)
  94. return FALSE;
  95. Delete(iPos1, iPos2-iPos1);
  96. return TRUE;
  97. }
  98. /////////////////////////////////////////////////////////////////////////////
  99. // CReportView
  100. IMPLEMENT_DYNCREATE(CReportView, CView)
  101. CReportView::CReportView()
  102. {
  103. m_bCreated = FALSE;
  104. }
  105. CReportView::~CReportView()
  106. {
  107. }
  108. void CReportView::OnInitialUpdate() 
  109. {
  110. CView::OnInitialUpdate();
  111. if(!m_bCreated)
  112. {
  113. CRect rect;
  114. GetClientRect(rect);
  115. if(m_wndReportCtrl.Create(WS_CHILD|WS_TABSTOP|WS_VISIBLE, rect, this, IDC_REPORTCTRL) == NULL)
  116. AfxThrowMemoryException();
  117. m_bCreated = TRUE;
  118. }
  119. }
  120. BEGIN_MESSAGE_MAP(CReportView, CView)
  121. //{{AFX_MSG_MAP(CReportView)
  122. ON_WM_SIZE()
  123. ON_WM_SETFOCUS()
  124. ON_WM_ERASEBKGND()
  125. //}}AFX_MSG_MAP
  126. END_MESSAGE_MAP()
  127. /////////////////////////////////////////////////////////////////////////////
  128. // CReportView drawing
  129. void CReportView::OnDraw(CDC* pDC)
  130. {
  131. ;
  132. }
  133. /////////////////////////////////////////////////////////////////////////////
  134. // CReportView diagnostics
  135. #ifdef _DEBUG
  136. void CReportView::AssertValid() const
  137. {
  138. CView::AssertValid();
  139. }
  140. void CReportView::Dump(CDumpContext& dc) const
  141. {
  142. CView::Dump(dc);
  143. }
  144. #endif //_DEBUG
  145. /////////////////////////////////////////////////////////////////////////////
  146. // CReportView implementation
  147. CReportCtrl& CReportView::GetReportCtrl()
  148. {
  149. return m_wndReportCtrl;
  150. }
  151. BOOL CReportView::OnEraseBkgnd(CDC* pDC) 
  152. {
  153. return TRUE;
  154. }
  155. void CReportView::OnSize(UINT nType, int cx, int cy) 
  156. {
  157. CView::OnSize(nType, cx, cy);
  158. if(m_wndReportCtrl.GetSafeHwnd())
  159. {
  160. CRect rect;
  161. GetClientRect(rect);
  162. m_wndReportCtrl.MoveWindow(rect);
  163. }
  164. }
  165. void CReportView::OnSetFocus(CWnd* pOldWnd) 
  166. {
  167. m_wndReportCtrl.SetFocus();
  168. }
  169. /////////////////////////////////////////////////////////////////////////////
  170. // CReportCtrl
  171. IMPLEMENT_DYNCREATE(CReportCtrl, CWnd)
  172. CReportCtrl::CReportCtrl()
  173. {
  174. // Register the window class if it has not already been registered.
  175. WNDCLASS wndclass;
  176. HINSTANCE hInst = AfxGetInstanceHandle();
  177. if(!(::GetClassInfo(hInst, REPORTCTRL_CLASSNAME, &wndclass)))
  178. {
  179. // Otherwise we need to register a new class
  180.         wndclass.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
  181. wndclass.lpfnWndProc = ::DefWindowProc;
  182. wndclass.cbClsExtra = wndclass.cbWndExtra = 0;
  183. wndclass.hInstance = hInst;
  184. wndclass.hIcon = NULL;
  185. wndclass.hCursor = LoadCursor(hInst, IDC_ARROW);
  186. wndclass.hbrBackground = (HBRUSH)COLOR_WINDOW; 
  187. wndclass.lpszMenuName = NULL;
  188. wndclass.lpszClassName = REPORTCTRL_CLASSNAME;
  189. if (!AfxRegisterClass(&wndclass))
  190. AfxThrowResourceException();
  191. }
  192. m_bSubclassFromCreate = FALSE;
  193. m_bDoubleBuffer = TRUE;
  194. m_iSpacing = 6;
  195.     // Initially use the system message font for the ReportCtrl font
  196. NONCLIENTMETRICS ncm;
  197. ncm.cbSize = sizeof(NONCLIENTMETRICS);
  198. VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
  199. m_font.CreateFontIndirect(&(ncm.lfMessageFont));
  200. m_pImageList = NULL;
  201. m_sizeImage.cx = 0;
  202. m_sizeImage.cy = 0;
  203. m_sizeCheck.cx = 8;
  204. m_sizeCheck.cy = 8;
  205. GetSysColors();
  206. m_arrayColors.SetSize(0, 8);
  207. m_iGridStyle = PS_SOLID;
  208. m_strNoItems = _T("There are no items to show in this view.");
  209. m_iDefaultWidth = 200;
  210. m_iDefaultHeight = 10;
  211. m_iVirtualWidth = 0;
  212. m_iVirtualHeight = 0;
  213. m_arraySubItems.SetSize(0, 8);
  214. m_arrayItems.SetSize(0, 128);
  215. m_bColumnsReordered = FALSE;
  216. m_arrayColumns.SetSize(0, 8);
  217. m_bFocus = FALSE;
  218. m_iFocusRow = -1;
  219. m_iSelectRow = 0;
  220. m_arrayRows.SetSize(0, 128);
  221. m_lprclc = NULL;
  222. m_lpfnrvc = NULL;
  223. }
  224. CReportCtrl::~CReportCtrl()
  225. {
  226. if(m_palette.m_hObject)
  227. m_palette.DeleteObject();
  228.     if(m_font.m_hObject)
  229. m_font.DeleteObject();
  230. if(m_fontBold.m_hObject)
  231. m_fontBold.DeleteObject();
  232. }
  233. BOOL CReportCtrl::Create()
  234. {
  235. CRect rect(0, 0, 0, 0);
  236. DWORD dwStyle = HDS_HORZ|HDS_BUTTONS|HDS_FULLDRAG|HDS_DRAGDROP|CCS_TOP;
  237. if(!m_wndHeader.Create(dwStyle, rect, this, IDC_HEADERCTRL))
  238. return FALSE;
  239. CWnd* pWnd = GetParent();
  240. if(pWnd)
  241. {
  242. CFont* pFont = pWnd->GetFont();
  243. if(pFont)
  244. {
  245. LOGFONT lf;
  246. pFont->GetLogFont(&lf);
  247. m_font.DeleteObject();
  248. m_font.CreateFontIndirect(&lf);
  249. }
  250. }
  251. OnSetFont((WPARAM)((HFONT)m_font), FALSE);
  252. m_wndHeader.SetFont(&m_font, FALSE);
  253. GetClientRect(rect);
  254. Layout(rect.Width(), rect.Height());
  255. return TRUE;
  256. }
  257. BOOL CReportCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
  258. {
  259. m_bSubclassFromCreate = TRUE;
  260. if(!CWnd::Create(REPORTCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID, pContext))
  261. return FALSE;
  262. return Create();
  263. }
  264. void CReportCtrl::PreSubclassWindow() 
  265. {
  266. CWnd::PreSubclassWindow();
  267. if(!m_bSubclassFromCreate)
  268. if(!Create())
  269. AfxThrowMemoryException();
  270. }
  271. BEGIN_MESSAGE_MAP(CReportCtrl, CWnd)
  272. //{{AFX_MSG_MAP(CReportCtrl)
  273. ON_WM_SIZE()
  274. ON_WM_ERASEBKGND()
  275. ON_WM_PAINT()
  276. ON_WM_SYSCOLORCHANGE()
  277. ON_NOTIFY(HDN_ITEMCHANGED, IDC_HEADERCTRL, OnHdnItemChanged)
  278. ON_NOTIFY(HDN_ITEMCLICK, IDC_HEADERCTRL, OnHdnItemClick)
  279. ON_NOTIFY(HDN_ENDDRAG, IDC_HEADERCTRL, OnHdnEndDrag)
  280. ON_WM_HSCROLL()
  281. ON_WM_VSCROLL()
  282. ON_WM_LBUTTONDOWN()
  283. ON_WM_SETCURSOR()
  284. ON_WM_KEYDOWN()
  285. ON_WM_GETDLGCODE()
  286. ON_WM_LBUTTONDBLCLK()
  287. ON_WM_QUERYNEWPALETTE()
  288. ON_WM_PALETTECHANGED()
  289. ON_WM_SETFOCUS()
  290. ON_WM_KILLFOCUS()
  291. //}}AFX_MSG_MAP
  292.     ON_MESSAGE(WM_SETFONT, OnSetFont)
  293.     ON_MESSAGE(WM_GETFONT, OnGetFont)
  294. END_MESSAGE_MAP()
  295. /////////////////////////////////////////////////////////////////////////////
  296. // CReportCtrl attributes
  297. BOOL CReportCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam)
  298. {
  299. switch(wParam)
  300. {
  301. case RVP_SPACING:
  302. m_iSpacing = (INT)lParam;
  303. break;
  304. case RVP_CHECK:
  305. m_sizeCheck.cx = LOWORD(lParam);
  306. m_sizeCheck.cy = HIWORD(lParam);
  307. break;
  308. case RVP_NOITEMTEXT:
  309. m_strNoItems = (LPCTSTR)lParam;
  310. break;
  311. case RVP_GRIDSTYLE:
  312. switch(wParam)
  313. {
  314. case RVP_GRIDSTYLE_DOT: m_iGridStyle = PS_DOT; break;
  315. case RVP_GRIDSTYLE_DASH: m_iGridStyle = PS_DASH; break;
  316. case RVP_GRIDSTYLE_SOLID: m_iGridStyle = PS_SOLID; break;
  317. default:
  318. return FALSE;
  319. }
  320. break;
  321. default:
  322. return FALSE;
  323. }
  324. CRect rect;
  325. GetClientRect(rect);
  326. Layout(rect.Width(), rect.Height());
  327. return TRUE;
  328. }
  329. INT CReportCtrl::ActivateColumn(INT iColumn, INT iOrder)
  330. {
  331. ASSERT(iColumn<m_arraySubItems.GetSize());
  332. SUBITEM& subitem = m_arraySubItems[iColumn];
  333. INT iResult = -1;
  334. INT iHeaderItems = m_arrayColumns.GetSize();
  335. HDITEM hdi;
  336. hdi.mask = HDI_LPARAM;
  337. for(INT iItem=0;iItem<iHeaderItems;iItem++)
  338. if(m_wndHeader.GetItem(iItem, &hdi))
  339. if(hdi.lParam == iColumn)
  340. break;
  341. if(iItem == iHeaderItems)
  342. {
  343. try
  344. {
  345. hdi.mask = HDI_FORMAT|HDI_WIDTH|HDI_LPARAM|HDI_ORDER;
  346. hdi.fmt = subitem.nFormat&RVCF_MASK;
  347. hdi.cxy = subitem.iWidth;
  348. hdi.iOrder = iOrder;
  349. hdi.lParam = (LPARAM)iColumn;
  350. if(subitem.nFormat&RVCF_IMAGE)
  351. {
  352. hdi.mask |= HDI_IMAGE;
  353. hdi.iImage = subitem.iImage;
  354. }
  355. if(subitem.nFormat&RVCF_TEXT)
  356. {
  357. hdi.mask |= HDI_TEXT;
  358. hdi.pszText = subitem.strText.GetBuffer(0);
  359. }
  360. iResult = m_wndHeader.InsertItem(iHeaderItems, &hdi);
  361. if(iResult >= 0)
  362. {
  363. m_iVirtualWidth += subitem.iWidth;
  364. HDITEMEX hditemex;
  365. hditemex.nStyle = (subitem.nFormat&RVCF_EX_MASK)>>16;
  366. hditemex.iMinWidth = subitem.iMinWidth;
  367. hditemex.iMaxWidth = subitem.iMaxWidth;
  368. m_wndHeader.SetItemEx(iResult, &hditemex);
  369. hdi.mask = HDI_WIDTH;
  370. m_wndHeader.GetItem(iResult, &hdi);
  371. subitem.iWidth = hdi.cxy;
  372. m_bColumnsReordered = TRUE;
  373. ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));
  374. }
  375. }
  376. catch(CMemoryException* e)
  377. {
  378. e->Delete();
  379. if(iResult >= 0)
  380. m_wndHeader.DeleteItem(iResult);
  381. }
  382. }
  383. return iResult;
  384. }
  385. BOOL CReportCtrl::DeactivateColumn(INT iColumn)
  386. {
  387. ASSERT(iColumn<m_arraySubItems.GetSize());
  388. HDITEM hdi;
  389. hdi.mask = HDI_WIDTH|HDI_LPARAM;
  390. INT iHeaderItems = m_arrayColumns.GetSize();
  391. for(INT iItem=0;iItem<iHeaderItems;iItem++)
  392. if(m_wndHeader.GetItem(iItem, &hdi))
  393. if(hdi.lParam == iColumn)
  394. break;
  395. if(iItem == iHeaderItems)
  396. return FALSE;
  397. ASSERT(iHeaderItems > 1); // At least one column must be active
  398. BOOL bResult = m_wndHeader.DeleteItem(iItem);
  399. m_iVirtualWidth -= hdi.cxy;
  400. m_bColumnsReordered = TRUE;
  401. ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));
  402. return bResult;
  403. }
  404. BOOL CReportCtrl::IsActiveColumn(INT iColumn)
  405. {
  406. INT iHeaderItems = m_arrayColumns.GetSize();
  407. HDITEM hdi;
  408. hdi.mask = HDI_LPARAM;
  409. for(INT iItem=0;iItem<iHeaderItems;iItem++)
  410. if(m_wndHeader.GetItem(iItem, &hdi))
  411. if(hdi.lParam == iColumn)
  412. break;
  413. if(iItem == iHeaderItems)
  414. return FALSE;
  415. return TRUE;
  416. }
  417. BOOL CReportCtrl::GetItem(LPRVITEM lprvi)
  418. {
  419. ASSERT(lprvi->iItem < m_arrayItems.GetSize()); // Specify item
  420. ASSERT(lprvi->iSubItem < m_arraySubItems.GetSize()); // Specify subitem
  421. UINT nMask = lprvi->nMask;
  422. ITEM item = m_arrayItems[lprvi->iItem];
  423. lprvi->nMask = 0;
  424. lprvi->nPreview = item.nPreview;
  425. if(lprvi->nPreview > 0)
  426. lprvi->nMask |= RVIM_PREVIEW;
  427. lprvi->iBkColor = item.iBkColor;
  428. if(lprvi->iBkColor >= 0)
  429. lprvi->nMask |= RVIM_BKCOLOR;
  430. lprvi->lpszText = nMask&RVIM_TEXT ? lprvi->lpszText:NULL;
  431. item.rdData.GetSubItem(lprvi->iSubItem, &lprvi->iImage, &lprvi->iCheck, &lprvi->iTextColor, lprvi->lpszText, lprvi->iTextMax);
  432. if(lprvi->lpszText && _tcslen(lprvi->lpszText))
  433. lprvi->nMask |= RVIM_TEXT;
  434. if(lprvi->iImage >= 0)
  435. lprvi->nMask |= RVIM_IMAGE;
  436. if(lprvi->iCheck >= 0)
  437. lprvi->nMask |= RVIM_CHECK;
  438. if(lprvi->iTextColor >= 0)
  439. lprvi->nMask |= RVIM_TEXTCOLOR;
  440. lprvi->nMask |= RVIM_STATE|RVIM_LPARAM;
  441. lprvi->nState = item.nState;
  442. lprvi->lParam = item.lParam;
  443. return TRUE;
  444. }
  445. BOOL CReportCtrl::SetItem(LPRVITEM lprvi)
  446. {
  447. TCHAR szText[REPORTCTRL_MAX_TEXT];
  448. RVITEM rvi;
  449. rvi.iItem = lprvi->iItem;
  450. rvi.iSubItem = lprvi->iSubItem;
  451. rvi.lpszText = szText;
  452. rvi.iTextMax = REPORTCTRL_MAX_TEXT;
  453. rvi.nMask = RVIM_TEXT;
  454. VERIFY(GetItem(&rvi));
  455. if(lprvi->nMask&RVIM_TEXT)
  456. {
  457. _tcsncpy(rvi.lpszText, lprvi->lpszText, REPORTCTRL_MAX_TEXT-1);
  458. rvi.lpszText[REPORTCTRL_MAX_TEXT-1] = 0;
  459. }
  460. if(lprvi->nMask&RVIM_TEXTCOLOR)
  461. rvi.iTextColor = lprvi->iTextColor;
  462. if(lprvi->nMask&RVIM_IMAGE)
  463. rvi.iImage = lprvi->iImage;
  464. if(lprvi->nMask&RVIM_CHECK)
  465. rvi.iCheck = lprvi->iCheck;
  466. if(lprvi->nMask&RVIM_BKCOLOR)
  467. rvi.iBkColor = lprvi->iBkColor;
  468. if(lprvi->nMask&RVIM_PREVIEW)
  469. rvi.nPreview = lprvi->nPreview;
  470. if(lprvi->nMask&RVIM_STATE)
  471. rvi.nState = lprvi->nState;
  472. if(lprvi->nMask&RVIM_LPARAM)
  473. rvi.lParam = lprvi->lParam;
  474. ITEM item = m_arrayItems[rvi.iItem];
  475. VERIFY(item.rdData.InsertSubItem(rvi.iSubItem, rvi.iImage, rvi.iCheck, rvi.iTextColor, rvi.lpszText));
  476. VERIFY(item.rdData.DeleteSubItem(rvi.iSubItem+1));
  477. item.iBkColor = rvi.iBkColor;
  478. item.nPreview = rvi.nPreview;
  479. item.nState = rvi.nState;
  480. item.lParam = rvi.lParam;
  481. m_arrayItems.SetAt(rvi.iItem, item);
  482. ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));
  483. RedrawItems(rvi.iItem);
  484. return TRUE;
  485. }
  486. INT CReportCtrl::GetItemText(INT iItem, INT iSubItem, LPTSTR lpszText, INT iLen)
  487. {
  488. RVITEM rvi;
  489. rvi.nMask = RVIM_TEXT;
  490. rvi.iItem = iItem;
  491. rvi.iSubItem = iSubItem;
  492. rvi.lpszText = lpszText;
  493. rvi.iTextMax = iLen;
  494. return GetItem(&rvi) ? _tcslen(rvi.lpszText):0;
  495. }
  496. CString CReportCtrl::GetItemText(INT iItem, INT iSubItem)
  497. {
  498. CString str;
  499. TCHAR szText[REPORTCTRL_MAX_TEXT];
  500. if(GetItemText(iItem, iSubItem, szText, REPORTCTRL_MAX_TEXT))
  501. str = szText;
  502. return str;
  503. }
  504. BOOL CReportCtrl::SetItemText(INT iItem, INT iSubItem, LPTSTR lpszText)
  505. {
  506. RVITEM rvi;
  507. rvi.nMask = RVIM_TEXT;
  508. rvi.iItem = iItem;
  509. rvi.iSubItem = iSubItem;
  510. rvi.lpszText = lpszText;
  511. return SetItem(&rvi);
  512. }
  513. INT CReportCtrl::GetItemImage(INT iItem, INT iSubItem)
  514. {
  515. RVITEM rvi;
  516. rvi.nMask = RVIM_IMAGE;
  517. rvi.iItem = iItem;
  518. rvi.iSubItem = iSubItem;
  519. return GetItem(&rvi) ? rvi.iImage:-1;
  520. }
  521. BOOL CReportCtrl::SetItemImage(INT iItem, INT iSubItem, INT iImage)
  522. {
  523. RVITEM rvi;
  524. rvi.nMask = RVIM_IMAGE;
  525. rvi.iItem = iItem;
  526. rvi.iSubItem = iSubItem;
  527. rvi.iImage = iImage;
  528. return SetItem(&rvi);
  529. }
  530. INT CReportCtrl::GetItemCheck(INT iItem, INT iSubItem)
  531. {
  532. RVITEM rvi;
  533. rvi.nMask = RVIM_CHECK;
  534. rvi.iItem = iItem;
  535. rvi.iSubItem = iSubItem;
  536. return GetItem(&rvi) ? rvi.iCheck:-1;
  537. }
  538. BOOL CReportCtrl::SetItemCheck(INT iItem, INT iSubItem, INT iCheck)
  539. {
  540. RVITEM rvi;
  541. rvi.nMask = RVIM_CHECK;
  542. rvi.iItem = iItem;
  543. rvi.iSubItem = iSubItem;
  544. rvi.iCheck = iCheck;
  545. return SetItem(&rvi);
  546. }
  547. DWORD CReportCtrl::GetItemData(INT iItem)
  548. {
  549. RVITEM rvi;
  550. rvi.nMask = RVIM_LPARAM;
  551. rvi.iItem = iItem;
  552. return GetItem(&rvi) ? rvi.lParam:0;
  553. }
  554. BOOL CReportCtrl::SetItemData(INT iItem, DWORD dwData)
  555. {
  556. RVITEM rvi;
  557. rvi.nMask = RVIM_LPARAM;
  558. rvi.iItem = iItem;
  559. rvi.lParam = dwData;
  560. return SetItem(&rvi);
  561. }
  562. INT CReportCtrl::GetVisibleCount(BOOL bUnobstructed)
  563. {
  564. return GetVisibleRows(bUnobstructed);
  565. }
  566. INT CReportCtrl::GetItemCount()
  567. {
  568. return m_arrayItems.GetSize();
  569. }
  570. INT CReportCtrl::GetFirstSelectedItem()
  571. {
  572. return GetNextSelectedItem(-1);
  573. }
  574. INT CReportCtrl::GetNextSelectedItem(INT iItem)
  575. {
  576. RVITEM rvi;
  577. rvi.nMask = RVIM_STATE;
  578. INT iItems = m_arrayItems.GetSize();
  579. for(iItem++;rvi.iItem<iItems;rvi.iItem++)
  580. if(GetItem(&rvi) && rvi.nState&RVIS_SELECTED)
  581. return rvi.iItem;
  582. return -1;
  583. }
  584. BOOL CReportCtrl::SetImageList(CImageList* pImageList)
  585. {
  586. m_pImageList = pImageList;
  587. m_wndHeader.SetImageList(pImageList);
  588. IMAGEINFO info;
  589. if(pImageList->GetImageInfo(0, &info))
  590. {
  591. m_sizeImage.cx = info.rcImage.right - info.rcImage.left;
  592. m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top;
  593. m_iDefaultHeight = m_sizeImage.cy>m_iDefaultHeight ? m_sizeImage.cy:m_iDefaultHeight;
  594. Invalidate();
  595. return TRUE;
  596. }
  597. else
  598. return FALSE;
  599. }
  600. CImageList* CReportCtrl::GetImageList(void)
  601. {
  602. return m_pImageList;
  603. }
  604. CFlatHeaderCtrl* CReportCtrl::GetHeaderCtrl()
  605. {
  606. return &m_wndHeader;
  607. }
  608. BOOL CReportCtrl::SetReportColumnListCtrl(CReportColumnListCtrl* lprclc)
  609. {
  610. if(m_lprclc != NULL)
  611. {
  612. m_wndHeader.ModifyProperty(FH_PROPERTY_DROPTARGET, NULL);
  613. m_lprclc->SetReportCtrl(NULL);
  614. }
  615. m_lprclc = lprclc;
  616. if(m_lprclc != NULL)
  617. {
  618. m_wndHeader.ModifyProperty(FH_PROPERTY_DROPTARGET, (LPARAM)m_lprclc->m_hWnd);
  619. m_lprclc->SetReportCtrl(this);
  620. }
  621. return TRUE;
  622. }
  623. CReportColumnListCtrl* CReportCtrl::GetReportColumnListCtrl()
  624. {
  625. return m_lprclc;
  626. }
  627. BOOL CReportCtrl::SetSortCallback(LPFNRVCOMPARE lpfnrvc)
  628. {
  629. m_lpfnrvc = lpfnrvc;
  630. return TRUE;
  631. }
  632. LPFNRVCOMPARE CReportCtrl::GetSortCallback()
  633. {
  634. return m_lpfnrvc;
  635. }
  636. BOOL CReportCtrl::WriteProfile(LPCTSTR lpszSection, LPCTSTR lpszEntry)
  637. {
  638. CString str, strProfile;
  639. INT i;
  640. INT iSubItems = m_arraySubItems.GetSize();
  641. INT iColumns = m_arrayColumns.GetSize();
  642. strProfile.Format(_T("(%d,%d)"), iSubItems, iColumns);
  643. for(i=0;i<iSubItems;i++)
  644. {
  645. str.Format(" %d", m_arraySubItems[i].iWidth);
  646. strProfile += str;
  647. }
  648. for(i=0;i<iColumns;i++)
  649. {
  650. HDITEM hdi;
  651. hdi.mask = HDI_LPARAM;
  652. m_wndHeader.GetItem(m_arrayColumns[i], &hdi);
  653. str.Format(" %d", hdi.lParam);
  654. strProfile += str;
  655. }
  656. CWinApp* pApp = AfxGetApp();
  657. return pApp->WriteProfileString(lpszSection, lpszEntry, strProfile);
  658. }
  659. BOOL CReportCtrl::GetProfile(LPCTSTR lpszSection, LPCTSTR lpszEntry)
  660. {
  661. CString str, strProfile;
  662. CWinApp* pApp = AfxGetApp();
  663. strProfile = pApp->GetProfileString(lpszSection, lpszEntry);
  664. if(strProfile.IsEmpty())
  665. return FALSE;
  666. LPTSTR lpsz = strProfile.GetBuffer(0);
  667. INT i;
  668. INT iSubItems;
  669. INT iColumns;
  670. iSubItems = _tcstol(++lpsz, &lpsz, 10);
  671. iColumns = _tcstol(++lpsz, &lpsz, 10);
  672. if(iSubItems != m_arraySubItems.GetSize())
  673. return FALSE;
  674. for(i=0;i<iSubItems;i++)
  675. m_arraySubItems[i].iWidth = _tcstol(++lpsz, &lpsz, 10);
  676. for(i=0;i<iColumns;i++)
  677. ActivateColumn(_tcstol(++lpsz, &lpsz, 10), i);
  678. return TRUE;
  679. }
  680. /////////////////////////////////////////////////////////////////////////////
  681. // CReportCtrl operations
  682. BOOL CReportCtrl::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  683. {
  684. DWORD dwStyle = GetStyle();
  685. if(CWnd::ModifyStyle(dwRemove, dwAdd, nFlags))
  686. {
  687. if(!(dwStyle&RVS_SHOWHGRID) && dwAdd&RVS_SHOWHGRID)
  688. m_iDefaultHeight++;
  689. if(dwStyle&RVS_SHOWHGRID && dwRemove&RVS_SHOWHGRID)
  690. m_iDefaultHeight--;
  691. CRect rect;
  692. GetClientRect(rect);
  693. Layout(rect.Width(), rect.Height());
  694. return TRUE;
  695. }
  696. return FALSE;
  697. }
  698. INT CReportCtrl::DefineColumn(INT iColumn, LPRVCOLUMN lprvc, BOOL bUpdateList)
  699. {
  700. INT i;
  701. INT iColumns = m_arraySubItems.GetSize();
  702. ASSERT(iColumn <= iColumns);
  703. ASSERT(lprvc->lpszText != NULL); // Must supply (descriptive) text for subitem selector
  704. ASSERT(_tcslen(lprvc->lpszText) < FLATHEADER_TEXT_MAX);
  705. try
  706. {
  707. SUBITEM subitem;
  708. subitem.nFormat = lprvc->nFormat;
  709. subitem.iWidth = lprvc->iWidth<0 ? m_iDefaultWidth:lprvc->iWidth;
  710. subitem.iMinWidth = lprvc->iMinWidth;
  711. subitem.iMaxWidth = lprvc->iMaxWidth;
  712. subitem.iImage = lprvc->nFormat&RVCF_IMAGE ? lprvc->iImage:0;
  713. subitem.strText = lprvc->lpszText;
  714. m_arraySubItems.InsertAt(iColumn, subitem);
  715. HDITEM hdi;
  716. hdi.mask = HDI_LPARAM;
  717. INT iHeaderItems = m_arrayColumns.GetSize();
  718. for(i=0;i<iHeaderItems;i++)
  719. if(m_wndHeader.GetItem(i, &hdi))
  720. if(hdi.lParam >= iColumn)
  721. {
  722. hdi.lParam++;
  723. m_wndHeader.SetItem(i, &hdi);
  724. }
  725. INT iItems = m_arrayItems.GetSize();
  726. for(i=0;i<iItems;i++)
  727. VERIFY(m_arrayItems[i].rdData.InsertSubItem(iColumn, -1, -1, -1, NULL));
  728. if(bUpdateList && m_lprclc != NULL)
  729. m_lprclc->UpdateList();
  730. return iColumn;
  731. }
  732. catch(CMemoryException* e)
  733. {
  734. e->Delete();
  735. return -1;
  736. }
  737. }
  738. BOOL CReportCtrl::UndefineColumn(INT iColumn)
  739. {
  740. ASSERT(iColumn<m_arraySubItems.GetSize());
  741. VERIFY(!DeactivateColumn(iColumn));
  742. m_arraySubItems.RemoveAt(iColumn);
  743. HDITEM hdi;
  744. hdi.mask = HDI_LPARAM;
  745. INT i;
  746. INT iHeaderItems = m_arrayColumns.GetSize();
  747. for(i=0;i<iHeaderItems;i++)
  748. if(m_wndHeader.GetItem(i, &hdi))
  749. if(hdi.lParam > iColumn)
  750. {
  751. hdi.lParam--;
  752. m_wndHeader.SetItem(i, &hdi);
  753. }
  754. INT iItems = m_arrayItems.GetSize();
  755. for(i=0;i<iItems;i++)
  756. VERIFY(m_arrayItems[i].rdData.DeleteSubItem(iColumn));
  757. if(m_lprclc != NULL)
  758. m_lprclc->UpdateList();
  759. return TRUE;
  760. }
  761. INT CReportCtrl::InsertItem(INT iItem, LPTSTR lpszText, INT iImage, INT iCheck, INT iTextColor)
  762. {
  763. RVITEM rvi;
  764. rvi.nMask = RVIM_TEXT;
  765. rvi.iItem = iItem;
  766. rvi.iSubItem = 0;
  767. rvi.lpszText = lpszText;
  768. rvi.iTextColor = iTextColor;
  769. rvi.iImage = iImage;
  770. rvi.iCheck = iCheck;
  771. if(iTextColor >= 0)
  772. rvi.nMask |= RVIM_TEXTCOLOR;
  773. if(iImage >= 0)
  774. rvi.nMask |= RVIM_IMAGE;
  775. if(iCheck >= 0)
  776. rvi.nMask |= RVIM_CHECK;
  777. return InsertItem(&rvi);
  778. }
  779. INT CReportCtrl::InsertItem(LPRVITEM lprvi)
  780. {
  781. ASSERT(lprvi->iItem <= m_arrayItems.GetSize());
  782. ASSERT(lprvi->iSubItem < m_arraySubItems.GetSize());
  783. BOOL bInserted = FALSE;
  784. try
  785. {
  786. ITEM item;
  787. item.rdData.New(m_arraySubItems.GetSize());
  788. m_arrayItems.InsertAt(lprvi->iItem, item); bInserted = TRUE;
  789. m_arrayRows.InsertAt(lprvi->iItem, INT_MIN);
  790. INT iItems = m_arrayRows.GetSize();
  791. for(INT i=0;i<iItems;i++)
  792. if(m_arrayRows[i]>=lprvi->iItem)
  793. m_arrayRows[i]++;
  794. m_arrayRows[lprvi->iItem] = lprvi->iItem;
  795. m_iVirtualHeight++;
  796. VERIFY(SetItem(lprvi));
  797. ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));
  798. return lprvi->iItem;
  799. }
  800. catch(CMemoryException* e)
  801. {
  802. if(bInserted)
  803. m_arrayItems.RemoveAt(lprvi->iItem);
  804. e->Delete();
  805. return -1;
  806. }
  807. }
  808. BOOL CReportCtrl::DeleteItem(INT iItem)
  809. {
  810. m_arrayItems.RemoveAt(iItem);
  811. INT iItems = m_arrayRows.GetSize();
  812. for(INT i=0;i<iItems;i++)
  813. if(m_arrayRows[i]>iItem)
  814. m_arrayRows[i]--;
  815. m_iVirtualHeight--;
  816. iItems = m_arrayItems.GetSize();
  817. INT iFirst = GetScrollPos32(SB_VERT), iLast;
  818. GetVisibleRows(TRUE, &iFirst, &iLast);
  819. if(iItem<=iFirst || iLast>=iItems-1)
  820. GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);
  821. ScrollWindow(SB_VERT, iFirst);
  822. return TRUE;
  823. }
  824. BOOL CReportCtrl::DeleteAllItems()
  825. {
  826. m_arrayItems.RemoveAll();
  827. m_iVirtualHeight = 0;
  828. ScrollWindow(SB_VERT, 0);
  829. return TRUE;
  830. }
  831. void CReportCtrl::RedrawItems(INT iFirst, INT iLast)
  832. {
  833. // TODO: Optimize to redraw indivual rows
  834. // taking into account that the row height
  835. // may have changed. Redrawing everything
  836. // will work as well :)
  837. Invalidate();
  838. }
  839. BOOL CReportCtrl::EnsureVisible(INT iItem, BOOL bUnobstructed)
  840. {
  841. INT iFirst = GetScrollPos32(SB_VERT), iLast;
  842. INT iRow = FindItem(iItem);
  843. if(iRow < 0)
  844. return FALSE;
  845. GetVisibleRows(bUnobstructed, &iFirst, &iLast);
  846. if(iRow<iFirst)
  847. ScrollWindow(SB_VERT, iRow);
  848. if(iRow>iLast)
  849. {
  850. iLast = iRow;
  851. GetVisibleRows(bUnobstructed, &iFirst, &iLast, TRUE);
  852. ScrollWindow(SB_VERT, iFirst);
  853. }
  854. return TRUE;
  855. }
  856. INT CReportCtrl::InsertColor(INT iIndex, COLORREF crColor)
  857. {
  858. if(m_arrayColors.GetSize() == REPORTCTRL_MAX_COLORS)
  859. return -1;
  860. try
  861. {
  862. m_arrayColors.InsertAt(iIndex, crColor);
  863. if(CreatePalette())
  864. return iIndex;
  865. return -1;
  866. }
  867. catch(CMemoryException* e)
  868. {
  869. e->Delete();
  870. return -1;
  871. }
  872. }
  873. BOOL CReportCtrl::DeleteColor(INT iIndex)
  874. {
  875. if(iIndex >= m_arrayColors.GetSize())
  876. return FALSE;
  877. m_arrayColors.RemoveAt(iIndex);
  878. CreatePalette();
  879. return TRUE;
  880. }
  881. INT CReportCtrl::HitTest(LPRVHITTESTINFO lprvhti)
  882. {
  883. ASSERT(lprvhti);
  884. lprvhti->nFlags = 0;
  885. lprvhti->iItem = -1;
  886. lprvhti->iSubItem = -1;
  887. if(m_rectReport.PtInRect(lprvhti->point))
  888. {
  889. INT iHPos = GetScrollPos32(SB_HORZ);
  890. INT iFirst = GetScrollPos32(SB_VERT), iLast;
  891. if(GetVisibleRows(FALSE, &iFirst, &iLast))
  892. {
  893. ITEM item;
  894. CRect rectItem(
  895. m_rectReport.left-iHPos, m_rectReport.top, 
  896. m_rectReport.left-iHPos+m_iVirtualWidth, m_rectReport.top
  897. );
  898. for(;iFirst<=iLast;iFirst++)
  899. {
  900. item = m_arrayItems[m_arrayRows[iFirst]];
  901. rectItem.bottom += m_iDefaultHeight+item.nPreview;
  902. if(rectItem.PtInRect(lprvhti->point))
  903. break;
  904. rectItem.top = rectItem.bottom;
  905. }
  906. if(iFirst<=iLast)
  907. {
  908. if(item.nPreview)
  909. {
  910. CRect rectPreview(rectItem);
  911. rectPreview.top += m_iDefaultHeight;
  912. if(rectPreview.PtInRect(lprvhti->point))
  913. {
  914. lprvhti->iItem = m_arrayRows[iFirst];
  915. lprvhti->nFlags |= RVHT_ONITEMPREVIEW;
  916. return lprvhti->iItem;
  917. }
  918. }
  919. INT iHeaderItems = m_arrayColumns.GetSize();
  920. HDITEM hdi;
  921. hdi.mask = HDI_WIDTH|HDI_LPARAM;
  922. rectItem.right = rectItem.left;
  923. for(INT iHeaderItem=0;iHeaderItem<iHeaderItems;iHeaderItem++)
  924. {
  925. m_wndHeader.GetItem(m_arrayColumns[iHeaderItem], &hdi);
  926. rectItem.right += hdi.cxy;
  927. if(rectItem.PtInRect(lprvhti->point))
  928. break;
  929. rectItem.left = rectItem.right;
  930. }
  931. lprvhti->iSubItem = hdi.lParam;
  932. if(iHeaderItem<iHeaderItems)
  933. {
  934. RVITEM rvi;
  935. rvi.iItem = iFirst;
  936. rvi.iSubItem = lprvhti->iSubItem;
  937. GetItem(&rvi);
  938. lprvhti->iItem = m_arrayRows[iFirst];
  939. rectItem.right = rectItem.left+m_iSpacing;
  940. if(rvi.nMask&RVIM_IMAGE)
  941. {
  942. rectItem.right += m_sizeImage.cx+m_iSpacing;
  943. if(lprvhti->point.x < rectItem.right)
  944. {
  945. lprvhti->nFlags |= RVHT_ONITEMIMAGE;
  946. return lprvhti->iItem;
  947. }
  948. }
  949. if(rvi.nMask&RVIM_CHECK)
  950. {
  951. rectItem.right += m_sizeCheck.cx+m_iSpacing;
  952. if(lprvhti->point.x < rectItem.right)
  953. {
  954. lprvhti->nFlags |= RVHT_ONITEMCHECK;
  955. return lprvhti->iItem;
  956. }
  957. }
  958. lprvhti->nFlags |= RVHT_ONITEMTEXT;
  959. }
  960. else
  961. lprvhti->nFlags = RVHT_NOWHERE;
  962. }
  963. else
  964. lprvhti->nFlags = RVHT_NOWHERE;
  965. }
  966. else
  967. lprvhti->nFlags = RVHT_NOWHERE;
  968. }
  969. else
  970. {
  971. lprvhti->nFlags |= lprvhti->point.y<m_rectReport.top ? RVHT_ABOVE:0;
  972. lprvhti->nFlags |= lprvhti->point.y>m_rectReport.bottom ? RVHT_BELOW:0;
  973. lprvhti->nFlags |= lprvhti->point.x<m_rectReport.left ? RVHT_TOLEFT:0;
  974. lprvhti->nFlags |= lprvhti->point.x>m_rectReport.right ? RVHT_TORIGHT:0;
  975. }
  976. return lprvhti->iItem;
  977. }
  978. BOOL CReportCtrl::SortItems(INT iColumn, BOOL bAscending)
  979. {
  980. INT iHeaderColumn = FindColumnInHeader(iColumn);
  981. if(iHeaderColumn < 0)
  982. return FALSE; // Can't sort on columns that are not active
  983. INT iFocusItem = m_iFocusRow>=0 ? m_arrayRows[m_iFocusRow]:-1;
  984. INT iRows = m_arrayRows.GetSize();
  985. if(iRows>1)
  986. {
  987. for(INT i=0;i<iRows-1;i++)
  988. {
  989. for(INT j=i+1;j<iRows;j++)
  990. {
  991. INT iSort = CompareItems(iColumn, m_arrayRows[i], m_arrayRows[j]);
  992. if((bAscending && iSort>0) ||
  993.    (!bAscending && iSort<0))
  994. {
  995. INT iItem = m_arrayRows[i];
  996. m_arrayRows[i] = m_arrayRows[j];
  997. m_arrayRows[j] = iItem;
  998. }  
  999. }
  1000. }
  1001. }
  1002. m_wndHeader.SetSortColumn(m_arrayColumns[iHeaderColumn], bAscending);
  1003. if(iFocusItem>=0)
  1004. {
  1005. m_iFocusRow = FindItem(iFocusItem);
  1006. INT iFirst = m_iFocusRow, iLast;
  1007. GetVisibleRows(TRUE, &iFirst, &iLast);
  1008. GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);
  1009. ScrollWindow(SB_VERT, iFirst);
  1010. }
  1011. Invalidate();
  1012. return TRUE;
  1013. }
  1014. INT CReportCtrl::CompareItems(INT iColumn, INT iItem1, INT iItem2)
  1015. {
  1016. if(m_lpfnrvc == NULL)
  1017. {
  1018. RVITEM rvi1, rvi2;
  1019. TCHAR szText1[REPORTCTRL_MAX_TEXT], szText2[REPORTCTRL_MAX_TEXT];
  1020. rvi1.nMask = RVIM_TEXT;
  1021. rvi1.iItem = iItem1;
  1022. rvi1.iSubItem = iColumn;
  1023. rvi1.lpszText = szText1;
  1024. rvi1.iTextMax = REPORTCTRL_MAX_TEXT;
  1025. VERIFY(GetItem(&rvi1));
  1026. rvi2.nMask = RVIM_TEXT;
  1027. rvi2.iItem = iItem2;
  1028. rvi2.iSubItem = iColumn;
  1029. rvi2.lpszText = szText2;
  1030. rvi2.iTextMax = REPORTCTRL_MAX_TEXT;
  1031. VERIFY(GetItem(&rvi2));
  1032. return _tcscmp(szText1, szText2);
  1033. }
  1034. else
  1035. return m_lpfnrvc(iColumn, iItem1, iItem2);
  1036. }
  1037. /////////////////////////////////////////////////////////////////////////////
  1038. // CReportCtrl implementation
  1039. void CReportCtrl::GetSysColors()
  1040. {
  1041. m_crBackground = GetSysColor(COLOR_WINDOW);
  1042. m_crBkSelected = GetSysColor(COLOR_HIGHLIGHT);
  1043. m_crBkSelectedNoFocus = GetSysColor(COLOR_BTNFACE);
  1044. m_crText = GetSysColor(COLOR_WINDOWTEXT);
  1045. m_crTextSelected = GetSysColor(COLOR_HIGHLIGHTTEXT);
  1046. m_crTextSelectedNoFocus = GetSysColor(COLOR_WINDOWTEXT);
  1047. m_crGrid = GetSysColor(COLOR_BTNFACE);
  1048. }
  1049. BOOL CReportCtrl::CreatePalette()
  1050. {
  1051. if(m_palette.m_hObject)
  1052. m_palette.DeleteObject();
  1053. INT iColors = m_arrayColors.GetSize();
  1054. if(iColors)
  1055. {
  1056. struct
  1057. {
  1058. LOGPALETTE    LogPalette;
  1059. PALETTEENTRY  PalEntry[REPORTCTRL_MAX_COLORS];
  1060. } pal;
  1061. LPLOGPALETTE lpLogPalette = (LOGPALETTE*) &pal;
  1062. lpLogPalette->palVersion    = 0x300;
  1063. lpLogPalette->palNumEntries = (WORD)iColors; 
  1064. for(INT i=0;i<iColors;i++)
  1065. {
  1066. lpLogPalette->palPalEntry[i].peRed   = GetRValue(m_arrayColors[i]);
  1067. lpLogPalette->palPalEntry[i].peGreen = GetGValue(m_arrayColors[i]);
  1068. lpLogPalette->palPalEntry[i].peBlue  = GetBValue(m_arrayColors[i]);
  1069. lpLogPalette->palPalEntry[i].peFlags = 0;
  1070. }
  1071. m_palette.CreatePalette(lpLogPalette);
  1072. return TRUE;
  1073. }
  1074. return FALSE;
  1075. }
  1076. BOOL CReportCtrl::Notify(UINT nCode, INT iItem, INT iSubItem, LPARAM lParam)
  1077. {
  1078. NMREPORTVIEW nmrv;
  1079. nmrv.hdr.hwndFrom = m_hWnd;
  1080. nmrv.hdr.idFrom = GetDlgCtrlID();
  1081. nmrv.hdr.code = nCode;
  1082. nmrv.iItem = iItem;
  1083. nmrv.iSubItem = iSubItem;
  1084. nmrv.lParam = lParam;
  1085. CWnd* pWnd = GetParent();
  1086. if(pWnd)
  1087. return pWnd->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmrv);
  1088. return FALSE;
  1089. }
  1090. BOOL CReportCtrl::Notify(UINT nCode, UINT nKeys, LPRVHITTESTINFO lprvhti)
  1091. {
  1092. NMREPORTVIEW nmrv;
  1093. nmrv.hdr.hwndFrom = m_hWnd;
  1094. nmrv.hdr.idFrom = GetDlgCtrlID();
  1095. nmrv.hdr.code = nCode;
  1096. nmrv.nKeys = nKeys;
  1097. nmrv.point = lprvhti->point;
  1098. nmrv.nFlags = lprvhti->nFlags;
  1099. nmrv.iItem = lprvhti->iItem;
  1100. nmrv.iSubItem = lprvhti->iSubItem;
  1101. if(lprvhti->iItem >= 0)
  1102. nmrv.lParam = m_arrayItems[lprvhti->iItem].lParam;
  1103. CWnd* pWnd = GetParent();
  1104. if(pWnd)
  1105. return pWnd->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmrv);
  1106. return FALSE;
  1107. }
  1108. void CReportCtrl::Layout(INT cx, INT cy)
  1109. {
  1110. HDLAYOUT hdl;
  1111. WINDOWPOS wpos;
  1112. hdl.prc = &m_rectReport;
  1113. hdl.pwpos = &wpos;
  1114. m_rectReport.SetRect(0, 0, cx, cy);
  1115. if(IsWindow(m_wndHeader.m_hWnd))
  1116. {
  1117. if(!(GetStyle()&RVS_NOHEADER))
  1118. {
  1119. VERIFY(m_wndHeader.SendMessage(HDM_LAYOUT, 0, (LPARAM)&hdl));
  1120. m_rectHeader.SetRect(wpos.x, wpos.y, wpos.x+wpos.cx, wpos.y+wpos.cy);
  1121. }
  1122. else
  1123. m_rectHeader.SetRect(0, 0, cx, 0);
  1124. ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));
  1125. ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));
  1126. }
  1127. }
  1128. INT CReportCtrl::FindItem(INT iItem)
  1129. {
  1130. INT iRows = m_arrayRows.GetSize();
  1131. for(INT iRow=0;iRow<iRows;iRow++)
  1132. if(m_arrayRows[iRow] == iItem)
  1133. return iRow;
  1134. return -1;
  1135. }
  1136. INT CReportCtrl::FindColumnInHeader(INT iColumn)
  1137. {
  1138. INT iColumns = m_arrayColumns.GetSize();
  1139. for(INT i=0;i<iColumns;i++)
  1140. {
  1141. HDITEM hdi;
  1142. hdi.mask = HDI_WIDTH|HDI_LPARAM;
  1143. m_wndHeader.GetItem(m_arrayColumns[i], &hdi);
  1144. if(hdi.lParam == iColumn)
  1145. return i;
  1146. }
  1147. return -1;
  1148. }
  1149. INT CReportCtrl::GetVisibleRows(BOOL bUnobstructed, LPINT lpiFirst, LPINT lpiLast, BOOL bReverse)
  1150. {
  1151. INT iHeight = m_rectReport.Height();
  1152. INT iRows = 0;
  1153. if(!bReverse)
  1154. {
  1155. INT iRow;
  1156. INT iMaxRows = m_arrayRows.GetSize();
  1157. if(lpiFirst)
  1158. iRow = *lpiFirst;
  1159. else
  1160. iRow = GetScrollPos32(SB_VERT);
  1161. for(;iRow<iMaxRows&&iHeight>0;iRow++,iRows++)
  1162. {
  1163. iHeight -= m_iDefaultHeight+m_arrayItems[m_arrayRows[iRow]].nPreview;
  1164. if(bUnobstructed && iHeight<=0)
  1165. break;
  1166. }
  1167. if(lpiLast)
  1168. *lpiLast = iRow-1;
  1169. }
  1170. else
  1171. {
  1172. ASSERT(lpiFirst);
  1173. ASSERT(lpiLast);
  1174. for(*lpiFirst=*lpiLast;*lpiFirst>=0&&iHeight>0;*lpiFirst-=1,iRows++)
  1175. {
  1176. iHeight -= m_iDefaultHeight+m_arrayItems[m_arrayRows[*lpiFirst]].nPreview;
  1177. if(bUnobstructed && iHeight<=0)
  1178. break;
  1179. }
  1180. *lpiFirst += 1;
  1181. }
  1182. return iRows;
  1183. }
  1184. void CReportCtrl::SelectRows(INT iFirst, INT iLast, BOOL bSelect, BOOL bKeepSelection, BOOL bInvert)
  1185. {
  1186. INT i;
  1187. if(GetStyle()&RVS_SINGLESELECT)
  1188. {
  1189. iLast = iFirst;
  1190. bKeepSelection = FALSE;
  1191. }
  1192. if(m_iFocusRow>=0 && iFirst!=m_iFocusRow)
  1193. {
  1194. m_arrayItems[m_arrayRows[m_iFocusRow]].nState &= ~RVIS_FOCUSED;
  1195. RedrawItems(m_iFocusRow);
  1196. }
  1197. m_iFocusRow = iFirst;
  1198. m_arrayItems[m_arrayRows[iFirst]].nState |= RVIS_FOCUSED;
  1199. if(iFirst > iLast)
  1200. {
  1201. iLast += iFirst;
  1202. iFirst = iLast - iFirst;
  1203. iLast -= iFirst;
  1204. }
  1205. if(bSelect)
  1206. {
  1207. for(i=iFirst;i<=iLast;i++)
  1208. {
  1209. INT iItem = m_arrayRows[i];
  1210. UINT nOldState, nNewState;
  1211. nOldState = nNewState = m_arrayItems[iItem].nState;
  1212. if(bInvert)
  1213. nNewState ^= RVIS_SELECTED;
  1214. else
  1215. nNewState |= RVIS_SELECTED;
  1216. if(nNewState != nOldState)
  1217. {
  1218. if(Notify(RVN_SELECTIONCHANGING, iItem))
  1219. continue;
  1220. m_arrayItems[iItem].nState = nNewState;
  1221. Notify(RVN_SELECTIONCHANGED, iItem);
  1222. }
  1223. }
  1224. RedrawItems(iFirst, iLast);
  1225. }
  1226. else
  1227. RedrawItems(iFirst);
  1228. if(!bKeepSelection && bSelect)
  1229. {
  1230. INT iRows = m_arrayRows.GetSize();
  1231. for(i=0;i<iRows;i++)
  1232. {
  1233. INT iItem = m_arrayRows[i];
  1234. UINT nOldState, nNewState;
  1235. nOldState = nNewState = m_arrayItems[iItem].nState;
  1236. if((i<iFirst || i>iLast) && nOldState&RVIS_SELECTED)
  1237. {
  1238. nNewState &= ~RVIS_SELECTED;
  1239. if(nNewState != nOldState)
  1240. {
  1241. if(Notify(RVN_SELECTIONCHANGING, iItem))
  1242. continue;
  1243. m_arrayItems[iItem].nState = nNewState;
  1244. Notify(RVN_SELECTIONCHANGED, iItem);
  1245. RedrawItems(i);
  1246. }
  1247. }
  1248. }
  1249. }
  1250. }
  1251. INT CReportCtrl::GetScrollPos32(INT iBar, BOOL bGetTrackPos)
  1252. {
  1253. SCROLLINFO si;
  1254. si.cbSize = sizeof(SCROLLINFO);
  1255. if(bGetTrackPos)
  1256. {
  1257. if(GetScrollInfo(iBar, &si, SIF_TRACKPOS))
  1258. return si.nTrackPos;
  1259. }
  1260. else 
  1261. {
  1262. if(GetScrollInfo(iBar, &si, SIF_POS))
  1263. return si.nPos;
  1264. }
  1265. return 0;
  1266. }
  1267. BOOL CReportCtrl::SetScrollPos32(INT iBar, INT iPos, BOOL bRedraw)
  1268. {
  1269.     SCROLLINFO si;
  1270.     si.cbSize = sizeof(SCROLLINFO);
  1271.     si.fMask  = SIF_POS;
  1272.     si.nPos   = iPos;
  1273.     return SetScrollInfo(iBar, &si, bRedraw);
  1274. }
  1275. void CReportCtrl::ScrollWindow(INT iBar, INT iPos)
  1276. {
  1277. if(m_rectReport.Width()<=0 || m_rectReport.Height()<=0)
  1278. return;
  1279. if(iBar == SB_HORZ)
  1280. {
  1281. SCROLLINFO si;
  1282. INT iWidth = m_rectReport.Width();
  1283. si.cbSize = sizeof(SCROLLINFO);
  1284. si.fMask  = SIF_PAGE|SIF_RANGE|SIF_POS;
  1285. si.nPage = iWidth;
  1286. si.nMin = 0;
  1287. si.nMax = iWidth<m_iVirtualWidth ? m_iVirtualWidth-1:0;
  1288. si.nPos = iPos;
  1289. SetScrollInfo(SB_HORZ, &si, TRUE);
  1290. INT x = GetScrollPos32(SB_HORZ);
  1291. INT cx = iWidth<m_iVirtualWidth ? m_iVirtualWidth:iWidth;
  1292. VERIFY(m_wndHeader.SetWindowPos(&wndTop, -x, m_rectHeader.top, cx, m_rectHeader.Height(), GetStyle()&RVS_NOHEADER ? SWP_HIDEWINDOW:SWP_SHOWWINDOW));
  1293. }
  1294. if(iBar == SB_VERT)
  1295. {
  1296. INT iItems = m_arrayItems.GetSize();
  1297. ASSERT(iPos >= 0 && iPos<=iItems);
  1298. INT iFirst = iPos, iLast;
  1299. GetVisibleRows(TRUE, &iFirst, &iLast);
  1300. SCROLLINFO si;
  1301. si.cbSize = sizeof(SCROLLINFO);
  1302. si.fMask  = SIF_PAGE|SIF_RANGE|SIF_POS;
  1303. si.nPage = (iLast - iFirst + 1);
  1304. si.nMin = 0;
  1305. si.nMax = (iLast - iFirst + 1)<iItems ? iItems-1:0;
  1306. si.nPos = iFirst;
  1307. SetScrollInfo(SB_VERT, &si, TRUE);
  1308. }
  1309. Invalidate();
  1310. }
  1311. void CReportCtrl::DrawCtrl(CDC* pDC)
  1312. {
  1313. CRect rectClip;
  1314. if (pDC->GetClipBox(&rectClip) == ERROR)
  1315. return;
  1316. DWORD dwStyle = GetStyle();
  1317. INT iHPos = GetScrollPos32(SB_HORZ);
  1318. INT iVPos = GetScrollPos32(SB_VERT);
  1319. pDC->FillSolidRect(rectClip, m_crBackground);
  1320. CPen pen(m_iGridStyle, 1, m_crGrid);
  1321. CPen* pPen = pDC->SelectObject(&pen);
  1322. CFont* pFont = pDC->SelectObject(GetFont());
  1323. pDC->SetBkMode(TRANSPARENT);
  1324. CRect rectRow(m_rectReport.left-iHPos, m_rectReport.top, m_rectReport.left-iHPos+m_iVirtualWidth, m_rectReport.top);
  1325. CRect rectItem(rectRow);
  1326. TCHAR szText[REPORTCTRL_MAX_TEXT];
  1327. RVITEM rvi;
  1328. rvi.lpszText = szText;
  1329. rvi.iTextMax = REPORTCTRL_MAX_TEXT;
  1330. NMRVDRAWPREVIEW nmrvdp;
  1331. nmrvdp.hdr.hwndFrom = m_hWnd;
  1332. nmrvdp.hdr.idFrom = GetDlgCtrlID();
  1333. nmrvdp.hdr.code = RVN_ITEMDRAWPREVIEW;
  1334. nmrvdp.hDC = pDC->m_hDC;
  1335. CWnd* pwndParent = GetParent();
  1336. INT iRows = m_arrayRows.GetSize();
  1337. INT iColumns = m_wndHeader.GetItemCount();
  1338. ASSERT(iColumns>0); // Make sure that always one column is active
  1339. if(m_bColumnsReordered)
  1340. {
  1341. LPINT lpi;
  1342. m_arrayColumns.SetSize(iColumns, 8);
  1343. lpi = m_arrayColumns.GetData();
  1344. if(!m_wndHeader.GetOrderArray(lpi, iColumns))
  1345. return;
  1346. if(m_lprclc != NULL)
  1347. m_lprclc->UpdateList();
  1348. m_bColumnsReordered = FALSE;
  1349. }
  1350. if(!iRows)
  1351. {
  1352. rectRow.top += 2;
  1353. rectRow.bottom = rectRow.top + m_iDefaultHeight;
  1354. pDC->SetTextColor(m_crText);
  1355. pDC->DrawText(m_strNoItems, rectRow, DT_CENTER|DT_END_ELLIPSIS);
  1356. return;
  1357. }
  1358. INT iRow = iVPos;
  1359. while(iRow<iRows && rectRow.top<rectClip.bottom)
  1360. {
  1361. rvi.iItem = m_arrayRows[iRow];
  1362. ITEM& item = m_arrayItems[rvi.iItem];
  1363. rectRow.bottom = rectRow.top + m_iDefaultHeight+item.nPreview;
  1364. if(rectRow.bottom >= rectClip.top)
  1365. {
  1366. // You have to insert at least 1 color to use color alternate style.
  1367. ASSERT(!(dwStyle&RVS_SHOWCOLORALTERNATE && !m_arrayColors.GetSize()));
  1368. COLORREF crItem;
  1369. crItem = (dwStyle&RVS_SHOWCOLORALTERNATE && iRow&1) ? m_arrayColors[0]:m_crBackground;
  1370. crItem = item.iBkColor>=0 ? m_arrayColors[item.iBkColor]:crItem;
  1371. if(item.nState&RVIS_SELECTED)
  1372. {
  1373. if(m_bFocus)
  1374. crItem = m_crBkSelected;
  1375. else
  1376. if(dwStyle&RVS_SHOWSELALWAYS)
  1377. crItem = m_crBkSelectedNoFocus;
  1378. }
  1379. pDC->FillSolidRect(rectRow, crItem);
  1380. pDC->SetBkColor(crItem);
  1381. if(item.nState&RVIS_BOLD)
  1382. pDC->SelectObject(&m_fontBold);
  1383. rectItem.SetRect(rectRow.left, rectRow.top, rectRow.left, rectRow.top+m_iDefaultHeight);
  1384. for(INT iColumn=0;iColumn<iColumns&&rectItem.left<rectClip.right;iColumn++)
  1385. {
  1386. HDITEM hdi;
  1387. hdi.mask = HDI_WIDTH|HDI_LPARAM;
  1388. m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);
  1389. rvi.iSubItem = hdi.lParam;
  1390. rectItem.right = rectItem.left + hdi.cxy;
  1391. if(rectItem.right > rectClip.left)
  1392. {
  1393. rvi.nMask = RVIM_TEXT;
  1394. VERIFY(GetItem(&rvi));
  1395. COLORREF crText = rvi.nMask&RVIM_TEXTCOLOR ? m_arrayColors[rvi.iTextColor]:m_crText;
  1396. if(item.nState&RVIS_SELECTED)
  1397. {
  1398. if(m_bFocus)
  1399. crText = (dwStyle&RVS_SHOWCOLORALWAYS && rvi.nMask&RVIM_TEXTCOLOR) ? crText:m_crTextSelected;
  1400. else
  1401. if(dwStyle&RVS_SHOWSELALWAYS)
  1402. crText = rvi.nMask&RVIM_TEXTCOLOR && dwStyle&RVS_SHOWCOLORALWAYS ? crText:m_crTextSelectedNoFocus;
  1403. }
  1404. pDC->SetTextColor(crText);
  1405. rectItem.DeflateRect(m_iSpacing, 0);
  1406. DrawItem(pDC, rectItem, &rvi);
  1407. rectItem.InflateRect(m_iSpacing, 0);
  1408. }
  1409. rectItem.left = rectItem.right;
  1410. }
  1411. if(item.nState&RVIS_BOLD)
  1412. pDC->SelectObject(GetFont());
  1413. if(rvi.nMask&RVIM_PREVIEW && item.nPreview && pwndParent)
  1414. {
  1415. nmrvdp.iItem = rvi.iItem;
  1416. nmrvdp.nState = item.nState;
  1417. nmrvdp.rect = rectRow;
  1418. nmrvdp.rect.top += m_iDefaultHeight;
  1419. nmrvdp.lParam = item.lParam;
  1420. pwndParent->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmrvdp);
  1421. }
  1422. if(dwStyle&RVS_SHOWHGRID)
  1423. {
  1424. pDC->MoveTo(rectRow.left, rectRow.bottom-1);
  1425. pDC->LineTo(rectRow.right, rectRow.bottom-1);
  1426. }
  1427. if(m_bFocus && item.nState&RVIS_FOCUSED)
  1428. {
  1429. if(dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))
  1430. rectRow.DeflateRect(1, 0, 1, 1);
  1431. pDC->SetBkColor(m_crBackground);
  1432. pDC->SetTextColor(m_crText);
  1433. pDC->DrawFocusRect(rectRow);
  1434. if(dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))
  1435. rectRow.InflateRect(1, 0, 1, 1);
  1436. }
  1437. }
  1438. rectRow.top = rectRow.bottom;
  1439. iRow++;
  1440. }
  1441. if(dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))
  1442. {
  1443. pDC->MoveTo(rectRow.left, m_rectReport.top);
  1444. pDC->LineTo(rectRow.left, m_rectReport.bottom);
  1445. pDC->MoveTo(rectRow.right-1, m_rectReport.top);
  1446. pDC->LineTo(rectRow.right-1, m_rectReport.bottom);
  1447. }
  1448. if(dwStyle&RVS_SHOWHGRID && iRow>=iRows)
  1449. {
  1450. while(rectRow.bottom<rectClip.bottom)
  1451. {
  1452. pDC->MoveTo(rectRow.left, rectRow.bottom-1);
  1453. pDC->LineTo(rectRow.right, rectRow.bottom-1);
  1454. rectRow.bottom += m_iDefaultHeight;
  1455. }
  1456. }
  1457. if(dwStyle&RVS_SHOWVGRID)
  1458. {
  1459. for(INT iColumn=0;iColumn<iColumns&&rectItem.left<rectClip.right;iColumn++)
  1460. {
  1461. HDITEM hdi;
  1462. hdi.mask = HDI_WIDTH;
  1463. m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);
  1464. rectRow.left += hdi.cxy;
  1465. pDC->MoveTo(rectRow.left-1, m_rectReport.top);
  1466. pDC->LineTo(rectRow.left-1, m_rectReport.bottom);
  1467. }
  1468. }
  1469. pDC->SelectObject(pFont);
  1470. pDC->SelectObject(pPen);
  1471. pen.DeleteObject();
  1472. }
  1473. void CReportCtrl::DrawItem(CDC* pDC, CRect rect, LPRVITEM lprvi)
  1474. {
  1475. INT iWidth = 0;
  1476. rect.left += (iWidth = DrawImage(pDC, rect, lprvi)) ? iWidth+m_iSpacing : 0;
  1477. if(lprvi->nMask&RVIM_IMAGE && !iWidth)
  1478. return;
  1479. rect.left += (iWidth = DrawCheck(pDC, rect, lprvi)) ? iWidth+m_iSpacing : 0;
  1480. if(lprvi->nMask&RVIM_CHECK && !iWidth)
  1481. return;
  1482. DrawText(pDC, rect, lprvi);
  1483. }
  1484. INT CReportCtrl::DrawImage(CDC* pDC, CRect rect, LPRVITEM lprvi)
  1485. {
  1486. CImageList* pImageList = GetImageList();
  1487. INT iWidth = 0;
  1488. if(lprvi->nMask&RVIM_IMAGE)
  1489. {
  1490. ASSERT(pImageList);
  1491. ASSERT(lprvi->iImage>=0 && lprvi->iImage<pImageList->GetImageCount());
  1492. if(rect.Width()>0)
  1493. {
  1494. POINT point;
  1495. point.y = rect.CenterPoint().y - (m_sizeImage.cy>>1);
  1496. point.x = rect.left;
  1497. SIZE size;
  1498. size.cx = rect.Width()<m_sizeImage.cx ? rect.Width():m_sizeImage.cx;
  1499. size.cy = m_sizeImage.cy;
  1500. pImageList->DrawIndirect(pDC, lprvi->iImage, point, size, CPoint(0, 0));
  1501. iWidth = m_sizeImage.cx;
  1502. }
  1503. }
  1504. else
  1505. iWidth = m_arraySubItems[lprvi->iSubItem].nFormat&RVCF_SUBITEM_IMAGE ? m_sizeImage.cx:0;
  1506. return iWidth;
  1507. }
  1508. INT CReportCtrl::DrawCheck(CDC* pDC, CRect rect, LPRVITEM lprvi)
  1509. {
  1510. INT iWidth = 0;
  1511. if(lprvi->nMask&RVIM_CHECK)
  1512. {
  1513. if(rect.Width()>m_sizeCheck.cx)
  1514. {
  1515. rect.top = rect.CenterPoint().y - (m_sizeCheck.cy>>1);
  1516. rect.left = rect.left;
  1517. rect.bottom = rect.top + m_sizeCheck.cx;
  1518. rect.right = rect.left + m_sizeCheck.cy;
  1519. pDC->FillSolidRect(rect, m_crBackground); // Fixes visual problem with bigger fonts
  1520. pDC->DrawFrameControl(
  1521. rect, 
  1522. DFC_BUTTON, 
  1523. DFCS_BUTTONCHECK|DFCS_FLAT|(lprvi->iCheck?DFCS_CHECKED:0)
  1524. );
  1525. iWidth = m_sizeCheck.cx;
  1526. }
  1527. }
  1528. else
  1529. iWidth = m_arraySubItems[lprvi->iSubItem].nFormat&RVCF_SUBITEM_CHECK ? m_sizeCheck.cx:0;
  1530. return iWidth;
  1531. }
  1532. INT CReportCtrl::DrawText(CDC* pDC, CRect rect, LPRVITEM lprvi)
  1533. {
  1534. CSize size;
  1535. if(rect.Width()>0 && lprvi->nMask&RVIM_TEXT)
  1536. {
  1537. size = pDC->GetTextExtent(lprvi->lpszText);
  1538. switch(m_arraySubItems[lprvi->iSubItem].nFormat&HDF_JUSTIFYMASK)
  1539. {
  1540. case HDF_LEFT:
  1541. case HDF_LEFT|HDF_RTLREADING:
  1542. pDC->DrawText(lprvi->lpszText, -1, rect, DT_LEFT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
  1543. break;
  1544. case HDF_CENTER:
  1545. case HDF_CENTER|HDF_RTLREADING:
  1546. pDC->DrawText(lprvi->lpszText, -1, rect, DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
  1547. break;
  1548. case HDF_RIGHT:
  1549. case HDF_RIGHT|HDF_RTLREADING:
  1550. pDC->DrawText(lprvi->lpszText, -1, rect, DT_RIGHT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
  1551. break;
  1552. }
  1553. }
  1554. size.cx = rect.Width()>size.cx ? size.cx:rect.Width();
  1555. return size.cx>0 ? size.cx:0;
  1556. }
  1557. /////////////////////////////////////////////////////////////////////////////
  1558. // CReportCtrl message handlers
  1559. BOOL CReportCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  1560. {
  1561. SetCursor(::LoadCursor(NULL, IDC_ARROW));
  1562. return CWnd::OnSetCursor(pWnd, nHitTest, message);
  1563. }
  1564. void CReportCtrl::OnSetFocus(CWnd* pOldWnd) 
  1565. {
  1566. CWnd::OnSetFocus(pOldWnd);
  1567. m_bFocus = TRUE;
  1568. Invalidate();
  1569. }
  1570. void CReportCtrl::OnKillFocus(CWnd* pNewWnd) 
  1571. {
  1572. CWnd::OnKillFocus(pNewWnd);
  1573. m_bFocus = FALSE;
  1574. Invalidate();
  1575. }
  1576. void CReportCtrl::OnSysColorChange() 
  1577. {
  1578. CWnd::OnSysColorChange();
  1579. GetSysColors();
  1580. }
  1581. BOOL CReportCtrl::OnQueryNewPalette() 
  1582. {
  1583. Invalidate();
  1584. return CWnd::OnQueryNewPalette();
  1585. }
  1586. void CReportCtrl::OnPaletteChanged(CWnd* pFocusWnd) 
  1587. {
  1588. CWnd::OnPaletteChanged(pFocusWnd);
  1589. if(pFocusWnd->GetSafeHwnd() != GetSafeHwnd())
  1590. Invalidate();
  1591. }
  1592. void CReportCtrl::OnSize(UINT nType, int cx, int cy) 
  1593. {
  1594. CWnd::OnSize(nType, cx, cy);
  1595. CRect rect;
  1596. GetClientRect(rect);
  1597. Layout(rect.Width(), rect.Height());
  1598. }
  1599. LRESULT CReportCtrl::OnGetFont(WPARAM wParam, LPARAM lParam)
  1600. {
  1601.     return (LRESULT)m_font.m_hObject;
  1602. }
  1603. LRESULT CReportCtrl::OnSetFont(WPARAM wParam, LPARAM lParam)
  1604. {
  1605. LRESULT lResult = Default();
  1606. CFont *pFont = CFont::FromHandle((HFONT)wParam);
  1607. if(pFont)
  1608. {
  1609. LOGFONT lf;
  1610. pFont->GetLogFont(&lf);
  1611. m_font.DeleteObject();
  1612. m_font.CreateFontIndirect(&lf);
  1613. lf.lfWeight = FW_BOLD;
  1614. m_fontBold.DeleteObject();
  1615. m_fontBold.CreateFontIndirect(&lf);
  1616. }
  1617. CDC* pDC = GetDC();
  1618. if (pDC) 
  1619. {
  1620. CFont* pFont = pDC->SelectObject(&m_font);
  1621. TEXTMETRIC tm;
  1622. pDC->GetTextMetrics(&tm);
  1623. pDC->SelectObject(pFont);
  1624. ReleaseDC(pDC);
  1625. m_iDefaultHeight = tm.tmHeight + tm.tmExternalLeading + 2;
  1626. m_iDefaultHeight += GetStyle()&RVS_SHOWHGRID ? 1:0;
  1627. m_sizeCheck.cx = m_iDefaultHeight-2;
  1628. m_sizeCheck.cy = m_iDefaultHeight-2;
  1629. }
  1630. if(::IsWindow(GetSafeHwnd()) && lParam)
  1631. {
  1632. CRect rect;
  1633. GetClientRect(rect);
  1634. Layout(rect.Width(), rect.Height());
  1635. }
  1636. return lResult;
  1637. }
  1638. BOOL CReportCtrl::OnEraseBkgnd(CDC* pDC) 
  1639. {
  1640. return TRUE;
  1641. }
  1642. void CReportCtrl::OnPaint() 
  1643. {
  1644. CPaintDC dc(this);
  1645.     CPalette* pPalette = NULL;
  1646.     if(dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
  1647.     {
  1648.         pPalette = dc.SelectPalette(&m_palette, FALSE);
  1649.         dc.RealizePalette();
  1650.     }
  1651. dc.ExcludeClipRect(m_rectHeader);
  1652.     if(m_bDoubleBuffer)
  1653.     {
  1654.         CMemDC MemDC(&dc);
  1655.         DrawCtrl(&MemDC);
  1656.     }
  1657.     else
  1658.         DrawCtrl(&dc);
  1659.     if(pPalette && dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
  1660.         dc.SelectPalette(pPalette, FALSE);
  1661. }
  1662. void CReportCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  1663. {
  1664. INT iScrollPos = GetScrollPos32(SB_HORZ);
  1665. INT iScroll;
  1666. switch (nSBCode)
  1667. {
  1668. case SB_LINERIGHT:
  1669. iScroll = min(m_iVirtualWidth-(m_rectReport.Width()+iScrollPos), m_rectReport.Width()>>3);
  1670. ScrollWindow(SB_HORZ, iScrollPos + iScroll);
  1671. break;
  1672. case SB_LINELEFT:
  1673. iScroll = min(iScrollPos, m_rectReport.Width()>>3);
  1674. ScrollWindow(SB_HORZ, iScrollPos - iScroll);
  1675. break;
  1676. case SB_PAGERIGHT:
  1677. iScrollPos = min(m_iVirtualWidth, iScrollPos + m_rectReport.Width());
  1678. ScrollWindow(SB_HORZ, iScrollPos);
  1679. break;
  1680. case SB_PAGELEFT:
  1681. iScrollPos = max(0, iScrollPos - m_rectReport.Width());
  1682. ScrollWindow(SB_HORZ, iScrollPos);
  1683. break;
  1684. case SB_THUMBPOSITION:
  1685. case SB_THUMBTRACK:
  1686. iScrollPos = GetScrollPos32(SB_HORZ, TRUE);
  1687. ScrollWindow(SB_HORZ, iScrollPos);
  1688. break;
  1689. case SB_RIGHT:
  1690. ScrollWindow(SB_HORZ, m_iVirtualWidth);
  1691. break;
  1692. case SB_LEFT:
  1693. ScrollWindow(SB_HORZ, 0);
  1694. break;
  1695. default:
  1696. break;
  1697. }
  1698. }
  1699. void CReportCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  1700. {
  1701. INT iFirst = GetScrollPos32(SB_VERT), iLast;
  1702. INT iItems = GetVisibleRows(TRUE, &iFirst, &iLast);
  1703. switch(nSBCode)
  1704. {
  1705. case SB_LINEUP:
  1706. if(iFirst>0)
  1707. iFirst--;
  1708. break;
  1709. case SB_LINEDOWN:
  1710. if(iFirst+iItems < m_iVirtualHeight)
  1711. iFirst++;
  1712. break;
  1713. case SB_PAGEUP:
  1714. GetVisibleRows(TRUE, &iLast, &iFirst, TRUE);
  1715. iFirst = iLast-1;
  1716. iFirst = iFirst<0 ? 0:iFirst;
  1717. break;
  1718. case SB_PAGEDOWN:
  1719. iFirst += iItems;
  1720. GetVisibleRows(TRUE, &iFirst, &iLast);
  1721. GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);
  1722. break;
  1723. case SB_THUMBPOSITION:
  1724. case SB_THUMBTRACK:
  1725. iFirst = GetScrollPos32(SB_VERT, TRUE);
  1726. GetVisibleRows(TRUE, &iFirst, &iLast);
  1727. GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);
  1728. break;
  1729. case SB_TOP:
  1730. iFirst = 0;
  1731. break;
  1732. case SB_BOTTOM:
  1733. iLast = m_arrayRows.GetSize()-1;
  1734. GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);
  1735. break;
  1736. default:
  1737. return;
  1738. }
  1739. ScrollWindow(SB_VERT, iFirst);
  1740. }
  1741. void CReportCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
  1742. {
  1743. SetFocus();
  1744. RVHITTESTINFO rvhti;
  1745. rvhti.point = point;
  1746. HitTest(&rvhti);
  1747. if(Notify(RVN_ITEMCLICK, nFlags, &rvhti))
  1748. {
  1749. CWnd::OnLButtonDown(nFlags, point);
  1750. return;
  1751. }
  1752. if(rvhti.iItem>=0)
  1753. {
  1754. INT iRow = FindItem(rvhti.iItem);
  1755. ASSERT(iRow >= 0);
  1756. switch(nFlags&(MK_CONTROL|MK_SHIFT))
  1757. {
  1758. case MK_CONTROL:
  1759. SelectRows(iRow, iRow, TRUE, TRUE, TRUE);
  1760. m_iSelectRow = iRow;
  1761. break;
  1762. case MK_SHIFT:
  1763. SelectRows(m_iSelectRow, iRow, TRUE);
  1764. break;
  1765. case MK_CONTROL|MK_SHIFT:
  1766. SelectRows(m_iSelectRow, iRow, TRUE, TRUE);
  1767. m_iSelectRow = iRow;
  1768. break;
  1769. default:
  1770. SelectRows(iRow, iRow, TRUE);
  1771. m_iSelectRow = iRow;
  1772. break;
  1773. }
  1774. }
  1775. }
  1776. void CReportCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
  1777. {
  1778. RVHITTESTINFO rvhti;
  1779. rvhti.point = point;
  1780. HitTest(&rvhti);
  1781. if(Notify(RVN_ITEMDBCLICK, nFlags, &rvhti))
  1782. {
  1783. CWnd::OnLButtonDblClk(nFlags, point);
  1784. return;
  1785. }
  1786. }
  1787. UINT CReportCtrl::OnGetDlgCode() 
  1788. {
  1789. return DLGC_WANTARROWS;
  1790. }
  1791. #define IsShiftDown() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0   )
  1792. #define IsCtrlDown() ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 )
  1793. void CReportCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  1794. {
  1795. INT iFirst = GetScrollPos32(SB_VERT), iLast;
  1796. GetVisibleRows(TRUE, &iFirst, &iLast);
  1797.     switch (nChar)
  1798.     {
  1799. case VK_SPACE:
  1800. SelectRows(m_iFocusRow, m_iFocusRow, TRUE, TRUE);
  1801. return;
  1802. case VK_LEFT:
  1803. SendMessage(WM_HSCROLL, LOWORD(SB_LINELEFT), NULL);
  1804. return;
  1805. case VK_RIGHT:
  1806. SendMessage(WM_HSCROLL, LOWORD(SB_LINERIGHT), NULL);
  1807. return;
  1808. case VK_DOWN:
  1809. if(m_iFocusRow<m_iVirtualHeight-1)
  1810. {
  1811. if(IsCtrlDown())
  1812. {
  1813. SelectRows(m_iFocusRow+1, m_iFocusRow+1, FALSE);
  1814. m_iSelectRow = m_iFocusRow;
  1815. }
  1816. else if(!IsShiftDown())
  1817. {
  1818. SelectRows(m_iFocusRow+1, m_iFocusRow+1, TRUE);
  1819. m_iSelectRow = m_iFocusRow;
  1820. }
  1821. else
  1822. SelectRows(m_iFocusRow+1, m_iSelectRow, TRUE);
  1823. EnsureVisible(m_arrayRows[m_iFocusRow]);
  1824. }
  1825. return;
  1826. case VK_UP:
  1827. if(m_iFocusRow>0)
  1828. {
  1829. if(IsCtrlDown())
  1830. {
  1831. SelectRows(m_iFocusRow-1, m_iFocusRow-1, FALSE);
  1832. m_iSelectRow = m_iFocusRow;
  1833. }
  1834. else if(!IsShiftDown())
  1835. {
  1836. SelectRows(m_iFocusRow-1, m_iFocusRow-1, TRUE);
  1837. m_iSelectRow = m_iFocusRow;
  1838. }
  1839. else
  1840. SelectRows(m_iFocusRow-1, m_iSelectRow, TRUE);
  1841. EnsureVisible(m_arrayRows[m_iFocusRow]);
  1842. }
  1843. return;
  1844. case VK_NEXT:
  1845. if(m_iFocusRow == iLast)
  1846. {
  1847. SendMessage(WM_VSCROLL, SB_PAGEDOWN, 0);
  1848. iFirst = GetScrollPos32(SB_VERT);
  1849. GetVisibleRows(TRUE, &iFirst, &iLast);
  1850. }
  1851. if(!IsShiftDown())
  1852. {
  1853. iFirst = iLast;
  1854. m_iSelectRow = iLast;
  1855. }
  1856. else
  1857. iFirst = m_iSelectRow;
  1858. SelectRows(iLast, iFirst, TRUE);
  1859. return;
  1860. case VK_PRIOR:
  1861. if(m_iFocusRow == iFirst)
  1862. {
  1863. SendMessage(WM_VSCROLL, SB_PAGEUP, 0);
  1864. iFirst = GetScrollPos32(SB_VERT);
  1865. }
  1866. if(!IsShiftDown())
  1867. {
  1868. iLast = iFirst;
  1869. m_iSelectRow = iFirst;
  1870. }
  1871. else
  1872. iLast = m_iSelectRow;
  1873. SelectRows(iFirst, iLast, TRUE);
  1874. return;
  1875. case VK_HOME:
  1876. if(m_iFocusRow>0)
  1877. {
  1878. SendMessage(WM_VSCROLL, SB_TOP, 0);
  1879. if(!IsShiftDown())
  1880. m_iSelectRow = 0;
  1881. SelectRows(0, m_iSelectRow, TRUE);
  1882. }
  1883. break;
  1884. case VK_END:
  1885. if(m_iFocusRow<m_iVirtualHeight)
  1886. {
  1887. SendMessage(WM_VSCROLL, SB_BOTTOM, 0);
  1888. if(!IsShiftDown())
  1889. m_iSelectRow = m_iVirtualHeight-1;
  1890. SelectRows(m_iSelectRow, m_iVirtualHeight-1, TRUE);
  1891. }
  1892. break;
  1893. }
  1894. CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  1895. }
  1896. void CReportCtrl::OnHdnItemChanged(NMHDR* pNMHDR, LRESULT* pResult) 
  1897. {
  1898. LPHDITEM lphdi = (LPHDITEM)((LPNMHEADER)pNMHDR)->pitem;
  1899. HDITEM hdi;
  1900. hdi.mask = HDI_WIDTH|HDI_LPARAM;
  1901. m_wndHeader.GetItem(((LPNMHEADER)pNMHDR)->iItem, &hdi);
  1902. if(lphdi->mask&HDI_FORMAT)
  1903. m_arraySubItems[hdi.lParam].nFormat = lphdi->fmt&HDF_JUSTIFYMASK;
  1904. if(lphdi->mask&HDI_WIDTH)
  1905. {
  1906. m_iVirtualWidth += lphdi->cxy - m_arraySubItems[hdi.lParam].iWidth;
  1907. ASSERT(m_iVirtualWidth >= 0);
  1908. m_arraySubItems[hdi.lParam].iWidth = lphdi->cxy;
  1909. }
  1910. ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));
  1911. *pResult = FALSE;
  1912. }
  1913. void CReportCtrl::OnHdnItemClick(NMHDR* pNMHDR, LRESULT* pResult) 
  1914. {
  1915. LPHDITEM lphdi = (LPHDITEM)((LPNMHEADER)pNMHDR)->pitem;
  1916. HDITEM hdi;
  1917. hdi.mask = HDI_ORDER|HDI_LPARAM;
  1918. m_wndHeader.GetItem(((LPNMHEADER)pNMHDR)->iItem, &hdi);
  1919. if(!Notify(RVN_COLUMNCLICK, -1, (INT)hdi.lParam))
  1920. {
  1921. if(!(GetStyle()&RVS_NOSORT))
  1922. {
  1923. BOOL bAscending;
  1924. if(((LPNMHEADER)pNMHDR)->iItem == m_wndHeader.GetSortColumn(&bAscending))
  1925. bAscending = !bAscending;
  1926. else
  1927. bAscending = TRUE;
  1928. VERIFY(SortItems((INT)hdi.lParam, bAscending));
  1929. }
  1930. }
  1931. pResult = FALSE;
  1932. }
  1933. void CReportCtrl::OnHdnEndDrag(NMHDR* pNMHDR, LRESULT* pResult) 
  1934. {
  1935. LPNMHEADER lpnmhdr = (LPNMHEADER)pNMHDR;
  1936. if(m_wndHeader.GetDropResult())
  1937. {
  1938. if(GetStyle()&RVS_ALLOWCOLUMNREMOVAL && m_arrayColumns.GetSize()>1)
  1939. DeactivateColumn(lpnmhdr->pitem->lParam);
  1940. *pResult = TRUE;
  1941. }
  1942. else
  1943. {
  1944. m_bColumnsReordered = TRUE;
  1945. Invalidate();
  1946. *pResult = FALSE;
  1947. }
  1948. }
  1949. /////////////////////////////////////////////////////////////////////////////
  1950. // CReportColumnListCtrl
  1951. CReportColumnListCtrl::CReportColumnListCtrl()
  1952. {
  1953. m_pReportCtrl = NULL;
  1954. m_iColumn = -1;
  1955. m_pDragWnd = NULL;
  1956. }
  1957. CReportColumnListCtrl::~CReportColumnListCtrl()
  1958. {
  1959. }
  1960. BEGIN_MESSAGE_MAP(CReportColumnListCtrl, CDragListBox)
  1961. //{{AFX_MSG_MAP(CReportColumnListCtrl)
  1962. //}}AFX_MSG_MAP
  1963. END_MESSAGE_MAP()
  1964. /////////////////////////////////////////////////////////////////////////////
  1965. // CReportColumnListCtrl attributes
  1966. BOOL CReportColumnListCtrl::SetReportCtrl(CReportCtrl* pReportCtrl)
  1967. {
  1968. m_pReportCtrl = pReportCtrl;
  1969. ResetContent();
  1970. return TRUE;
  1971. }
  1972. CReportCtrl* CReportColumnListCtrl::GetReportCtrl()
  1973. {
  1974. return m_pReportCtrl;
  1975. }
  1976. /////////////////////////////////////////////////////////////////////////////
  1977. // CReportColumnListCtrl operations
  1978. BOOL CReportColumnListCtrl::UpdateList()
  1979. {
  1980. INT iColumn, iColumns = m_pReportCtrl->m_arraySubItems.GetSize();
  1981. ResetContent();
  1982. for(iColumn=0;iColumn<iColumns;iColumn++)
  1983. {
  1984. if(!m_pReportCtrl->IsActiveColumn(iColumn) && Include(iColumn))
  1985. {
  1986. INT iItem = AddString(m_pReportCtrl->m_arraySubItems[iColumn].strText);
  1987. SetItemData(iItem, iColumn);
  1988. }
  1989. }
  1990. return TRUE;
  1991. }
  1992. BOOL CReportColumnListCtrl::Include(INT iColumn)
  1993. {
  1994. return TRUE;
  1995. }
  1996. /////////////////////////////////////////////////////////////////////////////
  1997. // CReportColumnListCtrl message handlers
  1998. void CReportColumnListCtrl::PreSubclassWindow() 
  1999. {
  2000. CDragListBox::PreSubclassWindow();
  2001. SetItemHeight(0, GetItemHeight(0)+2);
  2002. }
  2003. void CReportColumnListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
  2004. {
  2005. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  2006. CRect rcItem(lpDrawItemStruct->rcItem);
  2007. if(GetCount() > 0)
  2008. {
  2009. pDC->DrawFrameControl(rcItem, DFC_BUTTON, DFCS_BUTTONPUSH);
  2010. rcItem.DeflateRect(2, 2);
  2011. if(lpDrawItemStruct->itemState&ODS_SELECTED)
  2012. {
  2013. pDC->FillRect(rcItem, &CBrush(::GetSysColor(COLOR_3DSHADOW)));
  2014. pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
  2015. }
  2016. else
  2017. pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
  2018. pDC->SetBkMode(TRANSPARENT);
  2019. pDC->DrawText(
  2020. m_pReportCtrl->m_arraySubItems[lpDrawItemStruct->itemData].strText,
  2021. -1,
  2022. rcItem,
  2023. DT_SINGLELINE|DT_NOPREFIX|DT_NOCLIP|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);
  2024. }
  2025. else
  2026. pDC->FillSolidRect(rcItem, ::GetSysColor(COLOR_WINDOW));
  2027. }
  2028. BOOL CReportColumnListCtrl::BeginDrag(CPoint pt)
  2029. {
  2030. if(GetCount() <= 0)
  2031. return FALSE;
  2032. BOOL bAutoScroll = FALSE;
  2033. INT iItem = ItemFromPt(pt);
  2034. if(iItem >= 0)
  2035. {
  2036. GetClientRect(m_rcDragWnd);
  2037. m_rcDragWnd.bottom = m_rcDragWnd.top + GetItemHeight(0);
  2038. m_iColumn = GetItemData(iItem);
  2039. _tcscpy(m_szColumnText, m_pReportCtrl->m_arraySubItems[m_iColumn].strText);
  2040. m_hdiColumn.mask = HDI_WIDTH|HDI_TEXT|HDI_FORMAT;
  2041. m_hdiColumn.cxy = m_rcDragWnd.Width();
  2042. m_hdiColumn.pszText = m_szColumnText;
  2043. m_hdiColumn.cchTextMax = sizeof(m_szColumnText);
  2044. m_hdiColumn.fmt = HDF_STRING|HDF_LEFT;
  2045. m_pDragWnd = new CFHDragWnd;
  2046. if(m_pDragWnd)
  2047. m_pDragWnd->Create(m_rcDragWnd, &m_pReportCtrl->m_wndHeader, -2, &m_hdiColumn);
  2048. GetWindowRect(m_rcDropTarget1);
  2049. m_pReportCtrl->m_wndHeader.GetWindowRect(m_rcDropTarget2);
  2050. }
  2051. m_iDropIndex = -1;
  2052. return TRUE;
  2053. }
  2054. UINT CReportColumnListCtrl::Dragging(CPoint pt)
  2055. {
  2056. CPoint point = pt;
  2057. point.Offset(-(m_rcDragWnd.Width()>>1), -(m_rcDragWnd.Height()>>1));
  2058. if(m_pDragWnd != NULL)
  2059. m_pDragWnd->SetWindowPos(
  2060. &wndTop, 
  2061. point.x, point.y,
  2062.   0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE
  2063. );
  2064. if(m_rcDropTarget1.PtInRect(pt))
  2065. return DL_MOVECURSOR;
  2066. m_iDropIndex = m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, TRUE, MAKELONG(pt.x, pt.y));
  2067. if(m_rcDropTarget2.PtInRect(pt))
  2068. return DL_MOVECURSOR;
  2069. return DL_STOPCURSOR;
  2070. }
  2071. void CReportColumnListCtrl::CancelDrag(CPoint pt)
  2072. {
  2073. m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, FALSE, -1);
  2074. if(m_pDragWnd != NULL)
  2075. {
  2076. m_pDragWnd->DestroyWindow();
  2077. m_pDragWnd = NULL;
  2078. }
  2079. }
  2080. void CReportColumnListCtrl::Dropped(INT iSrcIndex, CPoint pt)
  2081. {
  2082. m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, FALSE, -1);
  2083. if(m_pDragWnd != NULL)
  2084. {
  2085. m_pDragWnd->DestroyWindow();
  2086. m_pDragWnd = NULL;
  2087. }
  2088. if(m_iDropIndex >= 0)
  2089. m_pReportCtrl->ActivateColumn(m_iColumn, m_iDropIndex);
  2090. }