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.

1267 lines
30 KiB

  1. // HoursCtl.cpp : Implementation of the CHoursCtrl OLE control class.
  2. #include "stdafx.h"
  3. #include "Hours.h"
  4. #include "HoursCtl.h"
  5. #include "HoursPpg.h"
  6. #include <time.h>
  7. #include <sys\timeb.h>
  8. #ifdef _DEBUG
  9. //#define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. IMPLEMENT_DYNCREATE(CHoursCtrl, COleControl)
  14. //#ifdef DBCS
  15. // For localization
  16. // We hate hardcord resource
  17. // V-HIDEKK 1996.09.23
  18. USHORT CONTROL_WIDTH = 375;
  19. USHORT CONTROL_HEIGHT = 163;
  20. USHORT DAY_BUTTON_WIDTH = 83;
  21. USHORT HOUR_BUTTON_HEIGHT = 20;
  22. USHORT CELL_WIDTH = ((CONTROL_WIDTH - DAY_BUTTON_WIDTH) / 24);
  23. USHORT CELL_HEIGHT = ((CONTROL_HEIGHT - HOUR_BUTTON_HEIGHT) / 7);
  24. /*
  25. #else
  26. const USHORT CONTROL_WIDTH = 375;
  27. const USHORT CONTROL_HEIGHT = 163;
  28. const USHORT DAY_BUTTON_WIDTH = 83;
  29. const USHORT HOUR_BUTTON_HEIGHT = 20;
  30. const USHORT CELL_WIDTH = ((CONTROL_WIDTH - DAY_BUTTON_WIDTH) / 24);
  31. const USHORT CELL_HEIGHT = ((CONTROL_HEIGHT - HOUR_BUTTON_HEIGHT) / 7);
  32. #endif
  33. */
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Message map
  36. BEGIN_MESSAGE_MAP(CHoursCtrl, COleControl)
  37. //{{AFX_MSG_MAP(CHoursCtrl)
  38. ON_WM_CREATE()
  39. ON_WM_SETCURSOR()
  40. ON_WM_LBUTTONDOWN()
  41. ON_WM_LBUTTONUP()
  42. ON_WM_MOUSEMOVE()
  43. //}}AFX_MSG_MAP
  44. ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
  45. END_MESSAGE_MAP()
  46. /////////////////////////////////////////////////////////////////////////////
  47. // Dispatch map VT_ARRAY
  48. BEGIN_DISPATCH_MAP(CHoursCtrl, COleControl)
  49. //{{AFX_DISPATCH_MAP(CHoursCtrl)
  50. DISP_PROPERTY_NOTIFY(CHoursCtrl, "crPermitColor", m_crPermitColor, OnCrPermitColorChanged, VT_COLOR)
  51. DISP_PROPERTY_NOTIFY(CHoursCtrl, "crDenyColor", m_crDenyColor, OnCrDenyColorChanged, VT_COLOR)
  52. DISP_PROPERTY_EX(CHoursCtrl, "DateData", GetDateData, SetDateData, VT_VARIANT)
  53. //}}AFX_DISPATCH_MAP
  54. END_DISPATCH_MAP()
  55. /////////////////////////////////////////////////////////////////////////////
  56. // Event map
  57. BEGIN_EVENT_MAP(CHoursCtrl, COleControl)
  58. //{{AFX_EVENT_MAP(CHoursCtrl)
  59. //}}AFX_EVENT_MAP
  60. END_EVENT_MAP()
  61. /////////////////////////////////////////////////////////////////////////////
  62. // Property pages
  63. BEGIN_PROPPAGEIDS(CHoursCtrl, 1)
  64. PROPPAGEID(CHoursPropPage::guid)
  65. END_PROPPAGEIDS(CHoursCtrl)
  66. /////////////////////////////////////////////////////////////////////////////
  67. // Initialize class factory and guid
  68. IMPLEMENT_OLECREATE_EX(CHoursCtrl, "HOURS.HoursCtrl.1",
  69. 0xa44ea7ad, 0x9d58, 0x11cf, 0xa3, 0x5f, 0, 0xaa, 0, 0xb6, 0x74, 0x3b)
  70. /////////////////////////////////////////////////////////////////////////////
  71. // Type library ID and version
  72. IMPLEMENT_OLETYPELIB(CHoursCtrl, _tlid, _wVerMajor, _wVerMinor)
  73. /////////////////////////////////////////////////////////////////////////////
  74. // Interface IDs
  75. const IID BASED_CODE IID_DHours =
  76. { 0xa44ea7ab, 0x9d58, 0x11cf, { 0xa3, 0x5f, 0, 0xaa, 0, 0xb6, 0x74, 0x3b } };
  77. const IID BASED_CODE IID_DHoursEvents =
  78. { 0xa44ea7ac, 0x9d58, 0x11cf, { 0xa3, 0x5f, 0, 0xaa, 0, 0xb6, 0x74, 0x3b } };
  79. /////////////////////////////////////////////////////////////////////////////
  80. // Control type information
  81. static const DWORD BASED_CODE _dwHoursOleMisc =
  82. OLEMISC_ACTIVATEWHENVISIBLE |
  83. OLEMISC_SETCLIENTSITEFIRST |
  84. OLEMISC_INSIDEOUT |
  85. OLEMISC_CANTLINKINSIDE |
  86. OLEMISC_RECOMPOSEONRESIZE;
  87. IMPLEMENT_OLECTLTYPE(CHoursCtrl, IDS_HOURS, _dwHoursOleMisc)
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CHoursCtrl::CHoursCtrlFactory::UpdateRegistry -
  90. // Adds or removes system registry entries for CHoursCtrl
  91. BOOL CHoursCtrl::CHoursCtrlFactory::UpdateRegistry(BOOL bRegister)
  92. {
  93. // TODO: Verify that your control follows apartment-model threading rules.
  94. // Refer to MFC TechNote 64 for more information.
  95. // If your control does not conform to the apartment-model rules, then
  96. // you must modify the code below, changing the 6th parameter from
  97. // afxRegApartmentThreading to 0.
  98. if (bRegister)
  99. return AfxOleRegisterControlClass(
  100. AfxGetInstanceHandle(),
  101. m_clsid,
  102. m_lpszProgID,
  103. IDS_HOURS,
  104. IDB_HOURS,
  105. /* afxRegApartmentThreading, */0,
  106. _dwHoursOleMisc,
  107. _tlid,
  108. _wVerMajor,
  109. _wVerMinor);
  110. else
  111. return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  112. }
  113. /////////////////////////////////////////////////////////////////////////////
  114. // CHoursCtrl::CHoursCtrl - Constructor
  115. CHoursCtrl::CHoursCtrl()
  116. {
  117. InitializeIIDs(&IID_DHours, &IID_DHoursEvents);
  118. // regular font
  119. m_pFont = new CFont;
  120. LOGFONT lf;
  121. memset(&lf, 0, sizeof(LOGFONT)); // Clear out structure.
  122. //#ifdef DBCS
  123. // for localize
  124. // V-HIDEKK 1996.09.23
  125. CString csFontName,csFontSize;
  126. csFontName.LoadString(IDS_STR_FONTNAME);
  127. csFontSize.LoadString(IDS_STR_FONTSIZE);
  128. lf.lfHeight = _ttoi(csFontSize.GetBuffer(0));
  129. _tcscpy(lf.lfFaceName, csFontName.GetBuffer(0));
  130. /*
  131. #else
  132. lf.lfHeight = 15;
  133. _tcscpy(lf.lfFaceName, TEXT("Arial"));
  134. #endif
  135. */
  136. lf.lfWeight = 100;
  137. m_pFont->CreateFontIndirect(&lf); // Create the font.
  138. // create the individual 'cells' (m_sCells)
  139. USHORT x, y;
  140. x = HOUR_BUTTON_HEIGHT;
  141. y = DAY_BUTTON_WIDTH;
  142. CRect crOuter;
  143. USHORT sCount = 1;
  144. USHORT sRow = 1;
  145. USHORT sCol = 1;
  146. for (x = DAY_BUTTON_WIDTH; (x + CELL_WIDTH) < CONTROL_WIDTH; x += CELL_WIDTH)
  147. {
  148. for (y = HOUR_BUTTON_HEIGHT; (y + CELL_HEIGHT) < CONTROL_HEIGHT; y += CELL_HEIGHT)
  149. {
  150. m_sCell[sCount].x = x;
  151. m_sCell[sCount].y = y;
  152. m_sCell[sCount].cx = x + CELL_WIDTH + 1;
  153. m_sCell[sCount].cy = y + CELL_HEIGHT + 1;
  154. m_sCell[sCount].bVal = TRUE;
  155. m_sCell[sCount].row = sRow;
  156. m_sCell[sCount].col = sCol;
  157. m_sCell[sCount].bSelected = FALSE;
  158. sCount++;
  159. sRow++;
  160. }
  161. sRow = 1;
  162. sCol++;
  163. }
  164. // create the buttons
  165. // start with the days
  166. y = HOUR_BUTTON_HEIGHT;
  167. sRow = 0;
  168. while (sCount < 176)
  169. {
  170. m_sCell[sCount].x = 2;
  171. m_sCell[sCount].y = y;
  172. m_sCell[sCount].cx = m_sCell[sCount].x + DAY_BUTTON_WIDTH;
  173. m_sCell[sCount].cy = y + CELL_HEIGHT;
  174. m_sCell[sCount].bVal = TRUE;
  175. m_sCell[sCount].row = sRow;
  176. m_sCell[sCount].col = 0;
  177. m_sCell[sCount].bSelected = FALSE;
  178. sCount++;
  179. sRow++;
  180. //#ifdef DBCS
  181. // This is right!
  182. // V-HIDEKK 1996.09.23
  183. y += CELL_HEIGHT;
  184. /*
  185. #else
  186. y += HOUR_BUTTON_HEIGHT;
  187. #endif
  188. */
  189. }
  190. // 'select all' button
  191. m_sCell[sCount].x = 2;
  192. m_sCell[sCount].y = 2;
  193. m_sCell[sCount].cx = m_sCell[sCount].x + DAY_BUTTON_WIDTH;
  194. //#ifdef DBCS
  195. // This is right!
  196. // V-HIDEKK 1996.09.23
  197. m_sCell[sCount].cy = m_sCell[sCount].y + HOUR_BUTTON_HEIGHT;
  198. /*
  199. #else
  200. m_sCell[sCount].cy = m_sCell[sCount].y + CELL_HEIGHT;
  201. #endif
  202. */
  203. m_sCell[sCount].bVal = TRUE;
  204. m_sCell[sCount].row = 0;
  205. m_sCell[sCount].col = 0;
  206. m_sCell[sCount].bSelected = FALSE;
  207. //#ifdef DBCS
  208. // This is right!
  209. // V-HIDEKK 1996.09.23
  210. x = DAY_BUTTON_WIDTH;
  211. /*
  212. #else
  213. x = 83;
  214. #endif
  215. */
  216. sCount++;
  217. while (sCount < 201)
  218. {
  219. m_sCell[sCount].x = x;
  220. m_sCell[sCount].y = 2;
  221. m_sCell[sCount].cx = x + CELL_WIDTH;
  222. //#ifdef DBCS
  223. // This is right!
  224. // V-HIDEKK 1996.09.23
  225. m_sCell[sCount].cy = m_sCell[sCount].y + HOUR_BUTTON_HEIGHT;
  226. /*
  227. #else
  228. m_sCell[sCount].cy = m_sCell[sCount].y + CELL_HEIGHT;
  229. #endif
  230. */
  231. m_sCell[sCount].bVal = TRUE;
  232. m_sCell[sCount].row = sRow;
  233. m_sCell[sCount].col = 0;
  234. m_sCell[sCount].bSelected = FALSE;
  235. sCount++;
  236. sRow++;
  237. x += CELL_WIDTH;
  238. }
  239. m_sCurrentRow = 1;
  240. m_sCurrentCol = 1;
  241. bToggle = TRUE;
  242. // set default color values
  243. m_crPermitColor = GetSysColor(COLOR_ACTIVECAPTION);
  244. m_crDenyColor = GetSysColor(COLOR_CAPTIONTEXT);
  245. }
  246. /////////////////////////////////////////////////////////////////////////////
  247. // CHoursCtrl::~CHoursCtrl - Destructor
  248. CHoursCtrl::~CHoursCtrl()
  249. {
  250. // remove button CFont*
  251. if (m_pFont != NULL) delete m_pFont;
  252. }
  253. /////////////////////////////////////////////////////////////////////////////
  254. // CHoursCtrl::OnDraw - Drawing function
  255. void CHoursCtrl::OnDraw(
  256. CDC* pDC, const CRect& rcBounds, const CRect& rcInvalid)
  257. {
  258. // create pen for the grid lines
  259. CPen pBlackPen(PS_SOLID, 1, RGB(0,0,0));
  260. CPen* pOriginalPen = (CPen*)pDC->SelectObject(pBlackPen);
  261. // create the two brushes for allowed color and denied color
  262. CBrush* pAllowedBrush = new CBrush;
  263. pAllowedBrush->CreateSolidBrush(m_crPermitColor);
  264. CBrush* pDeniedBrush = new CBrush;
  265. pDeniedBrush->CreateSolidBrush(m_crDenyColor);
  266. CBrush* pDragBrush = new CBrush;
  267. pDragBrush->CreateHatchBrush(HS_BDIAGONAL, GetSysColor(COLOR_ACTIVECAPTION));
  268. USHORT sCount = 1;
  269. CRect crOuter;
  270. pDC->SetBkColor(GetSysColor(COLOR_BTNFACE));
  271. // draw the grid
  272. while (sCount < 169)
  273. {
  274. crOuter = CRect(m_sCell[sCount].x,
  275. m_sCell[sCount].y,
  276. m_sCell[sCount].cx,
  277. m_sCell[sCount].cy);
  278. CRect crInterSect = (rcInvalid & crOuter);
  279. if (!crInterSect.IsRectNull())
  280. {
  281. pDC->Rectangle(&crOuter);
  282. crOuter.DeflateRect(1, 1);
  283. if (m_sCell[sCount].bSelected) pDC->FillRect(&crOuter, pDragBrush);
  284. else pDC->FillRect(&crOuter, (m_sCell[sCount].bVal ? pAllowedBrush : pDeniedBrush));
  285. if ((m_sCurrentRow && m_sCurrentCol) && (sCount == m_sCurrentLoc())) // is this the 'selected' cell?
  286. {
  287. crOuter.DeflateRect(2, 4);
  288. pDC->DrawFocusRect(&crOuter);
  289. }
  290. }
  291. sCount++;
  292. }
  293. delete pAllowedBrush;
  294. delete pDeniedBrush;
  295. delete pDragBrush;
  296. // draw the surrounding buttons
  297. CBrush* pButtonBrush = new CBrush;
  298. pButtonBrush->CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  299. CPen pWhitePen(PS_SOLID, 1, RGB(255, 255, 255));
  300. pOriginalPen = (CPen*)pDC->SelectObject(pWhitePen);
  301. CPen pDkGreyPen(PS_SOLID, 1, RGB(128, 128, 128));
  302. CPen pLtGreyPen(PS_SOLID, 1, RGB(196, 196, 196));
  303. CFont* pOldFont = pDC->SelectObject(m_pFont);
  304. while (sCount < 176) // start with the days of the week
  305. {
  306. crOuter = CRect(m_sCell[sCount].x,
  307. m_sCell[sCount].y,
  308. m_sCell[sCount].cx,
  309. m_sCell[sCount].cy);
  310. CRect crInterSect = (rcInvalid & crOuter);
  311. if (!crInterSect.IsRectNull())
  312. {
  313. crOuter.DeflateRect(1, 1);
  314. pDC->FillRect(&crOuter, pButtonBrush);
  315. if (m_sCell[sCount].bVal)
  316. {
  317. pDC->SelectObject(pWhitePen);
  318. pDC->MoveTo(m_sCell[sCount].x, m_sCell[sCount].cy - 1);
  319. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].y + 1);
  320. pDC->LineTo(m_sCell[sCount].cx - 2, m_sCell[sCount].y + 1);
  321. pDC->SelectObject(pBlackPen);
  322. pDC->LineTo(m_sCell[sCount].cx - 2, m_sCell[sCount].cy);
  323. pDC->LineTo(m_sCell[sCount].x - 1, m_sCell[sCount].cy);
  324. pDC->SelectObject(pDkGreyPen);
  325. pDC->MoveTo(m_sCell[sCount].cx - 3, m_sCell[sCount].y + 2);
  326. pDC->LineTo(m_sCell[sCount].cx - 3, m_sCell[sCount].cy - 1);
  327. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].cy - 1);
  328. }
  329. else
  330. {
  331. pDC->SelectObject(pBlackPen);
  332. pDC->MoveTo(m_sCell[sCount].x, m_sCell[sCount].cy - 1);
  333. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].y + 1);
  334. pDC->LineTo(m_sCell[sCount].cx - 2, m_sCell[sCount].y + 1);
  335. pDC->SelectObject(pWhitePen);
  336. pDC->MoveTo(m_sCell[sCount].cx - 2, m_sCell[sCount].cy);
  337. pDC->LineTo(m_sCell[sCount].x - 1, m_sCell[sCount].cy);
  338. pDC->SelectObject(pLtGreyPen);
  339. pDC->MoveTo(m_sCell[sCount].cx - 3, m_sCell[sCount].y + 2);
  340. pDC->LineTo(m_sCell[sCount].cx - 3, m_sCell[sCount].cy - 1);
  341. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].cy - 1);
  342. }
  343. pDC->SetBkMode(TRANSPARENT);
  344. crOuter.DeflateRect(3, 2);
  345. if (m_sCell[sCount].bVal)
  346. pDC->DrawText(csDay[sCount - 169],
  347. &crOuter,
  348. DT_CENTER);
  349. else
  350. {
  351. crOuter.OffsetRect(1, 1);
  352. pDC->DrawText(csDay[sCount - 169],
  353. &crOuter,
  354. DT_CENTER);
  355. }
  356. // current selection?
  357. if ((m_sCurrentCol == 0) && (m_sCurrentRow == sCount - 168))
  358. {
  359. CRect crSelection = CRect(m_sCell[sCount].x,
  360. m_sCell[sCount].y,
  361. m_sCell[sCount].cx,
  362. m_sCell[sCount].cy);
  363. crSelection.DeflateRect(5, 5);
  364. pDC->DrawFocusRect(&crSelection);
  365. }
  366. }
  367. sCount++;
  368. }
  369. // 'select all' button
  370. crOuter = CRect(m_sCell[sCount].x,
  371. m_sCell[sCount].y,
  372. m_sCell[sCount].cx + 1,
  373. m_sCell[sCount].cy + 1);
  374. CRect crInterSect = (rcInvalid & crOuter);
  375. if (!crInterSect.IsRectNull())
  376. {
  377. crOuter.DeflateRect(1, 1);
  378. pDC->FillRect(&crOuter, pButtonBrush);
  379. if (m_sCell[sCount].bVal)
  380. {
  381. pDC->SelectObject(pWhitePen);
  382. pDC->MoveTo(m_sCell[sCount].x, m_sCell[sCount].cy - 1);
  383. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].y);
  384. pDC->LineTo(m_sCell[sCount].cx - 2, m_sCell[sCount].y);
  385. pDC->SelectObject(pBlackPen);
  386. pDC->LineTo(m_sCell[sCount].cx - 2, m_sCell[sCount].cy - 2);
  387. pDC->LineTo(m_sCell[sCount].x - 1, m_sCell[sCount].cy - 2);
  388. pDC->SelectObject(pDkGreyPen);
  389. pDC->MoveTo(m_sCell[sCount].cx - 3, m_sCell[sCount].y + 1);
  390. pDC->LineTo(m_sCell[sCount].cx - 3, m_sCell[sCount].cy - 3);
  391. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].cy - 3);
  392. }
  393. else
  394. {
  395. pDC->SelectObject(pBlackPen);
  396. pDC->MoveTo(m_sCell[sCount].x, m_sCell[sCount].cy - 1);
  397. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].y);
  398. pDC->LineTo(m_sCell[sCount].cx - 2, m_sCell[sCount].y);
  399. pDC->SelectObject(pWhitePen);
  400. pDC->LineTo(m_sCell[sCount].cx - 2, m_sCell[sCount].cy - 2);
  401. pDC->LineTo(m_sCell[sCount].x - 1, m_sCell[sCount].cy - 2);
  402. pDC->SelectObject(pLtGreyPen);
  403. pDC->MoveTo(m_sCell[sCount].cx - 3, m_sCell[sCount].y + 1);
  404. pDC->LineTo(m_sCell[sCount].cx - 3, m_sCell[sCount].cy - 3);
  405. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].cy - 3);
  406. }
  407. // current selection?
  408. if ((m_sCurrentCol == 0) && (m_sCurrentRow == 0))
  409. {
  410. CRect crSelection = CRect(m_sCell[sCount].x,
  411. m_sCell[sCount].y,
  412. m_sCell[sCount].cx,
  413. m_sCell[sCount].cy);
  414. crSelection.DeflateRect(5, 5);
  415. pDC->DrawFocusRect(&crSelection);
  416. }
  417. }
  418. sCount++;
  419. // finish with col headers
  420. while (sCount < 201)
  421. {
  422. crOuter = CRect(m_sCell[sCount].x,
  423. m_sCell[sCount].y,
  424. m_sCell[sCount].cx,
  425. m_sCell[sCount].cy);
  426. CRect crInterSect = (rcInvalid & crOuter);
  427. if (!crInterSect.IsRectNull())
  428. {
  429. crOuter.DeflateRect(1, 1);
  430. pDC->FillRect(&crOuter, pButtonBrush);
  431. if (m_sCell[sCount].bVal)
  432. {
  433. pDC->SelectObject(pWhitePen);
  434. pDC->MoveTo(m_sCell[sCount].x + 1, m_sCell[sCount].cy - 2);
  435. pDC->LineTo(m_sCell[sCount].x + 1, m_sCell[sCount].y);
  436. pDC->LineTo(m_sCell[sCount].cx, m_sCell[sCount].y);
  437. pDC->SelectObject(pBlackPen);
  438. pDC->LineTo(m_sCell[sCount].cx, m_sCell[sCount].cy - 2);
  439. pDC->LineTo(m_sCell[sCount].x - 1, m_sCell[sCount].cy - 2);
  440. pDC->SelectObject(pDkGreyPen);
  441. pDC->MoveTo(m_sCell[sCount].cx - 1, m_sCell[sCount].y + 1);
  442. pDC->LineTo(m_sCell[sCount].cx - 1, m_sCell[sCount].cy - 3);
  443. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].cy - 3);
  444. }
  445. else
  446. {
  447. pDC->SelectObject(pBlackPen);
  448. pDC->MoveTo(m_sCell[sCount].x + 1, m_sCell[sCount].cy - 2);
  449. pDC->LineTo(m_sCell[sCount].x + 1, m_sCell[sCount].y);
  450. pDC->LineTo(m_sCell[sCount].cx, m_sCell[sCount].y);
  451. pDC->SelectObject(pWhitePen);
  452. pDC->LineTo(m_sCell[sCount].cx, m_sCell[sCount].cy - 2);
  453. pDC->LineTo(m_sCell[sCount].x - 1, m_sCell[sCount].cy - 2);
  454. pDC->SelectObject(pLtGreyPen);
  455. pDC->MoveTo(m_sCell[sCount].cx - 1, m_sCell[sCount].y + 1);
  456. pDC->LineTo(m_sCell[sCount].cx - 1, m_sCell[sCount].cy - 3);
  457. pDC->LineTo(m_sCell[sCount].x, m_sCell[sCount].cy - 3);
  458. }
  459. // current selection?
  460. if ((m_sCurrentCol == sCount - 176) && (m_sCurrentRow == 0))
  461. {
  462. CRect crSelection = CRect(m_sCell[sCount].x,
  463. m_sCell[sCount].y,
  464. m_sCell[sCount].cx,
  465. m_sCell[sCount].cy);
  466. crSelection.DeflateRect(3, 3);
  467. pDC->DrawFocusRect(&crSelection);
  468. }
  469. }
  470. sCount++;
  471. }
  472. delete pButtonBrush;
  473. pDC->SelectObject(pOldFont);
  474. // draw the border
  475. pDC->SelectObject(pBlackPen);
  476. pDC->MoveTo(1, rcBounds.BottomRight().y - 1);
  477. pDC->LineTo(rcBounds.TopLeft().x + 1, rcBounds.TopLeft().y + 1);
  478. pDC->LineTo(rcBounds.BottomRight().x + 1, 1);
  479. pDC->SelectObject(pDkGreyPen);
  480. pDC->MoveTo(0, rcBounds.BottomRight().y);
  481. pDC->LineTo(rcBounds.TopLeft().x, rcBounds.TopLeft().y);
  482. pDC->LineTo(rcBounds.BottomRight().x, 0);
  483. pDC->SelectObject(pWhitePen);
  484. pDC->MoveTo(1, rcBounds.BottomRight().y - 1);
  485. pDC->LineTo(rcBounds.BottomRight().x - 1, rcBounds.BottomRight().y - 1);
  486. pDC->LineTo(rcBounds.BottomRight().x - 1, 0);
  487. pDC->SelectObject(pLtGreyPen);
  488. pDC->MoveTo(2, rcBounds.BottomRight().y - 2);
  489. pDC->LineTo(rcBounds.BottomRight().x - 2, rcBounds.BottomRight().y - 2);
  490. pDC->LineTo(rcBounds.BottomRight().x - 2, 2);
  491. }
  492. /////////////////////////////////////////////////////////////////////////////
  493. // CHoursCtrl::DoPropExchange - Persistence support
  494. void CHoursCtrl::DoPropExchange(CPropExchange* pPX)
  495. {
  496. ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  497. COleControl::DoPropExchange(pPX);
  498. }
  499. /////////////////////////////////////////////////////////////////////////////
  500. // CHoursCtrl::OnResetState - Reset control to default state
  501. void CHoursCtrl::OnResetState()
  502. {
  503. COleControl::OnResetState(); // Resets defaults found in DoPropExchange
  504. }
  505. /////////////////////////////////////////////////////////////////////////////
  506. // CHoursCtrl message handlers
  507. int CHoursCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
  508. {
  509. //#ifdef DBCS
  510. // for debug and localize
  511. // We need this code. because dialog-size changed for RL (addusrw.exe)
  512. // HardCord size mismatched
  513. // V-HIDEKK 1996.09.23
  514. CString csButtonWidth;
  515. csButtonWidth.LoadString(IDS_STR_BUTTONWIDTH);
  516. DAY_BUTTON_WIDTH = (USHORT)_ttoi(csButtonWidth.GetBuffer(0));
  517. CONTROL_WIDTH = (USHORT)lpCreateStruct->cx;
  518. CONTROL_HEIGHT = (USHORT)lpCreateStruct->cy;
  519. HOUR_BUTTON_HEIGHT = CONTROL_HEIGHT/8 + CONTROL_HEIGHT%8 - 3;
  520. CELL_WIDTH = ((CONTROL_WIDTH - DAY_BUTTON_WIDTH) / 24);
  521. CELL_HEIGHT = ((CONTROL_HEIGHT - HOUR_BUTTON_HEIGHT) / 7);
  522. // create the individual 'cells' (m_sCells)
  523. USHORT x, y;
  524. x = HOUR_BUTTON_HEIGHT;
  525. y = DAY_BUTTON_WIDTH;
  526. CRect crOuter;
  527. USHORT sCount = 1;
  528. USHORT sRow = 1;
  529. USHORT sCol = 1;
  530. for (x = DAY_BUTTON_WIDTH; (x + CELL_WIDTH) < CONTROL_WIDTH; x += CELL_WIDTH)
  531. {
  532. for (y = HOUR_BUTTON_HEIGHT; (y + CELL_HEIGHT) < CONTROL_HEIGHT; y += CELL_HEIGHT)
  533. {
  534. m_sCell[sCount].x = x;
  535. m_sCell[sCount].y = y;
  536. m_sCell[sCount].cx = x + CELL_WIDTH + 1;
  537. m_sCell[sCount].cy = y + CELL_HEIGHT + 1;
  538. m_sCell[sCount].bVal = TRUE;
  539. m_sCell[sCount].row = sRow;
  540. m_sCell[sCount].col = sCol;
  541. m_sCell[sCount].bSelected = FALSE;
  542. sCount++;
  543. sRow++;
  544. }
  545. sRow = 1;
  546. sCol++;
  547. }
  548. // create the buttons
  549. // start with the days
  550. y = HOUR_BUTTON_HEIGHT;
  551. sRow = 0;
  552. while (sCount < 176)
  553. {
  554. m_sCell[sCount].x = 2;
  555. m_sCell[sCount].y = y;
  556. m_sCell[sCount].cx = m_sCell[sCount].x + DAY_BUTTON_WIDTH;
  557. m_sCell[sCount].cy = y + CELL_HEIGHT;
  558. m_sCell[sCount].bVal = TRUE;
  559. m_sCell[sCount].row = sRow;
  560. m_sCell[sCount].col = 0;
  561. m_sCell[sCount].bSelected = FALSE;
  562. sCount++;
  563. sRow++;
  564. y += CELL_HEIGHT;
  565. }
  566. // 'select all' button
  567. m_sCell[sCount].x = 2;
  568. m_sCell[sCount].y = 2;
  569. m_sCell[sCount].cx = m_sCell[sCount].x + DAY_BUTTON_WIDTH;
  570. m_sCell[sCount].cy = m_sCell[sCount].y + HOUR_BUTTON_HEIGHT;
  571. m_sCell[sCount].bVal = TRUE;
  572. m_sCell[sCount].row = 0;
  573. m_sCell[sCount].col = 0;
  574. m_sCell[sCount].bSelected = FALSE;
  575. x = DAY_BUTTON_WIDTH;
  576. sCount++;
  577. while (sCount < 201)
  578. {
  579. m_sCell[sCount].x = x;
  580. m_sCell[sCount].y = 2;
  581. m_sCell[sCount].cx = x + CELL_WIDTH;
  582. m_sCell[sCount].cy = m_sCell[sCount].y + HOUR_BUTTON_HEIGHT;
  583. m_sCell[sCount].bVal = TRUE;
  584. m_sCell[sCount].row = sRow;
  585. m_sCell[sCount].col = 0;
  586. m_sCell[sCount].bSelected = FALSE;
  587. sCount++;
  588. sRow++;
  589. x += CELL_WIDTH;
  590. }
  591. //#endif
  592. if (COleControl::OnCreate(lpCreateStruct) == -1)
  593. return -1;
  594. // load the text for the day buttons
  595. csDay[0].LoadString(IDS_SUNDAY);
  596. csDay[1].LoadString(IDS_MONDAY);
  597. csDay[2].LoadString(IDS_TUESDAY);
  598. csDay[3].LoadString(IDS_WEDNESDAY);
  599. csDay[4].LoadString(IDS_THURSDAY);
  600. csDay[5].LoadString(IDS_FRIDAY);
  601. csDay[6].LoadString(IDS_SATURDAY);
  602. return 0;
  603. }
  604. // make the cursor over the control into the '+' sign
  605. BOOL CHoursCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  606. {
  607. ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
  608. return TRUE;
  609. }
  610. // trap lButton clicks to toggle single cells
  611. void CHoursCtrl::OnLButtonDown(UINT nFlags, CPoint point)
  612. {
  613. // invalidate the previous selection
  614. InvalidateCell(m_sCurrentLoc());
  615. Click(point);
  616. pointDrag = point;
  617. USHORT sCount = 1;
  618. // clear out the old drag selection(s)
  619. while (sCount < 168)
  620. {
  621. if (m_sCell[sCount].bSelected)
  622. {
  623. m_sCell[sCount].bSelected = FALSE;
  624. InvalidateCell(sCount);
  625. }
  626. sCount++;
  627. }
  628. // COleControl::OnLButtonDown(nFlags, point);
  629. }
  630. void CHoursCtrl::InvalidateCell(USHORT sCellID)
  631. {
  632. CRect crCell = CRect(m_sCell[sCellID].x,
  633. m_sCell[sCellID].y,
  634. m_sCell[sCellID].cx,
  635. m_sCell[sCellID].cy);
  636. InvalidateRect(crCell);
  637. }
  638. void CHoursCtrl::OnMouseMove(UINT nFlags, CPoint point)
  639. {
  640. if (nFlags == MK_LBUTTON)
  641. {
  642. USHORT sEndCell = GetCellID(point);
  643. USHORT sStartCell = GetCellID(pointDrag);
  644. //#ifdef DBCS
  645. // If sEndCell==0, this cell is invalid
  646. // It seems this like better!
  647. // V-HIDEKK 1996.09.23
  648. if (sStartCell == sEndCell || !sEndCell ) return;
  649. /*
  650. #else
  651. if (sStartCell == sEndCell) return;
  652. #endif
  653. */
  654. CRect crSelected = CRect(min(m_sCell[sStartCell].x, m_sCell[sEndCell].x),
  655. min(m_sCell[sStartCell].y, m_sCell[sEndCell].y),
  656. max(m_sCell[sStartCell].x, m_sCell[sEndCell].x) + CELL_WIDTH,
  657. max(m_sCell[sStartCell].y, m_sCell[sEndCell].y) + CELL_HEIGHT);
  658. USHORT sCount = 0;
  659. // clear out the old selection
  660. while (sCount < 169)
  661. {
  662. if (!crSelected.PtInRect(CPoint(m_sCell[sCount].x + 1, m_sCell[sCount].y + 1)))
  663. {
  664. if (m_sCell[sCount].bSelected)
  665. {
  666. m_sCell[sCount].bSelected = FALSE;
  667. InvalidateCell(sCount);
  668. }
  669. }
  670. else
  671. {
  672. if (!m_sCell[sCount].bSelected)
  673. {
  674. m_sCell[sCount].bSelected = TRUE;
  675. InvalidateCell(sCount);
  676. }
  677. }
  678. sCount++;
  679. }
  680. }
  681. COleControl::OnMouseMove(nFlags, point);
  682. }
  683. void CHoursCtrl::OnLButtonUp(UINT nFlags, CPoint point)
  684. {
  685. USHORT sEndCell = GetCellID(point);
  686. USHORT sStartCell = GetCellID(pointDrag);
  687. //#ifdef DBCS
  688. // If sEndCell==0, this cell is invalid
  689. // It seems this like better!
  690. // V-HIDEKK 1996.09.23
  691. if (sStartCell == sEndCell || !sEndCell ) return;
  692. /*
  693. #else
  694. if (sStartCell == sEndCell) return;
  695. #endif
  696. */
  697. CRect crSelected = CRect(min(m_sCell[sStartCell].x, m_sCell[sEndCell].x),
  698. min(m_sCell[sStartCell].y, m_sCell[sEndCell].y),
  699. max(m_sCell[sStartCell].x, m_sCell[sEndCell].x) + CELL_WIDTH,
  700. max(m_sCell[sStartCell].y, m_sCell[sEndCell].y) + CELL_HEIGHT);
  701. // first get the avg
  702. short sTmp = 0;
  703. USHORT sCount = 0;
  704. while (sCount < 169)
  705. {
  706. if (crSelected.PtInRect(CPoint(m_sCell[sCount].x + 1, m_sCell[sCount].y + 1)))
  707. {
  708. if (m_sCell[sCount].bVal) sTmp++;
  709. else sTmp--;
  710. }
  711. sCount++;
  712. }
  713. BOOL bNewVal;
  714. if (sTmp >= 0) bNewVal = FALSE;
  715. else bNewVal = TRUE;
  716. sCount = 0;
  717. // now change them all to be !the average
  718. // first get the avg
  719. while (sCount < 169)
  720. {
  721. if (crSelected.PtInRect(CPoint(m_sCell[sCount].x + 1, m_sCell[sCount].y + 1)))
  722. {
  723. m_sCell[sCount].bVal = bNewVal;
  724. m_sCell[sCount].bSelected = FALSE;
  725. InvalidateCell(sCount);
  726. }
  727. sCount++;
  728. }
  729. COleControl::OnLButtonUp(nFlags, point);
  730. }
  731. USHORT CHoursCtrl::GetCellID(CPoint point)
  732. {
  733. USHORT sCount = 1;
  734. // big grid?
  735. CRect crOuter;
  736. while (sCount < 169)
  737. {
  738. crOuter = CRect(m_sCell[sCount].x,
  739. m_sCell[sCount].y,
  740. m_sCell[sCount].x + CELL_WIDTH + 1,
  741. m_sCell[sCount].y + CELL_HEIGHT + 1);
  742. if (crOuter.PtInRect(point)) return sCount;
  743. sCount++;
  744. }
  745. // day button?
  746. while (sCount < 176)
  747. {
  748. crOuter = CRect(m_sCell[sCount].x,
  749. m_sCell[sCount].y,
  750. m_sCell[sCount].x + DAY_BUTTON_WIDTH + 1,
  751. m_sCell[sCount].y + CELL_HEIGHT + 1);
  752. if (crOuter.PtInRect(point)) return sCount;
  753. sCount++;
  754. }
  755. // big button?
  756. crOuter = CRect(m_sCell[sCount].x,
  757. m_sCell[sCount].y,
  758. m_sCell[sCount].x + DAY_BUTTON_WIDTH + 1,
  759. //#ifdef DBCS
  760. // It seems this is right!
  761. // V-HIDEKK 1996.09.23
  762. m_sCell[sCount].y + HOUR_BUTTON_HEIGHT + 1 ); //CELL_HEIGHT + 1);
  763. /*
  764. #else
  765. m_sCell[sCount].y + CELL_HEIGHT + 1);
  766. #endif
  767. */
  768. if (crOuter.PtInRect(point)) return sCount;
  769. // column button?
  770. while (sCount < 201)
  771. {
  772. crOuter = CRect(m_sCell[sCount].x,
  773. m_sCell[sCount].y,
  774. m_sCell[sCount].x + CELL_WIDTH + 1,
  775. //#ifdef DBCS
  776. // It seems this is right!
  777. // V-HIDEKK 1996.09.23
  778. m_sCell[sCount].y + HOUR_BUTTON_HEIGHT + 1 ); //CELL_HEIGHT + 1);
  779. /*
  780. #else
  781. m_sCell[sCount].y + CELL_HEIGHT + 1);
  782. #endif
  783. */
  784. if (crOuter.PtInRect(point)) return sCount;
  785. sCount++;
  786. }
  787. return 0;
  788. }
  789. void CHoursCtrl::Click(CPoint point)
  790. {
  791. USHORT sCount = 0;
  792. CRect crOuter;
  793. USHORT sCell = GetCellID(point);
  794. //#ifdef DBCS
  795. // Fix: Invalid Area clicked, then AV occurred.
  796. // sCell==0 is Invalid Cell
  797. // V-HIDEKK 1996.09.23
  798. if( !sCell )
  799. return;
  800. //#endif
  801. m_sCurrentRow = m_sCell[sCell].row;
  802. m_sCurrentCol = m_sCell[sCell].col;
  803. //#ifdef DBCS
  804. // Fix: most right-bottom area can not selected
  805. // Where is sCell==168 ?
  806. // This is RIGHT!
  807. // V-HIDEKK 1996.09.23
  808. if (sCell < 169) m_sCell[sCell].bVal = !m_sCell[sCell].bVal;
  809. /*
  810. #else
  811. if (sCell < 168) m_sCell[sCell].bVal = !m_sCell[sCell].bVal;
  812. #endif
  813. */
  814. InvalidateCell(sCell);
  815. // if we clicked on a button toggle its value and redraw
  816. if (sCell > 168)
  817. {
  818. if ((sCell > 168) && (sCell < 176)) // day button
  819. ToggleDay(sCell - 168);
  820. else if (sCell == 176) // toggle all
  821. OnBigButton();
  822. else // column header
  823. ToggleCol(sCell - 177);
  824. }
  825. }
  826. // toggle the values of a row (by day)
  827. void CHoursCtrl::ToggleDay(UINT nID)
  828. {
  829. USHORT sCount;
  830. CRect crOuter;
  831. for (sCount = (USHORT)nID; sCount < 169; sCount += 7)
  832. {
  833. m_sCell[sCount].bVal = !m_sCell[nID + 168].bVal;
  834. InvalidateCell(sCount);
  835. }
  836. m_sCell[nID + 168].bVal = !m_sCell[nID + 168].bVal;
  837. m_sCurrentRow = (USHORT)nID;
  838. m_sCurrentCol = 0;
  839. }
  840. // toggle the values of a column
  841. void CHoursCtrl::ToggleCol(UINT nID)
  842. {
  843. USHORT sCount;
  844. CRect crOuter;
  845. m_sCurrentRow = 0;
  846. m_sCurrentCol = nID + 1;
  847. USHORT sVal = nID + 177;
  848. nID *= 7;
  849. for (sCount = 1; sCount < 8; sCount += 1)
  850. {
  851. m_sCell[sCount + nID].bVal = !m_sCell[sVal].bVal;
  852. InvalidateCell(sCount + nID);
  853. }
  854. m_sCell[sVal].bVal = !m_sCell[sVal].bVal;
  855. }
  856. // toggle the whole page
  857. void CHoursCtrl::OnBigButton()
  858. {
  859. USHORT sCount;
  860. CRect crOuter;
  861. m_sCurrentRow = 0;
  862. m_sCurrentCol = 0;
  863. for (sCount = 1; sCount < 169; sCount ++)
  864. {
  865. m_sCell[sCount].bVal = !m_sCell[176].bVal;
  866. InvalidateCell(sCount);
  867. }
  868. m_sCell[176].bVal = !m_sCell[176].bVal;
  869. }
  870. BOOL CHoursCtrl::PreTranslateMessage(LPMSG lpmsg)
  871. {
  872. BOOL bHandleNow = FALSE;
  873. CRect crOld, crNew;
  874. switch (lpmsg->message)
  875. {
  876. case WM_KEYDOWN:
  877. switch (lpmsg->wParam)
  878. {
  879. case VK_SPACE: // toggle the cell under the dot
  880. {
  881. short sOldCell = m_sCurrentLoc();
  882. //#ifdef DBCS
  883. // FIX: most left hours button can not selected.
  884. // It seems rectangle mismatched.
  885. // V-HIDEKK 1996.09.23
  886. Click(CPoint(m_sCell[sOldCell].x + 5, m_sCell[sOldCell].y + 5));
  887. /*
  888. #else
  889. Click(CPoint(m_sCell[sOldCell].x + 1, m_sCell[sOldCell].y + 1));
  890. #endif
  891. */
  892. bHandleNow = TRUE;
  893. break;
  894. }
  895. case VK_UP:
  896. {
  897. // first store the old cell pos so we can erase it
  898. short sOldCell = m_sCurrentLoc();
  899. // move the carat to the new cell
  900. m_sCurrentRow--;
  901. if (m_sCurrentRow < 0) m_sCurrentRow = 7;
  902. // now draw the new cell
  903. short sNewCell = m_sCurrentLoc();
  904. InvalidateCell(sOldCell);
  905. InvalidateCell(sNewCell);
  906. bHandleNow = TRUE;
  907. break;
  908. }
  909. case VK_DOWN:
  910. {
  911. short sOldCell = m_sCurrentLoc();
  912. m_sCurrentRow++;
  913. if (m_sCurrentRow > 7) m_sCurrentRow = 0;
  914. short sNewCell = m_sCurrentLoc();
  915. InvalidateCell(sOldCell);
  916. InvalidateCell(sNewCell);
  917. bHandleNow = TRUE;
  918. break;
  919. }
  920. case VK_LEFT:
  921. {
  922. short sOldCell = m_sCurrentLoc();
  923. m_sCurrentCol--;
  924. if (m_sCurrentCol < 0) m_sCurrentCol = 24;
  925. short sNewCell = m_sCurrentLoc();
  926. InvalidateCell(sOldCell);
  927. InvalidateCell(sNewCell);
  928. bHandleNow = TRUE;
  929. break;
  930. }
  931. case VK_RIGHT:
  932. {
  933. short sOldCell = m_sCurrentLoc();
  934. m_sCurrentCol++;
  935. if (m_sCurrentCol > 24) m_sCurrentCol = 0;
  936. short sNewCell = m_sCurrentLoc();
  937. InvalidateCell(sOldCell);
  938. InvalidateCell(sNewCell);
  939. bHandleNow = TRUE;
  940. break;
  941. }
  942. }
  943. }
  944. return bHandleNow;
  945. }
  946. short CHoursCtrl::m_sCurrentLoc()
  947. {
  948. if (!m_sCurrentCol && !m_sCurrentRow) // select all button
  949. return 176;
  950. else if (!m_sCurrentCol)
  951. return m_sCurrentRow + 168;
  952. else if (!m_sCurrentRow)
  953. return m_sCurrentCol + 176;
  954. return ((max(m_sCurrentCol - 1, 0) * 7) + m_sCurrentRow);
  955. }
  956. // these are triggered when the client app changes one of the exported properties
  957. void CHoursCtrl::OnCrPermitColorChanged()
  958. {
  959. Invalidate();
  960. SetModifiedFlag();
  961. }
  962. void CHoursCtrl::OnCrDenyColorChanged()
  963. {
  964. Invalidate();
  965. SetModifiedFlag();
  966. }
  967. VARIANT CHoursCtrl::GetDateData()
  968. {
  969. VARIANT vaResult;
  970. VariantInit(&vaResult);
  971. vaResult.vt = VT_ARRAY | VT_UI1;
  972. SAFEARRAYBOUND sab[1];
  973. sab[0].cElements = 21;
  974. sab[0].lLbound = 0;
  975. vaResult.parray = SafeArrayCreate(VT_UI1, 1, sab);
  976. // load constant offsets into an array
  977. DWORD dwOffset[8];
  978. USHORT sCount;
  979. short sVal = 1;
  980. for (sCount = 0; sCount < 8; sCount++)
  981. {
  982. dwOffset[sCount] = sVal;
  983. sVal = sVal << 1;
  984. }
  985. // find the diff between current time and GMT (UTC)
  986. struct _timeb tstruct;
  987. _tzset();
  988. _ftime( &tstruct );
  989. // time difference in "seconds moving westward" - this is the amount of hours to add to the
  990. // listbox values to get GMT
  991. short sHourDiff = tstruct.timezone / 60;
  992. sCount = 0;
  993. short sOffset = 0;
  994. // adjust for GMT
  995. if (sHourDiff != 0)
  996. {
  997. sOffset += (sHourDiff % 8);
  998. sCount = (int)(sHourDiff / 8);
  999. }
  1000. USHORT sCount2 = 1; // address 0 is used elsewhere
  1001. USHORT sBase;
  1002. BYTE bRet[21];
  1003. ZeroMemory(bRet, 21);
  1004. for (sBase = 1; sBase < 8; sBase++)
  1005. {
  1006. sCount2 = sBase;
  1007. while (sCount2 < 169)
  1008. {
  1009. if (m_sCell[sCount2].bVal) // 1 = marked
  1010. bRet[sCount] |= dwOffset[sOffset];
  1011. sOffset++;
  1012. if (sOffset > 7)
  1013. {
  1014. sOffset = 0;
  1015. sCount++;
  1016. if (sCount > 20) sCount = 0;
  1017. }
  1018. sCount2+=7;
  1019. }
  1020. }
  1021. long index[1];
  1022. for (index[0] = 0; index[0] < 21; index[0]++)
  1023. SafeArrayPutElement(vaResult.parray, &index[0], &bRet[index[0]]);
  1024. return vaResult;
  1025. }
  1026. void CHoursCtrl::SetDateData(const VARIANT FAR& newValue)
  1027. {
  1028. // TODO: Add your property handler here
  1029. SetModifiedFlag();
  1030. }