Index: third_party/wtl/include/atlscrl.h |
diff --git a/third_party/wtl/include/atlscrl.h b/third_party/wtl/include/atlscrl.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bafb595455dc0cb0e8baf961f9939e743cceb655 |
--- /dev/null |
+++ b/third_party/wtl/include/atlscrl.h |
@@ -0,0 +1,2012 @@ |
+// Windows Template Library - WTL version 8.0 |
+// Copyright (C) Microsoft Corporation. All rights reserved. |
+// |
+// This file is a part of the Windows Template Library. |
+// The use and distribution terms for this software are covered by the |
+// Microsoft Permissive License (Ms-PL) which can be found in the file |
+// Ms-PL.txt at the root of this distribution. |
+ |
+#ifndef __ATLSCRL_H__ |
+#define __ATLSCRL_H__ |
+ |
+#pragma once |
+ |
+#ifndef __cplusplus |
+ #error ATL requires C++ compilation (use a .cpp suffix) |
+#endif |
+ |
+#ifndef __ATLAPP_H__ |
+ #error atlscrl.h requires atlapp.h to be included first |
+#endif |
+ |
+#ifndef __ATLWIN_H__ |
+ #error atlscrl.h requires atlwin.h to be included first |
+#endif |
+ |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ #include <zmouse.h> |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ |
+#ifndef GET_WHEEL_DELTA_WPARAM |
+ #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam)) |
+#endif |
+ |
+#ifndef WM_MOUSEHWHEEL |
+ #define WM_MOUSEHWHEEL 0x020E |
+#endif |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// Classes in this file: |
+// |
+// CScrollImpl<T> |
+// CScrollWindowImpl<T, TBase, TWinTraits> |
+// CMapScrollImpl<T> |
+// CMapScrollWindowImpl<T, TBase, TWinTraits> |
+// CFSBWindowT<TBase> |
+// CZoomScrollImpl<T> |
+// CZoomScrollWindowImpl<T, TBase, TWinTraits> |
+// CScrollContainerImpl<T, TBase, TWinTraits> |
+// CScrollContainer |
+ |
+namespace WTL |
+{ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CScrollImpl - Provides scrolling support to any window |
+ |
+// Scroll extended styles |
+#define SCRL_SCROLLCHILDREN 0x00000001 |
+#define SCRL_ERASEBACKGROUND 0x00000002 |
+#define SCRL_NOTHUMBTRACKING 0x00000004 |
+#if (WINVER >= 0x0500) |
+#define SCRL_SMOOTHSCROLL 0x00000008 |
+#endif // (WINVER >= 0x0500) |
+#define SCRL_DISABLENOSCROLLV 0x00000010 |
+#define SCRL_DISABLENOSCROLLH 0x00000020 |
+#define SCRL_DISABLENOSCROLL (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH) |
+ |
+ |
+template <class T> |
+class CScrollImpl |
+{ |
+public: |
+ enum { uSCROLL_FLAGS = SW_INVALIDATE }; |
+ |
+ POINT m_ptOffset; |
+ SIZE m_sizeAll; |
+ SIZE m_sizeLine; |
+ SIZE m_sizePage; |
+ SIZE m_sizeClient; |
+ int m_zDelta; // current wheel value |
+ int m_nWheelLines; // number of lines to scroll on wheel |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ // Note that this message must be forwarded from a top level window |
+ UINT m_uMsgMouseWheel; // MSH_MOUSEWHEEL |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ int m_zHDelta; // current horizontal wheel value |
+ int m_nHWheelChars; // number of chars to scroll on horizontal wheel |
+ UINT m_uScrollFlags; |
+ DWORD m_dwExtendedStyle; // scroll specific extended styles |
+ |
+// Constructor |
+ CScrollImpl() : m_zDelta(0), m_nWheelLines(3), |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ m_uMsgMouseWheel(0U), |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ m_zHDelta(0), m_nHWheelChars(3), |
+ m_uScrollFlags(0U), m_dwExtendedStyle(0) |
+ { |
+ m_ptOffset.x = 0; |
+ m_ptOffset.y = 0; |
+ m_sizeAll.cx = 0; |
+ m_sizeAll.cy = 0; |
+ m_sizePage.cx = 0; |
+ m_sizePage.cy = 0; |
+ m_sizeLine.cx = 0; |
+ m_sizeLine.cy = 0; |
+ m_sizeClient.cx = 0; |
+ m_sizeClient.cy = 0; |
+ |
+ SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND); |
+ } |
+ |
+// Attributes & Operations |
+ DWORD GetScrollExtendedStyle() const |
+ { |
+ return m_dwExtendedStyle; |
+ } |
+ |
+ DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) |
+ { |
+ DWORD dwPrevStyle = m_dwExtendedStyle; |
+ if(dwMask == 0) |
+ m_dwExtendedStyle = dwExtendedStyle; |
+ else |
+ m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); |
+ // cache scroll flags |
+ T* pT = static_cast<T*>(this); |
+ pT; // avoid level 4 warning |
+ m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0); |
+#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) |
+ m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0); |
+#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) |
+ return dwPrevStyle; |
+ } |
+ |
+ // offset operations |
+ void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+ pT->AdjustScrollOffset(x, y); |
+ |
+ int dx = m_ptOffset.x - x; |
+ int dy = m_ptOffset.y - y; |
+ m_ptOffset.x = x; |
+ m_ptOffset.y = y; |
+ |
+ // block: set horizontal scroll bar |
+ { |
+ SCROLLINFO si = { sizeof(SCROLLINFO) }; |
+ si.fMask = SIF_POS; |
+ if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) |
+ si.fMask |= SIF_DISABLENOSCROLL; |
+ si.nPos = m_ptOffset.x; |
+ pT->SetScrollInfo(SB_HORZ, &si, bRedraw); |
+ } |
+ |
+ // block: set vertical scroll bar |
+ { |
+ SCROLLINFO si = { sizeof(SCROLLINFO) }; |
+ si.fMask = SIF_POS; |
+ if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) |
+ si.fMask |= SIF_DISABLENOSCROLL; |
+ si.nPos = m_ptOffset.y; |
+ pT->SetScrollInfo(SB_VERT, &si, bRedraw); |
+ } |
+ |
+ // Move all children if needed |
+ if(IsScrollingChildren() && (dx != 0 || dy != 0)) |
+ { |
+ for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT)) |
+ { |
+ RECT rect = { 0 }; |
+ ::GetWindowRect(hWndChild, &rect); |
+ ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1); |
+ ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); |
+ } |
+ } |
+ |
+ if(bRedraw) |
+ pT->Invalidate(); |
+ } |
+ |
+ void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE) |
+ { |
+ SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw); |
+ } |
+ |
+ void GetScrollOffset(POINT& ptOffset) const |
+ { |
+ ptOffset = m_ptOffset; |
+ } |
+ |
+ // size operations |
+ void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+ m_sizeAll.cx = cx; |
+ m_sizeAll.cy = cy; |
+ |
+ int x = 0; |
+ int y = 0; |
+ if(!bResetOffset) |
+ { |
+ x = m_ptOffset.x; |
+ y = m_ptOffset.y; |
+ pT->AdjustScrollOffset(x, y); |
+ } |
+ |
+ int dx = m_ptOffset.x - x; |
+ int dy = m_ptOffset.y - y; |
+ m_ptOffset.x = x; |
+ m_ptOffset.y = y; |
+ |
+ // block: set horizontal scroll bar |
+ { |
+ SCROLLINFO si = { sizeof(SCROLLINFO) }; |
+ si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; |
+ if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) |
+ si.fMask |= SIF_DISABLENOSCROLL; |
+ si.nMin = 0; |
+ si.nMax = m_sizeAll.cx - 1; |
+ si.nPage = m_sizeClient.cx; |
+ si.nPos = m_ptOffset.x; |
+ pT->SetScrollInfo(SB_HORZ, &si, bRedraw); |
+ } |
+ |
+ // block: set vertical scroll bar |
+ { |
+ SCROLLINFO si = { sizeof(SCROLLINFO) }; |
+ si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; |
+ if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) |
+ si.fMask |= SIF_DISABLENOSCROLL; |
+ si.nMin = 0; |
+ si.nMax = m_sizeAll.cy - 1; |
+ si.nPage = m_sizeClient.cy; |
+ si.nPos = m_ptOffset.y; |
+ pT->SetScrollInfo(SB_VERT, &si, bRedraw); |
+ } |
+ |
+ // Move all children if needed |
+ if(IsScrollingChildren() && (dx != 0 || dy != 0)) |
+ { |
+ for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT)) |
+ { |
+ RECT rect = { 0 }; |
+ ::GetWindowRect(hWndChild, &rect); |
+ ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1); |
+ ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); |
+ } |
+ } |
+ |
+ SetScrollLine(0, 0); |
+ SetScrollPage(0, 0); |
+ |
+ if(bRedraw) |
+ pT->Invalidate(); |
+ } |
+ |
+ void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true) |
+ { |
+ SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset); |
+ } |
+ |
+ void GetScrollSize(SIZE& sizeWnd) const |
+ { |
+ sizeWnd = m_sizeAll; |
+ } |
+ |
+ // line operations |
+ void SetScrollLine(int cxLine, int cyLine) |
+ { |
+ ATLASSERT(cxLine >= 0 && cyLine >= 0); |
+ ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0); |
+ |
+ m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100); |
+ m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100); |
+ } |
+ |
+ void SetScrollLine(SIZE sizeLine) |
+ { |
+ SetScrollLine(sizeLine.cx, sizeLine.cy); |
+ } |
+ |
+ void GetScrollLine(SIZE& sizeLine) const |
+ { |
+ sizeLine = m_sizeLine; |
+ } |
+ |
+ // page operations |
+ void SetScrollPage(int cxPage, int cyPage) |
+ { |
+ ATLASSERT(cxPage >= 0 && cyPage >= 0); |
+ ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0); |
+ |
+ m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10); |
+ m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10); |
+ } |
+ |
+ void SetScrollPage(SIZE sizePage) |
+ { |
+ SetScrollPage(sizePage.cx, sizePage.cy); |
+ } |
+ |
+ void GetScrollPage(SIZE& sizePage) const |
+ { |
+ sizePage = m_sizePage; |
+ } |
+ |
+ // commands |
+ void ScrollLineDown() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); |
+ } |
+ |
+ void ScrollLineUp() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); |
+ } |
+ |
+ void ScrollPageDown() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); |
+ } |
+ |
+ void ScrollPageUp() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); |
+ } |
+ |
+ void ScrollTop() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); |
+ } |
+ |
+ void ScrollBottom() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); |
+ } |
+ |
+ void ScrollLineRight() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ } |
+ |
+ void ScrollLineLeft() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ } |
+ |
+ void ScrollPageRight() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ } |
+ |
+ void ScrollPageLeft() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ } |
+ |
+ void ScrollAllLeft() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ } |
+ |
+ void ScrollAllRight() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ } |
+ |
+ // scroll to make point/view/window visible |
+ void ScrollToView(POINT pt) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ RECT rect = { pt.x, pt.y, pt.x, pt.y }; |
+ pT->ScrollToView(rect); |
+ } |
+ |
+ void ScrollToView(RECT& rect) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+ RECT rcClient = { 0 }; |
+ pT->GetClientRect(&rcClient); |
+ |
+ int x = m_ptOffset.x; |
+ if(rect.left < m_ptOffset.x) |
+ x = rect.left; |
+ else if(rect.right > (m_ptOffset.x + rcClient.right)) |
+ x = rect.right - rcClient.right; |
+ |
+ int y = m_ptOffset.y; |
+ if(rect.top < m_ptOffset.y) |
+ y = rect.top; |
+ else if(rect.bottom > (m_ptOffset.y + rcClient.bottom)) |
+ y = rect.bottom - rcClient.bottom; |
+ |
+ SetScrollOffset(x, y); |
+ } |
+ |
+ void ScrollToView(HWND hWnd) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+ RECT rect = { 0 }; |
+ ::GetWindowRect(hWnd, &rect); |
+ ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2); |
+ ScrollToView(rect); |
+ } |
+ |
+ BEGIN_MSG_MAP(CScrollImpl) |
+ MESSAGE_HANDLER(WM_CREATE, OnCreate) |
+ MESSAGE_HANDLER(WM_VSCROLL, OnVScroll) |
+ MESSAGE_HANDLER(WM_HSCROLL, OnHScroll) |
+ MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel) |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ MESSAGE_HANDLER(m_uMsgMouseWheel, OnMouseWheel) |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel) |
+ MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) |
+ MESSAGE_HANDLER(WM_SIZE, OnSize) |
+ MESSAGE_HANDLER(WM_PAINT, OnPaint) |
+#ifndef _WIN32_WCE |
+ MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) |
+#endif // !_WIN32_WCE |
+ // standard scroll commands |
+ ALT_MSG_MAP(1) |
+ COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop) |
+ COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom) |
+ COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight) |
+ END_MSG_MAP() |
+ |
+ LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) |
+ { |
+ GetSystemSettings(); |
+ bHandled = FALSE; |
+ return 1; |
+ } |
+ |
+ LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); |
+ return 0; |
+ } |
+ |
+ LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ return 0; |
+ } |
+ |
+ LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE) |
+ uMsg; |
+ int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam); |
+#else |
+ int zDelta = (uMsg == WM_MOUSEWHEEL) ? (int)GET_WHEEL_DELTA_WPARAM(wParam) : (int)wParam; |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE)) |
+ int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN); |
+ m_zDelta += zDelta; // cumulative |
+ int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines; |
+ if(m_sizeAll.cy > m_sizeClient.cy) |
+ { |
+ for(int i = 0; i < zTotal; i += WHEEL_DELTA) |
+ { |
+ pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); |
+ pT->UpdateWindow(); |
+ } |
+ } |
+ else // can't scroll vertically, scroll horizontally |
+ { |
+ for(int i = 0; i < zTotal; i += WHEEL_DELTA) |
+ { |
+ pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ pT->UpdateWindow(); |
+ } |
+ } |
+ m_zDelta %= WHEEL_DELTA; |
+ |
+ return 0; |
+ } |
+ |
+ LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+ int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam); |
+ int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT); |
+ m_zHDelta += zDelta; // cumulative |
+ int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars; |
+ if(m_sizeAll.cx > m_sizeClient.cx) |
+ { |
+ for(int i = 0; i < zTotal; i += WHEEL_DELTA) |
+ { |
+ pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); |
+ pT->UpdateWindow(); |
+ } |
+ } |
+ m_zHDelta %= WHEEL_DELTA; |
+ |
+ return 0; |
+ } |
+ |
+ LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ GetSystemSettings(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+ m_sizeClient.cx = GET_X_LPARAM(lParam); |
+ m_sizeClient.cy = GET_Y_LPARAM(lParam); |
+ |
+ // block: set horizontal scroll bar |
+ { |
+ SCROLLINFO si = { sizeof(SCROLLINFO) }; |
+ si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; |
+ si.nMin = 0; |
+ si.nMax = m_sizeAll.cx - 1; |
+ if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) |
+ si.fMask |= SIF_DISABLENOSCROLL; |
+ si.nPage = m_sizeClient.cx; |
+ si.nPos = m_ptOffset.x; |
+ pT->SetScrollInfo(SB_HORZ, &si, TRUE); |
+ } |
+ |
+ // block: set vertical scroll bar |
+ { |
+ SCROLLINFO si = { sizeof(SCROLLINFO) }; |
+ si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; |
+ si.nMin = 0; |
+ si.nMax = m_sizeAll.cy - 1; |
+ if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) |
+ si.fMask |= SIF_DISABLENOSCROLL; |
+ si.nPage = m_sizeClient.cy; |
+ si.nPos = m_ptOffset.y; |
+ pT->SetScrollInfo(SB_VERT, &si, TRUE); |
+ } |
+ |
+ int x = m_ptOffset.x; |
+ int y = m_ptOffset.y; |
+ if(pT->AdjustScrollOffset(x, y)) |
+ { |
+ // Children will be moved in SetScrollOffset, if needed |
+ pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN)); |
+ SetScrollOffset(x, y, FALSE); |
+ } |
+ |
+ bHandled = FALSE; |
+ return 1; |
+ } |
+ |
+ LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ if(wParam != NULL) |
+ { |
+ CDCHandle dc = (HDC)wParam; |
+ POINT ptViewportOrg = { 0, 0 }; |
+ dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); |
+ pT->DoPaint(dc); |
+ dc.SetViewportOrg(ptViewportOrg); |
+ } |
+ else |
+ { |
+ CPaintDC dc(pT->m_hWnd); |
+ dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); |
+ pT->DoPaint(dc.m_hDC); |
+ } |
+ return 0; |
+ } |
+ |
+ // scrolling handlers |
+ LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollLineUp(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollLineDown(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollPageUp(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollPageDown(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollTop(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollBottom(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollLineLeft(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollLineRight(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollPageLeft(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollPageRight(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollAllLeft(); |
+ return 0; |
+ } |
+ |
+ LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
+ { |
+ ScrollAllRight(); |
+ return 0; |
+ } |
+ |
+// Overrideables |
+ void DoPaint(CDCHandle /*dc*/) |
+ { |
+ // must be implemented in a derived class |
+ ATLASSERT(FALSE); |
+ } |
+ |
+// Implementation |
+ void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ RECT rect = { 0 }; |
+ pT->GetClientRect(&rect); |
+ int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right; |
+ int cxyMax = cxySizeAll - cxyClient; |
+ |
+ if(cxyMax < 0) // can't scroll, client area is bigger |
+ return; |
+ |
+ bool bUpdate = true; |
+ int cxyScroll = 0; |
+ |
+ switch(nScrollCode) |
+ { |
+ case SB_TOP: // top or all left |
+ cxyScroll = cxyOffset; |
+ cxyOffset = 0; |
+ break; |
+ case SB_BOTTOM: // bottom or all right |
+ cxyScroll = cxyOffset - cxyMax; |
+ cxyOffset = cxyMax; |
+ break; |
+ case SB_LINEUP: // line up or line left |
+ if(cxyOffset >= cxySizeLine) |
+ { |
+ cxyScroll = cxySizeLine; |
+ cxyOffset -= cxySizeLine; |
+ } |
+ else |
+ { |
+ cxyScroll = cxyOffset; |
+ cxyOffset = 0; |
+ } |
+ break; |
+ case SB_LINEDOWN: // line down or line right |
+ if(cxyOffset < cxyMax - cxySizeLine) |
+ { |
+ cxyScroll = -cxySizeLine; |
+ cxyOffset += cxySizeLine; |
+ } |
+ else |
+ { |
+ cxyScroll = cxyOffset - cxyMax; |
+ cxyOffset = cxyMax; |
+ } |
+ break; |
+ case SB_PAGEUP: // page up or page left |
+ if(cxyOffset >= cxySizePage) |
+ { |
+ cxyScroll = cxySizePage; |
+ cxyOffset -= cxySizePage; |
+ } |
+ else |
+ { |
+ cxyScroll = cxyOffset; |
+ cxyOffset = 0; |
+ } |
+ break; |
+ case SB_PAGEDOWN: // page down or page right |
+ if(cxyOffset < cxyMax - cxySizePage) |
+ { |
+ cxyScroll = -cxySizePage; |
+ cxyOffset += cxySizePage; |
+ } |
+ else |
+ { |
+ cxyScroll = cxyOffset - cxyMax; |
+ cxyOffset = cxyMax; |
+ } |
+ break; |
+ case SB_THUMBTRACK: |
+ if(IsNoThumbTracking()) |
+ break; |
+ // else fall through |
+ case SB_THUMBPOSITION: |
+ { |
+ SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS }; |
+ if(pT->GetScrollInfo(nType, &si)) |
+ { |
+ cxyScroll = cxyOffset - si.nTrackPos; |
+ cxyOffset = si.nTrackPos; |
+ } |
+ } |
+ break; |
+ case SB_ENDSCROLL: |
+ default: |
+ bUpdate = false; |
+ break; |
+ } |
+ |
+ if(bUpdate && cxyScroll != 0) |
+ { |
+ pT->SetScrollPos(nType, cxyOffset, TRUE); |
+ if(nType == SB_VERT) |
+ pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags); |
+ else |
+ pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags); |
+ } |
+ } |
+ |
+ static int CalcLineOrPage(int nVal, int nMax, int nDiv) |
+ { |
+ if(nVal == 0) |
+ { |
+ nVal = nMax / nDiv; |
+ if(nVal < 1) |
+ nVal = 1; |
+ } |
+ else if(nVal > nMax) |
+ { |
+ nVal = nMax; |
+ } |
+ |
+ return nVal; |
+ } |
+ |
+ bool AdjustScrollOffset(int& x, int& y) |
+ { |
+ int xOld = x; |
+ int yOld = y; |
+ |
+ int cxMax = m_sizeAll.cx - m_sizeClient.cx; |
+ if(x > cxMax) |
+ x = (cxMax >= 0) ? cxMax : 0; |
+ else if(x < 0) |
+ x = 0; |
+ |
+ int cyMax = m_sizeAll.cy - m_sizeClient.cy; |
+ if(y > cyMax) |
+ y = (cyMax >= 0) ? cyMax : 0; |
+ else if(y < 0) |
+ y = 0; |
+ |
+ return (x != xOld || y != yOld); |
+ } |
+ |
+ void GetSystemSettings() |
+ { |
+#ifndef _WIN32_WCE |
+#ifndef SPI_GETWHEELSCROLLLINES |
+ const UINT SPI_GETWHEELSCROLLLINES = 104; |
+#endif // !SPI_GETWHEELSCROLLLINES |
+ ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0); |
+ |
+#ifndef SPI_GETWHEELSCROLLCHARS |
+ const UINT SPI_GETWHEELSCROLLCHARS = 0x006C; |
+#endif // !SPI_GETWHEELSCROLLCHARS |
+ ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0); |
+ |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ if(m_uMsgMouseWheel != 0) |
+ m_uMsgMouseWheel = ::RegisterWindowMessage(MSH_MOUSEWHEEL); |
+ |
+ HWND hWndWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); |
+ if(::IsWindow(hWndWheel)) |
+ { |
+ UINT uMsgScrollLines = ::RegisterWindowMessage(MSH_SCROLL_LINES); |
+ if(uMsgScrollLines != 0) |
+ m_nWheelLines = (int)::SendMessage(hWndWheel, uMsgScrollLines, 0, 0L); |
+ } |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+#endif // !_WIN32_WCE |
+ } |
+ |
+ bool IsScrollingChildren() const |
+ { |
+ return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0; |
+ } |
+ |
+ bool IsErasingBackground() const |
+ { |
+ return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0; |
+ } |
+ |
+ bool IsNoThumbTracking() const |
+ { |
+ return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0; |
+ } |
+ |
+#if (WINVER >= 0x0500) |
+ bool IsSmoothScroll() const |
+ { |
+ return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0; |
+ } |
+#endif // (WINVER >= 0x0500) |
+}; |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CScrollWindowImpl - Implements a scrollable window |
+ |
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits> |
+class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CScrollImpl< T > |
+{ |
+public: |
+ BEGIN_MSG_MAP(CScrollWindowImpl) |
+ MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) |
+ MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) |
+ MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) |
+ MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) |
+ MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) |
+ MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) |
+ MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint) |
+#ifndef _WIN32_WCE |
+ MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint) |
+#endif // !_WIN32_WCE |
+ ALT_MSG_MAP(1) |
+ COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) |
+ COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) |
+ COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) |
+ END_MSG_MAP() |
+}; |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CMapScrollImpl - Provides mapping and scrolling support to any window |
+ |
+#ifndef _WIN32_WCE |
+ |
+template <class T> |
+class CMapScrollImpl : public CScrollImpl< T > |
+{ |
+public: |
+ int m_nMapMode; |
+ RECT m_rectLogAll; |
+ SIZE m_sizeLogLine; |
+ SIZE m_sizeLogPage; |
+ |
+// Constructor |
+ CMapScrollImpl() : m_nMapMode(MM_TEXT) |
+ { |
+ ::SetRectEmpty(&m_rectLogAll); |
+ m_sizeLogPage.cx = 0; |
+ m_sizeLogPage.cy = 0; |
+ m_sizeLogLine.cx = 0; |
+ m_sizeLogLine.cy = 0; |
+ } |
+ |
+// Attributes & Operations |
+ // mapping mode operations |
+ void SetScrollMapMode(int nMapMode) |
+ { |
+ ATLASSERT(nMapMode >= MM_MIN && nMapMode <= MM_MAX_FIXEDSCALE); |
+ m_nMapMode = nMapMode; |
+ } |
+ |
+ int GetScrollMapMode() const |
+ { |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ return m_nMapMode; |
+ } |
+ |
+ // offset operations |
+ void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE) |
+ { |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ POINT ptOff = { x, y }; |
+ // block: convert logical to device units |
+ { |
+ CWindowDC dc(NULL); |
+ dc.SetMapMode(m_nMapMode); |
+ dc.LPtoDP(&ptOff); |
+ } |
+ CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw); |
+ } |
+ |
+ void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE) |
+ { |
+ SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw); |
+ } |
+ |
+ void GetScrollOffset(POINT& ptOffset) const |
+ { |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ ptOffset = m_ptOffset; |
+ // block: convert device to logical units |
+ { |
+ CWindowDC dc(NULL); |
+ dc.SetMapMode(m_nMapMode); |
+ dc.DPtoLP(&ptOffset); |
+ } |
+ } |
+ |
+ // size operations |
+ void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true) |
+ { |
+ ATLASSERT(xMax > xMin && yMax > yMin); |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ |
+ ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax); |
+ |
+ SIZE sizeAll = { 0 }; |
+ sizeAll.cx = xMax - xMin + 1; |
+ sizeAll.cy = yMax - yMin + 1; |
+ // block: convert logical to device units |
+ { |
+ CWindowDC dc(NULL); |
+ dc.SetMapMode(m_nMapMode); |
+ dc.LPtoDP(&sizeAll); |
+ } |
+ CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset); |
+ SetScrollLine(0, 0); |
+ SetScrollPage(0, 0); |
+ } |
+ |
+ void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true) |
+ { |
+ SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset); |
+ } |
+ |
+ void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true) |
+ { |
+ SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset); |
+ } |
+ |
+ void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true) |
+ { |
+ SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset); |
+ } |
+ |
+ void GetScrollSize(RECT& rcScroll) const |
+ { |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ rcScroll = m_rectLogAll; |
+ } |
+ |
+ // line operations |
+ void SetScrollLine(int cxLine, int cyLine) |
+ { |
+ ATLASSERT(cxLine >= 0 && cyLine >= 0); |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ |
+ m_sizeLogLine.cx = cxLine; |
+ m_sizeLogLine.cy = cyLine; |
+ SIZE sizeLine = m_sizeLogLine; |
+ // block: convert logical to device units |
+ { |
+ CWindowDC dc(NULL); |
+ dc.SetMapMode(m_nMapMode); |
+ dc.LPtoDP(&sizeLine); |
+ } |
+ CScrollImpl< T >::SetScrollLine(sizeLine); |
+ } |
+ |
+ void SetScrollLine(SIZE sizeLine) |
+ { |
+ SetScrollLine(sizeLine.cx, sizeLine.cy); |
+ } |
+ |
+ void GetScrollLine(SIZE& sizeLine) const |
+ { |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ sizeLine = m_sizeLogLine; |
+ } |
+ |
+ // page operations |
+ void SetScrollPage(int cxPage, int cyPage) |
+ { |
+ ATLASSERT(cxPage >= 0 && cyPage >= 0); |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ |
+ m_sizeLogPage.cx = cxPage; |
+ m_sizeLogPage.cy = cyPage; |
+ SIZE sizePage = m_sizeLogPage; |
+ // block: convert logical to device units |
+ { |
+ CWindowDC dc(NULL); |
+ dc.SetMapMode(m_nMapMode); |
+ dc.LPtoDP(&sizePage); |
+ } |
+ CScrollImpl< T >::SetScrollPage(sizePage); |
+ } |
+ |
+ void SetScrollPage(SIZE sizePage) |
+ { |
+ SetScrollPage(sizePage.cx, sizePage.cy); |
+ } |
+ |
+ void GetScrollPage(SIZE& sizePage) const |
+ { |
+ ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); |
+ sizePage = m_sizeLogPage; |
+ } |
+ |
+ BEGIN_MSG_MAP(CMapScrollImpl) |
+ MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) |
+ MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) |
+ MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) |
+ MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) |
+ MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) |
+ MESSAGE_HANDLER(WM_PAINT, OnPaint) |
+ MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) |
+ ALT_MSG_MAP(1) |
+ COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) |
+ COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) |
+ COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) |
+ END_MSG_MAP() |
+ |
+ LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ if(wParam != NULL) |
+ { |
+ CDCHandle dc = (HDC)wParam; |
+ int nMapModeSav = dc.GetMapMode(); |
+ dc.SetMapMode(m_nMapMode); |
+ POINT ptViewportOrg = { 0, 0 }; |
+ if(m_nMapMode == MM_TEXT) |
+ dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); |
+ else |
+ dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy, &ptViewportOrg); |
+ POINT ptWindowOrg = { 0, 0 }; |
+ dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg); |
+ |
+ pT->DoPaint(dc); |
+ |
+ dc.SetMapMode(nMapModeSav); |
+ dc.SetViewportOrg(ptViewportOrg); |
+ dc.SetWindowOrg(ptWindowOrg); |
+ } |
+ else |
+ { |
+ CPaintDC dc(pT->m_hWnd); |
+ dc.SetMapMode(m_nMapMode); |
+ if(m_nMapMode == MM_TEXT) |
+ dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); |
+ else |
+ dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy); |
+ dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top); |
+ pT->DoPaint(dc.m_hDC); |
+ } |
+ return 0; |
+ } |
+}; |
+ |
+#endif // !_WIN32_WCE |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CMapScrollWindowImpl - Implements scrolling window with mapping |
+ |
+#ifndef _WIN32_WCE |
+ |
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits> |
+class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T > |
+{ |
+public: |
+ BEGIN_MSG_MAP(CMapScrollWindowImpl) |
+ MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) |
+ MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) |
+ MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) |
+ MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) |
+ MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) |
+ MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint) |
+ MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint) |
+ ALT_MSG_MAP(1) |
+ COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) |
+ COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) |
+ COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) |
+ END_MSG_MAP() |
+}; |
+ |
+#endif // !_WIN32_WCE |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support |
+ |
+#if defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) |
+ |
+template <class TBase = ATL::CWindow> |
+class CFSBWindowT : public TBase, public CFlatScrollBarImpl<CFSBWindowT< TBase > > |
+{ |
+public: |
+// Constructors |
+ CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd) |
+ { } |
+ |
+ CFSBWindowT< TBase >& operator =(HWND hWnd) |
+ { |
+ m_hWnd = hWnd; |
+ return *this; |
+ } |
+ |
+// CWindow overrides that use flat scroll bar API |
+// (only those methods that are used by scroll window classes) |
+ int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) |
+ { |
+ ATLASSERT(::IsWindow(m_hWnd)); |
+ return FlatSB_SetScrollPos(nBar, nPos, bRedraw); |
+ } |
+ |
+ BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) |
+ { |
+ ATLASSERT(::IsWindow(m_hWnd)); |
+ return FlatSB_GetScrollInfo(nBar, lpScrollInfo); |
+ } |
+ |
+ BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) |
+ { |
+ ATLASSERT(::IsWindow(m_hWnd)); |
+ return FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw); |
+ } |
+}; |
+ |
+typedef CFSBWindowT<ATL::CWindow> CFSBWindow; |
+ |
+#endif // defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CZoomScrollImpl - Provides zooming and scrolling support to any window |
+ |
+#ifndef _WIN32_WCE |
+ |
+// The zoom modes that can be set with the SetZoomMode method |
+enum |
+{ |
+ ZOOMMODE_OFF, |
+ ZOOMMODE_IN, // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged. |
+ ZOOMMODE_OUT // If left mouse button clicked, zoom out on point clicked. |
+}; |
+ |
+// Notification to parent that zoom scale changed as a result of user mouse action. |
+#define ZSN_ZOOMCHANGED (NM_FIRST - 50) |
+ |
+template <class T> |
+class CZoomScrollImpl : public CScrollImpl< T > |
+{ |
+public: |
+ enum { m_cxyMinZoomRect = 12 }; // min rect size to zoom in on rect. |
+ |
+// Data members |
+ SIZE m_sizeLogAll; |
+ SIZE m_sizeLogLine; |
+ SIZE m_sizeLogPage; |
+ float m_fZoomScale; |
+ float m_fZoomScaleMin; |
+ float m_fZoomDelta; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click. |
+ int m_nZoomMode; |
+ RECT m_rcTrack; |
+ bool m_bTracking; |
+ |
+// Constructor |
+ CZoomScrollImpl(): |
+ m_fZoomScale(1.0), |
+ m_fZoomScaleMin(0.5), |
+ m_fZoomDelta(0.5), |
+ m_nZoomMode(ZOOMMODE_OFF), |
+ m_bTracking(false) |
+ { |
+ m_sizeLogAll.cx = 0; |
+ m_sizeLogAll.cy = 0; |
+ m_sizeLogPage.cx = 0; |
+ m_sizeLogPage.cy = 0; |
+ m_sizeLogLine.cx = 0; |
+ m_sizeLogLine.cy = 0; |
+ ::SetRectEmpty(&m_rcTrack); |
+ } |
+ |
+// Attributes & Operations |
+ |
+ // size operations |
+ void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true) |
+ { |
+ ATLASSERT(cxLog >= 0 && cyLog >= 0); |
+ |
+ // Set up the defaults |
+ if (cxLog == 0 && cyLog == 0) |
+ { |
+ cxLog = 1; |
+ cyLog = 1; |
+ } |
+ |
+ m_sizeLogAll.cx = cxLog; |
+ m_sizeLogAll.cy = cyLog; |
+ SIZE sizeAll = { 0 }; |
+ sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale); |
+ sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale); |
+ |
+ CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset); |
+ } |
+ |
+ void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true) |
+ { |
+ SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset); |
+ } |
+ |
+ void GetScrollSize(SIZE& sizeLog) const |
+ { |
+ sizeLog = m_sizeLogAll; |
+ } |
+ |
+ // line operations |
+ void SetScrollLine(int cxLogLine, int cyLogLine) |
+ { |
+ ATLASSERT(cxLogLine >= 0 && cyLogLine >= 0); |
+ |
+ m_sizeLogLine.cx = cxLogLine; |
+ m_sizeLogLine.cy = cyLogLine; |
+ |
+ SIZE sizeLine = { 0 }; |
+ sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale); |
+ sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale); |
+ CScrollImpl< T >::SetScrollLine(sizeLine); |
+ } |
+ |
+ void SetScrollLine(SIZE sizeLogLine) |
+ { |
+ SetScrollLine(sizeLogLine.cx, sizeLogLine.cy); |
+ } |
+ |
+ void GetScrollLine(SIZE& sizeLogLine) const |
+ { |
+ sizeLogLine = m_sizeLogLine; |
+ } |
+ |
+ // page operations |
+ void SetScrollPage(int cxLogPage, int cyLogPage) |
+ { |
+ ATLASSERT(cxLogPage >= 0 && cyLogPage >= 0); |
+ |
+ m_sizeLogPage.cx = cxLogPage; |
+ m_sizeLogPage.cy = cyLogPage; |
+ |
+ SIZE sizePage = { 0 }; |
+ sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale); |
+ sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale); |
+ |
+ CScrollImpl< T >::SetScrollPage(sizePage); |
+ } |
+ |
+ void SetScrollPage(SIZE sizeLogPage) |
+ { |
+ SetScrollPage(sizeLogPage.cx, sizeLogPage.cy); |
+ } |
+ |
+ void GetScrollPage(SIZE& sizeLogPage) const |
+ { |
+ sizeLogPage = m_sizeLogPage; |
+ } |
+ |
+ void SetZoomScale(float fZoomScale) |
+ { |
+ ATLASSERT(fZoomScale > 0); |
+ |
+ if(fZoomScale > 0 && fZoomScale >= m_fZoomScaleMin) |
+ m_fZoomScale = fZoomScale; |
+ } |
+ |
+ float GetZoomScale() const |
+ { |
+ return m_fZoomScale; |
+ } |
+ |
+ void SetZoomScaleMin(float fZoomScaleMin) |
+ { |
+ m_fZoomScaleMin = fZoomScaleMin; |
+ } |
+ |
+ float GetZoomScaleMin() const |
+ { |
+ return m_fZoomScaleMin; |
+ } |
+ |
+ void SetZoomDelta(float fZoomDelta) |
+ { |
+ ATLASSERT(fZoomDelta >= 0); |
+ |
+ if(fZoomDelta >= 0) |
+ m_fZoomDelta = fZoomDelta; |
+ } |
+ |
+ float GetZoomDelta() const |
+ { |
+ return m_fZoomDelta; |
+ } |
+ |
+ void SetZoomMode(int nZoomMode) |
+ { |
+ m_nZoomMode = nZoomMode; |
+ } |
+ |
+ int GetZoomMode() const |
+ { |
+ return m_nZoomMode; |
+ } |
+ |
+ void Zoom(int x, int y, float fZoomScale) |
+ { |
+ if(fZoomScale <= 0) |
+ return; |
+ |
+ fZoomScale = __max(fZoomScale, m_fZoomScaleMin); |
+ |
+ T* pT = static_cast<T*>(this); |
+ POINT pt = { x, y }; |
+ if(!pT->PtInDevRect(pt)) |
+ return; |
+ |
+ pT->ViewDPtoLP(&pt); |
+ pT->Zoom(fZoomScale, false); |
+ pT->CenterOnLogicalPoint(pt); |
+ } |
+ |
+ void Zoom(POINT pt, float fZoomScale) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ pT->Zoom(pt.x, pt.y, fZoomScale); |
+ } |
+ |
+ void Zoom(RECT& rc) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ RECT rcZoom = rc; |
+ pT->NormalizeRect(rcZoom); |
+ SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top }; |
+ POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 }; |
+ if(size.cx < m_cxyMinZoomRect || size.cy < m_cxyMinZoomRect) |
+ { |
+ pT->Zoom(pt, m_fZoomScale + m_fZoomDelta); |
+ return; |
+ } |
+ |
+ ATLASSERT(size.cx > 0 && size.cy > 0); |
+ |
+ float fScaleH = (float)(m_sizeClient.cx + 1) / (float)size.cx; |
+ float fScaleV = (float)(m_sizeClient.cy + 1) / (float)size.cy; |
+ float fZoomScale = __min(fScaleH, fScaleV) * m_fZoomScale; |
+ pT->Zoom(pt, fZoomScale); |
+ } |
+ |
+ void Zoom(float fZoomScale, bool bCenter = true) |
+ { |
+ if(fZoomScale <= 0) |
+ return; |
+ |
+ fZoomScale = __max(fZoomScale, m_fZoomScaleMin); |
+ |
+ |
+ T* pT = static_cast<T*>(this); |
+ POINT pt = { 0 }; |
+ if(bCenter) |
+ { |
+ RECT rc; |
+ ::GetClientRect(pT->m_hWnd, &rc); |
+ pt.x = rc.right / 2; |
+ pt.y = rc.bottom / 2; |
+ pT->ViewDPtoLP(&pt); |
+ } |
+ |
+ // Modify the Viewport extent |
+ m_fZoomScale = fZoomScale; |
+ SIZE sizeAll = { 0 }; |
+ sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale); |
+ sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale); |
+ |
+ // Update scroll bars and window |
+ CScrollImpl< T >::SetScrollSize(sizeAll); |
+ |
+ if(bCenter) |
+ pT->CenterOnLogicalPoint(pt); |
+ } |
+ |
+ // Helper functions |
+ void PrepareDC(CDCHandle dc) |
+ { |
+ ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0); |
+ dc.SetMapMode(MM_ANISOTROPIC); |
+ dc.SetWindowExt(m_sizeLogAll); |
+ dc.SetViewportExt(m_sizeAll); |
+ dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); |
+ } |
+ |
+ void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1) |
+ { |
+ ATLASSERT(lpPoints); |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+ CWindowDC dc(pT->m_hWnd); |
+ pT->PrepareDC(dc.m_hDC); |
+ dc.DPtoLP(lpPoints, nCount); |
+ } |
+ |
+ void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1) |
+ { |
+ ATLASSERT(lpPoints); |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ |
+ CWindowDC dc(pT->m_hWnd); |
+ pT->PrepareDC(dc.m_hDC); |
+ dc.LPtoDP(lpPoints, nCount); |
+ } |
+ |
+ void ClientToDevice(POINT &pt) |
+ { |
+ pt.x += m_ptOffset.x; |
+ pt.y += m_ptOffset.y; |
+ } |
+ |
+ void DeviceToClient(POINT &pt) |
+ { |
+ pt.x -= m_ptOffset.x; |
+ pt.y -= m_ptOffset.y; |
+ } |
+ |
+ void CenterOnPoint(POINT pt) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ RECT rect; |
+ pT->GetClientRect(&rect); |
+ |
+ int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x; |
+ if(xOfs < 0) |
+ { |
+ xOfs = 0; |
+ } |
+ else |
+ { |
+ int xMax = __max((int)(m_sizeAll.cx - rect.right), 0); |
+ if(xOfs > xMax) |
+ xOfs = xMax; |
+ } |
+ |
+ int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y; |
+ if(yOfs < 0) |
+ { |
+ yOfs = 0; |
+ } |
+ else |
+ { |
+ int yMax = __max((int)(m_sizeAll.cy - rect.bottom), 0); |
+ if(yOfs > yMax) |
+ yOfs = yMax; |
+ } |
+ |
+ CScrollImpl< T >::SetScrollOffset(xOfs, yOfs); |
+ } |
+ |
+ void CenterOnLogicalPoint(POINT ptLog) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ pT->ViewLPtoDP(&ptLog); |
+ pT->DeviceToClient(ptLog); |
+ pT->CenterOnPoint(ptLog); |
+ } |
+ |
+ BOOL PtInDevRect(POINT pt) |
+ { |
+ RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy }; |
+ ::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y); |
+ return ::PtInRect(&rc, pt); |
+ } |
+ |
+ void NormalizeRect(RECT& rc) |
+ { |
+ if(rc.left > rc.right) |
+ { |
+ int r = rc.right; |
+ rc.right = rc.left; |
+ rc.left = r; |
+ } |
+ if(rc.top > rc.bottom) |
+ { |
+ int b = rc.bottom; |
+ rc.bottom = rc.top; |
+ rc.top = b; |
+ } |
+ } |
+ |
+ void DrawTrackRect() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ const SIZE sizeLines = { 2, 2 }; |
+ RECT rc = m_rcTrack; |
+ pT->NormalizeRect(rc); |
+ if(!::IsRectEmpty(&rc)) |
+ { |
+ ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2); |
+ CWindowDC dc(NULL); |
+ dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines); |
+ } |
+ } |
+ |
+ void NotifyParentZoomChanged() |
+ { |
+ T* pT = static_cast<T*>(this); |
+ int nId = pT->GetDlgCtrlID(); |
+ NMHDR nmhdr = { pT->m_hWnd, nId, ZSN_ZOOMCHANGED }; |
+ ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr); |
+ } |
+ |
+ BEGIN_MSG_MAP(CZoomScrollImpl) |
+ MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) |
+ MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) |
+ MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) |
+ MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) |
+ MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) |
+ MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) |
+ MESSAGE_HANDLER(WM_PAINT, OnPaint) |
+ MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) |
+ MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) |
+ MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) |
+ MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) |
+ MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) |
+ ALT_MSG_MAP(1) |
+ COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) |
+ COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) |
+ COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) |
+ END_MSG_MAP() |
+ |
+ LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ ATLASSERT(m_sizeLogAll.cx >= 0 && m_sizeLogAll.cy >= 0); |
+ ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0); |
+ |
+ if(wParam != NULL) |
+ { |
+ CDCHandle dc = (HDC)wParam; |
+ int nMapModeSav = dc.GetMapMode(); |
+ dc.SetMapMode(MM_ANISOTROPIC); |
+ SIZE szWindowExt = { 0, 0 }; |
+ dc.SetWindowExt(m_sizeLogAll, &szWindowExt); |
+ SIZE szViewportExt = { 0, 0 }; |
+ dc.SetViewportExt(m_sizeAll, &szViewportExt); |
+ POINT ptViewportOrg = { 0, 0 }; |
+ dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); |
+ |
+ pT->DoPaint(dc); |
+ |
+ dc.SetMapMode(nMapModeSav); |
+ dc.SetWindowExt(szWindowExt); |
+ dc.SetViewportExt(szViewportExt); |
+ dc.SetViewportOrg(ptViewportOrg); |
+ } |
+ else |
+ { |
+ CPaintDC dc(pT->m_hWnd); |
+ pT->PrepareDC(dc.m_hDC); |
+ pT->DoPaint(dc.m_hDC); |
+ } |
+ return 0; |
+ } |
+ |
+ LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) |
+ { |
+ if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; |
+ if(pT->PtInDevRect(pt)) |
+ { |
+ pT->SetCapture(); |
+ m_bTracking = true; |
+ ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y); |
+ } |
+ } |
+ bHandled = FALSE; |
+ return 0; |
+ } |
+ |
+ LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) |
+ { |
+ if(m_bTracking) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; |
+ if(pT->PtInDevRect(pt)) |
+ { |
+ pT->DrawTrackRect(); |
+ m_rcTrack.right = pt.x; |
+ m_rcTrack.bottom = pt.y; |
+ pT->DrawTrackRect(); |
+ } |
+ } |
+ bHandled = FALSE; |
+ return 0; |
+ } |
+ |
+ LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) |
+ { |
+ ::ReleaseCapture(); |
+ if(m_nZoomMode == ZOOMMODE_OUT) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta); |
+ pT->NotifyParentZoomChanged(); |
+ } |
+ bHandled = FALSE; |
+ return 0; |
+ } |
+ |
+ LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) |
+ { |
+ if(m_bTracking) |
+ { |
+ m_bTracking = false; |
+ T* pT = static_cast<T*>(this); |
+ pT->DrawTrackRect(); |
+ pT->Zoom(m_rcTrack); |
+ pT->NotifyParentZoomChanged(); |
+ ::SetRectEmpty(&m_rcTrack); |
+ } |
+ bHandled = FALSE; |
+ return 0; |
+ } |
+ |
+ LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) |
+ { |
+ if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ if((HWND)wParam == pT->m_hWnd) |
+ { |
+ DWORD dwPos = ::GetMessagePos(); |
+ POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; |
+ pT->ScreenToClient(&pt); |
+ if(pT->PtInDevRect(pt)) |
+ { |
+ ::SetCursor(::LoadCursor(NULL, IDC_CROSS)); |
+ return 1; |
+ } |
+ } |
+ } |
+ bHandled = FALSE; |
+ return 0; |
+ } |
+}; |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CZoomScrollWindowImpl - Implements scrolling window with zooming |
+ |
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits> |
+class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T > |
+{ |
+public: |
+ BEGIN_MSG_MAP(CZoomScrollWindowImpl) |
+ MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor) |
+ MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) |
+ MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) |
+ MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) |
+#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) |
+#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) |
+ MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) |
+ MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) |
+ MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) |
+ MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint) |
+ MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint) |
+ MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown) |
+ MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove) |
+ MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp) |
+ MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged) |
+ ALT_MSG_MAP(1) |
+ COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) |
+ COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) |
+ COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) |
+ COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) |
+ COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) |
+ END_MSG_MAP() |
+}; |
+ |
+#endif // !_WIN32_WCE |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CScrollContainer |
+ |
+template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits> |
+class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits > |
+{ |
+public: |
+ DECLARE_WND_CLASS_EX(NULL, 0, -1) |
+ |
+ typedef CScrollWindowImpl< T, TBase, TWinTraits > _baseClass; |
+ |
+// Data members |
+ ATL::CWindow m_wndClient; |
+ bool m_bAutoSizeClient; |
+ bool m_bDrawEdgeIfEmpty; |
+ |
+// Constructor |
+ CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false) |
+ { |
+ // Set CScrollWindowImpl extended style |
+ SetScrollExtendedStyle(SCRL_SCROLLCHILDREN); |
+ } |
+ |
+// Attributes |
+ HWND GetClient() const |
+ { |
+ return m_wndClient; |
+ } |
+ |
+ HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true) |
+ { |
+ ATLASSERT(::IsWindow(m_hWnd)); |
+ |
+ HWND hWndOldClient = m_wndClient; |
+ m_wndClient = hWndClient; |
+ |
+ SetRedraw(FALSE); |
+ SetScrollSize(1, 1, FALSE); |
+ |
+ if(m_wndClient.m_hWnd != NULL) |
+ { |
+ m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); |
+ |
+ if(bClientSizeAsMin) |
+ { |
+ RECT rect = { 0 }; |
+ m_wndClient.GetWindowRect(&rect); |
+ if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0) |
+ SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE); |
+ } |
+ |
+ T* pT = static_cast<T*>(this); |
+ pT->UpdateLayout(); |
+ } |
+ |
+ SetRedraw(TRUE); |
+ RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); |
+ |
+ return hWndOldClient; |
+ } |
+ |
+// Message map and handlers |
+ BEGIN_MSG_MAP(CScrollContainerImpl) |
+ MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) |
+ MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) |
+ MESSAGE_HANDLER(WM_SIZE, OnSize) |
+ CHAIN_MSG_MAP(_baseClass) |
+ FORWARD_NOTIFICATIONS() |
+ ALT_MSG_MAP(1) |
+ CHAIN_MSG_MAP_ALT(_baseClass, 1) |
+ END_MSG_MAP() |
+ |
+ LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ if(m_wndClient.m_hWnd != NULL) |
+ m_wndClient.SetFocus(); |
+ |
+ return 0; |
+ } |
+ |
+ LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) |
+ { |
+ return 1; // no background needed |
+ } |
+ |
+ LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) |
+ { |
+ BOOL bTmp = TRUE; |
+ LRESULT lRet = _baseClass::OnSize(uMsg, wParam, lParam, bTmp); |
+ |
+ T* pT = static_cast<T*>(this); |
+ pT->UpdateLayout(); |
+ |
+ return lRet; |
+ } |
+ |
+// Overrides for CScrollWindowImpl |
+ void DoPaint(CDCHandle dc) |
+ { |
+ if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ RECT rect = { 0 }; |
+ pT->GetContainerRect(rect); |
+ |
+ if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL) |
+ dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); |
+ |
+ dc.FillRect(&rect, COLOR_APPWORKSPACE); |
+ } |
+ } |
+ |
+ void ScrollToView(POINT pt) |
+ { |
+ CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt); |
+ } |
+ |
+ void ScrollToView(RECT& rect) |
+ { |
+ CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect); |
+ } |
+ |
+ void ScrollToView(HWND hWnd) // client window coordinates |
+ { |
+ T* pT = static_cast<T*>(this); |
+ pT; // avoid level 4 warning |
+ ATLASSERT(::IsWindow(pT->m_hWnd)); |
+ ATLASSERT(m_wndClient.IsWindow()); |
+ |
+ RECT rect = { 0 }; |
+ ::GetWindowRect(hWnd, &rect); |
+ ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2); |
+ ScrollToView(rect); |
+ } |
+ |
+// Implementation - overrideable methods |
+ void UpdateLayout() |
+ { |
+ ATLASSERT(::IsWindow(m_hWnd)); |
+ |
+ if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ RECT rect = { 0 }; |
+ pT->GetContainerRect(rect); |
+ |
+ m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE); |
+ } |
+ else |
+ { |
+ Invalidate(); |
+ } |
+ } |
+ |
+ void GetContainerRect(RECT& rect) |
+ { |
+ GetClientRect(&rect); |
+ |
+ if(rect.right < m_sizeAll.cx) |
+ rect.right = m_sizeAll.cx; |
+ |
+ if(rect.bottom < m_sizeAll.cy) |
+ rect.bottom = m_sizeAll.cy; |
+ } |
+}; |
+ |
+class CScrollContainer : public CScrollContainerImpl<CScrollContainer> |
+{ |
+public: |
+ DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1) |
+}; |
+ |
+}; // namespace WTL |
+ |
+#endif // __ATLSCRL_H__ |