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.

966 lines
23 KiB

  1. /*++
  2. Copyright (c) 1994-1998, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. clock.c
  5. Abstract:
  6. This module implements the clock control for the Date/Time applet.
  7. Revision History:
  8. --*/
  9. //
  10. // Include Files.
  11. //
  12. #include "timedate.h"
  13. #include "rc.h"
  14. #include "clock.h"
  15. //
  16. // Constant Declarations.
  17. //
  18. #define TIMER_ID 1
  19. #define SECONDSCALE 80
  20. #define HHAND TRUE
  21. #define MHAND FALSE
  22. #define MAXBLOBWIDTH 25
  23. #define REPAINT 0
  24. #define HANDPAINT 1
  25. #define OPEN_TLEN 450 /* < half second */
  26. #define MINDESIREDHEIGHT 3
  27. //
  28. // Macro Definitions.
  29. //
  30. #ifdef WIN32
  31. #define MoveTo(hdc, x, y) MoveToEx(hdc, x, y, NULL)
  32. #define GetWindowPtr(w, o) GetWindowLongPtr(w, o)
  33. #define SetWindowPtr(w, o, p) SetWindowLongPtr(w, o, (LPARAM)(p))
  34. #else
  35. #define GetWindowPtr(w, o) GetWindowWord(w, o)
  36. #define SetWindowPtr(w, o, p) SetWindowWord(w, o, p)
  37. #endif
  38. //
  39. // Typedef Declarations.
  40. //
  41. typedef struct
  42. {
  43. int hour; // 0 - 11 hours for analog clock
  44. int minute;
  45. int second;
  46. } TIME;
  47. typedef struct
  48. {
  49. HWND hWnd; // Us.
  50. HWND hwndGetTime; // window to provide get/set time
  51. // Brushes
  52. HBRUSH hbrColorWindow;
  53. HBRUSH hbrBtnHighlight;
  54. HBRUSH hbrForeground;
  55. HBRUSH hbrBlobColor;
  56. // Pens
  57. HPEN hpenForeground;
  58. HPEN hpenBackground;
  59. HPEN hpenBlobHlt;
  60. // Dimensions of clock
  61. RECT clockRect;
  62. int clockRadius;
  63. int HorzRes;
  64. int VertRes;
  65. int aspectD;
  66. int aspectN;
  67. // Position of clock
  68. POINT clockCenter;
  69. TIME oTime;
  70. TIME nTime;
  71. } CLOCKSTR, *PCLOCKSTR;
  72. typedef struct
  73. {
  74. SHORT x;
  75. SHORT y;
  76. } TRIG;
  77. //
  78. // Array containing the sine and cosine values for hand positions.
  79. //
  80. POINT rCircleTable[] =
  81. {
  82. { 0, -7999},
  83. { 836, -7956},
  84. { 1663, -7825},
  85. { 2472, -7608},
  86. { 3253, -7308},
  87. { 3999, -6928},
  88. { 4702, -6472},
  89. { 5353, -5945},
  90. { 5945, -5353},
  91. { 6472, -4702},
  92. { 6928, -4000},
  93. { 7308, -3253},
  94. { 7608, -2472},
  95. { 7825, -1663},
  96. { 7956, -836 },
  97. { 8000, 0 },
  98. { 7956, 836 },
  99. { 7825, 1663 },
  100. { 7608, 2472 },
  101. { 7308, 3253 },
  102. { 6928, 4000 },
  103. { 6472, 4702 },
  104. { 5945, 5353 },
  105. { 5353, 5945 },
  106. { 4702, 6472 },
  107. { 3999, 6928 },
  108. { 3253, 7308 },
  109. { 2472, 7608 },
  110. { 1663, 7825 },
  111. { 836, 7956 },
  112. { 0, 7999 },
  113. { -836, 7956 },
  114. { -1663, 7825 },
  115. { -2472, 7608 },
  116. { -3253, 7308 },
  117. { -4000, 6928 },
  118. { -4702, 6472 },
  119. { -5353, 5945 },
  120. { -5945, 5353 },
  121. { -6472, 4702 },
  122. { -6928, 3999 },
  123. { -7308, 3253 },
  124. { -7608, 2472 },
  125. { -7825, 1663 },
  126. { -7956, 836 },
  127. { -7999, -0 },
  128. { -7956, -836 },
  129. { -7825, -1663},
  130. { -7608, -2472},
  131. { -7308, -3253},
  132. { -6928, -4000},
  133. { -6472, -4702},
  134. { -5945, -5353},
  135. { -5353, -5945},
  136. { -4702, -6472},
  137. { -3999, -6928},
  138. { -3253, -7308},
  139. { -2472, -7608},
  140. { -1663, -7825},
  141. { -836 , -7956},
  142. };
  143. //
  144. // Function prototypes.
  145. //
  146. LRESULT CALLBACK ClockWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  147. void ClockCreate(HWND hWnd, PCLOCKSTR np);
  148. void ClockTimer(HWND hWnd, WPARAM idTimer, PCLOCKSTR np);
  149. void ClockPaint(PCLOCKSTR np, HDC hDC, int hint);
  150. void ClockTimerInterval( HWND hWnd, PCLOCKSTR np );
  151. void CompClockDim(HWND hWnd, PCLOCKSTR np);
  152. void CreateTools(PCLOCKSTR np);
  153. void DeleteTools(PCLOCKSTR np);
  154. void DrawFace(HDC hDC, PCLOCKSTR np);
  155. void DrawFatHand( HDC hDC, int pos, HPEN hPen, BOOL hHand, PCLOCKSTR np);
  156. void DrawHand( HDC hDC, int pos, HPEN hPen, int scale, int patMode, PCLOCKSTR np);
  157. ////////////////////////////////////////////////////////////////////////////
  158. //
  159. // ClockInit
  160. //
  161. // Registers the clock class.
  162. //
  163. ////////////////////////////////////////////////////////////////////////////
  164. TCHAR const c_szClockClass[] = CLOCK_CLASS;
  165. BOOL ClockInit(
  166. HINSTANCE hInstance)
  167. {
  168. WNDCLASS wc;
  169. if (!GetClassInfo(hInstance, c_szClockClass, &wc))
  170. {
  171. wc.cbClsExtra = 0;
  172. wc.cbWndExtra = sizeof(PCLOCKSTR);
  173. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  174. wc.hbrBackground = NULL;
  175. wc.hIcon = NULL;
  176. wc.lpszMenuName = NULL;
  177. wc.lpszClassName = c_szClockClass;
  178. wc.hInstance = hInstance;
  179. wc.style = CS_VREDRAW | CS_HREDRAW ;
  180. wc.lpfnWndProc = ClockWndProc;
  181. return (RegisterClass(&wc));
  182. }
  183. return (TRUE);
  184. }
  185. ////////////////////////////////////////////////////////////////////////////
  186. //
  187. // GetTimeClock
  188. //
  189. // Gets the time that we should display on the clock.
  190. // The client could have specified a function to call to get this
  191. // or an HWND to pass a message to to get it from.
  192. //
  193. ////////////////////////////////////////////////////////////////////////////
  194. void GetTimeClock(
  195. TIME *pt,
  196. PCLOCKSTR np)
  197. {
  198. SYSTEMTIME st;
  199. //
  200. // Call our time provider or default to GetTime.
  201. //
  202. if (np->hwndGetTime)
  203. {
  204. SendMessage( np->hwndGetTime,
  205. CLM_UPDATETIME,
  206. CLF_GETTIME,
  207. (LPARAM)(LPSYSTEMTIME)&st );
  208. pt->hour = st.wHour % 12;
  209. pt->minute = st.wMinute;
  210. pt->second = st.wSecond;
  211. }
  212. else
  213. {
  214. #ifdef WIN32
  215. GetLocalTime(&st);
  216. pt->hour = st.wHour;
  217. pt->minute = st.wMinute;
  218. pt->second = st.wSecond;
  219. #else
  220. //
  221. // No function call back and no HWND callback.
  222. //
  223. GetTime();
  224. pt->hour = wDateTime[HOUR] % 12;
  225. pt->minute = wDateTime[MINUTE];
  226. pt->second = wDateTime[SECOND];
  227. #endif
  228. }
  229. }
  230. ////////////////////////////////////////////////////////////////////////////
  231. //
  232. // CreateTools
  233. //
  234. ////////////////////////////////////////////////////////////////////////////
  235. void CreateTools(
  236. PCLOCKSTR np)
  237. {
  238. #define BLOB_COLOR RGB(0, 128, 128)
  239. np->hbrForeground = GetSysColorBrush(COLOR_BTNSHADOW);
  240. np->hbrColorWindow = GetSysColorBrush(COLOR_BTNFACE);
  241. np->hbrBlobColor = CreateSolidBrush( BLOB_COLOR );
  242. np->hbrBtnHighlight = GetSysColorBrush(COLOR_BTNHIGHLIGHT);
  243. np->hpenForeground = CreatePen(0, 1, GetSysColor(COLOR_WINDOWTEXT));
  244. np->hpenBackground = CreatePen(0, 1, GetSysColor(COLOR_BTNFACE));
  245. np->hpenBlobHlt = CreatePen(0, 1, RGB(0, 255, 255));
  246. }
  247. ////////////////////////////////////////////////////////////////////////////
  248. //
  249. // DeleteTools
  250. //
  251. ////////////////////////////////////////////////////////////////////////////
  252. void DeleteTools(
  253. PCLOCKSTR np)
  254. {
  255. // DeleteObject(np->hbrForeground);
  256. // DeleteObject(np->hbrColorWindow);
  257. DeleteObject(np->hbrBlobColor);
  258. // DeleteObject(np->hbrBtnHighlight);
  259. DeleteObject(np->hpenForeground);
  260. DeleteObject(np->hpenBackground);
  261. DeleteObject(np->hpenBlobHlt);
  262. }
  263. ////////////////////////////////////////////////////////////////////////////
  264. //
  265. // CompClockDim
  266. //
  267. // Calculates the clock dimensions.
  268. //
  269. ////////////////////////////////////////////////////////////////////////////
  270. void CompClockDim(
  271. HWND hWnd,
  272. PCLOCKSTR np)
  273. {
  274. int i;
  275. int tWidth;
  276. int tHeight;
  277. tWidth = np->clockRect.right - np->clockRect.left;
  278. tHeight = np->clockRect.bottom - np->clockRect.top;
  279. if (tWidth > MulDiv(tHeight,np->aspectD,np->aspectN))
  280. {
  281. i = MulDiv(tHeight, np->aspectD, np->aspectN);
  282. np->clockRect.left += (tWidth - i) / 2;
  283. np->clockRect.right = np->clockRect.left + i;
  284. }
  285. else
  286. {
  287. i = MulDiv(tWidth, np->aspectN, np->aspectD);
  288. np->clockRect.top += (tHeight - i) / 2;
  289. np->clockRect.bottom = np->clockRect.top + i;
  290. }
  291. }
  292. ////////////////////////////////////////////////////////////////////////////
  293. //
  294. // ClockTimerInterval
  295. //
  296. // Sets the timer interval. Two things affect this interval:
  297. // 1) if the window is iconic, or
  298. // 2) if seconds option has been disabled
  299. // In both cases, timer ticks occur every half-minute. Otherwise, timer
  300. // every half-second.
  301. //
  302. ////////////////////////////////////////////////////////////////////////////
  303. void ClockTimerInterval(
  304. HWND hWnd,
  305. PCLOCKSTR np)
  306. {
  307. //
  308. // Update every 1/2 second in the opened state.
  309. //
  310. KillTimer(hWnd, TIMER_ID);
  311. SetTimer(hWnd, TIMER_ID, OPEN_TLEN, 0L);
  312. }
  313. ////////////////////////////////////////////////////////////////////////////
  314. //
  315. // ClockSize
  316. //
  317. // Sizes the clock to the specified size.
  318. //
  319. ////////////////////////////////////////////////////////////////////////////
  320. void ClockSize(
  321. PCLOCKSTR np,
  322. int newWidth,
  323. int newHeight)
  324. {
  325. SetRect(&np->clockRect, 0, 0, newWidth, newHeight);
  326. CompClockDim(np->hWnd, np);
  327. ClockTimerInterval(np->hWnd, np);
  328. }
  329. ////////////////////////////////////////////////////////////////////////////
  330. //
  331. // DrawFace
  332. //
  333. // Draws the clock face.
  334. //
  335. ////////////////////////////////////////////////////////////////////////////
  336. void DrawFace(
  337. HDC hDC,
  338. PCLOCKSTR np)
  339. {
  340. int i;
  341. RECT tRect;
  342. LPPOINT ppt;
  343. int blobHeight, blobWidth;
  344. blobWidth = MulDiv( MAXBLOBWIDTH,
  345. (np->clockRect.right - np->clockRect.left),
  346. np->HorzRes );
  347. blobHeight = MulDiv(blobWidth, np->aspectN, np->aspectD);
  348. if (blobHeight < 2)
  349. {
  350. blobHeight = 1;
  351. }
  352. if (blobWidth < 2)
  353. {
  354. blobWidth = 2;
  355. }
  356. InflateRect(&np->clockRect, -(blobHeight / 2), -(blobWidth / 2));
  357. np->clockRadius = (np->clockRect.right - np->clockRect.left - 8) / 2;
  358. np->clockCenter.y = np->clockRect.top +
  359. ((np->clockRect.bottom - np->clockRect.top) / 2) - 1;
  360. np->clockCenter.x = np->clockRect.left + np->clockRadius + 3;
  361. for (i = 0; i < 60; i++)
  362. {
  363. ppt = rCircleTable + i;
  364. tRect.top = MulDiv(ppt->y, np->clockRadius, 8000) + np->clockCenter.y;
  365. tRect.left = MulDiv(ppt->x, np->clockRadius, 8000) + np->clockCenter.x;
  366. if (i % 5)
  367. {
  368. //
  369. // Draw a dot.
  370. //
  371. if (blobWidth > 2 && blobHeight >= 2)
  372. {
  373. tRect.right = tRect.left + 2;
  374. tRect.bottom = tRect.top + 2;
  375. FillRect(hDC, &tRect, GetStockObject(WHITE_BRUSH));
  376. OffsetRect(&tRect, -1, -1);
  377. FillRect(hDC, &tRect, np->hbrForeground);
  378. tRect.left++;
  379. tRect.top++;
  380. FillRect(hDC, &tRect, np->hbrColorWindow);
  381. }
  382. }
  383. else
  384. {
  385. tRect.right = tRect.left + blobWidth;
  386. tRect.bottom = tRect.top + blobHeight;
  387. OffsetRect(&tRect, -(blobWidth / 2) , -(blobHeight / 2));
  388. SelectObject(hDC, GetStockObject(BLACK_PEN));
  389. SelectObject(hDC, np->hbrBlobColor);
  390. Rectangle(hDC, tRect.left, tRect.top, tRect.right, tRect.bottom);
  391. SelectObject(hDC, np->hpenBlobHlt);
  392. MoveTo(hDC, tRect.left, tRect.bottom - 1);
  393. LineTo(hDC, tRect.left, tRect.top);
  394. LineTo(hDC, tRect.right - 1, tRect.top);
  395. }
  396. }
  397. InflateRect(&np->clockRect, blobHeight / 2, blobWidth / 2);
  398. }
  399. ////////////////////////////////////////////////////////////////////////////
  400. //
  401. // DrawHand
  402. //
  403. // Draws the hands of the clock.
  404. //
  405. ////////////////////////////////////////////////////////////////////////////
  406. void DrawHand(
  407. HDC hDC,
  408. int pos,
  409. HPEN hPen,
  410. int scale,
  411. int patMode,
  412. PCLOCKSTR np)
  413. {
  414. LPPOINT lppt;
  415. int radius;
  416. MoveTo(hDC, np->clockCenter.x, np->clockCenter.y);
  417. radius = MulDiv(np->clockRadius, scale, 100);
  418. lppt = rCircleTable + pos;
  419. SetROP2(hDC, patMode);
  420. SelectObject(hDC, hPen);
  421. LineTo( hDC,
  422. np->clockCenter.x + MulDiv(lppt->x, radius, 8000),
  423. np->clockCenter.y + MulDiv(lppt->y, radius, 8000) );
  424. }
  425. ////////////////////////////////////////////////////////////////////////////
  426. //
  427. // Adjust
  428. //
  429. ////////////////////////////////////////////////////////////////////////////
  430. void Adjust(
  431. POINT *rgpt,
  432. int cPoint,
  433. int iDelta)
  434. {
  435. int i;
  436. for (i = 0; i < cPoint; i++)
  437. {
  438. rgpt[i].x += iDelta;
  439. rgpt[i].y += iDelta;
  440. }
  441. }
  442. ////////////////////////////////////////////////////////////////////////////
  443. //
  444. // DrawFatHand
  445. //
  446. // Draws either hour or minute hand.
  447. //
  448. ////////////////////////////////////////////////////////////////////////////
  449. void DrawFatHand(
  450. HDC hDC,
  451. int pos,
  452. HPEN hPen,
  453. BOOL hHand,
  454. PCLOCKSTR np)
  455. {
  456. int m;
  457. int n;
  458. int scale;
  459. TRIG tip;
  460. TRIG stip;
  461. BOOL fErase;
  462. POINT rgpt[4];
  463. HBRUSH hbrInit, hbrControl = NULL;
  464. SetROP2(hDC, 13);
  465. fErase = (hPen == np->hpenBackground);
  466. SelectObject(hDC, hPen);
  467. scale = hHand ? 7 : 5;
  468. n = (pos + 15) % 60;
  469. m = MulDiv(np->clockRadius, scale, 100);
  470. stip.y = (SHORT)MulDiv(rCircleTable[n].y, m, 8000);
  471. stip.x = (SHORT)MulDiv(rCircleTable[n].x, m, 8000);
  472. scale = hHand ? 65 : 80;
  473. tip.y = (SHORT)MulDiv(rCircleTable[pos % 60].y, MulDiv(np->clockRadius, scale, 100), 8000);
  474. tip.x = (SHORT)MulDiv(rCircleTable[pos % 60].x, MulDiv(np->clockRadius, scale, 100), 8000);
  475. rgpt[0].x = np->clockCenter.x + stip.x;
  476. rgpt[0].y = np->clockCenter.y + stip.y;
  477. rgpt[1].x = np->clockCenter.x + tip.x;
  478. rgpt[1].y = np->clockCenter.y + tip.y;
  479. rgpt[2].x = np->clockCenter.x - stip.x;
  480. rgpt[2].y = np->clockCenter.y - stip.y;
  481. scale = hHand ? 15 : 20;
  482. n = (pos + 30) % 60;
  483. m = MulDiv(np->clockRadius, scale, 100);
  484. tip.y = (SHORT)MulDiv(rCircleTable[n].y, m, 8000);
  485. tip.x = (SHORT)MulDiv(rCircleTable[n].x, m, 8000);
  486. rgpt[3].x = np->clockCenter.x + tip.x;
  487. rgpt[3].y = np->clockCenter.y + tip.y;
  488. SelectObject(hDC, GetStockObject(NULL_PEN));
  489. if (fErase)
  490. {
  491. hbrControl = (HBRUSH)SendMessage(GetParent(np->hWnd), WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)np->hWnd);
  492. hbrInit = SelectObject(hDC, hbrControl ? hbrControl : np->hbrColorWindow);
  493. }
  494. else
  495. {
  496. hbrInit = SelectObject(hDC, np->hbrBtnHighlight);
  497. }
  498. Adjust(rgpt, 4, -2);
  499. Polygon(hDC, rgpt, 4);
  500. if (!fErase)
  501. {
  502. SelectObject(hDC, np->hbrForeground);
  503. }
  504. Adjust(rgpt, 4, 4);
  505. Polygon(hDC, rgpt, 4);
  506. if (!fErase)
  507. {
  508. SelectObject(hDC, np->hbrBlobColor);
  509. }
  510. Adjust(rgpt, 4, -2);
  511. Polygon(hDC, rgpt, 4);
  512. //
  513. // If we selected a brush in, reset it now.
  514. //
  515. if (fErase)
  516. {
  517. SelectObject(hDC, hbrInit);
  518. }
  519. }
  520. ////////////////////////////////////////////////////////////////////////////
  521. //
  522. // ClockPaint
  523. //
  524. // Only paints the clock.
  525. //
  526. // It assumes you have set nTime already. This allows it to be called by
  527. // the timer or by the client.
  528. //
  529. ////////////////////////////////////////////////////////////////////////////
  530. void ClockPaint(
  531. PCLOCKSTR np,
  532. HDC hDC,
  533. int hint)
  534. {
  535. SetBkMode(hDC, TRANSPARENT);
  536. if (hint == REPAINT)
  537. {
  538. //
  539. // If doing a full repaint, we do not advance the time.
  540. // Otherwise we will create artifacts when there is a clipping
  541. // region.
  542. //
  543. DrawFace(hDC, np);
  544. DrawFatHand(hDC, np->oTime.hour * 5 + (np->oTime.minute / 12), np->hpenForeground, HHAND,np);
  545. DrawFatHand(hDC, np->oTime.minute, np->hpenForeground, MHAND,np);
  546. //
  547. // Draw the second hand.
  548. //
  549. DrawHand(hDC, np->oTime.second, np->hpenBackground, SECONDSCALE, R2_NOT,np);
  550. }
  551. else if (hint == HANDPAINT)
  552. {
  553. DrawHand(hDC, np->oTime.second, np->hpenBackground, SECONDSCALE, R2_NOT, np);
  554. if (np->nTime.minute != np->oTime.minute || np->nTime.hour != np->oTime.hour)
  555. {
  556. DrawFatHand(hDC, np->oTime.minute, np->hpenBackground, MHAND, np);
  557. DrawFatHand(hDC, np->oTime.hour * 5 + (np->oTime.minute / 12), np->hpenBackground, HHAND,np);
  558. DrawFatHand(hDC, np->nTime.minute, np->hpenForeground, MHAND, np);
  559. DrawFatHand(hDC, (np->nTime.hour) * 5 + (np->nTime.minute / 12), np->hpenForeground, HHAND, np);
  560. }
  561. DrawHand(hDC, np->nTime.second, np->hpenBackground, SECONDSCALE, R2_NOT, np);
  562. np->oTime = np->nTime;
  563. }
  564. }
  565. ////////////////////////////////////////////////////////////////////////////
  566. //
  567. // ClockTimer
  568. //
  569. // Update the clock. Called on a timer tick.
  570. //
  571. ////////////////////////////////////////////////////////////////////////////
  572. void ClockTimer(
  573. HWND hWnd,
  574. UINT_PTR idTimer,
  575. PCLOCKSTR np)
  576. {
  577. HDC hDC;
  578. GetTimeClock(&np->nTime, np);
  579. if ((np->nTime.second == np->oTime.second) &&
  580. (np->nTime.minute == np->oTime.minute) &&
  581. (np->nTime.hour == np->oTime.hour))
  582. {
  583. return;
  584. }
  585. hDC = GetDC(hWnd);
  586. ClockPaint(np, hDC, HANDPAINT);
  587. ReleaseDC(hWnd, hDC);
  588. }
  589. ////////////////////////////////////////////////////////////////////////////
  590. //
  591. // ClockCreate
  592. //
  593. ////////////////////////////////////////////////////////////////////////////
  594. void ClockCreate(
  595. HWND hWnd,
  596. PCLOCKSTR np)
  597. {
  598. int i;
  599. HDC hDC;
  600. int HorzSize;
  601. int VertSize;
  602. LPPOINT lppt;
  603. hDC = GetDC(hWnd);
  604. np->VertRes = GetDeviceCaps(hDC, VERTRES);
  605. np->HorzRes = GetDeviceCaps(hDC, HORZRES);
  606. VertSize= GetDeviceCaps(hDC, VERTSIZE);
  607. HorzSize= GetDeviceCaps(hDC, HORZSIZE);
  608. ReleaseDC(hWnd, hDC);
  609. np->aspectN = MulDiv(np->VertRes, 100, VertSize);
  610. np->aspectD = MulDiv(np->HorzRes, 100, HorzSize);
  611. //
  612. // Instance stuff.
  613. //
  614. np->hWnd = hWnd;
  615. CreateTools(np);
  616. //
  617. // Scale cosines for aspect ratio if this is the first instance.
  618. //
  619. for (i = 0; i < 60; i++)
  620. {
  621. lppt = rCircleTable + i;
  622. lppt->y = MulDiv(lppt->y, np->aspectN, np->aspectD);
  623. }
  624. }
  625. ////////////////////////////////////////////////////////////////////////////
  626. //
  627. // ClockWndProc
  628. //
  629. // Deals with the clock messages.
  630. //
  631. ////////////////////////////////////////////////////////////////////////////
  632. LRESULT CALLBACK ClockWndProc(
  633. HWND hWnd,
  634. UINT message,
  635. WPARAM wParam,
  636. LPARAM lParam)
  637. {
  638. PCLOCKSTR np = (PCLOCKSTR)GetWindowPtr(hWnd, 0);
  639. switch (message)
  640. {
  641. case ( WM_DESTROY ) :
  642. {
  643. if (np)
  644. {
  645. KillTimer(hWnd, TIMER_ID);
  646. DeleteTools(np);
  647. LocalFree((HLOCAL)np);
  648. SetWindowPtr(hWnd, 0, 0);
  649. }
  650. break;
  651. }
  652. case ( WM_CREATE ) :
  653. {
  654. //
  655. // Allocate the instance data space.
  656. //
  657. np = (PCLOCKSTR)LocalAlloc(LPTR, sizeof(CLOCKSTR));
  658. if (!np)
  659. {
  660. return (-1);
  661. }
  662. SetWindowPtr(hWnd, 0, np);
  663. ClockCreate(hWnd, np);
  664. SetLayout(GetDC(hWnd), LAYOUT_BITMAPORIENTATIONPRESERVED);
  665. //
  666. // Loop if control panel time being changed.
  667. //
  668. GetTimeClock(&(np->nTime), np);
  669. do
  670. {
  671. GetTimeClock(&(np->oTime), np);
  672. } while (np->nTime.second == np->oTime.second &&
  673. np->nTime.minute == np->oTime.minute &&
  674. np->nTime.hour == np->oTime.hour);
  675. SetTimer(hWnd, TIMER_ID, OPEN_TLEN, 0L);
  676. ClockSize( np,
  677. ((LPCREATESTRUCT)lParam)->cx,
  678. ((LPCREATESTRUCT)lParam)->cy );
  679. break;
  680. }
  681. case ( WM_SIZE ) :
  682. {
  683. if (np)
  684. {
  685. ClockSize(np, LOWORD(lParam), HIWORD(lParam));
  686. }
  687. break;
  688. }
  689. case ( WM_PAINT ) :
  690. {
  691. PAINTSTRUCT ps;
  692. BeginPaint(hWnd, &ps);
  693. GetTimeClock(&(np->nTime), np);
  694. ClockPaint(np, ps.hdc, REPAINT);
  695. EndPaint(hWnd, &ps);
  696. break;
  697. }
  698. case ( WM_TIMECHANGE ) :
  699. {
  700. //
  701. // I'm not top level - so I wont get this message.
  702. //
  703. InvalidateRect(hWnd, NULL, TRUE);
  704. if (np->hwndGetTime)
  705. {
  706. SYSTEMTIME System;
  707. GetTime();
  708. System.wHour = wDateTime[HOUR];
  709. System.wMinute = wDateTime[MINUTE];
  710. System.wSecond = wDateTime[SECOND];
  711. SendMessage( np->hwndGetTime,
  712. CLM_UPDATETIME,
  713. CLF_SETTIME,
  714. (LPARAM)(LPSYSTEMTIME)&System );
  715. }
  716. // fall thru...
  717. }
  718. case ( WM_TIMER ) :
  719. {
  720. ClockTimer(hWnd, wParam, np);
  721. break;
  722. }
  723. case ( WM_SYSCOLORCHANGE ) :
  724. {
  725. DeleteTools(np);
  726. CreateTools(np);
  727. break;
  728. }
  729. case ( CLM_UPDATETIME ) :
  730. {
  731. //
  732. // Force the clock to repaint. lParam will point to a
  733. // SYSTEMTIME struct.
  734. //
  735. switch (wParam)
  736. {
  737. case ( CLF_SETTIME ) :
  738. {
  739. //
  740. // Caller wants us to reflect a new time.
  741. //
  742. HDC hDC;
  743. LPSYSTEMTIME lpSysTime = (LPSYSTEMTIME)lParam;
  744. np->nTime.hour = lpSysTime->wHour;
  745. np->nTime.minute = lpSysTime->wMinute;
  746. np->nTime.second = lpSysTime->wSecond;
  747. hDC = GetDC(hWnd);
  748. ClockPaint(np, hDC, HANDPAINT);
  749. ReleaseDC(hWnd, hDC);
  750. break;
  751. }
  752. case ( CLF_GETTIME ) :
  753. {
  754. //
  755. // Caller wants to know what we think the time is.
  756. //
  757. LPSYSTEMTIME lpSysTime = (LPSYSTEMTIME)lParam;
  758. lpSysTime->wHour = (WORD)np->nTime.hour;
  759. lpSysTime->wMinute = (WORD)np->nTime.minute;
  760. lpSysTime->wSecond = (WORD)np->nTime.second;
  761. break;
  762. }
  763. }
  764. break;
  765. }
  766. case ( CLM_TIMEHWND ) :
  767. {
  768. //
  769. // Get/Set the HWND that we ask to provide the time.
  770. //
  771. switch (wParam)
  772. {
  773. case ( CLF_SETHWND ) :
  774. {
  775. //
  776. // Caller wants us to reflect a new time.
  777. //
  778. np->hwndGetTime = (HWND)lParam;
  779. break;
  780. }
  781. case ( CLF_GETTIME ) :
  782. {
  783. //
  784. // Caller wants to know what we think the time is.
  785. //
  786. *((HWND *)lParam) = np->hwndGetTime;
  787. break;
  788. }
  789. }
  790. break;
  791. }
  792. default :
  793. {
  794. return ( DefWindowProc(hWnd, message, wParam, lParam) );
  795. }
  796. }
  797. return (0);
  798. }