123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127 |
- // Windows Template Library - WTL version 10.0
- // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
- //
- // This file is a part of the Windows Template Library.
- // The use and distribution terms for this software are covered by the
- // Microsoft Public License (http://opensource.org/licenses/MS-PL)
- // which can be found in the file MS-PL.txt at the root folder.
- #ifndef __ATLSCRL_H__
- #define __ATLSCRL_H__
- #pragma once
- #ifndef __ATLAPP_H__
- #error atlscrl.h requires atlapp.h to be included first
- #endif
- #ifndef __ATLWIN_H__
- #error atlscrl.h requires atlwin.h to be included first
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // Classes in this file:
- //
- // CScrollImpl<T>
- // CScrollWindowImpl<T, TBase, TWinTraits>
- // CMapScrollImpl<T>
- // CMapScrollWindowImpl<T, TBase, TWinTraits>
- // CFSBWindowT<TBase>
- // CZoomScrollImpl<T>
- // CZoomScrollWindowImpl<T, TBase, TWinTraits>
- // CScrollContainerImpl<T, TBase, TWinTraits>
- // CScrollContainer
- namespace WTL
- {
- ///////////////////////////////////////////////////////////////////////////////
- // CScrollImpl - Provides scrolling support to any window
- // Scroll extended styles
- #define SCRL_SCROLLCHILDREN 0x00000001
- #define SCRL_ERASEBACKGROUND 0x00000002
- #define SCRL_NOTHUMBTRACKING 0x00000004
- #define SCRL_SMOOTHSCROLL 0x00000008
- #define SCRL_DISABLENOSCROLLV 0x00000010
- #define SCRL_DISABLENOSCROLLH 0x00000020
- #define SCRL_DISABLENOSCROLL (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH)
- template <class T>
- class CScrollImpl
- {
- public:
- enum { uSCROLL_FLAGS = SW_INVALIDATE };
- POINT m_ptOffset;
- SIZE m_sizeAll;
- SIZE m_sizeLine;
- SIZE m_sizePage;
- SIZE m_sizeClient;
- int m_zDelta; // current wheel value
- int m_nWheelLines; // number of lines to scroll on wheel
- int m_zHDelta; // current horizontal wheel value
- int m_nHWheelChars; // number of chars to scroll on horizontal wheel
- UINT m_uScrollFlags;
- DWORD m_dwExtendedStyle; // scroll specific extended styles
- // Constructor
- CScrollImpl() : m_zDelta(0), m_nWheelLines(3),
- m_zHDelta(0), m_nHWheelChars(3),
- m_uScrollFlags(0U), m_dwExtendedStyle(0)
- {
- m_ptOffset.x = 0;
- m_ptOffset.y = 0;
- m_sizeAll.cx = 0;
- m_sizeAll.cy = 0;
- m_sizePage.cx = 0;
- m_sizePage.cy = 0;
- m_sizeLine.cx = 0;
- m_sizeLine.cy = 0;
- m_sizeClient.cx = 0;
- m_sizeClient.cy = 0;
- SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND);
- }
- // Attributes & Operations
- DWORD GetScrollExtendedStyle() const
- {
- return m_dwExtendedStyle;
- }
- DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
- {
- DWORD dwPrevStyle = m_dwExtendedStyle;
- if(dwMask == 0)
- m_dwExtendedStyle = dwExtendedStyle;
- else
- m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
- // cache scroll flags
- T* pT = static_cast<T*>(this);
- (void)pT; // avoid level 4 warning
- m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0);
- m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0);
- return dwPrevStyle;
- }
- // offset operations
- void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->AdjustScrollOffset(x, y);
- int dx = m_ptOffset.x - x;
- int dy = m_ptOffset.y - y;
- m_ptOffset.x = x;
- m_ptOffset.y = y;
- // block: set horizontal scroll bar
- {
- SCROLLINFO si = { sizeof(SCROLLINFO) };
- si.fMask = SIF_POS;
- if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
- si.fMask |= SIF_DISABLENOSCROLL;
- si.nPos = m_ptOffset.x;
- pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
- }
- // block: set vertical scroll bar
- {
- SCROLLINFO si = { sizeof(SCROLLINFO) };
- si.fMask = SIF_POS;
- if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
- si.fMask |= SIF_DISABLENOSCROLL;
- si.nPos = m_ptOffset.y;
- pT->SetScrollInfo(SB_VERT, &si, bRedraw);
- }
- // Move all children if needed
- if(IsScrollingChildren() && ((dx != 0) || (dy != 0)))
- {
- for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
- {
- RECT rect = {};
- ::GetWindowRect(hWndChild, &rect);
- ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
- ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
- }
- }
- if(bRedraw)
- pT->Invalidate();
- }
- void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
- {
- SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
- }
- void GetScrollOffset(POINT& ptOffset) const
- {
- ptOffset = m_ptOffset;
- }
- // size operations
- void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- m_sizeAll.cx = cx;
- m_sizeAll.cy = cy;
- int x = 0;
- int y = 0;
- if(!bResetOffset)
- {
- x = m_ptOffset.x;
- y = m_ptOffset.y;
- pT->AdjustScrollOffset(x, y);
- }
- int dx = m_ptOffset.x - x;
- int dy = m_ptOffset.y - y;
- m_ptOffset.x = x;
- m_ptOffset.y = y;
- // block: set horizontal scroll bar
- {
- SCROLLINFO si = { sizeof(SCROLLINFO) };
- si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
- if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
- si.fMask |= SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = m_sizeAll.cx - 1;
- si.nPage = m_sizeClient.cx;
- si.nPos = m_ptOffset.x;
- pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
- }
- // block: set vertical scroll bar
- {
- SCROLLINFO si = { sizeof(SCROLLINFO) };
- si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
- if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
- si.fMask |= SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = m_sizeAll.cy - 1;
- si.nPage = m_sizeClient.cy;
- si.nPos = m_ptOffset.y;
- pT->SetScrollInfo(SB_VERT, &si, bRedraw);
- }
- // Move all children if needed
- if(IsScrollingChildren() && ((dx != 0) || (dy != 0)))
- {
- for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
- {
- RECT rect = {};
- ::GetWindowRect(hWndChild, &rect);
- ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
- ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
- }
- }
- SetScrollLine(0, 0);
- SetScrollPage(0, 0);
- if(bRedraw)
- pT->Invalidate();
- }
- void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
- {
- SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset);
- }
- void GetScrollSize(SIZE& sizeWnd) const
- {
- sizeWnd = m_sizeAll;
- }
- // line operations
- void SetScrollLine(int cxLine, int cyLine)
- {
- ATLASSERT((cxLine >= 0) && (cyLine >= 0));
- ATLASSERT((m_sizeAll.cx != 0) && (m_sizeAll.cy != 0));
- m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100);
- m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100);
- }
- void SetScrollLine(SIZE sizeLine)
- {
- SetScrollLine(sizeLine.cx, sizeLine.cy);
- }
- void GetScrollLine(SIZE& sizeLine) const
- {
- sizeLine = m_sizeLine;
- }
- // page operations
- void SetScrollPage(int cxPage, int cyPage)
- {
- ATLASSERT((cxPage >= 0) && (cyPage >= 0));
- ATLASSERT((m_sizeAll.cx != 0) && (m_sizeAll.cy != 0));
- m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10);
- m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10);
- }
- void SetScrollPage(SIZE sizePage)
- {
- SetScrollPage(sizePage.cx, sizePage.cy);
- }
- void GetScrollPage(SIZE& sizePage) const
- {
- sizePage = m_sizePage;
- }
- // commands
- void ScrollLineDown()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
- }
- void ScrollLineUp()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
- }
- void ScrollPageDown()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
- }
- void ScrollPageUp()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
- }
- void ScrollTop()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
- }
- void ScrollBottom()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
- }
- void ScrollLineRight()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- }
- void ScrollLineLeft()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- }
- void ScrollPageRight()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- }
- void ScrollPageLeft()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- }
- void ScrollAllLeft()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- }
- void ScrollAllRight()
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- }
- // scroll to make point/view/window visible
- void ScrollToView(POINT pt)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- RECT rect = { pt.x, pt.y, pt.x, pt.y };
- pT->ScrollToView(rect);
- }
- void ScrollToView(RECT& rect)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- RECT rcClient = {};
- pT->GetClientRect(&rcClient);
- int x = m_ptOffset.x;
- if(rect.left < m_ptOffset.x)
- x = rect.left;
- else if(rect.right > (m_ptOffset.x + rcClient.right))
- x = rect.right - rcClient.right;
- int y = m_ptOffset.y;
- if(rect.top < m_ptOffset.y)
- y = rect.top;
- else if(rect.bottom > (m_ptOffset.y + rcClient.bottom))
- y = rect.bottom - rcClient.bottom;
- SetScrollOffset(x, y);
- }
- void ScrollToView(HWND hWnd)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- RECT rect = {};
- ::GetWindowRect(hWnd, &rect);
- ::OffsetRect(&rect, m_ptOffset.x, m_ptOffset.y);
- ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
- ScrollToView(rect);
- }
- BEGIN_MSG_MAP(CScrollImpl)
- MESSAGE_HANDLER(WM_CREATE, OnCreate)
- MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
- MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
- MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
- MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel)
- MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
- MESSAGE_HANDLER(WM_SIZE, OnSize)
- MESSAGE_HANDLER(WM_PAINT, OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
- // standard scroll commands
- ALT_MSG_MAP(1)
- COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp)
- COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown)
- COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop)
- COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom)
- COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight)
- END_MSG_MAP()
- LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- T* pT = static_cast<T*>(this);
- pT->GetSystemSettings();
- bHandled = FALSE;
- return 1;
- }
- LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
- return 0;
- }
- LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- return 0;
- }
- LRESULT OnMouseWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
- int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN);
- m_zDelta += zDelta; // cumulative
- int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines;
- if(m_sizeAll.cy > m_sizeClient.cy)
- {
- for(int i = 0; i < zTotal; i += WHEEL_DELTA)
- {
- pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
- pT->UpdateWindow();
- }
- }
- else if(m_sizeAll.cx > m_sizeClient.cx) // can't scroll vertically, scroll horizontally
- {
- for(int i = 0; i < zTotal; i += WHEEL_DELTA)
- {
- pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- pT->UpdateWindow();
- }
- }
- m_zDelta %= WHEEL_DELTA;
- return 0;
- }
- LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
- int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT);
- m_zHDelta += zDelta; // cumulative
- int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars;
- if(m_sizeAll.cx > m_sizeClient.cx)
- {
- for(int i = 0; i < zTotal; i += WHEEL_DELTA)
- {
- pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
- pT->UpdateWindow();
- }
- }
- m_zHDelta %= WHEEL_DELTA;
- return 0;
- }
- LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- GetSystemSettings();
- return 0;
- }
- LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- pT->DoSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- bHandled = FALSE;
- return 1;
- }
- LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- if(wParam != NULL)
- {
- CDCHandle dc = (HDC)wParam;
- POINT ptViewportOrg = { 0, 0 };
- dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
- pT->DoPaint(dc);
- dc.SetViewportOrg(ptViewportOrg);
- }
- else
- {
- CPaintDC dc(pT->m_hWnd);
- dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
- pT->DoPaint(dc.m_hDC);
- }
- return 0;
- }
- // scrolling handlers
- LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollLineUp();
- return 0;
- }
- LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollLineDown();
- return 0;
- }
- LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollPageUp();
- return 0;
- }
- LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollPageDown();
- return 0;
- }
- LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollTop();
- return 0;
- }
- LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollBottom();
- return 0;
- }
- LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollLineLeft();
- return 0;
- }
- LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollLineRight();
- return 0;
- }
- LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollPageLeft();
- return 0;
- }
- LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollPageRight();
- return 0;
- }
- LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollAllLeft();
- return 0;
- }
- LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ScrollAllRight();
- return 0;
- }
- // Overrideables
- void DoPaint(CDCHandle /*dc*/)
- {
- // must be implemented in a derived class
- ATLASSERT(FALSE);
- }
- // Implementation
- void DoSize(int cx, int cy)
- {
- m_sizeClient.cx = cx;
- m_sizeClient.cy = cy;
- T* pT = static_cast<T*>(this);
- // block: set horizontal scroll bar
- {
- SCROLLINFO si = { sizeof(SCROLLINFO) };
- si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
- si.nMin = 0;
- si.nMax = m_sizeAll.cx - 1;
- if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
- si.fMask |= SIF_DISABLENOSCROLL;
- si.nPage = m_sizeClient.cx;
- si.nPos = m_ptOffset.x;
- pT->SetScrollInfo(SB_HORZ, &si, TRUE);
- }
- // block: set vertical scroll bar
- {
- SCROLLINFO si = { sizeof(SCROLLINFO) };
- si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
- si.nMin = 0;
- si.nMax = m_sizeAll.cy - 1;
- if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
- si.fMask |= SIF_DISABLENOSCROLL;
- si.nPage = m_sizeClient.cy;
- si.nPos = m_ptOffset.y;
- pT->SetScrollInfo(SB_VERT, &si, TRUE);
- }
- int x = m_ptOffset.x;
- int y = m_ptOffset.y;
- if(pT->AdjustScrollOffset(x, y))
- {
- // Children will be moved in SetScrollOffset, if needed
- pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN));
- SetScrollOffset(x, y, FALSE);
- }
- }
- void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine)
- {
- T* pT = static_cast<T*>(this);
- RECT rect = {};
- pT->GetClientRect(&rect);
- int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right;
- int cxyMax = cxySizeAll - cxyClient;
- if(cxyMax < 0) // can't scroll, client area is bigger
- return;
- bool bUpdate = true;
- int cxyScroll = 0;
- switch(nScrollCode)
- {
- case SB_TOP: // top or all left
- cxyScroll = cxyOffset;
- cxyOffset = 0;
- break;
- case SB_BOTTOM: // bottom or all right
- cxyScroll = cxyOffset - cxyMax;
- cxyOffset = cxyMax;
- break;
- case SB_LINEUP: // line up or line left
- if(cxyOffset >= cxySizeLine)
- {
- cxyScroll = cxySizeLine;
- cxyOffset -= cxySizeLine;
- }
- else
- {
- cxyScroll = cxyOffset;
- cxyOffset = 0;
- }
- break;
- case SB_LINEDOWN: // line down or line right
- if(cxyOffset < cxyMax - cxySizeLine)
- {
- cxyScroll = -cxySizeLine;
- cxyOffset += cxySizeLine;
- }
- else
- {
- cxyScroll = cxyOffset - cxyMax;
- cxyOffset = cxyMax;
- }
- break;
- case SB_PAGEUP: // page up or page left
- if(cxyOffset >= cxySizePage)
- {
- cxyScroll = cxySizePage;
- cxyOffset -= cxySizePage;
- }
- else
- {
- cxyScroll = cxyOffset;
- cxyOffset = 0;
- }
- break;
- case SB_PAGEDOWN: // page down or page right
- if(cxyOffset < cxyMax - cxySizePage)
- {
- cxyScroll = -cxySizePage;
- cxyOffset += cxySizePage;
- }
- else
- {
- cxyScroll = cxyOffset - cxyMax;
- cxyOffset = cxyMax;
- }
- break;
- case SB_THUMBTRACK:
- if(IsNoThumbTracking())
- break;
- // else fall through
- case SB_THUMBPOSITION:
- {
- SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS };
- if(pT->GetScrollInfo(nType, &si))
- {
- cxyScroll = cxyOffset - si.nTrackPos;
- cxyOffset = si.nTrackPos;
- }
- }
- break;
- case SB_ENDSCROLL:
- default:
- bUpdate = false;
- break;
- }
- if(bUpdate && (cxyScroll != 0))
- {
- pT->SetScrollPos(nType, cxyOffset, TRUE);
- if(nType == SB_VERT)
- pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags);
- else
- pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags);
- }
- }
- static int CalcLineOrPage(int nVal, int nMax, int nDiv)
- {
- if(nVal == 0)
- {
- nVal = nMax / nDiv;
- if(nVal < 1)
- nVal = 1;
- }
- else if(nVal > nMax)
- {
- nVal = nMax;
- }
- return nVal;
- }
- bool AdjustScrollOffset(int& x, int& y)
- {
- int xOld = x;
- int yOld = y;
- int cxMax = m_sizeAll.cx - m_sizeClient.cx;
- if(x > cxMax)
- x = (cxMax >= 0) ? cxMax : 0;
- else if(x < 0)
- x = 0;
- int cyMax = m_sizeAll.cy - m_sizeClient.cy;
- if(y > cyMax)
- y = (cyMax >= 0) ? cyMax : 0;
- else if(y < 0)
- y = 0;
- return ((x != xOld) || (y != yOld));
- }
- void GetSystemSettings()
- {
- ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0);
- #ifndef SPI_GETWHEELSCROLLCHARS
- const UINT SPI_GETWHEELSCROLLCHARS = 0x006C;
- #endif
- ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0);
- }
- bool IsScrollingChildren() const
- {
- return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0;
- }
- bool IsErasingBackground() const
- {
- return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0;
- }
- bool IsNoThumbTracking() const
- {
- return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0;
- }
- bool IsSmoothScroll() const
- {
- return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0;
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CScrollWindowImpl - Implements a scrollable window
- template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
- class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CScrollImpl< T >
- {
- public:
- BOOL SubclassWindow(HWND hWnd)
- {
- BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
- if(bRet != FALSE)
- {
- T* pT = static_cast<T*>(this);
- pT->GetSystemSettings();
- RECT rect = {};
- this->GetClientRect(&rect);
- pT->DoSize(rect.right, rect.bottom);
- }
- return bRet;
- }
- BEGIN_MSG_MAP(CScrollWindowImpl)
- MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
- MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
- MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
- MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
- MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
- MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
- MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint)
- ALT_MSG_MAP(1)
- COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
- COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
- COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
- COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
- COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
- END_MSG_MAP()
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CMapScrollImpl - Provides mapping and scrolling support to any window
- template <class T>
- class CMapScrollImpl : public CScrollImpl< T >
- {
- public:
- int m_nMapMode;
- RECT m_rectLogAll;
- SIZE m_sizeLogLine;
- SIZE m_sizeLogPage;
- // Constructor
- CMapScrollImpl() : m_nMapMode(MM_TEXT)
- {
- ::SetRectEmpty(&m_rectLogAll);
- m_sizeLogPage.cx = 0;
- m_sizeLogPage.cy = 0;
- m_sizeLogLine.cx = 0;
- m_sizeLogLine.cy = 0;
- }
- // Attributes & Operations
- // mapping mode operations
- void SetScrollMapMode(int nMapMode)
- {
- ATLASSERT((nMapMode >= MM_MIN) && (nMapMode <= MM_MAX_FIXEDSCALE));
- m_nMapMode = nMapMode;
- }
- int GetScrollMapMode() const
- {
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- return m_nMapMode;
- }
- // offset operations
- void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
- {
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- POINT ptOff = { x, y };
- // block: convert logical to device units
- {
- CWindowDC dc(NULL);
- dc.SetMapMode(m_nMapMode);
- dc.LPtoDP(&ptOff);
- }
- CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw);
- }
- void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
- {
- SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
- }
- void GetScrollOffset(POINT& ptOffset) const
- {
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- ptOffset = this->m_ptOffset;
- // block: convert device to logical units
- {
- CWindowDC dc(NULL);
- dc.SetMapMode(m_nMapMode);
- dc.DPtoLP(&ptOffset);
- }
- }
- // size operations
- void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true)
- {
- ATLASSERT((xMax > xMin) && (yMax > yMin));
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax);
- SIZE sizeAll = {};
- sizeAll.cx = xMax - xMin + 1;
- sizeAll.cy = yMax - yMin + 1;
- // block: convert logical to device units
- {
- CWindowDC dc(NULL);
- dc.SetMapMode(m_nMapMode);
- dc.LPtoDP(&sizeAll);
- }
- CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
- SetScrollLine(0, 0);
- SetScrollPage(0, 0);
- }
- void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true)
- {
- SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset);
- }
- void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
- {
- SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset);
- }
- void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
- {
- SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset);
- }
- void GetScrollSize(RECT& rcScroll) const
- {
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- rcScroll = m_rectLogAll;
- }
- // line operations
- void SetScrollLine(int cxLine, int cyLine)
- {
- ATLASSERT((cxLine >= 0) && (cyLine >= 0));
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- m_sizeLogLine.cx = cxLine;
- m_sizeLogLine.cy = cyLine;
- SIZE sizeLine = m_sizeLogLine;
- // block: convert logical to device units
- {
- CWindowDC dc(NULL);
- dc.SetMapMode(m_nMapMode);
- dc.LPtoDP(&sizeLine);
- }
- CScrollImpl< T >::SetScrollLine(sizeLine);
- }
- void SetScrollLine(SIZE sizeLine)
- {
- SetScrollLine(sizeLine.cx, sizeLine.cy);
- }
- void GetScrollLine(SIZE& sizeLine) const
- {
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- sizeLine = m_sizeLogLine;
- }
- // page operations
- void SetScrollPage(int cxPage, int cyPage)
- {
- ATLASSERT((cxPage >= 0) && (cyPage >= 0));
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- m_sizeLogPage.cx = cxPage;
- m_sizeLogPage.cy = cyPage;
- SIZE sizePage = m_sizeLogPage;
- // block: convert logical to device units
- {
- CWindowDC dc(NULL);
- dc.SetMapMode(m_nMapMode);
- dc.LPtoDP(&sizePage);
- }
- CScrollImpl< T >::SetScrollPage(sizePage);
- }
- void SetScrollPage(SIZE sizePage)
- {
- SetScrollPage(sizePage.cx, sizePage.cy);
- }
- void GetScrollPage(SIZE& sizePage) const
- {
- ATLASSERT((m_nMapMode >= MM_MIN) && (m_nMapMode <= MM_MAX_FIXEDSCALE));
- sizePage = m_sizeLogPage;
- }
- BEGIN_MSG_MAP(CMapScrollImpl)
- MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
- MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
- MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
- MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
- MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
- MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
- MESSAGE_HANDLER(WM_PAINT, OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
- ALT_MSG_MAP(1)
- COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
- COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
- COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
- COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
- COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
- END_MSG_MAP()
- LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- if(wParam != NULL)
- {
- CDCHandle dc = (HDC)wParam;
- int nMapModeSav = dc.GetMapMode();
- dc.SetMapMode(m_nMapMode);
- POINT ptViewportOrg = { 0, 0 };
- if(m_nMapMode == MM_TEXT)
- dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y, &ptViewportOrg);
- else
- dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y + this->m_sizeAll.cy, &ptViewportOrg);
- POINT ptWindowOrg = { 0, 0 };
- dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg);
- pT->DoPaint(dc);
- dc.SetMapMode(nMapModeSav);
- dc.SetViewportOrg(ptViewportOrg);
- dc.SetWindowOrg(ptWindowOrg);
- }
- else
- {
- CPaintDC dc(pT->m_hWnd);
- dc.SetMapMode(m_nMapMode);
- if(m_nMapMode == MM_TEXT)
- dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y);
- else
- dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y + this->m_sizeAll.cy);
- dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top);
- pT->DoPaint(dc.m_hDC);
- }
- return 0;
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CMapScrollWindowImpl - Implements scrolling window with mapping
- template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
- class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T >
- {
- public:
- BOOL SubclassWindow(HWND hWnd)
- {
- BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
- if(bRet != FALSE)
- {
- T* pT = static_cast<T*>(this);
- pT->GetSystemSettings();
- RECT rect = {};
- this->GetClientRect(&rect);
- pT->DoSize(rect.right, rect.bottom);
- }
- return bRet;
- }
- BEGIN_MSG_MAP(CMapScrollWindowImpl)
- MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
- MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
- MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
- MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
- MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
- MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
- MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint)
- ALT_MSG_MAP(1)
- COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
- COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
- COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
- COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
- COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
- END_MSG_MAP()
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support
- #ifdef __ATLCTRLS_H__
- template <class TBase = ATL::CWindow>
- class CFSBWindowT : public TBase, public CFlatScrollBarImpl<CFSBWindowT< TBase > >
- {
- public:
- // Constructors
- CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd)
- { }
- CFSBWindowT< TBase >& operator =(HWND hWnd)
- {
- this->m_hWnd = hWnd;
- return *this;
- }
- // CWindow overrides that use flat scroll bar API
- // (only those methods that are used by scroll window classes)
- int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
- {
- ATLASSERT(::IsWindow(this->m_hWnd));
- return this->FlatSB_SetScrollPos(nBar, nPos, bRedraw);
- }
- BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
- {
- ATLASSERT(::IsWindow(this->m_hWnd));
- return this->FlatSB_GetScrollInfo(nBar, lpScrollInfo);
- }
- BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
- {
- ATLASSERT(::IsWindow(this->m_hWnd));
- return this->FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw);
- }
- };
- typedef CFSBWindowT<ATL::CWindow> CFSBWindow;
- #endif // __ATLCTRLS_H__
- ///////////////////////////////////////////////////////////////////////////////
- // CZoomScrollImpl - Provides zooming and scrolling support to any window
- // The zoom modes that can be set with the SetZoomMode method
- enum
- {
- ZOOMMODE_OFF,
- ZOOMMODE_IN, // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged.
- ZOOMMODE_OUT // If left mouse button clicked, zoom out on point clicked.
- };
- // Notification to parent that zoom scale changed as a result of user mouse action.
- #define ZSN_ZOOMCHANGED (NM_FIRST - 50)
- template <class T>
- class CZoomScrollImpl : public CScrollImpl< T >
- {
- public:
- enum { m_cxyMinZoomRect = 12 }; // min rect size to zoom in on rect.
- struct _ChildPlacement
- {
- HWND hWnd;
- int x;
- int y;
- int cx;
- int cy;
- bool operator ==(const _ChildPlacement& cp) const { return (memcmp(this, &cp, sizeof(_ChildPlacement)) == 0); }
- };
- // Data members
- SIZE m_sizeLogAll;
- SIZE m_sizeLogLine;
- SIZE m_sizeLogPage;
- float m_fZoomScale;
- float m_fZoomScaleMin;
- float m_fZoomScaleMax;
- float m_fZoomDelta; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click.
- int m_nZoomMode;
- RECT m_rcTrack;
- bool m_bTracking;
- bool m_bZoomChildren;
- ATL::CSimpleArray<_ChildPlacement> m_arrChildren;
- // Constructor
- CZoomScrollImpl(): m_fZoomScale(1.0f), m_fZoomScaleMin(0.1f), m_fZoomScaleMax(100.0f), m_fZoomDelta(0.5f),
- m_nZoomMode(ZOOMMODE_OFF), m_bTracking(false), m_bZoomChildren(false)
- {
- m_sizeLogAll.cx = 0;
- m_sizeLogAll.cy = 0;
- m_sizeLogPage.cx = 0;
- m_sizeLogPage.cy = 0;
- m_sizeLogLine.cx = 0;
- m_sizeLogLine.cy = 0;
- ::SetRectEmpty(&m_rcTrack);
- }
- // Attributes & Operations
- // size operations
- void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
- {
- ATLASSERT((cxLog >= 0) && (cyLog >= 0));
- // Set up the defaults
- if((cxLog == 0) && (cyLog == 0))
- {
- cxLog = 1;
- cyLog = 1;
- }
- m_sizeLogAll.cx = cxLog;
- m_sizeLogAll.cy = cyLog;
- SIZE sizeAll = {};
- sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale);
- sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale);
- CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
- }
- void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
- {
- SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset);
- }
- void GetScrollSize(SIZE& sizeLog) const
- {
- sizeLog = m_sizeLogAll;
- }
- // line operations
- void SetScrollLine(int cxLogLine, int cyLogLine)
- {
- ATLASSERT((cxLogLine >= 0) && (cyLogLine >= 0));
- m_sizeLogLine.cx = cxLogLine;
- m_sizeLogLine.cy = cyLogLine;
- SIZE sizeLine = {};
- sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale);
- sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale);
- CScrollImpl< T >::SetScrollLine(sizeLine);
- }
- void SetScrollLine(SIZE sizeLogLine)
- {
- SetScrollLine(sizeLogLine.cx, sizeLogLine.cy);
- }
- void GetScrollLine(SIZE& sizeLogLine) const
- {
- sizeLogLine = m_sizeLogLine;
- }
- // page operations
- void SetScrollPage(int cxLogPage, int cyLogPage)
- {
- ATLASSERT((cxLogPage >= 0) && (cyLogPage >= 0));
- m_sizeLogPage.cx = cxLogPage;
- m_sizeLogPage.cy = cyLogPage;
- SIZE sizePage = {};
- sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale);
- sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale);
- CScrollImpl< T >::SetScrollPage(sizePage);
- }
- void SetScrollPage(SIZE sizeLogPage)
- {
- SetScrollPage(sizeLogPage.cx, sizeLogPage.cy);
- }
- void GetScrollPage(SIZE& sizeLogPage) const
- {
- sizeLogPage = m_sizeLogPage;
- }
- void SetZoomScale(float fZoomScale)
- {
- ATLASSERT(fZoomScale > 0.0f);
- if(fZoomScale <= 0.0f)
- return;
- m_fZoomScale = fZoomScale;
- if(m_fZoomScale < m_fZoomScaleMin)
- m_fZoomScale = m_fZoomScaleMin;
- else if(m_fZoomScale > m_fZoomScaleMax)
- m_fZoomScale = m_fZoomScaleMax;
- }
- float GetZoomScale() const
- {
- return m_fZoomScale;
- }
- void SetZoomScaleMin(float fZoomScaleMin)
- {
- ATLASSERT(fZoomScaleMin > 0.0f);
- ATLASSERT(fZoomScaleMin <= m_fZoomScaleMax);
- m_fZoomScaleMin = fZoomScaleMin;
- }
- float GetZoomScaleMin() const
- {
- return m_fZoomScaleMin;
- }
- void SetZoomScaleMax(float fZoomScaleMax)
- {
- ATLASSERT(fZoomScaleMax > 0.0f);
- ATLASSERT(m_fZoomScaleMin <= fZoomScaleMax);
- m_fZoomScaleMax = fZoomScaleMax;
- }
- float GetZoomScaleMax() const
- {
- return m_fZoomScaleMax;
- }
- void SetZoomDelta(float fZoomDelta)
- {
- ATLASSERT(fZoomDelta >= 0.0f);
- if(fZoomDelta >= 0.0f)
- m_fZoomDelta = fZoomDelta;
- }
- float GetZoomDelta() const
- {
- return m_fZoomDelta;
- }
- void SetZoomMode(int nZoomMode)
- {
- m_nZoomMode = nZoomMode;
- }
- int GetZoomMode() const
- {
- return m_nZoomMode;
- }
- void SetZoomChildren(bool bEnable = true)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- m_bZoomChildren = bEnable;
- m_arrChildren.RemoveAll();
- if(m_bZoomChildren)
- {
- for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
- {
- RECT rect = {};
- ::GetWindowRect(hWndChild, &rect);
- ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
- _ChildPlacement cp = {};
- cp.hWnd = hWndChild;
- cp.x = rect.left;
- cp.y = rect.top;
- cp.cx = rect.right - rect.left;
- cp.cy = rect.bottom - rect.top;
- m_arrChildren.Add(cp);
- }
- }
- }
- bool GetZoomChildren() const
- {
- return m_bZoomChildren;
- }
- void Zoom(int x, int y, float fZoomScale)
- {
- if(fZoomScale <= 0.0f)
- return;
- if(fZoomScale < m_fZoomScaleMin)
- fZoomScale = m_fZoomScaleMin;
- else if(fZoomScale > m_fZoomScaleMax)
- fZoomScale = m_fZoomScaleMax;
- T* pT = static_cast<T*>(this);
- POINT pt = { x, y };
- if(!pT->PtInDevRect(pt))
- return;
- pT->ViewDPtoLP(&pt);
- pT->Zoom(fZoomScale, false);
- pT->CenterOnLogicalPoint(pt);
- }
- void Zoom(POINT pt, float fZoomScale)
- {
- T* pT = static_cast<T*>(this);
- pT->Zoom(pt.x, pt.y, fZoomScale);
- }
- void Zoom(RECT& rc)
- {
- T* pT = static_cast<T*>(this);
- RECT rcZoom = rc;
- pT->NormalizeRect(rcZoom);
- SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top };
- POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 };
- if((size.cx < m_cxyMinZoomRect) || (size.cy < m_cxyMinZoomRect))
- {
- pT->Zoom(pt, m_fZoomScale + m_fZoomDelta);
- return;
- }
- ATLASSERT((size.cx > 0) && (size.cy > 0));
-
- float fScaleH = (float)(this->m_sizeClient.cx + 1) / (float)size.cx;
- float fScaleV = (float)(this->m_sizeClient.cy + 1) / (float)size.cy;
- float fZoomScale = __min(fScaleH, fScaleV) * m_fZoomScale;
- pT->Zoom(pt, fZoomScale);
- }
- void Zoom(float fZoomScale, bool bCenter = true)
- {
- if(fZoomScale <= 0.0f)
- return;
- if(fZoomScale < m_fZoomScaleMin)
- fZoomScale = m_fZoomScaleMin;
- else if(fZoomScale > m_fZoomScaleMax)
- fZoomScale = m_fZoomScaleMax;
- T* pT = static_cast<T*>(this);
- POINT pt = { 0, 0 };
- if(bCenter)
- {
- RECT rcClient = {};
- ::GetClientRect(pT->m_hWnd, &rcClient);
- pt.x = rcClient.right / 2;
- pt.y = rcClient.bottom / 2;
- pT->ViewDPtoLP(&pt);
- }
- // Modify the Viewport extent
- SIZE sizeAll = {};
- sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale);
- sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale);
-
- // Update scroll bars and window
- CScrollImpl< T >::SetScrollSize(sizeAll);
- // Zoom all children if needed
- if(m_bZoomChildren && (m_fZoomScale != fZoomScale))
- {
- for(int i = 0; i < m_arrChildren.GetSize(); i++)
- {
- ATLASSERT(::IsWindow(m_arrChildren[i].hWnd));
- ::SetWindowPos(m_arrChildren[i].hWnd, NULL,
- (int)((float)m_arrChildren[i].x * fZoomScale + 0.5f),
- (int)((float)m_arrChildren[i].y * fZoomScale + 0.5f),
- (int)((float)m_arrChildren[i].cx * fZoomScale + 0.5f),
- (int)((float)m_arrChildren[i].cy * fZoomScale + 0.5f),
- SWP_NOZORDER | SWP_NOACTIVATE);
- }
- }
- // Set new zoom scale
- m_fZoomScale = fZoomScale;
- if(bCenter)
- pT->CenterOnLogicalPoint(pt);
- }
- void ZoomIn(bool bCenter = true)
- {
- T* pT = static_cast<T*>(this);
- pT->Zoom(m_fZoomScale + m_fZoomDelta, bCenter);
- }
- void ZoomOut(bool bCenter = true)
- {
- T* pT = static_cast<T*>(this);
- pT->Zoom(m_fZoomScale - m_fZoomDelta, bCenter);
- }
- void ZoomDefault(bool bCenter = true)
- {
- T* pT = static_cast<T*>(this);
- pT->Zoom(1.0f, bCenter);
- }
- // Helper functions
- void PrepareDC(CDCHandle dc)
- {
- ATLASSERT((this->m_sizeAll.cx >= 0) && (this->m_sizeAll.cy >= 0));
- dc.SetMapMode(MM_ANISOTROPIC);
- dc.SetWindowExt(this->m_sizeLogAll);
- dc.SetViewportExt(this->m_sizeAll);
- dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y);
- }
- void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1)
- {
- ATLASSERT(lpPoints);
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- CWindowDC dc(pT->m_hWnd);
- pT->PrepareDC(dc.m_hDC);
- dc.DPtoLP(lpPoints, nCount);
- }
- void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1)
- {
- ATLASSERT(lpPoints);
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
-
- CWindowDC dc(pT->m_hWnd);
- pT->PrepareDC(dc.m_hDC);
- dc.LPtoDP(lpPoints, nCount);
- }
- void ClientToDevice(POINT &pt)
- {
- pt.x += this->m_ptOffset.x;
- pt.y += this->m_ptOffset.y;
- }
- void DeviceToClient(POINT &pt)
- {
- pt.x -= this->m_ptOffset.x;
- pt.y -= this->m_ptOffset.y;
- }
- void CenterOnPoint(POINT pt)
- {
- T* pT = static_cast<T*>(this);
- RECT rect = {};
- pT->GetClientRect(&rect);
- int xOfs = pt.x - (rect.right / 2) + this->m_ptOffset.x;
- if(xOfs < 0)
- {
- xOfs = 0;
- }
- else
- {
- int xMax = __max((int)(this->m_sizeAll.cx - rect.right), 0);
- if(xOfs > xMax)
- xOfs = xMax;
- }
-
- int yOfs = pt.y - (rect.bottom / 2) + this->m_ptOffset.y;
- if(yOfs < 0)
- {
- yOfs = 0;
- }
- else
- {
- int yMax = __max((int)(this->m_sizeAll.cy - rect.bottom), 0);
- if(yOfs > yMax)
- yOfs = yMax;
- }
- CScrollImpl< T >::SetScrollOffset(xOfs, yOfs);
- }
- void CenterOnLogicalPoint(POINT ptLog)
- {
- T* pT = static_cast<T*>(this);
- pT->ViewLPtoDP(&ptLog);
- pT->DeviceToClient(ptLog);
- pT->CenterOnPoint(ptLog);
- }
- BOOL PtInDevRect(POINT pt)
- {
- RECT rc = { 0, 0, this->m_sizeAll.cx, this->m_sizeAll.cy };
- ::OffsetRect(&rc, -this->m_ptOffset.x, -this->m_ptOffset.y);
- return ::PtInRect(&rc, pt);
- }
- void NormalizeRect(RECT& rc)
- {
- if(rc.left > rc.right)
- {
- int r = rc.right;
- rc.right = rc.left;
- rc.left = r;
- }
- if(rc.top > rc.bottom)
- {
- int b = rc.bottom;
- rc.bottom = rc.top;
- rc.top = b;
- }
- }
- void DrawTrackRect()
- {
- T* pT = static_cast<T*>(this);
- RECT rc = m_rcTrack;
- pT->NormalizeRect(rc);
- if(!::IsRectEmpty(&rc))
- {
- const SIZE sizeLines = { 2, 2 };
- CClientDC dc(pT->m_hWnd);
- dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines);
- }
- }
- void NotifyParentZoomChanged()
- {
- T* pT = static_cast<T*>(this);
- int nId = pT->GetDlgCtrlID();
- NMHDR nmhdr = { pT->m_hWnd, (UINT_PTR)nId, ZSN_ZOOMCHANGED };
- ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr);
- }
- void DoWheelZoom(int zDelta)
- {
- float fZoomScale = m_fZoomScale + ((zDelta > 0) ? m_fZoomDelta : -m_fZoomDelta);
- T* pT = static_cast<T*>(this);
- pT->Zoom(fZoomScale);
- pT->NotifyParentZoomChanged();
- }
- BEGIN_MSG_MAP(CZoomScrollImpl)
- MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
- MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
- MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
- MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
- MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
- MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
- MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
- MESSAGE_HANDLER(WM_PAINT, OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
- MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
- MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
- MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
- MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
- ALT_MSG_MAP(1)
- COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
- COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
- COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
- COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
- COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
- END_MSG_MAP()
- LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- if((LOWORD(lParam) == HTCLIENT) && (m_nZoomMode != ZOOMMODE_OFF))
- {
- T* pT = static_cast<T*>(this);
- if((HWND)wParam == pT->m_hWnd)
- {
- DWORD dwPos = ::GetMessagePos();
- POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
- pT->ScreenToClient(&pt);
- if(pT->PtInDevRect(pt))
- {
- ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
- return 1;
- }
- }
- }
- bHandled = FALSE;
- return 0;
- }
- LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- if((GET_KEYSTATE_WPARAM(wParam) & MK_CONTROL) != 0) // handle zoom if Ctrl is pressed
- {
- int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
- T* pT = static_cast<T*>(this);
- pT->DoWheelZoom(zDelta);
- }
- else
- {
- CScrollImpl< T >::OnMouseWheel(uMsg, wParam, lParam, bHandled);
- }
- return 0;
- }
- LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- ATLASSERT(::IsWindow(pT->m_hWnd));
- ATLASSERT((m_sizeLogAll.cx >= 0) && (m_sizeLogAll.cy >= 0));
- ATLASSERT((this->m_sizeAll.cx >= 0) && (this->m_sizeAll.cy >= 0));
- if(wParam != NULL)
- {
- CDCHandle dc = (HDC)wParam;
- int nMapModeSav = dc.GetMapMode();
- dc.SetMapMode(MM_ANISOTROPIC);
- SIZE szWindowExt = { 0, 0 };
- dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
- SIZE szViewportExt = { 0, 0 };
- dc.SetViewportExt(this->m_sizeAll, &szViewportExt);
- POINT ptViewportOrg = { 0, 0 };
- dc.SetViewportOrg(-this->m_ptOffset.x, -this->m_ptOffset.y, &ptViewportOrg);
- pT->DoPaint(dc);
- dc.SetMapMode(nMapModeSav);
- dc.SetWindowExt(szWindowExt);
- dc.SetViewportExt(szViewportExt);
- dc.SetViewportOrg(ptViewportOrg);
- }
- else
- {
- CPaintDC dc(pT->m_hWnd);
- pT->PrepareDC(dc.m_hDC);
- pT->DoPaint(dc.m_hDC);
- }
- return 0;
- }
- LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
- {
- if((m_nZoomMode == ZOOMMODE_IN) && !m_bTracking)
- {
- T* pT = static_cast<T*>(this);
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- if(pT->PtInDevRect(pt))
- {
- pT->SetCapture();
- m_bTracking = true;
- ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y);
- RECT rcClip;
- pT->GetClientRect(&rcClip);
- if((this->m_ptOffset.x == 0) && (this->m_ptOffset.y == 0))
- {
- if(rcClip.right > this->m_sizeAll.cx)
- rcClip.right = this->m_sizeAll.cx;
- if(rcClip.bottom > this->m_sizeAll.cy)
- rcClip.bottom = this->m_sizeAll.cy;
- }
- ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rcClip, 2);
- ::ClipCursor(&rcClip);
- }
- }
- bHandled = FALSE;
- return 0;
- }
- LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
- {
- if(m_bTracking)
- {
- T* pT = static_cast<T*>(this);
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- if(pT->PtInDevRect(pt))
- {
- pT->DrawTrackRect();
- m_rcTrack.right = pt.x + 1;
- m_rcTrack.bottom = pt.y + 1;
- pT->DrawTrackRect();
- }
- }
- bHandled = FALSE;
- return 0;
- }
- LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
- {
- ::ReleaseCapture();
- if(m_nZoomMode == ZOOMMODE_OUT)
- {
- T* pT = static_cast<T*>(this);
- pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta);
- pT->NotifyParentZoomChanged();
- }
- bHandled = FALSE;
- return 0;
- }
- LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(m_bTracking)
- {
- m_bTracking = false;
- T* pT = static_cast<T*>(this);
- pT->DrawTrackRect();
- pT->Zoom(m_rcTrack);
- pT->NotifyParentZoomChanged();
- ::SetRectEmpty(&m_rcTrack);
- ::ClipCursor(NULL);
- }
- bHandled = FALSE;
- return 0;
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CZoomScrollWindowImpl - Implements scrolling window with zooming
- template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
- class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
- {
- public:
- BOOL SubclassWindow(HWND hWnd)
- {
- BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
- if(bRet != FALSE)
- {
- T* pT = static_cast<T*>(this);
- pT->GetSystemSettings();
- RECT rect = {};
- this->GetClientRect(&rect);
- pT->DoSize(rect.right, rect.bottom);
- }
- return bRet;
- }
- BEGIN_MSG_MAP(CZoomScrollWindowImpl)
- MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
- MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
- MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
- MESSAGE_HANDLER(WM_MOUSEWHEEL, CZoomScrollImpl< T >::OnMouseWheel)
- MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
- MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
- MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
- MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint)
- MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
- MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
- MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
- MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
- ALT_MSG_MAP(1)
- COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
- COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
- COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
- COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
- COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
- COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
- END_MSG_MAP()
- };
- ///////////////////////////////////////////////////////////////////////////////
- // CScrollContainer
- template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
- class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits >
- {
- public:
- DECLARE_WND_CLASS_EX2(NULL, T, 0, -1)
- typedef CScrollWindowImpl< T, TBase, TWinTraits > _baseClass;
- // Data members
- ATL::CWindow m_wndClient;
- bool m_bAutoSizeClient;
- bool m_bDrawEdgeIfEmpty;
- // Constructor
- CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false)
- {
- // Set CScrollWindowImpl extended style
- this->SetScrollExtendedStyle(SCRL_SCROLLCHILDREN);
- }
- // Attributes
- HWND GetClient() const
- {
- return m_wndClient;
- }
- HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true)
- {
- ATLASSERT(::IsWindow(this->m_hWnd));
- HWND hWndOldClient = m_wndClient;
- m_wndClient = hWndClient;
- this->SetRedraw(FALSE);
- this->SetScrollSize(1, 1, FALSE);
- if(m_wndClient.m_hWnd != NULL)
- {
- m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
- if(bClientSizeAsMin)
- {
- RECT rect = {};
- m_wndClient.GetWindowRect(&rect);
- if(((rect.right - rect.left) > 0) && ((rect.bottom - rect.top) > 0))
- this->SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE);
- }
- T* pT = static_cast<T*>(this);
- pT->UpdateLayout();
- }
- this->SetRedraw(TRUE);
- this->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
- return hWndOldClient;
- }
- // Message map and handlers
- BEGIN_MSG_MAP(CScrollContainerImpl)
- MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
- MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
- CHAIN_MSG_MAP(_baseClass)
- FORWARD_NOTIFICATIONS()
- ALT_MSG_MAP(1)
- CHAIN_MSG_MAP_ALT(_baseClass, 1)
- END_MSG_MAP()
- LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- if(m_wndClient.m_hWnd != NULL)
- m_wndClient.SetFocus();
- return 0;
- }
- LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- return 1; // no background needed
- }
- // Overrides for CScrollWindowImpl
- void DoSize(int cx, int cy)
- {
- _baseClass::DoSize(cx, cy);
- T* pT = static_cast<T*>(this);
- pT->UpdateLayout();
- }
- void DoPaint(CDCHandle dc)
- {
- if(!m_bAutoSizeClient || (m_wndClient.m_hWnd == NULL))
- {
- T* pT = static_cast<T*>(this);
- RECT rect = {};
- pT->GetContainerRect(rect);
- if(m_bDrawEdgeIfEmpty && (m_wndClient.m_hWnd == NULL))
- dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
- dc.FillRect(&rect, COLOR_APPWORKSPACE);
- }
- }
- void ScrollToView(POINT pt)
- {
- CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt);
- }
- void ScrollToView(RECT& rect)
- {
- CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect);
- }
- void ScrollToView(HWND hWnd) // client window coordinates
- {
- T* pT = static_cast<T*>(this);
- (void)pT; // avoid level 4 warning
- ATLASSERT(::IsWindow(pT->m_hWnd));
- ATLASSERT(m_wndClient.IsWindow());
- RECT rect = {};
- ::GetWindowRect(hWnd, &rect);
- ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2);
- ScrollToView(rect);
- }
- // Implementation - overrideable methods
- void UpdateLayout()
- {
- ATLASSERT(::IsWindow(this->m_hWnd));
- if(m_bAutoSizeClient && (m_wndClient.m_hWnd != NULL))
- {
- T* pT = static_cast<T*>(this);
- RECT rect = {};
- pT->GetContainerRect(rect);
- m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
- }
- else
- {
- this->Invalidate();
- }
- }
- void GetContainerRect(RECT& rect)
- {
- this->GetClientRect(&rect);
- if(rect.right < this->m_sizeAll.cx)
- rect.right = this->m_sizeAll.cx;
- if(rect.bottom < this->m_sizeAll.cy)
- rect.bottom = this->m_sizeAll.cy;
- }
- };
- class CScrollContainer : public CScrollContainerImpl<CScrollContainer>
- {
- public:
- DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1)
- };
- } // namespace WTL
- #endif // __ATLSCRL_H__
|