Leaked source code of windows server 2003
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.

2252 lines
70 KiB

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