SmoothScrollList.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837
  1. #include "main.h"
  2. #include "../Winamp/gen.h"
  3. #include "../gen_ml/ml.h"
  4. #include "../gen_ml/ml_ipc_0313.h"
  5. #define WM_EX_GETREALLIST (WM_USER + 0x01)
  6. #define WM_EX_UNLOCKREDRAW (WM_USER + 0x02)
  7. #define WM_EX_UPDATESCROLLINFO (WM_USER + 0x03)
  8. #define WM_EX_GETCOUNTPERPAGE (WM_USER + 0x04)
  9. #define LVN_EX_SIZECHANGED (LVN_LAST)
  10. #define IWF_NORMAL 0x0000
  11. #define IWF_ERASE 0x0001
  12. #define IWF_UPDATENOW 0x0002
  13. #define IWF_FRAME 0x0004
  14. typedef enum ScrollPosFlags
  15. {
  16. SPF_NORMAL = 0,
  17. SPF_NOREDRAW = (1 << 0),
  18. SPF_FORCE = (1 << 1),
  19. SPF_RELATIVE = (1 << 2),
  20. } ScrollPosFlags;
  21. DEFINE_ENUM_FLAG_OPERATORS(ScrollPosFlags);
  22. BOOL
  23. CopyListColumnToHeaderItem(const LVCOLUMNW *column, HDITEMW *item);
  24. BOOL
  25. CopyHeaderItemToListColumn(const HDITEMW *item, LVCOLUMNW *column);
  26. typedef enum PostProcessKeyCommands
  27. {
  28. PostProcessKeyCmd_Nothing = 0,
  29. PostProcessKeyCmd_UpdateScrollPos = (1 << 0),
  30. PostProcessKeyCmd_EnsureFocusVisible = (1 << 1),
  31. } PostProcessKeyCommands;
  32. DEFINE_ENUM_FLAG_OPERATORS(PostProcessKeyCommands);
  33. typedef struct SmoothScrollList
  34. {
  35. unsigned int itemHeight;
  36. unsigned int textHeight;
  37. long viewHeight;
  38. unsigned int listFontHeight;
  39. unsigned int headerFontHeight;
  40. int wheelCarryover;
  41. } SmoothScrollList;
  42. #define GetUserData(hwnd) ((SmoothScrollList*)(LONG_PTR)GetWindowLongPtrW(hwnd, GWLP_USERDATA))
  43. static LRESULT
  44. SubclassedListView_CallPrevWndProc(HWND hwnd, unsigned int message, WPARAM wParam, LPARAM lParam)
  45. {
  46. WNDPROC windowProc;
  47. windowProc = (WNDPROC)(LONG_PTR)GetWindowLongPtrW(hwnd,GWLP_USERDATA);
  48. if (NULL == windowProc)
  49. return DefWindowProcW(hwnd, message, wParam, lParam);
  50. return CallWindowProcW(windowProc, hwnd, message,wParam,lParam);
  51. }
  52. static BOOL
  53. GetViewRect(HWND hwnd, RECT *prc)
  54. {
  55. HWND headerWindow;
  56. GetClientRect(hwnd, prc);
  57. headerWindow = GetDlgItem(hwnd, 3);
  58. if (NULL != headerWindow)
  59. {
  60. RECT rh;
  61. GetWindowRect(headerWindow, &rh);
  62. MapWindowPoints(HWND_DESKTOP, headerWindow, ((POINT*)&rh) + 1, 1);
  63. prc->top = rh.bottom;
  64. }
  65. if (prc->right < prc->left)
  66. prc->right = prc->left;
  67. if (prc->bottom < prc->top)
  68. prc->bottom = prc->top;
  69. return TRUE;
  70. }
  71. static int
  72. SmoothScrollList_GetScrollPosFromItem(HWND hwnd, int iItem)
  73. {
  74. HWND listWindow;
  75. RECT listRect, viewRect;
  76. int pos;
  77. int count;
  78. pos = 0;
  79. if (FALSE == GetViewRect(hwnd, &viewRect))
  80. return 0;
  81. listWindow = GetDlgItem(hwnd, 2);
  82. if (NULL == listWindow ||
  83. FALSE == GetWindowRect(listWindow, &listRect))
  84. {
  85. return 0;
  86. }
  87. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&listRect, 2);
  88. count = (int)SendMessageW(listWindow, LVM_GETITEMCOUNT, 0, 0L);
  89. if (0 != count)
  90. {
  91. SmoothScrollList *self;
  92. if (iItem < 0)
  93. iItem = 0;
  94. if (iItem >= count)
  95. iItem = count - 1;
  96. self = GetUserData(hwnd);
  97. if (NULL != self)
  98. pos = iItem * self->itemHeight;
  99. }
  100. pos += (viewRect.top - listRect.top);
  101. return pos;
  102. }
  103. static BOOL
  104. UpdateScrollInfo(HWND hwndView, UINT fFlags, BOOL bRedraw)
  105. {
  106. RECT rv;
  107. HWND hwndList;
  108. SCROLLINFO si;
  109. BOOL needUpdate;
  110. BOOL needRedraw;
  111. HRGN regionUpdate, regionTemp;
  112. SmoothScrollList* s = GetUserData(hwndView);
  113. hwndList = GetDlgItem(hwndView, 2);
  114. if (!s || !hwndList ) return FALSE;
  115. if (FALSE!= bRedraw)
  116. {
  117. GetWindowRect(hwndView, &rv);
  118. MapWindowPoints(HWND_DESKTOP, hwndView, (POINT*)&rv, 2);
  119. regionUpdate = CreateRectRgnIndirect(&rv);
  120. GetClientRect(hwndView, &rv);
  121. regionTemp = CreateRectRgnIndirect(&rv);
  122. CombineRgn(regionUpdate, regionUpdate, regionTemp, RGN_DIFF);
  123. }
  124. else
  125. {
  126. regionUpdate = NULL;
  127. regionTemp = NULL;
  128. }
  129. si.cbSize = sizeof(SCROLLINFO);
  130. si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
  131. if (!GetScrollInfo(hwndView, SB_VERT, &si))
  132. return FALSE;
  133. if (FALSE == GetViewRect(hwndView, &rv))
  134. SetRectEmpty(&rv);
  135. needUpdate = FALSE;
  136. needRedraw = FALSE;
  137. if (SIF_RANGE & fFlags)
  138. {
  139. unsigned int count, nPage, nMax;
  140. nPage = rv.bottom - rv.top;
  141. count = (INT)SendMessageW(hwndList, LVM_GETITEMCOUNT, 0, 0L);
  142. nMax = count * s->itemHeight;
  143. if (si.nPage != nPage || si.nMax != nMax)
  144. {
  145. BOOL forcePos;
  146. unsigned int windowStyle;
  147. si.fMask = SIF_PAGE | SIF_RANGE;
  148. si.nPage = nPage;
  149. si.nMax = nMax;
  150. windowStyle = GetWindowLongPtrW(hwndView, GWL_STYLE);
  151. SetScrollInfo(hwndView, SB_VERT, &si, FALSE);
  152. needUpdate = TRUE;
  153. needRedraw = FALSE;
  154. forcePos = FALSE;
  155. if (nPage >= nMax &&
  156. 0 != (WS_VSCROLL & windowStyle))
  157. {
  158. SetWindowLongPtrW(hwndView, GWL_STYLE, windowStyle & ~WS_VSCROLL);
  159. RECT rc;
  160. HWND hwndHeader;
  161. // MLSkinnedScrollWnd_UpdateBars(hwndView, bRedraw);
  162. GetClientRect(hwndView, &rc);
  163. hwndHeader = GetDlgItem(hwndView, 3);
  164. if (hwndHeader)
  165. {
  166. HDLAYOUT headerLayout;
  167. WINDOWPOS headerPos;
  168. headerLayout.prc = &rc;
  169. headerLayout.pwpos = &headerPos;
  170. if (FALSE != SendMessageW(hwndHeader, HDM_LAYOUT, 0, (LPARAM)&headerLayout))
  171. {
  172. headerPos.flags |= SWP_NOREDRAW | SWP_NOCOPYBITS;
  173. headerPos.flags &= ~SWP_NOZORDER;
  174. headerPos.hwndInsertAfter = HWND_TOP;
  175. SetWindowPos(hwndHeader, headerPos.hwndInsertAfter, headerPos.x, headerPos.y,
  176. headerPos.cx, headerPos.cy, headerPos.flags);
  177. InvalidateRect(hwndHeader, NULL, FALSE);
  178. }
  179. }
  180. rv.right = rc.right;
  181. forcePos = TRUE;
  182. needUpdate = FALSE;
  183. needRedraw = TRUE;
  184. }
  185. if (nPage >= nMax || forcePos)
  186. {
  187. RECT rl;
  188. GetWindowRect(hwndList, &rl);
  189. MapWindowPoints(HWND_DESKTOP, hwndView, (POINT*)&rl, 2);
  190. if (rv.top != rl.top || forcePos)
  191. {
  192. SetWindowPos(hwndList, NULL, rv.left, rv.top, rv.right - rv.left, rv.bottom - rv.top,
  193. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
  194. needRedraw = TRUE;
  195. }
  196. }
  197. }
  198. }
  199. if (SIF_POS & fFlags)
  200. {
  201. INT nTop;
  202. nTop = (INT)SendMessageW(hwndList, LVM_GETTOPINDEX, 0, 0L);
  203. nTop = SmoothScrollList_GetScrollPosFromItem(hwndView, nTop);
  204. if(si.nMax > 0)
  205. {
  206. if (nTop >= (si.nMax - (int)si.nPage))
  207. nTop = (si.nMax - si.nPage) + 1;
  208. }
  209. else
  210. nTop = 0;
  211. if (nTop < si.nMin)
  212. nTop = si.nMin;
  213. if (si.nPos != nTop)
  214. {
  215. si.fMask = SIF_POS;
  216. si.nPos = nTop;
  217. SetScrollInfo(hwndView, SB_VERT, &si, (FALSE == needRedraw && FALSE != bRedraw));
  218. needUpdate = TRUE;
  219. }
  220. }
  221. if (FALSE != needUpdate)
  222. MLSkinnedScrollWnd_UpdateBars(hwndView, (FALSE == needRedraw && FALSE != bRedraw));
  223. if (FALSE != bRedraw && FALSE != needRedraw)
  224. {
  225. HRGN regionTemp2;
  226. GetWindowRect(hwndView, &rv);
  227. MapWindowPoints(HWND_DESKTOP, hwndView, (POINT*)&rv, 2);
  228. SetRectRgn(regionTemp, rv.left, rv.top, rv.right, rv.bottom);
  229. GetClientRect(hwndView, &rv);
  230. regionTemp2 = CreateRectRgnIndirect(&rv);
  231. CombineRgn(regionTemp, regionTemp, regionTemp2, RGN_DIFF);
  232. CombineRgn(regionUpdate, regionUpdate, regionTemp, RGN_OR);
  233. DeleteObject(regionTemp2);
  234. RedrawWindow(hwndView, NULL, regionUpdate, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME);
  235. }
  236. if (NULL != regionUpdate)
  237. DeleteObject(regionUpdate);
  238. if (NULL != regionTemp)
  239. DeleteObject(regionTemp);
  240. return TRUE;
  241. }
  242. static BOOL
  243. SmoothScrollList_SetScrollPos(HWND hwnd, int position, ScrollPosFlags flags)
  244. {
  245. SmoothScrollList *self;
  246. HWND listWindow;
  247. BOOL invalidate, failed;
  248. unsigned long viewStyle;
  249. int y, scrollPos;
  250. RECT rv, rl;
  251. SCROLLINFO si;
  252. listWindow = GetDlgItem(hwnd, 2);
  253. if (NULL == listWindow)
  254. return FALSE;
  255. self = GetUserData(hwnd);
  256. if (NULL == self)
  257. return FALSE;
  258. si.cbSize = sizeof(si);
  259. si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
  260. if (FALSE == GetScrollInfo(hwnd, SB_VERT, &si))
  261. return FALSE;
  262. scrollPos = si.nPos;
  263. viewStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  264. invalidate = FALSE;
  265. failed = FALSE;
  266. y = 0;
  267. if (0 != (SPF_RELATIVE & flags))
  268. {
  269. position = si.nPos + position;
  270. if (si.nPos > (si.nMax - (int)si.nPage))
  271. position -= (si.nPos - (si.nMax - (int)si.nPage));
  272. }
  273. if (position < si.nMin)
  274. position = si.nMin;
  275. if (position > (si.nMax - (INT)si.nPage + 1))
  276. position = si.nMax - si.nPage + 1;
  277. if (position == si.nPos && 0 == (SPF_FORCE & flags))
  278. return TRUE;
  279. if (FALSE == GetViewRect(hwnd, &rv))
  280. SetRectEmpty(&rv);
  281. if (FALSE == GetWindowRect(listWindow, &rl))
  282. SetRectEmpty(&rl);
  283. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rl, 2);
  284. if (0 != (WS_VISIBLE & viewStyle))
  285. SetWindowLongPtrW(hwnd, GWL_STYLE, viewStyle & ~WS_VISIBLE);
  286. if (si.nMin == position)
  287. {
  288. if (rl.top != rv.top || rl.bottom != rv.bottom || rl.left != rv.left || rl.right != rv.right)
  289. {
  290. SetWindowPos(listWindow, NULL, rv.left, rv.top, rv.right - rv.left, rv.bottom - rv.top,
  291. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
  292. invalidate = TRUE;
  293. }
  294. if (0 != (int)SendMessageW(listWindow, LVM_GETITEMCOUNT, 0, 0L))
  295. {
  296. RECT rect;
  297. rect.left = LVIR_BOUNDS;
  298. if (FALSE != SendMessageW(listWindow, LVM_GETITEMRECT, 0, (LPARAM)&rect) &&
  299. 0 != rect.top)
  300. {
  301. int scrollY;
  302. scrollY = rect.top;
  303. failed = !SendMessageW(listWindow, LVM_SCROLL, 0, scrollY);
  304. invalidate = TRUE;
  305. }
  306. }
  307. }
  308. else
  309. {
  310. int iTop, iPos;
  311. iTop = (int)SendMessageW(listWindow, LVM_GETTOPINDEX, 0, 0L);
  312. if (position > (si.nMax - (int)si.nPage))
  313. position = (si.nMax - si.nPage);
  314. iPos = position/self->itemHeight;
  315. y = (position - iPos*self->itemHeight);
  316. if (iTop > iPos)
  317. {
  318. failed = !SendMessageW(listWindow, LVM_SCROLL, 0, (iPos - iTop) * self->itemHeight);
  319. invalidate = TRUE;
  320. }
  321. if (rl.top != rv.top + y || rl.bottom != rv.bottom || rl.left != rv.left || rl.right != rv.right)
  322. {
  323. SetWindowPos(listWindow, NULL, rv.left, rv.top - y, rv.right - rv.left, rv.bottom - rv.top + y,
  324. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
  325. invalidate = TRUE;
  326. }
  327. if (iTop < iPos)
  328. {
  329. failed = !SendMessageW(listWindow, LVM_SCROLL, 0, (iPos - iTop)*self->itemHeight);
  330. invalidate = TRUE;
  331. }
  332. }
  333. if (FALSE == failed)
  334. {
  335. if (position == si.nMax - si.nPage && 0 != si.nMax)
  336. position++;
  337. if (scrollPos != position)
  338. {
  339. si.nPos = position;
  340. si.fMask = SIF_POS;
  341. SetScrollInfo(hwnd, SB_VERT, &si, (0 == (SPF_NOREDRAW & flags)));
  342. }
  343. }
  344. if (0 != (WS_VISIBLE & viewStyle))
  345. {
  346. viewStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  347. if (0 == (WS_VISIBLE & viewStyle))
  348. {
  349. viewStyle |= WS_VISIBLE;
  350. SetWindowLongPtrW(hwnd, GWL_STYLE, viewStyle);
  351. }
  352. if (0 == (SPF_NOREDRAW & flags) &&
  353. FALSE != invalidate)
  354. {
  355. InvalidateRect(listWindow, NULL, TRUE);
  356. }
  357. }
  358. return TRUE;
  359. }
  360. static BOOL
  361. SmoothScrollList_EnsureVisible(HWND hwnd, int iItem, BOOL partialOk)
  362. {
  363. int itemTop, itemBottom;
  364. int pageTop, pageBottom, delta;
  365. SCROLLINFO scrollInfo;
  366. SmoothScrollList *self;
  367. if (NULL == hwnd || iItem < 0)
  368. return FALSE;
  369. self = GetUserData(hwnd);
  370. if (NULL == self)
  371. return FALSE;
  372. scrollInfo.cbSize = sizeof(scrollInfo);
  373. scrollInfo.fMask = SIF_POS | SIF_PAGE;
  374. if (FALSE == GetScrollInfo(hwnd, SB_VERT, &scrollInfo))
  375. return FALSE;
  376. itemTop = iItem * self->itemHeight;
  377. itemBottom = itemTop + self->itemHeight;
  378. pageTop = scrollInfo.nPos;
  379. pageBottom = pageTop + scrollInfo.nPage;
  380. if (FALSE != partialOk)
  381. {
  382. if (itemTop < pageBottom &&
  383. itemBottom > pageTop)
  384. {
  385. return TRUE;
  386. }
  387. }
  388. else
  389. {
  390. if (itemTop >= pageTop &&
  391. itemBottom <= pageBottom)
  392. {
  393. return TRUE;
  394. }
  395. }
  396. if (itemTop < pageTop)
  397. delta = itemTop - pageTop;
  398. else
  399. {
  400. delta = itemBottom - pageBottom;
  401. if ((itemTop - delta) < pageTop)
  402. delta = itemTop - pageTop;
  403. }
  404. if (FALSE == SmoothScrollList_SetScrollPos(hwnd, delta, SPF_RELATIVE | SPF_FORCE))
  405. return FALSE;
  406. MLSkinnedScrollWnd_UpdateBars(hwnd, TRUE);
  407. return TRUE;
  408. }
  409. static BOOL
  410. SmoothScrollList_PreProcessKey(HWND hwnd, unsigned int vKey, unsigned int keyFlags, PostProcessKeyCommands *postProcessCommands)
  411. {
  412. HWND listWindow;
  413. RECT viewRect;
  414. SmoothScrollList *self;
  415. int iItem, iNextItem, count;
  416. BOOL shortView;
  417. if (NULL != postProcessCommands)
  418. *postProcessCommands = PostProcessKeyCmd_Nothing;
  419. switch(vKey)
  420. {
  421. case VK_UP:
  422. case VK_DOWN:
  423. case VK_HOME:
  424. case VK_END:
  425. case VK_PRIOR:
  426. case VK_NEXT:
  427. break;
  428. default:
  429. return TRUE;
  430. }
  431. if (NULL == hwnd || FALSE == GetViewRect(hwnd, &viewRect))
  432. return FALSE;
  433. self = GetUserData(hwnd);
  434. if (NULL == self)
  435. return FALSE;
  436. listWindow = GetDlgItem(hwnd, 2);
  437. if (NULL == listWindow)
  438. return FALSE;
  439. iItem = (int)SendMessageW(listWindow, LVM_GETNEXTITEM, (WPARAM)-1, (LPARAM)(LVNI_ALL | LVNI_FOCUSED));
  440. if (-1 == iItem)
  441. return FALSE;
  442. count = (int)SendMessageW(listWindow, LVM_GETITEMCOUNT, 0, 0L);
  443. iNextItem = iItem;
  444. shortView = ((viewRect.bottom - viewRect.top) < (long)self->itemHeight);
  445. switch(vKey)
  446. {
  447. case VK_UP:
  448. if (iNextItem > 0)
  449. iNextItem--;
  450. if (FALSE != shortView)
  451. {
  452. if (NULL != postProcessCommands)
  453. *postProcessCommands |= PostProcessKeyCmd_EnsureFocusVisible;
  454. }
  455. break;
  456. case VK_DOWN:
  457. if (FALSE == shortView)
  458. {
  459. if ((iNextItem + 1) < count)
  460. iNextItem++;
  461. }
  462. else
  463. {
  464. if (NULL != postProcessCommands)
  465. *postProcessCommands |= PostProcessKeyCmd_EnsureFocusVisible;
  466. }
  467. break;
  468. case VK_HOME:
  469. if (FALSE == shortView)
  470. {
  471. iNextItem = 0;
  472. }
  473. else
  474. {
  475. iNextItem = 1;
  476. if (NULL != postProcessCommands)
  477. *postProcessCommands |= PostProcessKeyCmd_UpdateScrollPos;
  478. }
  479. break;
  480. case VK_END:
  481. if (FALSE == shortView)
  482. {
  483. iNextItem = count - 1;
  484. }
  485. else
  486. {
  487. iNextItem = -1;
  488. if (NULL != postProcessCommands)
  489. *postProcessCommands |= PostProcessKeyCmd_EnsureFocusVisible;
  490. }
  491. break;
  492. case VK_PRIOR:
  493. {
  494. RECT listRect;
  495. GetWindowRect(listWindow, &listRect);
  496. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&listRect, 2);
  497. if (listRect.top != viewRect.top)
  498. SmoothScrollList_SetScrollPos(hwnd, listRect.top - viewRect.top, SPF_RELATIVE);
  499. if (FALSE == shortView)
  500. {
  501. iNextItem = (viewRect.bottom - viewRect.top)/self->itemHeight;
  502. iNextItem = iItem - iNextItem;
  503. if (iNextItem < 0)
  504. iNextItem = 0;
  505. }
  506. else
  507. {
  508. if (0 == iItem)
  509. iNextItem = 1;
  510. if (NULL != postProcessCommands)
  511. *postProcessCommands |= PostProcessKeyCmd_UpdateScrollPos;
  512. }
  513. }
  514. break;
  515. case VK_NEXT:
  516. {
  517. RECT listRect;
  518. int reminder;
  519. GetWindowRect(listWindow, &listRect);
  520. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&listRect, 2);
  521. reminder = (listRect.bottom - listRect.top)%self->itemHeight;
  522. if (0 != reminder)
  523. SmoothScrollList_SetScrollPos(hwnd, self->itemHeight - reminder, SPF_RELATIVE);
  524. if (FALSE == shortView)
  525. {
  526. iNextItem = (viewRect.bottom - viewRect.top)/self->itemHeight;
  527. iNextItem = iItem + iNextItem;
  528. if (iNextItem >= count)
  529. iNextItem = count - 1;
  530. }
  531. else
  532. {
  533. if (NULL != postProcessCommands)
  534. *postProcessCommands |= (PostProcessKeyCmd_UpdateScrollPos | PostProcessKeyCmd_EnsureFocusVisible);
  535. }
  536. }
  537. break;
  538. }
  539. if (iNextItem >= 0 && iNextItem < count)
  540. SmoothScrollList_EnsureVisible(hwnd, iNextItem, FALSE);
  541. return TRUE;
  542. }
  543. static void
  544. SmoothScrollList_PostProcessKey(HWND hwnd, unsigned int vKey, unsigned int keyFlags, PostProcessKeyCommands processCommands)
  545. {
  546. if (0 != (PostProcessKeyCmd_UpdateScrollPos & processCommands))
  547. UpdateScrollInfo(hwnd, SIF_POS, TRUE);
  548. if (0 != (PostProcessKeyCmd_EnsureFocusVisible & processCommands))
  549. {
  550. HWND listWindow = GetDlgItem(hwnd, 2);
  551. if (NULL != listWindow)
  552. {
  553. int iItem = (int)SendMessageW(listWindow, LVM_GETNEXTITEM, (WPARAM)-1, (LPARAM)(LVNI_ALL | LVNI_FOCUSED));
  554. if (-1 != iItem)
  555. {
  556. SmoothScrollList_EnsureVisible(hwnd, iItem, FALSE);
  557. }
  558. }
  559. }
  560. }
  561. static void
  562. SmoothScrollList_UpdateFontMetrics(HWND hwnd, BOOL redraw)
  563. {
  564. SmoothScrollList *self;
  565. HWND controlWindow;
  566. unsigned int windowStyle;
  567. HFONT font, prevFont;
  568. HDC hdc;
  569. TEXTMETRICW textMetrics;
  570. unsigned int fontHeight;
  571. self = GetUserData(hwnd);
  572. if (NULL == self)
  573. return;
  574. windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
  575. if(0 != (WS_VISIBLE & windowStyle))
  576. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  577. hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
  578. if (NULL != hdc)
  579. prevFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
  580. else
  581. prevFont = NULL;
  582. controlWindow = GetDlgItem(hwnd, 3);
  583. if (NULL != controlWindow)
  584. {
  585. font = (HFONT)SendMessageW(controlWindow, WM_GETFONT, 0, 0L);
  586. fontHeight = 0;
  587. if (NULL != hdc)
  588. {
  589. SelectObject(hdc, font);
  590. if (FALSE != GetTextMetricsW(hdc, &textMetrics))
  591. fontHeight = textMetrics.tmHeight;
  592. }
  593. if (self->headerFontHeight != fontHeight)
  594. {
  595. self->headerFontHeight = fontHeight;
  596. MLSkinnedHeader_SetHeight(controlWindow, -1);
  597. }
  598. }
  599. controlWindow = GetDlgItem(hwnd, 2);
  600. if (NULL != controlWindow)
  601. {
  602. font = (HFONT)SendMessageW(controlWindow, WM_GETFONT, 0, 0L);
  603. fontHeight = 0;
  604. if (NULL != hdc)
  605. {
  606. SelectObject(hdc, font);
  607. if (FALSE != GetTextMetricsW(hdc, &textMetrics))
  608. fontHeight = textMetrics.tmHeight;
  609. }
  610. if (self->listFontHeight != fontHeight)
  611. {
  612. self->listFontHeight = fontHeight;
  613. SmoothScrollList_SetScrollPos(hwnd, 0, SPF_NOREDRAW | SPF_FORCE);
  614. MLSkinnedScrollWnd_UpdateBars(hwnd, FALSE);
  615. }
  616. }
  617. if (NULL != hdc)
  618. {
  619. SelectObject(hdc, prevFont);
  620. ReleaseDC(hwnd, hdc);
  621. }
  622. if (0 != (WS_VISIBLE & windowStyle))
  623. {
  624. windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
  625. if (0 == (WS_VISIBLE & windowStyle))
  626. {
  627. windowStyle |= WS_VISIBLE;
  628. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle);
  629. }
  630. if (FALSE != redraw)
  631. RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
  632. }
  633. }
  634. static HHOOK hook = NULL;
  635. static HWND hwndToMonitor = NULL;
  636. static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
  637. {
  638. MSG *pMsg = (MSG*)lParam;
  639. if (pMsg->hwnd == hwndToMonitor)
  640. {
  641. static INT lastScrollPos = -1;
  642. switch(pMsg->message)
  643. {
  644. case WM_LBUTTONUP:
  645. case WM_RBUTTONUP:
  646. {
  647. LRESULT result = CallNextHookEx(hook, nCode, wParam, lParam);
  648. UnhookWindowsHookEx(hook);
  649. hwndToMonitor = NULL;
  650. hook = NULL;
  651. lastScrollPos = -1;
  652. return result;
  653. }
  654. case WM_MOUSEMOVE:
  655. if ((MK_LBUTTON | MK_RBUTTON) & pMsg->wParam)
  656. {
  657. RECT rw;
  658. POINTS pts(MAKEPOINTS(pMsg->lParam));
  659. POINT pt;
  660. POINTSTOPOINT(pt, pts);
  661. MapWindowPoints(pMsg->hwnd, HWND_DESKTOP, &pt, 1);
  662. GetWindowRect(pMsg->hwnd, &rw);
  663. if (pt.y < rw.top || pt.y > rw.bottom)
  664. {
  665. HWND hwndParent = GetParent(pMsg->hwnd);
  666. if (hwndParent)
  667. {
  668. SCROLLINFO si;
  669. si.cbSize = sizeof(SCROLLINFO);
  670. si.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
  671. if (GetScrollInfo(hwndParent, SB_VERT, &si))
  672. {
  673. if ((si.nPos > si.nMin && pt.y < rw.top) || (si.nPos <= (si.nMax - (INT)si.nPage) && pt.y > rw.bottom))
  674. {
  675. LRESULT result;
  676. if (lastScrollPos == si.nPos)
  677. {
  678. result = CallNextHookEx(hook, nCode, wParam, lParam);
  679. SmoothScrollList_SetScrollPos(hwndParent, (pt.y < rw.top) ? --si.nPos : ++si.nPos, SPF_NORMAL);
  680. }
  681. else
  682. {
  683. unsigned long windowStyle;
  684. windowStyle = GetWindowLongPtrW(hwndParent, GWL_STYLE);
  685. if (0 != (WS_VISIBLE & windowStyle))
  686. SetWindowLongPtrW(hwndParent, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  687. result = CallNextHookEx(hook, nCode, wParam, lParam);
  688. PostMessageW(hwndParent, WM_EX_UPDATESCROLLINFO, SIF_POS, TRUE);
  689. if (0 != (WS_VISIBLE & windowStyle))
  690. PostMessageW(hwndParent, WM_EX_UNLOCKREDRAW, IWF_UPDATENOW | IWF_FRAME, 0L);
  691. }
  692. lastScrollPos = si.nPos;
  693. return result;
  694. }
  695. }
  696. }
  697. }
  698. SleepEx(1, TRUE);
  699. }
  700. break;
  701. }
  702. }
  703. return CallNextHookEx(hook, nCode, wParam, lParam);
  704. }
  705. static LRESULT CALLBACK ListViewSubclass(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  706. if(uMsg == WM_MOUSEMOVE ||
  707. uMsg == WM_LBUTTONDOWN)
  708. {
  709. LVHITTESTINFO ht = {{LOWORD(lParam),HIWORD(lParam)},LVHT_ONITEM,-1,0};
  710. int item = ListView_SubItemHitTest(hwnd, &ht);
  711. {
  712. RECT r={0};
  713. ListView_GetItemRect(hwnd,item,&r,LVIR_BOUNDS);
  714. ht.pt.x -= r.left;
  715. ht.pt.y -= r.top;
  716. typedef struct {
  717. int x,y,item;
  718. HWND hwnd;
  719. UINT msg;
  720. } hitinfo;
  721. hitinfo info = {
  722. ht.pt.x, ht.pt.y, item, hwnd, uMsg,
  723. };
  724. SendMessage(GetParent(GetParent(hwnd)),WM_USER+700,(WPARAM)&info,0);
  725. }
  726. }
  727. switch(uMsg)
  728. {
  729. case WM_HSCROLL:
  730. case WM_VSCROLL:
  731. case WM_MOUSEWHEEL:
  732. {
  733. HWND parentWindow;
  734. KillTimer(hwnd, 43);
  735. parentWindow = GetAncestor(hwnd, GA_PARENT);
  736. if (NULL != parentWindow)
  737. return SendMessageW(parentWindow, uMsg, wParam, lParam);
  738. }
  739. break;
  740. case WM_TIMER:
  741. if (43 == wParam)
  742. {
  743. HWND parentWindow;
  744. KillTimer(hwnd, wParam);
  745. parentWindow = GetAncestor(hwnd, GA_PARENT);
  746. if (NULL != parentWindow)
  747. {
  748. int iFocused = (int)SendMessageW(hwnd, LVM_GETNEXTITEM, (WPARAM)-1, (LPARAM)(LVNI_ALL | LVNI_FOCUSED));
  749. if (-1 != iFocused)
  750. SmoothScrollList_EnsureVisible(parentWindow, iFocused, FALSE);
  751. return 0;
  752. }
  753. }
  754. break;
  755. case WM_LBUTTONDOWN:
  756. case WM_RBUTTONDOWN:
  757. case WM_MBUTTONDOWN:
  758. case WM_XBUTTONDOWN:
  759. hwndToMonitor = hwnd;
  760. hook = SetWindowsHookEx(WH_MSGFILTER, HookProc, NULL, GetCurrentThreadId());
  761. {
  762. unsigned int windowStyle;
  763. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  764. if (0 != (LVS_OWNERDRAWFIXED & windowStyle))
  765. {
  766. LRESULT result;
  767. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~LVS_OWNERDRAWFIXED);
  768. result = SubclassedListView_CallPrevWndProc(hwnd, uMsg, wParam, lParam);
  769. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  770. if (0 == (LVS_OWNERDRAWFIXED & windowStyle))
  771. {
  772. windowStyle |= LVS_OWNERDRAWFIXED;
  773. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle);
  774. }
  775. return result;
  776. }
  777. }
  778. break;
  779. case WM_KEYDOWN:
  780. {
  781. HWND parentWindow;
  782. parentWindow = GetAncestor(hwnd, GA_PARENT);
  783. if (NULL != parentWindow)
  784. {
  785. PostProcessKeyCommands postProcessKeyCommands;
  786. if (FALSE == SmoothScrollList_PreProcessKey(parentWindow,
  787. (unsigned int)wParam,
  788. (unsigned int)lParam,
  789. &postProcessKeyCommands))
  790. {
  791. postProcessKeyCommands = PostProcessKeyCmd_UpdateScrollPos;
  792. }
  793. SubclassedListView_CallPrevWndProc(hwnd, uMsg, wParam, lParam);
  794. SmoothScrollList_PostProcessKey(parentWindow,
  795. (unsigned int)wParam,
  796. (unsigned int)lParam,
  797. postProcessKeyCommands);
  798. return 0;
  799. }
  800. }
  801. break;
  802. case WM_CHAR:
  803. case WM_UNICHAR:
  804. {
  805. HWND parentWindow;
  806. parentWindow = GetAncestor(hwnd, GA_PARENT);
  807. if (NULL != parentWindow)
  808. {
  809. int iFocused;
  810. unsigned int windowStyle;
  811. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  812. if (0 != (WS_VISIBLE & windowStyle))
  813. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  814. SubclassedListView_CallPrevWndProc(hwnd, uMsg, wParam, lParam);
  815. iFocused = (int)SendMessageW(hwnd, LVM_GETNEXTITEM, (WPARAM)-1, (LPARAM)(LVNI_ALL | LVNI_FOCUSED));
  816. if (-1 != iFocused)
  817. SmoothScrollList_EnsureVisible(parentWindow, iFocused, FALSE);
  818. if (0 != (WS_VISIBLE & windowStyle))
  819. {
  820. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  821. windowStyle |= WS_VISIBLE;
  822. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle);
  823. }
  824. InvalidateRect(hwnd, NULL, FALSE);
  825. return 0;
  826. }
  827. }
  828. break;
  829. case LVM_ENSUREVISIBLE:
  830. {
  831. HWND parentWindow = GetAncestor(hwnd, GA_PARENT);
  832. if (NULL != parentWindow)
  833. return SmoothScrollList_EnsureVisible(parentWindow, (int)wParam, (BOOL)lParam);
  834. }
  835. break;
  836. }
  837. return SubclassedListView_CallPrevWndProc(hwnd, uMsg, wParam, lParam);
  838. }
  839. static LRESULT
  840. SmoothScrollList_OnCreate(HWND hwnd, CREATESTRUCT *createStruct)
  841. {
  842. HWND hwndList, hwndHeader;
  843. MLSKINWINDOW m = {0};
  844. RECT rc;
  845. DWORD style;
  846. SmoothScrollList *self = (SmoothScrollList *)calloc(1, sizeof(SmoothScrollList));
  847. if (NULL == self)
  848. return -1;
  849. self->itemHeight = 1;
  850. self->textHeight = 1;
  851. SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONGX86)(LONG_PTR)self);
  852. m.skinType = SKINNEDWND_TYPE_SCROLLWND;
  853. m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS;
  854. m.hwndToSkin = hwnd;
  855. MLSkinWindow(g_hwnd, &m);
  856. SetScrollRange(hwnd, SB_VERT, 0, 0, FALSE);
  857. MLSkinnedScrollWnd_UpdateBars(hwnd, FALSE);
  858. if (FALSE == GetClientRect(hwnd, &rc))
  859. SetRectEmpty(&rc);
  860. style = WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | HDS_BUTTONS | HDS_FULLDRAG;
  861. hwndHeader = CreateWindowExW(WS_EX_NOPARENTNOTIFY, WC_HEADERW, NULL, style,
  862. 0, 0, rc.right - rc.left, 0, hwnd, (HMENU)3,0,0);
  863. if (NULL != hwndHeader)
  864. {
  865. m.hwndToSkin = hwndHeader;
  866. m.skinType = SKINNEDWND_TYPE_HEADER;
  867. m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS;
  868. MLSkinWindow(g_hwnd, &m);
  869. }
  870. style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CHILD | WS_TABSTOP | WS_VISIBLE |
  871. LVS_REPORT | LVS_SHOWSELALWAYS | LVS_OWNERDRAWFIXED | LVS_OWNERDATA | LVS_NOCOLUMNHEADER;
  872. hwndList = CreateWindowExW(WS_EX_NOPARENTNOTIFY, WC_LISTVIEWW, NULL, style,
  873. 0, 0, rc.right - rc.left, rc.bottom - rc.top, hwnd,(HMENU)2,0,0);
  874. if (NULL != hwndList)
  875. {
  876. WNDPROC oldp = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndList, GWLP_WNDPROC, (LONGX86)(LONG_PTR)ListViewSubclass);
  877. SetWindowLongPtrW(hwndList,GWLP_USERDATA, (LONGX86)(LONG_PTR)oldp);
  878. if(NULL != hwndHeader)
  879. SetWindowPos(hwndHeader, hwndList, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  880. m.skinType = SKINNEDWND_TYPE_LISTVIEW;
  881. m.hwndToSkin = hwndList;
  882. m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS |
  883. SWLVS_FULLROWSELECT | SWLVS_DOUBLEBUFFER | SWLVS_ALTERNATEITEMS;
  884. MLSkinWindow(g_hwnd, &m);
  885. MLSkinnedScrollWnd_SetMode(hwndList, SCROLLMODE_STANDARD);
  886. MLSkinnedScrollWnd_ShowHorzBar(hwndList, FALSE);
  887. MLSkinnedScrollWnd_ShowVertBar(hwndList, FALSE);
  888. }
  889. SmoothScrollList_UpdateFontMetrics(hwnd, FALSE);
  890. return 0;
  891. }
  892. static void
  893. SmoothScrollList_OnDestroy(HWND hwnd)
  894. {
  895. SmoothScrollList *self;
  896. self = (SmoothScrollList*)(LONG_PTR)SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0);
  897. if (NULL == self)
  898. return;
  899. free(self);
  900. }
  901. static void
  902. SmoothScrollList_OnWindowPosChanged(HWND hwnd, WINDOWPOS *windowPos)
  903. {
  904. HWND controlWindow;
  905. RECT rect;
  906. long clientWidth;
  907. HWND parentWindow;
  908. SmoothScrollList *self;
  909. if ((SWP_NOSIZE | SWP_NOMOVE) == ((SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED) & windowPos->flags))
  910. return;
  911. self = GetUserData(hwnd);
  912. if (NULL == self)
  913. return;
  914. if (FALSE == GetClientRect(hwnd, &rect))
  915. return;
  916. clientWidth = rect.right - rect.left;
  917. controlWindow = GetDlgItem(hwnd, 3);
  918. if (NULL != controlWindow)
  919. {
  920. HDLAYOUT headerLayout;
  921. WINDOWPOS headerPos;
  922. headerLayout.prc = &rect;
  923. headerLayout.pwpos = &headerPos;
  924. if (FALSE != SendMessageW(controlWindow, HDM_LAYOUT, 0, (LPARAM)&headerLayout))
  925. {
  926. headerPos.flags |= ((SWP_NOREDRAW | SWP_NOCOPYBITS) & windowPos->flags);
  927. headerPos.flags &= ~SWP_NOZORDER;
  928. headerPos.hwndInsertAfter = HWND_TOP;
  929. SetWindowPos(controlWindow, headerPos.hwndInsertAfter, headerPos.x, headerPos.y,
  930. headerPos.cx, headerPos.cy, headerPos.flags);
  931. }
  932. }
  933. if (self->viewHeight != windowPos->cy ||
  934. 0 != (SWP_FRAMECHANGED & windowPos->flags))
  935. {
  936. ScrollPosFlags scrollFlags;
  937. scrollFlags = SPF_FORCE | SPF_RELATIVE;
  938. if (0 != (SWP_NOREDRAW & windowPos->flags))
  939. scrollFlags |= SPF_NOREDRAW;
  940. self->viewHeight = windowPos->cy;
  941. UpdateScrollInfo(hwnd, SIF_RANGE | SIF_POS, TRUE);
  942. SmoothScrollList_SetScrollPos(hwnd, 0, scrollFlags);
  943. }
  944. else
  945. {
  946. controlWindow = GetDlgItem(hwnd, 2);
  947. if (NULL != controlWindow)
  948. {
  949. if (FALSE != GetWindowRect(controlWindow, &rect) &&
  950. (rect.right - rect.left) != clientWidth)
  951. {
  952. SetWindowPos(controlWindow, NULL, 0, 0, clientWidth, rect.bottom - rect.top,
  953. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | ((SWP_NOREDRAW | SWP_NOCOPYBITS) & windowPos->flags));
  954. }
  955. }
  956. }
  957. parentWindow = GetAncestor(hwnd, GA_PARENT);
  958. if (NULL != parentWindow)
  959. {
  960. NMHDR hdr;
  961. hdr.code = LVN_EX_SIZECHANGED;
  962. hdr.hwndFrom = hwnd;
  963. hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID);
  964. SendMessageW(parentWindow, WM_NOTIFY, hdr.idFrom, (LPARAM)&hdr);
  965. }
  966. }
  967. static void
  968. SmoothScrollList_OnMouseWheel(HWND hwnd, INT virtualKeys, INT distance, LONG pointer_s)
  969. {
  970. SmoothScrollList *self;
  971. int pos;
  972. unsigned int wheelScroll;
  973. int scrollLines;
  974. KillTimer(hwnd, 43);
  975. self = GetUserData(hwnd);
  976. if (NULL == self)
  977. return;
  978. if (FALSE == SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &wheelScroll, 0))
  979. wheelScroll = 3;
  980. if (0 == wheelScroll)
  981. return;
  982. if (WHEEL_PAGESCROLL == wheelScroll)
  983. {
  984. SendMessageW(hwnd, WM_VSCROLL, MAKEWPARAM(((distance > 0) ? SB_PAGEUP : SB_PAGEDOWN), 0), 0L);
  985. SendMessageW(hwnd, WM_VSCROLL, MAKEWPARAM(SB_ENDSCROLL, 0), 0L);
  986. return;
  987. }
  988. distance += self->wheelCarryover;
  989. scrollLines = distance * (int)wheelScroll / WHEEL_DELTA;
  990. self->wheelCarryover = distance - scrollLines * WHEEL_DELTA / (int)wheelScroll;
  991. pos = scrollLines * (int)self->textHeight;
  992. SmoothScrollList_SetScrollPos(hwnd, -pos, SPF_RELATIVE | SPF_NORMAL);
  993. MLSkinnedScrollWnd_UpdateBars(hwnd, TRUE);
  994. }
  995. static void
  996. SmoothScrollList_OnVertScroll(HWND hwnd, INT actionLayout, INT trackPosition, HWND scrollBar)
  997. {
  998. SmoothScrollList *s;
  999. SCROLLINFO si;
  1000. int pos;
  1001. ScrollPosFlags scrollFlags;
  1002. unsigned int lineHeight;
  1003. KillTimer(hwnd, 43);
  1004. s = GetUserData(hwnd);
  1005. if (NULL == s)
  1006. return;
  1007. si.cbSize =sizeof(si);
  1008. si.fMask = SIF_PAGE | SIF_POS | SIF_TRACKPOS | SIF_RANGE;
  1009. if (FALSE == GetScrollInfo(hwnd, SB_VERT, &si))
  1010. return;
  1011. scrollFlags = SPF_NORMAL;
  1012. if (si.nPos > (si.nMax - (INT)si.nPage))
  1013. si.nPos = si.nMax - si.nPage;
  1014. lineHeight = s->textHeight * 3;
  1015. if (lineHeight > s->itemHeight)
  1016. lineHeight = s->itemHeight;
  1017. if (lineHeight > si.nPage)
  1018. lineHeight = si.nPage;
  1019. switch(actionLayout)
  1020. {
  1021. case SB_TOP: pos = si.nMin; break;
  1022. case SB_BOTTOM: pos = si.nMax; break;
  1023. case SB_LINEDOWN: pos = si.nPos + lineHeight; break;
  1024. case SB_LINEUP: pos = si.nPos - lineHeight; break;
  1025. case SB_PAGEDOWN: pos = si.nPos + (si.nPage / s->itemHeight) * s->itemHeight; break;
  1026. case SB_PAGEUP: pos = si.nPos - (si.nPage / s->itemHeight) * s->itemHeight; break;
  1027. case SB_THUMBPOSITION:
  1028. case SB_THUMBTRACK: pos = si.nTrackPos; scrollFlags |= SPF_FORCE; break;
  1029. case SB_ENDSCROLL: MLSkinnedScrollWnd_UpdateBars(hwnd, TRUE); return;
  1030. default: pos = si.nPos;
  1031. }
  1032. SmoothScrollList_SetScrollPos(hwnd, pos, scrollFlags);
  1033. }
  1034. static LRESULT
  1035. SmoothScrollList_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT *measureItem)
  1036. {
  1037. LRESULT result;
  1038. HWND parentWindow;
  1039. SmoothScrollList *self;
  1040. unsigned int itemHeight, textHeight;
  1041. BOOL updateScroll;
  1042. if(2 != measureItem->CtlID)
  1043. return FALSE;
  1044. self = GetUserData(hwnd);
  1045. updateScroll = FALSE;
  1046. itemHeight = measureItem->itemHeight;
  1047. parentWindow = GetAncestor(hwnd, GA_PARENT);
  1048. if (NULL != parentWindow)
  1049. {
  1050. measureItem->CtlID = GetWindowLongPtrW(hwnd, GWLP_ID);
  1051. result = SendMessageW(parentWindow, WM_MEASUREITEM, measureItem->CtlID, (LPARAM)measureItem);
  1052. itemHeight = measureItem->itemHeight;
  1053. }
  1054. else
  1055. result = 0;
  1056. textHeight = 12;
  1057. HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
  1058. if (NULL != hdc)
  1059. {
  1060. HFONT font, fontPrev;
  1061. TEXTMETRIC textMetrics;
  1062. font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0L);
  1063. fontPrev = (HFONT)SelectObject(hdc, font);
  1064. if (FALSE != GetTextMetrics(hdc, &textMetrics))
  1065. textHeight = textMetrics.tmHeight;
  1066. SelectObject(hdc, fontPrev);
  1067. ReleaseDC(hwnd, hdc);
  1068. }
  1069. if (NULL != self)
  1070. {
  1071. if (self->itemHeight != itemHeight)
  1072. {
  1073. SmoothScrollList_SetScrollPos(hwnd, 0, SPF_NOREDRAW);
  1074. self->itemHeight = itemHeight;
  1075. updateScroll = TRUE;
  1076. }
  1077. if (self->textHeight != textHeight)
  1078. {
  1079. self->textHeight = textHeight;
  1080. updateScroll = TRUE;
  1081. }
  1082. }
  1083. if (FALSE != updateScroll)
  1084. {
  1085. UpdateScrollInfo(hwnd, SIF_RANGE | SIF_POS, TRUE);
  1086. }
  1087. return result;
  1088. }
  1089. static void
  1090. SmoothScrollList_OnSetFont(HWND hwnd, HFONT font, BOOL redraw)
  1091. {
  1092. if (0 == (SWS_USESKINFONT & MLSkinnedWnd_GetStyle(hwnd)))
  1093. {
  1094. HWND controlWindow;
  1095. controlWindow = GetDlgItem(hwnd,3);
  1096. if (NULL != controlWindow)
  1097. SendMessageW(controlWindow, WM_SETFONT, (WPARAM)font, MAKELPARAM(0, 0L));
  1098. controlWindow = GetDlgItem(hwnd,2);
  1099. if (NULL != controlWindow)
  1100. SendMessageW(controlWindow, WM_SETFONT, (WPARAM)font, MAKELPARAM(0, 0L));
  1101. SmoothScrollList_UpdateFontMetrics(hwnd, redraw);
  1102. }
  1103. }
  1104. static LRESULT
  1105. SmoothScrollList_OnGetFont(HWND hwnd)
  1106. {
  1107. HWND listWindow;
  1108. listWindow = GetDlgItem(hwnd, 2);
  1109. if (NULL != listWindow)
  1110. return SendMessageW(listWindow, WM_GETFONT, 0, 0L);
  1111. return DefWindowProcW(hwnd, WM_GETFONT, 0, 0L);
  1112. }
  1113. static void
  1114. SmoothScrollList_OnSetRedraw(HWND hwnd, BOOL enableRedraw)
  1115. {
  1116. HWND childWindow;
  1117. DefWindowProcW(hwnd, WM_SETREDRAW, enableRedraw, 0L);
  1118. childWindow = GetDlgItem(hwnd, 3);
  1119. if (NULL != childWindow)
  1120. {
  1121. SendMessage(childWindow, WM_SETREDRAW, enableRedraw, 0L);
  1122. if (FALSE != enableRedraw)
  1123. InvalidateRect(childWindow, NULL, TRUE);
  1124. }
  1125. childWindow = GetDlgItem(hwnd, 2);
  1126. if (NULL != childWindow)
  1127. {
  1128. SendMessage(childWindow, WM_SETREDRAW, enableRedraw, 0L);
  1129. if (FALSE != enableRedraw)
  1130. InvalidateRect(childWindow, NULL, TRUE);
  1131. }
  1132. }
  1133. static void
  1134. SmoothScrollList_OnSkinUpdated(HWND hwnd, BOOL notifyChildren, BOOL redraw)
  1135. {
  1136. SmoothScrollList_UpdateFontMetrics(hwnd, redraw);
  1137. }
  1138. static LRESULT
  1139. SmoothScrollList_OnDisplaySort(HWND hwnd, int sortIndex, BOOL ascendingOrder)
  1140. {
  1141. HWND headerWindow;
  1142. headerWindow = GetDlgItem(hwnd, 3);
  1143. if (NULL == headerWindow)
  1144. return 0;
  1145. return SENDMLIPC(headerWindow, ML_IPC_SKINNEDHEADER_DISPLAYSORT, MAKEWPARAM(sortIndex, ascendingOrder));
  1146. }
  1147. static LRESULT
  1148. SmoothScrollList_OnGetSort(HWND hwnd)
  1149. {
  1150. HWND headerWindow;
  1151. headerWindow = GetDlgItem(hwnd, 3);
  1152. if (NULL == headerWindow)
  1153. return 0;
  1154. return SENDMLIPC(headerWindow, ML_IPC_SKINNEDHEADER_GETSORT, 0);
  1155. }
  1156. static void
  1157. SmoothScrollList_OnKeyDown(HWND hwnd, unsigned int vKey, unsigned int keyFlags)
  1158. {
  1159. HWND listWindow;
  1160. listWindow = GetDlgItem(hwnd, 2);
  1161. if (NULL != listWindow &&
  1162. WS_VISIBLE == ((WS_VISIBLE | WS_DISABLED) & GetWindowLongPtrW(listWindow, GWL_STYLE)))
  1163. {
  1164. SendMessageW(listWindow, WM_KEYDOWN, vKey, (LPARAM)keyFlags);
  1165. }
  1166. DefWindowProcW(hwnd, WM_KEYDOWN, vKey, (LPARAM)keyFlags);
  1167. }
  1168. static LRESULT
  1169. SmoothScrollList_OnMediaLibraryIPC(HWND hwnd, INT msg, INT_PTR param)
  1170. {
  1171. switch(msg)
  1172. {
  1173. case ML_IPC_SKINNEDWND_SKINUPDATED: SmoothScrollList_OnSkinUpdated(hwnd, LOWORD(param), HIWORD(param)); break;
  1174. case ML_IPC_SKINNEDLISTVIEW_DISPLAYSORT: return SmoothScrollList_OnDisplaySort(hwnd, LOWORD(param), HIWORD(param));
  1175. case ML_IPC_SKINNEDLISTVIEW_GETSORT: return SmoothScrollList_OnGetSort(hwnd);
  1176. }
  1177. return 0;
  1178. }
  1179. static LRESULT CALLBACK SmoothScrollMsgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  1180. switch(uMsg)
  1181. {
  1182. case WM_CREATE: return SmoothScrollList_OnCreate(hwnd, (CREATESTRUCT*)lParam);
  1183. case WM_DESTROY: SmoothScrollList_OnDestroy(hwnd); return 0;
  1184. case WM_WINDOWPOSCHANGED: SmoothScrollList_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0;
  1185. case WM_MOUSEWHEEL: SmoothScrollList_OnMouseWheel(hwnd, LOWORD(wParam), (short)HIWORD(wParam), (LONG)lParam); return 0;
  1186. case WM_VSCROLL: SmoothScrollList_OnVertScroll(hwnd, LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); return 0;
  1187. case WM_ERASEBKGND: return 1;
  1188. case WM_MEASUREITEM: return SmoothScrollList_OnMeasureItem(hwnd, (MEASUREITEMSTRUCT*)lParam);
  1189. case WM_SETFONT: SmoothScrollList_OnSetFont(hwnd, (HFONT)wParam, LOWORD(lParam)); return 0;
  1190. case WM_GETFONT: return SmoothScrollList_OnGetFont(hwnd);
  1191. case WM_SETREDRAW: SmoothScrollList_OnSetRedraw(hwnd, (BOOL)wParam); return 0;
  1192. case LVM_GETHEADER:
  1193. return (LRESULT)GetDlgItem(hwnd,3);
  1194. case LVM_INSERTCOLUMNA:
  1195. case LVM_INSERTCOLUMNW:
  1196. {
  1197. LVCOLUMNW *listColumn = (LVCOLUMNW*)lParam;
  1198. HWND controlWindow;
  1199. LRESULT result;
  1200. result = -1;
  1201. controlWindow = GetDlgItem(hwnd,3);
  1202. if (NULL != controlWindow)
  1203. {
  1204. HDITEMW headerItem;
  1205. if (FALSE == CopyListColumnToHeaderItem(listColumn, &headerItem))
  1206. return -1;
  1207. if (0 == (HDI_FORMAT & headerItem.mask))
  1208. {
  1209. headerItem.mask |= HDI_FORMAT;
  1210. headerItem.fmt = HDF_LEFT;
  1211. }
  1212. result = SendMessageW(controlWindow,
  1213. (LVM_INSERTCOLUMNW == uMsg) ? HDM_INSERTITEMW : HDM_INSERTITEMA,
  1214. wParam, (LPARAM)&headerItem);
  1215. if (-1 == result)
  1216. return result;
  1217. }
  1218. controlWindow = GetDlgItem(hwnd, 2);
  1219. if (NULL != controlWindow)
  1220. result = SendMessageW(controlWindow, uMsg, wParam, lParam);
  1221. return result;
  1222. }
  1223. break;
  1224. case LVM_DELETECOLUMN:
  1225. {
  1226. HWND controlWindow;
  1227. controlWindow = GetDlgItem(hwnd,3);
  1228. if (NULL != controlWindow &&
  1229. FALSE ==SendMessageW(controlWindow, HDM_DELETEITEM, wParam, 0L))
  1230. {
  1231. return FALSE;
  1232. }
  1233. controlWindow = GetDlgItem(hwnd,2);
  1234. if (NULL != controlWindow)
  1235. return SendMessageW(controlWindow ,uMsg,wParam,lParam);
  1236. }
  1237. return FALSE;
  1238. case LVM_GETCOLUMNW:
  1239. case LVM_GETCOLUMNA:
  1240. {
  1241. LVCOLUMNW *l = (LVCOLUMNW *)lParam;
  1242. HDITEMW h;
  1243. HWND headerWindow;
  1244. headerWindow = GetDlgItem(hwnd, 3);
  1245. if (NULL == headerWindow)
  1246. return FALSE;
  1247. if (FALSE == CopyListColumnToHeaderItem(l, &h))
  1248. return FALSE;
  1249. if(!SendMessageW(headerWindow,
  1250. (LVM_GETCOLUMNW == uMsg) ? HDM_GETITEMW : HDM_GETITEMA,
  1251. wParam,
  1252. (LPARAM)&h))
  1253. {
  1254. return FALSE;
  1255. }
  1256. if (FALSE == CopyHeaderItemToListColumn(&h, l))
  1257. return FALSE;
  1258. }
  1259. return TRUE;
  1260. case LVM_GETCOLUMNWIDTH:
  1261. {
  1262. HWND controlWindow;
  1263. controlWindow = GetDlgItem(hwnd,3);
  1264. if (NULL != controlWindow)
  1265. {
  1266. HDITEMW h;
  1267. h.mask = HDI_WIDTH;
  1268. if (FALSE == SendMessageW(controlWindow, HDM_GETITEM, wParam, (LPARAM)&h))
  1269. return 0;
  1270. return h.cxy;
  1271. }
  1272. controlWindow = GetDlgItem(hwnd, 2);
  1273. if (NULL != controlWindow)
  1274. return SendMessageW(controlWindow, uMsg, wParam, lParam);
  1275. }
  1276. break;
  1277. case LVM_SETCOLUMNW:
  1278. case LVM_SETCOLUMNA:
  1279. {
  1280. LVCOLUMNW *l = (LVCOLUMNW *)lParam;
  1281. HWND controlWindow;
  1282. LRESULT result;
  1283. controlWindow = GetDlgItem(hwnd, 3);
  1284. if (NULL != controlWindow)
  1285. {
  1286. HDITEMW h;
  1287. if (FALSE == CopyListColumnToHeaderItem(l, &h))
  1288. return FALSE;
  1289. if(!SendMessageW(controlWindow,
  1290. (LVM_SETCOLUMNW == uMsg) ? HDM_SETITEMW : HDM_SETITEMA,
  1291. wParam, (LPARAM)&h))
  1292. {
  1293. return FALSE;
  1294. }
  1295. if (FALSE == CopyHeaderItemToListColumn(&h, l))
  1296. return FALSE;
  1297. result = TRUE;
  1298. }
  1299. else result = FALSE;
  1300. controlWindow = GetDlgItem(hwnd,2);
  1301. if (NULL != controlWindow)
  1302. result = SendMessageW(controlWindow, uMsg, wParam, lParam);
  1303. return result;
  1304. }
  1305. break;
  1306. case LVM_SETCOLUMNWIDTH:
  1307. {
  1308. HWND controlWindow;
  1309. LRESULT result;
  1310. controlWindow = GetDlgItem(hwnd, 3);
  1311. if (NULL != controlWindow)
  1312. {
  1313. HDITEMW headerItem;
  1314. if (LVSCW_AUTOSIZE == lParam)
  1315. return FALSE;
  1316. if (LVSCW_AUTOSIZE_USEHEADER == lParam)
  1317. return FALSE;
  1318. headerItem.mask = HDI_WIDTH;
  1319. headerItem.cxy = (int)lParam;
  1320. result = SendMessageW(controlWindow, HDM_SETITEMW, (WPARAM)wParam, (LPARAM)&headerItem);
  1321. if (FALSE == result)
  1322. return FALSE;
  1323. }
  1324. else
  1325. result = FALSE;
  1326. controlWindow = GetDlgItem(hwnd,2);
  1327. if (NULL != controlWindow)
  1328. result = SendMessageW(controlWindow, uMsg, wParam, lParam);
  1329. return result;
  1330. }
  1331. break;
  1332. case LVM_SETITEMCOUNT:
  1333. {
  1334. LRESULT result;
  1335. HWND controlWindow = GetDlgItem(hwnd,2);
  1336. result = (NULL != controlWindow) ?
  1337. SendMessageW(controlWindow, uMsg, wParam,lParam) :
  1338. 0;
  1339. UpdateScrollInfo(hwnd, SIF_RANGE | SIF_POS, TRUE);
  1340. return result;
  1341. }
  1342. break;
  1343. case LVM_ENSUREVISIBLE:
  1344. return SmoothScrollList_EnsureVisible(hwnd, (int)wParam, (BOOL)lParam);
  1345. case WM_EX_UPDATESCROLLINFO:
  1346. return UpdateScrollInfo(hwnd, (UINT)wParam, (BOOL)lParam);
  1347. case WM_EX_UNLOCKREDRAW:
  1348. {
  1349. unsigned long windowStyle;
  1350. unsigned int redrawFlags;
  1351. HRGN regionInvalid;
  1352. RECT rect;
  1353. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  1354. if (0 == (WS_VISIBLE & windowStyle))
  1355. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  1356. redrawFlags = RDW_INVALIDATE | RDW_ALLCHILDREN;
  1357. if (0 != (IWF_FRAME & wParam))
  1358. {
  1359. redrawFlags |= RDW_FRAME;
  1360. GetWindowRect(hwnd, &rect);
  1361. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rect, 2);
  1362. }
  1363. else
  1364. GetClientRect(hwnd, &rect);
  1365. if (0 != (IWF_ERASE & wParam))
  1366. redrawFlags |= RDW_ERASE;
  1367. if (0 != (IWF_UPDATENOW & wParam))
  1368. {
  1369. redrawFlags |= RDW_UPDATENOW;
  1370. if (0 != (IWF_ERASE & wParam))
  1371. redrawFlags |= RDW_ERASENOW;
  1372. }
  1373. regionInvalid = CreateRectRgnIndirect(&rect);
  1374. if (NULL != regionInvalid)
  1375. {
  1376. HWND headerWindow;
  1377. headerWindow = GetDlgItem(hwnd, 3);
  1378. if (NULL != headerWindow &&
  1379. 0 != (WS_VISIBLE & GetWindowLongPtrW(headerWindow, GWL_STYLE)))
  1380. {
  1381. HRGN regionHeader;
  1382. GetWindowRect(headerWindow, &rect);
  1383. MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rect, 2);
  1384. regionHeader = CreateRectRgnIndirect(&rect);
  1385. if (NULL != regionHeader)
  1386. {
  1387. CombineRgn(regionInvalid, regionInvalid, regionHeader, RGN_DIFF);
  1388. DeleteObject(regionHeader);
  1389. }
  1390. }
  1391. }
  1392. RedrawWindow(hwnd, NULL, regionInvalid, redrawFlags);
  1393. if (NULL != regionInvalid)
  1394. DeleteObject(regionInvalid);
  1395. }
  1396. break;
  1397. case WM_NOTIFY:
  1398. {
  1399. LPNMHDR l=(LPNMHDR)lParam;
  1400. if(l->idFrom == 2)
  1401. {
  1402. l->idFrom = GetWindowLongPtrW(hwnd,GWLP_ID);
  1403. l->hwndFrom = hwnd; // this is prevents double reflecting
  1404. return SendMessageW(GetParent(hwnd),uMsg,l->idFrom,lParam);
  1405. }
  1406. else if(l->idFrom == 3)
  1407. {
  1408. switch(l->code)
  1409. {
  1410. case HDN_ITEMCLICKA:
  1411. case HDN_ITEMCLICKW:
  1412. {
  1413. NMHEADER *nm = (NMHEADER*)lParam;
  1414. HWND hwndParent;
  1415. hwndParent = GetParent(hwnd);
  1416. if (hwndParent)
  1417. {
  1418. wParam = GetWindowLongPtrW(hwnd,GWLP_ID);
  1419. if(nm->iButton == 0) { // left click
  1420. NMLISTVIEW p = {{hwnd, wParam, LVN_COLUMNCLICK},-1,nm->iItem,0};
  1421. return SendMessageW(hwndParent,WM_NOTIFY,wParam,(LPARAM)&p);
  1422. } else if(nm->iButton == 1) { // right click
  1423. NMHDR p = {nm->hdr.hwndFrom,wParam,NM_RCLICK};
  1424. return SendMessageW(hwndParent,WM_NOTIFY,wParam,(LPARAM)&p);
  1425. }
  1426. }
  1427. }
  1428. break;
  1429. case HDN_ITEMCHANGINGA:
  1430. case HDN_ITEMCHANGINGW:
  1431. case HDN_ITEMCHANGEDA:
  1432. case HDN_ITEMCHANGEDW:
  1433. {
  1434. LRESULT result;
  1435. NMHEADER *nm = (NMHEADER*)lParam;
  1436. result = SendMessageW(GetParent(hwnd),uMsg, wParam,lParam);
  1437. if (FALSE != result &&
  1438. (HDN_ITEMCHANGINGW == l->code || HDN_ITEMCHANGINGA == l->code))
  1439. {
  1440. return result;
  1441. }
  1442. if (NULL != nm->pitem &&
  1443. 0 != (HDI_WIDTH & nm->pitem->mask))
  1444. {
  1445. HWND hwndList;
  1446. hwndList = GetDlgItem(hwnd,2);
  1447. if (hwndList)
  1448. {
  1449. unsigned long windowStyle;
  1450. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  1451. if (0 != (WS_VISIBLE & windowStyle))
  1452. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  1453. ListView_SetColumnWidth(hwndList, nm->iItem,nm->pitem->cxy);
  1454. if (0 != (WS_VISIBLE & windowStyle))
  1455. {
  1456. windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  1457. if (0 == (WS_VISIBLE & windowStyle))
  1458. {
  1459. windowStyle |= WS_VISIBLE;
  1460. SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle);
  1461. }
  1462. InvalidateRect(hwndList, NULL, FALSE);
  1463. }
  1464. }
  1465. }
  1466. return result;
  1467. }
  1468. break;
  1469. }
  1470. return SendMessageW(GetParent(hwnd),uMsg, wParam,lParam);
  1471. }
  1472. }
  1473. break;
  1474. case WM_EX_GETREALLIST:
  1475. return (LRESULT)GetDlgItem(hwnd, 2);
  1476. case WM_EX_GETCOUNTPERPAGE:
  1477. return SendMessageW(GetDlgItem(hwnd, 2), LVM_GETCOUNTPERPAGE, 0, 0L) + 1;
  1478. case WM_KEYDOWN: SmoothScrollList_OnKeyDown(hwnd, (unsigned int)wParam, (unsigned int)lParam); return 0;
  1479. case WM_ML_IPC:
  1480. return SmoothScrollList_OnMediaLibraryIPC(hwnd, (INT)lParam, (INT_PTR)wParam);
  1481. default:
  1482. if(uMsg >= LVM_FIRST && uMsg < LVM_FIRST + 0x100)
  1483. {
  1484. HWND hwndList = GetDlgItem(hwnd,2);
  1485. if (hwndList) return ListViewSubclass(hwndList, uMsg, wParam, lParam);
  1486. }
  1487. break;
  1488. }
  1489. return DefWindowProcW(hwnd,uMsg,wParam,lParam);
  1490. }
  1491. void InitSmoothScrollList() {
  1492. WNDCLASSW wc = {0, };
  1493. if (GetClassInfoW(plugin.hDllInstance, L"SmoothScrollList", &wc)) return;
  1494. wc.style = CS_DBLCLKS;
  1495. wc.lpfnWndProc = SmoothScrollMsgProc;
  1496. wc.hInstance = plugin.hDllInstance;
  1497. wc.lpszClassName = L"SmoothScrollList";
  1498. RegisterClassW(&wc);
  1499. }