1
0

skinnedscrollwnd.cpp 89 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285
  1. // some code taken from (freeware) Cool ScrollBar library by J Brown
  2. #include "./skinnedscrollwnd.h"
  3. #include "main.h"
  4. #include <commctrl.h>
  5. #include <windowsx.h>
  6. #include "../winamp/wa_dlg.h"
  7. #include "api__gen_ml.h"
  8. #include "./colors.h"
  9. #include <tataki/bitmap/bitmap.h>
  10. #include <tataki/bitmap/autobitmap.h>
  11. #include <tataki/canvas/canvas.h>
  12. #include <api/wnd/api_window.h>
  13. #include "./stockobjects.h"
  14. /* minimum size of scrollbar before inserted buttons are hidden to make room when the window is sized too small */
  15. #define MIN_COOLSB_SIZE 24
  16. /* min size of scrollbar when resizing a button, before the resize is stopped because the scrollbar has gotten too small */
  17. #define MINSCROLLSIZE 50
  18. /* a normal scrollbar "snaps" its scroll-thumb back into position if
  19. you move the mouse too far away from the window, whilst you are
  20. dragging the thumb, that is. #undeffing this results in the thumb
  21. never snapping back into position, no matter how far away you move
  22. the mouse */
  23. #define SNAP_THUMB_BACK
  24. /* distance (in pixels) the mouse must move away from the thumb
  25. during tracking to cause the thumb bar to snap back to its
  26. starting place. Has no effect unless SNAP_THUMB_BACK is defined */
  27. #define THUMBTRACK_SNAPDIST 128
  28. // To complement the exisiting SB_HORZ, SB_VERT, SB_BOTH
  29. // scrollbar identifiers
  30. #define COOLSB_NONE (-1)
  31. #define SB_INSBUT (-2)
  32. // Arrow size defines
  33. #define SYSTEM_METRIC (-1)
  34. // general scrollbar styles
  35. //
  36. // use the standard ESB_DISABLE_xxx flags to represent the
  37. // enabled / disabled states. (defined in winuser.h)
  38. //
  39. #define CSBS_THUMBALWAYS 0x0004
  40. #define CSBS_VISIBLE 0x0008
  41. #define CSBS_TRACKING 0x0010
  42. #define CSBS_FLATSB 0x0020
  43. #define CSBS_BTNVISBEFORE 0x0040 //if the buttons to the left are visible
  44. #define CSBS_BTNVISAFTER 0x0080 //if the buttons to the right are visible
  45. #define CSBS_HOVERING 0x0100 //if the buttons to the right are visible
  46. //cool scrollbar styles for Flat scrollbars
  47. #define CSBS_NORMAL 0
  48. #define CSBS_FLAT 1
  49. #define CSBS_HOTTRACKED 2
  50. // Button mask flags for indicating which members of SCROLLBUT
  51. // to use during a button insertion / modification
  52. #define SBBF_TYPE 0x0001
  53. #define SBBF_ID 0x0002
  54. #define SBBF_PLACEMENT 0x0004
  55. #define SBBF_SIZE 0x0008
  56. #define SBBF_BITMAP 0x0010
  57. #define SBBF_ENHMETAFILE 0x0020
  58. //#define SBBF_OWNERDRAW 0x0040 //unused at present
  59. #define SBBF_CURSOR 0x0080
  60. #define SBBF_BUTMINMAX 0x0100
  61. #define SBBF_STATE 0x0200
  62. //button styles (states)
  63. #define SBBS_NORMAL 0
  64. #define SBBS_PUSHED 1
  65. #define SBBS_CHECKED SBBS_PUSHED
  66. // scrollbar button types
  67. #define SBBT_PUSHBUTTON 1 //standard push button
  68. #define SBBT_TOGGLEBUTTON 2 //toggle button
  69. #define SBBT_FIXED 3 //fixed button (non-clickable)
  70. #define SBBT_FLAT 4 //blank area (flat, with border)
  71. #define SBBT_BLANK 5 //blank area (flat, no border)
  72. #define SBBT_DARK 6 //dark blank area (flat)
  73. #define SBBT_OWNERDRAW 7 //user draws the button via a WM_NOTIFY
  74. #define SBBT_MASK 0x1f //mask off low 5 bits
  75. //button type modifiers
  76. #define SBBM_RECESSED 0x0020 //recessed when clicked (like Word 97)
  77. #define SBBM_LEFTARROW 0x0040
  78. #define SBBM_RIGHTARROW 0x0080
  79. #define SBBM_UPARROW 0x0100
  80. #define SBBM_DOWNARROW 0x0200
  81. #define SBBM_RESIZABLE 0x0400
  82. #define SBBM_TYPE2 0x0800
  83. #define SBBM_TYPE3 0x1000
  84. #define SBBM_TOOLTIPS 0x2000 //currently unused (define COOLSB_TOOLTIPS in userdefs.h)
  85. //button placement flags
  86. #define SBBP_LEFT 1
  87. #define SBBP_RIGHT 2
  88. #define SBBP_TOP 1 //3
  89. #define SBBP_BOTTOM 2 //4
  90. #define DFCS_HOVER 0x800
  91. //
  92. // Button command notification codes
  93. // for sending with a WM_COMMAND message
  94. //
  95. #define CSBN_BASE 0
  96. #define CSBN_CLICKED (1 + CSBN_BASE)
  97. #define CSBN_HILIGHT (2 + CSBN_BASE)
  98. // Minimum size in pixels of a scrollbar thumb
  99. #define MINTHUMBSIZE_NT4 9
  100. #define MINTHUMBSIZE_2000 7
  101. //define some more hittest values for our cool-scrollbar
  102. #define HTSCROLL_LEFT (SB_LINELEFT)
  103. #define HTSCROLL_RIGHT (SB_LINERIGHT)
  104. #define HTSCROLL_UP (SB_LINEUP)
  105. #define HTSCROLL_DOWN (SB_LINEDOWN)
  106. #define HTSCROLL_THUMB (SB_THUMBTRACK)
  107. #define HTSCROLL_PAGEGUP (SB_PAGEUP)
  108. #define HTSCROLL_PAGEGDOWN (SB_PAGEDOWN)
  109. #define HTSCROLL_PAGELEFT (SB_PAGELEFT)
  110. #define HTSCROLL_PAGERIGHT (SB_PAGERIGHT)
  111. #define HTSCROLL_NONE (-1)
  112. #define HTSCROLL_NORMAL (-1)
  113. #define HTSCROLL_INSERTED (128)
  114. #define HTSCROLL_PRE (32 | HTSCROLL_INSERTED)
  115. #define HTSCROLL_POST (64 | HTSCROLL_INSERTED)
  116. // SCROLLBAR datatype. There are two of these structures per window
  117. typedef struct _SCROLLBAR
  118. {
  119. UINT fScrollFlags; //flags
  120. BOOL fScrollVisible; //if this scrollbar visible?
  121. SCROLLINFO scrollInfo; //positional data (range, position, page size etc)
  122. //data for inserted buttons
  123. int nButSizeBefore; //size to the left / above the bar
  124. int nButSizeAfter; //size to the right / below the bar
  125. int nMinThumbSize;
  126. int nBarType; //SB_HORZ / SB_VERT
  127. } SCROLLBAR;
  128. static WORD wCheckPat[8] =
  129. {
  130. 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555
  131. };
  132. // scrollwnd styles
  133. #define SWS_UPDATEFRAME 0x0001
  134. #define SWS_LEFT 0x0002
  135. #define SWS_DISABLENOSCROLL 0x0004
  136. #define SWS_HIDEHSCROLL 0x0008
  137. #define SWS_LISTVIEW 0x0010
  138. #define SWS_TREEVIEW 0x0020
  139. #define SWS_HIDEVSCROLL 0x0040
  140. #define SWS_COMBOLBOX 0x0080
  141. #define SWS_USEFREEFORM 0x0100
  142. //
  143. // PRIVATE INTERNAL FUNCTIONS
  144. //
  145. #define COOLSB_TIMERID1 65533 //initial timer
  146. #define COOLSB_TIMERID2 65534 //scroll message timer
  147. #define COOLSB_TIMERID3 -14 //mouse hover timer
  148. #define COOLSB_TIMERINTERVAL1 300
  149. #define COOLSB_TIMERINTERVAL2 55
  150. #define COOLSB_TIMERINTERVAL3 20 //mouse hover time
  151. //
  152. // direction: 0 - same axis as scrollbar (i.e. width of a horizontal bar)
  153. // 1 - perpendicular dimesion (i.e. height of a horizontal bar)
  154. //
  155. #define SM_CXVERTSB 1
  156. #define SM_CYVERTSB 0
  157. #define SM_CXHORZSB 0
  158. #define SM_CYHORZSB 1
  159. #define SM_SCROLL_WIDTH 1
  160. #define SM_SCROLL_LENGTH 0
  161. #ifndef WM_MOUSEWHEEL
  162. #define WM_MOUSEWHEEL 0x020A
  163. #endif
  164. #define INACTIVEBAR_ALPHA 127
  165. //
  166. // Special thumb-tracking variables
  167. //
  168. //
  169. static UINT uCurrentScrollbar = COOLSB_NONE; //SB_HORZ / SB_VERT
  170. static UINT uCurrentScrollPortion = HTSCROLL_NONE;
  171. static UINT uCurrentButton = 0;
  172. static RECT rcThumbBounds; //area that the scroll thumb can travel in
  173. static int nThumbSize; //(pixels)
  174. static int nThumbPos; //(pixels)
  175. static int nThumbMouseOffset; //(pixels)
  176. static int nLastPos = -1; //(scrollbar units)
  177. static int nThumbPos0; //(pixels) initial thumb position
  178. static int trackThumbPos;
  179. //
  180. // Temporary state used to auto-generate timer messages
  181. //
  182. static UINT uScrollTimerMsg = 0;
  183. static UINT uScrollTimerPortion = HTSCROLL_NONE;
  184. static UINT_PTR uScrollTimerId = 0;
  185. static HWND hwndCurCoolSB = 0;
  186. static INT bUseUpdateRgn = -1;
  187. static BOOL bDoHover=FALSE;
  188. static BOOL ignoreCaptureChange = FALSE;
  189. static BOOL captureSet = FALSE;
  190. static HBRUSH hbrChecked = NULL;
  191. #define GetSBForeColor() WADlg_getColor(WADLG_SCROLLBAR_FGCOLOR)
  192. #define GetSBBackColor() WADlg_getColor(WADLG_SCROLLBAR_BGCOLOR)
  193. // Send a WM_VSCROLL or WM_HSCROLL message
  194. #define SendScrollMessage(__hwnd, __srcMsg, __srcId, __pos) ::SendMessageW(__hwnd, __srcMsg, (MAKEWPARAM(__srcId, __pos)), 0)
  195. static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags);
  196. static void RenderBaseTexture(Canvas *canvas, const RECT *r, HWND hwnd)
  197. {
  198. // TODO: find the ifc_window * object for the media library container, and call renderBaseTexture on it
  199. if (WASABI_API_WND)
  200. {
  201. HWND checkWnd = GetParent(hwnd);
  202. while (checkWnd)
  203. {
  204. ifc_window *window = WASABI_API_WND->rootWndFromOSHandle(checkWnd);
  205. if (window && window->getRenderBaseTexture())
  206. {
  207. window->renderBaseTexture(canvas, r);
  208. return;
  209. }
  210. checkWnd = GetParent(checkWnd);
  211. }
  212. }
  213. // fallback code
  214. COLORREF bgcolor = WADlg_getColor(WADLG_WNDBG/*WADLG_SCROLLBAR_BGCOLOR*/);
  215. canvas->fillRect(r, bgcolor);
  216. }
  217. // swap the rectangle's x coords with its y coords
  218. static void __stdcall RotateRect(RECT *rect)
  219. {
  220. LONG temp;
  221. temp = rect->left;
  222. rect->left = rect->top;
  223. rect->top = temp;
  224. temp = rect->right;
  225. rect->right = rect->bottom;
  226. rect->bottom = temp;
  227. }
  228. // swap the coords if the scrollbar is a SB_VERT
  229. #define RotateRect0(__psb, __prc) ((__psb && __psb->nBarType == SB_VERT) ? RotateRect(__prc) : 0)
  230. static bool UseFreeformScrollbars()
  231. {
  232. if (config_use_ff_scrollbars && WASABI_API_SKIN && WASABI_API_SKIN->skin_isLoaded())
  233. {
  234. return WASABI_API_SKIN->skin_getVersion() >= 1.3;
  235. }
  236. else
  237. {
  238. return false;
  239. }
  240. }
  241. // Calculate if the SCROLLINFO members produce an enabled or disabled scrollbar
  242. static BOOL IsScrollInfoActive(SCROLLINFO *si)
  243. {
  244. return (si->nPage <= (UINT)si->nMax && si->nMax > si->nMin && si->nMax != 0);
  245. }
  246. // Return if the specified scrollbar is enabled or not
  247. static BOOL IsScrollbarActive(SCROLLBAR *sb)
  248. {
  249. return (((sb->fScrollFlags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ||
  250. !(sb->fScrollFlags & CSBS_THUMBALWAYS) && !IsScrollInfoActive(&sb->scrollInfo)) ? FALSE : TRUE;
  251. }
  252. enum
  253. {
  254. HORIZ_LEFT,
  255. HORIZ_LEFT_PRESSED,
  256. HORIZ_LEFT_HOVER,
  257. HORIZ_LEFT_INACTIVE,
  258. HORIZ_RIGHT,
  259. HORIZ_RIGHT_PRESSED,
  260. HORIZ_RIGHT_HOVER,
  261. HORIZ_RIGHT_INACTIVE,
  262. VERT_UP,
  263. VERT_UP_PRESSED,
  264. VERT_UP_HOVER,
  265. VERT_UP_INACTIVE,
  266. VERT_DOWN,
  267. VERT_DOWN_PRESSED,
  268. VERT_DOWN_HOVER,
  269. VERT_DOWN_INACTIVE,
  270. };
  271. static int GetBitmapEnum(UINT state, BOOL hover)
  272. {
  273. int offset=0;
  274. if (state&DFCS_PUSHED)
  275. offset=1;
  276. if (state&DFCS_INACTIVE)
  277. offset=3;
  278. else if (hover)
  279. offset=2;
  280. switch (state&3)
  281. {
  282. case DFCS_SCROLLRIGHT:
  283. return HORIZ_RIGHT+offset;
  284. case DFCS_SCROLLLEFT:
  285. return HORIZ_LEFT+offset;
  286. case DFCS_SCROLLDOWN:
  287. return VERT_DOWN+offset;
  288. default://case DFCS_SCROLLUP:
  289. return VERT_UP+offset;
  290. }
  291. }
  292. class ScrollBitmaps
  293. {
  294. public:
  295. ScrollBitmaps() : v_up(L"wasabi.scrollbar.vertical.background.top"),
  296. v_down(L"wasabi.scrollbar.vertical.background.bottom"),
  297. v_mid(L"wasabi.scrollbar.vertical.background.middle"),
  298. h_left(L"wasabi.scrollbar.horizontal.background.left"),
  299. h_mid(L"wasabi.scrollbar.horizontal.background.middle"),
  300. h_right(L"wasabi.scrollbar.horizontal.background.right")
  301. {
  302. }
  303. AutoSkinBitmap v_up, v_down, v_mid, h_left, h_mid, h_right;
  304. };
  305. static ScrollBitmaps *scrollBitmaps=0;
  306. void SkinnedScrollWnd_Init()
  307. {
  308. scrollBitmaps = new ScrollBitmaps();
  309. }
  310. void SkinnedScrollWnd_Quit()
  311. {
  312. if (scrollBitmaps)
  313. {
  314. delete scrollBitmaps;
  315. scrollBitmaps=0;
  316. }
  317. }
  318. static HBITMAP hbmpCachedDib = NULL;
  319. // Paint a checkered rectangle, with each alternate pixel being assigned a different colour
  320. static BOOL DrawFrameCtrl(HDC hdc, LPRECT lprc, UINT uType, UINT state, BOOL hover, BOOL freeform)
  321. {
  322. int startx, starty, alpha = 255;
  323. const wchar_t *bitmapid=0;
  324. const wchar_t *backgroundid=0;
  325. SkinBitmap *bg=0;
  326. switch (GetBitmapEnum(state, hover))
  327. {
  328. case HORIZ_LEFT:
  329. bitmapid = L"wasabi.scrollbar.horizontal.left";
  330. if (scrollBitmaps)
  331. bg=scrollBitmaps->h_left.getBitmap();
  332. startx = 0; starty = 45; break;
  333. case HORIZ_LEFT_PRESSED:
  334. bitmapid = L"wasabi.scrollbar.horizontal.left.pressed";
  335. if (scrollBitmaps)
  336. bg=scrollBitmaps->h_left.getBitmap();
  337. startx = 28; starty = 45; break;
  338. case HORIZ_LEFT_HOVER:
  339. bitmapid = L"wasabi.scrollbar.horizontal.left.hover";
  340. if (scrollBitmaps)
  341. bg=scrollBitmaps->h_left.getBitmap();
  342. startx = 0; starty = 45; break;
  343. case HORIZ_LEFT_INACTIVE:
  344. alpha = INACTIVEBAR_ALPHA;
  345. bitmapid = L"wasabi.scrollbar.horizontal.left";
  346. if (scrollBitmaps)
  347. bg=scrollBitmaps->h_left.getBitmap();
  348. startx = 0; starty = 45; break;
  349. case HORIZ_RIGHT:
  350. bitmapid = L"wasabi.scrollbar.horizontal.right";
  351. if (scrollBitmaps)
  352. bg=scrollBitmaps->h_right.getBitmap();
  353. startx = 14; starty = 45; break;
  354. case HORIZ_RIGHT_PRESSED:
  355. bitmapid = L"wasabi.scrollbar.horizontal.right.pressed";
  356. if (scrollBitmaps)
  357. bg=scrollBitmaps->h_right.getBitmap();
  358. startx = 42; starty = 45; break;
  359. case HORIZ_RIGHT_HOVER:
  360. bitmapid = L"wasabi.scrollbar.horizontal.right.hover";
  361. if (scrollBitmaps)
  362. bg=scrollBitmaps->h_right.getBitmap();
  363. startx = 14; starty = 45; break;
  364. case HORIZ_RIGHT_INACTIVE:
  365. alpha = INACTIVEBAR_ALPHA;
  366. bitmapid = L"wasabi.scrollbar.horizontal.right";
  367. if (scrollBitmaps)
  368. bg=scrollBitmaps->h_right.getBitmap();
  369. startx = 14; starty = 45; break;
  370. case VERT_UP:
  371. bitmapid = L"wasabi.scrollbar.vertical.left";
  372. if (scrollBitmaps)
  373. bg=scrollBitmaps->v_up.getBitmap();
  374. startx = 0; starty = 31; break;
  375. case VERT_UP_PRESSED:
  376. bitmapid = L"wasabi.scrollbar.vertical.left.pressed";
  377. if (scrollBitmaps)
  378. bg=scrollBitmaps->v_up.getBitmap();
  379. startx = 28; starty = 31; break;
  380. case VERT_UP_HOVER:
  381. bitmapid = L"wasabi.scrollbar.vertical.left.hover";
  382. if (scrollBitmaps)
  383. bg=scrollBitmaps->v_up.getBitmap();
  384. startx = 0; starty = 31; break;
  385. case VERT_UP_INACTIVE:
  386. alpha = INACTIVEBAR_ALPHA;
  387. bitmapid = L"wasabi.scrollbar.vertical.left";
  388. if (scrollBitmaps)
  389. bg=scrollBitmaps->v_up.getBitmap();
  390. startx = 0; starty = 31; break;
  391. case VERT_DOWN:
  392. bitmapid = L"wasabi.scrollbar.vertical.right";
  393. if (scrollBitmaps)
  394. bg=scrollBitmaps->v_down.getBitmap();
  395. startx = 14; starty = 31; break;
  396. case VERT_DOWN_PRESSED:
  397. bitmapid = L"wasabi.scrollbar.vertical.right.pressed";
  398. if (scrollBitmaps)
  399. bg=scrollBitmaps->v_down.getBitmap();
  400. startx = 42; starty = 31; break;
  401. case VERT_DOWN_HOVER:
  402. bitmapid = L"wasabi.scrollbar.vertical.right.hover";
  403. if (scrollBitmaps)
  404. bg=scrollBitmaps->v_down.getBitmap();
  405. startx = 14; starty = 31; break;
  406. case VERT_DOWN_INACTIVE:
  407. alpha = INACTIVEBAR_ALPHA;
  408. bitmapid = L"wasabi.scrollbar.vertical.right";
  409. if (scrollBitmaps)
  410. bg=scrollBitmaps->v_down.getBitmap();
  411. startx = 14; starty = 31; break;
  412. }
  413. if (freeform)
  414. {
  415. SkinBitmap bmp(bitmapid);
  416. if (!bmp.isInvalid() && bg && !bg->isInvalid())
  417. {
  418. DCCanvas canvas(hdc);
  419. bg->stretchToRectAlpha(&canvas, lprc, alpha);
  420. bmp.stretchToRectAlpha(&canvas, lprc, alpha);
  421. return 1;
  422. }
  423. }
  424. // fallback code
  425. HDC hdcbmp;
  426. HBITMAP hbmpOld, hbmp;
  427. hbmp = WADlg_getBitmap();
  428. if (!hbmp) return FALSE;
  429. hdcbmp = (HDC)MlStockObjects_Get(CACHED_DC);
  430. if (!hdcbmp) return FALSE;
  431. hbmpOld = (HBITMAP)SelectObject(hdcbmp, hbmp);
  432. if (255 == alpha)
  433. StretchBlt(hdc, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, hdcbmp, startx, starty, 14, 14, SRCCOPY);
  434. else
  435. {
  436. HDC hdcTmp = CreateCompatibleDC(hdc);
  437. DIBSECTION dibSection;
  438. if (NULL == hbmpCachedDib ||
  439. sizeof(DIBSECTION) != GetObjectW(hbmpCachedDib, sizeof(DIBSECTION), &dibSection)
  440. || dibSection.dsBm.bmWidth < (lprc->right - lprc->left) || ABS(dibSection.dsBm.bmHeight) < (lprc->bottom - lprc->top))
  441. {
  442. if (hbmpCachedDib) DeleteObject(hbmpCachedDib);
  443. BITMAPINFOHEADER bi;
  444. ZeroMemory(&bi, sizeof(BITMAPINFOHEADER));
  445. bi.biSize = sizeof(BITMAPINFOHEADER);
  446. bi.biWidth = lprc->right - lprc->left;
  447. bi.biHeight = -(lprc->bottom - lprc->top);
  448. bi.biPlanes = 1;
  449. bi.biBitCount = 32;
  450. bi.biCompression = BI_RGB;
  451. hbmpCachedDib = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (VOID**)&dibSection.dsBm.bmBits, NULL, 0);
  452. dibSection.dsBm.bmHeight = bi.biHeight;
  453. dibSection.dsBm.bmWidth = bi.biWidth;
  454. }
  455. ASSERT(hbmpCachedDib != 0);
  456. HBITMAP hbmpTmp = (HBITMAP)SelectObject(hdcTmp, hbmpCachedDib);
  457. StretchBlt(hdcTmp, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, hdcbmp, startx, starty, 14, 14, SRCCOPY);
  458. LONG pitch = dibSection.dsBm.bmWidth*4, cy = lprc->bottom - lprc->top, x;
  459. LPBYTE cursor, line;
  460. COLORREF rgbBk = WADlg_getColor(WADLG_WNDBG);// BlendColors(GetSBBackColor(), WADlg_getColor(WADLG_ITEMBG), ((float)INACTIVEBAR_ALPHA)/255.0f);
  461. BYTE k = (((255 - alpha)*255 + 127)/255);
  462. BYTE r = (GetRValue(rgbBk)*k + 127)/255, g = (GetGValue(rgbBk)*k + 127)>>8, b = (GetBValue(rgbBk)*k + 127)/255;
  463. for (line = (BYTE*)dibSection.dsBm.bmBits; cy-- != 0; line += pitch )
  464. {
  465. for (x = (lprc->right - lprc->left), cursor = line; x-- != 0; cursor += 4)
  466. {
  467. cursor[0] = (cursor[0]*alpha)/255 + b;
  468. cursor[1] = (cursor[1]*alpha)/255 + g;
  469. cursor[2] = (cursor[2]*alpha)/255 + r;
  470. cursor[3] = 0xFF;
  471. }
  472. }
  473. BitBlt(hdc, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, hdcTmp, 0, 0, SRCCOPY);
  474. SelectObject(hdcTmp, hbmpTmp);
  475. DeleteDC(hdcTmp);
  476. }
  477. SelectObject(hdcbmp, hbmpOld);
  478. return 1;
  479. }
  480. // Draw a standard scrollbar arrow
  481. static int DrawScrollArrow(SCROLLBAR *sbar, HDC hdc, RECT *rect, UINT arrow, BOOL fMouseDown, BOOL fMouseOver, BOOL freeform)
  482. {
  483. UINT ret;
  484. UINT flags = arrow;
  485. //HACKY bit so this routine can be called by vertical and horizontal code
  486. if (sbar->nBarType == SB_VERT)
  487. {
  488. if (flags & DFCS_SCROLLLEFT) flags = flags & ~DFCS_SCROLLLEFT | DFCS_SCROLLUP;
  489. if (flags & DFCS_SCROLLRIGHT) flags = flags & ~DFCS_SCROLLRIGHT | DFCS_SCROLLDOWN;
  490. }
  491. if (fMouseDown) flags |= (DFCS_FLAT | DFCS_PUSHED);
  492. ret = DrawFrameCtrl(hdc, rect, DFC_SCROLL, flags, fMouseOver, freeform);
  493. return ret;
  494. }
  495. // Return the size in pixels for the specified scrollbar metric, for the specified scrollbar
  496. static int GetScrollMetric(SCROLLBAR *psb, int metric, DWORD scrollFlags)
  497. {
  498. int type (psb ? psb->nBarType : SB_VERT);
  499. switch (type)
  500. {
  501. case SB_HORZ:
  502. {
  503. switch (metric)
  504. {
  505. case SM_CXHORZSB:
  506. if (SWS_USEFREEFORM & scrollFlags)
  507. {
  508. SkinBitmap button(L"wasabi.scrollbar.horizontal.left"); // we assume symmetry which isn't necessary safe
  509. if (!button.isInvalid())
  510. return WASABI_API_APP->getScaleX(button.getWidth());
  511. }
  512. return WASABI_API_APP->getScaleX(14); // classic skin fixes this at 14
  513. default:
  514. if (SWS_USEFREEFORM & scrollFlags)
  515. {
  516. SkinBitmap button(L"wasabi.scrollbar.horizontal.left"); // we assume symmetry which isn't necessary safe
  517. if (!button.isInvalid())
  518. return WASABI_API_APP->getScaleY(button.getHeight());
  519. }
  520. return WASABI_API_APP->getScaleY(14); // classic skin fixes this at 14
  521. break;
  522. }
  523. }
  524. break;
  525. default: // case SB_VERT:
  526. {
  527. switch (metric)
  528. {
  529. case SM_CYVERTSB:
  530. if (SWS_USEFREEFORM & scrollFlags)
  531. {
  532. SkinBitmap button(L"wasabi.scrollbar.vertical.left"); // we assume symmetry which isn't necessary safe
  533. if (!button.isInvalid())
  534. return WASABI_API_APP->getScaleY(button.getHeight());
  535. }
  536. return WASABI_API_APP->getScaleY(14); // classic skin fixes this at 14
  537. default:
  538. if (SWS_USEFREEFORM & scrollFlags)
  539. {
  540. SkinBitmap button(L"wasabi.scrollbar.vertical.left"); // we assume symmetry which isn't necessary safe
  541. if (!button.isInvalid())
  542. return WASABI_API_APP->getScaleX(button.getWidth());
  543. }
  544. return WASABI_API_APP->getScaleX(14); // classic skin fixes this at 14
  545. break;
  546. }
  547. }
  548. break;
  549. }
  550. /*
  551. if ((SB_HORZ == psb->nBarType && metric == SM_CXHORZSB) || (SB_VERT == psb->nBarType && metric == SM_CYVERTSB))
  552. return (psb->nArrowLength == SYSTEM_METRIC) * ((psb->nArrowLength < 0) ? -14 : 1);
  553. else return psb->nArrowWidth * ((psb->nArrowWidth < 0) ? -14 : 1);
  554. */
  555. }
  556. // Fill the specifed rectangle using a solid colour
  557. static void PaintRect(HDC hdc, RECT *rect, COLORREF color)
  558. {
  559. COLORREF oldcol = SetBkColor(hdc, color);
  560. ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, rect, L"", 0, 0);
  561. SetBkColor(hdc, oldcol);
  562. }
  563. //
  564. // Set the minimum size, in pixels, that the thumb box will shrink to.
  565. //
  566. // Draw a simple blank scrollbar push-button. Can be used
  567. // to draw a push button, or the scrollbar thumb
  568. // drawflag - could set to BF_FLAT to make flat scrollbars
  569. static void DrawBlankButton(HDC hdc, const RECT *rect, UINT drawflag, int pushed, int vertical)
  570. {
  571. HBITMAP hbmp, hbmpOld;
  572. hbmp = WADlg_getBitmap();
  573. if (!hbmp) return;
  574. HDC hdcbmp = (HDC)MlStockObjects_Get(CACHED_DC);
  575. if (!hdcbmp) return;
  576. hbmpOld = (HBITMAP)SelectObject(hdcbmp, hbmp);
  577. #define PART1SIZE 4 //copied top
  578. #define PART2SIZE 5 //stretched top
  579. #define PART3SIZE 10 //copied middle
  580. #define PART4SIZE 5 //stretched bottom
  581. #define PART5SIZE 4 //copied bottom
  582. if (vertical)
  583. {
  584. int middle = (rect->bottom - rect->top) / 2;
  585. int startx = pushed ? 70 : 56;
  586. //top
  587. StretchBlt(hdc, rect->left, rect->top, rect->right - rect->left, PART1SIZE, hdcbmp, startx, 31, 14, PART1SIZE, SRCCOPY);
  588. int p = PART1SIZE;
  589. //stretched top
  590. int l = middle - PART1SIZE - (PART3SIZE / 2);
  591. if (l > 0)
  592. {
  593. StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, l, hdcbmp, startx, 31 + PART1SIZE, 14, PART2SIZE, SRCCOPY);
  594. p += middle - PART1SIZE - (PART3SIZE / 2);
  595. }
  596. //copied middle
  597. int m = (rect->bottom - rect->top) - PART1SIZE - PART5SIZE; //space that's available for middle
  598. m = min(m, PART3SIZE);
  599. if (m > 0)
  600. {
  601. StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, m, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE, 14, m, SRCCOPY);
  602. p += m;
  603. }
  604. //stretched bottom
  605. l = rect->bottom - rect->top - p - PART5SIZE;
  606. if (l > 0) StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, l, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE + PART3SIZE, 14, PART4SIZE, SRCCOPY);
  607. //bottom
  608. StretchBlt(hdc, rect->left, rect->bottom - PART5SIZE, rect->right - rect->left, PART5SIZE, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE + PART3SIZE + PART4SIZE, 14, PART5SIZE, SRCCOPY);
  609. }
  610. else
  611. {
  612. int middle = (rect->right - rect->left) / 2;
  613. int starty = pushed ? 45 : 31;
  614. //top
  615. StretchBlt(hdc, rect->left, rect->top, PART1SIZE, rect->bottom - rect->top, hdcbmp, 84, starty, PART1SIZE, 14, SRCCOPY);
  616. int p = PART1SIZE;
  617. //stretched top
  618. int l = middle - PART1SIZE - (PART3SIZE / 2);
  619. if (l > 0)
  620. {
  621. StretchBlt(hdc, rect->left + p, rect->top, l, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE, starty, PART2SIZE, 14, SRCCOPY);
  622. p += middle - PART1SIZE - (PART3SIZE / 2);
  623. }
  624. //copied middle
  625. int m = (rect->right - rect->left) - PART1SIZE - PART5SIZE; //space that's available for middle
  626. m = min(m, PART3SIZE);
  627. if (m > 0)
  628. {
  629. StretchBlt(hdc, rect->left + p, rect->top, m, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE, starty, m, 14, SRCCOPY);
  630. p += m;
  631. }
  632. //stretched bottom
  633. l = rect->right - rect->left - p - PART5SIZE;
  634. if (l > 0) StretchBlt(hdc, rect->left + p, rect->top, l, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE + PART3SIZE, starty, PART4SIZE, 14, SRCCOPY);
  635. //bottom
  636. StretchBlt(hdc, rect->right - PART5SIZE, rect->top, PART5SIZE, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE + PART3SIZE + PART4SIZE, starty, PART5SIZE, 14, SRCCOPY);
  637. }
  638. SelectObject(hdcbmp, hbmpOld);
  639. }
  640. // Calculate the screen coordinates of the area taken by
  641. // the horizontal scrollbar. Take into account the size
  642. // of the window borders
  643. static BOOL GetHScrollRect(SkinnedScrollWnd *pWnd, RECT *prc)
  644. {
  645. if (pWnd->psbHorz->fScrollVisible)
  646. {
  647. GetClientRect(pWnd->hwnd, prc);
  648. MapWindowPoints(pWnd->hwnd, HWND_DESKTOP, (POINT*)prc, 2);
  649. prc->top = prc->bottom;
  650. prc->bottom += GetScrollMetric(pWnd->psbHorz, SM_CYHORZSB, pWnd->scrollFlags);
  651. }
  652. else SetRect(prc, 0, 0, 0, 0);
  653. return TRUE;
  654. }
  655. // Calculate the screen coordinates of the area taken by the
  656. // vertical scrollbar
  657. static BOOL GetVScrollRect(SkinnedScrollWnd *pWnd, RECT *prc)
  658. {
  659. if (pWnd->psbVert->fScrollVisible)
  660. {
  661. GetClientRect(pWnd->hwnd, prc);
  662. MapWindowPoints(pWnd->hwnd, HWND_DESKTOP, (POINT*)prc, 2);
  663. if (SWS_LEFT & pWnd->scrollFlags)
  664. {
  665. prc->right = prc->left;
  666. prc->left -= GetScrollMetric(pWnd->psbVert, SM_CXVERTSB, pWnd->scrollFlags);
  667. }
  668. else
  669. {
  670. prc->left = prc->right;
  671. prc->right += GetScrollMetric(pWnd->psbVert, SM_CXVERTSB, pWnd->scrollFlags);
  672. }
  673. }
  674. else SetRect(prc, 0, 0, 0, 0);
  675. return TRUE;
  676. }
  677. // Depending on what type of scrollbar nBar refers to, call the
  678. // appropriate Get?ScrollRect function
  679. //
  680. static BOOL GetScrollRect(SkinnedScrollWnd *pWnd, UINT nBar, RECT *prc)
  681. {
  682. if (nBar == SB_HORZ) return GetHScrollRect(pWnd, prc);
  683. else if (nBar == SB_VERT) return GetVScrollRect(pWnd, prc);
  684. else return FALSE;
  685. }
  686. //
  687. // Work out the scrollbar width/height for either type of scrollbar (SB_HORZ/SB_VERT)
  688. // rect - coords of the scrollbar.
  689. // store results into *thumbsize and *thumbpos
  690. //
  691. static int CalcThumbSize(SCROLLBAR *sbar, const RECT *rect, int *pthumbsize, int *pthumbpos, DWORD scrollFlags)
  692. {
  693. SCROLLINFO *si;
  694. int scrollsize; //total size of the scrollbar including arrow buttons
  695. int workingsize; //working area (where the thumb can slide)
  696. int siMaxMin;
  697. int butsize;
  698. int startcoord;
  699. int thumbpos = 0, thumbsize = 0;
  700. //work out the width (for a horizontal) or the height (for a vertical)
  701. //of a standard scrollbar button
  702. butsize = GetScrollMetric(sbar, SM_SCROLL_LENGTH, scrollFlags);
  703. if (1) //sbar->nBarType == SB_HORZ)
  704. {
  705. scrollsize = rect->right - rect->left;
  706. startcoord = rect->left;
  707. }
  708. /*else if(sbar->nBarType == SB_VERT)
  709. {
  710. scrollsize = rect->bottom - rect->top;
  711. startcoord = rect->top;
  712. }
  713. else
  714. {
  715. return 0;
  716. }*/
  717. si = &sbar->scrollInfo;
  718. siMaxMin = si->nMax - si->nMin + 1;
  719. workingsize = scrollsize - butsize * 2;
  720. //
  721. // Work out the scrollbar thumb SIZE
  722. //
  723. if (si->nPage == 0)
  724. {
  725. thumbsize = butsize;
  726. }
  727. else if (siMaxMin > 0)
  728. {
  729. /*if (SWS_HIDEHSCROLL & scrollFlags)
  730. thumbsize = MulDiv(si->nPage, workingsize, si->nMax);
  731. else*/
  732. thumbsize = MulDiv(si->nPage, workingsize, siMaxMin);
  733. if (SWS_USEFREEFORM & scrollFlags)
  734. {
  735. SkinBitmap thumb((sbar->nBarType == SB_VERT)?L"wasabi.scrollbar.vertical.button":L"wasabi.scrollbar.horizontal.button");
  736. if (!thumb.isInvalid())
  737. thumbsize = (sbar->nBarType == SB_VERT)?thumb.getHeight():thumb.getWidth();
  738. }
  739. if (thumbsize < sbar->nMinThumbSize)
  740. thumbsize = sbar->nMinThumbSize;
  741. }
  742. //
  743. // Work out the scrollbar thumb position
  744. //
  745. if (siMaxMin > 0)
  746. {
  747. int pagesize = max(1, si->nPage);
  748. thumbpos = MulDiv(si->nPos - si->nMin, workingsize - thumbsize, siMaxMin - pagesize);
  749. /*if (SWS_HIDEHSCROLL & scrollFlags)
  750. {
  751. thumbpos = (si->nPos == (si->nMax - si->nPage)) ?
  752. (workingsize - thumbsize) : MulDiv(si->nPos, workingsize, si->nMax);
  753. }*/
  754. if (thumbpos < 0)
  755. thumbpos = 0;
  756. if (thumbpos >= workingsize - thumbsize)
  757. thumbpos = workingsize - thumbsize;
  758. }
  759. thumbpos += startcoord + butsize;
  760. *pthumbpos = thumbpos;
  761. *pthumbsize = thumbsize;
  762. return 1;
  763. }
  764. //
  765. // return a hit-test value for whatever part of the scrollbar x,y is located in
  766. // rect, x, y: SCREEN coordinates
  767. // the rectangle must not include space for any inserted buttons
  768. // (i.e, JUST the scrollbar area)
  769. //
  770. static UINT GetHorzScrollPortion(SCROLLBAR *sbar, HWND hwnd, const RECT *rect, int x, int y, DWORD scrollFlags)
  771. {
  772. int thumbwidth, thumbpos;
  773. int butwidth = GetScrollMetric(sbar, SM_SCROLL_LENGTH, scrollFlags);
  774. int scrollwidth = rect->right - rect->left;
  775. int workingwidth = scrollwidth - butwidth * 2;
  776. if (y < rect->top || y >= rect->bottom)
  777. return HTSCROLL_NONE;
  778. CalcThumbSize(sbar, rect, &thumbwidth, &thumbpos, scrollFlags);
  779. //if we have had to scale the buttons to fit in the rect,
  780. //then adjust the button width accordingly
  781. if (scrollwidth <= butwidth * 2)
  782. {
  783. butwidth = scrollwidth / 2;
  784. }
  785. //check for left button click
  786. if (x >= rect->left && x < rect->left + butwidth)
  787. {
  788. return (ESB_DISABLE_LEFT & sbar->fScrollFlags) ? HTSCROLL_NONE : HTSCROLL_LEFT;
  789. }
  790. //check for right button click
  791. else if (x >= rect->right - butwidth && x < rect->right)
  792. {
  793. return (ESB_DISABLE_RIGHT & sbar->fScrollFlags) ? HTSCROLL_NONE : HTSCROLL_RIGHT;
  794. }
  795. //if the thumb is too big to fit (i.e. it isn't visible)
  796. //then return a NULL scrollbar area
  797. if (thumbwidth >= workingwidth)
  798. return HTSCROLL_NONE;
  799. //check for point in the thumbbar
  800. if (x >= thumbpos && x < thumbpos + thumbwidth)
  801. {
  802. return HTSCROLL_THUMB;
  803. }
  804. //check for left margin
  805. else if (x >= rect->left + butwidth && x < thumbpos)
  806. {
  807. return HTSCROLL_PAGELEFT;
  808. }
  809. else if (x >= thumbpos + thumbwidth && x < rect->right - butwidth)
  810. {
  811. return HTSCROLL_PAGERIGHT;
  812. }
  813. return HTSCROLL_NONE;
  814. }
  815. //
  816. // For vertical scrollbars, rotate all coordinates by -90 degrees
  817. // so that we can use the horizontal version of this function
  818. //
  819. static UINT GetVertScrollPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags)
  820. {
  821. UINT r;
  822. RotateRect(rect);
  823. r = GetHorzScrollPortion(sb, hwnd, rect, y, x, scrollFlags);
  824. RotateRect(rect);
  825. return r;
  826. }
  827. static const wchar_t *GetThumbID(UINT barType, UINT scrollFlags, BOOL hover)
  828. {
  829. if (barType == SB_VERT)
  830. {
  831. if (scrollFlags & CSBS_TRACKING)
  832. return L"wasabi.scrollbar.vertical.button.pressed";
  833. else if (hover)
  834. return L"wasabi.scrollbar.vertical.button.hover";
  835. else
  836. return L"wasabi.scrollbar.vertical.button";
  837. }
  838. else
  839. {
  840. if (scrollFlags & CSBS_TRACKING)
  841. return L"wasabi.scrollbar.horizontal.button.pressed";
  842. else if (hover)
  843. return L"wasabi.scrollbar.horizontal.button.hover";
  844. else
  845. return L"wasabi.scrollbar.horizontal.button";
  846. }
  847. }
  848. static HBRUSH SetWindowPatternBrush(HWND hwnd, HDC hdc, UINT nBarType)
  849. {
  850. RECT rw;
  851. GetWindowRect(hwnd, &rw);
  852. HWND hwndAncestor = GetAncestor(hwnd, GA_ROOT);
  853. if (hwndAncestor) MapWindowPoints(HWND_DESKTOP, hwndAncestor, (POINT*)&rw, 2);
  854. POINT ptOrg;
  855. if (GetViewportOrgEx(hdc, &ptOrg)) OffsetRect(&rw, ptOrg.x, ptOrg.y);
  856. if (nBarType == SB_VERT)
  857. {
  858. if (0 == (GetWindowLongPtrW(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR)) rw.left = rw.right;
  859. }
  860. else rw.top = rw.bottom;
  861. SetBrushOrgEx(hdc, rw.left, rw.top, (POINT*)&rw);
  862. return (HBRUSH)SelectObject(hdc, hbrChecked);
  863. }
  864. //
  865. // Draw a complete HORIZONTAL scrollbar in the given rectangle
  866. // Don't draw any inserted buttons in this procedure
  867. //
  868. // uDrawFlags - hittest code, to say if to draw the
  869. // specified portion in an active state or not.
  870. //
  871. //
  872. static LRESULT NCDrawHScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags, UINT hoverFlags, DWORD scrollFlags)
  873. {
  874. SCROLLINFO *si;
  875. RECT ctrl, thumb;
  876. RECT sbm;
  877. int butwidth = GetScrollMetric(sb, SM_SCROLL_LENGTH, scrollFlags);
  878. int scrollwidth = rect->right - rect->left;
  879. int workingwidth = scrollwidth - butwidth * 2;
  880. int thumbwidth = 0, thumbpos = 0;
  881. int siMaxMin;
  882. BOOL fMouseDownL = 0, fMouseOverL = (hoverFlags == HTSCROLL_LEFT);
  883. BOOL fMouseDownR = 0, fMouseOverR = (hoverFlags == HTSCROLL_RIGHT);
  884. BOOL fMouseOverThumb = (hoverFlags == HTSCROLL_THUMB);
  885. COLORREF crCheck1 = GetSBForeColor();
  886. COLORREF crCheck2 = GetSBBackColor();
  887. COLORREF crInverse1 = WADlg_getColor(WADLG_SCROLLBAR_INV_FGCOLOR);
  888. COLORREF crInverse2 = WADlg_getColor(WADLG_SCROLLBAR_INV_BGCOLOR);
  889. UINT uDFCFlat = (CSBS_FLATSB & sb->fScrollFlags) ? DFCS_FLAT : 0;
  890. UINT uDEFlat = (CSBS_FLATSB & sb->fScrollFlags) ? BF_FLAT : 0;
  891. //drawing flags to modify the appearance of the scrollbar buttons
  892. UINT uLeftButFlags = DFCS_SCROLLLEFT;
  893. UINT uRightButFlags = DFCS_SCROLLRIGHT;
  894. if (scrollwidth <= 0)
  895. return 0;
  896. si = &sb->scrollInfo;
  897. siMaxMin = si->nMax - si->nMin;
  898. if (hwnd != hwndCurCoolSB)
  899. uDrawFlags = HTSCROLL_NONE;
  900. //
  901. // work out the thumb size and position
  902. //
  903. CalcThumbSize(sb, rect, &thumbwidth, &thumbpos, scrollFlags);
  904. if ((CSBS_TRACKING & sb->fScrollFlags) && trackThumbPos != -1)
  905. {
  906. thumbpos=trackThumbPos;
  907. }
  908. if (sb->fScrollFlags & ESB_DISABLE_LEFT) uLeftButFlags |= DFCS_INACTIVE;
  909. if (sb->fScrollFlags & ESB_DISABLE_RIGHT) uRightButFlags |= DFCS_INACTIVE;
  910. //if we need to grey the arrows because there is no data to scroll
  911. if ((0 == (DFCS_INACTIVE & uLeftButFlags) || 0 == (DFCS_INACTIVE & uRightButFlags)) &&
  912. !(sb->fScrollFlags & CSBS_THUMBALWAYS) && !IsScrollInfoActive(si))
  913. {
  914. uLeftButFlags |= DFCS_INACTIVE;
  915. uRightButFlags |= DFCS_INACTIVE;
  916. }
  917. if ((DFCS_INACTIVE & uLeftButFlags) && (DFCS_INACTIVE & uRightButFlags))
  918. {
  919. COLORREF rgbBk = WADlg_getColor(WADLG_WNDBG);
  920. crCheck1 = BlendColors(crCheck1, rgbBk, INACTIVEBAR_ALPHA);
  921. crCheck2 = BlendColors(crCheck2, rgbBk, INACTIVEBAR_ALPHA);
  922. }
  923. if (hwnd == hwndCurCoolSB)
  924. {
  925. fMouseDownL = (uDrawFlags == HTSCROLL_LEFT);
  926. fMouseDownR = (uDrawFlags == HTSCROLL_RIGHT);
  927. }
  928. if (NULL == hbrChecked) //recreate pattern brush if needed
  929. {
  930. HBITMAP hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);
  931. hbrChecked = CreatePatternBrush(hbmp);
  932. DeleteObject(hbmp);
  933. if (NULL == hbrChecked) return 0;
  934. }
  935. HBRUSH hbrOld = NULL;
  936. COLORREF rgbFgOld, rgbBkOld;
  937. rgbFgOld = SetTextColor(hdc, crCheck1);
  938. rgbBkOld = SetBkColor(hdc, crCheck2);
  939. //
  940. // Draw the scrollbar now
  941. //
  942. if (scrollwidth > butwidth*2)
  943. {
  944. DCCanvas canvas(hdc);
  945. if (SWS_USEFREEFORM & scrollFlags)
  946. {
  947. CopyRect(&ctrl, rect);
  948. RotateRect0(sb, &ctrl);
  949. RenderBaseTexture(&canvas, &ctrl, hwnd);
  950. }
  951. //LEFT ARROW
  952. SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
  953. RotateRect0(sb, &ctrl);
  954. DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL, (SWS_USEFREEFORM & scrollFlags));
  955. RotateRect0(sb, &ctrl);
  956. //MIDDLE PORTION
  957. //if we can fit the thumbbar in, then draw it
  958. if (thumbwidth > 0 && thumbwidth <= workingwidth
  959. && IsScrollInfoActive(si) && ((sb->fScrollFlags & ESB_DISABLE_BOTH) != ESB_DISABLE_BOTH))
  960. {
  961. SkinBitmap *bg = (scrollBitmaps && (SWS_USEFREEFORM & scrollFlags)) ?
  962. ((sb->nBarType== SB_VERT) ? scrollBitmaps->v_mid.getBitmap(): scrollBitmaps->h_mid.getBitmap())
  963. : 0;
  964. if ((SWS_USEFREEFORM & scrollFlags) && bg && !bg->isInvalid())
  965. {
  966. SetRect(&sbm, rect->left + butwidth, rect->top, rect->right-butwidth, rect->bottom);
  967. RotateRect0(sb, &sbm);
  968. bg->stretchToRectAlpha(&canvas, &sbm);
  969. SkinBitmap thumbBitmap(GetThumbID(sb->nBarType, sb->fScrollFlags, fMouseOverThumb));
  970. SetRect(&sbm, thumbpos, rect->top, thumbpos+thumbwidth, rect->bottom);
  971. RotateRect0(sb, &sbm);
  972. if (!thumbBitmap.isInvalid())
  973. thumbBitmap.stretchToRectAlpha(&canvas, &sbm);
  974. else
  975. DrawBlankButton(hdc, &sbm, uDEFlat, (CSBS_TRACKING & sb->fScrollFlags), sb->nBarType == SB_VERT);
  976. }
  977. else
  978. {
  979. //Draw the scrollbar margin above the thumb
  980. SetRect(&sbm, rect->left + butwidth, rect->top, thumbpos, rect->bottom);
  981. RotateRect0(sb, &sbm);
  982. if (HTSCROLL_PAGELEFT == uDrawFlags)
  983. {
  984. SetTextColor(hdc, crInverse1);
  985. SetBkColor(hdc, crInverse2);
  986. }
  987. if (GetTextColor(hdc) == GetBkColor(hdc)) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &sbm, NULL, 0, NULL);
  988. else
  989. {
  990. if (NULL == hbrOld) hbrOld = SetWindowPatternBrush(hwnd, hdc, sb->nBarType);
  991. PatBlt(hdc, sbm.left, sbm.top, sbm.right - sbm.left, sbm.bottom - sbm.top, PATCOPY);
  992. }
  993. if (HTSCROLL_PAGELEFT == uDrawFlags)
  994. {
  995. SetTextColor(hdc, crCheck1);
  996. SetBkColor(hdc, crCheck2);
  997. }
  998. RotateRect0(sb, &sbm);
  999. //Draw the margin below the thumb
  1000. sbm.left = thumbpos + thumbwidth;
  1001. sbm.right = rect->right - butwidth;
  1002. RotateRect0(sb, &sbm);
  1003. if (HTSCROLL_PAGERIGHT == uDrawFlags)
  1004. {
  1005. SetTextColor(hdc, crInverse1);
  1006. SetBkColor(hdc, crInverse2);
  1007. }
  1008. if (GetTextColor(hdc) == GetBkColor(hdc)) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &sbm, NULL, 0, NULL);
  1009. else
  1010. {
  1011. if (NULL == hbrOld) hbrOld = SetWindowPatternBrush(hwnd, hdc, sb->nBarType);
  1012. PatBlt(hdc, sbm.left, sbm.top, sbm.right - sbm.left, sbm.bottom - sbm.top, PATCOPY);
  1013. }
  1014. if (HTSCROLL_PAGERIGHT == uDrawFlags)
  1015. {
  1016. SetTextColor(hdc, crCheck1);
  1017. SetBkColor(hdc, crCheck2);
  1018. }
  1019. RotateRect0(sb, &sbm);
  1020. //Draw the THUMB finally
  1021. SetRect(&thumb, thumbpos, rect->top, thumbpos + thumbwidth, rect->bottom);
  1022. RotateRect0(sb, &thumb);
  1023. DrawBlankButton(hdc, &thumb, uDEFlat, (CSBS_TRACKING & sb->fScrollFlags), sb->nBarType == SB_VERT);
  1024. RotateRect0(sb, &thumb);
  1025. }
  1026. }
  1027. //otherwise, just leave that whole area blank
  1028. else
  1029. {
  1030. OffsetRect(&ctrl, butwidth, 0);
  1031. ctrl.right = rect->right - butwidth;
  1032. //if we always show the thumb covering the whole scrollbar,
  1033. //then draw it that way
  1034. if (!IsScrollInfoActive(si) && (sb->fScrollFlags & CSBS_THUMBALWAYS)
  1035. && ctrl.right - ctrl.left > sb->nMinThumbSize)
  1036. {
  1037. //leave a 1-pixel gap between the thumb + right button
  1038. ctrl.right --;
  1039. RotateRect0(sb, &ctrl);
  1040. DrawBlankButton(hdc, &ctrl, uDEFlat, 0, sb->nBarType == SB_VERT);
  1041. RotateRect0(sb, &ctrl);
  1042. //draw the single-line gap
  1043. ctrl.left = ctrl.right;
  1044. ctrl.right += 1;
  1045. RotateRect0(sb, &ctrl);
  1046. PaintRect(hdc, &ctrl, GetSysColor(COLOR_SCROLLBAR));
  1047. RotateRect0(sb, &ctrl);
  1048. }
  1049. //otherwise, paint a blank if the thumb doesn't fit in
  1050. else
  1051. {
  1052. RotateRect0(sb, &ctrl);
  1053. BOOL classic(TRUE);
  1054. if (SWS_USEFREEFORM & scrollFlags)
  1055. {
  1056. SkinBitmap background(sb->nBarType== SB_VERT?L"wasabi.scrollbar.vertical.background.middle":L"wasabi.scrollbar.horizontal.background.middle");
  1057. if (!background.isInvalid())
  1058. {
  1059. background.stretchToRectAlpha(&canvas, &ctrl,
  1060. ((DFCS_INACTIVE & uLeftButFlags) && (DFCS_INACTIVE & uRightButFlags)) ? INACTIVEBAR_ALPHA : 255);
  1061. classic = FALSE;
  1062. }
  1063. }
  1064. if (classic)
  1065. {
  1066. if (crCheck1 == crCheck2) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &ctrl, NULL, 0, NULL);
  1067. else
  1068. {
  1069. if (NULL == hbrOld) hbrOld = SetWindowPatternBrush(hwnd, hdc, sb->nBarType);
  1070. PatBlt(hdc, ctrl.left, ctrl.top, ctrl.right - ctrl.left, ctrl.bottom - ctrl.top, PATCOPY);
  1071. }
  1072. }
  1073. RotateRect0(sb, &ctrl);
  1074. }
  1075. }
  1076. //RIGHT ARROW
  1077. SetRect(&ctrl, rect->right - butwidth, rect->top, rect->right, rect->bottom);
  1078. RotateRect0(sb, &ctrl);
  1079. DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR, (SWS_USEFREEFORM & scrollFlags));
  1080. RotateRect0(sb, &ctrl);
  1081. }
  1082. //not enough room for the scrollbar, so just draw the buttons (scaled in size to fit)
  1083. else
  1084. {
  1085. butwidth = scrollwidth / 2;
  1086. //LEFT ARROW
  1087. SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
  1088. RotateRect0(sb, &ctrl);
  1089. DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL, (SWS_USEFREEFORM & scrollFlags));
  1090. RotateRect0(sb, &ctrl);
  1091. //RIGHT ARROW
  1092. OffsetRect(&ctrl, scrollwidth - butwidth, 0);
  1093. RotateRect0(sb, &ctrl);
  1094. DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR, (SWS_USEFREEFORM & scrollFlags));
  1095. RotateRect0(sb, &ctrl);
  1096. //if there is a gap between the buttons, fill it with a solid color
  1097. //if(butwidth & 0x0001)
  1098. if (ctrl.left != rect->left + butwidth)
  1099. {
  1100. ctrl.left --;
  1101. ctrl.right -= butwidth;
  1102. RotateRect0(sb, &ctrl);
  1103. BOOL classic(TRUE);
  1104. if (SWS_USEFREEFORM & scrollFlags)
  1105. {
  1106. SkinBitmap background(sb->nBarType== SB_VERT?L"wasabi.scrollbar.vertical.background.middle":L"wasabi.scrollbar.horizontal.background.middle");
  1107. if (!background.isInvalid())
  1108. {
  1109. DCCanvas canvas(hdc);
  1110. RenderBaseTexture(&canvas, &ctrl, hwnd);
  1111. background.stretchToRectAlpha(&canvas, &ctrl,
  1112. ((DFCS_INACTIVE & uLeftButFlags) && (DFCS_INACTIVE & uRightButFlags)) ? INACTIVEBAR_ALPHA : 255);
  1113. classic = FALSE;
  1114. }
  1115. }
  1116. if (classic)
  1117. {
  1118. if (crCheck1 == crCheck2) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &ctrl, NULL, 0, NULL);
  1119. else
  1120. {
  1121. if (NULL == hbrOld) hbrOld = SetWindowPatternBrush(hwnd, hdc, sb->nBarType);
  1122. PatBlt(hdc, ctrl.left, ctrl.top, ctrl.right - ctrl.left, ctrl.bottom - ctrl.top, PATCOPY);
  1123. }
  1124. }
  1125. RotateRect0(sb, &ctrl);
  1126. }
  1127. }
  1128. SetBkColor(hdc, rgbBkOld);
  1129. SetTextColor(hdc, rgbFgOld);
  1130. if (hbrOld)
  1131. {
  1132. SelectObject(hdc, hbrOld);
  1133. SetBrushOrgEx(hdc, 0, 0, NULL);
  1134. }
  1135. return 0;
  1136. }
  1137. //
  1138. // Draw a vertical scrollbar using the horizontal draw routine, but
  1139. // with the coordinates adjusted accordingly
  1140. //
  1141. static LRESULT NCDrawVScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags, UINT hoverFlags, DWORD scrollFlags)
  1142. {
  1143. LRESULT ret;
  1144. RECT rc;
  1145. rc = *rect;
  1146. RotateRect(&rc);
  1147. ret = NCDrawHScrollbar(sb, hwnd, hdc, &rc, uDrawFlags, hoverFlags, scrollFlags);
  1148. RotateRect(&rc);
  1149. return ret;
  1150. }
  1151. //
  1152. // Generic wrapper function for the scrollbar drawing
  1153. //
  1154. static LRESULT NCDrawScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags, UINT hoverFlags, DWORD scrollFlags)
  1155. {
  1156. if (sb->nBarType == SB_HORZ)
  1157. return NCDrawHScrollbar(sb, hwnd, hdc, rect, uDrawFlags, hoverFlags, scrollFlags);
  1158. else
  1159. return NCDrawVScrollbar(sb, hwnd, hdc, rect, uDrawFlags, hoverFlags, scrollFlags);
  1160. }
  1161. void SkinnedScrollWnd::PaintNonClient(HDC hdc)
  1162. {
  1163. RECT winrect, rcH, rcV;
  1164. BOOL drawH = FALSE, drawV = FALSE;
  1165. if (!psbHorz->fScrollVisible && !psbVert->fScrollVisible)
  1166. {
  1167. DrawBorder(hdc);
  1168. return;
  1169. }
  1170. if (0 == (SWS_UPDATEFRAME & scrollFlags))
  1171. {
  1172. HWND hwndActive;
  1173. hwndActive = GetActiveWindow();
  1174. if (hwndActive != hwnd && !IsChild(hwndActive, hwnd)) scrollFlags |= SWS_UPDATEFRAME;
  1175. }
  1176. GetWindowRect(hwnd, &winrect);
  1177. if (psbHorz->fScrollVisible)
  1178. {
  1179. GetHScrollRect(this, &rcH);
  1180. OffsetRect(&rcH, -winrect.left, -winrect.top);
  1181. if (rcH.right > rcH.left && rcH.bottom > rcH.top && RectVisible(hdc, &rcH)) drawH = TRUE;
  1182. }
  1183. if (psbVert->fScrollVisible)
  1184. {
  1185. GetVScrollRect(this, &rcV);
  1186. OffsetRect(&rcV, -winrect.left, -winrect.top);
  1187. if (rcV.right > rcV.left && rcV.bottom > rcV.top && RectVisible(hdc, &rcV)) drawV = TRUE;
  1188. }
  1189. DrawBorder(hdc);
  1190. POINT ptOrg;
  1191. GetViewportOrgEx(hdc, &ptOrg);
  1192. if (drawH)
  1193. {
  1194. UINT fDraw, fHover;
  1195. if (uCurrentScrollbar == SB_HORZ) { fDraw = uScrollTimerPortion; fHover = HTSCROLL_NONE; }
  1196. else
  1197. {
  1198. fDraw = HTSCROLL_NONE;
  1199. fHover = (NULL != psbHorz && 0 != (CSBS_HOVERING & psbHorz->fScrollFlags)) ? scrollPortionHover : HTSCROLL_NONE;
  1200. }
  1201. if (SWS_USEFREEFORM & scrollFlags)
  1202. {
  1203. DCBltCanvas buffer;
  1204. buffer.cloneDC(hdc, &rcH);
  1205. NCDrawHScrollbar(psbHorz, hwnd, buffer.getHDC(), &rcH, fDraw, fHover, scrollFlags);
  1206. }
  1207. else
  1208. {
  1209. SetViewportOrgEx(hdc, ptOrg.x + rcH.left, ptOrg.y + rcH.top, NULL);
  1210. OffsetRect(&rcH, -rcH.left, -rcH.top);
  1211. NCDrawHScrollbar(psbHorz, hwnd, hdc, &rcH, fDraw, fHover, scrollFlags);
  1212. SetViewportOrgEx(hdc, ptOrg.x, ptOrg.y, NULL);
  1213. }
  1214. }
  1215. if (drawV)
  1216. {
  1217. UINT fDraw, fHover;
  1218. if (uCurrentScrollbar == SB_VERT) { fDraw = uScrollTimerPortion; fHover = HTSCROLL_NONE; }
  1219. else
  1220. {
  1221. fDraw = HTSCROLL_NONE;
  1222. fHover = (NULL != psbVert && 0 != (CSBS_HOVERING & psbVert->fScrollFlags)) ? scrollPortionHover : HTSCROLL_NONE;
  1223. }
  1224. if (SWS_USEFREEFORM & scrollFlags)
  1225. {
  1226. DCBltCanvas buffer;
  1227. buffer.cloneDC(hdc, &rcV);
  1228. NCDrawVScrollbar(psbVert, hwnd, buffer.getHDC(), &rcV, fDraw, fHover, scrollFlags);
  1229. }
  1230. else
  1231. {
  1232. SetViewportOrgEx(hdc, ptOrg.x + rcV.left, ptOrg.y + rcV.top, NULL);
  1233. OffsetRect(&rcV, -rcV.left, -rcV.top);
  1234. NCDrawVScrollbar(psbVert, hwnd, hdc, &rcV, fDraw, fHover, scrollFlags);
  1235. SetViewportOrgEx(hdc, ptOrg.x, ptOrg.y, NULL);
  1236. }
  1237. }
  1238. SetViewportOrgEx(hdc, ptOrg.x, ptOrg.y, NULL);
  1239. // DRAW THE DEAD AREA
  1240. // only do this if the horizontal and vertical bars are visible
  1241. if (psbHorz->fScrollVisible && psbVert->fScrollVisible)
  1242. {
  1243. GetClientRect(hwnd, &rcH);
  1244. MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&rcH, 2);
  1245. OffsetRect(&rcH, -winrect.left, -winrect.top);
  1246. rcH.top = rcH.bottom;
  1247. rcH.bottom += GetScrollMetric(psbHorz, SM_CYHORZSB, scrollFlags);
  1248. if (SWS_LEFT & scrollFlags)
  1249. {
  1250. rcH.right = rcH.left;
  1251. rcH.left -= GetScrollMetric(psbVert, SM_CXVERTSB, scrollFlags);
  1252. }
  1253. else
  1254. {
  1255. rcH.left = rcH.right;
  1256. rcH.right += GetScrollMetric(psbVert, SM_CXVERTSB, scrollFlags);
  1257. }
  1258. if (RectVisible(hdc, &rcH))
  1259. {
  1260. PaintRect(hdc, &rcH, WADlg_getColor(WADLG_SCROLLBAR_DEADAREA_COLOR));
  1261. }
  1262. }
  1263. }
  1264. void SkinnedScrollWnd::OnNcPaint(HRGN rgnUpdate)
  1265. {
  1266. UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS |
  1267. DCX_INTERSECTUPDATE | DCX_VALIDATE;
  1268. HDC hdc = GetDCEx(hwnd, ((HRGN)NULLREGION != rgnUpdate) ? rgnUpdate : NULL, flags);
  1269. if (NULL == hdc)
  1270. {
  1271. return;
  1272. }
  1273. PaintNonClient(hdc);
  1274. ReleaseDC(hwnd, hdc);
  1275. }
  1276. //
  1277. // Need to detect if we have clicked in the scrollbar region or not
  1278. //
  1279. INT SkinnedScrollWnd::OnNcHitTest(POINTS pts)
  1280. {
  1281. RECT rc;
  1282. INT r = __super::OnNcHitTest(pts);
  1283. if (r == HTTRANSPARENT)
  1284. {
  1285. return r;
  1286. }
  1287. if (psbHorz->fScrollVisible && GetHScrollRect(this, &rc) &&
  1288. pts.x >= rc.left && pts.x <= rc.right && pts.y >= rc.top && pts.y <= rc.bottom) return HTHSCROLL;
  1289. if (psbVert->fScrollVisible && GetVScrollRect(this, &rc) &&
  1290. pts.x >= rc.left && pts.x <= rc.right && pts.y >= rc.top && pts.y <= rc.bottom) return HTVSCROLL;
  1291. return r;
  1292. }
  1293. //
  1294. // Return a HT* value indicating what part of the scrollbar was clicked
  1295. // Rectangle is not adjusted
  1296. //
  1297. static UINT GetHorzPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags)
  1298. {
  1299. RECT rc = *rect;
  1300. if (y < rc.top || y >= rc.bottom) return HTSCROLL_NONE;
  1301. //Now we have the rectangle for the scrollbar itself, so work out
  1302. //what part we clicked on.
  1303. return GetHorzScrollPortion(sb, hwnd, &rc, x, y, scrollFlags);
  1304. }
  1305. //
  1306. // Just call the horizontal version, with adjusted coordinates
  1307. //
  1308. static UINT GetVertPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags)
  1309. {
  1310. UINT ret;
  1311. RotateRect(rect);
  1312. ret = GetHorzPortion(sb, hwnd, rect, y, x, scrollFlags);
  1313. RotateRect(rect);
  1314. return ret;
  1315. }
  1316. //
  1317. // Wrapper function for GetHorzPortion and GetVertPortion
  1318. //
  1319. static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags)
  1320. {
  1321. if (sb->nBarType == SB_HORZ) return GetHorzPortion(sb, hwnd, rect, x, y, scrollFlags);
  1322. else if (sb->nBarType == SB_VERT) return GetVertPortion(sb, hwnd, rect, x, y, scrollFlags);
  1323. return HTSCROLL_NONE;
  1324. }
  1325. //
  1326. // Input: rectangle of the total scrollbar area
  1327. // Output: adjusted to take the inserted buttons into account
  1328. //
  1329. static void GetRealHorzScrollRect(SCROLLBAR *sb, RECT *rect)
  1330. {
  1331. if (CSBS_BTNVISBEFORE & sb->fScrollFlags) rect->left += sb->nButSizeBefore;
  1332. if (CSBS_BTNVISAFTER & sb->fScrollFlags) rect->right -= sb->nButSizeAfter;
  1333. }
  1334. //
  1335. // Input: rectangle of the total scrollbar area
  1336. // Output: adjusted to take the inserted buttons into account
  1337. //
  1338. static void GetRealVertScrollRect(SCROLLBAR *sb, RECT *rect)
  1339. {
  1340. if (CSBS_BTNVISBEFORE & sb->fScrollFlags) rect->top += sb->nButSizeBefore;
  1341. if (CSBS_BTNVISAFTER & sb->fScrollFlags) rect->bottom -= sb->nButSizeAfter;
  1342. }
  1343. //
  1344. // Decide which type of scrollbar we have before calling
  1345. // the real function to do the job
  1346. //
  1347. static void GetRealScrollRect(SCROLLBAR *sb, RECT *rect, DWORD scrollFlags)
  1348. {
  1349. if (sb->nBarType == SB_HORZ)
  1350. {
  1351. GetRealHorzScrollRect(sb, rect);
  1352. }
  1353. else if (sb->nBarType == SB_VERT)
  1354. {
  1355. GetRealVertScrollRect(sb, rect);
  1356. }
  1357. }
  1358. //
  1359. // Left button click in the non-client area
  1360. //
  1361. void SkinnedScrollWnd::OnNcLButtonDown(UINT nHitTest, POINTS pts)
  1362. {
  1363. RECT rect, winrect;
  1364. SCROLLBAR *psb;
  1365. hwndCurCoolSB = hwnd;
  1366. //
  1367. // HORIZONTAL SCROLLBAR PROCESSING
  1368. //
  1369. if (HTHSCROLL == nHitTest)
  1370. {
  1371. psb = psbHorz;
  1372. uScrollTimerMsg = WM_HSCROLL;
  1373. uCurrentScrollbar = SB_HORZ;
  1374. //get the total area of the normal Horz scrollbar area
  1375. GetHScrollRect(this, &rect);
  1376. uCurrentScrollPortion = GetHorzPortion(psbHorz, hwnd, &rect, pts.x, pts.y, scrollFlags);
  1377. }
  1378. //
  1379. // VERTICAL SCROLLBAR PROCESSING
  1380. //
  1381. else if (HTVSCROLL== nHitTest)
  1382. {
  1383. psb = psbVert;
  1384. uScrollTimerMsg = WM_VSCROLL;
  1385. uCurrentScrollbar = SB_VERT;
  1386. //get the total area of the normal Horz scrollbar area
  1387. GetVScrollRect(this, &rect);
  1388. uCurrentScrollPortion = GetVertPortion(psbVert, hwnd, &rect, pts.x, pts.y, scrollFlags);
  1389. }
  1390. //
  1391. // NORMAL PROCESSING
  1392. //
  1393. else
  1394. {
  1395. uCurrentScrollPortion = HTSCROLL_NONE;
  1396. __super::WindowProc(WM_NCLBUTTONDOWN, (WPARAM)nHitTest, *(LPARAM*)&pts);
  1397. return;
  1398. }
  1399. //
  1400. // we can now share the same code for vertical
  1401. // and horizontal scrollbars
  1402. //
  1403. switch (uCurrentScrollPortion)
  1404. {
  1405. //inserted buttons to the left/right
  1406. case HTSCROLL_THUMB:
  1407. //if the scrollbar is disabled, then do no further processing
  1408. if (!IsScrollbarActive(psb)) return;
  1409. GetRealScrollRect(psb, &rect, scrollFlags);
  1410. RotateRect0(psb, &rect);
  1411. CalcThumbSize(psb, &rect, &nThumbSize, &nThumbPos, scrollFlags);
  1412. RotateRect0(psb, &rect);
  1413. //remember the bounding rectangle of the scrollbar work area
  1414. rcThumbBounds = rect;
  1415. trackThumbPos=-1;
  1416. psb->fScrollFlags |= CSBS_TRACKING;
  1417. psb->scrollInfo.nTrackPos = psb->scrollInfo.nPos;
  1418. if (nHitTest == HTVSCROLL) nThumbMouseOffset = pts.y - nThumbPos;
  1419. else nThumbMouseOffset = pts.x - nThumbPos;
  1420. nLastPos = psb->scrollInfo.nPos;
  1421. nThumbPos0 = nThumbPos;
  1422. SCROLLINFO info;
  1423. info.cbSize = sizeof(SCROLLINFO);
  1424. info.fMask = SIF_POS;
  1425. info.nPos = nLastPos;
  1426. SetScrollInfo(hwnd, psb->nBarType, &info, FALSE);
  1427. SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBTRACK, nLastPos);
  1428. //if(sb->fFlatScrollbar)
  1429. //{
  1430. GetWindowRect(hwnd, &winrect);
  1431. OffsetRect(&rect, -winrect.left, -winrect.top);
  1432. InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar);
  1433. //}
  1434. break;
  1435. //Any part of the scrollbar
  1436. case HTSCROLL_LEFT:
  1437. if (psb->fScrollFlags & ESB_DISABLE_LEFT) return;
  1438. goto target1;
  1439. case HTSCROLL_RIGHT:
  1440. if (psb->fScrollFlags & ESB_DISABLE_RIGHT) return;
  1441. goto target1;
  1442. case HTSCROLL_PAGELEFT:
  1443. case HTSCROLL_PAGERIGHT:
  1444. target1:
  1445. //if the scrollbar is disabled, then do no further processing
  1446. if (!IsScrollbarActive(psb))
  1447. break;
  1448. //ajust the horizontal rectangle to NOT include
  1449. //any inserted buttons
  1450. GetRealScrollRect(psb, &rect, scrollFlags);
  1451. SendScrollMessage(hwnd, uScrollTimerMsg, uCurrentScrollPortion, 0);
  1452. // Check what area the mouse is now over :
  1453. // If the scroll thumb has moved under the mouse in response to
  1454. // a call to SetScrollPos etc, then we don't hilight the scrollbar margin
  1455. if (uCurrentScrollbar == SB_HORZ)
  1456. uScrollTimerPortion = GetHorzScrollPortion(psb, hwnd, &rect, pts.x, pts.y, scrollFlags);
  1457. else
  1458. uScrollTimerPortion = GetVertScrollPortion(psb, hwnd, &rect, pts.x, pts.y, scrollFlags);
  1459. GetWindowRect(hwnd, &winrect);
  1460. OffsetRect(&rect, -winrect.left, -winrect.top);
  1461. //if we aren't hot-tracking, then don't highlight
  1462. //the scrollbar thumb unless we click on it
  1463. if (uScrollTimerPortion == HTSCROLL_THUMB) uScrollTimerPortion = HTSCROLL_NONE;
  1464. InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar);
  1465. //Post the scroll message!!!!
  1466. uScrollTimerPortion = uCurrentScrollPortion;
  1467. //set a timer going on the first click.
  1468. //if this one expires, then we can start off a more regular timer
  1469. //to generate the auto-scroll behaviour
  1470. uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID1, COOLSB_TIMERINTERVAL1, 0);
  1471. UpdateScrollBars(FALSE);
  1472. break;
  1473. default:
  1474. __super::WindowProc(WM_NCLBUTTONDOWN, (WPARAM)nHitTest, *(LPARAM*)&pts);
  1475. return;
  1476. }
  1477. if ((0 == (SWS_COMBOLBOX & scrollFlags)) && hwnd != GetCapture())
  1478. {
  1479. ignoreCaptureChange = TRUE;
  1480. SetCapture(hwnd);
  1481. ignoreCaptureChange = FALSE;
  1482. captureSet = TRUE;
  1483. }
  1484. }
  1485. //
  1486. // Left button released
  1487. //
  1488. void SkinnedScrollWnd::Emulate_LeftButtonUp(UINT nFlags, POINTS pts, BOOL forwardMessage)
  1489. {
  1490. //current scrollportion is the button that we clicked down on
  1491. if (uCurrentScrollPortion != HTSCROLL_NONE)
  1492. {
  1493. RECT rect;
  1494. //UINT thisportion;
  1495. POINT pt;
  1496. RECT winrect;
  1497. SCROLLBAR *psb;
  1498. if (captureSet && (0 == (SWS_COMBOLBOX & scrollFlags)) && hwnd == GetCapture())
  1499. {
  1500. ignoreCaptureChange = TRUE;
  1501. ReleaseCapture();
  1502. ignoreCaptureChange = FALSE;
  1503. }
  1504. captureSet = FALSE;
  1505. GetWindowRect(hwnd, &winrect);
  1506. POINTSTOPOINT(pt, pts);
  1507. //emulate the mouse input on a scrollbar here...
  1508. if (SB_VERT == uCurrentScrollbar)
  1509. {
  1510. //get the total area of the normal Horz scrollbar area
  1511. psb = psbVert;
  1512. GetVScrollRect(this, &rect);
  1513. }
  1514. else
  1515. {
  1516. //get the total area of the normal Horz scrollbar area
  1517. psb = psbHorz;
  1518. GetHScrollRect(this, &rect);
  1519. }
  1520. //we need to do different things depending on if the
  1521. //user is activating the scrollbar itself, or one of
  1522. //the inserted buttons
  1523. switch (uCurrentScrollPortion)
  1524. {
  1525. //The scrollbar is active
  1526. case HTSCROLL_LEFT:
  1527. case HTSCROLL_RIGHT:
  1528. case HTSCROLL_PAGELEFT:
  1529. case HTSCROLL_PAGERIGHT:
  1530. case HTSCROLL_NONE:
  1531. KillTimer(hwnd, uScrollTimerId);
  1532. case HTSCROLL_THUMB:
  1533. UpdateScrollBars(FALSE);
  1534. //In case we were thumb tracking, make sure we stop NOW
  1535. if (CSBS_TRACKING & psb->fScrollFlags)
  1536. {
  1537. SCROLLINFO info;
  1538. info.cbSize = sizeof(SCROLLINFO);
  1539. info.fMask = SIF_POS;
  1540. info.nPos = nLastPos;
  1541. SetScrollInfo(hwnd, psb->nBarType, &info, FALSE);
  1542. SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBPOSITION, nLastPos);
  1543. psb->fScrollFlags &= ~CSBS_TRACKING;
  1544. }
  1545. //send the SB_ENDSCROLL message now that scrolling has finished
  1546. SendScrollMessage(hwnd, uScrollTimerMsg, SB_ENDSCROLL, 0);
  1547. //adjust the total scroll area to become where the scrollbar
  1548. //really is (take into account the inserted buttons)
  1549. GetRealScrollRect(psb, &rect, scrollFlags);
  1550. OffsetRect(&rect, -winrect.left, -winrect.top);
  1551. InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar);
  1552. break;
  1553. }
  1554. //reset our state to default
  1555. uCurrentScrollPortion = HTSCROLL_NONE;
  1556. uScrollTimerPortion = HTSCROLL_NONE;
  1557. uScrollTimerId = 0;
  1558. uScrollTimerMsg = 0;
  1559. uCurrentScrollbar = COOLSB_NONE;
  1560. return;
  1561. }
  1562. else
  1563. {
  1564. /*
  1565. // Can't remember why I did this!
  1566. if(GetCapture() == hwnd)
  1567. {
  1568. ReleaseCapture();
  1569. }*/
  1570. }
  1571. //sw->update();
  1572. if (FALSE != forwardMessage)
  1573. {
  1574. __super::WindowProc(WM_LBUTTONUP, (WPARAM)nFlags, *(LPARAM*)&pts);
  1575. }
  1576. }
  1577. void SkinnedScrollWnd::OnLButtonUp(UINT nFlags, POINTS pts)
  1578. {
  1579. Emulate_LeftButtonUp(nFlags, pts, TRUE);
  1580. }
  1581. static int
  1582. ListView_ScrollWindow(HWND hwnd, int dy)
  1583. {
  1584. RECT rect;
  1585. if (0 == dy)
  1586. return NULLREGION;
  1587. if (FALSE == GetClientRect(hwnd, &rect))
  1588. return ERROR;
  1589. if (0 == (LVS_NOCOLUMNHEADER & GetWindowLongPtrW(hwnd, GWL_STYLE)))
  1590. {
  1591. HWND headerWindow;
  1592. headerWindow = (HWND)SendMessageW(hwnd, LVM_GETHEADER, 0, 0L);
  1593. if (NULL != headerWindow &&
  1594. 0 != (WS_VISIBLE & GetWindowLongPtrW(headerWindow, GWL_STYLE)))
  1595. {
  1596. HDLAYOUT headerLayout;
  1597. WINDOWPOS headerPos;
  1598. headerLayout.prc = &rect;
  1599. headerLayout.pwpos = &headerPos;
  1600. SendMessageW(headerWindow, HDM_LAYOUT, 0, (LPARAM)&headerLayout);
  1601. }
  1602. }
  1603. return ScrollWindowEx(hwnd, 0, dy, &rect, &rect, NULL, NULL, SW_INVALIDATE);
  1604. }
  1605. static BOOL ListView_ScrollReportModeVert(HWND hwnd, INT linesVert, BOOL horzBarHidden)
  1606. {
  1607. int max, pos, page;
  1608. int itemHeight, prevPos, dy;
  1609. RECT rect;
  1610. unsigned long windowStyle;
  1611. if (0 == linesVert)
  1612. return TRUE;
  1613. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  1614. pos = (int)SendMessageW(hwnd, LVM_GETTOPINDEX, 0, 0L);
  1615. max = (int)SendMessageW(hwnd, LVM_GETITEMCOUNT, 0, 0L);
  1616. page = (int)SendMessageW(hwnd, LVM_GETCOUNTPERPAGE, 0, 0L);
  1617. if (FALSE == horzBarHidden)
  1618. max++;
  1619. if ((linesVert < 0 && pos <= 0) ||
  1620. (linesVert > 0 && (pos + page) >= max))
  1621. {
  1622. return TRUE;
  1623. }
  1624. if (linesVert < 0 && (pos + linesVert) < 0)
  1625. linesVert = -pos;
  1626. else if (linesVert > 0 && (pos + page + linesVert) > max)
  1627. linesVert = max - (page + pos);
  1628. rect.left = LVIR_BOUNDS;
  1629. if (!SendMessageW(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect))
  1630. return FALSE;
  1631. if (rect.top < 0)
  1632. OffsetRect(&rect, 0, -rect.top);
  1633. itemHeight = rect.bottom - rect.top;
  1634. if (0 != (WS_VISIBLE & windowStyle))
  1635. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  1636. dy = linesVert * itemHeight;
  1637. SendMessageW(hwnd, LVM_SCROLL, 0, dy);
  1638. if (0 == (WS_VISIBLE & windowStyle))
  1639. return TRUE;
  1640. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle);
  1641. prevPos = pos;
  1642. pos = (int)SendMessageW(hwnd, LVM_GETTOPINDEX, 0, 0L);
  1643. linesVert = pos - prevPos;
  1644. dy = linesVert * itemHeight;
  1645. if (ERROR == ListView_ScrollWindow(hwnd, -dy))
  1646. InvalidateRect(hwnd, NULL, FALSE);
  1647. return TRUE;
  1648. }
  1649. static BOOL
  1650. ListView_ScrollReportModeVertPx(HWND hwnd, int dy, BOOL horzBarHidden)
  1651. {
  1652. int itemHeight, lines;
  1653. RECT rect;
  1654. unsigned long windowStyle;
  1655. if (0 == dy)
  1656. return TRUE;
  1657. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  1658. rect.left = LVIR_BOUNDS;
  1659. if (!SendMessageW(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect))
  1660. return FALSE;
  1661. if (rect.top < 0)
  1662. OffsetRect(&rect, 0, -rect.top);
  1663. itemHeight = rect.bottom - rect.top;
  1664. lines = dy / itemHeight;
  1665. if (0 != lines)
  1666. {
  1667. if (0 != (WS_VISIBLE & windowStyle))
  1668. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  1669. SendMessageW(hwnd, LVM_SCROLL, 0, lines);
  1670. if (0 != (WS_VISIBLE & windowStyle))
  1671. {
  1672. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  1673. windowStyle |= WS_VISIBLE;
  1674. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle);
  1675. }
  1676. }
  1677. if (0 != (WS_VISIBLE & windowStyle))
  1678. {
  1679. if (ERROR == ListView_ScrollWindow(hwnd, -dy))
  1680. InvalidateRect(hwnd, NULL, FALSE);
  1681. }
  1682. return TRUE;
  1683. }
  1684. //
  1685. // This function is called whenever the mouse is moved and
  1686. // we are dragging the scrollbar thumb about.
  1687. //
  1688. static void ThumbTrack(SCROLLBAR *sbar, HWND hwnd, POINTS pts, UINT scrollFlags)
  1689. {
  1690. POINT pt;
  1691. RECT rc, winrect, rc2;
  1692. int thumbpos = nThumbPos;
  1693. //int thumbDelta;
  1694. int pos;
  1695. int siMaxMin = 0;
  1696. //UINT flatflag = (CSBS_FLATSB & sbar->fScrollFlags) ? BF_FLAT : 0;
  1697. SCROLLINFO *si;
  1698. si = &sbar->scrollInfo;
  1699. POINTSTOPOINT(pt, pts);
  1700. MapWindowPoints(hwnd, HWND_DESKTOP, &pt, 1);
  1701. if (SB_VERT == sbar->nBarType)
  1702. {
  1703. LONG t;
  1704. t= pt.x; pt.x = pt.y; pt.y = t;
  1705. RotateRect(&rcThumbBounds);
  1706. }
  1707. //draw the thumb at whatever position
  1708. rc = rcThumbBounds;
  1709. SetRect(&rc2, rc.left - THUMBTRACK_SNAPDIST*2, rc.top - THUMBTRACK_SNAPDIST,
  1710. rc.right + THUMBTRACK_SNAPDIST*2, rc.bottom + THUMBTRACK_SNAPDIST);
  1711. int cxH = GetScrollMetric(sbar, SM_CXHORZSB, scrollFlags);
  1712. rc.left += cxH;
  1713. rc.right -= cxH;
  1714. //if the mouse is not in a suitable distance of the scrollbar,
  1715. //then "snap" the thumb back to its initial position
  1716. #ifdef SNAP_THUMB_BACK
  1717. if (!PtInRect(&rc2, pt))
  1718. {
  1719. thumbpos = nThumbPos0;
  1720. }
  1721. //otherwise, move the thumb to where the mouse is
  1722. else
  1723. #endif //SNAP_THUMB_BACK
  1724. {
  1725. //keep the thumb within the scrollbar limits
  1726. thumbpos = pt.x - nThumbMouseOffset;
  1727. if (thumbpos < rc.left) thumbpos = rc.left;
  1728. if (thumbpos > rc.right - nThumbSize) thumbpos = rc.right - nThumbSize;
  1729. }
  1730. GetClientRect(hwnd, &winrect);
  1731. MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&winrect, 2);
  1732. RotateRect0(sbar, &winrect);
  1733. OffsetRect(&rc, -winrect.left, -winrect.top);
  1734. thumbpos -= winrect.left;
  1735. /*if (-1 == trackThumbPos)
  1736. thumbDelta = thumbpos - rc.left;
  1737. else
  1738. thumbDelta = thumbpos - trackThumbPos;*/
  1739. trackThumbPos = thumbpos;
  1740. //post a SB_TRACKPOS message!!!
  1741. siMaxMin = si->nMax - si->nMin;
  1742. pos = (siMaxMin > 0) ? MulDiv(thumbpos - rc.left, siMaxMin - si->nPage + 1, rc.right - rc.left - nThumbSize) : (thumbpos - rc.left);
  1743. if (si->nPage == 0)
  1744. pos = 0; // this supposed to protect from moving on empty scrollbar
  1745. if (pos != nLastPos)
  1746. {
  1747. if (SWS_LISTVIEW & scrollFlags) // list view specific
  1748. {
  1749. // only for listviews
  1750. if (sbar->nBarType == SB_HORZ)
  1751. {
  1752. SCROLLINFO info;
  1753. info.cbSize = sizeof(SCROLLINFO);
  1754. info.fMask = SIF_TRACKPOS;
  1755. if (GetScrollInfo(hwnd, SB_HORZ, &info))
  1756. {
  1757. INT dx = pos - info.nTrackPos;
  1758. if (LVS_LIST == (LVS_TYPEMASK & GetWindowLongPtrW(hwnd, GWL_STYLE)))
  1759. {
  1760. INT cw = (INT)(INT_PTR)SendMessageW(hwnd, LVM_GETCOLUMNWIDTH, 0, 0L);
  1761. dx = dx * cw;
  1762. }
  1763. SendMessageW(hwnd, LVM_SCROLL, dx, 0);
  1764. }
  1765. }
  1766. else if (sbar->nBarType == SB_VERT)
  1767. {
  1768. SCROLLINFO info;
  1769. info.cbSize = sizeof(SCROLLINFO);
  1770. info.fMask = SIF_TRACKPOS;
  1771. if (GetScrollInfo(hwnd, SB_VERT, &info) && pos != info.nTrackPos)
  1772. {
  1773. INT dy = pos - info.nTrackPos;
  1774. if (LVS_REPORT == (LVS_TYPEMASK & GetWindowLongPtrW(hwnd, GWL_STYLE)))
  1775. {
  1776. ListView_ScrollReportModeVert(hwnd, dy, (0 != (SWS_HIDEHSCROLL & scrollFlags)));
  1777. }
  1778. else
  1779. {
  1780. SendMessageW(hwnd, LVM_SCROLL, 0, dy);
  1781. }
  1782. }
  1783. }
  1784. }
  1785. else if ((SWS_TREEVIEW & scrollFlags) &&
  1786. SB_VERT == sbar->nBarType &&
  1787. ABS(nLastPos - pos) < 2)
  1788. {
  1789. INT i, cmd;
  1790. i = nLastPos - pos;
  1791. cmd = (i < 0) ? SB_LINEDOWN : SB_LINEUP;
  1792. if (i < 0) i = -i;
  1793. while (i--)
  1794. {
  1795. SendMessageW(hwnd, WM_VSCROLL, cmd, 0L);
  1796. }
  1797. }
  1798. else
  1799. {
  1800. si->nTrackPos = pos;
  1801. SCROLLINFO info;
  1802. info.cbSize = sizeof(SCROLLINFO);
  1803. info.fMask = SIF_TRACKPOS|SIF_POS;
  1804. info.nTrackPos = pos;
  1805. info.nPos = pos;
  1806. SetScrollInfo(hwnd, sbar->nBarType, &info, FALSE);
  1807. SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBTRACK, pos);
  1808. }
  1809. }
  1810. nLastPos = pos;
  1811. if (SB_VERT == sbar->nBarType) RotateRect(&rcThumbBounds);
  1812. }
  1813. //
  1814. // remember to rotate the thumb bounds rectangle!!
  1815. //
  1816. //
  1817. // Called when we have set the capture from the NCLButtonDown(...)
  1818. //
  1819. void SkinnedScrollWnd::OnMouseMove(UINT nFlags, POINTS pts)
  1820. {
  1821. RECT rect;
  1822. //static UINT lastbutton = 0;
  1823. RECT winrect;
  1824. //UINT buttonIdx = 0;
  1825. SCROLLBAR *psb;
  1826. if (nFlags)
  1827. {
  1828. if (MK_LBUTTON & nFlags)
  1829. {
  1830. UpdateScrollBars(TRUE);
  1831. }
  1832. }
  1833. psb = (uCurrentScrollbar == SB_VERT) ? psbVert : psbHorz;
  1834. if (CSBS_TRACKING & psb->fScrollFlags)
  1835. {
  1836. ThumbTrack(psb, hwnd, pts, scrollFlags);
  1837. InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar);
  1838. return;
  1839. }
  1840. if (uCurrentScrollPortion == HTSCROLL_NONE)
  1841. {
  1842. __super::WindowProc(WM_MOUSEMOVE, (WPARAM)nFlags, *(LPARAM*)&pts);
  1843. return;
  1844. }
  1845. else
  1846. {
  1847. static UINT lastportion = 0;
  1848. POINT pt;
  1849. POINTSTOPOINT(pt, pts);
  1850. MapWindowPoints(hwnd, HWND_DESKTOP, &pt, 1);
  1851. GetWindowRect(hwnd, &winrect);
  1852. //get the total area of the normal scrollbar area
  1853. GetScrollRect(this, psb->nBarType, &rect);
  1854. //see if we clicked in the inserted buttons / normal scrollbar
  1855. //thisportion = GetPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam));
  1856. UINT thisportion = GetPortion(psb, hwnd, &rect, pt.x, pt.y, scrollFlags);
  1857. //we need to do different things depending on if the
  1858. //user is activating the scrollbar itself, or one of
  1859. //the inserted buttons
  1860. switch (uCurrentScrollPortion)
  1861. {
  1862. //The scrollbar is active
  1863. case HTSCROLL_LEFT:
  1864. case HTSCROLL_RIGHT:
  1865. case HTSCROLL_THUMB:
  1866. case HTSCROLL_PAGELEFT:
  1867. case HTSCROLL_PAGERIGHT:
  1868. case HTSCROLL_NONE:
  1869. //adjust the total scroll area to become where the scrollbar
  1870. //really is (take into account the inserted buttons)
  1871. GetRealScrollRect(psb, &rect, scrollFlags);
  1872. OffsetRect(&rect, -winrect.left, -winrect.top);
  1873. if (thisportion != uCurrentScrollPortion)
  1874. {
  1875. uScrollTimerPortion = HTSCROLL_NONE;
  1876. if (lastportion != thisportion)
  1877. {
  1878. InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar);
  1879. }
  1880. }
  1881. //otherwise, draw the button in its depressed / clicked state
  1882. else
  1883. {
  1884. uScrollTimerPortion = uCurrentScrollPortion;
  1885. if (lastportion != thisportion)
  1886. {
  1887. InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar);
  1888. }
  1889. }
  1890. break;
  1891. }
  1892. lastportion = thisportion;
  1893. //lastbutton = buttonIdx;
  1894. //must return zero here, because we might get cursor anomilies
  1895. //CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam);
  1896. return;
  1897. }
  1898. }
  1899. //
  1900. // We must allocate from in the non-client area for our scrollbars
  1901. // Call the default window procedure first, to get the borders (if any)
  1902. // allocated some space, then allocate the space for the scrollbars
  1903. // if they fit
  1904. //
  1905. INT SkinnedScrollWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *pncsp)
  1906. {
  1907. RECT *prc;
  1908. INT hcy, vcx, result;
  1909. BOOL bSizingDown;
  1910. prc = &pncsp->rgrc[0];
  1911. UINT updateBars = -1;
  1912. hcy = GetScrollMetric(psbHorz, SM_CYHORZSB, scrollFlags);
  1913. vcx = GetScrollMetric(psbVert, SM_CXVERTSB, scrollFlags);
  1914. if (SWS_UPDATEFRAME & scrollFlags)
  1915. {
  1916. // need to reset style
  1917. DWORD style;
  1918. scrollFlags &= ~SWS_UPDATEFRAME;
  1919. style = (DWORD)GetWindowLongPtrW(hwnd, GWL_STYLE);
  1920. if ((WS_HSCROLL | WS_VSCROLL) & style) SetWindowLongPtrW(hwnd, GWL_STYLE, style & ~(WS_HSCROLL | WS_VSCROLL));
  1921. CallDefWndProc(WM_NCCALCSIZE, (WPARAM)bCalcValidRects, (LPARAM)pncsp);
  1922. if ((WS_HSCROLL | WS_VSCROLL) & style) SetWindowLongPtrW(hwnd, GWL_STYLE, style);
  1923. }
  1924. result = __super::OnNcCalcSize(bCalcValidRects, pncsp);
  1925. bSizingDown = (bCalcValidRects &&
  1926. ((pncsp->rgrc[0].right - pncsp->rgrc[0].left) < (pncsp->rgrc[1].right - pncsp->rgrc[1].left) ||
  1927. (pncsp->rgrc[0].bottom - pncsp->rgrc[0].top) < (pncsp->rgrc[1].bottom - pncsp->rgrc[1].top)));
  1928. //if there is room, allocate some space for the horizontal scrollbar
  1929. //NOTE: Change the ">" to a ">=" to make the horz bar totally fill the
  1930. //window before disappearing
  1931. if ((psbHorz->fScrollFlags & CSBS_VISIBLE) && (prc->bottom - prc->top)
  1932. #ifdef COOLSB_FILLWINDOW
  1933. >=
  1934. #else
  1935. >
  1936. #endif
  1937. hcy)
  1938. {
  1939. prc->bottom -= hcy;
  1940. if (TRUE != psbHorz->fScrollVisible)
  1941. {
  1942. psbHorz->fScrollVisible = TRUE;
  1943. updateBars = SB_HORZ;
  1944. }
  1945. }
  1946. else
  1947. {
  1948. if (FALSE != psbHorz->fScrollVisible)
  1949. {
  1950. psbHorz->fScrollVisible = FALSE;
  1951. updateBars = SB_HORZ;
  1952. }
  1953. }
  1954. //if there is room, allocate some space for the vertical scrollbar
  1955. if ((psbVert->fScrollFlags & CSBS_VISIBLE) && (prc->right - prc->left) >= vcx)
  1956. {
  1957. if (SWS_LEFT & scrollFlags) prc->left += vcx;
  1958. else prc->right -= vcx;
  1959. if (TRUE != psbVert->fScrollVisible)
  1960. {
  1961. psbVert->fScrollVisible = TRUE;
  1962. updateBars = (SB_HORZ == updateBars) ? SB_BOTH : SB_VERT;
  1963. }
  1964. }
  1965. else
  1966. {
  1967. if (FALSE != psbVert->fScrollVisible)
  1968. {
  1969. psbVert->fScrollVisible = FALSE;
  1970. updateBars = (SB_HORZ == updateBars) ? SB_BOTH : SB_VERT;
  1971. }
  1972. }
  1973. if (-1 != updateBars)
  1974. {
  1975. if (SWS_COMBOLBOX & scrollFlags)
  1976. {
  1977. InvalidateNC(InvalidateFlag_RedrawNow, updateBars);
  1978. }
  1979. else if (bSizingDown)
  1980. {
  1981. PostMessageW(hwnd, WM_ML_IPC, TRUE, IPC_ML_SKINNEDSCROLLWND_UPDATEBARS);
  1982. }
  1983. }
  1984. return result;
  1985. }
  1986. void SkinnedScrollWnd::OnNcMouseLeave()
  1987. {
  1988. if (HTSCROLL_NONE != scrollPortionHover)
  1989. {
  1990. scrollPortionHover=HTSCROLL_NONE;
  1991. InvalidateNC(InvalidateFlag_Normal, SB_BOTH);
  1992. }
  1993. }
  1994. //
  1995. // used for hot-tracking over the scroll buttons
  1996. //
  1997. void SkinnedScrollWnd::OnNcMouseMove(UINT nHitTest, POINTS pts)
  1998. {
  1999. if (!bDoHover)
  2000. {
  2001. __super::WindowProc(WM_NCMOUSEMOVE, nHitTest, *(LPARAM*)&pts);
  2002. return;
  2003. }
  2004. SCROLLBAR *psb=0;
  2005. UINT scrollbar=0;
  2006. RECT rect;
  2007. if (psbHorz) psbHorz->fScrollFlags &= ~CSBS_HOVERING;
  2008. if (psbVert) psbVert->fScrollFlags &= ~CSBS_HOVERING;
  2009. if (HTHSCROLL == nHitTest)
  2010. {
  2011. psb = psbHorz;
  2012. scrollbar = SB_HORZ;
  2013. //get the total area of the normal Horz scrollbar area
  2014. GetHScrollRect(this, &rect);
  2015. }
  2016. //
  2017. // VERTICAL SCROLLBAR PROCESSING
  2018. //
  2019. else if (HTVSCROLL== nHitTest)
  2020. {
  2021. psb = psbVert;
  2022. scrollbar = SB_VERT;
  2023. //get the total area of the normal Horz scrollbar area
  2024. GetVScrollRect(this, &rect);
  2025. }
  2026. //
  2027. // NORMAL PROCESSING
  2028. //
  2029. else
  2030. {
  2031. scrollPortionHover=HTSCROLL_NONE;
  2032. __super::WindowProc(WM_NCMOUSEMOVE, nHitTest, *(LPARAM*)&pts);
  2033. return;
  2034. }
  2035. if (NULL != psb)
  2036. {
  2037. psb->fScrollFlags |= CSBS_HOVERING;
  2038. UINT thisportion = GetPortion(psb, hwnd, &rect, pts.x, pts.y, scrollFlags);
  2039. if (thisportion != scrollPortionHover)
  2040. {
  2041. TRACKMOUSEEVENT tracker;
  2042. tracker.cbSize = sizeof(tracker);
  2043. tracker.hwndTrack = hwnd;
  2044. tracker.dwHoverTime=0;
  2045. tracker.dwFlags = TME_LEAVE |TME_NONCLIENT; // benski> TME_NONCLIENT doesn't work on NT4.0, and we can work around it anyway
  2046. if (TrackMouseEvent(&tracker))
  2047. {
  2048. scrollPortionHover=thisportion;
  2049. InvalidateNC(InvalidateFlag_Normal, scrollbar);
  2050. }
  2051. }
  2052. }
  2053. __super::WindowProc(WM_NCMOUSEMOVE, nHitTest, *(LPARAM*)&pts);
  2054. }
  2055. //
  2056. // Timer routine to generate scrollbar messages
  2057. //
  2058. void SkinnedScrollWnd::OnTimer(UINT_PTR idEvent, TIMERPROC fnTimer)
  2059. {
  2060. //let all timer messages go past if we don't have a timer installed ourselves
  2061. if (uScrollTimerId != 0)
  2062. {
  2063. //if the first timer goes off, then we can start a more
  2064. //regular timer interval to auto-generate scroll messages
  2065. //this gives a slight pause between first pressing the scroll arrow, and the
  2066. //actual scroll starting
  2067. if (idEvent == COOLSB_TIMERID1)
  2068. {
  2069. KillTimer(hwnd, uScrollTimerId);
  2070. uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID2, COOLSB_TIMERINTERVAL2, 0);
  2071. return;
  2072. }
  2073. //send the scrollbar message repeatedly
  2074. else if (idEvent == COOLSB_TIMERID2)
  2075. {
  2076. //need to process a spoof WM_MOUSEMOVE, so that
  2077. //we know where the mouse is each time the scroll timer goes off.
  2078. //This is so we can stop sending scroll messages if the thumb moves
  2079. //under the mouse.
  2080. POINT pt;
  2081. GetCursorPos(&pt);
  2082. MapWindowPoints(HWND_DESKTOP, hwnd, &pt, 1);
  2083. pt.x = POINTTOPOINTS(pt);
  2084. OnMouseMove(MK_LBUTTON, MAKEPOINTS(pt.x));
  2085. if (uScrollTimerPortion != HTSCROLL_NONE) SendScrollMessage(hwnd, uScrollTimerMsg, uScrollTimerPortion, 0);
  2086. UpdateScrollBars(TRUE);
  2087. return;
  2088. }
  2089. }
  2090. __super::WindowProc(WM_TIMER, (WPARAM)idEvent, (LPARAM)fnTimer);
  2091. }
  2092. //
  2093. // We must intercept any calls to SetWindowLong, to check if
  2094. // left-scrollbars are taking effect or not
  2095. //
  2096. static UINT curTool = -1;
  2097. static LRESULT SendToolTipMessage0(HWND hwndTT, UINT message, WPARAM wParam, LPARAM lParam)
  2098. {
  2099. return SendMessageW(hwndTT, message, wParam, lParam);
  2100. }
  2101. #ifdef COOLSB_TOOLTIPS
  2102. #define SendToolTipMessage SendToolTipMessage0
  2103. #else
  2104. #define SendToolTipMessage 1 ? (void)0 : SendToolTipMessage0
  2105. #endif
  2106. void SkinnedScrollWnd::OnStyleChanged(INT styleType, STYLESTRUCT *pss)
  2107. {
  2108. if (styleType == GWL_EXSTYLE) scrollFlags = (scrollFlags & ~SWS_LEFT) | ((WS_EX_LEFTSCROLLBAR & pss->styleNew) ? SWS_LEFT : 0);
  2109. __super::OnStyleChanged(styleType, pss);
  2110. }
  2111. LRESULT SkinnedScrollWnd::OnEraseBackground(HDC hdc)
  2112. {
  2113. if (0 == (CSBS_TRACKING & psbVert->fScrollFlags) && 0 == (CSBS_TRACKING & psbHorz->fScrollFlags) && uCurrentScrollPortion == HTSCROLL_NONE)
  2114. {
  2115. LRESULT result;
  2116. result = __super::WindowProc(WM_ERASEBKGND, (WPARAM)hdc, 0L);
  2117. UpdateScrollBars(TRUE);
  2118. return result;
  2119. }
  2120. return __super::WindowProc(WM_ERASEBKGND, (WPARAM)hdc, 0L);
  2121. }
  2122. void SkinnedScrollWnd::OnPrint(HDC hdc, UINT options)
  2123. {
  2124. if ((PRF_NONCLIENT & options) &&
  2125. (0 == (PRF_CHECKVISIBLE & options) || IsWindowVisible(hwnd)))
  2126. {
  2127. PaintNonClient(hdc);
  2128. if (PRF_CLIENT & options)
  2129. CallPrevWndProc(WM_PRINT, (WPARAM)hdc, (LPARAM)(~(PRF_NONCLIENT | PRF_CHECKVISIBLE) & options));
  2130. }
  2131. else __super::OnPrint(hdc, options);
  2132. }
  2133. LRESULT SkinnedScrollWnd::OnListViewScroll(INT dx, INT dy)
  2134. {
  2135. if (0 != dy &&
  2136. 0 != (SWS_LISTVIEW & scrollFlags) &&
  2137. 0 != (SWS_HIDEHSCROLL & scrollFlags) &&
  2138. (psbHorz->scrollInfo.nPage <= (UINT)psbHorz->scrollInfo.nMax))
  2139. {
  2140. DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
  2141. if (LVS_REPORT == (LVS_TYPEMASK & windowStyle))
  2142. {
  2143. SCROLLINFO scrollInfo;
  2144. scrollInfo.cbSize = sizeof(SCROLLINFO);
  2145. scrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
  2146. if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo))
  2147. {
  2148. if (0 == dy ||
  2149. (scrollInfo.nPos == scrollInfo.nMin && dy < 0) ||
  2150. (scrollInfo.nPos >= (scrollInfo.nMax - (INT)scrollInfo.nPage) && dy > 0))
  2151. return TRUE;
  2152. RECT rc;
  2153. rc.left = LVIR_BOUNDS;
  2154. if (SendMessageW(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rc))
  2155. {
  2156. dy = dy / (rc.bottom - rc.top);
  2157. if (dy < 0)
  2158. {
  2159. if ((scrollInfo.nPos - dy) < scrollInfo.nMin)
  2160. dy = scrollInfo.nMin - scrollInfo.nPos;
  2161. }
  2162. else if (dy > 0)
  2163. {
  2164. if ((scrollInfo.nPos + dy) >= (scrollInfo.nMax - (INT)scrollInfo.nPage))
  2165. dy = scrollInfo.nMax - (INT)scrollInfo.nPage - scrollInfo.nPos;
  2166. }
  2167. dy = dy * (rc.bottom - rc.top);
  2168. if (0 == dy)
  2169. return TRUE;
  2170. }
  2171. }
  2172. }
  2173. }
  2174. LRESULT result = __super::WindowProc(LVM_SCROLL, (WPARAM)dx, (LPARAM)dy);
  2175. if (result) UpdateScrollBars(TRUE);
  2176. return result;
  2177. }
  2178. void SkinnedScrollWnd::OnVertScroll(UINT code, UINT pos, HWND hwndSB)
  2179. {
  2180. if (0 != (SWS_LISTVIEW & scrollFlags) &&
  2181. 0 != (SWS_HIDEHSCROLL & scrollFlags) &&
  2182. (psbHorz->scrollInfo.nPage <= (UINT)psbHorz->scrollInfo.nMax))
  2183. {
  2184. DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
  2185. if (LVS_REPORT == (LVS_TYPEMASK & windowStyle))
  2186. {
  2187. SCROLLINFO scrollInfo;
  2188. scrollInfo.cbSize = sizeof(SCROLLINFO);
  2189. switch(code)
  2190. {
  2191. case SB_LINEDOWN:
  2192. scrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
  2193. if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo)
  2194. && scrollInfo.nPos >= (scrollInfo.nMax - (INT)scrollInfo.nPage))
  2195. return;
  2196. break;
  2197. }
  2198. }
  2199. }
  2200. __super::WindowProc(WM_VSCROLL, MAKEWPARAM(code, pos), (LPARAM)hwndSB);
  2201. }
  2202. void SkinnedScrollWnd::OnMouseWheel(INT delta, UINT vtKey, POINTS pts)
  2203. {
  2204. if (0 == delta)
  2205. return;
  2206. if (0 != (SWS_LISTVIEW & scrollFlags))
  2207. {
  2208. DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
  2209. if (LVS_REPORT == (LVS_TYPEMASK & windowStyle))
  2210. {
  2211. if (0 != (WS_VSCROLL & windowStyle))
  2212. {
  2213. unsigned int wheelScroll;
  2214. int scrollLines, distance;
  2215. if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &wheelScroll, 0))
  2216. wheelScroll = 3;
  2217. if (0 == wheelScroll)
  2218. return;
  2219. if (WHEEL_PAGESCROLL == wheelScroll)
  2220. {
  2221. SendMessageW(hwnd, WM_VSCROLL, MAKEWPARAM(((delta > 0) ? SB_PAGEUP : SB_PAGEDOWN), 0), 0L);
  2222. SendMessageW(hwnd, WM_VSCROLL, MAKEWPARAM(SB_ENDSCROLL, 0), 0L);
  2223. return;
  2224. }
  2225. distance = delta + wheelCarryover;
  2226. scrollLines = distance * (INT)wheelScroll / WHEEL_DELTA;
  2227. wheelCarryover = distance - scrollLines * WHEEL_DELTA / (INT)wheelScroll;
  2228. if (ListView_ScrollReportModeVert(hwnd, -scrollLines, (0 != (SWS_HIDEHSCROLL & scrollFlags))))
  2229. {
  2230. InvalidateNC(InvalidateFlag_RedrawNow, SB_VERT);
  2231. return;
  2232. }
  2233. }
  2234. else if (0 != (SWS_HIDEHSCROLL & scrollFlags))
  2235. {
  2236. return;
  2237. }
  2238. }
  2239. }
  2240. __super::WindowProc(WM_MOUSEWHEEL, MAKEWPARAM(vtKey, delta), *(LPARAM*)&pts);
  2241. }
  2242. void SkinnedScrollWnd::UpdateFrame()
  2243. {
  2244. if (SWS_UPDATEFRAME & scrollFlags)
  2245. {
  2246. SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_NOREDRAW);
  2247. }
  2248. }
  2249. void SkinnedScrollWnd::OnSkinChanged(BOOL bNotifyChildren, BOOL bRedraw)
  2250. {
  2251. UINT newFlag = scrollFlags & ~SWS_USEFREEFORM;
  2252. if (UseFreeformScrollbars())
  2253. newFlag |= SWS_USEFREEFORM;
  2254. if (newFlag != scrollFlags)
  2255. {
  2256. RECT rcOld;
  2257. GetClientRect(hwnd, &rcOld);
  2258. scrollFlags = newFlag;
  2259. SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
  2260. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOREDRAW);
  2261. }
  2262. __super::OnSkinChanged(bNotifyChildren, bRedraw);
  2263. if (FALSE != bRedraw)
  2264. RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE |RDW_ERASE | RDW_FRAME);
  2265. }
  2266. LRESULT SkinnedScrollWnd::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  2267. {
  2268. switch (uMsg)
  2269. {
  2270. /*case SBM_GETSCROLLINFO:
  2271. {
  2272. SCROLLINFO *scrollInfo = (SCROLLINFO *)lParam;
  2273. int x=0;
  2274. x=0;
  2275. }
  2276. break;*/
  2277. case WM_NCMOUSEMOVE: OnNcMouseMove((UINT)wParam, MAKEPOINTS(lParam)); return 0;
  2278. case WM_NCRBUTTONDOWN:
  2279. case WM_NCRBUTTONUP:
  2280. case WM_NCMBUTTONDOWN:
  2281. case WM_NCMBUTTONUP: if (wParam == HTHSCROLL || wParam == HTVSCROLL) return 0;
  2282. break;
  2283. case WM_NCLBUTTONDBLCLK: if (wParam != HTHSCROLL && wParam != HTVSCROLL) break; // else fall to the nclbuttondown
  2284. case WM_NCLBUTTONDOWN: OnNcLButtonDown((UINT)wParam, MAKEPOINTS(lParam)); return 0;
  2285. case WM_NCMOUSELEAVE:
  2286. case WM_MOUSELEAVE: OnNcMouseLeave(); break;
  2287. case WM_LBUTTONUP: OnLButtonUp((UINT)wParam, MAKEPOINTS(lParam)); return 0;
  2288. case WM_MOUSEMOVE: OnMouseMove((UINT)wParam, MAKEPOINTS(lParam)); return 0;
  2289. case WM_TIMER: OnTimer((UINT_PTR)wParam, (TIMERPROC)lParam); return 0;
  2290. case WM_ERASEBKGND: return OnEraseBackground((HDC)wParam);
  2291. case WM_DISPLAYCHANGE:
  2292. SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSENDCHANGING);
  2293. break;
  2294. case WM_CAPTURECHANGED:
  2295. if (!ignoreCaptureChange)
  2296. {
  2297. LONG pts = GetMessagePos();
  2298. POINT pt;
  2299. POINTSTOPOINT(pt, pts);
  2300. MapWindowPoints(HWND_DESKTOP, hwnd, &pt, 1);
  2301. pts = POINTTOPOINTS(pt);
  2302. Emulate_LeftButtonUp((UINT)wParam, MAKEPOINTS(pts), FALSE);
  2303. }
  2304. break;
  2305. // sometimes update frame required when this messges arrive
  2306. case WM_ACTIVATE:
  2307. case WM_SETFOCUS:
  2308. case WM_HSCROLL:
  2309. {
  2310. LRESULT result = __super::WindowProc(uMsg, wParam, lParam);
  2311. UpdateFrame();
  2312. return result;
  2313. }
  2314. break;
  2315. case WM_MOUSEWHEEL:
  2316. OnMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), MAKEPOINTS(lParam));
  2317. UpdateFrame();
  2318. return 0;
  2319. case WM_VSCROLL:
  2320. OnVertScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
  2321. UpdateFrame();
  2322. return 0;
  2323. case LVM_SCROLL:
  2324. if (SWS_LISTVIEW & scrollFlags)
  2325. return OnListViewScroll((INT)wParam, (INT)lParam);
  2326. break;
  2327. case WM_KEYDOWN:
  2328. if (0 != ((SWS_LISTVIEW | SWS_TREEVIEW ) & scrollFlags))
  2329. {
  2330. LRESULT result = __super::WindowProc(uMsg, wParam, lParam);
  2331. switch(wParam)
  2332. {
  2333. case VK_PRIOR:
  2334. case VK_NEXT:
  2335. case VK_UP:
  2336. case VK_DOWN:
  2337. case VK_HOME:
  2338. case VK_END:
  2339. UpdateScrollBars(TRUE);
  2340. break;
  2341. }
  2342. return result;
  2343. }
  2344. break;
  2345. case WM_USER + 0x3443:
  2346. UpdateScrollBars(TRUE);
  2347. break;
  2348. }
  2349. return __super::WindowProc(uMsg, wParam, lParam);
  2350. }
  2351. //
  2352. // return the default minimum size of a scrollbar thumb
  2353. //
  2354. static int WINAPI CoolSB_GetDefaultMinThumbSize(void)
  2355. {
  2356. DWORD dwVersion = GetVersion();
  2357. // set the minimum thumb size for a scrollbar. This
  2358. // differs between NT4 and 2000, so need to check to see
  2359. // which platform we are running under
  2360. return (dwVersion >= 0x80000000 && LOBYTE(LOWORD(dwVersion)) >= 5) ? MINTHUMBSIZE_2000 : MINTHUMBSIZE_NT4;
  2361. }
  2362. BOOL SkinnedScrollWnd::ShowScrollBar(int wBar, BOOL fShow)
  2363. {
  2364. DWORD styleOld, styleNew;
  2365. styleOld = GetWindowLongPtrW(hwnd, GWL_STYLE);
  2366. styleNew = styleOld;
  2367. if (wBar == SB_HORZ || wBar == SB_BOTH)
  2368. {
  2369. psbHorz->fScrollFlags = (psbHorz->fScrollFlags & ~CSBS_VISIBLE) | ((fShow) ? CSBS_VISIBLE : 0);
  2370. styleNew = (styleNew & ~WS_HSCROLL) | ((fShow) ? WS_HSCROLL :0);
  2371. }
  2372. if (wBar == SB_VERT || wBar == SB_BOTH)
  2373. {
  2374. psbVert->fScrollFlags = (psbVert->fScrollFlags & ~CSBS_VISIBLE) | ((fShow) ? CSBS_VISIBLE : 0);
  2375. styleNew = (styleNew & ~WS_VSCROLL) | ((fShow) ? WS_VSCROLL :0);
  2376. }
  2377. if (styleNew != styleOld)
  2378. {
  2379. SetWindowLongPtrW(hwnd, GWL_STYLE, styleNew);
  2380. SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOREDRAW);
  2381. }
  2382. return TRUE;
  2383. }
  2384. SkinnedScrollWnd::SkinnedScrollWnd(BOOL bIsDialog)
  2385. : SkinnedWnd(bIsDialog), psbHorz(0), psbVert(0),
  2386. scrollFlags(0), scrollPortionHover(0), wheelCarryover(0)
  2387. {
  2388. if (-1 == bUseUpdateRgn)
  2389. {
  2390. OSVERSIONINFO osver = {0};
  2391. osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  2392. if (::GetVersionEx(&osver))
  2393. {
  2394. bUseUpdateRgn =
  2395. ((VER_PLATFORM_WIN32_NT != osver.dwPlatformId ||
  2396. (osver.dwMajorVersion < 6 && osver.dwMinorVersion != 2)));
  2397. bDoHover = !(VER_PLATFORM_WIN32_NT == osver.dwPlatformId && osver.dwMajorVersion == 4); // can't use TrackMouseEvent with non-client areas on Windows NT 4.0
  2398. }
  2399. }
  2400. }
  2401. BOOL SkinnedScrollWnd::Attach(HWND hwndToSkin)
  2402. {
  2403. DWORD style;
  2404. if (!SkinnedWnd::Attach(hwndToSkin))
  2405. return FALSE;
  2406. SetType(SKINNEDWND_TYPE_SCROLLWND);
  2407. psbHorz = (SCROLLBAR*)calloc(1, sizeof(SCROLLBAR));
  2408. psbVert = (SCROLLBAR*)calloc(1, sizeof(SCROLLBAR));
  2409. if (!psbHorz || !psbVert) return FALSE;
  2410. scrollFlags = 0;
  2411. wheelCarryover = 0;
  2412. psbHorz->scrollInfo.cbSize = sizeof(SCROLLINFO);
  2413. psbHorz->scrollInfo.fMask = SIF_ALL;
  2414. if (!GetScrollInfo(hwnd, SB_HORZ, &psbHorz->scrollInfo))
  2415. ZeroMemory(&psbHorz->scrollInfo, sizeof(SCROLLINFO));
  2416. psbVert->scrollInfo.cbSize = sizeof(SCROLLINFO);
  2417. psbVert->scrollInfo.fMask = SIF_ALL;
  2418. if (!GetScrollInfo(hwnd, SB_VERT, &psbVert->scrollInfo))
  2419. ZeroMemory(&psbVert->scrollInfo, sizeof(SCROLLINFO));
  2420. scrollPortionHover = HTSCROLL_NONE;
  2421. //check to see if the window has left-aligned scrollbars
  2422. if (GetWindowLongPtrW(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR) scrollFlags |= SWS_LEFT;
  2423. style = GetWindowLongPtrW(hwnd, GWL_STYLE);
  2424. if (WS_HSCROLL & style) psbHorz->fScrollFlags = CSBS_VISIBLE;
  2425. if (WS_VSCROLL & style) psbVert->fScrollFlags = CSBS_VISIBLE;
  2426. psbHorz->nBarType = SB_HORZ;
  2427. psbVert->nBarType = SB_VERT;
  2428. //set the default arrow sizes for the scrollbars
  2429. psbHorz->nMinThumbSize = CoolSB_GetDefaultMinThumbSize();
  2430. psbVert->nMinThumbSize = psbHorz->nMinThumbSize;
  2431. scrollFlags |= SWS_UPDATEFRAME;
  2432. SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_NOREDRAW);
  2433. InvalidateNC(InvalidateFlag_Frame | InvalidateFlag_RedrawNow, SB_BOTH);
  2434. return TRUE;
  2435. }
  2436. SkinnedScrollWnd::~SkinnedScrollWnd(void)
  2437. {
  2438. InvalidateNC(InvalidateFlag_Frame | InvalidateFlag_RedrawNow, SB_BOTH);
  2439. if (psbHorz) free(psbHorz);
  2440. if (psbVert) free(psbVert);
  2441. if (hbrChecked)
  2442. {
  2443. DeleteObject(hbrChecked);
  2444. hbrChecked = NULL;
  2445. }
  2446. }
  2447. void SkinnedScrollWnd::DisableNoScroll(BOOL bDisable)
  2448. {
  2449. if (bDisable) scrollFlags |= SWS_DISABLENOSCROLL;
  2450. else scrollFlags &= ~SWS_DISABLENOSCROLL;
  2451. }
  2452. BOOL SkinnedScrollWnd::IsNoScrollDisabled()
  2453. {
  2454. return (0 != (SWS_DISABLENOSCROLL & scrollFlags));
  2455. }
  2456. void SkinnedScrollWnd::InvalidateNC(InvalidateFlags invalidate, UINT bars)
  2457. {
  2458. HRGN rgnH = NULL, rgnV = NULL;
  2459. RECT rc;
  2460. int scrollLength;
  2461. unsigned int flags;
  2462. long frameEdge, clientEdge;
  2463. if (0 != (InvalidateFlag_Frame & invalidate))
  2464. {
  2465. flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE |
  2466. SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_NOREDRAW;
  2467. SetWindowPos(hwnd, NULL, 0, 0, 0, 0, flags);
  2468. }
  2469. if (FALSE == GetClientRect(hwnd, &rc))
  2470. return;
  2471. if (SB_HORZ == bars || SB_BOTH == bars)
  2472. {
  2473. scrollLength = GetScrollMetric(psbHorz, SM_CYVERTSB, scrollFlags);
  2474. clientEdge = rc.bottom;
  2475. if (0 != (InvalidateFlag_HorzBarRemoved & invalidate))
  2476. clientEdge -= scrollLength;
  2477. frameEdge = clientEdge + scrollLength;
  2478. rgnH = CreateRectRgn(rc.left, clientEdge, rc.right, frameEdge);
  2479. }
  2480. else
  2481. rgnH = NULL;
  2482. if (SB_VERT == bars || SB_BOTH == bars)
  2483. {
  2484. scrollLength = GetScrollMetric(psbVert, SM_CXVERTSB, scrollFlags);
  2485. if (0 != (SWS_LEFT & scrollFlags))
  2486. {
  2487. clientEdge = rc.left;
  2488. if (0 == (InvalidateFlag_VertBarRemoved & invalidate))
  2489. clientEdge -= scrollLength;
  2490. }
  2491. else
  2492. {
  2493. clientEdge = rc.right;
  2494. if (0 != (InvalidateFlag_VertBarRemoved & invalidate))
  2495. clientEdge -= scrollLength;
  2496. frameEdge = clientEdge + scrollLength;
  2497. }
  2498. rgnV = CreateRectRgn(clientEdge, rc.top, frameEdge, rc.bottom);
  2499. if (NULL != rgnV && SB_BOTH == bars)
  2500. CombineRgn(rgnH, rgnH, rgnV, RGN_OR);
  2501. }
  2502. else
  2503. rgnV = NULL;
  2504. flags = RDW_INVALIDATE | /*RDW_INTERNALPAINT | RDW_ERASE |*/ RDW_FRAME | RDW_NOCHILDREN;
  2505. if (0 != (InvalidateFlag_RedrawNow & invalidate))
  2506. flags |= (RDW_UPDATENOW | RDW_ERASENOW);
  2507. HRGN rgn = ((NULL != rgnH) ? rgnH : rgnV);
  2508. if (rgn)
  2509. RedrawWindow(hwnd, NULL, rgn, flags);
  2510. if (rgnH)
  2511. DeleteRgn(rgnH);
  2512. if (rgnV)
  2513. DeleteRgn(rgnV);
  2514. }
  2515. void SkinnedScrollWnd::UpdateScrollBars(BOOL fInvalidate)
  2516. {
  2517. UINT bars;
  2518. InvalidateFlags invalidateFlags;
  2519. SCROLLINFO tsi;
  2520. tsi.cbSize = sizeof(SCROLLINFO);
  2521. tsi.fMask = SIF_ALL;
  2522. bars = -1;
  2523. invalidateFlags = InvalidateFlag_Normal /*| InvalidateFlag_RedrawNow*/;
  2524. if (0 == (SWS_HIDEHSCROLL & scrollFlags))
  2525. {
  2526. if (GetScrollInfo(hwnd, SB_HORZ, &tsi) &&
  2527. memcmp(&tsi, &psbHorz->scrollInfo, sizeof(SCROLLINFO)))
  2528. {
  2529. memcpy(&psbHorz->scrollInfo, &tsi, sizeof(SCROLLINFO));
  2530. UpdateScrollBar(psbHorz, &invalidateFlags);
  2531. psbHorz->scrollInfo.cbSize = sizeof(SCROLLINFO);
  2532. psbHorz->scrollInfo.fMask = SIF_ALL;
  2533. if (!GetScrollInfo(hwnd, SB_HORZ, &psbHorz->scrollInfo))
  2534. ZeroMemory(&psbHorz->scrollInfo, sizeof(SCROLLINFO));
  2535. bars = SB_HORZ;
  2536. }
  2537. }
  2538. else
  2539. {
  2540. psbHorz->scrollInfo.cbSize = sizeof(SCROLLINFO);
  2541. psbHorz->scrollInfo.fMask = SIF_ALL;
  2542. if (!GetScrollInfo(hwnd, SB_HORZ, &psbHorz->scrollInfo))
  2543. ZeroMemory(&psbHorz->scrollInfo, sizeof(SCROLLINFO));
  2544. }
  2545. if (0 == (SWS_HIDEVSCROLL & scrollFlags))
  2546. {
  2547. if (GetScrollInfo(hwnd, SB_VERT, &tsi))
  2548. {
  2549. if (0 != (SWS_LISTVIEW & scrollFlags) &&
  2550. LVS_REPORT == (LVS_TYPEMASK & GetWindowLongPtrW(hwnd, GWL_STYLE)))
  2551. {
  2552. if (0 != (SWS_HIDEHSCROLL & scrollFlags))
  2553. {
  2554. tsi.nMax = (int)SendMessageW(hwnd, LVM_GETITEMCOUNT, 0, 0L);
  2555. tsi.nPage = (unsigned int)SendMessageW(hwnd, LVM_GETCOUNTPERPAGE, 0, 0L);
  2556. if(tsi.nMax > 0)
  2557. tsi.nMax--;
  2558. // if (psbHorz->scrollInfo.nPage <= (UINT)psbHorz->scrollInfo.nMax)
  2559. }
  2560. }
  2561. if (memcmp(&tsi, &psbVert->scrollInfo, sizeof(SCROLLINFO)))
  2562. {
  2563. memcpy(&psbVert->scrollInfo, &tsi, sizeof(SCROLLINFO));
  2564. UpdateScrollBar(psbVert, &invalidateFlags);
  2565. bars = (SB_HORZ == bars) ? SB_BOTH : SB_VERT;
  2566. }
  2567. }
  2568. }
  2569. else
  2570. {
  2571. psbVert->scrollInfo.cbSize = sizeof(SCROLLINFO);
  2572. psbVert->scrollInfo.fMask = SIF_ALL;
  2573. if (!GetScrollInfo(hwnd, SB_VERT, &psbVert->scrollInfo))
  2574. ZeroMemory(&psbVert->scrollInfo, sizeof(SCROLLINFO));
  2575. }
  2576. if ((fInvalidate || 0 != (InvalidateFlag_Frame & invalidateFlags)) &&
  2577. -1 != bars)
  2578. {
  2579. InvalidateNC(invalidateFlags, bars);
  2580. if (0 != (InvalidateFlag_Frame & invalidateFlags) &&
  2581. 0 != (SWS_LISTVIEW & scrollFlags) &&
  2582. LVS_REPORT == (LVS_TYPEMASK & GetWindowLongPtrW(hwnd, GWL_STYLE)))
  2583. {
  2584. if (0 == (LVS_NOCOLUMNHEADER & GetWindowLongPtrW(hwnd, GWL_STYLE)))
  2585. {
  2586. HWND hHeader = (HWND)SendMessageW(hwnd, LVM_GETHEADER, 0, 0L);
  2587. if (NULL != hHeader)
  2588. {
  2589. RECT clientRect;
  2590. WINDOWPOS wp;
  2591. GetClientRect(hwnd, &clientRect);
  2592. SCROLLINFO si;
  2593. si.cbSize = sizeof(si);
  2594. si.fMask = SIF_POS;
  2595. if (0 != GetScrollInfo(hwnd, SB_HORZ, &si))
  2596. clientRect.left -= si.nPos;
  2597. HDLAYOUT layout;
  2598. layout.prc = &clientRect;
  2599. layout.pwpos = &wp;
  2600. if (FALSE != SendMessageW(hHeader, HDM_LAYOUT, 0, (LPARAM)&layout))
  2601. {
  2602. if (FALSE == fInvalidate)
  2603. wp.flags |= SWP_NOREDRAW;
  2604. SetWindowPos(hHeader, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags | SWP_NOZORDER | SWP_NOACTIVATE);
  2605. }
  2606. }
  2607. }
  2608. }
  2609. }
  2610. }
  2611. void SkinnedScrollWnd::UpdateScrollBar(SCROLLBAR *psb, InvalidateFlags *invalidateFlags)
  2612. {
  2613. SCROLLINFO *psi;
  2614. psi = &psb->scrollInfo;
  2615. if ((psi->nPage > (UINT)psi->nMax || (psi->nPage == (UINT)psi->nMax && psi->nMax == 0) || psi->nMax <= psi->nMin))
  2616. {
  2617. if (psb->fScrollVisible)
  2618. {
  2619. if (SWS_DISABLENOSCROLL & scrollFlags)
  2620. {
  2621. psb->fScrollFlags |= (ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT);
  2622. }
  2623. else
  2624. {
  2625. ShowScrollBar(psb->nBarType, FALSE);
  2626. *invalidateFlags |= InvalidateFlag_Frame;
  2627. if (SB_VERT == psb->nBarType)
  2628. *invalidateFlags |= InvalidateFlag_VertBarRemoved;
  2629. else
  2630. *invalidateFlags |= InvalidateFlag_HorzBarRemoved;
  2631. }
  2632. }
  2633. }
  2634. else
  2635. {
  2636. if ((!psb->fScrollVisible || ((ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT) & psb->fScrollFlags)) && psi->nPage > 0)
  2637. {
  2638. if ((SWS_DISABLENOSCROLL & scrollFlags) && ((ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT) & psb->fScrollFlags))
  2639. {
  2640. psb->fScrollFlags &= ~(ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT);
  2641. }
  2642. if (!psb->fScrollVisible)
  2643. {
  2644. if (SWS_LISTVIEW & scrollFlags)
  2645. {
  2646. DWORD ws = GetWindowLongPtrW(hwnd, GWL_STYLE);
  2647. if (LVS_ICON == (LVS_TYPEMASK & ws) || LVS_SMALLICON == (LVS_TYPEMASK & ws))
  2648. {
  2649. switch(LVS_ALIGNMASK & ws)
  2650. {
  2651. case LVS_ALIGNLEFT:
  2652. if (SB_HORZ != psb->nBarType) psb->nBarType = ((SB_BOTH == psb->nBarType) ? SB_HORZ : -1);
  2653. break;
  2654. case LVS_ALIGNTOP:
  2655. if (SB_VERT != psb->nBarType) psb->nBarType = ((SB_BOTH == psb->nBarType) ? SB_VERT : -1);
  2656. break;
  2657. }
  2658. }
  2659. }
  2660. if (-1 != psb->nBarType)
  2661. {
  2662. ShowScrollBar(psb->nBarType, TRUE);
  2663. *invalidateFlags |= InvalidateFlag_Frame;
  2664. if (SB_VERT == psb->nBarType)
  2665. *invalidateFlags |= InvalidateFlag_VertBarAppeared;
  2666. else
  2667. *invalidateFlags |= InvalidateFlag_HorzBarAppeared;
  2668. }
  2669. }
  2670. }
  2671. else if (psb->fScrollVisible && 0 == psi->nPage)
  2672. {
  2673. if (SWS_DISABLENOSCROLL & scrollFlags)
  2674. {
  2675. psb->fScrollFlags |= (ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT);
  2676. }
  2677. else
  2678. {
  2679. ShowScrollBar(psb->nBarType, FALSE);
  2680. *invalidateFlags |= InvalidateFlag_Frame;
  2681. if (SB_VERT == psb->nBarType)
  2682. *invalidateFlags |= InvalidateFlag_VertBarRemoved;
  2683. else
  2684. *invalidateFlags |= InvalidateFlag_HorzBarRemoved;
  2685. }
  2686. }
  2687. }
  2688. }
  2689. void SkinnedScrollWnd::ShowHorzScroll(BOOL fEnable)
  2690. {
  2691. scrollFlags = (scrollFlags & ~SWS_HIDEHSCROLL) | ((fEnable) ? 0 : SWS_HIDEHSCROLL);
  2692. psbHorz->fScrollFlags = 0;
  2693. InvalidateNC(InvalidateFlag_Frame | InvalidateFlag_RedrawNow, SB_HORZ);
  2694. }
  2695. BOOL SkinnedScrollWnd::IsHorzBarHidden()
  2696. {
  2697. return (0 != (SWS_HIDEHSCROLL & scrollFlags));
  2698. }
  2699. BOOL SkinnedScrollWnd::IsVertBarHidden()
  2700. {
  2701. return (0 != (SWS_HIDEVSCROLL & scrollFlags));
  2702. }
  2703. void SkinnedScrollWnd::ShowVertScroll(BOOL fEnable)
  2704. {
  2705. scrollFlags = (scrollFlags & ~SWS_HIDEVSCROLL) | ((fEnable) ? 0 : SWS_HIDEVSCROLL);
  2706. psbVert->fScrollFlags = 0;
  2707. InvalidateNC(InvalidateFlag_Frame | InvalidateFlag_RedrawNow, SB_VERT);
  2708. }
  2709. BOOL SkinnedScrollWnd::SetMode(UINT nMode)
  2710. {
  2711. scrollFlags &= ~(SWS_LISTVIEW | SWS_TREEVIEW | SWS_COMBOLBOX);
  2712. switch (0xFF & nMode)
  2713. {
  2714. case SCROLLMODE_STANDARD_I: return TRUE;
  2715. case SCROLLMODE_LISTVIEW_I: scrollFlags |= SWS_LISTVIEW; return TRUE;
  2716. case SCROLLMODE_TREEVIEW_I: scrollFlags |= SWS_TREEVIEW; return TRUE;
  2717. case SCROLLMODE_COMBOLBOX_I: scrollFlags |= SWS_COMBOLBOX; return TRUE;
  2718. }
  2719. return FALSE;
  2720. }
  2721. UINT SkinnedScrollWnd::GetMode()
  2722. {
  2723. if (0 != (SWS_LISTVIEW & scrollFlags))
  2724. return SCROLLMODE_STANDARD_I;
  2725. if (0 != (SWS_TREEVIEW & scrollFlags))
  2726. return SCROLLMODE_TREEVIEW_I;
  2727. if (0 != (SWS_COMBOLBOX & scrollFlags))
  2728. return SCROLLMODE_COMBOLBOX_I;
  2729. return SCROLLMODE_STANDARD_I;
  2730. }
  2731. INT SkinnedScrollWnd::AdjustHover(UINT nHitTest, POINTS pts)
  2732. {
  2733. SCROLLBAR *psb = NULL;
  2734. RECT rect;
  2735. if (psbHorz) psbHorz->fScrollFlags &= ~CSBS_HOVERING;
  2736. if (psbVert) psbVert->fScrollFlags &= ~CSBS_HOVERING;
  2737. scrollPortionHover = HTSCROLL_NONE;
  2738. if (HTHSCROLL == nHitTest)
  2739. {
  2740. psb = psbHorz;
  2741. GetHScrollRect(this, &rect);
  2742. }
  2743. else if (HTVSCROLL== nHitTest)
  2744. {
  2745. psb = psbVert;
  2746. GetVScrollRect(this, &rect);
  2747. }
  2748. if (psb)
  2749. {
  2750. psb->fScrollFlags |= CSBS_HOVERING;
  2751. scrollPortionHover = GetPortion(psb, hwnd, &rect, pts.x, pts.y, scrollFlags);
  2752. }
  2753. return scrollPortionHover;
  2754. }
  2755. BOOL SkinnedScrollWnd::OnMediaLibraryIPC(INT msg, INT_PTR param, LRESULT *pResult)
  2756. {
  2757. switch (msg)
  2758. {
  2759. case IPC_ML_SKINNEDSCROLLWND_UPDATEBARS:
  2760. UpdateScrollBars((BOOL)param);
  2761. *pResult = 1;
  2762. return TRUE;
  2763. case IPC_ML_SKINNEDSCROLLWND_SHOWHORZBAR:
  2764. ShowHorzScroll((BOOL)param);
  2765. *pResult = 1;
  2766. return TRUE;
  2767. case IPC_ML_SKINNEDSCROLLWND_SHOWVERTBAR:
  2768. ShowVertScroll((BOOL)param);
  2769. *pResult = 1;
  2770. return TRUE;
  2771. case IPC_ML_SKINNEDSCROLLWND_SETMODE:
  2772. *pResult = SetMode((UINT)param);
  2773. return TRUE;
  2774. case IPC_ML_SKINNEDSCROLLWND_DISABLENOSCROLL:
  2775. DisableNoScroll(0 != param);
  2776. *pResult = -1;
  2777. return TRUE;
  2778. case IPC_ML_SKINNEDSCROLLWND_ADJUSTHOVER:
  2779. ((SBADJUSTHOVER*)param)->nResult = AdjustHover(((SBADJUSTHOVER*)param)->hitTest, ((SBADJUSTHOVER*)param)->ptMouse);
  2780. *pResult = TRUE;
  2781. return TRUE;
  2782. case IPC_ML_SKINNEDSCROLLWND_GETHORZBARHIDDEN:
  2783. *pResult = IsHorzBarHidden();
  2784. return TRUE;
  2785. case IPC_ML_SKINNEDSCROLLWND_GETVERTBARHIDDEN:
  2786. *pResult = IsVertBarHidden();
  2787. return TRUE;
  2788. case IPC_ML_SKINNEDSCROLLWND_GETMODE:
  2789. *pResult = GetMode();
  2790. return TRUE;
  2791. case IPC_ML_SKINNEDSCROLLWND_GETNOSCROLLDISABLED:
  2792. *pResult = IsNoScrollDisabled();
  2793. return TRUE;
  2794. }
  2795. return __super::OnMediaLibraryIPC(msg, param, pResult);
  2796. }