1 // Windows Template Library - WTL version 8.0
2 // Copyright (C) Microsoft Corporation. All rights reserved.
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.
15 #error ATL requires C++ compilation (use a .cpp suffix)
19 #error atlscrl.h requires atlapp.h to be included first
23 #error atlscrl.h requires atlwin.h to be included first
26 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
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))
34 #ifndef WM_MOUSEHWHEEL
35 #define WM_MOUSEHWHEEL 0x020E
39 ///////////////////////////////////////////////////////////////////////////////
40 // Classes in this file:
43 // CScrollWindowImpl<T, TBase, TWinTraits>
45 // CMapScrollWindowImpl<T, TBase, TWinTraits>
48 // CZoomScrollWindowImpl<T, TBase, TWinTraits>
49 // CScrollContainerImpl<T, TBase, TWinTraits>
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)
74 enum { uSCROLL_FLAGS
= SW_INVALIDATE
};
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
90 DWORD m_dwExtendedStyle
; // scroll specific extended styles
93 CScrollImpl() : m_zDelta(0), m_nWheelLines(3),
94 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
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)
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
;
124 m_dwExtendedStyle
= dwExtendedStyle
;
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)
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
;
150 // block: set horizontal scroll bar
152 SCROLLINFO si
= { sizeof(SCROLLINFO
) };
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
) };
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
))
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
);
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
;
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
));
211 pT
->AdjustScrollOffset(x
, y
);
214 int dx
= m_ptOffset
.x
- x
;
215 int dy
= 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
;
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
;
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
))
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
);
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
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
;
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
;
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
);
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
);
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
);
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
);
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
);
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
)
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
)
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
));
437 ::GetWindowRect(hWnd
, &rect
);
438 ::MapWindowPoints(NULL
, pT
->m_hWnd
, (LPPOINT
)&rect
, 2);
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
)
455 MESSAGE_HANDLER(WM_PRINTCLIENT
, OnPaint
)
456 #endif // !_WIN32_WCE
457 // standard scroll commands
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
)
473 LRESULT
OnCreate(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& bHandled
)
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
);
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
);
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)
503 int zDelta
= (int)GET_WHEEL_DELTA_WPARAM(wParam
);
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
);
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
);
526 m_zDelta
%= WHEEL_DELTA
;
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
);
548 m_zHDelta
%= WHEEL_DELTA
;
553 LRESULT
OnSettingChange(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
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
;
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
;
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
);
606 LRESULT
OnPaint(UINT
/*uMsg*/, WPARAM wParam
, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
608 T
* pT
= static_cast<T
*>(this);
609 ATLASSERT(::IsWindow(pT
->m_hWnd
));
612 CDCHandle dc
= (HDC
)wParam
;
613 POINT ptViewportOrg
= { 0, 0 };
614 dc
.SetViewportOrg(-m_ptOffset
.x
, -m_ptOffset
.y
, &ptViewportOrg
);
616 dc
.SetViewportOrg(ptViewportOrg
);
620 CPaintDC
dc(pT
->m_hWnd
);
621 dc
.SetViewportOrg(-m_ptOffset
.x
, -m_ptOffset
.y
);
622 pT
->DoPaint(dc
.m_hDC
);
627 // scrolling handlers
628 LRESULT
OnScrollUp(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
634 LRESULT
OnScrollDown(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
640 LRESULT
OnScrollPageUp(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
646 LRESULT
OnScrollPageDown(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
652 LRESULT
OnScrollTop(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
658 LRESULT
OnScrollBottom(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
664 LRESULT
OnScrollLeft(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
670 LRESULT
OnScrollRight(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
676 LRESULT
OnScrollPageLeft(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
682 LRESULT
OnScrollPageRight(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
688 LRESULT
OnScrollAllLeft(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
694 LRESULT
OnScrollAllRight(WORD
/*wNotifyCode*/, WORD
/*wID*/, HWND
/*hWndCtl*/, BOOL
& /*bHandled*/)
701 void DoPaint(CDCHandle
/*dc*/)
703 // must be implemented in a derived class
708 void DoScroll(int nType
, int nScrollCode
, int& cxyOffset
, int cxySizeAll
, int cxySizePage
, int cxySizeLine
)
710 T
* pT
= static_cast<T
*>(this);
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
724 case SB_TOP
: // top or all left
725 cxyScroll
= cxyOffset
;
728 case SB_BOTTOM
: // bottom or all right
729 cxyScroll
= cxyOffset
- cxyMax
;
732 case SB_LINEUP
: // line up or line left
733 if(cxyOffset
>= cxySizeLine
)
735 cxyScroll
= cxySizeLine
;
736 cxyOffset
-= cxySizeLine
;
740 cxyScroll
= cxyOffset
;
744 case SB_LINEDOWN
: // line down or line right
745 if(cxyOffset
< cxyMax
- cxySizeLine
)
747 cxyScroll
= -cxySizeLine
;
748 cxyOffset
+= cxySizeLine
;
752 cxyScroll
= cxyOffset
- cxyMax
;
756 case SB_PAGEUP
: // page up or page left
757 if(cxyOffset
>= cxySizePage
)
759 cxyScroll
= cxySizePage
;
760 cxyOffset
-= cxySizePage
;
764 cxyScroll
= cxyOffset
;
768 case SB_PAGEDOWN
: // page down or page right
769 if(cxyOffset
< cxyMax
- cxySizePage
)
771 cxyScroll
= -cxySizePage
;
772 cxyOffset
+= cxySizePage
;
776 cxyScroll
= cxyOffset
- cxyMax
;
781 if(IsNoThumbTracking())
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
;
800 if(bUpdate
&& cxyScroll
!= 0)
802 pT
->SetScrollPos(nType
, cxyOffset
, TRUE
);
804 pT
->ScrollWindowEx(0, cxyScroll
, m_uScrollFlags
);
806 pT
->ScrollWindowEx(cxyScroll
, 0, m_uScrollFlags
);
810 static int CalcLineOrPage(int nVal
, int nMax
, int nDiv
)
826 bool AdjustScrollOffset(int& x
, int& y
)
831 int cxMax
= m_sizeAll
.cx
- m_sizeClient
.cx
;
833 x
= (cxMax
>= 0) ? cxMax
: 0;
837 int cyMax
= m_sizeAll
.cy
- m_sizeClient
.cy
;
839 y
= (cyMax
>= 0) ? cyMax
: 0;
843 return (x
!= xOld
|| y
!= yOld
);
846 void GetSystemSettings()
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
>
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
)
917 MESSAGE_HANDLER(WM_PRINTCLIENT
, CScrollImpl
< T
>::OnPaint
)
918 #endif // !_WIN32_WCE
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
)
936 ///////////////////////////////////////////////////////////////////////////////
937 // CMapScrollImpl - Provides mapping and scrolling support to any window
942 class CMapScrollImpl
: public CScrollImpl
< T
>
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
);
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
982 dc
.SetMapMode(m_nMapMode
);
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
1000 dc
.SetMapMode(m_nMapMode
);
1001 dc
.DPtoLP(&ptOffset
);
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
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
;
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
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
;
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
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
)
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
)
1133 LRESULT
OnPaint(UINT
/*uMsg*/, WPARAM wParam
, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
1135 T
* pT
= static_cast<T
*>(this);
1136 ATLASSERT(::IsWindow(pT
->m_hWnd
));
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
);
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
);
1152 dc
.SetMapMode(nMapModeSav
);
1153 dc
.SetViewportOrg(ptViewportOrg
);
1154 dc
.SetWindowOrg(ptWindowOrg
);
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
);
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
);
1171 #endif // !_WIN32_WCE
1174 ///////////////////////////////////////////////////////////////////////////////
1175 // CMapScrollWindowImpl - Implements scrolling window with mapping
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
>
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
)
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
)
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
> >
1224 CFSBWindowT(HWND hWnd
= NULL
) : TBase(hWnd
)
1227 CFSBWindowT
< TBase
>& operator =(HWND hWnd
)
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
1264 // The zoom modes that can be set with the SetZoomMode method
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)
1276 class CZoomScrollImpl
: public CScrollImpl
< T
>
1279 enum { m_cxyMinZoomRect
= 12 }; // min rect size to zoom in on rect.
1286 float m_fZoomScaleMin
;
1287 float m_fZoomDelta
; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click.
1295 m_fZoomScaleMin(0.5),
1297 m_nZoomMode(ZOOMMODE_OFF
),
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
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)
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
;
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
;
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);
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
1437 void Zoom(int x
, int y
, float fZoomScale
)
1442 fZoomScale
= __max(fZoomScale
, m_fZoomScaleMin
);
1444 T
* pT
= static_cast<T
*>(this);
1445 POINT pt
= { x
, y
};
1446 if(!pT
->PtInDevRect(pt
))
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
);
1462 T
* pT
= static_cast<T
*>(this);
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
);
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)
1486 fZoomScale
= __max(fZoomScale
, m_fZoomScaleMin
);
1489 T
* pT
= static_cast<T
*>(this);
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
);
1510 pT
->CenterOnLogicalPoint(pt
);
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);
1561 pT
->GetClientRect(&rect
);
1563 int xOfs
= pt
.x
- (rect
.right
/ 2) + m_ptOffset
.x
;
1570 int xMax
= __max((int)(m_sizeAll
.cx
- rect
.right
), 0);
1575 int yOfs
= pt
.y
- (rect
.bottom
/ 2) + m_ptOffset
.y
;
1582 int yMax
= __max((int)(m_sizeAll
.cy
- rect
.bottom
), 0);
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
)
1613 if(rc
.top
> rc
.bottom
)
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);
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
)
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
)
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);
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
);
1696 dc
.SetMapMode(nMapModeSav
);
1697 dc
.SetWindowExt(szWindowExt
);
1698 dc
.SetViewportExt(szViewportExt
);
1699 dc
.SetViewportOrg(ptViewportOrg
);
1703 CPaintDC
dc(pT
->m_hWnd
);
1704 pT
->PrepareDC(dc
.m_hDC
);
1705 pT
->DoPaint(dc
.m_hDC
);
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
))
1720 ::SetRect(&m_rcTrack
, pt
.x
, pt
.y
, pt
.x
, pt
.y
);
1727 LRESULT
OnMouseMove(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& bHandled
)
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();
1745 LRESULT
OnLButtonUp(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& bHandled
)
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();
1758 LRESULT
OnCaptureChanged(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& bHandled
)
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
);
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
));
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
>
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
)
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
)
1835 #endif // !_WIN32_WCE
1838 ///////////////////////////////////////////////////////////////////////////////
1841 template <class T
, class TBase
= ATL::CWindow
, class TWinTraits
= ATL::CControlWinTraits
>
1842 class ATL_NO_VTABLE CScrollContainerImpl
: public CScrollWindowImpl
< T
, TBase
, TWinTraits
>
1845 DECLARE_WND_CLASS_EX(NULL
, 0, -1)
1847 typedef CScrollWindowImpl
< T
, TBase
, TWinTraits
> _baseClass
;
1850 ATL::CWindow m_wndClient
;
1851 bool m_bAutoSizeClient
;
1852 bool m_bDrawEdgeIfEmpty
;
1855 CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false)
1857 // Set CScrollWindowImpl extended style
1858 SetScrollExtendedStyle(SCRL_SCROLLCHILDREN
);
1862 HWND
GetClient() const
1867 HWND
SetClient(HWND hWndClient
, bool bClientSizeAsMin
= true)
1869 ATLASSERT(::IsWindow(m_hWnd
));
1871 HWND hWndOldClient
= m_wndClient
;
1872 m_wndClient
= hWndClient
;
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
)
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);
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()
1907 CHAIN_MSG_MAP_ALT(_baseClass
, 1)
1910 LRESULT
OnSetFocus(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
1912 if(m_wndClient
.m_hWnd
!= NULL
)
1913 m_wndClient
.SetFocus();
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*/)
1926 LRESULT lRet
= _baseClass::OnSize(uMsg
, wParam
, lParam
, bTmp
);
1928 T
* pT
= static_cast<T
*>(this);
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);
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());
1968 ::GetWindowRect(hWnd
, &rect
);
1969 ::MapWindowPoints(NULL
, m_wndClient
.m_hWnd
, (LPPOINT
)&rect
, 2);
1973 // Implementation - overrideable methods
1976 ATLASSERT(::IsWindow(m_hWnd
));
1978 if(m_bAutoSizeClient
&& m_wndClient
.m_hWnd
!= NULL
)
1980 T
* pT
= static_cast<T
*>(this);
1982 pT
->GetContainerRect(rect
);
1984 m_wndClient
.SetWindowPos(NULL
, &rect
, SWP_NOZORDER
| SWP_NOMOVE
);
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
>
2007 DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1)
2012 #endif // __ATLSCRL_H__