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