scrollwnd.cpp 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391
  1. // some code taken from (freeware) Cool ScrollBar library by J Brown
  2. #include "main.h"
  3. #include <windowsx.h>
  4. #include <tchar.h>
  5. #include "scrollwnd.h"
  6. #include "../winamp/wa_dlg.h"
  7. #ifndef WM_MOUSEWHEEL
  8. #define WM_MOUSEWHEEL 0x020A
  9. #endif
  10. extern HRESULT(WINAPI *SetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); //xp theme shit
  11. extern HRESULT(WINAPI *IsAppThemed)(void);
  12. static TCHAR szPropStr[] = _T("CoolSBSubclassPtr");
  13. //
  14. // Special thumb-tracking variables
  15. //
  16. //
  17. static UINT uCurrentScrollbar = COOLSB_NONE; //SB_HORZ / SB_VERT
  18. static UINT uCurrentScrollPortion = HTSCROLL_NONE;
  19. static UINT uCurrentButton = 0;
  20. static RECT rcThumbBounds; //area that the scroll thumb can travel in
  21. static int nThumbSize; //(pixels)
  22. static int nThumbPos; //(pixels)
  23. static int nThumbMouseOffset; //(pixels)
  24. static int nLastPos = -1; //(scrollbar units)
  25. static int nThumbPos0; //(pixels) initial thumb position
  26. //
  27. // Temporary state used to auto-generate timer messages
  28. //
  29. static UINT uMouseOverId = 0;
  30. static UINT uMouseOverScrollbar = COOLSB_NONE;
  31. static UINT uHitTestPortion = HTSCROLL_NONE;
  32. static UINT uLastHitTestPortion = HTSCROLL_NONE;
  33. static RECT MouseOverRect;
  34. static UINT uScrollTimerMsg = 0;
  35. static UINT uScrollTimerPortion = HTSCROLL_NONE;
  36. static UINT_PTR uScrollTimerId = 0;
  37. static HWND hwndCurCoolSB = 0;
  38. ScrollWnd *GetScrollWndFromHwnd(HWND hwnd)
  39. {
  40. return (ScrollWnd *)GetProp(hwnd, szPropStr);
  41. }
  42. //
  43. // swap the rectangle's x coords with its y coords
  44. //
  45. static void __stdcall RotateRect(RECT *rect)
  46. {
  47. int temp;
  48. temp = rect->left;
  49. rect->left = rect->top;
  50. rect->top = temp;
  51. temp = rect->right;
  52. rect->right = rect->bottom;
  53. rect->bottom = temp;
  54. }
  55. //
  56. // swap the coords if the scrollbar is a SB_VERT
  57. //
  58. static void __stdcall RotateRect0(SCROLLBAR *sb, RECT *rect)
  59. {
  60. if (sb->nBarType == SB_VERT)
  61. RotateRect(rect);
  62. }
  63. //
  64. // Calculate if the SCROLLINFO members produce
  65. // an enabled or disabled scrollbar
  66. //
  67. static BOOL IsScrollInfoActive(SCROLLINFO *si)
  68. {
  69. if ((si->nPage > (UINT)si->nMax
  70. || si->nMax <= si->nMin || si->nMax == 0))
  71. return FALSE;
  72. else
  73. return TRUE;
  74. }
  75. //
  76. // Return if the specified scrollbar is enabled or not
  77. //
  78. static BOOL IsScrollbarActive(SCROLLBAR *sb)
  79. {
  80. SCROLLINFO *si = &sb->scrollInfo;
  81. if (((sb->fScrollFlags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ||
  82. !(sb->fScrollFlags & CSBS_THUMBALWAYS) && !IsScrollInfoActive(si))
  83. return FALSE;
  84. else
  85. return TRUE;
  86. }
  87. BOOL drawFrameControl(HDC hdc, LPRECT lprc, UINT uType, UINT state)
  88. {
  89. HDC hdcbmp;
  90. HBITMAP hbmpOld, hbmp;
  91. int startx, starty;
  92. hbmp = WADlg_getBitmap();
  93. if (!hbmp) return FALSE;
  94. hdcbmp = CreateCompatibleDC(hdc);
  95. if (!hdcbmp) return FALSE;
  96. hbmpOld = (HBITMAP)SelectObject(hdcbmp, hbmp);
  97. startx = 0;
  98. starty = 31;
  99. switch (state&3)
  100. {
  101. case DFCS_SCROLLRIGHT: startx = 14; starty = 45; break;
  102. case DFCS_SCROLLLEFT: startx = 0; starty = 45; break;
  103. case DFCS_SCROLLDOWN: startx = 14; starty = 31; break;
  104. }
  105. if (state&DFCS_PUSHED) startx += 28;
  106. StretchBlt(hdc, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, hdcbmp, startx, starty, 14, 14, SRCCOPY);
  107. SelectObject(hdcbmp, hbmpOld);
  108. DeleteDC(hdcbmp);
  109. return 1;
  110. }
  111. //
  112. // Draw a standard scrollbar arrow
  113. //
  114. static int DrawScrollArrow(SCROLLBAR *sbar, HDC hdc, RECT *rect, UINT arrow, BOOL fMouseDown, BOOL fMouseOver)
  115. {
  116. UINT ret;
  117. UINT flags = arrow;
  118. //HACKY bit so this routine can be called by vertical and horizontal code
  119. if (sbar->nBarType == SB_VERT)
  120. {
  121. if (flags & DFCS_SCROLLLEFT) flags = flags & ~DFCS_SCROLLLEFT | DFCS_SCROLLUP;
  122. if (flags & DFCS_SCROLLRIGHT) flags = flags & ~DFCS_SCROLLRIGHT | DFCS_SCROLLDOWN;
  123. }
  124. if (fMouseDown) flags |= (DFCS_FLAT | DFCS_PUSHED);
  125. ret = drawFrameControl(hdc, rect, DFC_SCROLL, flags);
  126. return ret;
  127. }
  128. //
  129. // Return the size in pixels for the specified scrollbar metric,
  130. // for the specified scrollbar
  131. //
  132. static int GetScrollMetric(SCROLLBAR *sbar, int metric)
  133. {
  134. if (sbar->nBarType == SB_HORZ)
  135. {
  136. if (metric == SM_CXHORZSB)
  137. {
  138. if (sbar->nArrowLength < 0)
  139. return -sbar->nArrowLength * 14; //GetSystemMetrics(SM_CXHSCROLL);
  140. else
  141. return sbar->nArrowLength;
  142. }
  143. else
  144. {
  145. if (sbar->nArrowWidth < 0)
  146. return -sbar->nArrowWidth * 14; //GetSystemMetrics(SM_CYHSCROLL);
  147. else
  148. return sbar->nArrowWidth;
  149. }
  150. }
  151. else if (sbar->nBarType == SB_VERT)
  152. {
  153. if (metric == SM_CYVERTSB)
  154. {
  155. if (sbar->nArrowLength < 0)
  156. return -sbar->nArrowLength * 14;//GetSystemMetrics(SM_CYVSCROLL);
  157. else
  158. return sbar->nArrowLength;
  159. }
  160. else
  161. {
  162. if (sbar->nArrowWidth < 0)
  163. return -sbar->nArrowWidth * 14;//GetSystemMetrics(SM_CXVSCROLL);
  164. else
  165. return sbar->nArrowWidth;
  166. }
  167. }
  168. return 0;
  169. }
  170. //
  171. //
  172. //
  173. static COLORREF GetSBForeColor(void)
  174. {
  175. return WADlg_getColor(WADLG_SCROLLBAR_FGCOLOR);
  176. }
  177. static COLORREF GetSBBackColor(void)
  178. {
  179. return WADlg_getColor(WADLG_SCROLLBAR_BGCOLOR);
  180. }
  181. //
  182. // Paint a checkered rectangle, with each alternate
  183. // pixel being assigned a different colour
  184. //
  185. static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg)
  186. {
  187. static WORD wCheckPat[8] =
  188. {
  189. 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555
  190. };
  191. HBITMAP hbmp;
  192. HBRUSH hbr, hbrold;
  193. COLORREF fgold, bgold;
  194. hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);
  195. hbr = CreatePatternBrush(hbmp);
  196. UnrealizeObject(hbr);
  197. SetBrushOrgEx(hdc, rect->left, rect->top, 0);
  198. hbrold = (HBRUSH)SelectObject(hdc, hbr);
  199. fgold = SetTextColor(hdc, fg);
  200. bgold = SetBkColor(hdc, bg);
  201. PatBlt(hdc, rect->left, rect->top,
  202. rect->right - rect->left,
  203. rect->bottom - rect->top,
  204. PATCOPY);
  205. SetBkColor(hdc, bgold);
  206. SetTextColor(hdc, fgold);
  207. SelectObject(hdc, hbrold);
  208. DeleteObject(hbr);
  209. DeleteObject(hbmp);
  210. }
  211. //
  212. // Fill the specifed rectangle using a solid colour
  213. //
  214. static void PaintRect(HDC hdc, RECT *rect, COLORREF color)
  215. {
  216. COLORREF oldcol = SetBkColor(hdc, color);
  217. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, _T(""), 0, 0);
  218. SetBkColor(hdc, oldcol);
  219. }
  220. //
  221. // Draw a simple blank scrollbar push-button. Can be used
  222. // to draw a push button, or the scrollbar thumb
  223. // drawflag - could set to BF_FLAT to make flat scrollbars
  224. //
  225. void DrawBlankButton(HDC hdc, const RECT *rect, UINT drawflag, int pushed, int vertical)
  226. {
  227. HBITMAP hbmp, hbmpOld;
  228. hbmp = WADlg_getBitmap();
  229. if (!hbmp) return;
  230. HDC hdcbmp = CreateCompatibleDC(hdc);
  231. if (!hdcbmp) return;
  232. hbmpOld = (HBITMAP)SelectObject(hdcbmp, hbmp);
  233. #define PART1SIZE 4 //copied top
  234. #define PART2SIZE 5 //stretched top
  235. #define PART3SIZE 10 //copied middle
  236. #define PART4SIZE 5 //stretched bottom
  237. #define PART5SIZE 4 //copied bottom
  238. if (vertical)
  239. {
  240. int middle = (rect->bottom - rect->top) / 2;
  241. int startx = pushed ? 70 : 56;
  242. //top
  243. StretchBlt(hdc, rect->left, rect->top, rect->right - rect->left, PART1SIZE, hdcbmp, startx, 31, 14, PART1SIZE, SRCCOPY);
  244. int p = PART1SIZE;
  245. //stretched top
  246. int l = middle - PART1SIZE - (PART3SIZE / 2);
  247. if (l > 0)
  248. {
  249. StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, l, hdcbmp, startx, 31 + PART1SIZE, 14, PART2SIZE, SRCCOPY);
  250. p += middle - PART1SIZE - (PART3SIZE / 2);
  251. }
  252. //copied middle
  253. int m = (rect->bottom - rect->top) - PART1SIZE - PART5SIZE; //space that's available for middle
  254. m = min(m, PART3SIZE);
  255. if (m > 0)
  256. {
  257. StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, m, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE, 14, m, SRCCOPY);
  258. p += m;
  259. }
  260. //stretched bottom
  261. l = rect->bottom - rect->top - p - PART5SIZE;
  262. if (l > 0) StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, l, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE + PART3SIZE, 14, PART4SIZE, SRCCOPY);
  263. //bottom
  264. StretchBlt(hdc, rect->left, rect->bottom - PART5SIZE, rect->right - rect->left, PART5SIZE, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE + PART3SIZE + PART4SIZE, 14, PART5SIZE, SRCCOPY);
  265. }
  266. else
  267. {
  268. int middle = (rect->right - rect->left) / 2;
  269. int starty = pushed ? 45 : 31;
  270. //top
  271. StretchBlt(hdc, rect->left, rect->top, PART1SIZE, rect->bottom - rect->top, hdcbmp, 84, starty, PART1SIZE, 14, SRCCOPY);
  272. int p = PART1SIZE;
  273. //stretched top
  274. int l = middle - PART1SIZE - (PART3SIZE / 2);
  275. if (l > 0)
  276. {
  277. StretchBlt(hdc, rect->left + p, rect->top, l, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE, starty, PART2SIZE, 14, SRCCOPY);
  278. p += middle - PART1SIZE - (PART3SIZE / 2);
  279. }
  280. //copied middle
  281. int m = (rect->right - rect->left) - PART1SIZE - PART5SIZE; //space that's available for middle
  282. m = min(m, PART3SIZE);
  283. if (m > 0)
  284. {
  285. StretchBlt(hdc, rect->left + p, rect->top, m, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE, starty, m, 14, SRCCOPY);
  286. p += m;
  287. }
  288. //stretched bottom
  289. l = rect->right - rect->left - p - PART5SIZE;
  290. if (l > 0) StretchBlt(hdc, rect->left + p, rect->top, l, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE + PART3SIZE, starty, PART4SIZE, 14, SRCCOPY);
  291. //bottom
  292. StretchBlt(hdc, rect->right - PART5SIZE, rect->top, PART5SIZE, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE + PART3SIZE + PART4SIZE, starty, PART5SIZE, 14, SRCCOPY);
  293. }
  294. SelectObject(hdcbmp, hbmpOld);
  295. DeleteDC(hdcbmp);
  296. }
  297. //
  298. // Send a WM_VSCROLL or WM_HSCROLL message
  299. //
  300. static void SendScrollMessage(HWND hwnd, UINT scrMsg, UINT scrId, UINT pos)
  301. {
  302. SendMessage(hwnd, scrMsg, MAKEWPARAM(scrId, pos), 0);
  303. }
  304. //
  305. // Calculate the screen coordinates of the area taken by
  306. // the horizontal scrollbar. Take into account the size
  307. // of the window borders
  308. //
  309. static BOOL GetHScrollRect(ScrollWnd *sw, HWND hwnd, RECT *rect)
  310. {
  311. GetWindowRect(hwnd, rect);
  312. if (sw->fLeftScrollbar)
  313. {
  314. rect->left += sw->cxLeftEdge + (sw->sbarVert.fScrollVisible ?
  315. GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
  316. rect->right -= sw->cxRightEdge;
  317. }
  318. else
  319. {
  320. rect->left += sw->cxLeftEdge; //left window edge
  321. rect->right -= sw->cxRightEdge + //right window edge
  322. (sw->sbarVert.fScrollVisible ?
  323. GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
  324. }
  325. rect->bottom -= sw->cyBottomEdge; //bottom window edge
  326. rect->top = rect->bottom -
  327. (sw->sbarHorz.fScrollVisible ?
  328. GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB) : 0);
  329. return TRUE;
  330. }
  331. //
  332. // Calculate the screen coordinates of the area taken by the
  333. // vertical scrollbar
  334. //
  335. static BOOL GetVScrollRect(ScrollWnd *sw, HWND hwnd, RECT *rect)
  336. {
  337. GetWindowRect(hwnd, rect);
  338. rect->top += sw->cyTopEdge; //top window edge
  339. rect->bottom -= sw->cyBottomEdge +
  340. (sw->sbarHorz.fScrollVisible ? //bottom window edge
  341. GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB) : 0);
  342. if (sw->fLeftScrollbar)
  343. {
  344. rect->left += sw->cxLeftEdge;
  345. rect->right = rect->left + (sw->sbarVert.fScrollVisible ?
  346. GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
  347. }
  348. else
  349. {
  350. rect->right -= sw->cxRightEdge;
  351. rect->left = rect->right - (sw->sbarVert.fScrollVisible ?
  352. GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
  353. }
  354. return TRUE;
  355. }
  356. // Depending on what type of scrollbar nBar refers to, call the
  357. // appropriate Get?ScrollRect function
  358. //
  359. BOOL GetScrollRect(ScrollWnd *sw, UINT nBar, HWND hwnd, RECT *rect)
  360. {
  361. if (nBar == SB_HORZ)
  362. return GetHScrollRect(sw, hwnd, rect);
  363. else if (nBar == SB_VERT)
  364. return GetVScrollRect(sw, hwnd, rect);
  365. else
  366. return FALSE;
  367. }
  368. //
  369. // Work out the scrollbar width/height for either type of scrollbar (SB_HORZ/SB_VERT)
  370. // rect - coords of the scrollbar.
  371. // store results into *thumbsize and *thumbpos
  372. //
  373. static int CalcThumbSize(SCROLLBAR *sbar, const RECT *rect, int *pthumbsize, int *pthumbpos)
  374. {
  375. SCROLLINFO *si;
  376. int scrollsize; //total size of the scrollbar including arrow buttons
  377. int workingsize; //working area (where the thumb can slide)
  378. int siMaxMin;
  379. int butsize;
  380. int startcoord;
  381. int thumbpos = 0, thumbsize = 0;
  382. //work out the width (for a horizontal) or the height (for a vertical)
  383. //of a standard scrollbar button
  384. butsize = GetScrollMetric(sbar, SM_SCROLL_LENGTH);
  385. if (1) //sbar->nBarType == SB_HORZ)
  386. {
  387. scrollsize = rect->right - rect->left;
  388. startcoord = rect->left;
  389. }
  390. /*else if(sbar->nBarType == SB_VERT)
  391. {
  392. scrollsize = rect->bottom - rect->top;
  393. startcoord = rect->top;
  394. }
  395. else
  396. {
  397. return 0;
  398. }*/
  399. si = &sbar->scrollInfo;
  400. siMaxMin = si->nMax - si->nMin + 1;
  401. workingsize = scrollsize - butsize * 2;
  402. //
  403. // Work out the scrollbar thumb SIZE
  404. //
  405. if (si->nPage == 0)
  406. {
  407. thumbsize = butsize;
  408. }
  409. else if (siMaxMin > 0)
  410. {
  411. thumbsize = MulDiv(si->nPage, workingsize, siMaxMin);
  412. if (thumbsize < sbar->nMinThumbSize)
  413. thumbsize = sbar->nMinThumbSize;
  414. }
  415. //
  416. // Work out the scrollbar thumb position
  417. //
  418. if (siMaxMin > 0)
  419. {
  420. int pagesize = max(1, si->nPage);
  421. thumbpos = MulDiv(si->nPos - si->nMin, workingsize - thumbsize, siMaxMin - pagesize);
  422. if (thumbpos < 0)
  423. thumbpos = 0;
  424. if (thumbpos >= workingsize - thumbsize)
  425. thumbpos = workingsize - thumbsize;
  426. }
  427. thumbpos += startcoord + butsize;
  428. *pthumbpos = thumbpos;
  429. *pthumbsize = thumbsize;
  430. return 1;
  431. }
  432. //
  433. // return a hit-test value for whatever part of the scrollbar x,y is located in
  434. // rect, x, y: SCREEN coordinates
  435. // the rectangle must not include space for any inserted buttons
  436. // (i.e, JUST the scrollbar area)
  437. //
  438. static UINT GetHorzScrollPortion(SCROLLBAR *sbar, HWND hwnd, const RECT *rect, int x, int y)
  439. {
  440. int thumbwidth, thumbpos;
  441. int butwidth = GetScrollMetric(sbar, SM_SCROLL_LENGTH);
  442. int scrollwidth = rect->right - rect->left;
  443. int workingwidth = scrollwidth - butwidth * 2;
  444. if (y < rect->top || y >= rect->bottom)
  445. return HTSCROLL_NONE;
  446. CalcThumbSize(sbar, rect, &thumbwidth, &thumbpos);
  447. //if we have had to scale the buttons to fit in the rect,
  448. //then adjust the button width accordingly
  449. if (scrollwidth <= butwidth * 2)
  450. {
  451. butwidth = scrollwidth / 2;
  452. }
  453. //check for left button click
  454. if (x >= rect->left && x < rect->left + butwidth)
  455. {
  456. return HTSCROLL_LEFT;
  457. }
  458. //check for right button click
  459. else if (x >= rect->right - butwidth && x < rect->right)
  460. {
  461. return HTSCROLL_RIGHT;
  462. }
  463. //if the thumb is too big to fit (i.e. it isn't visible)
  464. //then return a NULL scrollbar area
  465. if (thumbwidth >= workingwidth)
  466. return HTSCROLL_NONE;
  467. //check for point in the thumbbar
  468. if (x >= thumbpos && x < thumbpos + thumbwidth)
  469. {
  470. return HTSCROLL_THUMB;
  471. }
  472. //check for left margin
  473. else if (x >= rect->left + butwidth && x < thumbpos)
  474. {
  475. return HTSCROLL_PAGELEFT;
  476. }
  477. else if (x >= thumbpos + thumbwidth && x < rect->right - butwidth)
  478. {
  479. return HTSCROLL_PAGERIGHT;
  480. }
  481. return HTSCROLL_NONE;
  482. }
  483. //
  484. // For vertical scrollbars, rotate all coordinates by -90 degrees
  485. // so that we can use the horizontal version of this function
  486. //
  487. static UINT GetVertScrollPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
  488. {
  489. UINT r;
  490. RotateRect(rect);
  491. r = GetHorzScrollPortion(sb, hwnd, rect, y, x);
  492. RotateRect(rect);
  493. return r;
  494. }
  495. //
  496. // CUSTOM DRAW support
  497. //
  498. static LRESULT PostCustomPrePostPaint0(HWND hwnd, HDC hdc, SCROLLBAR *sb, UINT dwStage)
  499. {
  500. return 0;
  501. }
  502. static LRESULT PostCustomDrawNotify0(HWND hwnd, HDC hdc, UINT nBar, RECT *prect, UINT nItem, BOOL fMouseDown, BOOL fMouseOver, BOOL fInactive)
  503. {
  504. return 0;
  505. }
  506. // Depending on if we are supporting custom draw, either define
  507. // a macro to the function name, or to nothing at all. If custom draw
  508. // is turned off, then we can save ALOT of code space by binning all
  509. // calls to the custom draw support.
  510. //
  511. #define PostCustomDrawNotify 1 ? (void)0 : PostCustomDrawNotify0
  512. #define PostCustomPrePostPaint 1 ? (void)0 : PostCustomPrePostPaint0
  513. static LRESULT PostMouseNotify0(HWND hwnd, UINT msg, UINT nBar, RECT *prect, UINT nCmdId, POINT pt)
  514. {
  515. return 0;
  516. }
  517. #ifdef NOTIFY_MOUSE
  518. #define PostMouseNotify PostMouseNotify0
  519. #else
  520. #define PostMouseNotify 1 ? (void)0 : PostMouseNotify0
  521. #endif
  522. //
  523. // Draw a complete HORIZONTAL scrollbar in the given rectangle
  524. // Don't draw any inserted buttons in this procedure
  525. //
  526. // uDrawFlags - hittest code, to say if to draw the
  527. // specified portion in an active state or not.
  528. //
  529. //
  530. static LRESULT NCDrawHScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
  531. {
  532. SCROLLINFO *si;
  533. RECT ctrl, thumb;
  534. RECT sbm;
  535. int butwidth = GetScrollMetric(sb, SM_SCROLL_LENGTH);
  536. int scrollwidth = rect->right - rect->left;
  537. int workingwidth = scrollwidth - butwidth * 2;
  538. int thumbwidth = 0, thumbpos = 0;
  539. BOOL fCustomDraw = 0;
  540. BOOL fMouseDownL = 0, fMouseOverL = 0;
  541. BOOL fMouseDownR = 0, fMouseOverR = 0;
  542. COLORREF crCheck1 = GetSBForeColor();
  543. COLORREF crCheck2 = GetSBBackColor();
  544. COLORREF crInverse1 = WADlg_getColor(WADLG_SCROLLBAR_INV_FGCOLOR);
  545. COLORREF crInverse2 = WADlg_getColor(WADLG_SCROLLBAR_INV_BGCOLOR);
  546. UINT uDEFlat = sb->fFlatScrollbar ? BF_FLAT : 0;
  547. //drawing flags to modify the appearance of the scrollbar buttons
  548. UINT uLeftButFlags = DFCS_SCROLLLEFT;
  549. UINT uRightButFlags = DFCS_SCROLLRIGHT;
  550. if (scrollwidth <= 0)
  551. return 0;
  552. si = &sb->scrollInfo;
  553. if (hwnd != hwndCurCoolSB)
  554. uDrawFlags = HTSCROLL_NONE;
  555. //
  556. // work out the thumb size and position
  557. //
  558. CalcThumbSize(sb, rect, &thumbwidth, &thumbpos);
  559. if (sb->fScrollFlags & ESB_DISABLE_LEFT) uLeftButFlags |= DFCS_INACTIVE;
  560. if (sb->fScrollFlags & ESB_DISABLE_RIGHT) uRightButFlags |= DFCS_INACTIVE;
  561. //if we need to grey the arrows because there is no data to scroll
  562. if (!IsScrollInfoActive(si) && !(sb->fScrollFlags & CSBS_THUMBALWAYS))
  563. {
  564. uLeftButFlags |= DFCS_INACTIVE;
  565. uRightButFlags |= DFCS_INACTIVE;
  566. }
  567. if (hwnd == hwndCurCoolSB)
  568. {
  569. fMouseDownL = (uDrawFlags == HTSCROLL_LEFT);
  570. fMouseDownR = (uDrawFlags == HTSCROLL_RIGHT);
  571. }
  572. //
  573. // Draw the scrollbar now
  574. //
  575. if (scrollwidth > butwidth*2)
  576. {
  577. //LEFT ARROW
  578. SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
  579. RotateRect0(sb, &ctrl);
  580. if (fCustomDraw)
  581. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE);
  582. else
  583. DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL);
  584. RotateRect0(sb, &ctrl);
  585. //MIDDLE PORTION
  586. //if we can fit the thumbbar in, then draw it
  587. if (thumbwidth > 0 && thumbwidth <= workingwidth
  588. && IsScrollInfoActive(si) && ((sb->fScrollFlags & ESB_DISABLE_BOTH) != ESB_DISABLE_BOTH))
  589. {
  590. //Draw the scrollbar margin above the thumb
  591. SetRect(&sbm, rect->left + butwidth, rect->top, thumbpos, rect->bottom);
  592. RotateRect0(sb, &sbm);
  593. if (fCustomDraw)
  594. {
  595. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGELEFT, uDrawFlags == HTSCROLL_PAGELEFT, FALSE, FALSE);
  596. }
  597. else
  598. {
  599. if (uDrawFlags == HTSCROLL_PAGELEFT)
  600. DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2);
  601. else
  602. DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2);
  603. }
  604. RotateRect0(sb, &sbm);
  605. //Draw the margin below the thumb
  606. sbm.left = thumbpos + thumbwidth;
  607. sbm.right = rect->right - butwidth;
  608. RotateRect0(sb, &sbm);
  609. if (fCustomDraw)
  610. {
  611. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGERIGHT, uDrawFlags == HTSCROLL_PAGERIGHT, 0, 0);
  612. }
  613. else
  614. {
  615. if (uDrawFlags == HTSCROLL_PAGERIGHT)
  616. DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2);
  617. else
  618. DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2);
  619. }
  620. RotateRect0(sb, &sbm);
  621. //Draw the THUMB finally
  622. SetRect(&thumb, thumbpos, rect->top, thumbpos + thumbwidth, rect->bottom);
  623. RotateRect0(sb, &thumb);
  624. if (fCustomDraw)
  625. {
  626. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &thumb, SB_THUMBTRACK, uDrawFlags == HTSCROLL_THUMB, uHitTestPortion == HTSCROLL_THUMB, FALSE);
  627. }
  628. else
  629. {
  630. int track = 0;
  631. if (uCurrentScrollbar == (UINT)sb->nBarType) track = GetScrollWndFromHwnd(hwnd)->fThumbTracking;
  632. DrawBlankButton(hdc, &thumb, uDEFlat, track, sb->nBarType == SB_VERT);
  633. }
  634. RotateRect0(sb, &thumb);
  635. }
  636. //otherwise, just leave that whole area blank
  637. else
  638. {
  639. OffsetRect(&ctrl, butwidth, 0);
  640. ctrl.right = rect->right - butwidth;
  641. //if we always show the thumb covering the whole scrollbar,
  642. //then draw it that way
  643. if (!IsScrollInfoActive(si) && (sb->fScrollFlags & CSBS_THUMBALWAYS)
  644. && ctrl.right - ctrl.left > sb->nMinThumbSize)
  645. {
  646. //leave a 1-pixel gap between the thumb + right button
  647. ctrl.right --;
  648. RotateRect0(sb, &ctrl);
  649. if (fCustomDraw)
  650. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_THUMBTRACK, fMouseDownL, FALSE, FALSE);
  651. else
  652. {
  653. DrawBlankButton(hdc, &ctrl, uDEFlat, 0, sb->nBarType == SB_VERT);
  654. }
  655. RotateRect0(sb, &ctrl);
  656. //draw the single-line gap
  657. ctrl.left = ctrl.right;
  658. ctrl.right += 1;
  659. RotateRect0(sb, &ctrl);
  660. if (fCustomDraw)
  661. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
  662. else
  663. PaintRect(hdc, &ctrl, GetSysColor(COLOR_SCROLLBAR));
  664. RotateRect0(sb, &ctrl);
  665. }
  666. //otherwise, paint a blank if the thumb doesn't fit in
  667. else
  668. {
  669. RotateRect0(sb, &ctrl);
  670. if (fCustomDraw)
  671. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
  672. else
  673. DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2);
  674. RotateRect0(sb, &ctrl);
  675. }
  676. }
  677. //RIGHT ARROW
  678. SetRect(&ctrl, rect->right - butwidth, rect->top, rect->right, rect->bottom);
  679. RotateRect0(sb, &ctrl);
  680. if (fCustomDraw)
  681. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINERIGHT, fMouseDownR, fMouseOverR, uRightButFlags & DFCS_INACTIVE);
  682. else
  683. DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR);
  684. RotateRect0(sb, &ctrl);
  685. }
  686. //not enough room for the scrollbar, so just draw the buttons (scaled in size to fit)
  687. else
  688. {
  689. butwidth = scrollwidth / 2;
  690. //LEFT ARROW
  691. SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
  692. RotateRect0(sb, &ctrl);
  693. if (fCustomDraw)
  694. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE);
  695. else
  696. DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL);
  697. RotateRect0(sb, &ctrl);
  698. //RIGHT ARROW
  699. OffsetRect(&ctrl, scrollwidth - butwidth, 0);
  700. RotateRect0(sb, &ctrl);
  701. if (fCustomDraw)
  702. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINERIGHT, fMouseDownR, fMouseOverR, uRightButFlags & DFCS_INACTIVE);
  703. else
  704. DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR);
  705. RotateRect0(sb, &ctrl);
  706. //if there is a gap between the buttons, fill it with a solid color
  707. //if(butwidth & 0x0001)
  708. if (ctrl.left != rect->left + butwidth)
  709. {
  710. ctrl.left --;
  711. ctrl.right -= butwidth;
  712. RotateRect0(sb, &ctrl);
  713. if (fCustomDraw)
  714. PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
  715. else
  716. DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2);
  717. RotateRect0(sb, &ctrl);
  718. }
  719. }
  720. return fCustomDraw;
  721. }
  722. //
  723. // Draw a vertical scrollbar using the horizontal draw routine, but
  724. // with the coordinates adjusted accordingly
  725. //
  726. static LRESULT NCDrawVScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
  727. {
  728. LRESULT ret;
  729. RECT rc;
  730. rc = *rect;
  731. RotateRect(&rc);
  732. ret = NCDrawHScrollbar(sb, hwnd, hdc, &rc, uDrawFlags);
  733. RotateRect(&rc);
  734. return ret;
  735. }
  736. //
  737. // Generic wrapper function for the scrollbar drawing
  738. //
  739. static LRESULT NCDrawScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
  740. {
  741. if (sb->nBarType == SB_HORZ)
  742. return NCDrawHScrollbar(sb, hwnd, hdc, rect, uDrawFlags);
  743. else
  744. return NCDrawVScrollbar(sb, hwnd, hdc, rect, uDrawFlags);
  745. }
  746. //
  747. // Define these two for proper processing of NCPAINT
  748. // NOT needed if we don't bother to mask the scrollbars we draw
  749. // to prevent the old window procedure from accidently drawing over them
  750. //
  751. HDC CoolSB_GetDC(HWND hwnd, WPARAM wParam)
  752. {
  753. // I just can't figure out GetDCEx, so I'll just use this:
  754. return GetWindowDC(hwnd);
  755. }
  756. static LRESULT NCPaint(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
  757. {
  758. SCROLLBAR *sb;
  759. HDC hdc;
  760. HRGN hrgn;
  761. RECT winrect, rect;
  762. HRGN clip;
  763. BOOL fUpdateAll = ((LONG)wParam == 1);
  764. BOOL fCustomDraw = FALSE;
  765. LRESULT ret;
  766. DWORD dwStyle;
  767. GetWindowRect(hwnd, &winrect);
  768. //if entire region needs painting, then make a region to cover the entire window
  769. hrgn = (HRGN)wParam;
  770. //hdc = GetWindowDC(hwnd);
  771. hdc = CoolSB_GetDC(hwnd, wParam);
  772. //
  773. // Only draw the horizontal scrollbar if the window is tall enough
  774. //
  775. sb = &sw->sbarHorz;
  776. if (sb->fScrollVisible)
  777. {
  778. //get the screen coordinates of the whole horizontal scrollbar area
  779. GetHScrollRect(sw, hwnd, &rect);
  780. //make the coordinates relative to the window for drawing
  781. OffsetRect(&rect, -winrect.left, -winrect.top);
  782. if (uCurrentScrollbar == SB_HORZ)
  783. fCustomDraw |= NCDrawHScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
  784. else
  785. fCustomDraw |= NCDrawHScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE);
  786. }
  787. //
  788. // Only draw the vertical scrollbar if the window is wide enough to accomodate it
  789. //
  790. sb = &sw->sbarVert;
  791. if (sb->fScrollVisible)
  792. {
  793. //get the screen cooridinates of the whole horizontal scrollbar area
  794. GetVScrollRect(sw, hwnd, &rect);
  795. //make the coordinates relative to the window for drawing
  796. OffsetRect(&rect, -winrect.left, -winrect.top);
  797. if (uCurrentScrollbar == SB_VERT)
  798. fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
  799. else
  800. fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE);
  801. }
  802. //Call the default window procedure for WM_NCPAINT, with the
  803. //new window region. ** region must be in SCREEN coordinates **
  804. dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
  805. // If the window has WS_(H-V)SCROLL bits set, we should reset them
  806. // to avoid windows taking the scrollbars into account.
  807. // We temporarily set a flag preventing the subsecuent
  808. // WM_STYLECHANGING/WM_STYLECHANGED to be forwarded to
  809. // the original window procedure
  810. if (dwStyle & (WS_VSCROLL | WS_HSCROLL))
  811. {
  812. sw->bPreventStyleChange = TRUE;
  813. SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL | WS_HSCROLL));
  814. }
  815. ret = (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCPAINT, (WPARAM)hrgn, lParam) :
  816. CallWindowProcA(sw->oldproc, hwnd, WM_NCPAINT, (WPARAM)hrgn, lParam);
  817. if (dwStyle & (WS_VSCROLL | WS_HSCROLL))
  818. {
  819. SetWindowLong(hwnd, GWL_STYLE, dwStyle);
  820. sw->bPreventStyleChange = FALSE;
  821. }
  822. // DRAW THE DEAD AREA
  823. // only do this if the horizontal and vertical bars are visible
  824. if (sw->sbarHorz.fScrollVisible && sw->sbarVert.fScrollVisible)
  825. {
  826. GetWindowRect(hwnd, &rect);
  827. OffsetRect(&rect, -winrect.left, -winrect.top);
  828. rect.bottom -= sw->cyBottomEdge;
  829. rect.top = rect.bottom - GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB);
  830. if (sw->fLeftScrollbar)
  831. {
  832. rect.left += sw->cxLeftEdge;
  833. rect.right = rect.left + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB);
  834. }
  835. else
  836. {
  837. rect.right -= sw->cxRightEdge;
  838. rect.left = rect.right - GetScrollMetric(&sw->sbarVert, SM_CXVERTSB);
  839. }
  840. if (fCustomDraw)
  841. PostCustomDrawNotify(hwnd, hdc, SB_BOTH, &rect, 32, 0, 0, 0);
  842. else
  843. {
  844. //calculate the position of THIS window's dead area
  845. //with the position of the PARENT window's client rectangle.
  846. //if THIS window has been positioned such that its bottom-right
  847. //corner sits in the parent's bottom-right corner, then we should
  848. //show the sizing-grip.
  849. //Otherwise, assume this window is not in the right place, and
  850. //just draw a blank rectangle
  851. RECT parent;
  852. RECT rect2;
  853. HWND hwndParent = GetParent(hwnd);
  854. GetClientRect(hwndParent, &parent);
  855. MapWindowPoints(hwndParent, 0, (POINT *)&parent, 2);
  856. CopyRect(&rect2, &rect);
  857. OffsetRect(&rect2, winrect.left, winrect.top);
  858. if (!sw->fLeftScrollbar && parent.right == rect2.right + sw->cxRightEdge && parent.bottom == rect2.bottom + sw->cyBottomEdge
  859. || sw->fLeftScrollbar && parent.left == rect2.left - sw->cxLeftEdge && parent.bottom == rect2.bottom + sw->cyBottomEdge)
  860. drawFrameControl(hdc, &rect, DFC_SCROLL, sw->fLeftScrollbar ? DFCS_SCROLLSIZEGRIPRIGHT : DFCS_SCROLLSIZEGRIP);
  861. else
  862. PaintRect(hdc, &rect, WADlg_getColor(WADLG_SCROLLBAR_DEADAREA_COLOR));
  863. }
  864. }
  865. UNREFERENCED_PARAMETER(clip);
  866. ReleaseDC(hwnd, hdc);
  867. return ret;
  868. }
  869. //
  870. // Need to detect if we have clicked in the scrollbar region or not
  871. //
  872. static LRESULT NCHitTest(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
  873. {
  874. RECT hrect;
  875. RECT vrect;
  876. POINT pt;
  877. pt.x = GET_X_LPARAM(lParam);
  878. pt.y = GET_Y_LPARAM(lParam);
  879. //work out exactly where the Horizontal and Vertical scrollbars are
  880. GetHScrollRect(sw, hwnd, &hrect);
  881. GetVScrollRect(sw, hwnd, &vrect);
  882. //Clicked in the horizontal scrollbar area
  883. if (sw->sbarHorz.fScrollVisible && PtInRect(&hrect, pt))
  884. {
  885. return HTHSCROLL;
  886. }
  887. //Clicked in the vertical scrollbar area
  888. else if (sw->sbarVert.fScrollVisible && PtInRect(&vrect, pt))
  889. {
  890. return HTVSCROLL;
  891. }
  892. //clicked somewhere else
  893. else
  894. {
  895. return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCHITTEST, wParam, lParam) :
  896. CallWindowProcA(sw->oldproc, hwnd, WM_NCHITTEST, wParam, lParam);
  897. }
  898. }
  899. //
  900. // Return a HT* value indicating what part of the scrollbar was clicked
  901. // Rectangle is not adjusted
  902. //
  903. static UINT GetHorzPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
  904. {
  905. RECT rc = *rect;
  906. if (y < rc.top || y >= rc.bottom) return HTSCROLL_NONE;
  907. //Now we have the rectangle for the scrollbar itself, so work out
  908. //what part we clicked on.
  909. return GetHorzScrollPortion(sb, hwnd, &rc, x, y);
  910. }
  911. //
  912. // Just call the horizontal version, with adjusted coordinates
  913. //
  914. static UINT GetVertPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
  915. {
  916. UINT ret;
  917. RotateRect(rect);
  918. ret = GetHorzPortion(sb, hwnd, rect, y, x);
  919. RotateRect(rect);
  920. return ret;
  921. }
  922. //
  923. // Wrapper function for GetHorzPortion and GetVertPortion
  924. //
  925. static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
  926. {
  927. if (sb->nBarType == SB_HORZ)
  928. return GetHorzPortion(sb, hwnd, rect, x, y);
  929. else if (sb->nBarType == SB_VERT)
  930. return GetVertPortion(sb, hwnd, rect, x, y);
  931. else
  932. return HTSCROLL_NONE;
  933. }
  934. //
  935. // Input: rectangle of the total scrollbar area
  936. // Output: adjusted to take the inserted buttons into account
  937. //
  938. static void GetRealHorzScrollRect(SCROLLBAR *sb, RECT *rect)
  939. {
  940. if (sb->fButVisibleBefore) rect->left += sb->nButSizeBefore;
  941. if (sb->fButVisibleAfter) rect->right -= sb->nButSizeAfter;
  942. }
  943. //
  944. // Input: rectangle of the total scrollbar area
  945. // Output: adjusted to take the inserted buttons into account
  946. //
  947. static void GetRealVertScrollRect(SCROLLBAR *sb, RECT *rect)
  948. {
  949. if (sb->fButVisibleBefore) rect->top += sb->nButSizeBefore;
  950. if (sb->fButVisibleAfter) rect->bottom -= sb->nButSizeAfter;
  951. }
  952. //
  953. // Decide which type of scrollbar we have before calling
  954. // the real function to do the job
  955. //
  956. static void GetRealScrollRect(SCROLLBAR *sb, RECT *rect)
  957. {
  958. if (sb->nBarType == SB_HORZ)
  959. {
  960. GetRealHorzScrollRect(sb, rect);
  961. }
  962. else if (sb->nBarType == SB_VERT)
  963. {
  964. GetRealVertScrollRect(sb, rect);
  965. }
  966. }
  967. //
  968. // Left button click in the non-client area
  969. //
  970. static LRESULT NCLButtonDown(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
  971. {
  972. RECT rect, winrect;
  973. HDC hdc;
  974. SCROLLBAR *sb;
  975. POINT pt;
  976. pt.x = GET_X_LPARAM(lParam);
  977. pt.y = GET_Y_LPARAM(lParam);
  978. hwndCurCoolSB = hwnd;
  979. //
  980. // HORIZONTAL SCROLLBAR PROCESSING
  981. //
  982. if (wParam == HTHSCROLL)
  983. {
  984. uScrollTimerMsg = WM_HSCROLL;
  985. uCurrentScrollbar = SB_HORZ;
  986. sb = &sw->sbarHorz;
  987. //get the total area of the normal Horz scrollbar area
  988. GetHScrollRect(sw, hwnd, &rect);
  989. uCurrentScrollPortion = GetHorzPortion(sb, hwnd, &rect, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
  990. }
  991. //
  992. // VERTICAL SCROLLBAR PROCESSING
  993. //
  994. else if (wParam == HTVSCROLL)
  995. {
  996. uScrollTimerMsg = WM_VSCROLL;
  997. uCurrentScrollbar = SB_VERT;
  998. sb = &sw->sbarVert;
  999. //get the total area of the normal Horz scrollbar area
  1000. GetVScrollRect(sw, hwnd, &rect);
  1001. uCurrentScrollPortion = GetVertPortion(sb, hwnd, &rect, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
  1002. }
  1003. //
  1004. // NORMAL PROCESSING
  1005. //
  1006. else
  1007. {
  1008. uCurrentScrollPortion = HTSCROLL_NONE;
  1009. return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam) :
  1010. CallWindowProcA(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam);
  1011. }
  1012. //
  1013. // we can now share the same code for vertical
  1014. // and horizontal scrollbars
  1015. //
  1016. switch (uCurrentScrollPortion)
  1017. {
  1018. //inserted buttons to the left/right
  1019. case HTSCROLL_THUMB:
  1020. //if the scrollbar is disabled, then do no further processing
  1021. if (!IsScrollbarActive(sb))
  1022. return 0;
  1023. GetRealScrollRect(sb, &rect);
  1024. RotateRect0(sb, &rect);
  1025. CalcThumbSize(sb, &rect, &nThumbSize, &nThumbPos);
  1026. RotateRect0(sb, &rect);
  1027. //remember the bounding rectangle of the scrollbar work area
  1028. rcThumbBounds = rect;
  1029. sw->fThumbTracking = TRUE;
  1030. sb->scrollInfo.nTrackPos = sb->scrollInfo.nPos;
  1031. if (wParam == HTVSCROLL)
  1032. nThumbMouseOffset = pt.y - nThumbPos;
  1033. else
  1034. nThumbMouseOffset = pt.x - nThumbPos;
  1035. nLastPos = -sb->scrollInfo.nPos;
  1036. nThumbPos0 = nThumbPos;
  1037. //if(sb->fFlatScrollbar)
  1038. //{
  1039. GetWindowRect(hwnd, &winrect);
  1040. OffsetRect(&rect, -winrect.left, -winrect.top);
  1041. hdc = GetWindowDC(hwnd);
  1042. NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_THUMB);
  1043. ReleaseDC(hwnd, hdc);
  1044. //}
  1045. break;
  1046. //Any part of the scrollbar
  1047. case HTSCROLL_LEFT:
  1048. if (sb->fScrollFlags & ESB_DISABLE_LEFT) return 0;
  1049. else goto target1;
  1050. case HTSCROLL_RIGHT:
  1051. if (sb->fScrollFlags & ESB_DISABLE_RIGHT) return 0;
  1052. else goto target1;
  1053. goto target1;
  1054. case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
  1055. target1:
  1056. //if the scrollbar is disabled, then do no further processing
  1057. if (!IsScrollbarActive(sb))
  1058. break;
  1059. //ajust the horizontal rectangle to NOT include
  1060. //any inserted buttons
  1061. GetRealScrollRect(sb, &rect);
  1062. SendScrollMessage(hwnd, uScrollTimerMsg, uCurrentScrollPortion, 0);
  1063. // Check what area the mouse is now over :
  1064. // If the scroll thumb has moved under the mouse in response to
  1065. // a call to SetScrollPos etc, then we don't hilight the scrollbar margin
  1066. if (uCurrentScrollbar == SB_HORZ)
  1067. uScrollTimerPortion = GetHorzScrollPortion(sb, hwnd, &rect, pt.x, pt.y);
  1068. else
  1069. uScrollTimerPortion = GetVertScrollPortion(sb, hwnd, &rect, pt.x, pt.y);
  1070. GetWindowRect(hwnd, &winrect);
  1071. OffsetRect(&rect, -winrect.left, -winrect.top);
  1072. hdc = GetWindowDC(hwnd);
  1073. //if we aren't hot-tracking, then don't highlight
  1074. //the scrollbar thumb unless we click on it
  1075. if (uScrollTimerPortion == HTSCROLL_THUMB)
  1076. uScrollTimerPortion = HTSCROLL_NONE;
  1077. NCDrawScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
  1078. ReleaseDC(hwnd, hdc);
  1079. //Post the scroll message!!!!
  1080. uScrollTimerPortion = uCurrentScrollPortion;
  1081. //set a timer going on the first click.
  1082. //if this one expires, then we can start off a more regular timer
  1083. //to generate the auto-scroll behaviour
  1084. uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID1, COOLSB_TIMERINTERVAL1, 0);
  1085. sw->update();
  1086. break;
  1087. default:
  1088. return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam) :
  1089. CallWindowProcA(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam);
  1090. //return 0;
  1091. }
  1092. SetCapture(hwnd);
  1093. return 0;
  1094. }
  1095. //
  1096. // Left button released
  1097. //
  1098. static LRESULT LButtonUp(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
  1099. {
  1100. RECT rect;
  1101. POINT pt;
  1102. RECT winrect;
  1103. //current scrollportion is the button that we clicked down on
  1104. if (uCurrentScrollPortion != HTSCROLL_NONE)
  1105. {
  1106. SCROLLBAR *sb = &sw->sbarHorz;
  1107. lParam = GetMessagePos();
  1108. ReleaseCapture();
  1109. GetWindowRect(hwnd, &winrect);
  1110. pt.x = GET_X_LPARAM(lParam);
  1111. pt.y = GET_Y_LPARAM(lParam);
  1112. //emulate the mouse input on a scrollbar here...
  1113. if (uCurrentScrollbar == SB_HORZ)
  1114. {
  1115. //get the total area of the normal Horz scrollbar area
  1116. sb = &sw->sbarHorz;
  1117. GetHScrollRect(sw, hwnd, &rect);
  1118. }
  1119. else if (uCurrentScrollbar == SB_VERT)
  1120. {
  1121. //get the total area of the normal Horz scrollbar area
  1122. sb = &sw->sbarVert;
  1123. GetVScrollRect(sw, hwnd, &rect);
  1124. }
  1125. //we need to do different things depending on if the
  1126. //user is activating the scrollbar itself, or one of
  1127. //the inserted buttons
  1128. switch (uCurrentScrollPortion)
  1129. {
  1130. //The scrollbar is active
  1131. case HTSCROLL_LEFT: case HTSCROLL_RIGHT:
  1132. case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
  1133. case HTSCROLL_NONE:
  1134. KillTimer(hwnd, uScrollTimerId);
  1135. case HTSCROLL_THUMB:
  1136. sw->update();
  1137. //In case we were thumb tracking, make sure we stop NOW
  1138. if (sw->fThumbTracking == TRUE)
  1139. {
  1140. SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBPOSITION, nLastPos);
  1141. sw->fThumbTracking = FALSE;
  1142. }
  1143. //send the SB_ENDSCROLL message now that scrolling has finished
  1144. SendScrollMessage(hwnd, uScrollTimerMsg, SB_ENDSCROLL, 0);
  1145. //adjust the total scroll area to become where the scrollbar
  1146. //really is (take into account the inserted buttons)
  1147. GetRealScrollRect(sb, &rect);
  1148. OffsetRect(&rect, -winrect.left, -winrect.top);
  1149. HDC hdc = GetWindowDC(hwnd);
  1150. //draw whichever scrollbar sb is
  1151. NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NORMAL);
  1152. ReleaseDC(hwnd, hdc);
  1153. break;
  1154. }
  1155. //reset our state to default
  1156. uCurrentScrollPortion = HTSCROLL_NONE;
  1157. uScrollTimerPortion = HTSCROLL_NONE;
  1158. uScrollTimerId = 0;
  1159. uScrollTimerMsg = 0;
  1160. uCurrentScrollbar = COOLSB_NONE;
  1161. return 0;
  1162. }
  1163. else
  1164. {
  1165. /*
  1166. // Can't remember why I did this!
  1167. if(GetCapture() == hwnd)
  1168. {
  1169. ReleaseCapture();
  1170. }*/
  1171. }
  1172. //sw->update();
  1173. return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_LBUTTONUP, wParam, lParam) :
  1174. CallWindowProcA(sw->oldproc, hwnd, WM_LBUTTONUP, wParam, lParam);
  1175. }
  1176. //
  1177. // This function is called whenever the mouse is moved and
  1178. // we are dragging the scrollbar thumb about.
  1179. //
  1180. static LRESULT ThumbTrackHorz(SCROLLBAR *sbar, HWND hwnd, int x, int y)
  1181. {
  1182. POINT pt;
  1183. RECT rc, winrect, rc2;
  1184. COLORREF crCheck1 = GetSBForeColor();
  1185. COLORREF crCheck2 = GetSBBackColor();
  1186. HDC hdc;
  1187. int thumbpos = nThumbPos;
  1188. int pos;
  1189. int siMaxMin = 0;
  1190. UINT flatflag = sbar->fFlatScrollbar ? BF_FLAT : 0;
  1191. BOOL fCustomDraw = FALSE;
  1192. SCROLLINFO *si;
  1193. si = &sbar->scrollInfo;
  1194. pt.x = x;
  1195. pt.y = y;
  1196. //draw the thumb at whatever position
  1197. rc = rcThumbBounds;
  1198. SetRect(&rc2, rc.left - THUMBTRACK_SNAPDIST*2, rc.top - THUMBTRACK_SNAPDIST,
  1199. rc.right + THUMBTRACK_SNAPDIST*2, rc.bottom + THUMBTRACK_SNAPDIST);
  1200. rc.left += GetScrollMetric(sbar, SM_CXHORZSB);
  1201. rc.right -= GetScrollMetric(sbar, SM_CXHORZSB);
  1202. //if the mouse is not in a suitable distance of the scrollbar,
  1203. //then "snap" the thumb back to its initial position
  1204. #ifdef SNAP_THUMB_BACK
  1205. if (!PtInRect(&rc2, pt))
  1206. {
  1207. thumbpos = nThumbPos0;
  1208. }
  1209. //otherwise, move the thumb to where the mouse is
  1210. else
  1211. #endif //SNAP_THUMB_BACK
  1212. {
  1213. //keep the thumb within the scrollbar limits
  1214. thumbpos = pt.x - nThumbMouseOffset;
  1215. if (thumbpos < rc.left) thumbpos = rc.left;
  1216. if (thumbpos > rc.right - nThumbSize) thumbpos = rc.right - nThumbSize;
  1217. }
  1218. GetWindowRect(hwnd, &winrect);
  1219. if (sbar->nBarType == SB_VERT)
  1220. RotateRect(&winrect);
  1221. hdc = GetWindowDC(hwnd);
  1222. OffsetRect(&rc, -winrect.left, -winrect.top);
  1223. thumbpos -= winrect.left;
  1224. //draw the margin before the thumb
  1225. SetRect(&rc2, rc.left, rc.top, thumbpos, rc.bottom);
  1226. RotateRect0(sbar, &rc2);
  1227. if (fCustomDraw)
  1228. PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_PAGELEFT, 0, 0, 0);
  1229. else
  1230. DrawCheckedRect(hdc, &rc2, crCheck1, crCheck2);
  1231. RotateRect0(sbar, &rc2);
  1232. //draw the margin after the thumb
  1233. SetRect(&rc2, thumbpos + nThumbSize, rc.top, rc.right, rc.bottom);
  1234. RotateRect0(sbar, &rc2);
  1235. if (fCustomDraw)
  1236. PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_PAGERIGHT, 0, 0, 0);
  1237. else
  1238. DrawCheckedRect(hdc, &rc2, crCheck1, crCheck2);
  1239. RotateRect0(sbar, &rc2);
  1240. //finally draw the thumb itelf. This is how it looks on win2000, anyway
  1241. SetRect(&rc2, thumbpos, rc.top, thumbpos + nThumbSize, rc.bottom);
  1242. RotateRect0(sbar, &rc2);
  1243. if (fCustomDraw)
  1244. PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_THUMBTRACK, TRUE, TRUE, FALSE);
  1245. else
  1246. {
  1247. DrawBlankButton(hdc, &rc2, flatflag, 1, sbar->nBarType == SB_VERT);
  1248. }
  1249. RotateRect0(sbar, &rc2);
  1250. ReleaseDC(hwnd, hdc);
  1251. //post a SB_TRACKPOS message!!!
  1252. siMaxMin = si->nMax - si->nMin;
  1253. if (siMaxMin > 0)
  1254. pos = MulDiv(thumbpos - rc.left, siMaxMin - si->nPage + 1, rc.right - rc.left - nThumbSize);
  1255. else
  1256. pos = thumbpos - rc.left;
  1257. if (pos != nLastPos)
  1258. {
  1259. if (sbar->flags & SCROLLBAR_LISTVIEW)
  1260. {
  1261. // only for listviews
  1262. if (sbar->nBarType == SB_HORZ)
  1263. {
  1264. SCROLLINFO info;
  1265. info.cbSize = sizeof(SCROLLINFO);
  1266. info.fMask = SIF_TRACKPOS;
  1267. if (GetScrollInfo(hwnd, SB_HORZ, &info))
  1268. {
  1269. int nPos = info.nTrackPos;
  1270. SendMessage(hwnd, LVM_SCROLL, pos - nPos, 0);
  1271. SetScrollInfo(hwnd, sbar->nBarType, &info, FALSE);
  1272. }
  1273. }
  1274. else if (sbar->nBarType == SB_VERT)
  1275. {
  1276. SCROLLINFO info;
  1277. info.cbSize = sizeof(SCROLLINFO);
  1278. info.fMask = SIF_TRACKPOS;
  1279. if (GetScrollInfo(hwnd, SB_VERT, &info))
  1280. {
  1281. int nPos = info.nTrackPos;
  1282. SendMessage(hwnd, LVM_SCROLL, 0, (pos - nPos)*14); //BIG FUCKO: get the text height size
  1283. SetScrollInfo(hwnd, sbar->nBarType, &info, FALSE);
  1284. }
  1285. }
  1286. }
  1287. else
  1288. {
  1289. si->nTrackPos = pos;
  1290. SCROLLINFO info;
  1291. info.cbSize = sizeof(SCROLLINFO);
  1292. info.fMask = SIF_TRACKPOS;
  1293. info.nTrackPos = pos;
  1294. SetScrollInfo(hwnd, sbar->nBarType, &info, FALSE);
  1295. SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBTRACK, pos);
  1296. }
  1297. }
  1298. nLastPos = pos;
  1299. return 0;
  1300. }
  1301. //
  1302. // remember to rotate the thumb bounds rectangle!!
  1303. //
  1304. static LRESULT ThumbTrackVert(SCROLLBAR *sb, HWND hwnd, int x, int y)
  1305. {
  1306. //sw->swapcoords = TRUE;
  1307. RotateRect(&rcThumbBounds);
  1308. ThumbTrackHorz(sb, hwnd, y, x);
  1309. RotateRect(&rcThumbBounds);
  1310. //sw->swapcoords = FALSE;
  1311. return 0;
  1312. }
  1313. //
  1314. // Called when we have set the capture from the NCLButtonDown(...)
  1315. //
  1316. static LRESULT MouseMove(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
  1317. {
  1318. RECT rect;
  1319. POINT pt;
  1320. RECT winrect;
  1321. if (sw->fThumbTracking == TRUE)
  1322. {
  1323. int x, y;
  1324. lParam = GetMessagePos();
  1325. x = GET_X_LPARAM(lParam);
  1326. y = GET_Y_LPARAM(lParam);
  1327. if (uCurrentScrollbar == SB_HORZ)
  1328. return ThumbTrackHorz(&sw->sbarHorz, hwnd, x, y);
  1329. else if (uCurrentScrollbar == SB_VERT)
  1330. return ThumbTrackVert(&sw->sbarVert, hwnd, x, y);
  1331. }
  1332. if (uCurrentScrollPortion == HTSCROLL_NONE)
  1333. {
  1334. return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam) :
  1335. CallWindowProcA(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam);
  1336. }
  1337. else
  1338. {
  1339. LPARAM nlParam;
  1340. SCROLLBAR *sb = &sw->sbarHorz;
  1341. nlParam = GetMessagePos();
  1342. GetWindowRect(hwnd, &winrect);
  1343. pt.x = GET_X_LPARAM(nlParam);
  1344. pt.y = GET_Y_LPARAM(nlParam);
  1345. //emulate the mouse input on a scrollbar here...
  1346. if (uCurrentScrollbar == SB_HORZ)
  1347. {
  1348. sb = &sw->sbarHorz;
  1349. }
  1350. else if (uCurrentScrollbar == SB_VERT)
  1351. {
  1352. sb = &sw->sbarVert;
  1353. }
  1354. //get the total area of the normal scrollbar area
  1355. GetScrollRect(sw, sb->nBarType, hwnd, &rect);
  1356. //see if we clicked in the inserted buttons / normal scrollbar
  1357. //thisportion = GetPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam));
  1358. UINT thisportion = GetPortion(sb, hwnd, &rect, pt.x, pt.y);
  1359. //we need to do different things depending on if the
  1360. //user is activating the scrollbar itself, or one of
  1361. //the inserted buttons
  1362. static UINT lastportion = 0;
  1363. switch (uCurrentScrollPortion)
  1364. {
  1365. //The scrollbar is active
  1366. case HTSCROLL_LEFT: case HTSCROLL_RIGHT: case HTSCROLL_THUMB:
  1367. case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
  1368. case HTSCROLL_NONE:
  1369. //adjust the total scroll area to become where the scrollbar
  1370. //really is (take into account the inserted buttons)
  1371. GetRealScrollRect(sb, &rect);
  1372. OffsetRect(&rect, -winrect.left, -winrect.top);
  1373. HDC hdc = GetWindowDC(hwnd);
  1374. if (thisportion != uCurrentScrollPortion)
  1375. {
  1376. uScrollTimerPortion = HTSCROLL_NONE;
  1377. if (lastportion != thisportion)
  1378. NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NORMAL);
  1379. }
  1380. //otherwise, draw the button in its depressed / clicked state
  1381. else
  1382. {
  1383. uScrollTimerPortion = uCurrentScrollPortion;
  1384. if (lastportion != thisportion)
  1385. NCDrawScrollbar(sb, hwnd, hdc, &rect, thisportion);
  1386. }
  1387. ReleaseDC(hwnd, hdc);
  1388. break;
  1389. }
  1390. lastportion = thisportion;
  1391. //must return zero here, because we might get cursor anomilies
  1392. //CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam);
  1393. return 0;
  1394. }
  1395. }
  1396. //
  1397. // We must allocate from in the non-client area for our scrollbars
  1398. // Call the default window procedure first, to get the borders (if any)
  1399. // allocated some space, then allocate the space for the scrollbars
  1400. // if they fit
  1401. //
  1402. static LRESULT NCCalcSize(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
  1403. {
  1404. NCCALCSIZE_PARAMS *nccsp;
  1405. RECT *rect;
  1406. RECT oldrect;
  1407. //BOOL fCalcValidRects = (wParam == TRUE);
  1408. SCROLLBAR *sb;
  1409. LRESULT ret;
  1410. DWORD dwStyle;
  1411. //Regardless of the value of fCalcValidRects, the first rectangle
  1412. //in the array specified by the rgrc structure member of the
  1413. //NCCALCSIZE_PARAMS structure contains the coordinates of the window,
  1414. //so we can use the exact same code to modify this rectangle, when
  1415. //wParam is TRUE and when it is FALSE.
  1416. nccsp = (NCCALCSIZE_PARAMS *)lParam;
  1417. rect = &nccsp->rgrc[0];
  1418. oldrect = *rect;
  1419. dwStyle = GetWindowLong(hwnd, GWL_STYLE);
  1420. // TURN OFF SCROLL-STYLES.
  1421. if (dwStyle & (WS_VSCROLL | WS_HSCROLL))
  1422. {
  1423. sw->bPreventStyleChange = TRUE;
  1424. SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL | WS_HSCROLL));
  1425. }
  1426. //call the default procedure to get the borders allocated
  1427. ret = (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCCALCSIZE, wParam, lParam) :
  1428. CallWindowProcA(sw->oldproc, hwnd, WM_NCCALCSIZE, wParam, lParam);
  1429. // RESTORE PREVIOUS STYLES (if present at all)
  1430. if (dwStyle & (WS_VSCROLL | WS_HSCROLL))
  1431. {
  1432. SetWindowLong(hwnd, GWL_STYLE, dwStyle);
  1433. sw->bPreventStyleChange = FALSE;
  1434. }
  1435. // calculate what the size of each window border is,
  1436. sw->cxLeftEdge = rect->left - oldrect.left;
  1437. sw->cxRightEdge = oldrect.right - rect->right;
  1438. sw->cyTopEdge = rect->top - oldrect.top;
  1439. sw->cyBottomEdge = oldrect.bottom - rect->bottom;
  1440. sb = &sw->sbarHorz;
  1441. //if there is room, allocate some space for the horizontal scrollbar
  1442. //NOTE: Change the ">" to a ">=" to make the horz bar totally fill the
  1443. //window before disappearing
  1444. if ((sb->fScrollFlags & CSBS_VISIBLE) &&
  1445. #ifdef COOLSB_FILLWINDOW
  1446. rect->bottom - rect->top >= GetScrollMetric(sb, SM_CYHORZSB))
  1447. #else
  1448. rect->bottom - rect->top > GetScrollMetric(sb, SM_CYHORZSB))
  1449. #endif
  1450. {
  1451. rect->bottom -= GetScrollMetric(sb, SM_CYHORZSB);
  1452. sb->fScrollVisible = TRUE;
  1453. }
  1454. else
  1455. sb->fScrollVisible = FALSE;
  1456. sb = &sw->sbarVert;
  1457. //if there is room, allocate some space for the vertical scrollbar
  1458. if ((sb->fScrollFlags & CSBS_VISIBLE) &&
  1459. rect->right - rect->left >= GetScrollMetric(sb, SM_CXVERTSB))
  1460. {
  1461. if (sw->fLeftScrollbar)
  1462. rect->left += GetScrollMetric(sb, SM_CXVERTSB);
  1463. else
  1464. rect->right -= GetScrollMetric(sb, SM_CXVERTSB);
  1465. sb->fScrollVisible = TRUE;
  1466. }
  1467. else
  1468. sb->fScrollVisible = FALSE;
  1469. //don't return a value unless we actually modify the other rectangles
  1470. //in the NCCALCSIZE_PARAMS structure. In this case, we return 0
  1471. //no matter what the value of fCalcValidRects is
  1472. return ret;//FALSE;
  1473. }
  1474. //
  1475. // used for hot-tracking over the scroll buttons
  1476. //
  1477. static LRESULT NCMouseMove(ScrollWnd *sw, HWND hwnd, WPARAM wHitTest, LPARAM lParam)
  1478. {
  1479. //install a timer for the mouse-over events, if the mouse moves
  1480. //over one of the scrollbars
  1481. return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam) :
  1482. CallWindowProcA(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam);
  1483. }
  1484. //
  1485. // Timer routine to generate scrollbar messages
  1486. //
  1487. static LRESULT CoolSB_Timer(ScrollWnd *swnd, HWND hwnd, WPARAM wTimerId, LPARAM lParam)
  1488. {
  1489. //let all timer messages go past if we don't have a timer installed ourselves
  1490. if (uScrollTimerId == 0 && uMouseOverId == 0)
  1491. {
  1492. return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam) :
  1493. CallWindowProcA(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam);
  1494. }
  1495. //if the first timer goes off, then we can start a more
  1496. //regular timer interval to auto-generate scroll messages
  1497. //this gives a slight pause between first pressing the scroll arrow, and the
  1498. //actual scroll starting
  1499. if (wTimerId == COOLSB_TIMERID1)
  1500. {
  1501. KillTimer(hwnd, uScrollTimerId);
  1502. uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID2, COOLSB_TIMERINTERVAL2, 0);
  1503. return 0;
  1504. }
  1505. //send the scrollbar message repeatedly
  1506. else if (wTimerId == COOLSB_TIMERID2)
  1507. {
  1508. //need to process a spoof WM_MOUSEMOVE, so that
  1509. //we know where the mouse is each time the scroll timer goes off.
  1510. //This is so we can stop sending scroll messages if the thumb moves
  1511. //under the mouse.
  1512. POINT pt;
  1513. GetCursorPos(&pt);
  1514. ScreenToClient(hwnd, &pt);
  1515. MouseMove(swnd, hwnd, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
  1516. if (uScrollTimerPortion != HTSCROLL_NONE)
  1517. SendScrollMessage(hwnd, uScrollTimerMsg, uScrollTimerPortion, 0);
  1518. swnd->update();
  1519. return 0;
  1520. }
  1521. else
  1522. {
  1523. return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam) :
  1524. CallWindowProcA(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam);
  1525. }
  1526. }
  1527. //
  1528. // We must intercept any calls to SetWindowLong, to check if
  1529. // left-scrollbars are taking effect or not
  1530. //
  1531. static LRESULT CoolSB_StyleChange(ScrollWnd *swnd, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1532. {
  1533. STYLESTRUCT *ss = (STYLESTRUCT *)lParam;
  1534. if (wParam == GWL_EXSTYLE)
  1535. {
  1536. if (ss->styleNew & WS_EX_LEFTSCROLLBAR)
  1537. swnd->fLeftScrollbar = TRUE;
  1538. else
  1539. swnd->fLeftScrollbar = FALSE;
  1540. }
  1541. return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, msg, wParam, lParam) :
  1542. CallWindowProcA(swnd->oldproc, hwnd, msg, wParam, lParam);
  1543. }
  1544. static UINT curTool = -1;
  1545. static LRESULT CoolSB_Notify(ScrollWnd *swnd, HWND hwnd, WPARAM wParam, LPARAM lParam)
  1546. {
  1547. return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, WM_NOTIFY, wParam, lParam) :
  1548. CallWindowProcA(swnd->oldproc, hwnd, WM_NOTIFY, wParam, lParam);
  1549. }
  1550. static LRESULT SendToolTipMessage0(HWND hwndTT, UINT message, WPARAM wParam, LPARAM lParam)
  1551. {
  1552. return SendMessage(hwndTT, message, wParam, lParam);
  1553. }
  1554. #ifdef COOLSB_TOOLTIPS
  1555. #define SendToolTipMessage SendToolTipMessage0
  1556. #else
  1557. #define SendToolTipMessage 1 ? (void)0 : SendToolTipMessage0
  1558. #endif
  1559. //
  1560. // We must intercept any calls to SetWindowLong, to make sure that
  1561. // the user does not set the WS_VSCROLL or WS_HSCROLL styles
  1562. //
  1563. static LRESULT CoolSB_SetCursor(ScrollWnd *swnd, HWND hwnd, WPARAM wParam, LPARAM lParam)
  1564. {
  1565. return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam) :
  1566. CallWindowProcA(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam);
  1567. }
  1568. //
  1569. // CoolScrollbar subclass procedure.
  1570. // Handle all messages needed to mimick normal windows scrollbars
  1571. //
  1572. LRESULT CALLBACK CoolSBWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1573. {
  1574. WNDPROC oldproc;
  1575. ScrollWnd *swnd = GetScrollWndFromHwnd(hwnd);
  1576. if (!swnd || !swnd->oldproc)
  1577. {
  1578. return (IsWindowUnicode(hwnd)) ? DefWindowProcW(hwnd, message, wParam, lParam) :
  1579. DefWindowProcA(hwnd, message, wParam, lParam);
  1580. }
  1581. switch (message)
  1582. {
  1583. case WM_NCDESTROY:
  1584. //this should NEVER be called, because the user
  1585. //should have called Uninitialize() themselves.
  1586. //However, if the user tries to call Uninitialize()..
  1587. //after this window is destroyed, this window's entry in the lookup
  1588. //table will not be there, and the call will fail
  1589. oldproc = swnd->oldproc;
  1590. delete(swnd);
  1591. //we must call the original window procedure, otherwise it
  1592. //will never get the WM_NCDESTROY message, and it wouldn't
  1593. //be able to clean up etc.
  1594. return (IsWindowUnicode(hwnd)) ? CallWindowProcW(oldproc, hwnd, message, wParam, lParam) : CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
  1595. case WM_NCCALCSIZE:
  1596. return NCCalcSize(swnd, hwnd, wParam, lParam);
  1597. case WM_NCPAINT:
  1598. return NCPaint(swnd, hwnd, wParam, lParam);
  1599. case WM_NCHITTEST:
  1600. return NCHitTest(swnd, hwnd, wParam, lParam);
  1601. case WM_NCRBUTTONDOWN: case WM_NCRBUTTONUP:
  1602. case WM_NCMBUTTONDOWN: case WM_NCMBUTTONUP:
  1603. if (wParam == HTHSCROLL || wParam == HTVSCROLL)
  1604. return 0;
  1605. else
  1606. break;
  1607. case WM_NCLBUTTONDBLCLK:
  1608. //TRACE("WM_NCLBUTTONDBLCLK %d\n", count++);
  1609. if (wParam == HTHSCROLL || wParam == HTVSCROLL)
  1610. return NCLButtonDown(swnd, hwnd, wParam, lParam);
  1611. else
  1612. break;
  1613. case WM_NCLBUTTONDOWN:
  1614. //TRACE("WM_NCLBUTTONDOWN%d\n", count++);
  1615. return NCLButtonDown(swnd, hwnd, wParam, lParam);
  1616. case WM_LBUTTONUP:
  1617. //TRACE("WM_LBUTTONUP %d\n", count++);
  1618. return LButtonUp(swnd, hwnd, wParam, lParam);
  1619. case WM_NOTIFY:
  1620. return CoolSB_Notify(swnd, hwnd, wParam, lParam);
  1621. //Mouse moves are received when we set the mouse capture,
  1622. //even when the mouse moves over the non-client area
  1623. case WM_MOUSEMOVE:
  1624. //TRACE("WM_MOUSEMOVE %d\n", count++);
  1625. return MouseMove(swnd, hwnd, wParam, lParam);
  1626. case WM_TIMER:
  1627. return CoolSB_Timer(swnd, hwnd, wParam, lParam);
  1628. //case WM_STYLECHANGING:
  1629. // return CoolSB_StyleChange(swnd, hwnd, WM_STYLECHANGING, wParam, lParam);
  1630. case WM_STYLECHANGED:
  1631. if (swnd->bPreventStyleChange)
  1632. {
  1633. // the NCPAINT handler has told us to eat this message!
  1634. return 0;
  1635. }
  1636. else
  1637. {
  1638. if (message == WM_STYLECHANGED)
  1639. return CoolSB_StyleChange(swnd, hwnd, WM_STYLECHANGED, wParam, lParam);
  1640. }
  1641. break;
  1642. case WM_NCMOUSEMOVE:
  1643. {
  1644. static LPARAM lastpos = -1;
  1645. //TRACE("WM_NCMOUSEMOVE %d\n", count++);
  1646. //The problem with NCMOUSEMOVE is that it is sent continuously
  1647. //even when the mouse is stationary (under win2000 / win98)
  1648. //
  1649. //Tooltips don't like being sent a continous stream of mouse-moves
  1650. //if the cursor isn't moving, because they will think that the mouse
  1651. //is moving position, and the internal timer will never expire
  1652. //
  1653. if (lastpos != lParam)
  1654. {
  1655. lastpos = lParam;
  1656. }
  1657. }
  1658. return NCMouseMove(swnd, hwnd, wParam, lParam);
  1659. case WM_SETCURSOR:
  1660. return CoolSB_SetCursor(swnd, hwnd, wParam, lParam);
  1661. case WM_CAPTURECHANGED:
  1662. break;
  1663. case WM_ERASEBKGND:
  1664. if (swnd && !swnd->fThumbTracking && uCurrentScrollPortion == HTSCROLL_NONE)
  1665. {
  1666. //disable windows scrollbar painting (fixes gfx repainting weirdness)
  1667. int style = GetWindowLong(hwnd, GWL_STYLE);
  1668. if (style&(WS_HSCROLL | WS_VSCROLL))
  1669. {
  1670. SetWindowLong(hwnd, GWL_STYLE, style&~(WS_HSCROLL | WS_VSCROLL));
  1671. }
  1672. LRESULT ret = (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, message, wParam, lParam) :
  1673. CallWindowProcA(swnd->oldproc, hwnd, message, wParam, lParam);
  1674. swnd->update();
  1675. return ret;
  1676. }
  1677. break;
  1678. //needed if we want mousewheel to work properly because we disable the styles in WM_ERASEBKGND...
  1679. case WM_MOUSEWHEEL:
  1680. {
  1681. int style = GetWindowLong(hwnd, GWL_STYLE);
  1682. swnd->bPreventStyleChange = TRUE;
  1683. SetWindowLong(hwnd, GWL_STYLE, style | (swnd->sbarHorz.fScrollVisible ? WS_HSCROLL : 0) | (swnd->sbarVert.fScrollVisible ? WS_VSCROLL : 0));
  1684. LRESULT ret = (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, message, wParam, lParam) :
  1685. CallWindowProcA(swnd->oldproc, hwnd, message, wParam, lParam);
  1686. SetWindowLongPtr(hwnd, GWL_STYLE, style);
  1687. swnd->bPreventStyleChange = FALSE;
  1688. return ret;
  1689. }
  1690. case WM_USER + 0x3443: //manually sent by other windows (like columns header for ex.)
  1691. if (swnd) swnd->update();
  1692. break;
  1693. default:
  1694. break;
  1695. }
  1696. return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, message, wParam, lParam) :
  1697. CallWindowProcA(swnd->oldproc, hwnd, message, wParam, lParam);
  1698. }
  1699. SCROLLBAR *GetScrollBarFromHwnd(HWND hwnd, UINT nBar)
  1700. {
  1701. ScrollWnd *sw = GetScrollWndFromHwnd(hwnd);
  1702. if (!sw) return 0;
  1703. if (nBar == SB_HORZ)
  1704. return &sw->sbarHorz;
  1705. else if (nBar == SB_VERT)
  1706. return &sw->sbarVert;
  1707. else
  1708. return 0;
  1709. }
  1710. //
  1711. // return the default minimum size of a scrollbar thumb
  1712. //
  1713. int WINAPI CoolSB_GetDefaultMinThumbSize(void)
  1714. {
  1715. DWORD dwVersion = GetVersion();
  1716. // set the minimum thumb size for a scrollbar. This
  1717. // differs between NT4 and 2000, so need to check to see
  1718. // which platform we are running under
  1719. if (dwVersion < 0x80000000) // Windows NT/2000
  1720. {
  1721. if (LOBYTE(LOWORD(dwVersion)) >= 5)
  1722. return MINTHUMBSIZE_2000;
  1723. else
  1724. return MINTHUMBSIZE_NT4;
  1725. }
  1726. else
  1727. {
  1728. return MINTHUMBSIZE_NT4;
  1729. }
  1730. }
  1731. //
  1732. // Set the minimum size, in pixels, that the thumb box will shrink to.
  1733. //
  1734. BOOL WINAPI CoolSB_SetMinThumbSize(HWND hwnd, UINT wBar, UINT size)
  1735. {
  1736. SCROLLBAR *sbar;
  1737. if (!GetScrollWndFromHwnd(hwnd))
  1738. return FALSE;
  1739. if (size == -1)
  1740. size = CoolSB_GetDefaultMinThumbSize();
  1741. if ((wBar == SB_HORZ || wBar == SB_BOTH) &&
  1742. (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
  1743. {
  1744. sbar->nMinThumbSize = size;
  1745. }
  1746. if ((wBar == SB_VERT || wBar == SB_BOTH) &&
  1747. (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
  1748. {
  1749. sbar->nMinThumbSize = size;
  1750. }
  1751. return TRUE;
  1752. }
  1753. static void RedrawNonClient(HWND hwnd, BOOL fFrameChanged)
  1754. {
  1755. if (fFrameChanged == FALSE)
  1756. {
  1757. SendMessage(hwnd, WM_NCPAINT, (WPARAM)1, 0);
  1758. }
  1759. else
  1760. {
  1761. SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE
  1762. | SWP_FRAMECHANGED | SWP_DRAWFRAME);
  1763. }
  1764. }
  1765. ScrollWnd::ScrollWnd(HWND hwnd, int flags)
  1766. {
  1767. SCROLLINFO *si;
  1768. RECT rect;
  1769. DWORD dwCurStyle;
  1770. bars = 0;
  1771. oldproc = NULL;
  1772. memset(&sbarHorz, 0, sizeof(sbarHorz));
  1773. memset(&sbarVert, 0, sizeof(sbarVert));
  1774. sbarHorz.flags = flags;
  1775. sbarVert.flags = flags;
  1776. fThumbTracking = 0;
  1777. fLeftScrollbar = 0;
  1778. cxLeftEdge = cxRightEdge = cyTopEdge = cyBottomEdge = 0;
  1779. bPreventStyleChange = 0;
  1780. m_disable_hscroll = 0;
  1781. m_xp_theme_disabled = 0;
  1782. m_hwnd = hwnd;
  1783. GetClientRect(hwnd, &rect);
  1784. si = &sbarHorz.scrollInfo;
  1785. si->cbSize = sizeof(SCROLLINFO);
  1786. si->fMask = SIF_ALL;
  1787. GetScrollInfo(hwnd, SB_HORZ, si);
  1788. si = &sbarVert.scrollInfo;
  1789. si->cbSize = sizeof(SCROLLINFO);
  1790. si->fMask = SIF_ALL;
  1791. GetScrollInfo(hwnd, SB_VERT, si);
  1792. //check to see if the window has left-aligned scrollbars
  1793. if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR)
  1794. fLeftScrollbar = TRUE;
  1795. else
  1796. fLeftScrollbar = FALSE;
  1797. dwCurStyle = GetWindowLong(hwnd, GWL_STYLE);
  1798. SetProp(hwnd, szPropStr, (HANDLE)this);
  1799. //scrollbars will automatically get enabled, even if
  1800. //they aren't to start with....sorry, but there isn't an
  1801. //easy alternative.
  1802. if (dwCurStyle & WS_HSCROLL)
  1803. sbarHorz.fScrollFlags = CSBS_VISIBLE;
  1804. if (dwCurStyle & WS_VSCROLL)
  1805. sbarVert.fScrollFlags = CSBS_VISIBLE;
  1806. //need to be able to distinguish between horizontal and vertical
  1807. //scrollbars in some instances
  1808. sbarHorz.nBarType = SB_HORZ;
  1809. sbarVert.nBarType = SB_VERT;
  1810. sbarHorz.fFlatScrollbar = CSBS_NORMAL;
  1811. sbarVert.fFlatScrollbar = CSBS_NORMAL;
  1812. //set the default arrow sizes for the scrollbars
  1813. sbarHorz.nArrowLength = SYSTEM_METRIC;
  1814. sbarHorz.nArrowWidth = SYSTEM_METRIC;
  1815. sbarVert.nArrowLength = SYSTEM_METRIC;
  1816. sbarVert.nArrowWidth = SYSTEM_METRIC;
  1817. bPreventStyleChange = FALSE;
  1818. fWndUnicode = IsWindowUnicode(hwnd);
  1819. oldproc = (WNDPROC)(LONG_PTR) ((fWndUnicode) ? SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)CoolSBWndProc) :
  1820. SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)CoolSBWndProc));
  1821. CoolSB_SetMinThumbSize(hwnd, SB_BOTH, CoolSB_GetDefaultMinThumbSize());
  1822. //send the window a frame changed message to update the scrollbars
  1823. RedrawNonClient(hwnd, TRUE);
  1824. //disable XP styles
  1825. if (SetWindowTheme && !m_xp_theme_disabled)
  1826. {
  1827. SetWindowTheme(m_hwnd, L" ", L" ");
  1828. m_xp_theme_disabled = 1;
  1829. }
  1830. }
  1831. BOOL WINAPI CoolSB_ShowScrollBar(HWND hwnd, int wBar, BOOL fShow)
  1832. {
  1833. SCROLLBAR *sbar;
  1834. BOOL bFailed = FALSE;
  1835. DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
  1836. if ((wBar == SB_HORZ || wBar == SB_BOTH) &&
  1837. (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
  1838. {
  1839. sbar->fScrollFlags = sbar->fScrollFlags & ~CSBS_VISIBLE;
  1840. sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0);
  1841. //bFailed = TRUE;
  1842. if (fShow) SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_HSCROLL);
  1843. else SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~WS_HSCROLL);
  1844. }
  1845. if ((wBar == SB_VERT || wBar == SB_BOTH) &&
  1846. (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
  1847. {
  1848. sbar->fScrollFlags = sbar->fScrollFlags & ~CSBS_VISIBLE;
  1849. sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0);
  1850. //bFailed = TRUE;
  1851. if (fShow) SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_VSCROLL);
  1852. else SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~WS_VSCROLL);
  1853. }
  1854. if (bFailed)
  1855. {
  1856. return FALSE;
  1857. }
  1858. else
  1859. {
  1860. SetWindowPos(hwnd, 0, 0, 0, 0, 0,
  1861. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
  1862. SWP_NOACTIVATE | SWP_FRAMECHANGED);
  1863. return TRUE;
  1864. }
  1865. }
  1866. ScrollWnd::~ScrollWnd()
  1867. {
  1868. if (oldproc)
  1869. {
  1870. ((fWndUnicode) ? SetWindowLongPtrW(m_hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)oldproc) :
  1871. SetWindowLongPtrA(m_hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)oldproc));
  1872. }
  1873. RemoveProp(m_hwnd, szPropStr);
  1874. RedrawNonClient(m_hwnd, TRUE);
  1875. }
  1876. void ScrollWnd::update()
  1877. {
  1878. int dohorz = 0, dovert = 0;
  1879. SCROLLINFO tsi = {sizeof(SCROLLINFO), SIF_ALL, };
  1880. if (!m_disable_hscroll)
  1881. {
  1882. GetScrollInfo(m_hwnd, SB_HORZ, &tsi);
  1883. if (memcmp(&tsi, &sbarHorz.scrollInfo, sizeof(SCROLLINFO)))
  1884. {
  1885. memcpy(&sbarHorz.scrollInfo, &tsi, sizeof(SCROLLINFO));
  1886. dohorz = 1;
  1887. }
  1888. }
  1889. GetScrollInfo(m_hwnd, SB_VERT, &tsi);
  1890. if (memcmp(&tsi, &sbarVert.scrollInfo, sizeof(SCROLLINFO)))
  1891. {
  1892. memcpy(&sbarVert.scrollInfo, &tsi, sizeof(SCROLLINFO));
  1893. dovert = 1;
  1894. }
  1895. BOOL fRecalcFrame = FALSE;
  1896. if (dohorz) updatesb(SB_HORZ, &fRecalcFrame);
  1897. if (dovert) updatesb(SB_VERT, &fRecalcFrame);
  1898. if (dohorz || dovert) RedrawNonClient(m_hwnd, fRecalcFrame);
  1899. }
  1900. void ScrollWnd::updatesb(int fnBar, BOOL *fRecalcFrame)
  1901. {
  1902. SCROLLBAR *sbar = (fnBar == SB_HORZ ? &sbarHorz : &sbarVert);
  1903. SCROLLINFO *mysi = &sbar->scrollInfo;
  1904. if (mysi->nPage > (UINT)mysi->nMax
  1905. || (mysi->nPage == (UINT)mysi->nMax && mysi->nMax == 0)
  1906. || mysi->nMax <= mysi->nMin)
  1907. {
  1908. if (sbar->fScrollVisible)
  1909. {
  1910. CoolSB_ShowScrollBar(m_hwnd, fnBar, FALSE);
  1911. *fRecalcFrame = TRUE;
  1912. }
  1913. }
  1914. else
  1915. {
  1916. if (!sbar->fScrollVisible && mysi->nPage > 0)
  1917. {
  1918. CoolSB_ShowScrollBar(m_hwnd, fnBar, TRUE);
  1919. *fRecalcFrame = TRUE;
  1920. }
  1921. else if (sbar->fScrollVisible && mysi->nPage == 0)
  1922. {
  1923. CoolSB_ShowScrollBar(m_hwnd, fnBar, FALSE);
  1924. *fRecalcFrame = TRUE;
  1925. }
  1926. }
  1927. }
  1928. void ScrollWnd::disableHorzScroll()
  1929. {
  1930. m_disable_hscroll = 1;
  1931. sbarHorz.fScrollFlags = 0;
  1932. }
  1933. #if 0 // unused
  1934. int ScrollWnd::setScrollInfo(int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw)
  1935. {
  1936. SCROLLINFO *mysi;
  1937. SCROLLBAR *sbar;
  1938. BOOL fRecalcFrame = FALSE;
  1939. if (!lpsi)
  1940. return FALSE;
  1941. if (fnBar == SB_HORZ) mysi = &sbarHorz.scrollInfo;
  1942. else mysi = &sbarVert.scrollInfo;
  1943. if (lpsi->fMask & SIF_RANGE)
  1944. {
  1945. mysi->nMin = lpsi->nMin;
  1946. mysi->nMax = lpsi->nMax;
  1947. }
  1948. //The nPage member must specify a value from 0 to nMax - nMin +1.
  1949. if (lpsi->fMask & SIF_PAGE)
  1950. {
  1951. UINT t = (UINT)(mysi->nMax - mysi->nMin + 1);
  1952. mysi->nPage = min(max(0, lpsi->nPage), t);
  1953. }
  1954. //The nPos member must specify a value between nMin and nMax - max(nPage - 1, 0).
  1955. if (lpsi->fMask & SIF_POS)
  1956. {
  1957. mysi->nPos = max(lpsi->nPos, mysi->nMin);
  1958. mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0));
  1959. }
  1960. sbar = GetScrollBarFromHwnd(m_hwnd, fnBar);
  1961. if ((lpsi->fMask & SIF_DISABLENOSCROLL) || (sbar->fScrollFlags & CSBS_THUMBALWAYS))
  1962. {
  1963. if (!sbar->fScrollVisible)
  1964. {
  1965. CoolSB_ShowScrollBar(m_hwnd, fnBar, TRUE);
  1966. fRecalcFrame = TRUE;
  1967. }
  1968. }
  1969. else
  1970. {
  1971. if (mysi->nPage > (UINT)mysi->nMax
  1972. || mysi->nPage == (UINT)mysi->nMax && mysi->nMax == 0
  1973. || mysi->nMax <= mysi->nMin)
  1974. {
  1975. if (sbar->fScrollVisible)
  1976. {
  1977. CoolSB_ShowScrollBar(m_hwnd, fnBar, FALSE);
  1978. fRecalcFrame = TRUE;
  1979. }
  1980. }
  1981. else
  1982. {
  1983. if (!sbar->fScrollVisible)
  1984. {
  1985. CoolSB_ShowScrollBar(m_hwnd, fnBar, TRUE);
  1986. fRecalcFrame = TRUE;
  1987. }
  1988. }
  1989. }
  1990. if (fRedraw && !fThumbTracking)
  1991. RedrawNonClient(m_hwnd, fRecalcFrame);
  1992. return mysi->nPos;
  1993. }
  1994. #endif