crashrpt2
atlscrl.h
1 // Windows Template Library - WTL version 9.10
2 // Copyright (C) Microsoft Corporation, WTL Team. 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 Public License (http://opensource.org/licenses/MS-PL)
7 // which can be found in the file MS-PL.txt at the root folder.
8 
9 #ifndef __ATLSCRL_H__
10 #define __ATLSCRL_H__
11 
12 #pragma once
13 
14 #ifndef __ATLAPP_H__
15  #error atlscrl.h requires atlapp.h to be included first
16 #endif
17 
18 #ifndef __ATLWIN_H__
19  #error atlscrl.h requires atlwin.h to be included first
20 #endif
21 
22 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
23  #include <zmouse.h>
24 #endif
25 
26 #ifndef GET_WHEEL_DELTA_WPARAM
27  #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
28 #endif
29 
30 
32 // Classes in this file:
33 //
34 // CScrollImpl<T>
35 // CScrollWindowImpl<T, TBase, TWinTraits>
36 // CMapScrollImpl<T>
37 // CMapScrollWindowImpl<T, TBase, TWinTraits>
38 // CFSBWindowT<TBase>
39 // CZoomScrollImpl<T>
40 // CZoomScrollWindowImpl<T, TBase, TWinTraits>
41 // CScrollContainerImpl<T, TBase, TWinTraits>
42 // CScrollContainer
43 
44 namespace WTL
45 {
46 
48 // CScrollImpl - Provides scrolling support to any window
49 
50 // Scroll extended styles
51 #define SCRL_SCROLLCHILDREN 0x00000001
52 #define SCRL_ERASEBACKGROUND 0x00000002
53 #define SCRL_NOTHUMBTRACKING 0x00000004
54 #if (WINVER >= 0x0500)
55 #define SCRL_SMOOTHSCROLL 0x00000008
56 #endif // (WINVER >= 0x0500)
57 #define SCRL_DISABLENOSCROLLV 0x00000010
58 #define SCRL_DISABLENOSCROLLH 0x00000020
59 #define SCRL_DISABLENOSCROLL (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH)
60 
61 
62 template <class T>
64 {
65 public:
66  enum { uSCROLL_FLAGS = SW_INVALIDATE };
67 
68  POINT m_ptOffset;
69  SIZE m_sizeAll;
70  SIZE m_sizeLine;
71  SIZE m_sizePage;
72  SIZE m_sizeClient;
73  int m_zDelta; // current wheel value
74  int m_nWheelLines; // number of lines to scroll on wheel
75 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
76  // Note that this message must be forwarded from a top level window
77  UINT m_uMsgMouseWheel; // MSH_MOUSEWHEEL
78 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
79  int m_zHDelta; // current horizontal wheel value
80  int m_nHWheelChars; // number of chars to scroll on horizontal wheel
81  UINT m_uScrollFlags;
82  DWORD m_dwExtendedStyle; // scroll specific extended styles
83 
84 // Constructor
85  CScrollImpl() : m_zDelta(0), m_nWheelLines(3),
86 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
87  m_uMsgMouseWheel(0U),
88 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
89  m_zHDelta(0), m_nHWheelChars(3),
90  m_uScrollFlags(0U), m_dwExtendedStyle(0)
91  {
92  m_ptOffset.x = 0;
93  m_ptOffset.y = 0;
94  m_sizeAll.cx = 0;
95  m_sizeAll.cy = 0;
96  m_sizePage.cx = 0;
97  m_sizePage.cy = 0;
98  m_sizeLine.cx = 0;
99  m_sizeLine.cy = 0;
100  m_sizeClient.cx = 0;
101  m_sizeClient.cy = 0;
102 
103  SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND);
104  }
105 
106 // Attributes & Operations
107  DWORD GetScrollExtendedStyle() const
108  {
109  return m_dwExtendedStyle;
110  }
111 
112  DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
113  {
114  DWORD dwPrevStyle = m_dwExtendedStyle;
115  if(dwMask == 0)
116  m_dwExtendedStyle = dwExtendedStyle;
117  else
118  m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
119  // cache scroll flags
120  T* pT = static_cast<T*>(this);
121  pT; // avoid level 4 warning
122  m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0);
123 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
124  m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0);
125 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
126  return dwPrevStyle;
127  }
128 
129  // offset operations
130  void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
131  {
132  T* pT = static_cast<T*>(this);
133  ATLASSERT(::IsWindow(pT->m_hWnd));
134 
135  pT->AdjustScrollOffset(x, y);
136 
137  int dx = m_ptOffset.x - x;
138  int dy = m_ptOffset.y - y;
139  m_ptOffset.x = x;
140  m_ptOffset.y = y;
141 
142  // block: set horizontal scroll bar
143  {
144  SCROLLINFO si = { sizeof(SCROLLINFO) };
145  si.fMask = SIF_POS;
146  if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
147  si.fMask |= SIF_DISABLENOSCROLL;
148  si.nPos = m_ptOffset.x;
149  pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
150  }
151 
152  // block: set vertical scroll bar
153  {
154  SCROLLINFO si = { sizeof(SCROLLINFO) };
155  si.fMask = SIF_POS;
156  if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
157  si.fMask |= SIF_DISABLENOSCROLL;
158  si.nPos = m_ptOffset.y;
159  pT->SetScrollInfo(SB_VERT, &si, bRedraw);
160  }
161 
162  // Move all children if needed
163  if(IsScrollingChildren() && (dx != 0 || dy != 0))
164  {
165  for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
166  {
167  RECT rect = { 0 };
168  ::GetWindowRect(hWndChild, &rect);
169  ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
170  ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
171  }
172  }
173 
174  if(bRedraw)
175  pT->Invalidate();
176  }
177 
178  void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
179  {
180  SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
181  }
182 
183  void GetScrollOffset(POINT& ptOffset) const
184  {
185  ptOffset = m_ptOffset;
186  }
187 
188  // size operations
189  void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
190  {
191  T* pT = static_cast<T*>(this);
192  ATLASSERT(::IsWindow(pT->m_hWnd));
193 
194  m_sizeAll.cx = cx;
195  m_sizeAll.cy = cy;
196 
197  int x = 0;
198  int y = 0;
199  if(!bResetOffset)
200  {
201  x = m_ptOffset.x;
202  y = m_ptOffset.y;
203  pT->AdjustScrollOffset(x, y);
204  }
205 
206  int dx = m_ptOffset.x - x;
207  int dy = m_ptOffset.y - y;
208  m_ptOffset.x = x;
209  m_ptOffset.y = y;
210 
211  // block: set horizontal scroll bar
212  {
213  SCROLLINFO si = { sizeof(SCROLLINFO) };
214  si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
215  if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
216  si.fMask |= SIF_DISABLENOSCROLL;
217  si.nMin = 0;
218  si.nMax = m_sizeAll.cx - 1;
219  si.nPage = m_sizeClient.cx;
220  si.nPos = m_ptOffset.x;
221  pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
222  }
223 
224  // block: set vertical scroll bar
225  {
226  SCROLLINFO si = { sizeof(SCROLLINFO) };
227  si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
228  if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
229  si.fMask |= SIF_DISABLENOSCROLL;
230  si.nMin = 0;
231  si.nMax = m_sizeAll.cy - 1;
232  si.nPage = m_sizeClient.cy;
233  si.nPos = m_ptOffset.y;
234  pT->SetScrollInfo(SB_VERT, &si, bRedraw);
235  }
236 
237  // Move all children if needed
238  if(IsScrollingChildren() && (dx != 0 || dy != 0))
239  {
240  for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
241  {
242  RECT rect = { 0 };
243  ::GetWindowRect(hWndChild, &rect);
244  ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
245  ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
246  }
247  }
248 
249  SetScrollLine(0, 0);
250  SetScrollPage(0, 0);
251 
252  if(bRedraw)
253  pT->Invalidate();
254  }
255 
256  void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
257  {
258  SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset);
259  }
260 
261  void GetScrollSize(SIZE& sizeWnd) const
262  {
263  sizeWnd = m_sizeAll;
264  }
265 
266  // line operations
267  void SetScrollLine(int cxLine, int cyLine)
268  {
269  ATLASSERT(cxLine >= 0 && cyLine >= 0);
270  ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
271 
272  m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100);
273  m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100);
274  }
275 
276  void SetScrollLine(SIZE sizeLine)
277  {
278  SetScrollLine(sizeLine.cx, sizeLine.cy);
279  }
280 
281  void GetScrollLine(SIZE& sizeLine) const
282  {
283  sizeLine = m_sizeLine;
284  }
285 
286  // page operations
287  void SetScrollPage(int cxPage, int cyPage)
288  {
289  ATLASSERT(cxPage >= 0 && cyPage >= 0);
290  ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
291 
292  m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10);
293  m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10);
294  }
295 
296  void SetScrollPage(SIZE sizePage)
297  {
298  SetScrollPage(sizePage.cx, sizePage.cy);
299  }
300 
301  void GetScrollPage(SIZE& sizePage) const
302  {
303  sizePage = m_sizePage;
304  }
305 
306  // commands
307  void ScrollLineDown()
308  {
309  T* pT = static_cast<T*>(this);
310  ATLASSERT(::IsWindow(pT->m_hWnd));
311  pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
312  }
313 
314  void ScrollLineUp()
315  {
316  T* pT = static_cast<T*>(this);
317  ATLASSERT(::IsWindow(pT->m_hWnd));
318  pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
319  }
320 
321  void ScrollPageDown()
322  {
323  T* pT = static_cast<T*>(this);
324  ATLASSERT(::IsWindow(pT->m_hWnd));
325  pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
326  }
327 
328  void ScrollPageUp()
329  {
330  T* pT = static_cast<T*>(this);
331  ATLASSERT(::IsWindow(pT->m_hWnd));
332  pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
333  }
334 
335  void ScrollTop()
336  {
337  T* pT = static_cast<T*>(this);
338  ATLASSERT(::IsWindow(pT->m_hWnd));
339  pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
340  }
341 
342  void ScrollBottom()
343  {
344  T* pT = static_cast<T*>(this);
345  ATLASSERT(::IsWindow(pT->m_hWnd));
346  pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
347  }
348 
349  void ScrollLineRight()
350  {
351  T* pT = static_cast<T*>(this);
352  ATLASSERT(::IsWindow(pT->m_hWnd));
353  pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
354  }
355 
356  void ScrollLineLeft()
357  {
358  T* pT = static_cast<T*>(this);
359  ATLASSERT(::IsWindow(pT->m_hWnd));
360  pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
361  }
362 
363  void ScrollPageRight()
364  {
365  T* pT = static_cast<T*>(this);
366  ATLASSERT(::IsWindow(pT->m_hWnd));
367  pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
368  }
369 
370  void ScrollPageLeft()
371  {
372  T* pT = static_cast<T*>(this);
373  ATLASSERT(::IsWindow(pT->m_hWnd));
374  pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
375  }
376 
377  void ScrollAllLeft()
378  {
379  T* pT = static_cast<T*>(this);
380  ATLASSERT(::IsWindow(pT->m_hWnd));
381  pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
382  }
383 
384  void ScrollAllRight()
385  {
386  T* pT = static_cast<T*>(this);
387  ATLASSERT(::IsWindow(pT->m_hWnd));
388  pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
389  }
390 
391  // scroll to make point/view/window visible
392  void ScrollToView(POINT pt)
393  {
394  T* pT = static_cast<T*>(this);
395  ATLASSERT(::IsWindow(pT->m_hWnd));
396  RECT rect = { pt.x, pt.y, pt.x, pt.y };
397  pT->ScrollToView(rect);
398  }
399 
400  void ScrollToView(RECT& rect)
401  {
402  T* pT = static_cast<T*>(this);
403  ATLASSERT(::IsWindow(pT->m_hWnd));
404 
405  RECT rcClient = { 0 };
406  pT->GetClientRect(&rcClient);
407 
408  int x = m_ptOffset.x;
409  if(rect.left < m_ptOffset.x)
410  x = rect.left;
411  else if(rect.right > (m_ptOffset.x + rcClient.right))
412  x = rect.right - rcClient.right;
413 
414  int y = m_ptOffset.y;
415  if(rect.top < m_ptOffset.y)
416  y = rect.top;
417  else if(rect.bottom > (m_ptOffset.y + rcClient.bottom))
418  y = rect.bottom - rcClient.bottom;
419 
420  SetScrollOffset(x, y);
421  }
422 
423  void ScrollToView(HWND hWnd)
424  {
425  T* pT = static_cast<T*>(this);
426  ATLASSERT(::IsWindow(pT->m_hWnd));
427 
428  RECT rect = { 0 };
429  ::GetWindowRect(hWnd, &rect);
430  ::OffsetRect(&rect, m_ptOffset.x, m_ptOffset.y);
431  ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
432  ScrollToView(rect);
433  }
434 
435  BEGIN_MSG_MAP(CScrollImpl)
436  MESSAGE_HANDLER(WM_CREATE, OnCreate)
437  MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
438  MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
439  MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
440 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
441  MESSAGE_HANDLER(m_uMsgMouseWheel, OnMouseWheel)
442 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
443  MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel)
444  MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
445  MESSAGE_HANDLER(WM_SIZE, OnSize)
446  MESSAGE_HANDLER(WM_PAINT, OnPaint)
447 #ifndef _WIN32_WCE
448  MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
449 #endif // !_WIN32_WCE
450  // standard scroll commands
451  ALT_MSG_MAP(1)
452  COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp)
453  COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown)
454  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp)
455  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown)
456  COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop)
457  COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom)
458  COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft)
459  COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight)
460  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft)
461  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight)
462  COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft)
463  COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight)
464  END_MSG_MAP()
465 
466  LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
467  {
468  T* pT = static_cast<T*>(this);
469  pT->GetSystemSettings();
470 
471  bHandled = FALSE;
472  return 1;
473  }
474 
475  LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
476  {
477  T* pT = static_cast<T*>(this);
478  ATLASSERT(::IsWindow(pT->m_hWnd));
479  pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
480  return 0;
481  }
482 
483  LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
484  {
485  T* pT = static_cast<T*>(this);
486  ATLASSERT(::IsWindow(pT->m_hWnd));
487  pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
488  return 0;
489  }
490 
491  LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
492  {
493  T* pT = static_cast<T*>(this);
494  ATLASSERT(::IsWindow(pT->m_hWnd));
495 
496 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE)
497  uMsg;
498  int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
499 #else
500  int zDelta = (uMsg == WM_MOUSEWHEEL) ? (int)GET_WHEEL_DELTA_WPARAM(wParam) : (int)wParam;
501 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE))
502  int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN);
503  m_zDelta += zDelta; // cumulative
504  int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines;
505  if(m_sizeAll.cy > m_sizeClient.cy)
506  {
507  for(int i = 0; i < zTotal; i += WHEEL_DELTA)
508  {
509  pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
510  pT->UpdateWindow();
511  }
512  }
513  else if(m_sizeAll.cx > m_sizeClient.cx) // can't scroll vertically, scroll horizontally
514  {
515  for(int i = 0; i < zTotal; i += WHEEL_DELTA)
516  {
517  pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
518  pT->UpdateWindow();
519  }
520  }
521  m_zDelta %= WHEEL_DELTA;
522 
523  return 0;
524  }
525 
526  LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
527  {
528  T* pT = static_cast<T*>(this);
529  ATLASSERT(::IsWindow(pT->m_hWnd));
530 
531  int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
532  int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT);
533  m_zHDelta += zDelta; // cumulative
534  int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars;
535  if(m_sizeAll.cx > m_sizeClient.cx)
536  {
537  for(int i = 0; i < zTotal; i += WHEEL_DELTA)
538  {
539  pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
540  pT->UpdateWindow();
541  }
542  }
543  m_zHDelta %= WHEEL_DELTA;
544 
545  return 0;
546  }
547 
548  LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
549  {
550  GetSystemSettings();
551  return 0;
552  }
553 
554  LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
555  {
556  T* pT = static_cast<T*>(this);
557  ATLASSERT(::IsWindow(pT->m_hWnd));
558 
559  pT->DoSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
560 
561  bHandled = FALSE;
562  return 1;
563  }
564 
565  LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
566  {
567  T* pT = static_cast<T*>(this);
568  ATLASSERT(::IsWindow(pT->m_hWnd));
569  if(wParam != NULL)
570  {
571  CDCHandle dc = (HDC)wParam;
572  POINT ptViewportOrg = { 0, 0 };
573  dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
574  pT->DoPaint(dc);
575  dc.SetViewportOrg(ptViewportOrg);
576  }
577  else
578  {
579  CPaintDC dc(pT->m_hWnd);
580  dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
581  pT->DoPaint(dc.m_hDC);
582  }
583  return 0;
584  }
585 
586  // scrolling handlers
587  LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
588  {
589  ScrollLineUp();
590  return 0;
591  }
592 
593  LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
594  {
595  ScrollLineDown();
596  return 0;
597  }
598 
599  LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
600  {
601  ScrollPageUp();
602  return 0;
603  }
604 
605  LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
606  {
607  ScrollPageDown();
608  return 0;
609  }
610 
611  LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
612  {
613  ScrollTop();
614  return 0;
615  }
616 
617  LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
618  {
619  ScrollBottom();
620  return 0;
621  }
622 
623  LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
624  {
625  ScrollLineLeft();
626  return 0;
627  }
628 
629  LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
630  {
631  ScrollLineRight();
632  return 0;
633  }
634 
635  LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
636  {
637  ScrollPageLeft();
638  return 0;
639  }
640 
641  LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
642  {
643  ScrollPageRight();
644  return 0;
645  }
646 
647  LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
648  {
649  ScrollAllLeft();
650  return 0;
651  }
652 
653  LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
654  {
655  ScrollAllRight();
656  return 0;
657  }
658 
659 // Overrideables
660  void DoPaint(CDCHandle /*dc*/)
661  {
662  // must be implemented in a derived class
663  ATLASSERT(FALSE);
664  }
665 
666 // Implementation
667  void DoSize(int cx, int cy)
668  {
669  m_sizeClient.cx = cx;
670  m_sizeClient.cy = cy;
671 
672  T* pT = static_cast<T*>(this);
673 
674  // block: set horizontal scroll bar
675  {
676  SCROLLINFO si = { sizeof(SCROLLINFO) };
677  si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
678  si.nMin = 0;
679  si.nMax = m_sizeAll.cx - 1;
680  if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
681  si.fMask |= SIF_DISABLENOSCROLL;
682  si.nPage = m_sizeClient.cx;
683  si.nPos = m_ptOffset.x;
684  pT->SetScrollInfo(SB_HORZ, &si, TRUE);
685  }
686 
687  // block: set vertical scroll bar
688  {
689  SCROLLINFO si = { sizeof(SCROLLINFO) };
690  si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
691  si.nMin = 0;
692  si.nMax = m_sizeAll.cy - 1;
693  if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
694  si.fMask |= SIF_DISABLENOSCROLL;
695  si.nPage = m_sizeClient.cy;
696  si.nPos = m_ptOffset.y;
697  pT->SetScrollInfo(SB_VERT, &si, TRUE);
698  }
699 
700  int x = m_ptOffset.x;
701  int y = m_ptOffset.y;
702  if(pT->AdjustScrollOffset(x, y))
703  {
704  // Children will be moved in SetScrollOffset, if needed
705  pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN));
706  SetScrollOffset(x, y, FALSE);
707  }
708  }
709 
710  void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine)
711  {
712  T* pT = static_cast<T*>(this);
713  RECT rect = { 0 };
714  pT->GetClientRect(&rect);
715  int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right;
716  int cxyMax = cxySizeAll - cxyClient;
717 
718  if(cxyMax < 0) // can't scroll, client area is bigger
719  return;
720 
721  bool bUpdate = true;
722  int cxyScroll = 0;
723 
724  switch(nScrollCode)
725  {
726  case SB_TOP: // top or all left
727  cxyScroll = cxyOffset;
728  cxyOffset = 0;
729  break;
730  case SB_BOTTOM: // bottom or all right
731  cxyScroll = cxyOffset - cxyMax;
732  cxyOffset = cxyMax;
733  break;
734  case SB_LINEUP: // line up or line left
735  if(cxyOffset >= cxySizeLine)
736  {
737  cxyScroll = cxySizeLine;
738  cxyOffset -= cxySizeLine;
739  }
740  else
741  {
742  cxyScroll = cxyOffset;
743  cxyOffset = 0;
744  }
745  break;
746  case SB_LINEDOWN: // line down or line right
747  if(cxyOffset < cxyMax - cxySizeLine)
748  {
749  cxyScroll = -cxySizeLine;
750  cxyOffset += cxySizeLine;
751  }
752  else
753  {
754  cxyScroll = cxyOffset - cxyMax;
755  cxyOffset = cxyMax;
756  }
757  break;
758  case SB_PAGEUP: // page up or page left
759  if(cxyOffset >= cxySizePage)
760  {
761  cxyScroll = cxySizePage;
762  cxyOffset -= cxySizePage;
763  }
764  else
765  {
766  cxyScroll = cxyOffset;
767  cxyOffset = 0;
768  }
769  break;
770  case SB_PAGEDOWN: // page down or page right
771  if(cxyOffset < cxyMax - cxySizePage)
772  {
773  cxyScroll = -cxySizePage;
774  cxyOffset += cxySizePage;
775  }
776  else
777  {
778  cxyScroll = cxyOffset - cxyMax;
779  cxyOffset = cxyMax;
780  }
781  break;
782  case SB_THUMBTRACK:
783  if(IsNoThumbTracking())
784  break;
785  // else fall through
786  case SB_THUMBPOSITION:
787  {
788  SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS };
789  if(pT->GetScrollInfo(nType, &si))
790  {
791  cxyScroll = cxyOffset - si.nTrackPos;
792  cxyOffset = si.nTrackPos;
793  }
794  }
795  break;
796  case SB_ENDSCROLL:
797  default:
798  bUpdate = false;
799  break;
800  }
801 
802  if(bUpdate && cxyScroll != 0)
803  {
804  pT->SetScrollPos(nType, cxyOffset, TRUE);
805  if(nType == SB_VERT)
806  pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags);
807  else
808  pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags);
809  }
810  }
811 
812  static int CalcLineOrPage(int nVal, int nMax, int nDiv)
813  {
814  if(nVal == 0)
815  {
816  nVal = nMax / nDiv;
817  if(nVal < 1)
818  nVal = 1;
819  }
820  else if(nVal > nMax)
821  {
822  nVal = nMax;
823  }
824 
825  return nVal;
826  }
827 
828  bool AdjustScrollOffset(int& x, int& y)
829  {
830  int xOld = x;
831  int yOld = y;
832 
833  int cxMax = m_sizeAll.cx - m_sizeClient.cx;
834  if(x > cxMax)
835  x = (cxMax >= 0) ? cxMax : 0;
836  else if(x < 0)
837  x = 0;
838 
839  int cyMax = m_sizeAll.cy - m_sizeClient.cy;
840  if(y > cyMax)
841  y = (cyMax >= 0) ? cyMax : 0;
842  else if(y < 0)
843  y = 0;
844 
845  return (x != xOld || y != yOld);
846  }
847 
848  void GetSystemSettings()
849  {
850 #ifndef _WIN32_WCE
851 #ifndef SPI_GETWHEELSCROLLLINES
852  const UINT SPI_GETWHEELSCROLLLINES = 104;
853 #endif // !SPI_GETWHEELSCROLLLINES
854  ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0);
855 
856 #ifndef SPI_GETWHEELSCROLLCHARS
857  const UINT SPI_GETWHEELSCROLLCHARS = 0x006C;
858 #endif // !SPI_GETWHEELSCROLLCHARS
859  ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0);
860 
861 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
862  if(m_uMsgMouseWheel != 0)
863  m_uMsgMouseWheel = ::RegisterWindowMessage(MSH_MOUSEWHEEL);
864 
865  HWND hWndWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE);
866  if(::IsWindow(hWndWheel))
867  {
868  UINT uMsgScrollLines = ::RegisterWindowMessage(MSH_SCROLL_LINES);
869  if(uMsgScrollLines != 0)
870  m_nWheelLines = (int)::SendMessage(hWndWheel, uMsgScrollLines, 0, 0L);
871  }
872 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
873 #endif // !_WIN32_WCE
874  }
875 
876  bool IsScrollingChildren() const
877  {
878  return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0;
879  }
880 
881  bool IsErasingBackground() const
882  {
883  return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0;
884  }
885 
886  bool IsNoThumbTracking() const
887  {
888  return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0;
889  }
890 
891 #if (WINVER >= 0x0500)
892  bool IsSmoothScroll() const
893  {
894  return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0;
895  }
896 #endif // (WINVER >= 0x0500)
897 };
898 
899 
901 // CScrollWindowImpl - Implements a scrollable window
902 
903 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
904 class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CScrollImpl< T >
905 {
906 public:
907  BOOL SubclassWindow(HWND hWnd)
908  {
909 #if (_MSC_VER >= 1300)
910  BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
911 #else // !(_MSC_VER >= 1300)
912  typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
913  BOOL bRet = _baseClass::SubclassWindow(hWnd);
914 #endif // !(_MSC_VER >= 1300)
915  if(bRet != FALSE)
916  {
917  T* pT = static_cast<T*>(this);
918  pT->GetSystemSettings();
919 
920  RECT rect = { 0 };
921  GetClientRect(&rect);
922  pT->DoSize(rect.right, rect.bottom);
923  }
924 
925  return bRet;
926  }
927 
928  BEGIN_MSG_MAP(CScrollWindowImpl)
929  MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
930  MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
931  MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
932 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
933  MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
934 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
935  MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
936  MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
937  MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
938  MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint)
939 #ifndef _WIN32_WCE
940  MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint)
941 #endif // !_WIN32_WCE
942  ALT_MSG_MAP(1)
943  COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
944  COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
945  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
946  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
947  COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
948  COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
949  COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
950  COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
951  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
952  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
953  COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
954  COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
955  END_MSG_MAP()
956 };
957 
958 
960 // CMapScrollImpl - Provides mapping and scrolling support to any window
961 
962 #ifndef _WIN32_WCE
963 
964 template <class T>
965 class CMapScrollImpl : public CScrollImpl< T >
966 {
967 public:
968  int m_nMapMode;
969  RECT m_rectLogAll;
970  SIZE m_sizeLogLine;
971  SIZE m_sizeLogPage;
972 
973 // Constructor
974  CMapScrollImpl() : m_nMapMode(MM_TEXT)
975  {
976  ::SetRectEmpty(&m_rectLogAll);
977  m_sizeLogPage.cx = 0;
978  m_sizeLogPage.cy = 0;
979  m_sizeLogLine.cx = 0;
980  m_sizeLogLine.cy = 0;
981  }
982 
983 // Attributes & Operations
984  // mapping mode operations
985  void SetScrollMapMode(int nMapMode)
986  {
987  ATLASSERT(nMapMode >= MM_MIN && nMapMode <= MM_MAX_FIXEDSCALE);
988  m_nMapMode = nMapMode;
989  }
990 
991  int GetScrollMapMode() const
992  {
993  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
994  return m_nMapMode;
995  }
996 
997  // offset operations
998  void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
999  {
1000  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1001  POINT ptOff = { x, y };
1002  // block: convert logical to device units
1003  {
1004  CWindowDC dc(NULL);
1005  dc.SetMapMode(m_nMapMode);
1006  dc.LPtoDP(&ptOff);
1007  }
1008  CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw);
1009  }
1010 
1011  void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
1012  {
1013  SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
1014  }
1015 
1016  void GetScrollOffset(POINT& ptOffset) const
1017  {
1018  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1019  ptOffset = m_ptOffset;
1020  // block: convert device to logical units
1021  {
1022  CWindowDC dc(NULL);
1023  dc.SetMapMode(m_nMapMode);
1024  dc.DPtoLP(&ptOffset);
1025  }
1026  }
1027 
1028  // size operations
1029  void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true)
1030  {
1031  ATLASSERT(xMax > xMin && yMax > yMin);
1032  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1033 
1034  ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax);
1035 
1036  SIZE sizeAll = { 0 };
1037  sizeAll.cx = xMax - xMin + 1;
1038  sizeAll.cy = yMax - yMin + 1;
1039  // block: convert logical to device units
1040  {
1041  CWindowDC dc(NULL);
1042  dc.SetMapMode(m_nMapMode);
1043  dc.LPtoDP(&sizeAll);
1044  }
1045  CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
1046  SetScrollLine(0, 0);
1047  SetScrollPage(0, 0);
1048  }
1049 
1050  void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true)
1051  {
1052  SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset);
1053  }
1054 
1055  void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
1056  {
1057  SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset);
1058  }
1059 
1060  void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
1061  {
1062  SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset);
1063  }
1064 
1065  void GetScrollSize(RECT& rcScroll) const
1066  {
1067  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1068  rcScroll = m_rectLogAll;
1069  }
1070 
1071  // line operations
1072  void SetScrollLine(int cxLine, int cyLine)
1073  {
1074  ATLASSERT(cxLine >= 0 && cyLine >= 0);
1075  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1076 
1077  m_sizeLogLine.cx = cxLine;
1078  m_sizeLogLine.cy = cyLine;
1079  SIZE sizeLine = m_sizeLogLine;
1080  // block: convert logical to device units
1081  {
1082  CWindowDC dc(NULL);
1083  dc.SetMapMode(m_nMapMode);
1084  dc.LPtoDP(&sizeLine);
1085  }
1087  }
1088 
1089  void SetScrollLine(SIZE sizeLine)
1090  {
1091  SetScrollLine(sizeLine.cx, sizeLine.cy);
1092  }
1093 
1094  void GetScrollLine(SIZE& sizeLine) const
1095  {
1096  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1097  sizeLine = m_sizeLogLine;
1098  }
1099 
1100  // page operations
1101  void SetScrollPage(int cxPage, int cyPage)
1102  {
1103  ATLASSERT(cxPage >= 0 && cyPage >= 0);
1104  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1105 
1106  m_sizeLogPage.cx = cxPage;
1107  m_sizeLogPage.cy = cyPage;
1108  SIZE sizePage = m_sizeLogPage;
1109  // block: convert logical to device units
1110  {
1111  CWindowDC dc(NULL);
1112  dc.SetMapMode(m_nMapMode);
1113  dc.LPtoDP(&sizePage);
1114  }
1116  }
1117 
1118  void SetScrollPage(SIZE sizePage)
1119  {
1120  SetScrollPage(sizePage.cx, sizePage.cy);
1121  }
1122 
1123  void GetScrollPage(SIZE& sizePage) const
1124  {
1125  ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1126  sizePage = m_sizeLogPage;
1127  }
1128 
1129  BEGIN_MSG_MAP(CMapScrollImpl)
1130  MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1131  MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1132  MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1133 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1134  MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1135 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1136  MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1137  MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1138  MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1139  MESSAGE_HANDLER(WM_PAINT, OnPaint)
1140  MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1141  ALT_MSG_MAP(1)
1142  COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1143  COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1144  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1145  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1146  COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1147  COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1148  COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1149  COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1150  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1151  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1152  COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1153  COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1154  END_MSG_MAP()
1155 
1156  LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1157  {
1158  T* pT = static_cast<T*>(this);
1159  ATLASSERT(::IsWindow(pT->m_hWnd));
1160  if(wParam != NULL)
1161  {
1162  CDCHandle dc = (HDC)wParam;
1163  int nMapModeSav = dc.GetMapMode();
1164  dc.SetMapMode(m_nMapMode);
1165  POINT ptViewportOrg = { 0, 0 };
1166  if(m_nMapMode == MM_TEXT)
1167  dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
1168  else
1169  dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy, &ptViewportOrg);
1170  POINT ptWindowOrg = { 0, 0 };
1171  dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg);
1172 
1173  pT->DoPaint(dc);
1174 
1175  dc.SetMapMode(nMapModeSav);
1176  dc.SetViewportOrg(ptViewportOrg);
1177  dc.SetWindowOrg(ptWindowOrg);
1178  }
1179  else
1180  {
1181  CPaintDC dc(pT->m_hWnd);
1182  dc.SetMapMode(m_nMapMode);
1183  if(m_nMapMode == MM_TEXT)
1184  dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
1185  else
1186  dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy);
1187  dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top);
1188  pT->DoPaint(dc.m_hDC);
1189  }
1190  return 0;
1191  }
1192 };
1193 
1194 #endif // !_WIN32_WCE
1195 
1196 
1198 // CMapScrollWindowImpl - Implements scrolling window with mapping
1199 
1200 #ifndef _WIN32_WCE
1201 
1202 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1203 class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T >
1204 {
1205 public:
1206  BOOL SubclassWindow(HWND hWnd)
1207  {
1208 #if (_MSC_VER >= 1300)
1209  BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
1210 #else // !(_MSC_VER >= 1300)
1211  typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
1212  BOOL bRet = _baseClass::SubclassWindow(hWnd);
1213 #endif // !(_MSC_VER >= 1300)
1214  if(bRet != FALSE)
1215  {
1216  T* pT = static_cast<T*>(this);
1217  pT->GetSystemSettings();
1218 
1219  RECT rect = { 0 };
1220  GetClientRect(&rect);
1221  pT->DoSize(rect.right, rect.bottom);
1222  }
1223 
1224  return bRet;
1225  }
1226 
1227  BEGIN_MSG_MAP(CMapScrollWindowImpl)
1228  MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1229  MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1230  MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1231 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1232  MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1233 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1234  MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1235  MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1236  MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1237  MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint)
1238  MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint)
1239  ALT_MSG_MAP(1)
1240  COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1241  COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1242  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1243  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1244  COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1245  COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1246  COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1247  COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1248  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1249  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1250  COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1251  COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1252  END_MSG_MAP()
1253 };
1254 
1255 #endif // !_WIN32_WCE
1256 
1257 
1259 // CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support
1260 
1261 #if defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
1262 
1263 template <class TBase = ATL::CWindow>
1264 class CFSBWindowT : public TBase, public CFlatScrollBarImpl<CFSBWindowT< TBase > >
1265 {
1266 public:
1267 // Constructors
1268  CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd)
1269  { }
1270 
1271  CFSBWindowT< TBase >& operator =(HWND hWnd)
1272  {
1273  m_hWnd = hWnd;
1274  return *this;
1275  }
1276 
1277 // CWindow overrides that use flat scroll bar API
1278 // (only those methods that are used by scroll window classes)
1279  int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
1280  {
1281  ATLASSERT(::IsWindow(m_hWnd));
1282  return FlatSB_SetScrollPos(nBar, nPos, bRedraw);
1283  }
1284 
1285  BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
1286  {
1287  ATLASSERT(::IsWindow(m_hWnd));
1288  return FlatSB_GetScrollInfo(nBar, lpScrollInfo);
1289  }
1290 
1291  BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
1292  {
1293  ATLASSERT(::IsWindow(m_hWnd));
1294  return FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw);
1295  }
1296 };
1297 
1298 typedef CFSBWindowT<ATL::CWindow> CFSBWindow;
1299 
1300 #endif // defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
1301 
1302 
1304 // CZoomScrollImpl - Provides zooming and scrolling support to any window
1305 
1306 #ifndef _WIN32_WCE
1307 
1308 // The zoom modes that can be set with the SetZoomMode method
1309 enum
1310 {
1311  ZOOMMODE_OFF,
1312  ZOOMMODE_IN, // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged.
1313  ZOOMMODE_OUT // If left mouse button clicked, zoom out on point clicked.
1314 };
1315 
1316 // Notification to parent that zoom scale changed as a result of user mouse action.
1317 #define ZSN_ZOOMCHANGED (NM_FIRST - 50)
1318 
1319 template <class T>
1320 class CZoomScrollImpl : public CScrollImpl< T >
1321 {
1322 public:
1323  enum { m_cxyMinZoomRect = 12 }; // min rect size to zoom in on rect.
1324 
1326  {
1327  HWND hWnd;
1328  int x;
1329  int y;
1330  int cx;
1331  int cy;
1332 
1333  bool operator ==(const _ChildPlacement& cp) const { return (memcmp(this, &cp, sizeof(_ChildPlacement)) == 0); }
1334  };
1335 
1336 // Data members
1337  SIZE m_sizeLogAll;
1338  SIZE m_sizeLogLine;
1339  SIZE m_sizeLogPage;
1340  float m_fZoomScale;
1341  float m_fZoomScaleMin;
1342  float m_fZoomScaleMax;
1343  float m_fZoomDelta; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click.
1344  int m_nZoomMode;
1345  RECT m_rcTrack;
1346  bool m_bTracking;
1347 
1348  bool m_bZoomChildren;
1349  ATL::CSimpleArray<_ChildPlacement> m_arrChildren;
1350 
1351 // Constructor
1352  CZoomScrollImpl(): m_fZoomScale(1.0f), m_fZoomScaleMin(0.1f), m_fZoomScaleMax(100.0f), m_fZoomDelta(0.5f),
1353  m_nZoomMode(ZOOMMODE_OFF), m_bTracking(false), m_bZoomChildren(false)
1354  {
1355  m_sizeLogAll.cx = 0;
1356  m_sizeLogAll.cy = 0;
1357  m_sizeLogPage.cx = 0;
1358  m_sizeLogPage.cy = 0;
1359  m_sizeLogLine.cx = 0;
1360  m_sizeLogLine.cy = 0;
1361  ::SetRectEmpty(&m_rcTrack);
1362  }
1363 
1364 // Attributes & Operations
1365  // size operations
1366  void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
1367  {
1368  ATLASSERT(cxLog >= 0 && cyLog >= 0);
1369 
1370  // Set up the defaults
1371  if((cxLog == 0) && (cyLog == 0))
1372  {
1373  cxLog = 1;
1374  cyLog = 1;
1375  }
1376 
1377  m_sizeLogAll.cx = cxLog;
1378  m_sizeLogAll.cy = cyLog;
1379  SIZE sizeAll = { 0 };
1380  sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale);
1381  sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale);
1382 
1383  CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
1384  }
1385 
1386  void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
1387  {
1388  SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset);
1389  }
1390 
1391  void GetScrollSize(SIZE& sizeLog) const
1392  {
1393  sizeLog = m_sizeLogAll;
1394  }
1395 
1396  // line operations
1397  void SetScrollLine(int cxLogLine, int cyLogLine)
1398  {
1399  ATLASSERT(cxLogLine >= 0 && cyLogLine >= 0);
1400 
1401  m_sizeLogLine.cx = cxLogLine;
1402  m_sizeLogLine.cy = cyLogLine;
1403 
1404  SIZE sizeLine = { 0 };
1405  sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale);
1406  sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale);
1408  }
1409 
1410  void SetScrollLine(SIZE sizeLogLine)
1411  {
1412  SetScrollLine(sizeLogLine.cx, sizeLogLine.cy);
1413  }
1414 
1415  void GetScrollLine(SIZE& sizeLogLine) const
1416  {
1417  sizeLogLine = m_sizeLogLine;
1418  }
1419 
1420  // page operations
1421  void SetScrollPage(int cxLogPage, int cyLogPage)
1422  {
1423  ATLASSERT((cxLogPage >= 0) && (cyLogPage >= 0));
1424 
1425  m_sizeLogPage.cx = cxLogPage;
1426  m_sizeLogPage.cy = cyLogPage;
1427 
1428  SIZE sizePage = { 0 };
1429  sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale);
1430  sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale);
1431 
1433  }
1434 
1435  void SetScrollPage(SIZE sizeLogPage)
1436  {
1437  SetScrollPage(sizeLogPage.cx, sizeLogPage.cy);
1438  }
1439 
1440  void GetScrollPage(SIZE& sizeLogPage) const
1441  {
1442  sizeLogPage = m_sizeLogPage;
1443  }
1444 
1445  void SetZoomScale(float fZoomScale)
1446  {
1447  ATLASSERT(fZoomScale > 0.0f);
1448  if(fZoomScale <= 0.0f)
1449  return;
1450 
1451  m_fZoomScale = fZoomScale;
1452  if(m_fZoomScale < m_fZoomScaleMin)
1453  m_fZoomScale = m_fZoomScaleMin;
1454  else if(m_fZoomScale > m_fZoomScaleMax)
1455  m_fZoomScale = m_fZoomScaleMax;
1456  }
1457 
1458  float GetZoomScale() const
1459  {
1460  return m_fZoomScale;
1461  }
1462 
1463  void SetZoomScaleMin(float fZoomScaleMin)
1464  {
1465  ATLASSERT(fZoomScaleMin > 0.0f);
1466  ATLASSERT(fZoomScaleMin <= m_fZoomScaleMax);
1467 
1468  m_fZoomScaleMin = fZoomScaleMin;
1469  }
1470 
1471  float GetZoomScaleMin() const
1472  {
1473  return m_fZoomScaleMin;
1474  }
1475 
1476  void SetZoomScaleMax(float fZoomScaleMax)
1477  {
1478  ATLASSERT(fZoomScaleMax > 0.0f);
1479  ATLASSERT(m_fZoomScaleMin <= fZoomScaleMax);
1480 
1481  m_fZoomScaleMax = fZoomScaleMax;
1482  }
1483 
1484  float GetZoomScaleMax() const
1485  {
1486  return m_fZoomScaleMax;
1487  }
1488 
1489  void SetZoomDelta(float fZoomDelta)
1490  {
1491  ATLASSERT(fZoomDelta >= 0.0f);
1492 
1493  if(fZoomDelta >= 0.0f)
1494  m_fZoomDelta = fZoomDelta;
1495  }
1496 
1497  float GetZoomDelta() const
1498  {
1499  return m_fZoomDelta;
1500  }
1501 
1502  void SetZoomMode(int nZoomMode)
1503  {
1504  m_nZoomMode = nZoomMode;
1505  }
1506 
1507  int GetZoomMode() const
1508  {
1509  return m_nZoomMode;
1510  }
1511 
1512  void SetZoomChildren(bool bEnable = true)
1513  {
1514  T* pT = static_cast<T*>(this);
1515  ATLASSERT(::IsWindow(pT->m_hWnd));
1516 
1517  m_bZoomChildren = bEnable;
1518 
1519  m_arrChildren.RemoveAll();
1520  if(m_bZoomChildren)
1521  {
1522  for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
1523  {
1524  RECT rect = { 0 };
1525  ::GetWindowRect(hWndChild, &rect);
1526  ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
1527 
1528  _ChildPlacement cp = { 0 };
1529  cp.hWnd = hWndChild;
1530  cp.x = rect.left;
1531  cp.y = rect.top;
1532  cp.cx = rect.right - rect.left;
1533  cp.cy = rect.bottom - rect.top;
1534  m_arrChildren.Add(cp);
1535  }
1536  }
1537  }
1538 
1539  bool GetZoomChildren() const
1540  {
1541  return m_bZoomChildren;
1542  }
1543 
1544  void Zoom(int x, int y, float fZoomScale)
1545  {
1546  if(fZoomScale <= 0.0f)
1547  return;
1548 
1549  if(fZoomScale < m_fZoomScaleMin)
1550  fZoomScale = m_fZoomScaleMin;
1551  else if(fZoomScale > m_fZoomScaleMax)
1552  fZoomScale = m_fZoomScaleMax;
1553 
1554  T* pT = static_cast<T*>(this);
1555  POINT pt = { x, y };
1556  if(!pT->PtInDevRect(pt))
1557  return;
1558 
1559  pT->ViewDPtoLP(&pt);
1560  pT->Zoom(fZoomScale, false);
1561  pT->CenterOnLogicalPoint(pt);
1562  }
1563 
1564  void Zoom(POINT pt, float fZoomScale)
1565  {
1566  T* pT = static_cast<T*>(this);
1567  pT->Zoom(pt.x, pt.y, fZoomScale);
1568  }
1569 
1570  void Zoom(RECT& rc)
1571  {
1572  T* pT = static_cast<T*>(this);
1573  RECT rcZoom = rc;
1574  pT->NormalizeRect(rcZoom);
1575  SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top };
1576  POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 };
1577  if(size.cx < m_cxyMinZoomRect || size.cy < m_cxyMinZoomRect)
1578  {
1579  pT->Zoom(pt, m_fZoomScale + m_fZoomDelta);
1580  return;
1581  }
1582 
1583  ATLASSERT((size.cx > 0) && (size.cy > 0));
1584 
1585  float fScaleH = (float)(m_sizeClient.cx + 1) / (float)size.cx;
1586  float fScaleV = (float)(m_sizeClient.cy + 1) / (float)size.cy;
1587  float fZoomScale = __min(fScaleH, fScaleV) * m_fZoomScale;
1588  pT->Zoom(pt, fZoomScale);
1589  }
1590 
1591  void Zoom(float fZoomScale, bool bCenter = true)
1592  {
1593  if(fZoomScale <= 0.0f)
1594  return;
1595 
1596  if(fZoomScale < m_fZoomScaleMin)
1597  fZoomScale = m_fZoomScaleMin;
1598  else if(fZoomScale > m_fZoomScaleMax)
1599  fZoomScale = m_fZoomScaleMax;
1600 
1601  T* pT = static_cast<T*>(this);
1602  POINT pt = { 0 };
1603  if(bCenter)
1604  {
1605  RECT rcClient = { 0 };
1606  ::GetClientRect(pT->m_hWnd, &rcClient);
1607  pt.x = rcClient.right / 2;
1608  pt.y = rcClient.bottom / 2;
1609  pT->ViewDPtoLP(&pt);
1610  }
1611 
1612  // Modify the Viewport extent
1613  SIZE sizeAll = { 0 };
1614  sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale);
1615  sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale);
1616 
1617  // Update scroll bars and window
1619 
1620  // Zoom all children if needed
1621  if(m_bZoomChildren && (m_fZoomScale != fZoomScale))
1622  {
1623  for(int i = 0; i < m_arrChildren.GetSize(); i++)
1624  {
1625  ATLASSERT(::IsWindow(m_arrChildren[i].hWnd));
1626 
1627  ::SetWindowPos(m_arrChildren[i].hWnd, NULL,
1628  (int)((float)m_arrChildren[i].x * fZoomScale + 0.5f),
1629  (int)((float)m_arrChildren[i].y * fZoomScale + 0.5f),
1630  (int)((float)m_arrChildren[i].cx * fZoomScale + 0.5f),
1631  (int)((float)m_arrChildren[i].cy * fZoomScale + 0.5f),
1632  SWP_NOZORDER | SWP_NOACTIVATE);
1633  }
1634  }
1635 
1636  // Set new zoom scale
1637  m_fZoomScale = fZoomScale;
1638 
1639  if(bCenter)
1640  pT->CenterOnLogicalPoint(pt);
1641  }
1642 
1643  // Helper functions
1644  void PrepareDC(CDCHandle dc)
1645  {
1646  ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
1647  dc.SetMapMode(MM_ANISOTROPIC);
1648  dc.SetWindowExt(m_sizeLogAll);
1649  dc.SetViewportExt(m_sizeAll);
1650  dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
1651  }
1652 
1653  void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1)
1654  {
1655  ATLASSERT(lpPoints);
1656  T* pT = static_cast<T*>(this);
1657  ATLASSERT(::IsWindow(pT->m_hWnd));
1658 
1659  CWindowDC dc(pT->m_hWnd);
1660  pT->PrepareDC(dc.m_hDC);
1661  dc.DPtoLP(lpPoints, nCount);
1662  }
1663 
1664  void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1)
1665  {
1666  ATLASSERT(lpPoints);
1667  T* pT = static_cast<T*>(this);
1668  ATLASSERT(::IsWindow(pT->m_hWnd));
1669 
1670  CWindowDC dc(pT->m_hWnd);
1671  pT->PrepareDC(dc.m_hDC);
1672  dc.LPtoDP(lpPoints, nCount);
1673  }
1674 
1675  void ClientToDevice(POINT &pt)
1676  {
1677  pt.x += m_ptOffset.x;
1678  pt.y += m_ptOffset.y;
1679  }
1680 
1681  void DeviceToClient(POINT &pt)
1682  {
1683  pt.x -= m_ptOffset.x;
1684  pt.y -= m_ptOffset.y;
1685  }
1686 
1687  void CenterOnPoint(POINT pt)
1688  {
1689  T* pT = static_cast<T*>(this);
1690  RECT rect = { 0 };
1691  pT->GetClientRect(&rect);
1692 
1693  int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x;
1694  if(xOfs < 0)
1695  {
1696  xOfs = 0;
1697  }
1698  else
1699  {
1700  int xMax = __max((int)(m_sizeAll.cx - rect.right), 0);
1701  if(xOfs > xMax)
1702  xOfs = xMax;
1703  }
1704 
1705  int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y;
1706  if(yOfs < 0)
1707  {
1708  yOfs = 0;
1709  }
1710  else
1711  {
1712  int yMax = __max((int)(m_sizeAll.cy - rect.bottom), 0);
1713  if(yOfs > yMax)
1714  yOfs = yMax;
1715  }
1716 
1718  }
1719 
1720  void CenterOnLogicalPoint(POINT ptLog)
1721  {
1722  T* pT = static_cast<T*>(this);
1723  pT->ViewLPtoDP(&ptLog);
1724  pT->DeviceToClient(ptLog);
1725  pT->CenterOnPoint(ptLog);
1726  }
1727 
1728  BOOL PtInDevRect(POINT pt)
1729  {
1730  RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy };
1731  ::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y);
1732  return ::PtInRect(&rc, pt);
1733  }
1734 
1735  void NormalizeRect(RECT& rc)
1736  {
1737  if(rc.left > rc.right)
1738  {
1739  int r = rc.right;
1740  rc.right = rc.left;
1741  rc.left = r;
1742  }
1743 
1744  if(rc.top > rc.bottom)
1745  {
1746  int b = rc.bottom;
1747  rc.bottom = rc.top;
1748  rc.top = b;
1749  }
1750  }
1751 
1752  void DrawTrackRect()
1753  {
1754  T* pT = static_cast<T*>(this);
1755  const SIZE sizeLines = { 2, 2 };
1756  RECT rc = m_rcTrack;
1757  pT->NormalizeRect(rc);
1758  if(!::IsRectEmpty(&rc))
1759  {
1760  ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2);
1761  CWindowDC dc(NULL);
1762  dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines);
1763  }
1764  }
1765 
1766  void NotifyParentZoomChanged()
1767  {
1768  T* pT = static_cast<T*>(this);
1769  int nId = pT->GetDlgCtrlID();
1770  NMHDR nmhdr = { pT->m_hWnd, (UINT_PTR)nId, ZSN_ZOOMCHANGED };
1771  ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr);
1772  }
1773 
1774  BEGIN_MSG_MAP(CZoomScrollImpl)
1775  MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
1776  MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1777  MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1778  MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1779 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1780  MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1781 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1782  MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1783  MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1784  MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1785  MESSAGE_HANDLER(WM_PAINT, OnPaint)
1786  MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1787  MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
1788  MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
1789  MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
1790  MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
1791  ALT_MSG_MAP(1)
1792  COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1793  COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1794  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1795  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1796  COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1797  COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1798  COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1799  COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1800  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1801  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1802  COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1803  COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1804  END_MSG_MAP()
1805 
1806  LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1807  {
1808  T* pT = static_cast<T*>(this);
1809  ATLASSERT(::IsWindow(pT->m_hWnd));
1810  ATLASSERT((m_sizeLogAll.cx >= 0) && (m_sizeLogAll.cy >= 0));
1811  ATLASSERT((m_sizeAll.cx >= 0) && (m_sizeAll.cy >= 0));
1812 
1813  if(wParam != NULL)
1814  {
1815  CDCHandle dc = (HDC)wParam;
1816  int nMapModeSav = dc.GetMapMode();
1817  dc.SetMapMode(MM_ANISOTROPIC);
1818  SIZE szWindowExt = { 0, 0 };
1819  dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
1820  SIZE szViewportExt = { 0, 0 };
1821  dc.SetViewportExt(m_sizeAll, &szViewportExt);
1822  POINT ptViewportOrg = { 0, 0 };
1823  dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
1824 
1825  pT->DoPaint(dc);
1826 
1827  dc.SetMapMode(nMapModeSav);
1828  dc.SetWindowExt(szWindowExt);
1829  dc.SetViewportExt(szViewportExt);
1830  dc.SetViewportOrg(ptViewportOrg);
1831  }
1832  else
1833  {
1834  CPaintDC dc(pT->m_hWnd);
1835  pT->PrepareDC(dc.m_hDC);
1836  pT->DoPaint(dc.m_hDC);
1837  }
1838 
1839  return 0;
1840  }
1841 
1842  LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1843  {
1844  if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking)
1845  {
1846  T* pT = static_cast<T*>(this);
1847  POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1848  if(pT->PtInDevRect(pt))
1849  {
1850  pT->SetCapture();
1851  m_bTracking = true;
1852  ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y);
1853  }
1854  }
1855 
1856  bHandled = FALSE;
1857  return 0;
1858  }
1859 
1860  LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1861  {
1862  if(m_bTracking)
1863  {
1864  T* pT = static_cast<T*>(this);
1865  POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1866  if(pT->PtInDevRect(pt))
1867  {
1868  pT->DrawTrackRect();
1869  m_rcTrack.right = pt.x;
1870  m_rcTrack.bottom = pt.y;
1871  pT->DrawTrackRect();
1872  }
1873  }
1874 
1875  bHandled = FALSE;
1876  return 0;
1877  }
1878 
1879  LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1880  {
1881  ::ReleaseCapture();
1882  if(m_nZoomMode == ZOOMMODE_OUT)
1883  {
1884  T* pT = static_cast<T*>(this);
1885  pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta);
1886  pT->NotifyParentZoomChanged();
1887  }
1888 
1889  bHandled = FALSE;
1890  return 0;
1891  }
1892 
1893  LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1894  {
1895  if(m_bTracking)
1896  {
1897  m_bTracking = false;
1898  T* pT = static_cast<T*>(this);
1899  pT->DrawTrackRect();
1900  pT->Zoom(m_rcTrack);
1901  pT->NotifyParentZoomChanged();
1902  ::SetRectEmpty(&m_rcTrack);
1903  }
1904 
1905  bHandled = FALSE;
1906  return 0;
1907  }
1908 
1909  LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1910  {
1911  if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF)
1912  {
1913  T* pT = static_cast<T*>(this);
1914  if((HWND)wParam == pT->m_hWnd)
1915  {
1916  DWORD dwPos = ::GetMessagePos();
1917  POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
1918  pT->ScreenToClient(&pt);
1919  if(pT->PtInDevRect(pt))
1920  {
1921  ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
1922  return 1;
1923  }
1924  }
1925  }
1926 
1927  bHandled = FALSE;
1928  return 0;
1929  }
1930 };
1931 
1933 // CZoomScrollWindowImpl - Implements scrolling window with zooming
1934 
1935 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1936 class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
1937 {
1938 public:
1939  BOOL SubclassWindow(HWND hWnd)
1940  {
1941 #if (_MSC_VER >= 1300)
1942  BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
1943 #else // !(_MSC_VER >= 1300)
1944  typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
1945  BOOL bRet = _baseClass::SubclassWindow(hWnd);
1946 #endif // !(_MSC_VER >= 1300)
1947  if(bRet != FALSE)
1948  {
1949  T* pT = static_cast<T*>(this);
1950  pT->GetSystemSettings();
1951 
1952  RECT rect = { 0 };
1953  GetClientRect(&rect);
1954  pT->DoSize(rect.right, rect.bottom);
1955  }
1956 
1957  return bRet;
1958  }
1959 
1960  BEGIN_MSG_MAP(CZoomScrollWindowImpl)
1961  MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
1962  MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1963  MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1964  MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1965 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1966  MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1967 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1968  MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1969  MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1970  MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1971  MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint)
1972  MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint)
1973  MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
1974  MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
1975  MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
1976  MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
1977  ALT_MSG_MAP(1)
1978  COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1979  COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1980  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1981  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1982  COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1983  COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1984  COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1985  COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1986  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1987  COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1988  COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1989  COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1990  END_MSG_MAP()
1991 };
1992 
1993 #endif // !_WIN32_WCE
1994 
1995 
1997 // CScrollContainer
1998 
1999 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
2000 class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits >
2001 {
2002 public:
2003  DECLARE_WND_CLASS_EX(NULL, 0, -1)
2004 
2006 
2007 // Data members
2008  ATL::CWindow m_wndClient;
2009  bool m_bAutoSizeClient;
2010  bool m_bDrawEdgeIfEmpty;
2011 
2012 // Constructor
2013  CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false)
2014  {
2015  // Set CScrollWindowImpl extended style
2016  SetScrollExtendedStyle(SCRL_SCROLLCHILDREN);
2017  }
2018 
2019 // Attributes
2020  HWND GetClient() const
2021  {
2022  return m_wndClient;
2023  }
2024 
2025  HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true)
2026  {
2027  ATLASSERT(::IsWindow(m_hWnd));
2028 
2029  HWND hWndOldClient = m_wndClient;
2030  m_wndClient = hWndClient;
2031 
2032  SetRedraw(FALSE);
2033  SetScrollSize(1, 1, FALSE);
2034 
2035  if(m_wndClient.m_hWnd != NULL)
2036  {
2037  m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
2038 
2039  if(bClientSizeAsMin)
2040  {
2041  RECT rect = { 0 };
2042  m_wndClient.GetWindowRect(&rect);
2043  if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0)
2044  SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE);
2045  }
2046 
2047  T* pT = static_cast<T*>(this);
2048  pT->UpdateLayout();
2049  }
2050 
2051  SetRedraw(TRUE);
2052  RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
2053 
2054  return hWndOldClient;
2055  }
2056 
2057 // Message map and handlers
2058  BEGIN_MSG_MAP(CScrollContainerImpl)
2059  MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
2060  MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
2061  CHAIN_MSG_MAP(_baseClass)
2062  FORWARD_NOTIFICATIONS()
2063  ALT_MSG_MAP(1)
2064  CHAIN_MSG_MAP_ALT(_baseClass, 1)
2065  END_MSG_MAP()
2066 
2067  LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2068  {
2069  if(m_wndClient.m_hWnd != NULL)
2070  m_wndClient.SetFocus();
2071 
2072  return 0;
2073  }
2074 
2075  LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2076  {
2077  return 1; // no background needed
2078  }
2079 
2080 // Overrides for CScrollWindowImpl
2081  void DoSize(int cx, int cy)
2082  {
2083  _baseClass::DoSize(cx, cy);
2084 
2085  T* pT = static_cast<T*>(this);
2086  pT->UpdateLayout();
2087  }
2088 
2089  void DoPaint(CDCHandle dc)
2090  {
2091  if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL)
2092  {
2093  T* pT = static_cast<T*>(this);
2094  RECT rect = { 0 };
2095  pT->GetContainerRect(rect);
2096 
2097  if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL)
2098  dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
2099 
2100  dc.FillRect(&rect, COLOR_APPWORKSPACE);
2101  }
2102  }
2103 
2104  void ScrollToView(POINT pt)
2105  {
2107  }
2108 
2109  void ScrollToView(RECT& rect)
2110  {
2112  }
2113 
2114  void ScrollToView(HWND hWnd) // client window coordinates
2115  {
2116  T* pT = static_cast<T*>(this);
2117  pT; // avoid level 4 warning
2118  ATLASSERT(::IsWindow(pT->m_hWnd));
2119  ATLASSERT(m_wndClient.IsWindow());
2120 
2121  RECT rect = { 0 };
2122  ::GetWindowRect(hWnd, &rect);
2123  ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2);
2124  ScrollToView(rect);
2125  }
2126 
2127 // Implementation - overrideable methods
2128  void UpdateLayout()
2129  {
2130  ATLASSERT(::IsWindow(m_hWnd));
2131 
2132  if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL)
2133  {
2134  T* pT = static_cast<T*>(this);
2135  RECT rect = { 0 };
2136  pT->GetContainerRect(rect);
2137 
2138  m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
2139  }
2140  else
2141  {
2142  Invalidate();
2143  }
2144  }
2145 
2146  void GetContainerRect(RECT& rect)
2147  {
2148  GetClientRect(&rect);
2149 
2150  if(rect.right < m_sizeAll.cx)
2151  rect.right = m_sizeAll.cx;
2152 
2153  if(rect.bottom < m_sizeAll.cy)
2154  rect.bottom = m_sizeAll.cy;
2155  }
2156 };
2157 
2158 class CScrollContainer : public CScrollContainerImpl<CScrollContainer>
2159 {
2160 public:
2161  DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1)
2162 };
2163 
2164 }; // namespace WTL
2165 
2166 #endif // __ATLSCRL_H__
Definition: atlscrl.h:2000
Definition: atlscrl.h:1203
Definition: atlscrl.h:2158
Definition: atlscrl.h:965
Definition: atlapp.h:553
Definition: atlscrl.h:1320
Definition: atlscrl.h:63
Definition: atlgdi.h:1209
Definition: atlgdi.h:3362
Definition: atlgdi.h:3407
Definition: atlscrl.h:1325
Definition: atlscrl.h:1936
Definition: atlscrl.h:904