|
|
/*++
Copyright (c) 1994-1998, Microsoft Corporation All rights reserved.
Module Name:
mapctl.c
Abstract:
This module implements the map control for the Date/Time applet.
Revision History:
--*/
//
// Include Files.
//
#include "timedate.h"
#include <commctrl.h>
#include "worldmap.h"
#include "mapctl.h"
#include "rc.h"
//
// Constant Declarations.
//
#define MAPCTL_BITMAP_NAME MAKEINTRESOURCE(IDB_TIMEZONE)
#define MAPCTL_ANIMATION_TIMER 1
#define MAPCTL_ANIMATION_INTERVAL 30
#define MAPCTL_ANIMATION_FACTOR 3
#define MAPCTL_DATA 0
static const RGBQUAD c_SeaNormalColor = { 127, 0, 0, 0 }; static const RGBQUAD c_SeaHiliteColor = { 255, 0, 0, 0 }; static const RGBQUAD c_LandNormalColor = { 0, 127, 0, 0 }; static const RGBQUAD c_LandHiliteColor = { 0, 255, 0, 0 };
static const RGBQUAD c_MonoSeaNormalColor = { 255, 255, 255, 0 }; static const RGBQUAD c_MonoSeaHiliteColor = { 0, 0, 0, 0 }; static const RGBQUAD c_MonoLandNormalColor = { 0, 0, 0, 0 }; static const RGBQUAD c_MonoLandHiliteColor = { 255, 255, 255, 0 };
//
// Typedef Declarations.
//
typedef struct tagMAPCTLDATA { HWND window; // window handle for this control
UINT_PTR timer; // timer id for this map control
int totaldelta; // total delta we must cover to center stuff
BOOL slowdevice; BOOL captured; WORLDMAP map; // world map object, at end of struct (>1k)
} MAPCTLDATA, *PMAPCTLDATA;
//
// Function Prototypes.
//
PMAPCTLDATA CreateMapControlData( HWND window);
void DestroyMapControlData( PMAPCTLDATA ctldata);
LRESULT CALLBACK MapControlWndProc( HWND window, UINT message, WPARAM wParam, LPARAM lParam);
BOOL MapControlNCCreate( PMAPCTLDATA ctldata, LPCREATESTRUCT cs);
BOOL MapControlCreate( PMAPCTLDATA ctldata, LPCREATESTRUCT cs);
void MapControlNCDestroy( PMAPCTLDATA ctldata);
BOOL MapControlErase( PMAPCTLDATA ctldata, HDC dc);
void MapControlPaint( PMAPCTLDATA ctldata);
void MapControlMouseMove( PMAPCTLDATA ctldata, int x, int y, UINT flags);
void MapControlMouseDown( PMAPCTLDATA ctldata, BOOL dblclk, int x, int y, UINT flags);
void MapControlMouseUp( PMAPCTLDATA ctldata, int x, int y, UINT flags);
void MapControlTimerProc( PMAPCTLDATA ctldata, UINT timer);
void MapControlRotate( PMAPCTLDATA ctldata, int delta);
void MapControlAnimateOneStep( PMAPCTLDATA ctldata);
////////////////////////////////////////////////////////////////////////////
//
// SetMapControlData
//
////////////////////////////////////////////////////////////////////////////
__inline void SetMapControlData( HWND window, PMAPCTLDATA ctldata) { SetWindowLongPtr(window, MAPCTL_DATA, (LONG_PTR)ctldata); }
////////////////////////////////////////////////////////////////////////////
//
// GetMapControlData
//
////////////////////////////////////////////////////////////////////////////
__inline PMAPCTLDATA GetMapControlData( HWND window) { return ( (PMAPCTLDATA)GetWindowLongPtr(window, MAPCTL_DATA) ); }
////////////////////////////////////////////////////////////////////////////
//
// RegisterMapControlStuff
//
////////////////////////////////////////////////////////////////////////////
BOOL RegisterMapControlStuff( HINSTANCE instance) { WNDCLASS wc;
wc.style = 0; wc.lpfnWndProc = MapControlWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(PMAPCTLDATA); wc.hInstance = instance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = MAPCTL_CLASSNAME;
return ( RegisterClass(&wc) ); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlSetSeaRegionHighlight
//
////////////////////////////////////////////////////////////////////////////
void MapControlSetSeaRegionHighlight( HWND window, int index, BOOL highlighted, int x, int cx) { ChangeWorldMapColor( &GetMapControlData(window)->map, index, #ifdef ENABLE_MAP
highlighted ? &c_SeaHiliteColor : &c_SeaNormalColor, #else
&c_SeaNormalColor, #endif
x, cx ); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlSetLandRegionHighlight
//
////////////////////////////////////////////////////////////////////////////
void MapControlSetLandRegionHighlight( HWND window, int index, BOOL highlighted, int x, int cx) { ChangeWorldMapColor( &GetMapControlData(window)->map, index, #ifdef ENABLE_MAP
highlighted ? &c_LandHiliteColor : &c_LandNormalColor, #else
&c_LandNormalColor, #endif
x, cx ); }
////////////////////////////////////////////////////////////////////////////
//
// _InvalidateProc
//
////////////////////////////////////////////////////////////////////////////
void _InvalidateProc( LPARAM data, int left, int right) { #define ctldata ((PMAPCTLDATA)data)
RECT ri = { left, 0, right, ctldata->map.size.cy };
InvalidateRect(ctldata->window, &ri, TRUE); #undef ctldata
}
////////////////////////////////////////////////////////////////////////////
//
// MapControlInvalidateDirtyRegions
//
////////////////////////////////////////////////////////////////////////////
void MapControlInvalidateDirtyRegions( HWND window) { PMAPCTLDATA ctldata = GetMapControlData(window);
EnumWorldMapDirtySpans( &ctldata->map, _InvalidateProc, (LPARAM)ctldata, TRUE ); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlRotateTo
//
////////////////////////////////////////////////////////////////////////////
void MapControlRotateTo( HWND window, int x, BOOL animate) { PMAPCTLDATA ctldata = GetMapControlData(window);
if (ctldata->timer) { KillTimer(ctldata->window, ctldata->timer); ctldata->timer = 0; }
ctldata->totaldelta = (ctldata->map.size.cx / 2) - WorldMapGetDisplayedLocation(&ctldata->map, x);
if (ctldata->totaldelta) { UpdateWindow(ctldata->window);
if (animate) { ctldata->timer = SetTimer( ctldata->window, MAPCTL_ANIMATION_TIMER, MAPCTL_ANIMATION_INTERVAL, NULL );
if (ctldata->timer) { MapControlAnimateOneStep(ctldata); return; } }
MapControlRotate(ctldata, ctldata->totaldelta); ctldata->totaldelta = 0; } }
////////////////////////////////////////////////////////////////////////////
//
// CreateMapControlData
//
////////////////////////////////////////////////////////////////////////////
PMAPCTLDATA CreateMapControlData( HWND window) { PMAPCTLDATA ctldata = (PMAPCTLDATA)LocalAlloc(LPTR, sizeof(MAPCTLDATA));
if (ctldata) { ctldata->window = window; SetMapControlData(window, ctldata); }
return (ctldata); }
////////////////////////////////////////////////////////////////////////////
//
// DestroyMapControlData
//
////////////////////////////////////////////////////////////////////////////
void DestroyMapControlData( PMAPCTLDATA ctldata) { if (ctldata) { SetMapControlData(ctldata->window, 0); LocalFree(ctldata); } }
////////////////////////////////////////////////////////////////////////////
//
// MapControlWndProc
//
////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK MapControlWndProc( HWND window, UINT message, WPARAM wParam, LPARAM lParam) { PMAPCTLDATA ctldata = (message == WM_NCCREATE) ? CreateMapControlData(window) : GetMapControlData(window);
switch (message) { HANDLE_MSG(ctldata, WM_NCCREATE, MapControlNCCreate); HANDLE_MSG(ctldata, WM_CREATE, MapControlCreate); HANDLE_MSG(ctldata, WM_NCDESTROY, MapControlNCDestroy);
HANDLE_MSG(ctldata, WM_ERASEBKGND, MapControlErase); HANDLE_MSG(ctldata, WM_PAINT, MapControlPaint);
#ifdef ENABLE_MAP
HANDLE_MSG(ctldata, WM_MOUSEMOVE, MapControlMouseMove); HANDLE_MSG(ctldata, WM_LBUTTONDOWN, MapControlMouseDown); HANDLE_MSG(ctldata, WM_LBUTTONUP, MapControlMouseUp); #endif
HANDLE_MSG(ctldata, WM_TIMER, MapControlTimerProc); }
return ( DefWindowProc(window, message, wParam, lParam) ); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlNCCreate
//
////////////////////////////////////////////////////////////////////////////
BOOL MapControlNCCreate( PMAPCTLDATA ctldata, LPCREATESTRUCT cs) { if (!ctldata) { return (FALSE); }
//
// NCDESTROY tries to nuke this if it's nonzero.
//
ctldata->timer = 0;
if (!LoadWorldMap(&ctldata->map, g_hInst, MAPCTL_BITMAP_NAME)) { return (FALSE); }
ctldata->slowdevice = (ctldata->map.prepared.dc != NULL); ctldata->totaldelta = 0; ctldata->captured = FALSE; return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlCreate
//
////////////////////////////////////////////////////////////////////////////
BOOL MapControlCreate( PMAPCTLDATA ctldata, LPCREATESTRUCT cs) { RECT rc = { 0, 0, ctldata->map.size.cx, ctldata->map.size.cy };
if (AdjustWindowRectEx( &rc, GetWindowLong(ctldata->window, GWL_STYLE), FALSE, GetWindowLong(ctldata->window, GWL_EXSTYLE))) { SIZE sz = { rc.right - rc.left, rc.bottom - rc.top };
MoveWindow( ctldata->window, cs->x + ((cs->cx - sz.cx) / 2), cs->y + ((cs->cy - sz.cy) / 2 ), sz.cx, sz.cy, FALSE ); }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlNCDestroy
//
////////////////////////////////////////////////////////////////////////////
void MapControlNCDestroy( PMAPCTLDATA ctldata) { if (ctldata) { if (ctldata->timer) { KillTimer(ctldata->window, ctldata->timer); }
FreeWorldMap(&ctldata->map); DestroyMapControlData(ctldata); } }
////////////////////////////////////////////////////////////////////////////
//
// MapControlErase
//
////////////////////////////////////////////////////////////////////////////
BOOL MapControlErase( PMAPCTLDATA ctldata, HDC dc) { RECT rce;
GetClipBox(dc, &rce);
DrawWorldMap( dc, rce.left, rce.top, rce.right - rce.left, rce.bottom - rce.top, &ctldata->map, rce.left, rce.top, SRCCOPY );
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlPaint
//
////////////////////////////////////////////////////////////////////////////
void MapControlPaint( PMAPCTLDATA ctldata) { PAINTSTRUCT ps;
BeginPaint(ctldata->window, &ps); EndPaint(ctldata->window, &ps); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlMouseMove
//
////////////////////////////////////////////////////////////////////////////
void MapControlMouseMove( PMAPCTLDATA ctldata, int x, int y, UINT flags) { if (ctldata->captured) { if (flags & MK_LBUTTON) { NFYMAPEVENT event;
event.index = GetWorldMapColorIndex(&ctldata->map, x, y);
SendNotify( GetParent(ctldata->window), ctldata->window, MAPN_TOUCH, (NMHDR *)&event ); } else { //
// No time to handle WM_CAPTURECHANGED.
//
ctldata->captured = FALSE; } } }
////////////////////////////////////////////////////////////////////////////
//
// MapControlMouseDown
//
////////////////////////////////////////////////////////////////////////////
void MapControlMouseDown( PMAPCTLDATA ctldata, BOOL dblclk, int x, int y, UINT flags) { NFYMAPEVENT event;
SetCapture(ctldata->window); ctldata->captured = TRUE;
if (ctldata->timer) { KillTimer(ctldata->window, ctldata->timer); ctldata->timer = 0; }
event.index = GetWorldMapColorIndex(&ctldata->map, x, y);
SendNotify( GetParent(ctldata->window), ctldata->window, MAPN_TOUCH, (NMHDR *)&event ); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlMouseUp
//
////////////////////////////////////////////////////////////////////////////
void MapControlMouseUp( PMAPCTLDATA ctldata, int x, int y, UINT flags) { if (ctldata->captured) { NFYMAPEVENT event; int index = GetWorldMapColorIndex(&ctldata->map, x, y);
ReleaseCapture();
event.index = index; SendNotify( GetParent(ctldata->window), ctldata->window, MAPN_TOUCH, (NMHDR *)&event );
event.index = index; SendNotify( GetParent(ctldata->window), ctldata->window, MAPN_SELECT, (NMHDR *)&event ); } }
////////////////////////////////////////////////////////////////////////////
//
// MapControlTimerProc
//
////////////////////////////////////////////////////////////////////////////
void MapControlTimerProc( PMAPCTLDATA ctldata, UINT timer) { if (timer == MAPCTL_ANIMATION_TIMER) { if (ctldata->totaldelta) { MapControlAnimateOneStep(ctldata); }
if (!ctldata->totaldelta && ctldata->timer) { KillTimer(ctldata->window, ctldata->timer); ctldata->timer = 0; } } }
////////////////////////////////////////////////////////////////////////////
//
// MapControlRotate
//
////////////////////////////////////////////////////////////////////////////
void MapControlRotate( PMAPCTLDATA ctldata, int delta) { RotateWorldMap(&ctldata->map, delta); ScrollWindow(ctldata->window, delta, 0, NULL, NULL); }
////////////////////////////////////////////////////////////////////////////
//
// MapControlAnimateOneStep
//
////////////////////////////////////////////////////////////////////////////
void MapControlAnimateOneStep( PMAPCTLDATA ctldata) { //
// Check that we really need to do something.
//
if (ctldata->totaldelta) { //
// Try to create a deceleration effect...
//
int delta = ctldata->totaldelta / MAPCTL_ANIMATION_FACTOR; BOOL negative = (ctldata->totaldelta < 0);
if (!delta) { delta = negative ? -1 : 1; }
if (ctldata->slowdevice) { //
// Multiples of 8 will help on planar devices.
//
int preferred = ((delta + (negative ? 0 : 7)) & ~7);
if (preferred) { delta = preferred; } }
//
// Don't go too far.
//
if ((negative && (delta < ctldata->totaldelta)) || (!negative && (delta > ctldata->totaldelta))) { delta = ctldata->totaldelta; }
//
// Rotate the map and update the total delta left to go.
//
ctldata->totaldelta -= delta; MapControlRotate(ctldata, delta); } }
|