Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2177 lines
64 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2001.
  5. //
  6. // File: Schedmat.cpp
  7. //
  8. // Contents:
  9. //
  10. //----------------------------------------------------------------------------
  11. // schedmat.cpp : implementation file
  12. //
  13. #include "stdafx.h"
  14. #include "resource.h"
  15. #include "schedmat.h"
  16. #include "AccessibleWrapper.h"
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. typedef HRESULT (WINAPI * PFNCREATESTDACCESSIBLEOBJECT)(HWND, LONG, REFIID, void **);
  23. typedef HRESULT (WINAPI * PFNCREATESTDACCESSIBLEPROXY)(HWND, LPCTSTR, LONG, REFIID, void **);
  24. typedef LRESULT (WINAPI * PFNLRESULTFROMOBJECT)(REFIID, WPARAM, LPUNKNOWN);
  25. PFNCREATESTDACCESSIBLEOBJECT s_pfnCreateStdAccessibleObject = 0;
  26. PFNCREATESTDACCESSIBLEPROXY s_pfnCreateStdAccessibleProxy = NULL;
  27. PFNLRESULTFROMOBJECT s_pfnLresultFromObject = NULL;
  28. BOOL g_fAttemptedOleAccLoad ;
  29. HMODULE g_hOleAcc;
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CMatrixCell
  32. IMPLEMENT_DYNAMIC(CMatrixCell, CObject)
  33. //****************************************************************************
  34. //
  35. // CMatrixCell::CMatrixCell
  36. //
  37. //****************************************************************************
  38. CMatrixCell::CMatrixCell()
  39. {
  40. m_crBackColor = DEFBACKCOLOR;
  41. m_crForeColor = DEFFORECOLOR;
  42. m_nPercentage = 0;
  43. m_crBlendColor = DEFBLENDCOLOR;
  44. m_dwUserValue = 0;
  45. m_pUserDataPtr = NULL;
  46. m_dwFlags = 0;
  47. }
  48. //****************************************************************************
  49. //
  50. // CMatrixCell::~CMatrixCell
  51. //
  52. //****************************************************************************
  53. CMatrixCell::~CMatrixCell()
  54. {
  55. }
  56. /////////////////////////////////////////////////////////////////////////////
  57. // CScheduleMatrix
  58. IMPLEMENT_DYNAMIC(CScheduleMatrix, CWnd)
  59. //****************************************************************************
  60. //
  61. // CScheduleMatrix::CScheduleMatrix
  62. //
  63. //****************************************************************************
  64. CScheduleMatrix::CScheduleMatrix()
  65. {
  66. SetType(MT_WEEKLY);
  67. m_hFont = NULL;
  68. m_nSelHour = m_nSelDay = m_nNumSelHours = m_nNumSelDays = 0;
  69. m_nSaveHour = m_nSaveDay = m_nNumSaveHours = m_nNumSaveDays = 0;
  70. m_bShifted = FALSE;
  71. }
  72. //****************************************************************************
  73. //
  74. // CScheduleMatrix::CScheduleMatrix
  75. //
  76. //****************************************************************************
  77. CScheduleMatrix::CScheduleMatrix(UINT nType)
  78. {
  79. SetType(nType);
  80. m_hFont = NULL;
  81. m_nSelHour = m_nSelDay = m_nNumSelHours = m_nNumSelDays = 0;
  82. m_nSaveHour = m_nSaveDay = m_nNumSaveHours = m_nNumSaveDays = 0;
  83. m_bShifted = FALSE;
  84. }
  85. //****************************************************************************
  86. //
  87. // CScheduleMatrix::~CScheduleMatrix
  88. //
  89. //****************************************************************************
  90. CScheduleMatrix::~CScheduleMatrix()
  91. {
  92. }
  93. BEGIN_MESSAGE_MAP(CScheduleMatrix, CWnd)
  94. //{{AFX_MSG_MAP(CScheduleMatrix)
  95. ON_WM_CREATE()
  96. ON_WM_SIZE()
  97. ON_WM_PAINT()
  98. ON_WM_SETFOCUS()
  99. ON_WM_KILLFOCUS()
  100. ON_WM_LBUTTONDOWN()
  101. ON_WM_LBUTTONUP()
  102. ON_WM_LBUTTONDBLCLK()
  103. ON_WM_MOUSEMOVE()
  104. ON_WM_GETDLGCODE()
  105. ON_WM_KEYDOWN()
  106. ON_WM_KEYUP()
  107. //}}AFX_MSG_MAP
  108. ON_MESSAGE(WM_SETFONT, OnSetFont)
  109. ON_MESSAGE(WM_GETFONT, OnGetFont)
  110. ON_MESSAGE(WM_GETOBJECT, OnGetObject)
  111. ON_MESSAGE(SCHEDMSG_GETSELDESCRIPTION, OnGetSelDescription)
  112. ON_MESSAGE(SCHEDMSG_GETPERCENTAGE, OnGetPercentage)
  113. END_MESSAGE_MAP()
  114. //****************************************************************************
  115. //
  116. // CScheduleMatrix::Create
  117. //
  118. //****************************************************************************
  119. BOOL CScheduleMatrix::Create(LPCTSTR lpszWindowName, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* /*pContext*/)
  120. {
  121. CRect r(0,0,0,0);
  122. if (!m_HourLegend.Create(NULL, _T(""), WS_CHILD | WS_VISIBLE, r, pParentWnd, (UINT) -1, NULL))
  123. return FALSE;
  124. if (!m_PercentLabel.Create(NULL, _T(""), WS_CHILD | WS_VISIBLE, r, pParentWnd, (UINT) -1, NULL))
  125. return FALSE;
  126. m_PercentLabel.m_pMatrix = this;
  127. return CWnd::Create(NULL, lpszWindowName, WS_CHILD | WS_VISIBLE | WS_TABSTOP,
  128. rect, pParentWnd, nID, NULL);
  129. }
  130. /////////////////////////////////////////////////////////////////////////////
  131. // CScheduleMatrix message handlers
  132. //****************************************************************************
  133. //
  134. // CScheduleMatrix::OnSize
  135. //
  136. //****************************************************************************
  137. void CScheduleMatrix::OnSize(UINT nType, int cx, int cy)
  138. {
  139. CWnd::OnSize(nType, cx, cy);
  140. SetMatrixMetrics(cx, cy);
  141. Invalidate();
  142. }
  143. //****************************************************************************
  144. //
  145. // CScheduleMatrix::SetMatrixMetrics
  146. //
  147. //****************************************************************************
  148. void CScheduleMatrix::SetMatrixMetrics(int cx, int cy)
  149. {
  150. if (m_hWnd == NULL)
  151. return;
  152. CDC *pdc = GetDC();
  153. CFont *pOldFont = NULL;
  154. CFont *pFont = CFont::FromHandle(m_hFont);
  155. if (pFont != NULL)
  156. pOldFont = pdc->SelectObject(pFont);
  157. // Calculate some useful metrics
  158. int i;
  159. int nRows = (m_nType==MT_DAILY ? 1 : 8); // 8 rows = 7 days + header
  160. CSize size = pdc->GetTextExtent(_T("0"));
  161. int nCharHeight = size.cy;
  162. int nCharWidth = size.cx;
  163. int nDayWidth = 0;
  164. for (i=0; i<8; i++)
  165. {
  166. size = pdc->GetTextExtent(m_DayStrings[i]);
  167. nDayWidth = max(nDayWidth, size.cx + 2*nCharWidth);
  168. // If daily schedule, stop after first
  169. if (m_nType == MT_DAILY)
  170. break;
  171. }
  172. if (pOldFont != NULL)
  173. pdc->SelectObject(pOldFont);
  174. ReleaseDC(pdc);
  175. nDayWidth = max(nDayWidth, 2*nCharWidth);
  176. int nLegendHeight = nCharHeight + 4 + 16; // a little margin over char height plus icon height
  177. int nLabelHeight = (m_nType == MT_DAILY ? nCharHeight + 4 : 0);
  178. // Cell array should fill space after hour legend and %labels...
  179. int nBtnHeight = max(0, cy-nLegendHeight-nLabelHeight)/nRows;
  180. // ... but should at least accomodate label text and some margin
  181. nBtnHeight = max(nBtnHeight, nCharHeight + 4);
  182. m_nCellWidth = max(0, (cx - nDayWidth)/24);
  183. m_nCellHeight = nBtnHeight;
  184. // Leave an extra pixel for the lower right cell border
  185. int nArrayWidth = 24*m_nCellWidth + 1;
  186. int nArrayHeight = (m_nType==MT_DAILY ? 1 : 7)*m_nCellHeight + 1;
  187. // Adjust header width to absorb roundoff from cells
  188. nDayWidth = max(0, cx - nArrayWidth);
  189. // Adjust legend height to absorb roundoff from cells
  190. nLegendHeight = max(0,
  191. cy - (nArrayHeight + (m_nType==MT_DAILY ? 0 : nBtnHeight)) - nLabelHeight);
  192. m_rHourLegend.SetRect(0, 0, cx, nLegendHeight);
  193. if (m_nType == MT_DAILY)
  194. {
  195. m_rAllHeader.SetRect(0, nLegendHeight, nDayWidth, nLegendHeight+nBtnHeight);
  196. m_rHourHeader.SetRect(0,0,0,0);
  197. m_rDayHeader.SetRect(0,0,0,0);
  198. m_rCellArray.SetRect(nDayWidth, nLegendHeight, cx, cy-nLabelHeight);
  199. m_rPercentLabel.SetRect(0,cy-nLabelHeight,cx,cy);
  200. }
  201. else
  202. {
  203. m_rAllHeader.SetRect(0, nLegendHeight, nDayWidth, nLegendHeight+nBtnHeight);
  204. m_rHourHeader.SetRect(nDayWidth, nLegendHeight, cx, nLegendHeight+nBtnHeight);
  205. m_rDayHeader.SetRect(0, nLegendHeight+nBtnHeight, nDayWidth, cy);
  206. m_rCellArray.SetRect(nDayWidth, nLegendHeight + nBtnHeight, cx, cy);
  207. m_rPercentLabel.SetRect(0,0,0,0);
  208. }
  209. // Move the hour legend window into place
  210. if (m_HourLegend.GetSafeHwnd() != NULL)
  211. {
  212. CRect rHourLegend = m_rHourLegend;
  213. ClientToScreen(rHourLegend);
  214. GetParent()->ScreenToClient(rHourLegend);
  215. rHourLegend.right += nCharWidth;
  216. m_HourLegend.MoveWindow(rHourLegend);
  217. m_HourLegend.m_nCharHeight = nCharHeight;
  218. m_HourLegend.m_nCharWidth = nCharWidth;
  219. m_HourLegend.m_nCellWidth = m_nCellWidth;
  220. m_HourLegend.m_hFont = m_hFont;
  221. m_HourLegend.m_rLegend.SetRect(m_rCellArray.left, 0, m_rCellArray.right,
  222. nLegendHeight);
  223. }
  224. // Move the % label window into place
  225. if (m_PercentLabel.GetSafeHwnd() != NULL)
  226. {
  227. CRect rPercentLabel = m_rPercentLabel;
  228. ClientToScreen(rPercentLabel);
  229. GetParent()->ScreenToClient(rPercentLabel);
  230. m_PercentLabel.MoveWindow(rPercentLabel);
  231. m_PercentLabel.m_nCellWidth = m_nCellWidth;
  232. m_PercentLabel.m_hFont = m_hFont;
  233. m_PercentLabel.m_rHeader.SetRect(m_rAllHeader.left, 0, m_rAllHeader.right,
  234. nLabelHeight);
  235. m_PercentLabel.m_rLabels.SetRect(m_rCellArray.left, 0, m_rCellArray.right,
  236. nLabelHeight);
  237. }
  238. }
  239. //****************************************************************************
  240. //
  241. // CScheduleMatrix::OnPaint
  242. //
  243. //****************************************************************************
  244. void CScheduleMatrix::OnPaint()
  245. {
  246. int i, j, x, y;
  247. CRect r, r2;
  248. BOOL bPressed;
  249. CPaintDC dc(this); // device context for painting
  250. CFont *pOldFont = NULL;
  251. CFont *pFont = CFont::FromHandle(m_hFont);
  252. if (pFont != NULL)
  253. pOldFont = dc.SelectObject(pFont);
  254. CBrush brFace(::GetSysColor(COLOR_3DFACE));
  255. CPen penFace(PS_SOLID, 0, ::GetSysColor(COLOR_3DFACE));
  256. CBrush *pbrOld = dc.SelectObject(&brFace);
  257. CPen *ppenOld = dc.SelectObject(&penFace);
  258. COLORREF crBkOld = dc.GetBkColor();
  259. COLORREF crTextOld = dc.GetTextColor();
  260. // Draw the All header
  261. if (GetCapture() == this && m_rAllHeader.PtInRect(m_ptDown))
  262. bPressed = TRUE;
  263. else
  264. bPressed = FALSE;
  265. DrawHeader(&dc, m_rAllHeader, m_DayStrings[0], bPressed);
  266. // Draw the hour header
  267. if (!m_rHourHeader.IsRectEmpty())
  268. {
  269. // First hour is special case
  270. r.SetRect(m_rHourHeader.left, m_rHourHeader.top,
  271. m_rHourHeader.left+m_nCellWidth+1, m_rHourHeader.bottom);
  272. if (GetCapture() == this && m_rHourHeader.PtInRect(m_ptDown) && CellInSel(0,0))
  273. bPressed = TRUE;
  274. else
  275. bPressed = FALSE;
  276. DrawHeader(&dc, r, NULL, bPressed);
  277. r = m_rHourHeader;
  278. r.left += 1;
  279. r.right = r.left + m_nCellWidth;
  280. for (i=1; i<24; i++)
  281. {
  282. r.OffsetRect(m_nCellWidth, 0);
  283. if (GetCapture() == this && m_rHourHeader.PtInRect(m_ptDown) && CellInSel(i,0))
  284. bPressed = TRUE;
  285. else
  286. bPressed = FALSE;
  287. DrawHeader(&dc, r, NULL, bPressed);
  288. }
  289. }
  290. // Draw the day header
  291. if (!m_rDayHeader.IsRectEmpty())
  292. {
  293. // First day is special case
  294. r.SetRect(m_rDayHeader.left, m_rDayHeader.top,
  295. m_rDayHeader.right, m_rDayHeader.top+m_nCellHeight+1);
  296. if (GetCapture() == this && m_rDayHeader.PtInRect(m_ptDown) && CellInSel(0,0))
  297. bPressed = TRUE;
  298. else
  299. bPressed = FALSE;
  300. DrawHeader(&dc, r, m_DayStrings[1], bPressed);
  301. r = m_rDayHeader;
  302. r.top += 1;
  303. r.bottom = r.top + m_nCellHeight;
  304. for (i=2; i<8; i++)
  305. {
  306. r.OffsetRect(0, m_nCellHeight);
  307. if (GetCapture() == this && m_rDayHeader.PtInRect(m_ptDown) && CellInSel(0,i-1))
  308. bPressed = TRUE;
  309. else
  310. bPressed = FALSE;
  311. DrawHeader(&dc, r, m_DayStrings[i], bPressed);
  312. }
  313. }
  314. // Draw the cell array
  315. int nDays = (m_nType==MT_DAILY ? 1 : 7);
  316. y = m_rCellArray.top;
  317. for (j=0; j<nDays; j++)
  318. {
  319. x = m_rCellArray.left;
  320. for (i=0; i<24; i++)
  321. {
  322. DrawCell(&dc, &m_CellArray[i][j], x, y, m_nCellWidth, m_nCellHeight);
  323. x += m_nCellWidth;
  324. }
  325. y += m_nCellHeight;
  326. }
  327. dc.SetBkColor(crBkOld);
  328. dc.SetTextColor(crTextOld);
  329. // Draw the lower right cell borders since no cell takes responsibility for it
  330. dc.MoveTo(m_rCellArray.left, m_rCellArray.bottom-1);
  331. dc.LineTo(m_rCellArray.right-1, m_rCellArray.bottom-1);
  332. dc.LineTo(m_rCellArray.right-1, m_rCellArray.top-1);
  333. // Draw selection indicator (hardwired black and white for max contrast).
  334. if (m_nNumSelHours != 0 && m_nNumSelDays != 0)
  335. {
  336. CRect rSel(m_nSelHour, m_nSelDay, m_nSelHour+m_nNumSelHours, m_nSelDay+m_nNumSelDays);
  337. CellToClient(rSel.left, rSel.top);
  338. CellToClient(rSel.right, rSel.bottom);
  339. rSel.right+=1;
  340. rSel.bottom+=1;
  341. CBrush brBlack(RGB(0,0,0)), brWhite(RGB(255,255,255));
  342. dc.FrameRect(rSel, &brBlack);
  343. if (GetFocus()==this)
  344. dc.DrawFocusRect(rSel);
  345. rSel.InflateRect(-1,-1);
  346. dc.FrameRect(rSel, &brBlack);
  347. rSel.InflateRect(-1,-1);
  348. dc.FrameRect(rSel, &brWhite);
  349. }
  350. if (pbrOld != NULL)
  351. dc.SelectObject(pbrOld);
  352. if (ppenOld != NULL)
  353. dc.SelectObject(ppenOld);
  354. if (pOldFont != NULL)
  355. dc.SelectObject(pOldFont);
  356. // Do not call CWnd::OnPaint() for painting messages
  357. }
  358. //****************************************************************************
  359. //
  360. // CScheduleMatrix::CellToClient
  361. //
  362. //****************************************************************************
  363. void CScheduleMatrix::CellToClient(LONG &nX, LONG &nY)
  364. {
  365. nX = nX*m_nCellWidth + m_rCellArray.left;
  366. nY = nY*m_nCellHeight + m_rCellArray.top;
  367. }
  368. //****************************************************************************
  369. //
  370. // CScheduleMatrix::ClientToCell
  371. //
  372. //****************************************************************************
  373. void CScheduleMatrix::ClientToCell(LONG &nX, LONG &nY)
  374. {
  375. nX = max(nX, m_rCellArray.left);
  376. nX = min(nX, m_rCellArray.right);
  377. nY = max(nY, m_rCellArray.top);
  378. nY = min(nY, m_rCellArray.bottom);
  379. nX = (nX-m_rCellArray.left)/m_nCellWidth;
  380. nY = (nY-m_rCellArray.top)/m_nCellHeight;
  381. nX = min(nX, 23);
  382. nY = min(nY, (m_nType == MT_DAILY ? 0 : 6));
  383. }
  384. //****************************************************************************
  385. //
  386. // CScheduleMatrix::GetCellSize
  387. //
  388. //****************************************************************************
  389. CSize CScheduleMatrix::GetCellSize()
  390. {
  391. SIZE size;
  392. size.cx = m_nCellWidth;
  393. size.cy = m_nCellHeight;
  394. return size;
  395. }
  396. //****************************************************************************
  397. //
  398. // CScheduleMatrix::DrawCell
  399. //
  400. //****************************************************************************
  401. void CScheduleMatrix::DrawCell(CDC *pdc, LPCRECT pRect, UINT nPercent, BOOL bBlendState,
  402. COLORREF crBackColor, COLORREF crForeColor, COLORREF crBlendColor)
  403. {
  404. CRect r(pRect);
  405. CMatrixCell Cell;
  406. ASSERT(nPercent <= 100);
  407. Cell.m_nPercentage = nPercent;
  408. //??
  409. Cell.m_dwFlags = MC_MERGELEFT | MC_MERGETOP;
  410. if (bBlendState)
  411. Cell.m_dwFlags |= MC_BLEND;
  412. Cell.m_crBackColor = crBackColor;
  413. Cell.m_crForeColor = crForeColor;
  414. Cell.m_crBlendColor = crBlendColor;
  415. CBrush brFace(::GetSysColor(COLOR_3DFACE));
  416. CPen penFace(PS_SOLID, 0, ::GetSysColor(COLOR_3DFACE));
  417. CBrush *pbrOld = pdc->SelectObject(&brFace);
  418. CPen *ppenOld = pdc->SelectObject(&penFace);
  419. COLORREF crBkOld = pdc->GetBkColor();
  420. COLORREF crTextOld = pdc->GetTextColor();
  421. DrawCell(pdc, &Cell, r.left, r.top, r.Width(), r.Height());
  422. pdc->SetBkColor(crBkOld);
  423. pdc->SetTextColor(crTextOld);
  424. // Draw the lower right cell border since cell doesn't take responsibility for it
  425. /* //??
  426. pdc->MoveTo(r.left, r.bottom-1);
  427. pdc->LineTo(r.right-1, r.bottom-1);
  428. pdc->LineTo(r.right-1, r.top-1);
  429. */
  430. if (pbrOld != NULL)
  431. pdc->SelectObject(pbrOld);
  432. if (ppenOld != NULL)
  433. pdc->SelectObject(ppenOld);
  434. }
  435. //****************************************************************************
  436. //
  437. // CScheduleMatrix::DrawCell
  438. //
  439. //****************************************************************************
  440. void CScheduleMatrix::DrawCell(CDC *pdc, CMatrixCell *pCell, int x, int y, int w, int h)
  441. {
  442. int x1, y1, nPercent;
  443. CRect rBack, rFore, rBlend, rClip, rCell, rWork;
  444. // Don't bother if not invalid
  445. pdc->GetClipBox(rClip);
  446. rCell.SetRect(x,y,x+w,y+h);
  447. if (!rWork.IntersectRect(rClip, rCell))
  448. return;
  449. // Calculate portions to devote to fore/back colors
  450. // Account for merge effect
  451. nPercent = MulDiv(pCell->m_nPercentage, h-(pCell->m_dwFlags & MC_MERGETOP?0:1), 100);
  452. if (pCell->m_dwFlags & MC_MERGELEFT)
  453. {
  454. x1 = x;
  455. }
  456. else
  457. {
  458. x1 = x + 1;
  459. pdc->MoveTo(x, y);
  460. pdc->LineTo(x, y+h);
  461. }
  462. if (pCell->m_dwFlags & MC_MERGETOP)
  463. {
  464. y1 = y;
  465. }
  466. else
  467. {
  468. y1 = y + 1;
  469. pdc->MoveTo(x, y);
  470. pdc->LineTo(x+w, y);
  471. }
  472. rBack.SetRect(x1, y1, x+w, y+h-nPercent);
  473. rFore.SetRect(x1, rBack.bottom, x+w, y+h);
  474. rBlend.SetRect(x1, y1, x+w, y+h);
  475. // Ensure a touch of color at the boundaries
  476. if (rBack.Height() == 0 && pCell->m_nPercentage != 100)
  477. {
  478. rBack.bottom+=1;
  479. rFore.top+=1;
  480. }
  481. if (rFore.Height() == 0 && pCell->m_nPercentage != 0)
  482. {
  483. rBack.bottom-=1;
  484. rFore.top-=1;
  485. }
  486. // Draw the histogram
  487. CBrush brBack(pCell->m_crBackColor);
  488. CBrush brFore(pCell->m_crForeColor);
  489. pdc->FillRect(rBack, &brBack);
  490. pdc->FillRect(rFore, &brFore);
  491. // Overlay the blend color
  492. if (pCell->m_dwFlags & MC_BLEND)
  493. {
  494. // Create the GDI work objects if necessary
  495. if (m_bmBlend.GetSafeHandle() == NULL)
  496. {
  497. SHORT BlendBits[] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
  498. SHORT MaskBits[] = {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
  499. m_bmBlend.CreateBitmap(8,8,1,1,&BlendBits);
  500. m_bmMask.CreateBitmap(8,8,1,1,&MaskBits);
  501. m_brBlend.CreatePatternBrush(&m_bmBlend);
  502. m_brMask.CreatePatternBrush(&m_bmMask);
  503. }
  504. pdc->SetTextColor(RGB(0,0,0));
  505. // Mask out the existing bits in the cell
  506. pdc->SetBkColor(RGB(255,255,255));
  507. pdc->SelectObject(&m_brMask);
  508. pdc->PatBlt(rBlend.left, rBlend.top, rBlend.Width(), rBlend.Height(), 0x00A000C9); //DPa
  509. // Add the blend color into the masked pixels
  510. pdc->SetBkColor(pCell->m_crBlendColor);
  511. pdc->SelectObject(&m_brBlend);
  512. pdc->PatBlt(rBlend.left, rBlend.top, rBlend.Width(), rBlend.Height(), 0x00FA0089); //DPo
  513. }
  514. }
  515. //****************************************************************************
  516. //
  517. // CScheduleMatrix::DrawHeader
  518. //
  519. //****************************************************************************
  520. void CScheduleMatrix::DrawHeader(CDC *pdc, LPCRECT lpRect, LPCTSTR pszText, BOOL bSelected)
  521. {
  522. CBrush brFace(::GetSysColor(COLOR_3DFACE));
  523. COLORREF crTL, crBR;
  524. COLORREF crBkOld = pdc->GetBkColor();
  525. COLORREF crTextOld = pdc->GetTextColor();
  526. if (bSelected)
  527. {
  528. crTL = ::GetSysColor(COLOR_3DSHADOW);
  529. crBR = ::GetSysColor(COLOR_3DHIGHLIGHT);
  530. }
  531. else
  532. {
  533. crTL = ::GetSysColor(COLOR_3DHIGHLIGHT);
  534. crBR = ::GetSysColor(COLOR_3DSHADOW);
  535. }
  536. pdc->FillRect(lpRect, &brFace);
  537. pdc->Draw3dRect(lpRect, crTL, crBR);
  538. pdc->SetBkColor(::GetSysColor(COLOR_3DFACE));
  539. pdc->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
  540. if (pszText != NULL)
  541. ::DrawTextEx(pdc->GetSafeHdc(), (LPTSTR)pszText, -1, (LPRECT)lpRect,
  542. DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS, NULL);
  543. pdc->SetBkColor(crBkOld);
  544. pdc->SetTextColor(crTextOld);
  545. }
  546. //****************************************************************************
  547. //
  548. // CScheduleMatrix::OnSetFont
  549. //
  550. //****************************************************************************
  551. LRESULT CScheduleMatrix::OnSetFont( WPARAM wParam, LPARAM lParam )
  552. {
  553. m_hFont = (HFONT)wParam;
  554. m_HourLegend.m_hFont = m_hFont;
  555. CRect rClient;
  556. GetClientRect(rClient);
  557. SetMatrixMetrics(rClient.Width(), rClient.Height());
  558. Invalidate();
  559. if (HIWORD(lParam) != 0)
  560. UpdateWindow();
  561. return 0L;
  562. }
  563. //****************************************************************************
  564. //
  565. // CScheduleMatrix::OnGetFont
  566. //
  567. //****************************************************************************
  568. LRESULT CScheduleMatrix::OnGetFont( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  569. {
  570. return (LRESULT)m_hFont;
  571. }
  572. //****************************************************************************
  573. //
  574. // CScheduleMatrix::SetSelValues
  575. //
  576. //****************************************************************************
  577. BOOL CScheduleMatrix::SetSelValues(UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  578. {
  579. // Deselect allows "illegal" values
  580. if (!(nHour == 0 && nDay == 0 && nNumHours == 0 && nNumDays == 0))
  581. {
  582. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  583. ASSERT(nHour < 24);
  584. ASSERT(nDay < nDays);
  585. ASSERT(nNumHours>=1);
  586. ASSERT(nNumDays>=1);
  587. ASSERT(nHour + nNumHours <= 24);
  588. ASSERT(nDay + nNumDays <= nDays);
  589. }
  590. if (m_nSelHour != nHour || m_nSelDay != nDay ||
  591. m_nNumSelHours != nNumHours || m_nNumSelDays != nNumDays)
  592. {
  593. InvalidateCells(m_nSelHour, m_nSelDay, m_nNumSelHours, m_nNumSelDays, FALSE);
  594. m_nSelHour = nHour;
  595. m_nSelDay = nDay;
  596. m_nNumSelHours = nNumHours;
  597. m_nNumSelDays = nNumDays;
  598. InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  599. return TRUE;
  600. }
  601. return FALSE;
  602. }
  603. //****************************************************************************
  604. //
  605. // CScheduleMatrix::SetSel
  606. //
  607. //****************************************************************************
  608. BOOL CScheduleMatrix::SetSel(UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  609. {
  610. if (SetSelValues(nHour, nDay, nNumHours, nNumDays))
  611. {
  612. UpdateWindow();
  613. m_ptDown.x = nHour;
  614. m_ptDown.y = nDay;
  615. CellToClient(m_ptDown.x, m_ptDown.y);
  616. m_ptFocus.x = nHour + nNumHours - 1;
  617. m_ptFocus.y = nDay + nNumDays - 1;
  618. CellToClient(m_ptFocus.x, m_ptFocus.y);
  619. return TRUE;
  620. }
  621. return FALSE;
  622. }
  623. //****************************************************************************
  624. //
  625. // CScheduleMatrix::SelectAll
  626. //
  627. //****************************************************************************
  628. BOOL CScheduleMatrix::SelectAll()
  629. {
  630. if (m_nType == MT_DAILY)
  631. return SetSel(0,0,23,1);
  632. return SetSel(0,0,23,7);
  633. }
  634. //****************************************************************************
  635. //
  636. // CScheduleMatrix::DeselectAll
  637. //
  638. //****************************************************************************
  639. BOOL CScheduleMatrix::DeselectAll()
  640. {
  641. return SetSel(0,0,0,0);
  642. }
  643. //****************************************************************************
  644. //
  645. // CScheduleMatrix::GetSel
  646. //
  647. //****************************************************************************
  648. void CScheduleMatrix::GetSel(UINT & nHour, UINT & nDay, UINT & nNumHours, UINT & nNumDays)
  649. {
  650. nHour = m_nSelHour;
  651. nDay = m_nSelDay;
  652. nNumHours = m_nNumSelHours;
  653. nNumDays = m_nNumSelDays;
  654. }
  655. //****************************************************************************
  656. //
  657. // CScheduleMatrix::GetSelDescription
  658. //
  659. //****************************************************************************
  660. void CScheduleMatrix::GetSelDescription(CString &sText)
  661. {
  662. GetDescription(sText, m_nSelHour, m_nSelDay, m_nNumSelHours, m_nNumSelDays);
  663. }
  664. //****************************************************************************
  665. //
  666. // CScheduleMatrix::FormatTime
  667. //
  668. //****************************************************************************
  669. CString CScheduleMatrix::FormatTime(UINT nHour) const
  670. {
  671. CString sTime;
  672. SYSTEMTIME sysTime;
  673. ::ZeroMemory (&sysTime, sizeof (SYSTEMTIME));
  674. // Make sure that nHour is 0 to 24
  675. nHour = nHour % 24;
  676. sysTime.wHour = (WORD)nHour;
  677. // Get first time
  678. // Get length to allocate buffer of sufficient size
  679. int iLen = ::GetTimeFormat (
  680. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  681. TIME_NOSECONDS, //TIME_NOMINUTESORSECONDS, // flags specifying function options
  682. &sysTime, // date to be formatted
  683. 0, // date format string
  684. 0, // buffer for storing formatted string
  685. 0); // size of buffer
  686. ASSERT (iLen > 0);
  687. if ( iLen > 0 )
  688. {
  689. int iResult = ::GetTimeFormat (
  690. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  691. TIME_NOSECONDS, //TIME_NOMINUTESORSECONDS, // flags specifying function options
  692. &sysTime, // date to be formatted
  693. 0, // date format string
  694. sTime.GetBufferSetLength (iLen), // buffer for storing formatted string
  695. iLen); // size of buffer
  696. ASSERT (iResult);
  697. sTime.ReleaseBuffer ();
  698. }
  699. return sTime;
  700. }
  701. //****************************************************************************
  702. //
  703. // CScheduleMatrix::GetDescription
  704. //
  705. //****************************************************************************
  706. void CScheduleMatrix::GetDescription(CString &sText, UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  707. {
  708. CString sDay1;
  709. CString sDay2;
  710. CString sHour1;
  711. CString sHour2;
  712. if (nNumDays == 0 || nNumHours == 0)
  713. {
  714. sText.Empty();
  715. return;
  716. }
  717. // Get day strings
  718. sDay1 = m_DayStrings[nDay + 1];
  719. sDay2 = m_DayStrings[nDay + nNumDays];
  720. // Get time strings
  721. if ( sHour1.IsEmpty () )
  722. sHour1 = L"Error";
  723. // Get first time
  724. sHour1 = FormatTime (nHour);
  725. // Get second time
  726. sHour2 = FormatTime (nHour + nNumHours);
  727. if (m_nType == MT_DAILY)
  728. {
  729. sText.FormatMessage(IDS_TOOL_SCHEDULE_FMT_DAILY, (LPCTSTR)sHour1, (LPCTSTR)sHour2);
  730. }
  731. else
  732. {
  733. if (nNumDays == 1)
  734. sText.FormatMessage(IDS_TOOL_SCHEDULE_FMT_WEEKLY_SHORT, (LPCTSTR)sDay1,
  735. (LPCTSTR)sHour1, (LPCTSTR)sHour2);
  736. else
  737. sText.FormatMessage(IDS_TOOL_SCHEDULE_FMT_WEEKLY_LONG,
  738. (LPCTSTR)sDay1, (LPCTSTR)sDay2, (LPCTSTR)sHour1, (LPCTSTR)sHour2);
  739. }
  740. }
  741. //****************************************************************************
  742. //
  743. // CScheduleMatrix::CellInSel
  744. //
  745. //****************************************************************************
  746. BOOL CScheduleMatrix::CellInSel(UINT nHour, UINT nDay)
  747. {
  748. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  749. ASSERT(nHour < 24);
  750. ASSERT(nDay < nDays);
  751. if (m_nNumSelHours == 0 || m_nNumSelDays == 0)
  752. return FALSE;
  753. if (nHour < m_nSelHour || nHour >= m_nSelHour + m_nNumSelHours)
  754. return FALSE;
  755. if (nDay < m_nSelDay || nDay >= m_nSelDay + m_nNumSelDays)
  756. return FALSE;
  757. return TRUE;
  758. }
  759. //****************************************************************************
  760. //
  761. // CScheduleMatrix::SetType
  762. //
  763. //****************************************************************************
  764. void CScheduleMatrix::SetType(UINT nType)
  765. {
  766. ASSERT(nType == MT_DAILY || nType == MT_WEEKLY);
  767. VERIFY (m_DayStrings[0].LoadString (IDS_ALL_HEADER_TEXT)); // "All" header
  768. // Day names start at index 1
  769. m_DayStrings[1] = GetLocaleDay (LOCALE_SDAYNAME7); // Sunday
  770. m_DayStrings[2] = GetLocaleDay (LOCALE_SDAYNAME1); // Monday, etc.
  771. m_DayStrings[3] = GetLocaleDay (LOCALE_SDAYNAME2);
  772. m_DayStrings[4] = GetLocaleDay (LOCALE_SDAYNAME3);
  773. m_DayStrings[5] = GetLocaleDay (LOCALE_SDAYNAME4);
  774. m_DayStrings[6] = GetLocaleDay (LOCALE_SDAYNAME5);
  775. m_DayStrings[7] = GetLocaleDay (LOCALE_SDAYNAME6);
  776. m_nType = nType;
  777. }
  778. //****************************************************************************
  779. //
  780. // CScheduleMatrix::GetLocaleDay
  781. //
  782. // Use the locale API to get the "official" days of the week.
  783. //
  784. //****************************************************************************
  785. CString CScheduleMatrix::GetLocaleDay (LCTYPE lcType) const
  786. {
  787. CString dayName;
  788. int cchData = 64;
  789. int iResult = 0;
  790. do {
  791. iResult = GetLocaleInfo(
  792. LOCALE_USER_DEFAULT, // locale identifier
  793. lcType, // information type
  794. const_cast <PWSTR>((PCWSTR) dayName.GetBufferSetLength (cchData)), // information buffer
  795. cchData); // size of buffer
  796. dayName.ReleaseBuffer ();
  797. if ( !iResult )
  798. {
  799. DWORD dwErr = GetLastError ();
  800. switch (dwErr)
  801. {
  802. case ERROR_INSUFFICIENT_BUFFER:
  803. cchData += 64;
  804. break;
  805. default:
  806. ASSERT (0);
  807. switch (lcType)
  808. {
  809. case LOCALE_SDAYNAME1:
  810. VERIFY (dayName.LoadString (IDS_MONDAY));
  811. break;
  812. case LOCALE_SDAYNAME2:
  813. VERIFY (dayName.LoadString (IDS_TUESDAY));
  814. break;
  815. case LOCALE_SDAYNAME3:
  816. VERIFY (dayName.LoadString (IDS_WEDNESDAY));
  817. break;
  818. case LOCALE_SDAYNAME4:
  819. VERIFY (dayName.LoadString (IDS_THURSDAY));
  820. break;
  821. case LOCALE_SDAYNAME5:
  822. VERIFY (dayName.LoadString (IDS_FRIDAY));
  823. break;
  824. case LOCALE_SDAYNAME6:
  825. VERIFY (dayName.LoadString (IDS_SATURDAY));
  826. break;
  827. case LOCALE_SDAYNAME7:
  828. VERIFY (dayName.LoadString (IDS_SUNDAY));
  829. break;
  830. default:
  831. ASSERT (0);
  832. break;
  833. }
  834. break;
  835. }
  836. }
  837. } while (!iResult);
  838. return dayName;
  839. }
  840. //****************************************************************************
  841. //
  842. // CScheduleMatrix::SetBackColor
  843. //
  844. //****************************************************************************
  845. void CScheduleMatrix::SetBackColor(COLORREF crColor, UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  846. {
  847. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  848. ASSERT(nHour < 24);
  849. ASSERT(nDay < nDays);
  850. ASSERT(nNumHours>=1);
  851. ASSERT(nNumDays>=1);
  852. ASSERT(nHour + nNumHours <= 24);
  853. ASSERT(nDay + nNumDays <= nDays);
  854. UINT i, j;
  855. for (i=0; i<nNumHours; i++)
  856. {
  857. for (j=0; j<nNumDays; j++)
  858. {
  859. m_CellArray[nHour+i][nDay+j].m_crBackColor = crColor;
  860. }
  861. }
  862. InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  863. }
  864. //****************************************************************************
  865. //
  866. // CScheduleMatrix::SetForeColor
  867. //
  868. //****************************************************************************
  869. void CScheduleMatrix::SetForeColor(COLORREF crColor, UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  870. {
  871. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  872. ASSERT(nHour < 24);
  873. ASSERT(nDay < nDays);
  874. ASSERT(nNumHours>=1);
  875. ASSERT(nNumDays>=1);
  876. ASSERT(nHour + nNumHours <= 24);
  877. ASSERT(nDay + nNumDays <= nDays);
  878. UINT i, j;
  879. for (i=0; i<nNumHours; i++)
  880. {
  881. for (j=0; j<nNumDays; j++)
  882. {
  883. m_CellArray[nHour+i][nDay+j].m_crForeColor = crColor;
  884. }
  885. }
  886. InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  887. }
  888. //****************************************************************************
  889. //
  890. // CScheduleMatrix::SetPercentage
  891. //
  892. //****************************************************************************
  893. void CScheduleMatrix::SetPercentage(UINT nPercent, UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  894. {
  895. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  896. ASSERT(nHour < 24);
  897. ASSERT(nDay < nDays);
  898. ASSERT(nNumHours>=1);
  899. ASSERT(nNumDays>=1);
  900. ASSERT(nHour + nNumHours <= 24);
  901. ASSERT(nDay + nNumDays <= nDays);
  902. ASSERT(nPercent <= 100);
  903. UINT i, j;
  904. for (i=0; i<nNumHours; i++)
  905. {
  906. for (j=0; j<nNumDays; j++)
  907. {
  908. m_CellArray[nHour+i][nDay+j].m_nPercentage = nPercent;
  909. }
  910. }
  911. InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  912. }
  913. //****************************************************************************
  914. //
  915. // CScheduleMatrix::SetBlendColor
  916. //
  917. //****************************************************************************
  918. void CScheduleMatrix::SetBlendColor(COLORREF crColor, UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  919. {
  920. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  921. ASSERT(nHour < 24);
  922. ASSERT(nDay < nDays);
  923. ASSERT(nNumHours>=1);
  924. ASSERT(nNumDays>=1);
  925. ASSERT(nHour + nNumHours <= 24);
  926. ASSERT(nDay + nNumDays <= nDays);
  927. UINT i, j;
  928. for (i=0; i<nNumHours; i++)
  929. {
  930. for (j=0; j<nNumDays; j++)
  931. {
  932. m_CellArray[nHour+i][nDay+j].m_crBlendColor = crColor;
  933. }
  934. }
  935. InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  936. }
  937. //****************************************************************************
  938. //
  939. // CScheduleMatrix::SetBlendState
  940. //
  941. //****************************************************************************
  942. void CScheduleMatrix::SetBlendState(BOOL bState, UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  943. {
  944. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  945. ASSERT(nHour < 24);
  946. ASSERT(nDay < nDays);
  947. ASSERT(nNumHours>=1);
  948. ASSERT(nNumDays>=1);
  949. ASSERT(nHour + nNumHours <= 24);
  950. ASSERT(nDay + nNumDays <= nDays);
  951. UINT i, j;
  952. for (i=0; i<nNumHours; i++)
  953. {
  954. for (j=0; j<nNumDays; j++)
  955. {
  956. if (bState)
  957. m_CellArray[nHour+i][nDay+j].m_dwFlags |= MC_BLEND;
  958. else
  959. m_CellArray[nHour+i][nDay+j].m_dwFlags &= (MC_BLEND^0xFFFFFFFF);
  960. }
  961. }
  962. InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  963. }
  964. //****************************************************************************
  965. //
  966. // CScheduleMatrix::SetUserValue
  967. //
  968. //****************************************************************************
  969. void CScheduleMatrix::SetUserValue(DWORD dwValue, UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  970. {
  971. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  972. ASSERT(nHour < 24);
  973. ASSERT(nDay < nDays);
  974. ASSERT(nNumHours>=1);
  975. ASSERT(nNumDays>=1);
  976. ASSERT(nHour + nNumHours <= 24);
  977. ASSERT(nDay + nNumDays <= nDays);
  978. UINT i, j;
  979. for (i=0; i<nNumHours; i++)
  980. {
  981. for (j=0; j<nNumDays; j++)
  982. {
  983. m_CellArray[nHour+i][nDay+j].m_dwUserValue = dwValue;
  984. }
  985. }
  986. //?? If we ever have ownerdraw
  987. //?? InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  988. }
  989. //****************************************************************************
  990. //
  991. // CScheduleMatrix::SetUserDataPtr
  992. //
  993. //****************************************************************************
  994. void CScheduleMatrix::SetUserDataPtr(void * lpData, UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  995. {
  996. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  997. ASSERT(nHour < 24);
  998. ASSERT(nDay < nDays);
  999. ASSERT(nNumHours>=1);
  1000. ASSERT(nNumDays>=1);
  1001. ASSERT(nHour + nNumHours <= 24);
  1002. ASSERT(nDay + nNumDays <= nDays);
  1003. UINT i, j;
  1004. for (i=0; i<nNumHours; i++)
  1005. {
  1006. for (j=0; j<nNumDays; j++)
  1007. {
  1008. m_CellArray[nHour+i][nDay+j].m_pUserDataPtr = lpData;
  1009. }
  1010. }
  1011. //?? If we ever have ownerdraw
  1012. //?? InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  1013. }
  1014. //****************************************************************************
  1015. //
  1016. // CScheduleMatrix::MergeCells
  1017. //
  1018. //****************************************************************************
  1019. void CScheduleMatrix::MergeCells(UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  1020. {
  1021. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1022. ASSERT(nHour < 24);
  1023. ASSERT(nDay < nDays);
  1024. ASSERT(nNumHours>=1);
  1025. ASSERT(nNumDays>=1);
  1026. ASSERT(nHour + nNumHours <= 24);
  1027. ASSERT(nDay + nNumDays <= nDays);
  1028. DWORD dwFlags;
  1029. UINT i, j;
  1030. for (i=0; i<nNumHours; i++)
  1031. {
  1032. for (j=0; j<nNumDays; j++)
  1033. {
  1034. dwFlags = m_CellArray[nHour+i][nDay+j].m_dwFlags;
  1035. dwFlags |= MC_MERGE;
  1036. dwFlags &= (MC_ALLEDGES^0xFFFFFFFF);
  1037. if (i != 0)
  1038. dwFlags |= MC_MERGELEFT;
  1039. if (i == 0)
  1040. dwFlags |= MC_LEFTEDGE;
  1041. if (i == nNumHours-1)
  1042. dwFlags |= MC_RIGHTEDGE;
  1043. if (j != 0)
  1044. dwFlags |= MC_MERGETOP;
  1045. if (j == 0)
  1046. dwFlags |= MC_TOPEDGE;
  1047. if (j == nNumDays-1)
  1048. dwFlags |= MC_BOTTOMEDGE;
  1049. m_CellArray[nHour+i][nDay+j].m_dwFlags = dwFlags;
  1050. }
  1051. }
  1052. InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  1053. }
  1054. //****************************************************************************
  1055. //
  1056. // CScheduleMatrix::UnMergeCells
  1057. //
  1058. //****************************************************************************
  1059. void CScheduleMatrix::UnMergeCells(UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  1060. {
  1061. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1062. ASSERT(nHour < 24);
  1063. ASSERT(nDay < nDays);
  1064. ASSERT(nNumHours>=1);
  1065. ASSERT(nNumDays>=1);
  1066. ASSERT(nHour + nNumHours <= 24);
  1067. ASSERT(nDay + nNumDays <= nDays);
  1068. DWORD dwFlags;
  1069. UINT i, j;
  1070. for (i=0; i<nNumHours; i++)
  1071. {
  1072. for (j=0; j<nNumDays; j++)
  1073. {
  1074. dwFlags = m_CellArray[nHour+i][nDay+j].m_dwFlags;
  1075. dwFlags &= (MC_ALLEDGES^0xFFFFFFFF);
  1076. dwFlags &= (MC_MERGE^0xFFFFFFFF);
  1077. if (i != 0)
  1078. dwFlags &= (MC_MERGELEFT^0xFFFFFFFF);
  1079. if (j != 0)
  1080. dwFlags &= (MC_MERGETOP^0xFFFFFFFF);
  1081. m_CellArray[nHour+i][nDay+j].m_dwFlags = dwFlags;
  1082. }
  1083. }
  1084. InvalidateCells(nHour, nDay, nNumHours, nNumDays, FALSE);
  1085. }
  1086. //****************************************************************************
  1087. //
  1088. // CScheduleMatrix::GetMergeState
  1089. //
  1090. //****************************************************************************
  1091. UINT CScheduleMatrix::GetMergeState(UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays)
  1092. {
  1093. // Returns:
  1094. // 0 = Unmerged
  1095. // 1 = Merged
  1096. // 2 = Indeterminate (mixed)
  1097. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1098. ASSERT(nHour < 24);
  1099. ASSERT(nDay < nDays);
  1100. ASSERT(nNumHours>=1);
  1101. ASSERT(nNumDays>=1);
  1102. ASSERT(nHour + nNumHours <= 24);
  1103. ASSERT(nDay + nNumDays <= nDays);
  1104. UINT i, j;
  1105. DWORD dwFlags;
  1106. BOOL bFoundMergedCell = FALSE, bFoundUnmergedCell = FALSE,
  1107. bFoundBadEdge = FALSE, bFoundBadNonEdge = FALSE;
  1108. for (i=0; i<nNumHours; i++)
  1109. {
  1110. for (j=0; j<nNumDays; j++)
  1111. {
  1112. dwFlags = m_CellArray[nHour+i][nDay+j].m_dwFlags;
  1113. if (dwFlags & MC_MERGE)
  1114. bFoundMergedCell = TRUE;
  1115. else
  1116. bFoundUnmergedCell = TRUE;
  1117. if (i == 0 || i == nNumHours-1 || j == 0 || j == nNumDays-1)
  1118. {
  1119. // If cell is an edge, make sure it's marked appropriately
  1120. if (i == 0 && !(dwFlags & MC_LEFTEDGE))
  1121. bFoundBadEdge = TRUE;
  1122. if (i == nNumHours-1 && !(dwFlags & MC_RIGHTEDGE))
  1123. bFoundBadEdge = TRUE;
  1124. if (j == 0 && !(dwFlags & MC_TOPEDGE))
  1125. bFoundBadEdge = TRUE;
  1126. if (j == nNumDays-1 && !(dwFlags & MC_BOTTOMEDGE))
  1127. bFoundBadEdge = TRUE;
  1128. }
  1129. else
  1130. {
  1131. // If cell is not an edge, make sure it's not marked as such
  1132. if (dwFlags & MC_ALLEDGES)
  1133. bFoundBadNonEdge = TRUE;
  1134. }
  1135. }
  1136. }
  1137. // If we found no merged cells, we are definitely unmerged
  1138. if (!bFoundMergedCell)
  1139. return MS_UNMERGED;
  1140. // If we found only good, merged cells, we are definitely merged
  1141. if (!bFoundUnmergedCell && !bFoundBadEdge && !bFoundBadNonEdge)
  1142. return MS_MERGED;
  1143. return MS_MIXEDMERGE;
  1144. }
  1145. //****************************************************************************
  1146. //
  1147. // CScheduleMatrix::GetBackColor
  1148. //
  1149. //****************************************************************************
  1150. COLORREF CScheduleMatrix::GetBackColor(UINT nHour, UINT nDay)
  1151. {
  1152. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1153. ASSERT(nHour < 24);
  1154. ASSERT(nDay < nDays);
  1155. return m_CellArray[nHour][nDay].m_crBackColor;
  1156. }
  1157. //****************************************************************************
  1158. //
  1159. // CScheduleMatrix::GetForeColor
  1160. //
  1161. //****************************************************************************
  1162. COLORREF CScheduleMatrix::GetForeColor(UINT nHour, UINT nDay)
  1163. {
  1164. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1165. ASSERT(nHour < 24);
  1166. ASSERT(nDay < nDays);
  1167. return m_CellArray[nHour][nDay].m_crForeColor;
  1168. }
  1169. //****************************************************************************
  1170. //
  1171. // CScheduleMatrix::GetPercentage
  1172. //
  1173. //****************************************************************************
  1174. UINT CScheduleMatrix::GetPercentage(UINT nHour, UINT nDay)
  1175. {
  1176. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1177. ASSERT(nHour < 24);
  1178. ASSERT(nDay < nDays);
  1179. return m_CellArray[nHour][nDay].m_nPercentage;
  1180. }
  1181. //****************************************************************************
  1182. //
  1183. // CScheduleMatrix::GetBlendColor
  1184. //
  1185. //****************************************************************************
  1186. COLORREF CScheduleMatrix::GetBlendColor(UINT nHour, UINT nDay)
  1187. {
  1188. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1189. ASSERT(nHour < 24);
  1190. ASSERT(nDay < nDays);
  1191. return m_CellArray[nHour][nDay].m_crBlendColor;
  1192. }
  1193. //****************************************************************************
  1194. //
  1195. // CScheduleMatrix::GetBlendState
  1196. //
  1197. //****************************************************************************
  1198. BOOL CScheduleMatrix::GetBlendState(UINT nHour, UINT nDay)
  1199. {
  1200. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1201. ASSERT(nHour < 24);
  1202. ASSERT(nDay < nDays);
  1203. if (m_CellArray[nHour][nDay].m_dwFlags & MC_BLEND)
  1204. return TRUE;
  1205. return FALSE;
  1206. }
  1207. //****************************************************************************
  1208. //
  1209. // CScheduleMatrix::GetUserValue
  1210. //
  1211. //****************************************************************************
  1212. DWORD CScheduleMatrix::GetUserValue(UINT nHour, UINT nDay)
  1213. {
  1214. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1215. ASSERT(nHour < 24);
  1216. ASSERT(nDay < nDays);
  1217. return m_CellArray[nHour][nDay].m_dwUserValue;
  1218. }
  1219. //****************************************************************************
  1220. //
  1221. // CScheduleMatrix::GetUserDataPtr
  1222. //
  1223. //****************************************************************************
  1224. LPVOID CScheduleMatrix::GetUserDataPtr(UINT nHour, UINT nDay)
  1225. {
  1226. UINT nDays = (m_nType == MT_DAILY ? 1 : 7);
  1227. ASSERT(nHour < 24);
  1228. ASSERT(nDay < nDays);
  1229. return m_CellArray[nHour][nDay].m_pUserDataPtr;
  1230. }
  1231. //****************************************************************************
  1232. //
  1233. // CScheduleMatrix::OnSetFocus
  1234. //
  1235. //****************************************************************************
  1236. void CScheduleMatrix::OnSetFocus(CWnd* pOldWnd)
  1237. {
  1238. CWnd::OnSetFocus(pOldWnd);
  1239. CDC *pdc = GetDC();
  1240. CRect rSel(m_nSelHour, m_nSelDay, m_nSelHour+m_nNumSelHours, m_nSelDay+m_nNumSelDays);
  1241. CellToClient(rSel.left, rSel.top);
  1242. CellToClient(rSel.right, rSel.bottom);
  1243. rSel.right+=1;
  1244. rSel.bottom+=1;
  1245. pdc->DrawFocusRect(rSel);
  1246. ReleaseDC(pdc);
  1247. }
  1248. //****************************************************************************
  1249. //
  1250. // CScheduleMatrix::OnKillFocus
  1251. //
  1252. //****************************************************************************
  1253. void CScheduleMatrix::OnKillFocus(CWnd* pNewWnd)
  1254. {
  1255. CWnd::OnKillFocus(pNewWnd);
  1256. CDC *pdc = GetDC();
  1257. CRect rSel(m_nSelHour, m_nSelDay, m_nSelHour+m_nNumSelHours, m_nSelDay+m_nNumSelDays);
  1258. CellToClient(rSel.left, rSel.top);
  1259. CellToClient(rSel.right, rSel.bottom);
  1260. rSel.right+=1;
  1261. rSel.bottom+=1;
  1262. pdc->DrawFocusRect(rSel);
  1263. ReleaseDC(pdc);
  1264. }
  1265. //****************************************************************************
  1266. //
  1267. // CScheduleMatrix::OnLButtonDown
  1268. //
  1269. //****************************************************************************
  1270. void CScheduleMatrix::OnLButtonDown(UINT nFlags, CPoint point)
  1271. {
  1272. SetFocus();
  1273. SetCapture();
  1274. m_ptDown = point;
  1275. m_ptFocus = point;
  1276. m_ptFocus.x = max(m_ptFocus.x, m_rCellArray.left);
  1277. m_ptFocus.y = max(m_ptFocus.y, m_rCellArray.top);
  1278. m_ptFocus.x = min(m_ptFocus.x, m_rCellArray.right);
  1279. m_ptFocus.y = min(m_ptFocus.y, m_rCellArray.bottom);
  1280. m_nSaveHour = m_nSelHour;
  1281. m_nSaveDay = m_nSelDay;
  1282. m_nNumSaveHours = m_nNumSelHours;
  1283. m_nNumSaveDays = m_nNumSelDays;
  1284. CWnd::OnLButtonDown(nFlags, point);
  1285. // Invalidate for "button selection" effect in the headers.
  1286. if (m_rAllHeader.PtInRect(m_ptDown))
  1287. InvalidateRect(m_rAllHeader, FALSE);
  1288. if (m_rHourHeader.PtInRect(m_ptDown))
  1289. InvalidateRect(m_rHourHeader, FALSE);
  1290. if (m_rDayHeader.PtInRect(m_ptDown))
  1291. InvalidateRect(m_rDayHeader, FALSE);
  1292. OnMouseMove(nFlags, point);
  1293. }
  1294. //****************************************************************************
  1295. //
  1296. // CScheduleMatrix::OnLButtonDblClk
  1297. //
  1298. //****************************************************************************
  1299. void CScheduleMatrix::OnLButtonDblClk(UINT nFlags, CPoint point)
  1300. {
  1301. // Same as button down
  1302. OnLButtonDown(nFlags, point);
  1303. CWnd::OnLButtonDblClk(nFlags, point);
  1304. }
  1305. //****************************************************************************
  1306. //
  1307. // CScheduleMatrix::OnLButtonUp
  1308. //
  1309. //****************************************************************************
  1310. void CScheduleMatrix::OnLButtonUp(UINT nFlags, CPoint point)
  1311. {
  1312. if (GetCapture() == this)
  1313. {
  1314. m_ptFocus = point;
  1315. m_ptFocus.x = max(m_ptFocus.x, m_rCellArray.left);
  1316. m_ptFocus.y = max(m_ptFocus.y, m_rCellArray.top);
  1317. m_ptFocus.x = min(m_ptFocus.x, m_rCellArray.right);
  1318. m_ptFocus.y = min(m_ptFocus.y, m_rCellArray.bottom);
  1319. ReleaseCapture();
  1320. // If drawing the "button selection" effect in the headers, redraw.
  1321. if (m_rAllHeader.PtInRect(m_ptDown))
  1322. InvalidateRect(m_rAllHeader, FALSE);
  1323. if (m_rHourHeader.PtInRect(m_ptDown))
  1324. InvalidateRect(m_rHourHeader, FALSE);
  1325. if (m_rDayHeader.PtInRect(m_ptDown))
  1326. InvalidateRect(m_rDayHeader, FALSE);
  1327. if (m_nSaveHour != m_nSelHour || m_nSaveDay != m_nSelDay ||
  1328. m_nNumSaveHours != m_nNumSelHours || m_nNumSaveDays != m_nNumSelDays)
  1329. {
  1330. GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), MN_SELCHANGE),
  1331. (LPARAM)GetSafeHwnd());
  1332. }
  1333. }
  1334. CWnd::OnLButtonUp(nFlags, point);
  1335. }
  1336. //****************************************************************************
  1337. //
  1338. // CScheduleMatrix::OnMouseMove
  1339. //
  1340. //****************************************************************************
  1341. void CScheduleMatrix::OnMouseMove(UINT nFlags, CPoint point)
  1342. {
  1343. if (GetCapture() == this)
  1344. {
  1345. m_ptFocus = point;
  1346. m_ptFocus.x = max(m_ptFocus.x, m_rCellArray.left);
  1347. m_ptFocus.y = max(m_ptFocus.y, m_rCellArray.top);
  1348. m_ptFocus.x = min(m_ptFocus.x, m_rCellArray.right);
  1349. m_ptFocus.y = min(m_ptFocus.y, m_rCellArray.bottom);
  1350. CRect rInvalid(0,0,0,0);
  1351. CRect rSel(m_ptDown.x, m_ptDown.y, point.x, point.y);
  1352. if (m_rDayHeader.PtInRect(m_ptDown))
  1353. {
  1354. rSel.right = m_rCellArray.right;
  1355. rInvalid = m_rDayHeader;
  1356. }
  1357. if (m_rHourHeader.PtInRect(m_ptDown))
  1358. {
  1359. rSel.bottom = m_rCellArray.bottom;
  1360. rInvalid = m_rHourHeader;
  1361. }
  1362. if (m_rAllHeader.PtInRect(m_ptDown))
  1363. {
  1364. rSel.right = m_rCellArray.right;
  1365. rSel.bottom = m_rCellArray.bottom;
  1366. rInvalid = m_rAllHeader;
  1367. }
  1368. ClientToCell(rSel.left, rSel.top);
  1369. ClientToCell(rSel.right, rSel.bottom);
  1370. rSel.NormalizeRect();
  1371. rSel.right += 1;
  1372. rSel.bottom += 1;
  1373. rSel.right = min(rSel.right, 24);
  1374. rSel.bottom = min(rSel.bottom, (m_nType == MT_DAILY ? 1 : 7));
  1375. // If we've drifted out of the down area, reset selection
  1376. CRect rDayHeader(m_rDayHeader);
  1377. CRect rHourHeader(m_rHourHeader);
  1378. CRect rAllHeader(m_rAllHeader);
  1379. CRect rCellArray(m_rCellArray);
  1380. int nBuffer = GetSystemMetrics(SM_CXVSCROLL);
  1381. rDayHeader.InflateRect(nBuffer,nBuffer);
  1382. rHourHeader.InflateRect(nBuffer,nBuffer);
  1383. rAllHeader.InflateRect(nBuffer,nBuffer);
  1384. rCellArray.InflateRect(nBuffer,nBuffer);
  1385. if ((m_rDayHeader.PtInRect(m_ptDown) && !rDayHeader.PtInRect(point)) ||
  1386. (m_rHourHeader.PtInRect(m_ptDown) && !rHourHeader.PtInRect(point)) ||
  1387. (m_rAllHeader.PtInRect(m_ptDown) && !rAllHeader.PtInRect(point)) ||
  1388. (m_rCellArray.PtInRect(m_ptDown) && !rCellArray.PtInRect(point)))
  1389. rSel.SetRect(m_nSaveHour, m_nSaveDay, m_nSaveHour+m_nNumSaveHours,
  1390. m_nSaveDay+m_nNumSaveDays);
  1391. if (SetSelValues(rSel.left, rSel.top, rSel.Width(), rSel.Height()))
  1392. InvalidateRect(rInvalid);
  1393. }
  1394. CWnd::OnMouseMove(nFlags, point);
  1395. }
  1396. //****************************************************************************
  1397. //
  1398. // CScheduleMatrix::OnGetDlgCode
  1399. //
  1400. //****************************************************************************
  1401. UINT CScheduleMatrix::OnGetDlgCode()
  1402. {
  1403. return (DLGC_WANTCHARS | DLGC_WANTARROWS);
  1404. }
  1405. //****************************************************************************
  1406. //
  1407. // CScheduleMatrix::OnKeyDown
  1408. //
  1409. //****************************************************************************
  1410. void CScheduleMatrix::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
  1411. {
  1412. // BOOL bShifted = 0x8000 & GetKeyState(VK_SHIFT);
  1413. CPoint ptCell, ptOldCell, ptClient;
  1414. ptCell = m_ptFocus;
  1415. ClientToCell(ptCell.x, ptCell.y);
  1416. ptOldCell = ptCell;
  1417. BOOL bToggle = FALSE;
  1418. switch (nChar)
  1419. {
  1420. case VK_SHIFT:
  1421. m_bShifted = TRUE;
  1422. break;;
  1423. case VK_SPACE:
  1424. bToggle = TRUE;
  1425. break;
  1426. case VK_LEFT:
  1427. ptCell.x -= 1;
  1428. break;
  1429. case VK_RIGHT:
  1430. ptCell.x += 1;
  1431. break;
  1432. case VK_UP:
  1433. ptCell.y -= 1;
  1434. break;
  1435. case VK_DOWN:
  1436. ptCell.y += 1;
  1437. break;
  1438. case VK_PRIOR:
  1439. ptCell.y = -1;
  1440. break;
  1441. case VK_NEXT:
  1442. ptCell.y = 6;
  1443. break;
  1444. case VK_HOME:
  1445. ptCell.x = -1;
  1446. ptCell.y = -1;
  1447. break;
  1448. case VK_END:
  1449. ptCell.x = 23;
  1450. ptCell.y = 6;
  1451. break;
  1452. }
  1453. // Restrict keyboard control to the matrix...
  1454. ptCell.x = max(0, ptCell.x);
  1455. ptCell.x = min(23, ptCell.x);
  1456. ptCell.y = max(0, ptCell.y);
  1457. ptCell.y = min((m_nType == MT_DAILY ? 0 : 6), ptCell.y);
  1458. ptClient = ptCell;
  1459. CellToClient(ptClient.x, ptClient.y);
  1460. if (bToggle)
  1461. {
  1462. OnLButtonDown(MK_LBUTTON, ptClient);
  1463. OnLButtonUp(MK_LBUTTON, ptClient);
  1464. /*
  1465. if (bShifted)
  1466. Extend(ptClient);
  1467. else
  1468. {
  1469. Press(ptClient, FALSE);
  1470. Release(ptClient);
  1471. }
  1472. ptFocus = ptClient;
  1473. */
  1474. }
  1475. else if (ptCell != ptOldCell)
  1476. {
  1477. if (m_bShifted)
  1478. {
  1479. // Extend(ptClient);
  1480. if (GetCapture() != this)
  1481. {
  1482. CPoint ptOldClient(ptOldCell);
  1483. CellToClient(ptOldClient.x, ptOldClient.y);
  1484. OnLButtonDown(MK_LBUTTON, ptOldClient);
  1485. }
  1486. OnMouseMove(MK_LBUTTON, ptClient);
  1487. }
  1488. else
  1489. {
  1490. OnLButtonDown(MK_LBUTTON, ptClient);
  1491. OnLButtonUp(MK_LBUTTON, ptClient);
  1492. }
  1493. /*
  1494. if (bFocus)
  1495. DrawFocus(FALSE, ptFocus, NULL);
  1496. ptFocus = ptClient;
  1497. if (bFocus)
  1498. DrawFocus(TRUE, ptFocus, NULL);
  1499. */
  1500. }
  1501. }
  1502. //****************************************************************************
  1503. //
  1504. // CScheduleMatrix::OnKeyUp
  1505. //
  1506. //****************************************************************************
  1507. void CScheduleMatrix::OnKeyUp(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
  1508. {
  1509. switch (nChar)
  1510. {
  1511. case VK_SHIFT:
  1512. m_bShifted = FALSE;
  1513. OnLButtonUp(MK_LBUTTON, m_ptFocus);
  1514. break;
  1515. case VK_SPACE:
  1516. case VK_LEFT:
  1517. case VK_RIGHT:
  1518. case VK_UP:
  1519. case VK_DOWN:
  1520. case VK_PRIOR:
  1521. case VK_NEXT:
  1522. case VK_HOME:
  1523. case VK_END:
  1524. // Release(ptFocus);
  1525. break;
  1526. }
  1527. }
  1528. //****************************************************************************
  1529. //
  1530. // CScheduleMatrix::InvalidateCells
  1531. //
  1532. //****************************************************************************
  1533. void CScheduleMatrix::InvalidateCells(UINT nHour, UINT nDay, UINT nNumHours, UINT nNumDays,
  1534. BOOL bErase)
  1535. {
  1536. CRect r(nHour, nDay, nHour+nNumHours, nDay+nNumDays);
  1537. CellToClient(r.left, r.top);
  1538. CellToClient(r.right, r.bottom);
  1539. r.right += 1;
  1540. r.bottom += 1;
  1541. InvalidateRect(r, bErase);
  1542. }
  1543. //****************************************************************************
  1544. //
  1545. // CScheduleMatrix::OnGetObject
  1546. //
  1547. //****************************************************************************
  1548. LRESULT CScheduleMatrix::OnGetObject (WPARAM wParam, LPARAM lParam)
  1549. {
  1550. if ( lParam == OBJID_CLIENT )
  1551. {
  1552. // At this point we will try to load oleacc and get the functions
  1553. // we need.
  1554. if (!g_fAttemptedOleAccLoad)
  1555. {
  1556. g_fAttemptedOleAccLoad = TRUE;
  1557. ASSERT (0 == s_pfnCreateStdAccessibleObject);
  1558. ASSERT(s_pfnCreateStdAccessibleProxy == NULL);
  1559. ASSERT(s_pfnLresultFromObject == NULL);
  1560. g_hOleAcc = LoadLibrary (L"OLEACC");
  1561. if (g_hOleAcc != NULL)
  1562. {
  1563. s_pfnCreateStdAccessibleObject = (PFNCREATESTDACCESSIBLEOBJECT)
  1564. GetProcAddress(g_hOleAcc, "CreateStdAccessibleObject");
  1565. s_pfnCreateStdAccessibleProxy = (PFNCREATESTDACCESSIBLEPROXY)
  1566. GetProcAddress(g_hOleAcc, "CreateStdAccessibleProxyW");
  1567. s_pfnLresultFromObject = (PFNLRESULTFROMOBJECT)
  1568. GetProcAddress(g_hOleAcc, "LresultFromObject");
  1569. }
  1570. if (s_pfnLresultFromObject == NULL ||
  1571. s_pfnCreateStdAccessibleProxy == NULL ||
  1572. 0 == s_pfnCreateStdAccessibleObject)
  1573. {
  1574. if (g_hOleAcc)
  1575. {
  1576. // No point holding on to Oleacc since we can't use it.
  1577. FreeLibrary(g_hOleAcc);
  1578. g_hOleAcc = NULL;
  1579. }
  1580. s_pfnLresultFromObject = NULL;
  1581. s_pfnCreateStdAccessibleProxy = NULL;
  1582. s_pfnCreateStdAccessibleObject = 0;
  1583. }
  1584. }
  1585. if (g_hOleAcc &&
  1586. s_pfnCreateStdAccessibleProxy &&
  1587. s_pfnLresultFromObject &&
  1588. s_pfnCreateStdAccessibleObject)
  1589. {
  1590. IAccessible* pAcc = NULL;
  1591. const int CLASS_NAME_LEN = 64;
  1592. WCHAR szClassName[CLASS_NAME_LEN];
  1593. int nRet = ::GetClassName(m_hWnd, szClassName, CLASS_NAME_LEN);
  1594. if ( !nRet )
  1595. {
  1596. DWORD dwErr = GetLastError ();
  1597. dwErr = dwErr;
  1598. }
  1599. // Create default proxy.
  1600. HRESULT hr = s_pfnCreateStdAccessibleObject (
  1601. m_hWnd,
  1602. OBJID_CLIENT,
  1603. IID_PPV_ARG (IAccessible, &pAcc));
  1604. if (SUCCEEDED(hr) && pAcc)
  1605. {
  1606. // now wrap it up in our customized wrapper...
  1607. IAccessible * pWrapAcc = new CAccessibleWrapper (m_hWnd, pAcc);
  1608. // Release our ref to proxy (wrapper has its own addref'd ptr)...
  1609. pAcc->Release();
  1610. if (pWrapAcc != NULL)
  1611. {
  1612. // ...and return the wrapper via LresultFromObject...
  1613. LRESULT lr = s_pfnLresultFromObject (IID_IAccessible, wParam, pWrapAcc);
  1614. // Release our interface pointer - OLEACC has its own addref to the object
  1615. pWrapAcc->Release();
  1616. // Return the lresult, which 'contains' a reference to our wrapper object.
  1617. return lr;
  1618. // All done!
  1619. }
  1620. // If it didn't work, fall through to default behavior instead.
  1621. }
  1622. }
  1623. }
  1624. return 0;
  1625. }
  1626. //****************************************************************************
  1627. //
  1628. // CScheduleMatrix::OnGetSelDescription
  1629. //
  1630. // wParam - length of passed in string buffer
  1631. // lParam - wide-char string buffer
  1632. //
  1633. //****************************************************************************
  1634. LRESULT CScheduleMatrix::OnGetSelDescription (WPARAM wParam, LPARAM lParam)
  1635. {
  1636. LRESULT lResult = 0;
  1637. PWSTR pszDescription = (PWSTR) lParam;
  1638. if ( pszDescription )
  1639. {
  1640. UINT nMaxLen = (UINT) wParam;
  1641. CString szDescription;
  1642. GetSelDescription (szDescription);
  1643. wcsncpy (pszDescription, szDescription, nMaxLen);
  1644. }
  1645. else
  1646. lResult = -1;
  1647. return lResult;
  1648. }
  1649. //****************************************************************************
  1650. //
  1651. // CScheduleMatrix::OnGetPercentage
  1652. //
  1653. // wParam - return % of selected cell
  1654. // lParam - unused
  1655. //
  1656. //****************************************************************************
  1657. LRESULT CScheduleMatrix::OnGetPercentage (WPARAM /*wParam*/, LPARAM /*lParam*/)
  1658. {
  1659. LRESULT lResult = 0;
  1660. if ( 1 == m_nNumSelHours && 1 == m_nNumSelDays )
  1661. lResult = GetPercentage (m_nSelHour, m_nSelDay);
  1662. else
  1663. lResult = -1;
  1664. return lResult;
  1665. }
  1666. /////////////////////////////////////////////////////////////////////////////
  1667. // CHourLegend
  1668. IMPLEMENT_DYNAMIC(CHourLegend, CWnd)
  1669. //****************************************************************************
  1670. //
  1671. // CHourLegend::CHourLegend
  1672. //
  1673. //****************************************************************************
  1674. CHourLegend::CHourLegend()
  1675. {
  1676. m_hiconSun = m_hiconMoon = NULL;
  1677. m_hFont = NULL;
  1678. }
  1679. //****************************************************************************
  1680. //
  1681. // CHourLegend::~CHourLegend
  1682. //
  1683. //****************************************************************************
  1684. CHourLegend::~CHourLegend()
  1685. {
  1686. if ( m_hiconMoon )
  1687. {
  1688. DestroyIcon (m_hiconMoon);
  1689. m_hiconMoon = 0;
  1690. }
  1691. if ( m_hiconSun )
  1692. {
  1693. DestroyIcon (m_hiconSun);
  1694. m_hiconSun = 0;
  1695. }
  1696. }
  1697. BEGIN_MESSAGE_MAP(CHourLegend, CWnd)
  1698. //{{AFX_MSG_MAP(CHourLegend)
  1699. ON_WM_PAINT()
  1700. //}}AFX_MSG_MAP
  1701. END_MESSAGE_MAP()
  1702. /////////////////////////////////////////////////////////////////////////////
  1703. // CHourLegend message handlers
  1704. //****************************************************************************
  1705. //
  1706. // CHourLegend::OnPaint
  1707. //
  1708. //****************************************************************************
  1709. void CHourLegend::OnPaint()
  1710. {
  1711. CRect rClient;
  1712. CPaintDC dc(this); // device context for painting
  1713. CFont *pOldFont = NULL;
  1714. CFont *pFont = CFont::FromHandle(m_hFont);
  1715. if (pFont != NULL)
  1716. pOldFont = dc.SelectObject(pFont);
  1717. CBrush brFace(::GetSysColor(COLOR_3DFACE));
  1718. CBrush *pbrOld = dc.SelectObject(&brFace);
  1719. GetClientRect(rClient);
  1720. // Draw the hour legend
  1721. if (m_hiconSun == NULL)
  1722. m_hiconSun = (HICON)::LoadImage(AfxFindResourceHandle(_T("SUN16"), RT_GROUP_ICON),
  1723. _T("SUN16"), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  1724. if (m_hiconMoon == NULL)
  1725. m_hiconMoon = (HICON)::LoadImage(AfxFindResourceHandle(_T("MOON16"), RT_GROUP_ICON),
  1726. _T("MOON16"), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  1727. dc.FillRect(rClient, &brFace);
  1728. ::DrawIconEx(dc.GetSafeHdc(),m_rLegend.left-8,rClient.bottom - m_nCharHeight - 16 - 2,
  1729. (HICON)m_hiconMoon,0,0,0,NULL,DI_NORMAL);
  1730. ::DrawIconEx(dc.GetSafeHdc(),m_rLegend.left + m_rLegend.Width()/2 - 8,
  1731. rClient.bottom - m_nCharHeight - 16 - 2,(HICON)m_hiconSun,0,0,0,NULL,DI_NORMAL);
  1732. ::DrawIconEx(dc.GetSafeHdc(),m_rLegend.right-8,rClient.bottom - m_nCharHeight - 16 - 2,
  1733. (HICON)m_hiconMoon,0,0,0,NULL,DI_NORMAL);
  1734. // Draw the hour text
  1735. COLORREF crBkOld = dc.GetBkColor();
  1736. COLORREF crTextOld = dc.GetTextColor();
  1737. COLORREF crText = ::GetSysColor(COLOR_BTNTEXT);
  1738. COLORREF crFace = ::GetSysColor(COLOR_3DFACE);
  1739. dc.SetBkColor(crFace);
  1740. dc.SetTextColor(crText);
  1741. int i, hr;
  1742. CRect rText, rBullet;
  1743. CString sHour;
  1744. rText.SetRect(m_rLegend.left-m_nCharWidth, rClient.bottom - m_nCharHeight - 2,
  1745. m_rLegend.left + m_nCharWidth, rClient.bottom - 2);
  1746. rBullet.SetRect(m_rLegend.left + m_nCellWidth - 1, rClient.bottom - 2 - rText.Height()/2 - 1,
  1747. m_rLegend.left + m_nCellWidth + 1, rClient.bottom - 2 - rText.Height()/2 + 1);
  1748. bool bIs24HourClock = false;
  1749. CString sFormat;
  1750. int iLen = ::GetLocaleInfo(
  1751. LOCALE_USER_DEFAULT, // locale identifier
  1752. LOCALE_ITIME, // type of information
  1753. 0, // address of buffer for information
  1754. 0); // size of buffer
  1755. ASSERT (iLen > 0);
  1756. if ( iLen > 0 )
  1757. {
  1758. int iResult = ::GetLocaleInfo(
  1759. LOCALE_USER_DEFAULT, // locale identifier
  1760. LOCALE_ITIME, // type of information
  1761. sFormat.GetBufferSetLength (iLen), // address of buffer for information
  1762. iLen); // size of buffer
  1763. ASSERT (iResult);
  1764. sFormat.ReleaseBuffer ();
  1765. if ( sFormat == _TEXT("1") )
  1766. bIs24HourClock = true;
  1767. }
  1768. if ( bIs24HourClock )
  1769. hr = 0;
  1770. else
  1771. hr = 12;
  1772. for (i=0; i<=24; i+=2)
  1773. {
  1774. if ( bIs24HourClock )
  1775. {
  1776. if ( 24 == hr )
  1777. hr = 0;
  1778. }
  1779. else if (hr > 12)
  1780. hr = 2;
  1781. sHour.Format(_T("%d"), hr);
  1782. dc.SetBkColor(crFace); //?? FillSolidRect seems to set BkColor
  1783. ::DrawTextEx(dc.GetSafeHdc(), (LPTSTR)(LPCTSTR)sHour, -1, rText,
  1784. DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS, NULL);
  1785. dc.FillSolidRect(rBullet, crText); //?? FillSolidRect seems to set BkColor
  1786. hr += 2;
  1787. rText.OffsetRect(2*m_nCellWidth, 0);
  1788. if (i < 24)
  1789. rBullet.OffsetRect(2*m_nCellWidth, 0);
  1790. }
  1791. dc.SetBkColor(crBkOld);
  1792. dc.SetTextColor(crTextOld);
  1793. if (pbrOld != NULL)
  1794. dc.SelectObject(pbrOld);
  1795. if (pOldFont != NULL)
  1796. dc.SelectObject(pOldFont);
  1797. // Do not call CWnd::OnPaint() for painting messages
  1798. }
  1799. /////////////////////////////////////////////////////////////////////////////
  1800. // CPercentLabel
  1801. IMPLEMENT_DYNAMIC(CPercentLabel, CWnd)
  1802. //****************************************************************************
  1803. //
  1804. // CPercentLabel::CPercentLabel
  1805. //
  1806. //****************************************************************************
  1807. CPercentLabel::CPercentLabel()
  1808. {
  1809. m_pMatrix = NULL;
  1810. m_hFont = NULL;
  1811. }
  1812. //****************************************************************************
  1813. //
  1814. // CPercentLabel::~CPercentLabel
  1815. //
  1816. //****************************************************************************
  1817. CPercentLabel::~CPercentLabel()
  1818. {
  1819. }
  1820. BEGIN_MESSAGE_MAP(CPercentLabel, CWnd)
  1821. //{{AFX_MSG_MAP(CPercentLabel)
  1822. ON_WM_PAINT()
  1823. //}}AFX_MSG_MAP
  1824. END_MESSAGE_MAP()
  1825. /////////////////////////////////////////////////////////////////////////////
  1826. // CPercentLabel message handlers
  1827. //****************************************************************************
  1828. //
  1829. // CPercentLabel::OnPaint
  1830. //
  1831. //****************************************************************************
  1832. void CPercentLabel::OnPaint()
  1833. {
  1834. CRect rClient;
  1835. CPaintDC dc(this); // device context for painting
  1836. CFont *pOldFont = NULL;
  1837. CFont *pFont = CFont::FromHandle(m_hFont);
  1838. if (pFont != NULL)
  1839. pOldFont = dc.SelectObject(pFont);
  1840. CBrush brFace(::GetSysColor(COLOR_3DFACE));
  1841. CBrush *pbrOld = dc.SelectObject(&brFace);
  1842. GetClientRect(rClient);
  1843. COLORREF crBkOld = dc.GetBkColor();
  1844. COLORREF crTextOld = dc.GetTextColor();
  1845. COLORREF crText = ::GetSysColor(COLOR_BTNTEXT);
  1846. COLORREF crFace = ::GetSysColor(COLOR_3DFACE);
  1847. dc.SetBkColor(crFace);
  1848. dc.SetTextColor(crText);
  1849. // Draw the header label
  1850. CString sText(_T("%"));
  1851. ::DrawTextEx(dc.GetSafeHdc(), (LPTSTR)(LPCTSTR)sText, -1, m_rHeader,
  1852. DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS, NULL);
  1853. // Draw the percent label text
  1854. int i;
  1855. UINT nPercent;
  1856. CRect rText, rBullet;
  1857. rText.SetRect(m_rLabels.left, 0, m_rLabels.left + m_nCellWidth, rClient.bottom);
  1858. for (i=0; i<24; i++)
  1859. {
  1860. nPercent = m_pMatrix->GetPercentage(i,0);
  1861. // Don't draw percentages greater than 99
  1862. if (nPercent <= 99)
  1863. {
  1864. sText.Format(_T("%d"), nPercent);
  1865. ::DrawTextEx(dc.GetSafeHdc(), (LPTSTR)(LPCTSTR)sText, -1, rText,
  1866. DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS, NULL);
  1867. }
  1868. rText.OffsetRect(m_nCellWidth, 0);
  1869. }
  1870. dc.SetBkColor(crBkOld);
  1871. dc.SetTextColor(crTextOld);
  1872. if (pbrOld != NULL)
  1873. dc.SelectObject(pbrOld);
  1874. if (pOldFont != NULL)
  1875. dc.SelectObject(pOldFont);
  1876. // Do not call CWnd::OnPaint() for painting messages
  1877. }