#include "stdafx.h"
|
#include "MapPosWnd.h"
|
#include "ColorTransfer.h"
|
|
#define HT_NOWHERE 0x1
|
#define HT_INDICATOR 0x2
|
|
CMapPosWnd::CMapPosWnd()
|
{
|
m_hWnd = NULL;
|
m_crFrame = RGB(0, 0, 0);
|
m_crBkgnd = RGB(255, 255, 255);
|
m_crViewPort = RGB(185, 122, 87);
|
|
m_nWndMaxSize = 200;
|
m_nStageCx = 4000;
|
m_nStageCy = 3000;
|
m_rcViewPort = {200, 200, 800, 800};
|
}
|
|
CMapPosWnd::~CMapPosWnd()
|
{
|
|
}
|
|
BOOL CMapPosWnd::RegisterWndClass()
|
{
|
WNDCLASS wc;
|
wc.lpszClassName = MAPPOSWND_CLASS;
|
wc.hInstance = AfxGetInstanceHandle();
|
wc.lpfnWndProc = WindowProc;
|
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
|
wc.hIcon = 0;
|
wc.lpszMenuName = NULL;
|
wc.hbrBackground = NULL;
|
wc.style = CS_GLOBALCLASS | CS_DBLCLKS;
|
wc.cbClsExtra = 0;
|
wc.cbWndExtra = 0;
|
|
// ×¢²á´°¿ÚÀà
|
return (::RegisterClass(&wc) != 0);
|
}
|
|
CMapPosWnd * CMapPosWnd::FromHandle(HWND hWnd)
|
{
|
CMapPosWnd *pMapPosWnd = (CMapPosWnd *)::GetProp(hWnd, MAPPOSWND_TAG);
|
return pMapPosWnd;
|
}
|
|
CMapPosWnd* CMapPosWnd::Hook(HWND hWnd)
|
{
|
CMapPosWnd* pMapPosWnd = (CMapPosWnd*)GetProp(hWnd, MAPPOSWND_TAG);
|
if (pMapPosWnd == NULL) {
|
pMapPosWnd = new CMapPosWnd();
|
pMapPosWnd->m_hWnd = hWnd;
|
|
SetProp(hWnd, MAPPOSWND_TAG, (HANDLE)pMapPosWnd);
|
}
|
|
|
return pMapPosWnd;
|
}
|
|
void CMapPosWnd::SetWndMaxSize(int nMaxSize)
|
{
|
m_nWndMaxSize = nMaxSize;
|
}
|
|
void CMapPosWnd::SetStageSize(int cx, int cy, BOOL bInvalidata)
|
{
|
m_nStageCx = cx;
|
m_nStageCy = cy;
|
|
float scale = max(m_nStageCx / (float)m_nWndMaxSize, m_nStageCy / (float)m_nWndMaxSize);
|
int w = (int)(m_nStageCx / scale) +1;
|
int h = (int)(m_nStageCy / scale) + 1;
|
::SetWindowPos(m_hWnd, NULL, 0, 0, w, h, SWP_NOMOVE);
|
|
if (bInvalidata) {
|
RECT rcClient;
|
GetClientRect(m_hWnd, &rcClient);
|
InvalidateRect(m_hWnd, &rcClient, TRUE);
|
}
|
}
|
|
void CMapPosWnd::SetViewPort(LPRECT lpRect, BOOL bInvalidata)
|
{
|
::CopyRect(&m_rcViewPort, lpRect);
|
if (bInvalidata) {
|
RECT rcClient;
|
GetClientRect(m_hWnd, &rcClient);
|
InvalidateRect(m_hWnd, &rcClient, TRUE);
|
}
|
}
|
|
void CMapPosWnd::GetViewPortRect(LPRECT lprcClient, LPRECT lprcDest)
|
{
|
RECT rcClient;
|
if (lprcClient == NULL) {
|
GetClientRect(m_hWnd, &rcClient);
|
lprcClient = &rcClient;
|
}
|
|
|
float scale = max(m_nStageCx / (float)(lprcClient->right - lprcClient->left), m_nStageCy / (float)(lprcClient->bottom - lprcClient->top));
|
lprcDest->left = long(m_rcViewPort.left / scale);
|
lprcDest->top = long(m_rcViewPort.top / scale);
|
lprcDest->right = long(m_rcViewPort.right / scale);
|
lprcDest->bottom = long(m_rcViewPort.bottom / scale);
|
}
|
|
void CMapPosWnd::Init()
|
{
|
}
|
|
void CMapPosWnd::Release()
|
{
|
|
// delete
|
delete this;
|
}
|
|
void CMapPosWnd::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/)
|
{
|
HWND hParent;
|
hParent = GetParent(m_hWnd);
|
if (hParent != NULL) {
|
MAPPOSWND_NMHDR nmhdr;
|
nmhdr.nmhdr.hwndFrom = m_hWnd;
|
nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
|
nmhdr.nmhdr.code = nCode;
|
nmhdr.dwData = dwData;
|
nmhdr.dwData1 = dwData1;
|
nmhdr.dwData2 = dwData2;
|
SendMessage(hParent, WM_NOTIFY, (WPARAM)nmhdr.nmhdr.idFrom, (LPARAM)&nmhdr);
|
}
|
}
|
|
/*
|
* ¼ì²â×ø±êµãËùÔÚµÄÏî
|
* ·µ»ØÏîÀàÐÍ, ÈçHT_INDICATOR
|
*/
|
int CMapPosWnd::HighTest(POINT pt)
|
{
|
// ¼ì²âÊÇ·ñÔÚij¸ö×ÓÏî
|
int nRet = HT_NOWHERE;
|
|
RECT rcClient, rcViewPort;
|
GetClientRect(m_hWnd, &rcClient);
|
GetViewPortRect(&rcClient, &rcViewPort);
|
if (::PtInRect(&rcViewPort, pt)) {
|
nRet = HT_INDICATOR;
|
}
|
|
return nRet;
|
}
|
|
/*
|
* WindowProc£¬´°¿Ú¹ý³Ì
|
*/
|
LRESULT CALLBACK CMapPosWnd::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
{
|
CMapPosWnd* pMapPosWnd = (CMapPosWnd *)GetProp(hWnd, MAPPOSWND_TAG);
|
if (pMapPosWnd == NULL && uMsg != WM_NCCREATE)
|
{
|
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
|
}
|
|
|
// ´¦Àí´°¿ÚÏûÏ¢
|
ASSERT(hWnd);
|
switch (uMsg)
|
{
|
case WM_NCCREATE:
|
return CMapPosWnd::OnNcCreate(hWnd, wParam, lParam);
|
|
case WM_DESTROY:
|
return pMapPosWnd->OnDestroy(wParam, lParam);
|
|
case WM_NCPAINT:
|
return pMapPosWnd->OnNcPaint(wParam, lParam);
|
|
case WM_PAINT:
|
return pMapPosWnd->OnPaint(wParam, lParam);
|
|
case WM_TIMER:
|
return pMapPosWnd->OnTimer(wParam, lParam);
|
|
case WM_MOUSEMOVE:
|
return pMapPosWnd->OnMouseMove(wParam, lParam);
|
|
case WM_LBUTTONDOWN:
|
return pMapPosWnd->OnLButtonDown(wParam, lParam);
|
|
case WM_LBUTTONDBLCLK:
|
return pMapPosWnd->OnLButtonDblclk(wParam, lParam);
|
|
case WM_MOUSEWHEEL:
|
return pMapPosWnd->OnMouseWheel(wParam, lParam);
|
|
case WM_KEYDOWN:
|
return pMapPosWnd->OnKeyDown(wParam, lParam);
|
|
case WM_SIZE:
|
return pMapPosWnd->OnSize(wParam, lParam);
|
|
case WM_GETDLGCODE:
|
return DLGC_WANTALLKEYS;
|
|
default:
|
break;
|
}
|
|
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
|
}
|
|
/*
|
* WM_NCCREATE
|
* ´°¿Ú´´½¨
|
*/
|
LRESULT CMapPosWnd::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
{
|
CMapPosWnd* pMapPosWnd = (CMapPosWnd *)GetProp(hWnd, MAPPOSWND_TAG);
|
ASSERT(pMapPosWnd == NULL);
|
|
Hook(hWnd)->Init();
|
return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam);
|
}
|
|
/*
|
* WM_DESTROY
|
* ´°¿ÚÏú»Ù
|
*/
|
LRESULT CMapPosWnd::OnDestroy(WPARAM wParam, LPARAM lParam)
|
{
|
Release();
|
return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam);
|
}
|
|
|
/*
|
* WM_TIMER
|
*/
|
LRESULT CMapPosWnd::OnTimer(WPARAM wParam, LPARAM lParam)
|
{
|
|
return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam);
|
}
|
|
/*
|
* WM_MOUSEMOVE
|
* Êó±ê¹ö¶¯
|
*/
|
LRESULT CMapPosWnd::OnMouseMove(WPARAM wParam, LPARAM lParam)
|
{
|
return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam);
|
}
|
|
/*
|
* WM_LBUTTONDOWN
|
* Êó±ê×ó¼ü°´ÏÂ
|
*/
|
LRESULT CMapPosWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam)
|
{
|
POINT pt, ptNew, ptPox;
|
pt.x = LOWORD(lParam);
|
pt.y = HIWORD(lParam);
|
|
RECT rcClient, rcLastViewPort;
|
GetClientRect(m_hWnd, &rcClient);
|
float scale = max(m_nStageCx / (float)(rcClient.right - rcClient.left), m_nStageCy / (float)(rcClient.bottom - rcClient.top));
|
CopyRect(&rcLastViewPort, &m_rcViewPort);
|
|
|
// ¼ì²âµã»÷×ø±êÊÇ·ñÔÚijһ×ÓÏîÉÏ£¬ÈçÊÇ£¬Ôò¸ßÁÁÏÔʾ
|
int nRet = HighTest(pt);
|
SetFocus(m_hWnd);
|
|
|
// ²¶×½Êó±êÏûÏ¢£¬¼ì²âÊÇ·ñÍ϶¯
|
if (nRet == HT_INDICATOR) {
|
|
if (::GetCapture() == NULL) {
|
SetCapture(m_hWnd);
|
ASSERT(m_hWnd == GetCapture());
|
AfxLockTempMaps();
|
for (;;) {
|
MSG msg;
|
VERIFY(::GetMessage(&msg, NULL, 0, 0));
|
|
if (GetCapture() != m_hWnd) break;
|
|
switch (msg.message)
|
{
|
case WM_MOUSEMOVE:
|
ptNew = msg.pt;
|
::ScreenToClient(m_hWnd, &ptNew);
|
ptPox.x = long(rcLastViewPort.left + (ptNew.x - pt.x) * scale);
|
ptPox.x = max(0, min(ptPox.x, m_nStageCx - (rcLastViewPort.right - rcLastViewPort.left)));
|
ptPox.y = long(rcLastViewPort.top + (ptNew.y - pt.y) * scale);
|
ptPox.y = max(0, min(ptPox.y, m_nStageCy - (rcLastViewPort.bottom - rcLastViewPort.top)));
|
Notify(MAPPOSWND_POSCHANGED, ptPox.x, ptPox.y);
|
break;
|
|
case WM_LBUTTONUP:
|
ptNew = msg.pt;
|
::ScreenToClient(m_hWnd, &ptNew);
|
ptPox.x = long(rcLastViewPort.left + (ptNew.x - pt.x) * scale);
|
ptPox.x = max(0, min(ptPox.x, m_nStageCx - (rcLastViewPort.right - rcLastViewPort.left)));
|
ptPox.y = long(rcLastViewPort.top + (ptNew.y - pt.y) * scale);
|
ptPox.y = max(0, min(ptPox.y, m_nStageCy - (rcLastViewPort.bottom - rcLastViewPort.top)));
|
Notify(MAPPOSWND_POSCHANGED, ptPox.x, ptPox.y);
|
|
ReleaseCapture();
|
::InvalidateRect(m_hWnd, &rcClient, TRUE);
|
goto ExitLoop;
|
|
case WM_KEYDOWN:
|
if (msg.wParam != VK_ESCAPE)
|
break;
|
|
default:
|
DispatchMessage(&msg);
|
break;
|
}
|
}
|
|
ReleaseCapture();
|
ExitLoop:
|
AfxUnlockTempMaps(FALSE);
|
}
|
}
|
|
|
return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam);
|
}
|
|
/*
|
* WM_LBUTTONDBLCLK
|
* Êó±ê×ó¼üË«»÷
|
*/
|
LRESULT CMapPosWnd::OnLButtonDblclk(WPARAM wParam, LPARAM lParam)
|
{
|
POINT pt, ptDest;
|
pt.x = LOWORD(lParam);
|
pt.y = HIWORD(lParam);
|
|
RECT rcClient, rcLast;
|
GetClientRect(m_hWnd, &rcClient);
|
rcLast = { 0, 0, 0, 0 };
|
|
// ¼ì²âµã»÷×ø±êÊÇ·ñÔÚ¿Õ°×´¦
|
// С´°×ø±êת»»Îª¶ÔӦ׸±ê
|
int nRet = HighTest(pt);
|
if (nRet == HT_NOWHERE || nRet == HT_INDICATOR) {
|
float scale = max(m_nStageCx / (float)(rcClient.right - rcClient.left), m_nStageCy / (float)(rcClient.bottom - rcClient.top));
|
ptDest.x = (int)(scale * pt.x) - (m_rcViewPort.right - m_rcViewPort.left) / 2;
|
ptDest.x = max(0, min(ptDest.x, m_nStageCx - (m_rcViewPort.right - m_rcViewPort.left)));
|
ptDest.y = (int)(scale * pt.y) - (m_rcViewPort.bottom - m_rcViewPort.top) / 2;
|
ptDest.y = max(0, min(ptDest.y, m_nStageCy - (m_rcViewPort.bottom - m_rcViewPort.top)));
|
Notify(MAPPOSWND_POSCHANGED, ptDest.x, ptDest.y);
|
}
|
|
|
return ::DefWindowProc(m_hWnd, WM_LBUTTONDBLCLK, wParam, lParam);
|
}
|
|
/*
|
* WM_MOUSEWHEEL
|
* Êó±ê¹ö¶¯
|
*/
|
LRESULT CMapPosWnd::OnMouseWheel(WPARAM wParam, LPARAM lParam)
|
{
|
return ::DefWindowProc(m_hWnd, WM_MOUSEWHEEL, wParam, lParam);
|
}
|
|
/*
|
* WM_KEYDOWN
|
* ¼üÅÌÏûÏ¢£¬°´Ï°´¼ü
|
*/
|
LRESULT CMapPosWnd::OnKeyDown(WPARAM wParam, LPARAM lParam)
|
{
|
BOOL bChanged = FALSE;
|
if (wParam == VK_DELETE) {
|
|
}
|
|
|
if (bChanged) {
|
RECT rcClient;
|
GetClientRect(m_hWnd, &rcClient);
|
::InvalidateRect(m_hWnd, &rcClient, TRUE);
|
}
|
|
return ::DefWindowProc(m_hWnd, WM_KEYDOWN, wParam, lParam);
|
}
|
|
/*
|
* WM_NCPAINT
|
*/
|
LRESULT CMapPosWnd::OnNcPaint(WPARAM wParam, LPARAM lParam)
|
{
|
LRESULT lRet = ::DefWindowProc(m_hWnd, WM_NCPAINT, wParam, lParam);
|
|
|
long styleEx = GetWindowLong(m_hWnd, GWL_EXSTYLE);
|
if ((styleEx & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE) {
|
|
RECT rect, rcClient;
|
GetClientRect(m_hWnd, &rcClient);
|
::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left);
|
::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right);
|
GetWindowRect(m_hWnd, &rect);
|
rcClient.right = rect.right - 1;
|
rcClient.bottom = rect.bottom - 1;
|
::OffsetRect(&rcClient, -rect.left, -rect.top);
|
|
rect.right -= rect.left;
|
rect.bottom -= rect.top;
|
rect.left = 0;
|
rect.top = 0;
|
|
HRGN hRgnWnd = CreateRectRgnIndirect(&rect);
|
HRGN hRgnClient = CreateRectRgnIndirect(&rcClient);
|
|
HBRUSH hBrushBK, hBrushFrame;
|
HDC hDC = ::GetWindowDC(m_hWnd);
|
::SelectClipRgn(hDC, hRgnWnd);
|
::ExtSelectClipRgn(hDC, hRgnClient, RGN_DIFF);
|
|
hBrushBK = CreateSolidBrush(m_crBkgnd);
|
::FillRect(hDC, &rect, hBrushBK);
|
DeleteObject(hBrushBK);
|
|
hBrushFrame = CreateSolidBrush(m_crFrame);
|
::FrameRect(hDC, &rect, hBrushFrame);
|
|
::DeleteObject(hRgnWnd);
|
::DeleteObject(hRgnClient);
|
DeleteObject(hBrushFrame);
|
::ReleaseDC(m_hWnd, hDC);
|
}
|
|
return lRet;
|
}
|
|
/*
|
* WM_PAINT
|
*/
|
LRESULT CMapPosWnd::OnPaint(WPARAM wParam, LPARAM lParam)
|
{
|
HDC hDC, hMemDC;
|
HBITMAP hBitmap;
|
RECT rcClient;
|
CString strText;
|
HBRUSH hBrushBK;
|
|
|
// BeginPaint
|
PAINTSTRUCT ps;
|
hDC = BeginPaint(m_hWnd, &ps);
|
GetClientRect(m_hWnd, &rcClient);
|
|
hMemDC = ::CreateCompatibleDC(hDC);
|
hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
|
rcClient.bottom - rcClient.top);
|
::SelectObject(hMemDC, hBitmap);
|
|
|
// ±³¾°ÑÕÉ«
|
hBrushBK = CreateSolidBrush(m_crBkgnd);
|
::FillRect(hMemDC, &rcClient, hBrushBK);
|
DeleteObject(hBrushBK);
|
|
|
// ±êÌâ
|
{
|
char szTitle[256];
|
GetWindowText(m_hWnd, szTitle, 256);
|
RECT rcTitle;
|
rcTitle.left = rcClient.left + 2;
|
rcTitle.top = rcClient.top + 2;
|
rcTitle.bottom = rcClient.bottom - 2;
|
rcTitle.right = rcClient.right - 2;
|
::DrawText(hMemDC, szTitle, (int)strlen(szTitle), &rcTitle, DT_LEFT | DT_TOP);
|
}
|
|
|
// View port
|
RECT rcViewPort;
|
GetViewPortRect(&rcClient, &rcViewPort);
|
HBRUSH hBrushFrame = CreateSolidBrush(m_crViewPort);
|
::FrameRect(hMemDC, &rcViewPort, hBrushFrame);
|
::DeleteObject(hBrushFrame);
|
|
|
// EndPaint
|
::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
|
hMemDC, 0, 0, SRCCOPY);
|
EndPaint(m_hWnd, &ps);
|
::DeleteObject(hBitmap);
|
::DeleteDC(hMemDC);
|
|
|
return 1;
|
}
|
|
/*
|
* WM_SIZE
|
*/
|
LRESULT CMapPosWnd::OnSize(WPARAM wParam, LPARAM lParam)
|
{
|
LRESULT lRet = ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam);
|
|
return lRet;
|
}
|
|
/*
|
* ÉèÖñ³¾°ÑÕÉ«
|
* color -- ±³¾°É«
|
*/
|
void CMapPosWnd::SetBkgndColor(COLORREF color)
|
{
|
m_crBkgnd = color;
|
}
|
|
/*
|
* ±ß¿òÑÕÉ«
|
* color -- ±ß¿òÉ«
|
*/
|
void CMapPosWnd::SetFrameColor(COLORREF color)
|
{
|
m_crFrame = color;
|
}
|