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