| 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__
|
|
|