atlscrl.h 56 KB

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