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