1 // Windows Template Library - WTL version 8.0
\r
2 // Copyright (C) Microsoft Corporation. All rights reserved.
\r
4 // This file is a part of the Windows Template Library.
\r
5 // The use and distribution terms for this software are covered by the
\r
6 // Common Public License 1.0 (http://opensource.org/osi3.0/licenses/cpl1.0.php)
\r
7 // which can be found in the file CPL.TXT at the root of this distribution.
\r
8 // By using this software in any fashion, you are agreeing to be bound by
\r
9 // the terms of this license. You must not remove this notice, or
\r
10 // any other, from this software.
\r
12 #ifndef __ATLSCRL_H__
\r
13 #define __ATLSCRL_H__
\r
18 #error ATL requires C++ compilation (use a .cpp suffix)
\r
21 #ifndef __ATLAPP_H__
\r
22 #error atlscrl.h requires atlapp.h to be included first
\r
25 #ifndef __ATLWIN_H__
\r
26 #error atlscrl.h requires atlwin.h to be included first
\r
29 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
31 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
33 #ifndef GET_WHEEL_DELTA_WPARAM
\r
34 #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
\r
37 #ifndef WM_MOUSEHWHEEL
\r
38 #define WM_MOUSEHWHEEL 0x020E
\r
42 ///////////////////////////////////////////////////////////////////////////////
\r
43 // Classes in this file:
\r
46 // CScrollWindowImpl<T, TBase, TWinTraits>
\r
47 // CMapScrollImpl<T>
\r
48 // CMapScrollWindowImpl<T, TBase, TWinTraits>
\r
49 // CFSBWindowT<TBase>
\r
50 // CZoomScrollImpl<T>
\r
51 // CZoomScrollWindowImpl<T, TBase, TWinTraits>
\r
52 // CScrollContainerImpl<T, TBase, TWinTraits>
\r
58 ///////////////////////////////////////////////////////////////////////////////
\r
59 // CScrollImpl - Provides scrolling support to any window
\r
61 // Scroll extended styles
\r
62 #define SCRL_SCROLLCHILDREN 0x00000001
\r
63 #define SCRL_ERASEBACKGROUND 0x00000002
\r
64 #define SCRL_NOTHUMBTRACKING 0x00000004
\r
65 #if (WINVER >= 0x0500)
\r
66 #define SCRL_SMOOTHSCROLL 0x00000008
\r
67 #endif // (WINVER >= 0x0500)
\r
68 #define SCRL_DISABLENOSCROLLV 0x00000010
\r
69 #define SCRL_DISABLENOSCROLLH 0x00000020
\r
70 #define SCRL_DISABLENOSCROLL (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH)
\r
77 enum { uSCROLL_FLAGS = SW_INVALIDATE };
\r
84 int m_zDelta; // current wheel value
\r
85 int m_nWheelLines; // number of lines to scroll on wheel
\r
86 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
87 // Note that this message must be forwarded from a top level window
\r
88 UINT m_uMsgMouseWheel; // MSH_MOUSEWHEEL
\r
89 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
90 int m_zHDelta; // current horizontal wheel value
\r
91 int m_nHWheelChars; // number of chars to scroll on horizontal wheel
\r
92 UINT m_uScrollFlags;
\r
93 DWORD m_dwExtendedStyle; // scroll specific extended styles
\r
96 CScrollImpl() : m_zDelta(0), m_nWheelLines(3),
\r
97 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
98 m_uMsgMouseWheel(0U),
\r
99 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
100 m_zHDelta(0), m_nHWheelChars(3),
\r
101 m_uScrollFlags(0U), m_dwExtendedStyle(0)
\r
111 m_sizeClient.cx = 0;
\r
112 m_sizeClient.cy = 0;
\r
114 SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND);
\r
117 // Attributes & Operations
\r
118 DWORD GetScrollExtendedStyle() const
\r
120 return m_dwExtendedStyle;
\r
123 DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
\r
125 DWORD dwPrevStyle = m_dwExtendedStyle;
\r
127 m_dwExtendedStyle = dwExtendedStyle;
\r
129 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
\r
130 // cache scroll flags
\r
131 T* pT = static_cast<T*>(this);
\r
132 pT; // avoid level 4 warning
\r
133 m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0);
\r
134 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
\r
135 m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0);
\r
136 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
\r
137 return dwPrevStyle;
\r
140 // offset operations
\r
141 void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
\r
143 T* pT = static_cast<T*>(this);
\r
144 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
146 pT->AdjustScrollOffset(x, y);
\r
148 int dx = m_ptOffset.x - x;
\r
149 int dy = m_ptOffset.y - y;
\r
153 // block: set horizontal scroll bar
\r
155 SCROLLINFO si = { sizeof(SCROLLINFO) };
\r
156 si.fMask = SIF_POS;
\r
157 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
\r
158 si.fMask |= SIF_DISABLENOSCROLL;
\r
159 si.nPos = m_ptOffset.x;
\r
160 pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
\r
163 // block: set vertical scroll bar
\r
165 SCROLLINFO si = { sizeof(SCROLLINFO) };
\r
166 si.fMask = SIF_POS;
\r
167 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
\r
168 si.fMask |= SIF_DISABLENOSCROLL;
\r
169 si.nPos = m_ptOffset.y;
\r
170 pT->SetScrollInfo(SB_VERT, &si, bRedraw);
\r
173 // Move all children if needed
\r
174 if(IsScrollingChildren() && (dx != 0 || dy != 0))
\r
176 for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
\r
179 ::GetWindowRect(hWndChild, &rect);
\r
180 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
\r
181 ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
\r
189 void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
\r
191 SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
\r
194 void GetScrollOffset(POINT& ptOffset) const
\r
196 ptOffset = m_ptOffset;
\r
200 void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
\r
202 T* pT = static_cast<T*>(this);
\r
203 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
214 pT->AdjustScrollOffset(x, y);
\r
217 int dx = m_ptOffset.x - x;
\r
218 int dy = m_ptOffset.y - y;
\r
222 // block: set horizontal scroll bar
\r
224 SCROLLINFO si = { sizeof(SCROLLINFO) };
\r
225 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
\r
226 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
\r
227 si.fMask |= SIF_DISABLENOSCROLL;
\r
229 si.nMax = m_sizeAll.cx - 1;
\r
230 si.nPage = m_sizeClient.cx;
\r
231 si.nPos = m_ptOffset.x;
\r
232 pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
\r
235 // block: set vertical scroll bar
\r
237 SCROLLINFO si = { sizeof(SCROLLINFO) };
\r
238 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
\r
239 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
\r
240 si.fMask |= SIF_DISABLENOSCROLL;
\r
242 si.nMax = m_sizeAll.cy - 1;
\r
243 si.nPage = m_sizeClient.cy;
\r
244 si.nPos = m_ptOffset.y;
\r
245 pT->SetScrollInfo(SB_VERT, &si, bRedraw);
\r
248 // Move all children if needed
\r
249 if(IsScrollingChildren() && (dx != 0 || dy != 0))
\r
251 for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
\r
254 ::GetWindowRect(hWndChild, &rect);
\r
255 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
\r
256 ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
\r
260 SetScrollLine(0, 0);
\r
261 SetScrollPage(0, 0);
\r
267 void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
\r
269 SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset);
\r
272 void GetScrollSize(SIZE& sizeWnd) const
\r
274 sizeWnd = m_sizeAll;
\r
278 void SetScrollLine(int cxLine, int cyLine)
\r
280 ATLASSERT(cxLine >= 0 && cyLine >= 0);
\r
281 ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
\r
283 m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100);
\r
284 m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100);
\r
287 void SetScrollLine(SIZE sizeLine)
\r
289 SetScrollLine(sizeLine.cx, sizeLine.cy);
\r
292 void GetScrollLine(SIZE& sizeLine) const
\r
294 sizeLine = m_sizeLine;
\r
298 void SetScrollPage(int cxPage, int cyPage)
\r
300 ATLASSERT(cxPage >= 0 && cyPage >= 0);
\r
301 ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
\r
303 m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10);
\r
304 m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10);
\r
307 void SetScrollPage(SIZE sizePage)
\r
309 SetScrollPage(sizePage.cx, sizePage.cy);
\r
312 void GetScrollPage(SIZE& sizePage) const
\r
314 sizePage = m_sizePage;
\r
318 void ScrollLineDown()
\r
320 T* pT = static_cast<T*>(this);
\r
321 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
322 pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
\r
325 void ScrollLineUp()
\r
327 T* pT = static_cast<T*>(this);
\r
328 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
329 pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
\r
332 void ScrollPageDown()
\r
334 T* pT = static_cast<T*>(this);
\r
335 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
336 pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
\r
339 void ScrollPageUp()
\r
341 T* pT = static_cast<T*>(this);
\r
342 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
343 pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
\r
348 T* pT = static_cast<T*>(this);
\r
349 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
350 pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
\r
353 void ScrollBottom()
\r
355 T* pT = static_cast<T*>(this);
\r
356 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
357 pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
\r
360 void ScrollLineRight()
\r
362 T* pT = static_cast<T*>(this);
\r
363 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
364 pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
367 void ScrollLineLeft()
\r
369 T* pT = static_cast<T*>(this);
\r
370 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
371 pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
374 void ScrollPageRight()
\r
376 T* pT = static_cast<T*>(this);
\r
377 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
378 pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
381 void ScrollPageLeft()
\r
383 T* pT = static_cast<T*>(this);
\r
384 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
385 pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
388 void ScrollAllLeft()
\r
390 T* pT = static_cast<T*>(this);
\r
391 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
392 pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
395 void ScrollAllRight()
\r
397 T* pT = static_cast<T*>(this);
\r
398 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
399 pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
402 // scroll to make point/view/window visible
\r
403 void ScrollToView(POINT pt)
\r
405 T* pT = static_cast<T*>(this);
\r
406 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
407 RECT rect = { pt.x, pt.y, pt.x, pt.y };
\r
408 pT->ScrollToView(rect);
\r
411 void ScrollToView(RECT& rect)
\r
413 T* pT = static_cast<T*>(this);
\r
414 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
416 RECT rcClient = { 0 };
\r
417 pT->GetClientRect(&rcClient);
\r
419 int x = m_ptOffset.x;
\r
420 if(rect.left < m_ptOffset.x)
\r
422 else if(rect.right > (m_ptOffset.x + rcClient.right))
\r
423 x = rect.right - rcClient.right;
\r
425 int y = m_ptOffset.y;
\r
426 if(rect.top < m_ptOffset.y)
\r
428 else if(rect.bottom > (m_ptOffset.y + rcClient.bottom))
\r
429 y = rect.bottom - rcClient.bottom;
\r
431 SetScrollOffset(x, y);
\r
434 void ScrollToView(HWND hWnd)
\r
436 T* pT = static_cast<T*>(this);
\r
437 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
440 ::GetWindowRect(hWnd, &rect);
\r
441 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
\r
442 ScrollToView(rect);
\r
445 BEGIN_MSG_MAP(CScrollImpl)
\r
446 MESSAGE_HANDLER(WM_CREATE, OnCreate)
\r
447 MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
\r
448 MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
\r
449 MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
\r
450 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
451 MESSAGE_HANDLER(m_uMsgMouseWheel, OnMouseWheel)
\r
452 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
453 MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel)
\r
454 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
\r
455 MESSAGE_HANDLER(WM_SIZE, OnSize)
\r
456 MESSAGE_HANDLER(WM_PAINT, OnPaint)
\r
458 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
\r
459 #endif // !_WIN32_WCE
\r
460 // standard scroll commands
\r
462 COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp)
\r
463 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown)
\r
464 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp)
\r
465 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown)
\r
466 COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop)
\r
467 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom)
\r
468 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft)
\r
469 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight)
\r
470 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft)
\r
471 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight)
\r
472 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft)
\r
473 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight)
\r
476 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
\r
478 GetSystemSettings();
\r
483 LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
485 T* pT = static_cast<T*>(this);
\r
486 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
487 pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
\r
491 LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
493 T* pT = static_cast<T*>(this);
\r
494 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
495 pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
499 LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
501 T* pT = static_cast<T*>(this);
\r
502 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
504 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE)
\r
506 int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
\r
508 int zDelta = (uMsg == WM_MOUSEWHEEL) ? (int)GET_WHEEL_DELTA_WPARAM(wParam) : (int)wParam;
\r
509 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE))
\r
510 int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN);
\r
511 m_zDelta += zDelta; // cumulative
\r
512 int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines;
\r
513 if(m_sizeAll.cy > m_sizeClient.cy)
\r
515 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
\r
517 pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
\r
518 pT->UpdateWindow();
\r
521 else // can't scroll vertically, scroll horizontally
\r
523 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
\r
525 pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
526 pT->UpdateWindow();
\r
529 m_zDelta %= WHEEL_DELTA;
\r
534 LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
536 T* pT = static_cast<T*>(this);
\r
537 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
539 int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
\r
540 int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT);
\r
541 m_zHDelta += zDelta; // cumulative
\r
542 int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars;
\r
543 if(m_sizeAll.cx > m_sizeClient.cx)
\r
545 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
\r
547 pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
\r
548 pT->UpdateWindow();
\r
551 m_zHDelta %= WHEEL_DELTA;
\r
556 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
558 GetSystemSettings();
\r
562 LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
564 T* pT = static_cast<T*>(this);
\r
565 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
567 m_sizeClient.cx = GET_X_LPARAM(lParam);
\r
568 m_sizeClient.cy = GET_Y_LPARAM(lParam);
\r
570 // block: set horizontal scroll bar
\r
572 SCROLLINFO si = { sizeof(SCROLLINFO) };
\r
573 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
\r
575 si.nMax = m_sizeAll.cx - 1;
\r
576 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
\r
577 si.fMask |= SIF_DISABLENOSCROLL;
\r
578 si.nPage = m_sizeClient.cx;
\r
579 si.nPos = m_ptOffset.x;
\r
580 pT->SetScrollInfo(SB_HORZ, &si, TRUE);
\r
583 // block: set vertical scroll bar
\r
585 SCROLLINFO si = { sizeof(SCROLLINFO) };
\r
586 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
\r
588 si.nMax = m_sizeAll.cy - 1;
\r
589 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
\r
590 si.fMask |= SIF_DISABLENOSCROLL;
\r
591 si.nPage = m_sizeClient.cy;
\r
592 si.nPos = m_ptOffset.y;
\r
593 pT->SetScrollInfo(SB_VERT, &si, TRUE);
\r
596 int x = m_ptOffset.x;
\r
597 int y = m_ptOffset.y;
\r
598 if(pT->AdjustScrollOffset(x, y))
\r
600 // Children will be moved in SetScrollOffset, if needed
\r
601 pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN));
\r
602 SetScrollOffset(x, y, FALSE);
\r
609 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
611 T* pT = static_cast<T*>(this);
\r
612 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
615 CDCHandle dc = (HDC)wParam;
\r
616 POINT ptViewportOrg = { 0, 0 };
\r
617 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
\r
619 dc.SetViewportOrg(ptViewportOrg);
\r
623 CPaintDC dc(pT->m_hWnd);
\r
624 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
\r
625 pT->DoPaint(dc.m_hDC);
\r
630 // scrolling handlers
\r
631 LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
637 LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
643 LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
649 LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
655 LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
661 LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
667 LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
673 LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
679 LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
685 LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
691 LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
697 LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
\r
704 void DoPaint(CDCHandle /*dc*/)
\r
706 // must be implemented in a derived class
\r
711 void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine)
\r
713 T* pT = static_cast<T*>(this);
\r
715 pT->GetClientRect(&rect);
\r
716 int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right;
\r
717 int cxyMax = cxySizeAll - cxyClient;
\r
719 if(cxyMax < 0) // can't scroll, client area is bigger
\r
722 bool bUpdate = true;
\r
725 switch(nScrollCode)
\r
727 case SB_TOP: // top or all left
\r
728 cxyScroll = cxyOffset;
\r
731 case SB_BOTTOM: // bottom or all right
\r
732 cxyScroll = cxyOffset - cxyMax;
\r
733 cxyOffset = cxyMax;
\r
735 case SB_LINEUP: // line up or line left
\r
736 if(cxyOffset >= cxySizeLine)
\r
738 cxyScroll = cxySizeLine;
\r
739 cxyOffset -= cxySizeLine;
\r
743 cxyScroll = cxyOffset;
\r
747 case SB_LINEDOWN: // line down or line right
\r
748 if(cxyOffset < cxyMax - cxySizeLine)
\r
750 cxyScroll = -cxySizeLine;
\r
751 cxyOffset += cxySizeLine;
\r
755 cxyScroll = cxyOffset - cxyMax;
\r
756 cxyOffset = cxyMax;
\r
759 case SB_PAGEUP: // page up or page left
\r
760 if(cxyOffset >= cxySizePage)
\r
762 cxyScroll = cxySizePage;
\r
763 cxyOffset -= cxySizePage;
\r
767 cxyScroll = cxyOffset;
\r
771 case SB_PAGEDOWN: // page down or page right
\r
772 if(cxyOffset < cxyMax - cxySizePage)
\r
774 cxyScroll = -cxySizePage;
\r
775 cxyOffset += cxySizePage;
\r
779 cxyScroll = cxyOffset - cxyMax;
\r
780 cxyOffset = cxyMax;
\r
783 case SB_THUMBTRACK:
\r
784 if(IsNoThumbTracking())
\r
786 // else fall through
\r
787 case SB_THUMBPOSITION:
\r
789 SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS };
\r
790 if(pT->GetScrollInfo(nType, &si))
\r
792 cxyScroll = cxyOffset - si.nTrackPos;
\r
793 cxyOffset = si.nTrackPos;
\r
803 if(bUpdate && cxyScroll != 0)
\r
805 pT->SetScrollPos(nType, cxyOffset, TRUE);
\r
806 if(nType == SB_VERT)
\r
807 pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags);
\r
809 pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags);
\r
813 static int CalcLineOrPage(int nVal, int nMax, int nDiv)
\r
817 nVal = nMax / nDiv;
\r
821 else if(nVal > nMax)
\r
829 bool AdjustScrollOffset(int& x, int& y)
\r
834 int cxMax = m_sizeAll.cx - m_sizeClient.cx;
\r
836 x = (cxMax >= 0) ? cxMax : 0;
\r
840 int cyMax = m_sizeAll.cy - m_sizeClient.cy;
\r
842 y = (cyMax >= 0) ? cyMax : 0;
\r
846 return (x != xOld || y != yOld);
\r
849 void GetSystemSettings()
\r
852 #ifndef SPI_GETWHEELSCROLLLINES
\r
853 const UINT SPI_GETWHEELSCROLLLINES = 104;
\r
854 #endif // !SPI_GETWHEELSCROLLLINES
\r
855 ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0);
\r
857 #ifndef SPI_GETWHEELSCROLLCHARS
\r
858 const UINT SPI_GETWHEELSCROLLCHARS = 0x006C;
\r
859 #endif // !SPI_GETWHEELSCROLLCHARS
\r
860 ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0);
\r
862 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
863 if(m_uMsgMouseWheel != 0)
\r
864 m_uMsgMouseWheel = ::RegisterWindowMessage(MSH_MOUSEWHEEL);
\r
866 HWND hWndWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE);
\r
867 if(::IsWindow(hWndWheel))
\r
869 UINT uMsgScrollLines = ::RegisterWindowMessage(MSH_SCROLL_LINES);
\r
870 if(uMsgScrollLines != 0)
\r
871 m_nWheelLines = (int)::SendMessage(hWndWheel, uMsgScrollLines, 0, 0L);
\r
873 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
874 #endif // !_WIN32_WCE
\r
877 bool IsScrollingChildren() const
\r
879 return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0;
\r
882 bool IsErasingBackground() const
\r
884 return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0;
\r
887 bool IsNoThumbTracking() const
\r
889 return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0;
\r
892 #if (WINVER >= 0x0500)
\r
893 bool IsSmoothScroll() const
\r
895 return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0;
\r
897 #endif // (WINVER >= 0x0500)
\r
901 ///////////////////////////////////////////////////////////////////////////////
\r
902 // CScrollWindowImpl - Implements a scrollable window
\r
904 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
\r
905 class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CScrollImpl< T >
\r
908 BEGIN_MSG_MAP(CScrollWindowImpl)
\r
909 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
\r
910 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
\r
911 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
\r
912 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
913 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
\r
914 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
\r
915 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
\r
916 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
\r
917 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
\r
918 MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint)
\r
920 MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint)
\r
921 #endif // !_WIN32_WCE
\r
923 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
\r
924 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
\r
925 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
\r
926 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
\r
927 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
\r
928 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
\r
929 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
\r
930 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
\r
931 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
\r
932 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
\r
933 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
\r
934 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
\r
939 ///////////////////////////////////////////////////////////////////////////////
\r
940 // CMapScrollImpl - Provides mapping and scrolling support to any window
\r
945 class CMapScrollImpl : public CScrollImpl< T >
\r
950 SIZE m_sizeLogLine;
\r
951 SIZE m_sizeLogPage;
\r
954 CMapScrollImpl() : m_nMapMode(MM_TEXT)
\r
956 ::SetRectEmpty(&m_rectLogAll);
\r
957 m_sizeLogPage.cx = 0;
\r
958 m_sizeLogPage.cy = 0;
\r
959 m_sizeLogLine.cx = 0;
\r
960 m_sizeLogLine.cy = 0;
\r
963 // Attributes & Operations
\r
964 // mapping mode operations
\r
965 void SetScrollMapMode(int nMapMode)
\r
967 ATLASSERT(nMapMode >= MM_MIN && nMapMode <= MM_MAX_FIXEDSCALE);
\r
968 m_nMapMode = nMapMode;
\r
971 int GetScrollMapMode() const
\r
973 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
977 // offset operations
\r
978 void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
\r
980 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
981 POINT ptOff = { x, y };
\r
982 // block: convert logical to device units
\r
984 CWindowDC dc(NULL);
\r
985 dc.SetMapMode(m_nMapMode);
\r
988 CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw);
\r
991 void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
\r
993 SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
\r
996 void GetScrollOffset(POINT& ptOffset) const
\r
998 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
999 ptOffset = m_ptOffset;
\r
1000 // block: convert device to logical units
\r
1002 CWindowDC dc(NULL);
\r
1003 dc.SetMapMode(m_nMapMode);
\r
1004 dc.DPtoLP(&ptOffset);
\r
1008 // size operations
\r
1009 void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true)
\r
1011 ATLASSERT(xMax > xMin && yMax > yMin);
\r
1012 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
1014 ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax);
\r
1016 SIZE sizeAll = { 0 };
\r
1017 sizeAll.cx = xMax - xMin + 1;
\r
1018 sizeAll.cy = yMax - yMin + 1;
\r
1019 // block: convert logical to device units
\r
1021 CWindowDC dc(NULL);
\r
1022 dc.SetMapMode(m_nMapMode);
\r
1023 dc.LPtoDP(&sizeAll);
\r
1025 CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
\r
1026 SetScrollLine(0, 0);
\r
1027 SetScrollPage(0, 0);
\r
1030 void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true)
\r
1032 SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset);
\r
1035 void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
\r
1037 SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset);
\r
1040 void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
\r
1042 SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset);
\r
1045 void GetScrollSize(RECT& rcScroll) const
\r
1047 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
1048 rcScroll = m_rectLogAll;
\r
1051 // line operations
\r
1052 void SetScrollLine(int cxLine, int cyLine)
\r
1054 ATLASSERT(cxLine >= 0 && cyLine >= 0);
\r
1055 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
1057 m_sizeLogLine.cx = cxLine;
\r
1058 m_sizeLogLine.cy = cyLine;
\r
1059 SIZE sizeLine = m_sizeLogLine;
\r
1060 // block: convert logical to device units
\r
1062 CWindowDC dc(NULL);
\r
1063 dc.SetMapMode(m_nMapMode);
\r
1064 dc.LPtoDP(&sizeLine);
\r
1066 CScrollImpl< T >::SetScrollLine(sizeLine);
\r
1069 void SetScrollLine(SIZE sizeLine)
\r
1071 SetScrollLine(sizeLine.cx, sizeLine.cy);
\r
1074 void GetScrollLine(SIZE& sizeLine) const
\r
1076 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
1077 sizeLine = m_sizeLogLine;
\r
1080 // page operations
\r
1081 void SetScrollPage(int cxPage, int cyPage)
\r
1083 ATLASSERT(cxPage >= 0 && cyPage >= 0);
\r
1084 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
1086 m_sizeLogPage.cx = cxPage;
\r
1087 m_sizeLogPage.cy = cyPage;
\r
1088 SIZE sizePage = m_sizeLogPage;
\r
1089 // block: convert logical to device units
\r
1091 CWindowDC dc(NULL);
\r
1092 dc.SetMapMode(m_nMapMode);
\r
1093 dc.LPtoDP(&sizePage);
\r
1095 CScrollImpl< T >::SetScrollPage(sizePage);
\r
1098 void SetScrollPage(SIZE sizePage)
\r
1100 SetScrollPage(sizePage.cx, sizePage.cy);
\r
1103 void GetScrollPage(SIZE& sizePage) const
\r
1105 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
\r
1106 sizePage = m_sizeLogPage;
\r
1109 BEGIN_MSG_MAP(CMapScrollImpl)
\r
1110 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
\r
1111 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
\r
1112 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
\r
1113 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
1114 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
\r
1115 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
1116 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
\r
1117 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
\r
1118 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
\r
1119 MESSAGE_HANDLER(WM_PAINT, OnPaint)
\r
1120 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
\r
1122 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
\r
1123 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
\r
1124 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
\r
1125 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
\r
1126 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
\r
1127 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
\r
1128 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
\r
1129 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
\r
1130 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
\r
1131 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
\r
1132 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
\r
1133 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
\r
1136 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
1138 T* pT = static_cast<T*>(this);
\r
1139 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
1140 if(wParam != NULL)
\r
1142 CDCHandle dc = (HDC)wParam;
\r
1143 int nMapModeSav = dc.GetMapMode();
\r
1144 dc.SetMapMode(m_nMapMode);
\r
1145 POINT ptViewportOrg = { 0, 0 };
\r
1146 if(m_nMapMode == MM_TEXT)
\r
1147 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
\r
1149 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy, &ptViewportOrg);
\r
1150 POINT ptWindowOrg = { 0, 0 };
\r
1151 dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg);
\r
1155 dc.SetMapMode(nMapModeSav);
\r
1156 dc.SetViewportOrg(ptViewportOrg);
\r
1157 dc.SetWindowOrg(ptWindowOrg);
\r
1161 CPaintDC dc(pT->m_hWnd);
\r
1162 dc.SetMapMode(m_nMapMode);
\r
1163 if(m_nMapMode == MM_TEXT)
\r
1164 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
\r
1166 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy);
\r
1167 dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top);
\r
1168 pT->DoPaint(dc.m_hDC);
\r
1174 #endif // !_WIN32_WCE
\r
1177 ///////////////////////////////////////////////////////////////////////////////
\r
1178 // CMapScrollWindowImpl - Implements scrolling window with mapping
\r
1180 #ifndef _WIN32_WCE
\r
1182 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
\r
1183 class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T >
\r
1186 BEGIN_MSG_MAP(CMapScrollWindowImpl)
\r
1187 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
\r
1188 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
\r
1189 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
\r
1190 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
1191 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
\r
1192 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
1193 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
\r
1194 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
\r
1195 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
\r
1196 MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint)
\r
1197 MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint)
\r
1199 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
\r
1200 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
\r
1201 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
\r
1202 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
\r
1203 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
\r
1204 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
\r
1205 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
\r
1206 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
\r
1207 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
\r
1208 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
\r
1209 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
\r
1210 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
\r
1214 #endif // !_WIN32_WCE
\r
1217 ///////////////////////////////////////////////////////////////////////////////
\r
1218 // CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support
\r
1220 #if defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
\r
1222 template <class TBase = ATL::CWindow>
\r
1223 class CFSBWindowT : public TBase, public CFlatScrollBarImpl<CFSBWindowT< TBase > >
\r
1227 CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd)
\r
1230 CFSBWindowT< TBase >& operator =(HWND hWnd)
\r
1236 // CWindow overrides that use flat scroll bar API
\r
1237 // (only those methods that are used by scroll window classes)
\r
1238 int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
\r
1240 ATLASSERT(::IsWindow(m_hWnd));
\r
1241 return FlatSB_SetScrollPos(nBar, nPos, bRedraw);
\r
1244 BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
\r
1246 ATLASSERT(::IsWindow(m_hWnd));
\r
1247 return FlatSB_GetScrollInfo(nBar, lpScrollInfo);
\r
1250 BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
\r
1252 ATLASSERT(::IsWindow(m_hWnd));
\r
1253 return FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw);
\r
1257 typedef CFSBWindowT<ATL::CWindow> CFSBWindow;
\r
1259 #endif // defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
\r
1262 ///////////////////////////////////////////////////////////////////////////////
\r
1263 // CZoomScrollImpl - Provides zooming and scrolling support to any window
\r
1265 #ifndef _WIN32_WCE
\r
1267 // The zoom modes that can be set with the SetZoomMode method
\r
1271 ZOOMMODE_IN, // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged.
\r
1272 ZOOMMODE_OUT // If left mouse button clicked, zoom out on point clicked.
\r
1275 // Notification to parent that zoom scale changed as a result of user mouse action.
\r
1276 #define ZSN_ZOOMCHANGED (NM_FIRST - 50)
\r
1278 template <class T>
\r
1279 class CZoomScrollImpl : public CScrollImpl< T >
\r
1282 enum { m_cxyMinZoomRect = 12 }; // min rect size to zoom in on rect.
\r
1285 SIZE m_sizeLogAll;
\r
1286 SIZE m_sizeLogLine;
\r
1287 SIZE m_sizeLogPage;
\r
1288 float m_fZoomScale;
\r
1289 float m_fZoomScaleMin;
\r
1290 float m_fZoomDelta; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click.
\r
1296 CZoomScrollImpl():
\r
1297 m_fZoomScale(1.0),
\r
1298 m_fZoomScaleMin(0.5),
\r
1299 m_fZoomDelta(0.5),
\r
1300 m_nZoomMode(ZOOMMODE_OFF),
\r
1301 m_bTracking(false)
\r
1303 m_sizeLogAll.cx = 0;
\r
1304 m_sizeLogAll.cy = 0;
\r
1305 m_sizeLogPage.cx = 0;
\r
1306 m_sizeLogPage.cy = 0;
\r
1307 m_sizeLogLine.cx = 0;
\r
1308 m_sizeLogLine.cy = 0;
\r
1309 ::SetRectEmpty(&m_rcTrack);
\r
1312 // Attributes & Operations
\r
1314 // size operations
\r
1315 void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
\r
1317 ATLASSERT(cxLog >= 0 && cyLog >= 0);
\r
1319 // Set up the defaults
\r
1320 if (cxLog == 0 && cyLog == 0)
\r
1326 m_sizeLogAll.cx = cxLog;
\r
1327 m_sizeLogAll.cy = cyLog;
\r
1328 SIZE sizeAll = { 0 };
\r
1329 sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale);
\r
1330 sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale);
\r
1332 CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
\r
1335 void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
\r
1337 SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset);
\r
1340 void GetScrollSize(SIZE& sizeLog) const
\r
1342 sizeLog = m_sizeLogAll;
\r
1345 // line operations
\r
1346 void SetScrollLine(int cxLogLine, int cyLogLine)
\r
1348 ATLASSERT(cxLogLine >= 0 && cyLogLine >= 0);
\r
1350 m_sizeLogLine.cx = cxLogLine;
\r
1351 m_sizeLogLine.cy = cyLogLine;
\r
1353 SIZE sizeLine = { 0 };
\r
1354 sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale);
\r
1355 sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale);
\r
1356 CScrollImpl< T >::SetScrollLine(sizeLine);
\r
1359 void SetScrollLine(SIZE sizeLogLine)
\r
1361 SetScrollLine(sizeLogLine.cx, sizeLogLine.cy);
\r
1364 void GetScrollLine(SIZE& sizeLogLine) const
\r
1366 sizeLogLine = m_sizeLogLine;
\r
1369 // page operations
\r
1370 void SetScrollPage(int cxLogPage, int cyLogPage)
\r
1372 ATLASSERT(cxLogPage >= 0 && cyLogPage >= 0);
\r
1374 m_sizeLogPage.cx = cxLogPage;
\r
1375 m_sizeLogPage.cy = cyLogPage;
\r
1377 SIZE sizePage = { 0 };
\r
1378 sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale);
\r
1379 sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale);
\r
1381 CScrollImpl< T >::SetScrollPage(sizePage);
\r
1384 void SetScrollPage(SIZE sizeLogPage)
\r
1386 SetScrollPage(sizeLogPage.cx, sizeLogPage.cy);
\r
1389 void GetScrollPage(SIZE& sizeLogPage) const
\r
1391 sizeLogPage = m_sizeLogPage;
\r
1394 void SetZoomScale(float fZoomScale)
\r
1396 ATLASSERT(fZoomScale > 0);
\r
1398 if(fZoomScale > 0 && fZoomScale >= m_fZoomScaleMin)
\r
1399 m_fZoomScale = fZoomScale;
\r
1402 float GetZoomScale() const
\r
1404 return m_fZoomScale;
\r
1407 void SetZoomScaleMin(float fZoomScaleMin)
\r
1409 m_fZoomScaleMin = fZoomScaleMin;
\r
1412 float GetZoomScaleMin() const
\r
1414 return m_fZoomScaleMin;
\r
1417 void SetZoomDelta(float fZoomDelta)
\r
1419 ATLASSERT(fZoomDelta >= 0);
\r
1421 if(fZoomDelta >= 0)
\r
1422 m_fZoomDelta = fZoomDelta;
\r
1425 float GetZoomDelta() const
\r
1427 return m_fZoomDelta;
\r
1430 void SetZoomMode(int nZoomMode)
\r
1432 m_nZoomMode = nZoomMode;
\r
1435 int GetZoomMode() const
\r
1437 return m_nZoomMode;
\r
1440 void Zoom(int x, int y, float fZoomScale)
\r
1442 if(fZoomScale <= 0)
\r
1445 fZoomScale = max(fZoomScale, m_fZoomScaleMin);
\r
1447 T* pT = static_cast<T*>(this);
\r
1448 POINT pt = { x, y };
\r
1449 if(!pT->PtInDevRect(pt))
\r
1452 pT->ViewDPtoLP(&pt);
\r
1453 pT->Zoom(fZoomScale, false);
\r
1454 pT->CenterOnLogicalPoint(pt);
\r
1457 void Zoom(POINT pt, float fZoomScale)
\r
1459 T* pT = static_cast<T*>(this);
\r
1460 pT->Zoom(pt.x, pt.y, fZoomScale);
\r
1463 void Zoom(RECT& rc)
\r
1465 T* pT = static_cast<T*>(this);
\r
1467 pT->NormalizeRect(rcZoom);
\r
1468 SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top };
\r
1469 POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 };
\r
1470 if(size.cx < m_cxyMinZoomRect || size.cy < m_cxyMinZoomRect)
\r
1472 pT->Zoom(pt, m_fZoomScale + m_fZoomDelta);
\r
1476 ATLASSERT(size.cx > 0 && size.cy > 0);
\r
1478 float fScaleH = (float)(m_sizeClient.cx + 1) / (float)size.cx;
\r
1479 float fScaleV = (float)(m_sizeClient.cy + 1) / (float)size.cy;
\r
1480 float fZoomScale = min(fScaleH, fScaleV) * m_fZoomScale;
\r
1481 pT->Zoom(pt, fZoomScale);
\r
1484 void Zoom(float fZoomScale, bool bCenter = true)
\r
1486 if(fZoomScale <= 0)
\r
1489 fZoomScale = max(fZoomScale, m_fZoomScaleMin);
\r
1492 T* pT = static_cast<T*>(this);
\r
1497 ::GetClientRect(pT->m_hWnd, &rc);
\r
1498 pt.x = rc.right / 2;
\r
1499 pt.y = rc.bottom / 2;
\r
1500 pT->ViewDPtoLP(&pt);
\r
1503 // Modify the Viewport extent
\r
1504 m_fZoomScale = fZoomScale;
\r
1505 SIZE sizeAll = { 0 };
\r
1506 sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale);
\r
1507 sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale);
\r
1509 // Update scroll bars and window
\r
1510 CScrollImpl< T >::SetScrollSize(sizeAll);
\r
1513 pT->CenterOnLogicalPoint(pt);
\r
1516 // Helper functions
\r
1517 void PrepareDC(CDCHandle dc)
\r
1519 ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
\r
1520 dc.SetMapMode(MM_ANISOTROPIC);
\r
1521 dc.SetWindowExt(m_sizeLogAll);
\r
1522 dc.SetViewportExt(m_sizeAll);
\r
1523 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
\r
1526 void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1)
\r
1528 ATLASSERT(lpPoints);
\r
1529 T* pT = static_cast<T*>(this);
\r
1530 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
1532 CWindowDC dc(pT->m_hWnd);
\r
1533 pT->PrepareDC(dc.m_hDC);
\r
1534 dc.DPtoLP(lpPoints, nCount);
\r
1537 void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1)
\r
1539 ATLASSERT(lpPoints);
\r
1540 T* pT = static_cast<T*>(this);
\r
1541 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
1543 CWindowDC dc(pT->m_hWnd);
\r
1544 pT->PrepareDC(dc.m_hDC);
\r
1545 dc.LPtoDP(lpPoints, nCount);
\r
1548 void ClientToDevice(POINT &pt)
\r
1550 pt.x += m_ptOffset.x;
\r
1551 pt.y += m_ptOffset.y;
\r
1554 void DeviceToClient(POINT &pt)
\r
1556 pt.x -= m_ptOffset.x;
\r
1557 pt.y -= m_ptOffset.y;
\r
1560 void CenterOnPoint(POINT pt)
\r
1562 T* pT = static_cast<T*>(this);
\r
1564 pT->GetClientRect(&rect);
\r
1566 int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x;
\r
1573 int xMax = max((int)(m_sizeAll.cx - rect.right), 0);
\r
1578 int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y;
\r
1585 int yMax = max((int)(m_sizeAll.cy - rect.bottom), 0);
\r
1590 CScrollImpl< T >::SetScrollOffset(xOfs, yOfs);
\r
1593 void CenterOnLogicalPoint(POINT ptLog)
\r
1595 T* pT = static_cast<T*>(this);
\r
1596 pT->ViewLPtoDP(&ptLog);
\r
1597 pT->DeviceToClient(ptLog);
\r
1598 pT->CenterOnPoint(ptLog);
\r
1601 BOOL PtInDevRect(POINT pt)
\r
1603 RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy };
\r
1604 ::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y);
\r
1605 return ::PtInRect(&rc, pt);
\r
1608 void NormalizeRect(RECT& rc)
\r
1610 if(rc.left > rc.right)
\r
1613 rc.right = rc.left;
\r
1616 if(rc.top > rc.bottom)
\r
1618 int b = rc.bottom;
\r
1619 rc.bottom = rc.top;
\r
1624 void DrawTrackRect()
\r
1626 T* pT = static_cast<T*>(this);
\r
1627 const SIZE sizeLines = { 2, 2 };
\r
1628 RECT rc = m_rcTrack;
\r
1629 pT->NormalizeRect(rc);
\r
1630 if(!::IsRectEmpty(&rc))
\r
1632 ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2);
\r
1633 CWindowDC dc(NULL);
\r
1634 dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines);
\r
1638 void NotifyParentZoomChanged()
\r
1640 T* pT = static_cast<T*>(this);
\r
1641 int nId = pT->GetDlgCtrlID();
\r
1642 NMHDR nmhdr = { pT->m_hWnd, nId, ZSN_ZOOMCHANGED };
\r
1643 ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr);
\r
1646 BEGIN_MSG_MAP(CZoomScrollImpl)
\r
1647 MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
\r
1648 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
\r
1649 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
\r
1650 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
\r
1651 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
1652 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
\r
1653 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
1654 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
\r
1655 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
\r
1656 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
\r
1657 MESSAGE_HANDLER(WM_PAINT, OnPaint)
\r
1658 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
\r
1659 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
\r
1660 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
\r
1661 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
\r
1662 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
\r
1664 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
\r
1665 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
\r
1666 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
\r
1667 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
\r
1668 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
\r
1669 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
\r
1670 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
\r
1671 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
\r
1672 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
\r
1673 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
\r
1674 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
\r
1675 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
\r
1678 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
1680 T* pT = static_cast<T*>(this);
\r
1681 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
1682 ATLASSERT(m_sizeLogAll.cx >= 0 && m_sizeLogAll.cy >= 0);
\r
1683 ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
\r
1685 if(wParam != NULL)
\r
1687 CDCHandle dc = (HDC)wParam;
\r
1688 int nMapModeSav = dc.GetMapMode();
\r
1689 dc.SetMapMode(MM_ANISOTROPIC);
\r
1690 SIZE szWindowExt = { 0, 0 };
\r
1691 dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
\r
1692 SIZE szViewportExt = { 0, 0 };
\r
1693 dc.SetViewportExt(m_sizeAll, &szViewportExt);
\r
1694 POINT ptViewportOrg = { 0, 0 };
\r
1695 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
\r
1699 dc.SetMapMode(nMapModeSav);
\r
1700 dc.SetWindowExt(szWindowExt);
\r
1701 dc.SetViewportExt(szViewportExt);
\r
1702 dc.SetViewportOrg(ptViewportOrg);
\r
1706 CPaintDC dc(pT->m_hWnd);
\r
1707 pT->PrepareDC(dc.m_hDC);
\r
1708 pT->DoPaint(dc.m_hDC);
\r
1713 LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
1715 if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking)
\r
1717 T* pT = static_cast<T*>(this);
\r
1718 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
\r
1719 if(pT->PtInDevRect(pt))
\r
1722 m_bTracking = true;
\r
1723 ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y);
\r
1730 LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
1734 T* pT = static_cast<T*>(this);
\r
1735 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
\r
1736 if(pT->PtInDevRect(pt))
\r
1738 pT->DrawTrackRect();
\r
1739 m_rcTrack.right = pt.x;
\r
1740 m_rcTrack.bottom = pt.y;
\r
1741 pT->DrawTrackRect();
\r
1748 LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
1750 ::ReleaseCapture();
\r
1751 if(m_nZoomMode == ZOOMMODE_OUT)
\r
1753 T* pT = static_cast<T*>(this);
\r
1754 pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta);
\r
1755 pT->NotifyParentZoomChanged();
\r
1761 LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
\r
1765 m_bTracking = false;
\r
1766 T* pT = static_cast<T*>(this);
\r
1767 pT->DrawTrackRect();
\r
1768 pT->Zoom(m_rcTrack);
\r
1769 pT->NotifyParentZoomChanged();
\r
1770 ::SetRectEmpty(&m_rcTrack);
\r
1776 LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
\r
1778 if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF)
\r
1780 T* pT = static_cast<T*>(this);
\r
1781 if((HWND)wParam == pT->m_hWnd)
\r
1783 DWORD dwPos = ::GetMessagePos();
\r
1784 POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
\r
1785 pT->ScreenToClient(&pt);
\r
1786 if(pT->PtInDevRect(pt))
\r
1788 ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
\r
1798 ///////////////////////////////////////////////////////////////////////////////
\r
1799 // CZoomScrollWindowImpl - Implements scrolling window with zooming
\r
1801 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
\r
1802 class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
\r
1805 BEGIN_MSG_MAP(CZoomScrollWindowImpl)
\r
1806 MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
\r
1807 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
\r
1808 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
\r
1809 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
\r
1810 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
1811 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
\r
1812 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
\r
1813 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
\r
1814 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
\r
1815 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
\r
1816 MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint)
\r
1817 MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint)
\r
1818 MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
\r
1819 MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
\r
1820 MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
\r
1821 MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
\r
1823 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
\r
1824 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
\r
1825 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
\r
1826 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
\r
1827 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
\r
1828 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
\r
1829 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
\r
1830 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
\r
1831 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
\r
1832 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
\r
1833 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
\r
1834 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
\r
1838 #endif // !_WIN32_WCE
\r
1841 ///////////////////////////////////////////////////////////////////////////////
\r
1842 // CScrollContainer
\r
1844 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
\r
1845 class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits >
\r
1848 DECLARE_WND_CLASS_EX(NULL, 0, -1)
\r
1850 typedef CScrollWindowImpl< T, TBase, TWinTraits > _baseClass;
\r
1853 ATL::CWindow m_wndClient;
\r
1854 bool m_bAutoSizeClient;
\r
1855 bool m_bDrawEdgeIfEmpty;
\r
1858 CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false)
\r
1860 // Set CScrollWindowImpl extended style
\r
1861 SetScrollExtendedStyle(SCRL_SCROLLCHILDREN);
\r
1865 HWND GetClient() const
\r
1867 return m_wndClient;
\r
1870 HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true)
\r
1872 ATLASSERT(::IsWindow(m_hWnd));
\r
1874 HWND hWndOldClient = m_wndClient;
\r
1875 m_wndClient = hWndClient;
\r
1878 SetScrollSize(1, 1, FALSE);
\r
1880 if(m_wndClient.m_hWnd != NULL)
\r
1882 m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
\r
1884 if(bClientSizeAsMin)
\r
1886 RECT rect = { 0 };
\r
1887 m_wndClient.GetWindowRect(&rect);
\r
1888 if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0)
\r
1889 SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE);
\r
1892 T* pT = static_cast<T*>(this);
\r
1893 pT->UpdateLayout();
\r
1897 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
\r
1899 return hWndOldClient;
\r
1902 // Message map and handlers
\r
1903 BEGIN_MSG_MAP(CScrollContainerImpl)
\r
1904 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
\r
1905 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
\r
1906 MESSAGE_HANDLER(WM_SIZE, OnSize)
\r
1907 CHAIN_MSG_MAP(_baseClass)
\r
1908 FORWARD_NOTIFICATIONS()
\r
1910 CHAIN_MSG_MAP_ALT(_baseClass, 1)
\r
1913 LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
1915 if(m_wndClient.m_hWnd != NULL)
\r
1916 m_wndClient.SetFocus();
\r
1921 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
1923 return 1; // no background needed
\r
1926 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
\r
1929 LRESULT lRet = _baseClass::OnSize(uMsg, wParam, lParam, bTmp);
\r
1931 T* pT = static_cast<T*>(this);
\r
1932 pT->UpdateLayout();
\r
1937 // Overrides for CScrollWindowImpl
\r
1938 void DoPaint(CDCHandle dc)
\r
1940 if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL)
\r
1942 T* pT = static_cast<T*>(this);
\r
1943 RECT rect = { 0 };
\r
1944 pT->GetContainerRect(rect);
\r
1946 if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL)
\r
1947 dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
\r
1949 dc.FillRect(&rect, COLOR_APPWORKSPACE);
\r
1953 void ScrollToView(POINT pt)
\r
1955 CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt);
\r
1958 void ScrollToView(RECT& rect)
\r
1960 CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect);
\r
1963 void ScrollToView(HWND hWnd) // client window coordinates
\r
1965 T* pT = static_cast<T*>(this);
\r
1966 pT; // avoid level 4 warning
\r
1967 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
1968 ATLASSERT(m_wndClient.IsWindow());
\r
1970 RECT rect = { 0 };
\r
1971 ::GetWindowRect(hWnd, &rect);
\r
1972 ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2);
\r
1973 ScrollToView(rect);
\r
1976 // Implementation - overrideable methods
\r
1977 void UpdateLayout()
\r
1979 ATLASSERT(::IsWindow(m_hWnd));
\r
1981 if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL)
\r
1983 T* pT = static_cast<T*>(this);
\r
1984 RECT rect = { 0 };
\r
1985 pT->GetContainerRect(rect);
\r
1987 m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
\r
1995 void GetContainerRect(RECT& rect)
\r
1997 GetClientRect(&rect);
\r
1999 if(rect.right < m_sizeAll.cx)
\r
2000 rect.right = m_sizeAll.cx;
\r
2002 if(rect.bottom < m_sizeAll.cy)
\r
2003 rect.bottom = m_sizeAll.cy;
\r
2007 class CScrollContainer : public CScrollContainerImpl<CScrollContainer>
\r
2010 DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1)
\r
2013 }; // namespace WTL
\r
2015 #endif // __ATLSCRL_H__
\r