Update mojo sdk to rev 1dc8a9a5db73d3718d99917fadf31f5fb2ebad4f
[chromium-blink-merge.git] / third_party / wtl / include / atlscrl.h
blobbafb595455dc0cb0e8baf961f9939e743cceb655
1 // Windows Template Library - WTL version 8.0
2 // Copyright (C) Microsoft Corporation. All rights reserved.
3 //
4 // This file is a part of the Windows Template Library.
5 // The use and distribution terms for this software are covered by the
6 // Microsoft Permissive License (Ms-PL) which can be found in the file
7 // Ms-PL.txt at the root of this distribution.
9 #ifndef __ATLSCRL_H__
10 #define __ATLSCRL_H__
12 #pragma once
14 #ifndef __cplusplus
15 #error ATL requires C++ compilation (use a .cpp suffix)
16 #endif
18 #ifndef __ATLAPP_H__
19 #error atlscrl.h requires atlapp.h to be included first
20 #endif
22 #ifndef __ATLWIN_H__
23 #error atlscrl.h requires atlwin.h to be included first
24 #endif
26 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
27 #include <zmouse.h>
28 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
30 #ifndef GET_WHEEL_DELTA_WPARAM
31 #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
32 #endif
34 #ifndef WM_MOUSEHWHEEL
35 #define WM_MOUSEHWHEEL 0x020E
36 #endif
39 ///////////////////////////////////////////////////////////////////////////////
40 // Classes in this file:
42 // CScrollImpl<T>
43 // CScrollWindowImpl<T, TBase, TWinTraits>
44 // CMapScrollImpl<T>
45 // CMapScrollWindowImpl<T, TBase, TWinTraits>
46 // CFSBWindowT<TBase>
47 // CZoomScrollImpl<T>
48 // CZoomScrollWindowImpl<T, TBase, TWinTraits>
49 // CScrollContainerImpl<T, TBase, TWinTraits>
50 // CScrollContainer
52 namespace WTL
55 ///////////////////////////////////////////////////////////////////////////////
56 // CScrollImpl - Provides scrolling support to any window
58 // Scroll extended styles
59 #define SCRL_SCROLLCHILDREN 0x00000001
60 #define SCRL_ERASEBACKGROUND 0x00000002
61 #define SCRL_NOTHUMBTRACKING 0x00000004
62 #if (WINVER >= 0x0500)
63 #define SCRL_SMOOTHSCROLL 0x00000008
64 #endif // (WINVER >= 0x0500)
65 #define SCRL_DISABLENOSCROLLV 0x00000010
66 #define SCRL_DISABLENOSCROLLH 0x00000020
67 #define SCRL_DISABLENOSCROLL (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH)
70 template <class T>
71 class CScrollImpl
73 public:
74 enum { uSCROLL_FLAGS = SW_INVALIDATE };
76 POINT m_ptOffset;
77 SIZE m_sizeAll;
78 SIZE m_sizeLine;
79 SIZE m_sizePage;
80 SIZE m_sizeClient;
81 int m_zDelta; // current wheel value
82 int m_nWheelLines; // number of lines to scroll on wheel
83 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
84 // Note that this message must be forwarded from a top level window
85 UINT m_uMsgMouseWheel; // MSH_MOUSEWHEEL
86 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
87 int m_zHDelta; // current horizontal wheel value
88 int m_nHWheelChars; // number of chars to scroll on horizontal wheel
89 UINT m_uScrollFlags;
90 DWORD m_dwExtendedStyle; // scroll specific extended styles
92 // Constructor
93 CScrollImpl() : m_zDelta(0), m_nWheelLines(3),
94 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
95 m_uMsgMouseWheel(0U),
96 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
97 m_zHDelta(0), m_nHWheelChars(3),
98 m_uScrollFlags(0U), m_dwExtendedStyle(0)
100 m_ptOffset.x = 0;
101 m_ptOffset.y = 0;
102 m_sizeAll.cx = 0;
103 m_sizeAll.cy = 0;
104 m_sizePage.cx = 0;
105 m_sizePage.cy = 0;
106 m_sizeLine.cx = 0;
107 m_sizeLine.cy = 0;
108 m_sizeClient.cx = 0;
109 m_sizeClient.cy = 0;
111 SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND);
114 // Attributes & Operations
115 DWORD GetScrollExtendedStyle() const
117 return m_dwExtendedStyle;
120 DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
122 DWORD dwPrevStyle = m_dwExtendedStyle;
123 if(dwMask == 0)
124 m_dwExtendedStyle = dwExtendedStyle;
125 else
126 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
127 // cache scroll flags
128 T* pT = static_cast<T*>(this);
129 pT; // avoid level 4 warning
130 m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0);
131 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
132 m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0);
133 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
134 return dwPrevStyle;
137 // offset operations
138 void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
140 T* pT = static_cast<T*>(this);
141 ATLASSERT(::IsWindow(pT->m_hWnd));
143 pT->AdjustScrollOffset(x, y);
145 int dx = m_ptOffset.x - x;
146 int dy = m_ptOffset.y - y;
147 m_ptOffset.x = x;
148 m_ptOffset.y = y;
150 // block: set horizontal scroll bar
152 SCROLLINFO si = { sizeof(SCROLLINFO) };
153 si.fMask = SIF_POS;
154 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
155 si.fMask |= SIF_DISABLENOSCROLL;
156 si.nPos = m_ptOffset.x;
157 pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
160 // block: set vertical scroll bar
162 SCROLLINFO si = { sizeof(SCROLLINFO) };
163 si.fMask = SIF_POS;
164 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
165 si.fMask |= SIF_DISABLENOSCROLL;
166 si.nPos = m_ptOffset.y;
167 pT->SetScrollInfo(SB_VERT, &si, bRedraw);
170 // Move all children if needed
171 if(IsScrollingChildren() && (dx != 0 || dy != 0))
173 for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
175 RECT rect = { 0 };
176 ::GetWindowRect(hWndChild, &rect);
177 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
178 ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
182 if(bRedraw)
183 pT->Invalidate();
186 void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
188 SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
191 void GetScrollOffset(POINT& ptOffset) const
193 ptOffset = m_ptOffset;
196 // size operations
197 void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
199 T* pT = static_cast<T*>(this);
200 ATLASSERT(::IsWindow(pT->m_hWnd));
202 m_sizeAll.cx = cx;
203 m_sizeAll.cy = cy;
205 int x = 0;
206 int y = 0;
207 if(!bResetOffset)
209 x = m_ptOffset.x;
210 y = m_ptOffset.y;
211 pT->AdjustScrollOffset(x, y);
214 int dx = m_ptOffset.x - x;
215 int dy = m_ptOffset.y - y;
216 m_ptOffset.x = x;
217 m_ptOffset.y = y;
219 // block: set horizontal scroll bar
221 SCROLLINFO si = { sizeof(SCROLLINFO) };
222 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
223 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
224 si.fMask |= SIF_DISABLENOSCROLL;
225 si.nMin = 0;
226 si.nMax = m_sizeAll.cx - 1;
227 si.nPage = m_sizeClient.cx;
228 si.nPos = m_ptOffset.x;
229 pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
232 // block: set vertical scroll bar
234 SCROLLINFO si = { sizeof(SCROLLINFO) };
235 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
236 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
237 si.fMask |= SIF_DISABLENOSCROLL;
238 si.nMin = 0;
239 si.nMax = m_sizeAll.cy - 1;
240 si.nPage = m_sizeClient.cy;
241 si.nPos = m_ptOffset.y;
242 pT->SetScrollInfo(SB_VERT, &si, bRedraw);
245 // Move all children if needed
246 if(IsScrollingChildren() && (dx != 0 || dy != 0))
248 for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
250 RECT rect = { 0 };
251 ::GetWindowRect(hWndChild, &rect);
252 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
253 ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
257 SetScrollLine(0, 0);
258 SetScrollPage(0, 0);
260 if(bRedraw)
261 pT->Invalidate();
264 void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
266 SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset);
269 void GetScrollSize(SIZE& sizeWnd) const
271 sizeWnd = m_sizeAll;
274 // line operations
275 void SetScrollLine(int cxLine, int cyLine)
277 ATLASSERT(cxLine >= 0 && cyLine >= 0);
278 ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
280 m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100);
281 m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100);
284 void SetScrollLine(SIZE sizeLine)
286 SetScrollLine(sizeLine.cx, sizeLine.cy);
289 void GetScrollLine(SIZE& sizeLine) const
291 sizeLine = m_sizeLine;
294 // page operations
295 void SetScrollPage(int cxPage, int cyPage)
297 ATLASSERT(cxPage >= 0 && cyPage >= 0);
298 ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
300 m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10);
301 m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10);
304 void SetScrollPage(SIZE sizePage)
306 SetScrollPage(sizePage.cx, sizePage.cy);
309 void GetScrollPage(SIZE& sizePage) const
311 sizePage = m_sizePage;
314 // commands
315 void ScrollLineDown()
317 T* pT = static_cast<T*>(this);
318 ATLASSERT(::IsWindow(pT->m_hWnd));
319 pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
322 void ScrollLineUp()
324 T* pT = static_cast<T*>(this);
325 ATLASSERT(::IsWindow(pT->m_hWnd));
326 pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
329 void ScrollPageDown()
331 T* pT = static_cast<T*>(this);
332 ATLASSERT(::IsWindow(pT->m_hWnd));
333 pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
336 void ScrollPageUp()
338 T* pT = static_cast<T*>(this);
339 ATLASSERT(::IsWindow(pT->m_hWnd));
340 pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
343 void ScrollTop()
345 T* pT = static_cast<T*>(this);
346 ATLASSERT(::IsWindow(pT->m_hWnd));
347 pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
350 void ScrollBottom()
352 T* pT = static_cast<T*>(this);
353 ATLASSERT(::IsWindow(pT->m_hWnd));
354 pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
357 void ScrollLineRight()
359 T* pT = static_cast<T*>(this);
360 ATLASSERT(::IsWindow(pT->m_hWnd));
361 pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
364 void ScrollLineLeft()
366 T* pT = static_cast<T*>(this);
367 ATLASSERT(::IsWindow(pT->m_hWnd));
368 pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
371 void ScrollPageRight()
373 T* pT = static_cast<T*>(this);
374 ATLASSERT(::IsWindow(pT->m_hWnd));
375 pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
378 void ScrollPageLeft()
380 T* pT = static_cast<T*>(this);
381 ATLASSERT(::IsWindow(pT->m_hWnd));
382 pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
385 void ScrollAllLeft()
387 T* pT = static_cast<T*>(this);
388 ATLASSERT(::IsWindow(pT->m_hWnd));
389 pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
392 void ScrollAllRight()
394 T* pT = static_cast<T*>(this);
395 ATLASSERT(::IsWindow(pT->m_hWnd));
396 pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
399 // scroll to make point/view/window visible
400 void ScrollToView(POINT pt)
402 T* pT = static_cast<T*>(this);
403 ATLASSERT(::IsWindow(pT->m_hWnd));
404 RECT rect = { pt.x, pt.y, pt.x, pt.y };
405 pT->ScrollToView(rect);
408 void ScrollToView(RECT& rect)
410 T* pT = static_cast<T*>(this);
411 ATLASSERT(::IsWindow(pT->m_hWnd));
413 RECT rcClient = { 0 };
414 pT->GetClientRect(&rcClient);
416 int x = m_ptOffset.x;
417 if(rect.left < m_ptOffset.x)
418 x = rect.left;
419 else if(rect.right > (m_ptOffset.x + rcClient.right))
420 x = rect.right - rcClient.right;
422 int y = m_ptOffset.y;
423 if(rect.top < m_ptOffset.y)
424 y = rect.top;
425 else if(rect.bottom > (m_ptOffset.y + rcClient.bottom))
426 y = rect.bottom - rcClient.bottom;
428 SetScrollOffset(x, y);
431 void ScrollToView(HWND hWnd)
433 T* pT = static_cast<T*>(this);
434 ATLASSERT(::IsWindow(pT->m_hWnd));
436 RECT rect = { 0 };
437 ::GetWindowRect(hWnd, &rect);
438 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
439 ScrollToView(rect);
442 BEGIN_MSG_MAP(CScrollImpl)
443 MESSAGE_HANDLER(WM_CREATE, OnCreate)
444 MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
445 MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
446 MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
447 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
448 MESSAGE_HANDLER(m_uMsgMouseWheel, OnMouseWheel)
449 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
450 MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel)
451 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
452 MESSAGE_HANDLER(WM_SIZE, OnSize)
453 MESSAGE_HANDLER(WM_PAINT, OnPaint)
454 #ifndef _WIN32_WCE
455 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
456 #endif // !_WIN32_WCE
457 // standard scroll commands
458 ALT_MSG_MAP(1)
459 COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp)
460 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown)
461 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp)
462 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown)
463 COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop)
464 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom)
465 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft)
466 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight)
467 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft)
468 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight)
469 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft)
470 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight)
471 END_MSG_MAP()
473 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
475 GetSystemSettings();
476 bHandled = FALSE;
477 return 1;
480 LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
482 T* pT = static_cast<T*>(this);
483 ATLASSERT(::IsWindow(pT->m_hWnd));
484 pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
485 return 0;
488 LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
490 T* pT = static_cast<T*>(this);
491 ATLASSERT(::IsWindow(pT->m_hWnd));
492 pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
493 return 0;
496 LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
498 T* pT = static_cast<T*>(this);
499 ATLASSERT(::IsWindow(pT->m_hWnd));
501 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE)
502 uMsg;
503 int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
504 #else
505 int zDelta = (uMsg == WM_MOUSEWHEEL) ? (int)GET_WHEEL_DELTA_WPARAM(wParam) : (int)wParam;
506 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE))
507 int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN);
508 m_zDelta += zDelta; // cumulative
509 int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines;
510 if(m_sizeAll.cy > m_sizeClient.cy)
512 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
514 pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
515 pT->UpdateWindow();
518 else // can't scroll vertically, scroll horizontally
520 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
522 pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
523 pT->UpdateWindow();
526 m_zDelta %= WHEEL_DELTA;
528 return 0;
531 LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
533 T* pT = static_cast<T*>(this);
534 ATLASSERT(::IsWindow(pT->m_hWnd));
536 int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
537 int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT);
538 m_zHDelta += zDelta; // cumulative
539 int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars;
540 if(m_sizeAll.cx > m_sizeClient.cx)
542 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
544 pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
545 pT->UpdateWindow();
548 m_zHDelta %= WHEEL_DELTA;
550 return 0;
553 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
555 GetSystemSettings();
556 return 0;
559 LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
561 T* pT = static_cast<T*>(this);
562 ATLASSERT(::IsWindow(pT->m_hWnd));
564 m_sizeClient.cx = GET_X_LPARAM(lParam);
565 m_sizeClient.cy = GET_Y_LPARAM(lParam);
567 // block: set horizontal scroll bar
569 SCROLLINFO si = { sizeof(SCROLLINFO) };
570 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
571 si.nMin = 0;
572 si.nMax = m_sizeAll.cx - 1;
573 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
574 si.fMask |= SIF_DISABLENOSCROLL;
575 si.nPage = m_sizeClient.cx;
576 si.nPos = m_ptOffset.x;
577 pT->SetScrollInfo(SB_HORZ, &si, TRUE);
580 // block: set vertical scroll bar
582 SCROLLINFO si = { sizeof(SCROLLINFO) };
583 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
584 si.nMin = 0;
585 si.nMax = m_sizeAll.cy - 1;
586 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
587 si.fMask |= SIF_DISABLENOSCROLL;
588 si.nPage = m_sizeClient.cy;
589 si.nPos = m_ptOffset.y;
590 pT->SetScrollInfo(SB_VERT, &si, TRUE);
593 int x = m_ptOffset.x;
594 int y = m_ptOffset.y;
595 if(pT->AdjustScrollOffset(x, y))
597 // Children will be moved in SetScrollOffset, if needed
598 pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN));
599 SetScrollOffset(x, y, FALSE);
602 bHandled = FALSE;
603 return 1;
606 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
608 T* pT = static_cast<T*>(this);
609 ATLASSERT(::IsWindow(pT->m_hWnd));
610 if(wParam != NULL)
612 CDCHandle dc = (HDC)wParam;
613 POINT ptViewportOrg = { 0, 0 };
614 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
615 pT->DoPaint(dc);
616 dc.SetViewportOrg(ptViewportOrg);
618 else
620 CPaintDC dc(pT->m_hWnd);
621 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
622 pT->DoPaint(dc.m_hDC);
624 return 0;
627 // scrolling handlers
628 LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
630 ScrollLineUp();
631 return 0;
634 LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
636 ScrollLineDown();
637 return 0;
640 LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
642 ScrollPageUp();
643 return 0;
646 LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
648 ScrollPageDown();
649 return 0;
652 LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
654 ScrollTop();
655 return 0;
658 LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
660 ScrollBottom();
661 return 0;
664 LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
666 ScrollLineLeft();
667 return 0;
670 LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
672 ScrollLineRight();
673 return 0;
676 LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
678 ScrollPageLeft();
679 return 0;
682 LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
684 ScrollPageRight();
685 return 0;
688 LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
690 ScrollAllLeft();
691 return 0;
694 LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
696 ScrollAllRight();
697 return 0;
700 // Overrideables
701 void DoPaint(CDCHandle /*dc*/)
703 // must be implemented in a derived class
704 ATLASSERT(FALSE);
707 // Implementation
708 void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine)
710 T* pT = static_cast<T*>(this);
711 RECT rect = { 0 };
712 pT->GetClientRect(&rect);
713 int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right;
714 int cxyMax = cxySizeAll - cxyClient;
716 if(cxyMax < 0) // can't scroll, client area is bigger
717 return;
719 bool bUpdate = true;
720 int cxyScroll = 0;
722 switch(nScrollCode)
724 case SB_TOP: // top or all left
725 cxyScroll = cxyOffset;
726 cxyOffset = 0;
727 break;
728 case SB_BOTTOM: // bottom or all right
729 cxyScroll = cxyOffset - cxyMax;
730 cxyOffset = cxyMax;
731 break;
732 case SB_LINEUP: // line up or line left
733 if(cxyOffset >= cxySizeLine)
735 cxyScroll = cxySizeLine;
736 cxyOffset -= cxySizeLine;
738 else
740 cxyScroll = cxyOffset;
741 cxyOffset = 0;
743 break;
744 case SB_LINEDOWN: // line down or line right
745 if(cxyOffset < cxyMax - cxySizeLine)
747 cxyScroll = -cxySizeLine;
748 cxyOffset += cxySizeLine;
750 else
752 cxyScroll = cxyOffset - cxyMax;
753 cxyOffset = cxyMax;
755 break;
756 case SB_PAGEUP: // page up or page left
757 if(cxyOffset >= cxySizePage)
759 cxyScroll = cxySizePage;
760 cxyOffset -= cxySizePage;
762 else
764 cxyScroll = cxyOffset;
765 cxyOffset = 0;
767 break;
768 case SB_PAGEDOWN: // page down or page right
769 if(cxyOffset < cxyMax - cxySizePage)
771 cxyScroll = -cxySizePage;
772 cxyOffset += cxySizePage;
774 else
776 cxyScroll = cxyOffset - cxyMax;
777 cxyOffset = cxyMax;
779 break;
780 case SB_THUMBTRACK:
781 if(IsNoThumbTracking())
782 break;
783 // else fall through
784 case SB_THUMBPOSITION:
786 SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS };
787 if(pT->GetScrollInfo(nType, &si))
789 cxyScroll = cxyOffset - si.nTrackPos;
790 cxyOffset = si.nTrackPos;
793 break;
794 case SB_ENDSCROLL:
795 default:
796 bUpdate = false;
797 break;
800 if(bUpdate && cxyScroll != 0)
802 pT->SetScrollPos(nType, cxyOffset, TRUE);
803 if(nType == SB_VERT)
804 pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags);
805 else
806 pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags);
810 static int CalcLineOrPage(int nVal, int nMax, int nDiv)
812 if(nVal == 0)
814 nVal = nMax / nDiv;
815 if(nVal < 1)
816 nVal = 1;
818 else if(nVal > nMax)
820 nVal = nMax;
823 return nVal;
826 bool AdjustScrollOffset(int& x, int& y)
828 int xOld = x;
829 int yOld = y;
831 int cxMax = m_sizeAll.cx - m_sizeClient.cx;
832 if(x > cxMax)
833 x = (cxMax >= 0) ? cxMax : 0;
834 else if(x < 0)
835 x = 0;
837 int cyMax = m_sizeAll.cy - m_sizeClient.cy;
838 if(y > cyMax)
839 y = (cyMax >= 0) ? cyMax : 0;
840 else if(y < 0)
841 y = 0;
843 return (x != xOld || y != yOld);
846 void GetSystemSettings()
848 #ifndef _WIN32_WCE
849 #ifndef SPI_GETWHEELSCROLLLINES
850 const UINT SPI_GETWHEELSCROLLLINES = 104;
851 #endif // !SPI_GETWHEELSCROLLLINES
852 ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0);
854 #ifndef SPI_GETWHEELSCROLLCHARS
855 const UINT SPI_GETWHEELSCROLLCHARS = 0x006C;
856 #endif // !SPI_GETWHEELSCROLLCHARS
857 ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0);
859 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
860 if(m_uMsgMouseWheel != 0)
861 m_uMsgMouseWheel = ::RegisterWindowMessage(MSH_MOUSEWHEEL);
863 HWND hWndWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE);
864 if(::IsWindow(hWndWheel))
866 UINT uMsgScrollLines = ::RegisterWindowMessage(MSH_SCROLL_LINES);
867 if(uMsgScrollLines != 0)
868 m_nWheelLines = (int)::SendMessage(hWndWheel, uMsgScrollLines, 0, 0L);
870 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
871 #endif // !_WIN32_WCE
874 bool IsScrollingChildren() const
876 return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0;
879 bool IsErasingBackground() const
881 return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0;
884 bool IsNoThumbTracking() const
886 return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0;
889 #if (WINVER >= 0x0500)
890 bool IsSmoothScroll() const
892 return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0;
894 #endif // (WINVER >= 0x0500)
898 ///////////////////////////////////////////////////////////////////////////////
899 // CScrollWindowImpl - Implements a scrollable window
901 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
902 class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CScrollImpl< T >
904 public:
905 BEGIN_MSG_MAP(CScrollWindowImpl)
906 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
907 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
908 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
909 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
910 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
911 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
912 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
913 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
914 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
915 MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint)
916 #ifndef _WIN32_WCE
917 MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint)
918 #endif // !_WIN32_WCE
919 ALT_MSG_MAP(1)
920 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
921 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
922 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
923 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
924 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
925 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
926 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
927 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
928 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
929 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
930 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
931 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
932 END_MSG_MAP()
936 ///////////////////////////////////////////////////////////////////////////////
937 // CMapScrollImpl - Provides mapping and scrolling support to any window
939 #ifndef _WIN32_WCE
941 template <class T>
942 class CMapScrollImpl : public CScrollImpl< T >
944 public:
945 int m_nMapMode;
946 RECT m_rectLogAll;
947 SIZE m_sizeLogLine;
948 SIZE m_sizeLogPage;
950 // Constructor
951 CMapScrollImpl() : m_nMapMode(MM_TEXT)
953 ::SetRectEmpty(&m_rectLogAll);
954 m_sizeLogPage.cx = 0;
955 m_sizeLogPage.cy = 0;
956 m_sizeLogLine.cx = 0;
957 m_sizeLogLine.cy = 0;
960 // Attributes & Operations
961 // mapping mode operations
962 void SetScrollMapMode(int nMapMode)
964 ATLASSERT(nMapMode >= MM_MIN && nMapMode <= MM_MAX_FIXEDSCALE);
965 m_nMapMode = nMapMode;
968 int GetScrollMapMode() const
970 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
971 return m_nMapMode;
974 // offset operations
975 void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
977 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
978 POINT ptOff = { x, y };
979 // block: convert logical to device units
981 CWindowDC dc(NULL);
982 dc.SetMapMode(m_nMapMode);
983 dc.LPtoDP(&ptOff);
985 CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw);
988 void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
990 SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
993 void GetScrollOffset(POINT& ptOffset) const
995 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
996 ptOffset = m_ptOffset;
997 // block: convert device to logical units
999 CWindowDC dc(NULL);
1000 dc.SetMapMode(m_nMapMode);
1001 dc.DPtoLP(&ptOffset);
1005 // size operations
1006 void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true)
1008 ATLASSERT(xMax > xMin && yMax > yMin);
1009 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1011 ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax);
1013 SIZE sizeAll = { 0 };
1014 sizeAll.cx = xMax - xMin + 1;
1015 sizeAll.cy = yMax - yMin + 1;
1016 // block: convert logical to device units
1018 CWindowDC dc(NULL);
1019 dc.SetMapMode(m_nMapMode);
1020 dc.LPtoDP(&sizeAll);
1022 CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
1023 SetScrollLine(0, 0);
1024 SetScrollPage(0, 0);
1027 void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true)
1029 SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset);
1032 void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
1034 SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset);
1037 void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
1039 SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset);
1042 void GetScrollSize(RECT& rcScroll) const
1044 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1045 rcScroll = m_rectLogAll;
1048 // line operations
1049 void SetScrollLine(int cxLine, int cyLine)
1051 ATLASSERT(cxLine >= 0 && cyLine >= 0);
1052 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1054 m_sizeLogLine.cx = cxLine;
1055 m_sizeLogLine.cy = cyLine;
1056 SIZE sizeLine = m_sizeLogLine;
1057 // block: convert logical to device units
1059 CWindowDC dc(NULL);
1060 dc.SetMapMode(m_nMapMode);
1061 dc.LPtoDP(&sizeLine);
1063 CScrollImpl< T >::SetScrollLine(sizeLine);
1066 void SetScrollLine(SIZE sizeLine)
1068 SetScrollLine(sizeLine.cx, sizeLine.cy);
1071 void GetScrollLine(SIZE& sizeLine) const
1073 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1074 sizeLine = m_sizeLogLine;
1077 // page operations
1078 void SetScrollPage(int cxPage, int cyPage)
1080 ATLASSERT(cxPage >= 0 && cyPage >= 0);
1081 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1083 m_sizeLogPage.cx = cxPage;
1084 m_sizeLogPage.cy = cyPage;
1085 SIZE sizePage = m_sizeLogPage;
1086 // block: convert logical to device units
1088 CWindowDC dc(NULL);
1089 dc.SetMapMode(m_nMapMode);
1090 dc.LPtoDP(&sizePage);
1092 CScrollImpl< T >::SetScrollPage(sizePage);
1095 void SetScrollPage(SIZE sizePage)
1097 SetScrollPage(sizePage.cx, sizePage.cy);
1100 void GetScrollPage(SIZE& sizePage) const
1102 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1103 sizePage = m_sizeLogPage;
1106 BEGIN_MSG_MAP(CMapScrollImpl)
1107 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1108 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1109 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1110 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1111 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1112 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1113 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1114 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1115 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1116 MESSAGE_HANDLER(WM_PAINT, OnPaint)
1117 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1118 ALT_MSG_MAP(1)
1119 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1120 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1121 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1122 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1123 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1124 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1125 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1126 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1127 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1128 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1129 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1130 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1131 END_MSG_MAP()
1133 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1135 T* pT = static_cast<T*>(this);
1136 ATLASSERT(::IsWindow(pT->m_hWnd));
1137 if(wParam != NULL)
1139 CDCHandle dc = (HDC)wParam;
1140 int nMapModeSav = dc.GetMapMode();
1141 dc.SetMapMode(m_nMapMode);
1142 POINT ptViewportOrg = { 0, 0 };
1143 if(m_nMapMode == MM_TEXT)
1144 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
1145 else
1146 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy, &ptViewportOrg);
1147 POINT ptWindowOrg = { 0, 0 };
1148 dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg);
1150 pT->DoPaint(dc);
1152 dc.SetMapMode(nMapModeSav);
1153 dc.SetViewportOrg(ptViewportOrg);
1154 dc.SetWindowOrg(ptWindowOrg);
1156 else
1158 CPaintDC dc(pT->m_hWnd);
1159 dc.SetMapMode(m_nMapMode);
1160 if(m_nMapMode == MM_TEXT)
1161 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
1162 else
1163 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy);
1164 dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top);
1165 pT->DoPaint(dc.m_hDC);
1167 return 0;
1171 #endif // !_WIN32_WCE
1174 ///////////////////////////////////////////////////////////////////////////////
1175 // CMapScrollWindowImpl - Implements scrolling window with mapping
1177 #ifndef _WIN32_WCE
1179 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1180 class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T >
1182 public:
1183 BEGIN_MSG_MAP(CMapScrollWindowImpl)
1184 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1185 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1186 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1187 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1188 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1189 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1190 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1191 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1192 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1193 MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint)
1194 MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint)
1195 ALT_MSG_MAP(1)
1196 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1197 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1198 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1199 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1200 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1201 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1202 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1203 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1204 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1205 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1206 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1207 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1208 END_MSG_MAP()
1211 #endif // !_WIN32_WCE
1214 ///////////////////////////////////////////////////////////////////////////////
1215 // CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support
1217 #if defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
1219 template <class TBase = ATL::CWindow>
1220 class CFSBWindowT : public TBase, public CFlatScrollBarImpl<CFSBWindowT< TBase > >
1222 public:
1223 // Constructors
1224 CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd)
1227 CFSBWindowT< TBase >& operator =(HWND hWnd)
1229 m_hWnd = hWnd;
1230 return *this;
1233 // CWindow overrides that use flat scroll bar API
1234 // (only those methods that are used by scroll window classes)
1235 int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
1237 ATLASSERT(::IsWindow(m_hWnd));
1238 return FlatSB_SetScrollPos(nBar, nPos, bRedraw);
1241 BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
1243 ATLASSERT(::IsWindow(m_hWnd));
1244 return FlatSB_GetScrollInfo(nBar, lpScrollInfo);
1247 BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
1249 ATLASSERT(::IsWindow(m_hWnd));
1250 return FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw);
1254 typedef CFSBWindowT<ATL::CWindow> CFSBWindow;
1256 #endif // defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
1259 ///////////////////////////////////////////////////////////////////////////////
1260 // CZoomScrollImpl - Provides zooming and scrolling support to any window
1262 #ifndef _WIN32_WCE
1264 // The zoom modes that can be set with the SetZoomMode method
1265 enum
1267 ZOOMMODE_OFF,
1268 ZOOMMODE_IN, // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged.
1269 ZOOMMODE_OUT // If left mouse button clicked, zoom out on point clicked.
1272 // Notification to parent that zoom scale changed as a result of user mouse action.
1273 #define ZSN_ZOOMCHANGED (NM_FIRST - 50)
1275 template <class T>
1276 class CZoomScrollImpl : public CScrollImpl< T >
1278 public:
1279 enum { m_cxyMinZoomRect = 12 }; // min rect size to zoom in on rect.
1281 // Data members
1282 SIZE m_sizeLogAll;
1283 SIZE m_sizeLogLine;
1284 SIZE m_sizeLogPage;
1285 float m_fZoomScale;
1286 float m_fZoomScaleMin;
1287 float m_fZoomDelta; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click.
1288 int m_nZoomMode;
1289 RECT m_rcTrack;
1290 bool m_bTracking;
1292 // Constructor
1293 CZoomScrollImpl():
1294 m_fZoomScale(1.0),
1295 m_fZoomScaleMin(0.5),
1296 m_fZoomDelta(0.5),
1297 m_nZoomMode(ZOOMMODE_OFF),
1298 m_bTracking(false)
1300 m_sizeLogAll.cx = 0;
1301 m_sizeLogAll.cy = 0;
1302 m_sizeLogPage.cx = 0;
1303 m_sizeLogPage.cy = 0;
1304 m_sizeLogLine.cx = 0;
1305 m_sizeLogLine.cy = 0;
1306 ::SetRectEmpty(&m_rcTrack);
1309 // Attributes & Operations
1311 // size operations
1312 void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
1314 ATLASSERT(cxLog >= 0 && cyLog >= 0);
1316 // Set up the defaults
1317 if (cxLog == 0 && cyLog == 0)
1319 cxLog = 1;
1320 cyLog = 1;
1323 m_sizeLogAll.cx = cxLog;
1324 m_sizeLogAll.cy = cyLog;
1325 SIZE sizeAll = { 0 };
1326 sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale);
1327 sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale);
1329 CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
1332 void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
1334 SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset);
1337 void GetScrollSize(SIZE& sizeLog) const
1339 sizeLog = m_sizeLogAll;
1342 // line operations
1343 void SetScrollLine(int cxLogLine, int cyLogLine)
1345 ATLASSERT(cxLogLine >= 0 && cyLogLine >= 0);
1347 m_sizeLogLine.cx = cxLogLine;
1348 m_sizeLogLine.cy = cyLogLine;
1350 SIZE sizeLine = { 0 };
1351 sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale);
1352 sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale);
1353 CScrollImpl< T >::SetScrollLine(sizeLine);
1356 void SetScrollLine(SIZE sizeLogLine)
1358 SetScrollLine(sizeLogLine.cx, sizeLogLine.cy);
1361 void GetScrollLine(SIZE& sizeLogLine) const
1363 sizeLogLine = m_sizeLogLine;
1366 // page operations
1367 void SetScrollPage(int cxLogPage, int cyLogPage)
1369 ATLASSERT(cxLogPage >= 0 && cyLogPage >= 0);
1371 m_sizeLogPage.cx = cxLogPage;
1372 m_sizeLogPage.cy = cyLogPage;
1374 SIZE sizePage = { 0 };
1375 sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale);
1376 sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale);
1378 CScrollImpl< T >::SetScrollPage(sizePage);
1381 void SetScrollPage(SIZE sizeLogPage)
1383 SetScrollPage(sizeLogPage.cx, sizeLogPage.cy);
1386 void GetScrollPage(SIZE& sizeLogPage) const
1388 sizeLogPage = m_sizeLogPage;
1391 void SetZoomScale(float fZoomScale)
1393 ATLASSERT(fZoomScale > 0);
1395 if(fZoomScale > 0 && fZoomScale >= m_fZoomScaleMin)
1396 m_fZoomScale = fZoomScale;
1399 float GetZoomScale() const
1401 return m_fZoomScale;
1404 void SetZoomScaleMin(float fZoomScaleMin)
1406 m_fZoomScaleMin = fZoomScaleMin;
1409 float GetZoomScaleMin() const
1411 return m_fZoomScaleMin;
1414 void SetZoomDelta(float fZoomDelta)
1416 ATLASSERT(fZoomDelta >= 0);
1418 if(fZoomDelta >= 0)
1419 m_fZoomDelta = fZoomDelta;
1422 float GetZoomDelta() const
1424 return m_fZoomDelta;
1427 void SetZoomMode(int nZoomMode)
1429 m_nZoomMode = nZoomMode;
1432 int GetZoomMode() const
1434 return m_nZoomMode;
1437 void Zoom(int x, int y, float fZoomScale)
1439 if(fZoomScale <= 0)
1440 return;
1442 fZoomScale = __max(fZoomScale, m_fZoomScaleMin);
1444 T* pT = static_cast<T*>(this);
1445 POINT pt = { x, y };
1446 if(!pT->PtInDevRect(pt))
1447 return;
1449 pT->ViewDPtoLP(&pt);
1450 pT->Zoom(fZoomScale, false);
1451 pT->CenterOnLogicalPoint(pt);
1454 void Zoom(POINT pt, float fZoomScale)
1456 T* pT = static_cast<T*>(this);
1457 pT->Zoom(pt.x, pt.y, fZoomScale);
1460 void Zoom(RECT& rc)
1462 T* pT = static_cast<T*>(this);
1463 RECT rcZoom = rc;
1464 pT->NormalizeRect(rcZoom);
1465 SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top };
1466 POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 };
1467 if(size.cx < m_cxyMinZoomRect || size.cy < m_cxyMinZoomRect)
1469 pT->Zoom(pt, m_fZoomScale + m_fZoomDelta);
1470 return;
1473 ATLASSERT(size.cx > 0 && size.cy > 0);
1475 float fScaleH = (float)(m_sizeClient.cx + 1) / (float)size.cx;
1476 float fScaleV = (float)(m_sizeClient.cy + 1) / (float)size.cy;
1477 float fZoomScale = __min(fScaleH, fScaleV) * m_fZoomScale;
1478 pT->Zoom(pt, fZoomScale);
1481 void Zoom(float fZoomScale, bool bCenter = true)
1483 if(fZoomScale <= 0)
1484 return;
1486 fZoomScale = __max(fZoomScale, m_fZoomScaleMin);
1489 T* pT = static_cast<T*>(this);
1490 POINT pt = { 0 };
1491 if(bCenter)
1493 RECT rc;
1494 ::GetClientRect(pT->m_hWnd, &rc);
1495 pt.x = rc.right / 2;
1496 pt.y = rc.bottom / 2;
1497 pT->ViewDPtoLP(&pt);
1500 // Modify the Viewport extent
1501 m_fZoomScale = fZoomScale;
1502 SIZE sizeAll = { 0 };
1503 sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale);
1504 sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale);
1506 // Update scroll bars and window
1507 CScrollImpl< T >::SetScrollSize(sizeAll);
1509 if(bCenter)
1510 pT->CenterOnLogicalPoint(pt);
1513 // Helper functions
1514 void PrepareDC(CDCHandle dc)
1516 ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
1517 dc.SetMapMode(MM_ANISOTROPIC);
1518 dc.SetWindowExt(m_sizeLogAll);
1519 dc.SetViewportExt(m_sizeAll);
1520 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
1523 void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1)
1525 ATLASSERT(lpPoints);
1526 T* pT = static_cast<T*>(this);
1527 ATLASSERT(::IsWindow(pT->m_hWnd));
1529 CWindowDC dc(pT->m_hWnd);
1530 pT->PrepareDC(dc.m_hDC);
1531 dc.DPtoLP(lpPoints, nCount);
1534 void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1)
1536 ATLASSERT(lpPoints);
1537 T* pT = static_cast<T*>(this);
1538 ATLASSERT(::IsWindow(pT->m_hWnd));
1540 CWindowDC dc(pT->m_hWnd);
1541 pT->PrepareDC(dc.m_hDC);
1542 dc.LPtoDP(lpPoints, nCount);
1545 void ClientToDevice(POINT &pt)
1547 pt.x += m_ptOffset.x;
1548 pt.y += m_ptOffset.y;
1551 void DeviceToClient(POINT &pt)
1553 pt.x -= m_ptOffset.x;
1554 pt.y -= m_ptOffset.y;
1557 void CenterOnPoint(POINT pt)
1559 T* pT = static_cast<T*>(this);
1560 RECT rect;
1561 pT->GetClientRect(&rect);
1563 int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x;
1564 if(xOfs < 0)
1566 xOfs = 0;
1568 else
1570 int xMax = __max((int)(m_sizeAll.cx - rect.right), 0);
1571 if(xOfs > xMax)
1572 xOfs = xMax;
1575 int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y;
1576 if(yOfs < 0)
1578 yOfs = 0;
1580 else
1582 int yMax = __max((int)(m_sizeAll.cy - rect.bottom), 0);
1583 if(yOfs > yMax)
1584 yOfs = yMax;
1587 CScrollImpl< T >::SetScrollOffset(xOfs, yOfs);
1590 void CenterOnLogicalPoint(POINT ptLog)
1592 T* pT = static_cast<T*>(this);
1593 pT->ViewLPtoDP(&ptLog);
1594 pT->DeviceToClient(ptLog);
1595 pT->CenterOnPoint(ptLog);
1598 BOOL PtInDevRect(POINT pt)
1600 RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy };
1601 ::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y);
1602 return ::PtInRect(&rc, pt);
1605 void NormalizeRect(RECT& rc)
1607 if(rc.left > rc.right)
1609 int r = rc.right;
1610 rc.right = rc.left;
1611 rc.left = r;
1613 if(rc.top > rc.bottom)
1615 int b = rc.bottom;
1616 rc.bottom = rc.top;
1617 rc.top = b;
1621 void DrawTrackRect()
1623 T* pT = static_cast<T*>(this);
1624 const SIZE sizeLines = { 2, 2 };
1625 RECT rc = m_rcTrack;
1626 pT->NormalizeRect(rc);
1627 if(!::IsRectEmpty(&rc))
1629 ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2);
1630 CWindowDC dc(NULL);
1631 dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines);
1635 void NotifyParentZoomChanged()
1637 T* pT = static_cast<T*>(this);
1638 int nId = pT->GetDlgCtrlID();
1639 NMHDR nmhdr = { pT->m_hWnd, nId, ZSN_ZOOMCHANGED };
1640 ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr);
1643 BEGIN_MSG_MAP(CZoomScrollImpl)
1644 MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
1645 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1646 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1647 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1648 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1649 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1650 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1651 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1652 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1653 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1654 MESSAGE_HANDLER(WM_PAINT, OnPaint)
1655 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1656 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
1657 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
1658 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
1659 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
1660 ALT_MSG_MAP(1)
1661 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1662 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1663 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1664 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1665 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1666 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1667 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1668 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1669 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1670 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1671 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1672 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1673 END_MSG_MAP()
1675 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1677 T* pT = static_cast<T*>(this);
1678 ATLASSERT(::IsWindow(pT->m_hWnd));
1679 ATLASSERT(m_sizeLogAll.cx >= 0 && m_sizeLogAll.cy >= 0);
1680 ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
1682 if(wParam != NULL)
1684 CDCHandle dc = (HDC)wParam;
1685 int nMapModeSav = dc.GetMapMode();
1686 dc.SetMapMode(MM_ANISOTROPIC);
1687 SIZE szWindowExt = { 0, 0 };
1688 dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
1689 SIZE szViewportExt = { 0, 0 };
1690 dc.SetViewportExt(m_sizeAll, &szViewportExt);
1691 POINT ptViewportOrg = { 0, 0 };
1692 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
1694 pT->DoPaint(dc);
1696 dc.SetMapMode(nMapModeSav);
1697 dc.SetWindowExt(szWindowExt);
1698 dc.SetViewportExt(szViewportExt);
1699 dc.SetViewportOrg(ptViewportOrg);
1701 else
1703 CPaintDC dc(pT->m_hWnd);
1704 pT->PrepareDC(dc.m_hDC);
1705 pT->DoPaint(dc.m_hDC);
1707 return 0;
1710 LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1712 if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking)
1714 T* pT = static_cast<T*>(this);
1715 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1716 if(pT->PtInDevRect(pt))
1718 pT->SetCapture();
1719 m_bTracking = true;
1720 ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y);
1723 bHandled = FALSE;
1724 return 0;
1727 LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1729 if(m_bTracking)
1731 T* pT = static_cast<T*>(this);
1732 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1733 if(pT->PtInDevRect(pt))
1735 pT->DrawTrackRect();
1736 m_rcTrack.right = pt.x;
1737 m_rcTrack.bottom = pt.y;
1738 pT->DrawTrackRect();
1741 bHandled = FALSE;
1742 return 0;
1745 LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1747 ::ReleaseCapture();
1748 if(m_nZoomMode == ZOOMMODE_OUT)
1750 T* pT = static_cast<T*>(this);
1751 pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta);
1752 pT->NotifyParentZoomChanged();
1754 bHandled = FALSE;
1755 return 0;
1758 LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1760 if(m_bTracking)
1762 m_bTracking = false;
1763 T* pT = static_cast<T*>(this);
1764 pT->DrawTrackRect();
1765 pT->Zoom(m_rcTrack);
1766 pT->NotifyParentZoomChanged();
1767 ::SetRectEmpty(&m_rcTrack);
1769 bHandled = FALSE;
1770 return 0;
1773 LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1775 if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF)
1777 T* pT = static_cast<T*>(this);
1778 if((HWND)wParam == pT->m_hWnd)
1780 DWORD dwPos = ::GetMessagePos();
1781 POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
1782 pT->ScreenToClient(&pt);
1783 if(pT->PtInDevRect(pt))
1785 ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
1786 return 1;
1790 bHandled = FALSE;
1791 return 0;
1795 ///////////////////////////////////////////////////////////////////////////////
1796 // CZoomScrollWindowImpl - Implements scrolling window with zooming
1798 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1799 class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
1801 public:
1802 BEGIN_MSG_MAP(CZoomScrollWindowImpl)
1803 MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
1804 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1805 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1806 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1807 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1808 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1809 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1810 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1811 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1812 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1813 MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint)
1814 MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint)
1815 MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
1816 MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
1817 MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
1818 MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
1819 ALT_MSG_MAP(1)
1820 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1821 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1822 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1823 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1824 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1825 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1826 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1827 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1828 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1829 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1830 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1831 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1832 END_MSG_MAP()
1835 #endif // !_WIN32_WCE
1838 ///////////////////////////////////////////////////////////////////////////////
1839 // CScrollContainer
1841 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1842 class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits >
1844 public:
1845 DECLARE_WND_CLASS_EX(NULL, 0, -1)
1847 typedef CScrollWindowImpl< T, TBase, TWinTraits > _baseClass;
1849 // Data members
1850 ATL::CWindow m_wndClient;
1851 bool m_bAutoSizeClient;
1852 bool m_bDrawEdgeIfEmpty;
1854 // Constructor
1855 CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false)
1857 // Set CScrollWindowImpl extended style
1858 SetScrollExtendedStyle(SCRL_SCROLLCHILDREN);
1861 // Attributes
1862 HWND GetClient() const
1864 return m_wndClient;
1867 HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true)
1869 ATLASSERT(::IsWindow(m_hWnd));
1871 HWND hWndOldClient = m_wndClient;
1872 m_wndClient = hWndClient;
1874 SetRedraw(FALSE);
1875 SetScrollSize(1, 1, FALSE);
1877 if(m_wndClient.m_hWnd != NULL)
1879 m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
1881 if(bClientSizeAsMin)
1883 RECT rect = { 0 };
1884 m_wndClient.GetWindowRect(&rect);
1885 if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0)
1886 SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE);
1889 T* pT = static_cast<T*>(this);
1890 pT->UpdateLayout();
1893 SetRedraw(TRUE);
1894 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
1896 return hWndOldClient;
1899 // Message map and handlers
1900 BEGIN_MSG_MAP(CScrollContainerImpl)
1901 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
1902 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
1903 MESSAGE_HANDLER(WM_SIZE, OnSize)
1904 CHAIN_MSG_MAP(_baseClass)
1905 FORWARD_NOTIFICATIONS()
1906 ALT_MSG_MAP(1)
1907 CHAIN_MSG_MAP_ALT(_baseClass, 1)
1908 END_MSG_MAP()
1910 LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1912 if(m_wndClient.m_hWnd != NULL)
1913 m_wndClient.SetFocus();
1915 return 0;
1918 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1920 return 1; // no background needed
1923 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1925 BOOL bTmp = TRUE;
1926 LRESULT lRet = _baseClass::OnSize(uMsg, wParam, lParam, bTmp);
1928 T* pT = static_cast<T*>(this);
1929 pT->UpdateLayout();
1931 return lRet;
1934 // Overrides for CScrollWindowImpl
1935 void DoPaint(CDCHandle dc)
1937 if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL)
1939 T* pT = static_cast<T*>(this);
1940 RECT rect = { 0 };
1941 pT->GetContainerRect(rect);
1943 if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL)
1944 dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1946 dc.FillRect(&rect, COLOR_APPWORKSPACE);
1950 void ScrollToView(POINT pt)
1952 CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt);
1955 void ScrollToView(RECT& rect)
1957 CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect);
1960 void ScrollToView(HWND hWnd) // client window coordinates
1962 T* pT = static_cast<T*>(this);
1963 pT; // avoid level 4 warning
1964 ATLASSERT(::IsWindow(pT->m_hWnd));
1965 ATLASSERT(m_wndClient.IsWindow());
1967 RECT rect = { 0 };
1968 ::GetWindowRect(hWnd, &rect);
1969 ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2);
1970 ScrollToView(rect);
1973 // Implementation - overrideable methods
1974 void UpdateLayout()
1976 ATLASSERT(::IsWindow(m_hWnd));
1978 if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL)
1980 T* pT = static_cast<T*>(this);
1981 RECT rect = { 0 };
1982 pT->GetContainerRect(rect);
1984 m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
1986 else
1988 Invalidate();
1992 void GetContainerRect(RECT& rect)
1994 GetClientRect(&rect);
1996 if(rect.right < m_sizeAll.cx)
1997 rect.right = m_sizeAll.cx;
1999 if(rect.bottom < m_sizeAll.cy)
2000 rect.bottom = m_sizeAll.cy;
2004 class CScrollContainer : public CScrollContainerImpl<CScrollContainer>
2006 public:
2007 DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1)
2010 }; // namespace WTL
2012 #endif // __ATLSCRL_H__