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