#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; }