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.

747 lines
16 KiB

  1. /*++
  2. Copyright (c) 1994-1998, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. mapctl.c
  5. Abstract:
  6. This module implements the map control for the Date/Time applet.
  7. Revision History:
  8. --*/
  9. //
  10. // Include Files.
  11. //
  12. #include "timedate.h"
  13. #include <commctrl.h>
  14. #include "worldmap.h"
  15. #include "mapctl.h"
  16. #include "rc.h"
  17. //
  18. // Constant Declarations.
  19. //
  20. #define MAPCTL_BITMAP_NAME MAKEINTRESOURCE(IDB_TIMEZONE)
  21. #define MAPCTL_ANIMATION_TIMER 1
  22. #define MAPCTL_ANIMATION_INTERVAL 30
  23. #define MAPCTL_ANIMATION_FACTOR 3
  24. #define MAPCTL_DATA 0
  25. static const RGBQUAD c_SeaNormalColor = { 127, 0, 0, 0 };
  26. static const RGBQUAD c_SeaHiliteColor = { 255, 0, 0, 0 };
  27. static const RGBQUAD c_LandNormalColor = { 0, 127, 0, 0 };
  28. static const RGBQUAD c_LandHiliteColor = { 0, 255, 0, 0 };
  29. static const RGBQUAD c_MonoSeaNormalColor = { 255, 255, 255, 0 };
  30. static const RGBQUAD c_MonoSeaHiliteColor = { 0, 0, 0, 0 };
  31. static const RGBQUAD c_MonoLandNormalColor = { 0, 0, 0, 0 };
  32. static const RGBQUAD c_MonoLandHiliteColor = { 255, 255, 255, 0 };
  33. //
  34. // Typedef Declarations.
  35. //
  36. typedef struct tagMAPCTLDATA
  37. {
  38. HWND window; // window handle for this control
  39. UINT_PTR timer; // timer id for this map control
  40. int totaldelta; // total delta we must cover to center stuff
  41. BOOL slowdevice;
  42. BOOL captured;
  43. WORLDMAP map; // world map object, at end of struct (>1k)
  44. } MAPCTLDATA, *PMAPCTLDATA;
  45. //
  46. // Function Prototypes.
  47. //
  48. PMAPCTLDATA
  49. CreateMapControlData(
  50. HWND window);
  51. void
  52. DestroyMapControlData(
  53. PMAPCTLDATA ctldata);
  54. LRESULT CALLBACK
  55. MapControlWndProc(
  56. HWND window,
  57. UINT message,
  58. WPARAM wParam,
  59. LPARAM lParam);
  60. BOOL
  61. MapControlNCCreate(
  62. PMAPCTLDATA ctldata,
  63. LPCREATESTRUCT cs);
  64. BOOL
  65. MapControlCreate(
  66. PMAPCTLDATA ctldata,
  67. LPCREATESTRUCT cs);
  68. void
  69. MapControlNCDestroy(
  70. PMAPCTLDATA ctldata);
  71. BOOL
  72. MapControlErase(
  73. PMAPCTLDATA ctldata,
  74. HDC dc);
  75. void
  76. MapControlPaint(
  77. PMAPCTLDATA ctldata);
  78. void
  79. MapControlMouseMove(
  80. PMAPCTLDATA ctldata,
  81. int x,
  82. int y,
  83. UINT flags);
  84. void
  85. MapControlMouseDown(
  86. PMAPCTLDATA ctldata,
  87. BOOL dblclk,
  88. int x,
  89. int y,
  90. UINT flags);
  91. void
  92. MapControlMouseUp(
  93. PMAPCTLDATA ctldata,
  94. int x,
  95. int y,
  96. UINT flags);
  97. void
  98. MapControlTimerProc(
  99. PMAPCTLDATA ctldata,
  100. UINT timer);
  101. void
  102. MapControlRotate(
  103. PMAPCTLDATA ctldata,
  104. int delta);
  105. void
  106. MapControlAnimateOneStep(
  107. PMAPCTLDATA ctldata);
  108. ////////////////////////////////////////////////////////////////////////////
  109. //
  110. // SetMapControlData
  111. //
  112. ////////////////////////////////////////////////////////////////////////////
  113. __inline
  114. void SetMapControlData(
  115. HWND window,
  116. PMAPCTLDATA ctldata)
  117. {
  118. SetWindowLongPtr(window, MAPCTL_DATA, (LONG_PTR)ctldata);
  119. }
  120. ////////////////////////////////////////////////////////////////////////////
  121. //
  122. // GetMapControlData
  123. //
  124. ////////////////////////////////////////////////////////////////////////////
  125. __inline
  126. PMAPCTLDATA GetMapControlData(
  127. HWND window)
  128. {
  129. return ( (PMAPCTLDATA)GetWindowLongPtr(window, MAPCTL_DATA) );
  130. }
  131. ////////////////////////////////////////////////////////////////////////////
  132. //
  133. // RegisterMapControlStuff
  134. //
  135. ////////////////////////////////////////////////////////////////////////////
  136. BOOL RegisterMapControlStuff(
  137. HINSTANCE instance)
  138. {
  139. WNDCLASS wc;
  140. wc.style = 0;
  141. wc.lpfnWndProc = MapControlWndProc;
  142. wc.cbClsExtra = 0;
  143. wc.cbWndExtra = sizeof(PMAPCTLDATA);
  144. wc.hInstance = instance;
  145. wc.hIcon = NULL;
  146. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  147. wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  148. wc.lpszMenuName = NULL;
  149. wc.lpszClassName = MAPCTL_CLASSNAME;
  150. return ( RegisterClass(&wc) );
  151. }
  152. ////////////////////////////////////////////////////////////////////////////
  153. //
  154. // MapControlSetSeaRegionHighlight
  155. //
  156. ////////////////////////////////////////////////////////////////////////////
  157. void MapControlSetSeaRegionHighlight(
  158. HWND window,
  159. int index,
  160. BOOL highlighted,
  161. int x,
  162. int cx)
  163. {
  164. ChangeWorldMapColor( &GetMapControlData(window)->map,
  165. index,
  166. #ifdef ENABLE_MAP
  167. highlighted ? &c_SeaHiliteColor : &c_SeaNormalColor,
  168. #else
  169. &c_SeaNormalColor,
  170. #endif
  171. x,
  172. cx );
  173. }
  174. ////////////////////////////////////////////////////////////////////////////
  175. //
  176. // MapControlSetLandRegionHighlight
  177. //
  178. ////////////////////////////////////////////////////////////////////////////
  179. void MapControlSetLandRegionHighlight(
  180. HWND window,
  181. int index,
  182. BOOL highlighted,
  183. int x,
  184. int cx)
  185. {
  186. ChangeWorldMapColor( &GetMapControlData(window)->map,
  187. index,
  188. #ifdef ENABLE_MAP
  189. highlighted ? &c_LandHiliteColor : &c_LandNormalColor,
  190. #else
  191. &c_LandNormalColor,
  192. #endif
  193. x,
  194. cx );
  195. }
  196. ////////////////////////////////////////////////////////////////////////////
  197. //
  198. // _InvalidateProc
  199. //
  200. ////////////////////////////////////////////////////////////////////////////
  201. void _InvalidateProc(
  202. LPARAM data,
  203. int left,
  204. int right)
  205. {
  206. #define ctldata ((PMAPCTLDATA)data)
  207. RECT ri = { left, 0, right, ctldata->map.size.cy };
  208. InvalidateRect(ctldata->window, &ri, TRUE);
  209. #undef ctldata
  210. }
  211. ////////////////////////////////////////////////////////////////////////////
  212. //
  213. // MapControlInvalidateDirtyRegions
  214. //
  215. ////////////////////////////////////////////////////////////////////////////
  216. void MapControlInvalidateDirtyRegions(
  217. HWND window)
  218. {
  219. PMAPCTLDATA ctldata = GetMapControlData(window);
  220. EnumWorldMapDirtySpans( &ctldata->map,
  221. _InvalidateProc,
  222. (LPARAM)ctldata,
  223. TRUE );
  224. }
  225. ////////////////////////////////////////////////////////////////////////////
  226. //
  227. // MapControlRotateTo
  228. //
  229. ////////////////////////////////////////////////////////////////////////////
  230. void MapControlRotateTo(
  231. HWND window,
  232. int x,
  233. BOOL animate)
  234. {
  235. PMAPCTLDATA ctldata = GetMapControlData(window);
  236. if (ctldata->timer)
  237. {
  238. KillTimer(ctldata->window, ctldata->timer);
  239. ctldata->timer = 0;
  240. }
  241. ctldata->totaldelta = (ctldata->map.size.cx / 2) -
  242. WorldMapGetDisplayedLocation(&ctldata->map, x);
  243. if (ctldata->totaldelta)
  244. {
  245. UpdateWindow(ctldata->window);
  246. if (animate)
  247. {
  248. ctldata->timer = SetTimer( ctldata->window,
  249. MAPCTL_ANIMATION_TIMER,
  250. MAPCTL_ANIMATION_INTERVAL,
  251. NULL );
  252. if (ctldata->timer)
  253. {
  254. MapControlAnimateOneStep(ctldata);
  255. return;
  256. }
  257. }
  258. MapControlRotate(ctldata, ctldata->totaldelta);
  259. ctldata->totaldelta = 0;
  260. }
  261. }
  262. ////////////////////////////////////////////////////////////////////////////
  263. //
  264. // CreateMapControlData
  265. //
  266. ////////////////////////////////////////////////////////////////////////////
  267. PMAPCTLDATA CreateMapControlData(
  268. HWND window)
  269. {
  270. PMAPCTLDATA ctldata = (PMAPCTLDATA)LocalAlloc(LPTR, sizeof(MAPCTLDATA));
  271. if (ctldata)
  272. {
  273. ctldata->window = window;
  274. SetMapControlData(window, ctldata);
  275. }
  276. return (ctldata);
  277. }
  278. ////////////////////////////////////////////////////////////////////////////
  279. //
  280. // DestroyMapControlData
  281. //
  282. ////////////////////////////////////////////////////////////////////////////
  283. void DestroyMapControlData(
  284. PMAPCTLDATA ctldata)
  285. {
  286. if (ctldata)
  287. {
  288. SetMapControlData(ctldata->window, 0);
  289. LocalFree(ctldata);
  290. }
  291. }
  292. ////////////////////////////////////////////////////////////////////////////
  293. //
  294. // MapControlWndProc
  295. //
  296. ////////////////////////////////////////////////////////////////////////////
  297. LRESULT CALLBACK MapControlWndProc(
  298. HWND window,
  299. UINT message,
  300. WPARAM wParam,
  301. LPARAM lParam)
  302. {
  303. PMAPCTLDATA ctldata = (message == WM_NCCREATE)
  304. ? CreateMapControlData(window)
  305. : GetMapControlData(window);
  306. switch (message)
  307. {
  308. HANDLE_MSG(ctldata, WM_NCCREATE, MapControlNCCreate);
  309. HANDLE_MSG(ctldata, WM_CREATE, MapControlCreate);
  310. HANDLE_MSG(ctldata, WM_NCDESTROY, MapControlNCDestroy);
  311. HANDLE_MSG(ctldata, WM_ERASEBKGND, MapControlErase);
  312. HANDLE_MSG(ctldata, WM_PAINT, MapControlPaint);
  313. #ifdef ENABLE_MAP
  314. HANDLE_MSG(ctldata, WM_MOUSEMOVE, MapControlMouseMove);
  315. HANDLE_MSG(ctldata, WM_LBUTTONDOWN, MapControlMouseDown);
  316. HANDLE_MSG(ctldata, WM_LBUTTONUP, MapControlMouseUp);
  317. #endif
  318. HANDLE_MSG(ctldata, WM_TIMER, MapControlTimerProc);
  319. }
  320. return ( DefWindowProc(window, message, wParam, lParam) );
  321. }
  322. ////////////////////////////////////////////////////////////////////////////
  323. //
  324. // MapControlNCCreate
  325. //
  326. ////////////////////////////////////////////////////////////////////////////
  327. BOOL MapControlNCCreate(
  328. PMAPCTLDATA ctldata,
  329. LPCREATESTRUCT cs)
  330. {
  331. if (!ctldata)
  332. {
  333. return (FALSE);
  334. }
  335. //
  336. // NCDESTROY tries to nuke this if it's nonzero.
  337. //
  338. ctldata->timer = 0;
  339. if (!LoadWorldMap(&ctldata->map, g_hInst, MAPCTL_BITMAP_NAME))
  340. {
  341. return (FALSE);
  342. }
  343. ctldata->slowdevice = (ctldata->map.prepared.dc != NULL);
  344. ctldata->totaldelta = 0;
  345. ctldata->captured = FALSE;
  346. return (TRUE);
  347. }
  348. ////////////////////////////////////////////////////////////////////////////
  349. //
  350. // MapControlCreate
  351. //
  352. ////////////////////////////////////////////////////////////////////////////
  353. BOOL MapControlCreate(
  354. PMAPCTLDATA ctldata,
  355. LPCREATESTRUCT cs)
  356. {
  357. RECT rc = { 0, 0, ctldata->map.size.cx, ctldata->map.size.cy };
  358. if (AdjustWindowRectEx( &rc,
  359. GetWindowLong(ctldata->window, GWL_STYLE),
  360. FALSE,
  361. GetWindowLong(ctldata->window, GWL_EXSTYLE)))
  362. {
  363. SIZE sz = { rc.right - rc.left, rc.bottom - rc.top };
  364. MoveWindow( ctldata->window,
  365. cs->x + ((cs->cx - sz.cx) / 2),
  366. cs->y + ((cs->cy - sz.cy) / 2 ),
  367. sz.cx,
  368. sz.cy,
  369. FALSE );
  370. }
  371. return (TRUE);
  372. }
  373. ////////////////////////////////////////////////////////////////////////////
  374. //
  375. // MapControlNCDestroy
  376. //
  377. ////////////////////////////////////////////////////////////////////////////
  378. void MapControlNCDestroy(
  379. PMAPCTLDATA ctldata)
  380. {
  381. if (ctldata)
  382. {
  383. if (ctldata->timer)
  384. {
  385. KillTimer(ctldata->window, ctldata->timer);
  386. }
  387. FreeWorldMap(&ctldata->map);
  388. DestroyMapControlData(ctldata);
  389. }
  390. }
  391. ////////////////////////////////////////////////////////////////////////////
  392. //
  393. // MapControlErase
  394. //
  395. ////////////////////////////////////////////////////////////////////////////
  396. BOOL MapControlErase(
  397. PMAPCTLDATA ctldata,
  398. HDC dc)
  399. {
  400. RECT rce;
  401. GetClipBox(dc, &rce);
  402. DrawWorldMap( dc,
  403. rce.left,
  404. rce.top,
  405. rce.right - rce.left,
  406. rce.bottom - rce.top,
  407. &ctldata->map,
  408. rce.left,
  409. rce.top,
  410. SRCCOPY );
  411. return (TRUE);
  412. }
  413. ////////////////////////////////////////////////////////////////////////////
  414. //
  415. // MapControlPaint
  416. //
  417. ////////////////////////////////////////////////////////////////////////////
  418. void MapControlPaint(
  419. PMAPCTLDATA ctldata)
  420. {
  421. PAINTSTRUCT ps;
  422. BeginPaint(ctldata->window, &ps);
  423. EndPaint(ctldata->window, &ps);
  424. }
  425. ////////////////////////////////////////////////////////////////////////////
  426. //
  427. // MapControlMouseMove
  428. //
  429. ////////////////////////////////////////////////////////////////////////////
  430. void MapControlMouseMove(
  431. PMAPCTLDATA ctldata,
  432. int x,
  433. int y,
  434. UINT flags)
  435. {
  436. if (ctldata->captured)
  437. {
  438. if (flags & MK_LBUTTON)
  439. {
  440. NFYMAPEVENT event;
  441. event.index = GetWorldMapColorIndex(&ctldata->map, x, y);
  442. SendNotify( GetParent(ctldata->window),
  443. ctldata->window,
  444. MAPN_TOUCH,
  445. (NMHDR *)&event );
  446. }
  447. else
  448. {
  449. //
  450. // No time to handle WM_CAPTURECHANGED.
  451. //
  452. ctldata->captured = FALSE;
  453. }
  454. }
  455. }
  456. ////////////////////////////////////////////////////////////////////////////
  457. //
  458. // MapControlMouseDown
  459. //
  460. ////////////////////////////////////////////////////////////////////////////
  461. void MapControlMouseDown(
  462. PMAPCTLDATA ctldata,
  463. BOOL dblclk,
  464. int x,
  465. int y,
  466. UINT flags)
  467. {
  468. NFYMAPEVENT event;
  469. SetCapture(ctldata->window);
  470. ctldata->captured = TRUE;
  471. if (ctldata->timer)
  472. {
  473. KillTimer(ctldata->window, ctldata->timer);
  474. ctldata->timer = 0;
  475. }
  476. event.index = GetWorldMapColorIndex(&ctldata->map, x, y);
  477. SendNotify( GetParent(ctldata->window),
  478. ctldata->window,
  479. MAPN_TOUCH,
  480. (NMHDR *)&event );
  481. }
  482. ////////////////////////////////////////////////////////////////////////////
  483. //
  484. // MapControlMouseUp
  485. //
  486. ////////////////////////////////////////////////////////////////////////////
  487. void MapControlMouseUp(
  488. PMAPCTLDATA ctldata,
  489. int x,
  490. int y,
  491. UINT flags)
  492. {
  493. if (ctldata->captured)
  494. {
  495. NFYMAPEVENT event;
  496. int index = GetWorldMapColorIndex(&ctldata->map, x, y);
  497. ReleaseCapture();
  498. event.index = index;
  499. SendNotify( GetParent(ctldata->window),
  500. ctldata->window,
  501. MAPN_TOUCH,
  502. (NMHDR *)&event );
  503. event.index = index;
  504. SendNotify( GetParent(ctldata->window),
  505. ctldata->window,
  506. MAPN_SELECT,
  507. (NMHDR *)&event );
  508. }
  509. }
  510. ////////////////////////////////////////////////////////////////////////////
  511. //
  512. // MapControlTimerProc
  513. //
  514. ////////////////////////////////////////////////////////////////////////////
  515. void MapControlTimerProc(
  516. PMAPCTLDATA ctldata,
  517. UINT timer)
  518. {
  519. if (timer == MAPCTL_ANIMATION_TIMER)
  520. {
  521. if (ctldata->totaldelta)
  522. {
  523. MapControlAnimateOneStep(ctldata);
  524. }
  525. if (!ctldata->totaldelta && ctldata->timer)
  526. {
  527. KillTimer(ctldata->window, ctldata->timer);
  528. ctldata->timer = 0;
  529. }
  530. }
  531. }
  532. ////////////////////////////////////////////////////////////////////////////
  533. //
  534. // MapControlRotate
  535. //
  536. ////////////////////////////////////////////////////////////////////////////
  537. void MapControlRotate(
  538. PMAPCTLDATA ctldata,
  539. int delta)
  540. {
  541. RotateWorldMap(&ctldata->map, delta);
  542. ScrollWindow(ctldata->window, delta, 0, NULL, NULL);
  543. }
  544. ////////////////////////////////////////////////////////////////////////////
  545. //
  546. // MapControlAnimateOneStep
  547. //
  548. ////////////////////////////////////////////////////////////////////////////
  549. void MapControlAnimateOneStep(
  550. PMAPCTLDATA ctldata)
  551. {
  552. //
  553. // Check that we really need to do something.
  554. //
  555. if (ctldata->totaldelta)
  556. {
  557. //
  558. // Try to create a deceleration effect...
  559. //
  560. int delta = ctldata->totaldelta / MAPCTL_ANIMATION_FACTOR;
  561. BOOL negative = (ctldata->totaldelta < 0);
  562. if (!delta)
  563. {
  564. delta = negative ? -1 : 1;
  565. }
  566. if (ctldata->slowdevice)
  567. {
  568. //
  569. // Multiples of 8 will help on planar devices.
  570. //
  571. int preferred = ((delta + (negative ? 0 : 7)) & ~7);
  572. if (preferred)
  573. {
  574. delta = preferred;
  575. }
  576. }
  577. //
  578. // Don't go too far.
  579. //
  580. if ((negative && (delta < ctldata->totaldelta)) ||
  581. (!negative && (delta > ctldata->totaldelta)))
  582. {
  583. delta = ctldata->totaldelta;
  584. }
  585. //
  586. // Rotate the map and update the total delta left to go.
  587. //
  588. ctldata->totaldelta -= delta;
  589. MapControlRotate(ctldata, delta);
  590. }
  591. }