skinnedheader.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. #include "main.h"
  2. #include "config.h"
  3. #include "../winamp/wa_dlg.h"
  4. #include "./skinnedheader.h"
  5. #include "./skinning.h"
  6. #include "./ml_imagelist.h"
  7. #include "./imagefilters.h"
  8. #include "./ml_cloudcolumn.h"
  9. #include "./resource.h"
  10. // Timers
  11. #define TIMER_UNBLOCKREDRAW_ID 1978
  12. #define TIMER_ENDTRACK_ID 1979
  13. #define TIMER_ENDTRACK_DELAY 5
  14. // Header internal flags (LOWORD reserved to sort index)
  15. #define HIF_ASCENDING 0x00010000
  16. #define HIF_OWNPARENTSW 0x00020000 // parent was subclassed by this control
  17. #define HIF_REALCXY 0x00040000
  18. #define HIF_DEFSIZERULE 0x00100000 // item will use default size rule.
  19. #define HIF_BLOCKCHANGING 0x10000000
  20. #define HIF_BLOCKCHANGED 0x20000000
  21. #define HIF_BLOCKWNDPOS 0x40000000
  22. #define HIF_BLOCKREDRAW 0x80000000
  23. extern HMLIMGFLTRMNGR hmlifMngr; // default gen_ml fitler manager
  24. typedef struct _HDSIZE
  25. {
  26. INT instanceRef;
  27. INT *pCXY; // stored by index
  28. INT *pOrder; // current left-to-right order of items (index values for items in the header).
  29. INT count;
  30. INT allocated;
  31. INT headerCXY;
  32. INT lastCXY;
  33. HWND hwndParent;
  34. HDITEMW hdi; // safe to use duaring size
  35. } HDSIZE;
  36. typedef struct _HDCURSOR
  37. {
  38. HWND hwndParent;
  39. NMMOUSE nm;
  40. HDHITTESTINFO hitTest;
  41. DWORD pts;
  42. } HDCURSOR;
  43. static HDSIZE hdrSize = {0,0,0, } ;
  44. static INT GetDefaultSizeRule(void)
  45. {
  46. INT rule;
  47. rule = g_config->ReadInt(L"column_resize_mode", 0);
  48. switch(rule)
  49. {
  50. case 1: return SHS_SIZERULE_ADJUSTONE;
  51. case 2: return SHS_SIZERULE_PROPORTIONAL;
  52. case 3: return SHS_SIZERULE_ADJUSTALL;
  53. }
  54. return SHS_SIZERULE_WINDOWS;
  55. }
  56. SkinnedHeader::SkinnedHeader(void) : SkinnedWnd(FALSE), hcurNormal(NULL), cloudColumn(-1)
  57. {
  58. if (!hdrSize.instanceRef)
  59. ZeroMemory(&hdrSize, sizeof(HDSIZE));
  60. hdrSize.instanceRef++;
  61. hdrFlags = LOWORD(-1) | HIF_ASCENDING | HIF_DEFSIZERULE;
  62. hdrSizeRule = (HIF_DEFSIZERULE & hdrFlags) ? GetDefaultSizeRule() : SHS_SIZERULE_WINDOWS;
  63. }
  64. SkinnedHeader::~SkinnedHeader(void)
  65. {
  66. if (hdrSize.instanceRef && !--hdrSize.instanceRef)
  67. {
  68. if (hdrSize.pCXY)
  69. free(hdrSize.pCXY); // pOrder - use same buffer
  70. ZeroMemory(&hdrSize, sizeof(HDSIZE));
  71. }
  72. }
  73. extern HMLIMGLST hmlilCloud;
  74. BOOL SkinnedHeader::Attach(HWND hwndHeader)
  75. {
  76. HWND hwndParent;
  77. if(!__super::Attach(hwndHeader)) return FALSE;
  78. SetType(SKINNEDWND_TYPE_HEADER);
  79. hwndParent = GetParent(hwndHeader);
  80. if (hwndParent) SkinWindow(hwndParent, SWS_NORMAL);
  81. hdrFlags = LOWORD(-1) | HIF_ASCENDING | HIF_DEFSIZERULE;
  82. hdrSizeRule = (HIF_DEFSIZERULE & hdrFlags) ? GetDefaultSizeRule() : SHS_SIZERULE_WINDOWS;
  83. // set default height
  84. SetHeight(-1);
  85. return TRUE;
  86. }
  87. void SkinnedHeader::OnSkinChanged(BOOL bNotifyChildren, BOOL bRedraw)
  88. {
  89. hcurNormal = (HCURSOR)SendMessageW(plugin.hwndParent, WM_WA_IPC, WACURSOR_NORMAL, IPC_GETSKINCURSORS);
  90. __super::OnSkinChanged(bNotifyChildren, bRedraw);
  91. }
  92. void SkinnedHeader::BlockRedraw(BOOL bBlock, UINT unblockDelay)
  93. {
  94. KillTimer(hwnd, TIMER_UNBLOCKREDRAW_ID);
  95. if (FALSE != bBlock)
  96. hdrFlags |= HIF_BLOCKREDRAW;
  97. else
  98. hdrFlags &= ~HIF_BLOCKREDRAW;
  99. CallDefWndProc(WM_SETREDRAW, (WPARAM)!bBlock, 0L);
  100. if (FALSE != bBlock && -1 != unblockDelay)
  101. SetTimer(hwnd, TIMER_UNBLOCKREDRAW_ID, unblockDelay, NULL);
  102. }
  103. DWORD SkinnedHeader::GetSortArrowSize(void)
  104. {
  105. return MAKELPARAM(7, 8);
  106. }
  107. BOOL SkinnedHeader::DrawSortArrow(HDC hdc, RECT *prc, COLORREF rgbBk, COLORREF rgbFg, BOOL bAscending)
  108. {
  109. static HMLIMGLST hmlilSort = NULL;
  110. IMAGELISTDRAWPARAMS ildp;
  111. if (!hmlilSort)
  112. {
  113. DWORD arrowSize = GetSortArrowSize();
  114. hmlilSort = MLImageListI_Create(GET_X_LPARAM(arrowSize)*2, GET_Y_LPARAM(arrowSize), MLILC_COLOR24_I, 1, 1, 1, hmlifMngr);
  115. if (hmlilSort)
  116. {
  117. MLIMAGESOURCE_I mlis;
  118. ZeroMemory(&mlis, sizeof(MLIMAGESOURCE_I));
  119. mlis.type = SRC_TYPE_PNG_I;
  120. mlis.hInst = plugin.hDllInstance;
  121. mlis.lpszName = MAKEINTRESOURCEW(IDB_SORTARROW);
  122. MLImageListI_Add(hmlilSort, &mlis, MLIF_FILTER1_UID, 0);
  123. }
  124. }
  125. ZeroMemory(&ildp, sizeof(IMAGELISTDRAWPARAMS));
  126. ildp.cbSize = 56; // keep it hardcoded for now - otherwise brakes win2000. sizeof(IMAGELISTDRAWPARAMS);
  127. ildp.i = MLImageListI_GetRealIndex(hmlilSort, 0, rgbBk, rgbFg);
  128. if (-1 != ildp.i)
  129. {
  130. ildp.hdcDst = hdc;
  131. ildp.himl = MLImageListI_GetRealList(hmlilSort);
  132. ildp.cx = prc->right - prc->left;
  133. ildp.cy = prc->bottom - prc->top;
  134. ildp.x = prc->left;
  135. ildp.y = prc->top;
  136. ildp.fStyle = ILD_NORMAL;
  137. ildp.dwRop = SRCCOPY;
  138. ildp.xBitmap = (bAscending) ? ildp.cx : 0;
  139. return ImageList_DrawIndirect(&ildp);
  140. }
  141. return FALSE;
  142. }
  143. BOOL SkinnedHeader::DrawCloudIcon(HDC hdc, RECT *prc, COLORREF rgbBk, COLORREF rgbFg)
  144. {
  145. IMAGELISTDRAWPARAMS ildp;
  146. ZeroMemory(&ildp, sizeof(IMAGELISTDRAWPARAMS));
  147. ildp.cbSize = 56; // keep it hardcoded for now - otherwise brakes win2000. sizeof(IMAGELISTDRAWPARAMS);
  148. ildp.i = MLImageListI_GetRealIndex(hmlilCloud, 0, rgbBk, rgbFg);
  149. if (-1 != ildp.i)
  150. {
  151. ildp.hdcDst = hdc;
  152. ildp.himl = MLImageListI_GetRealList(hmlilCloud);
  153. ildp.cx = 16;
  154. ildp.cy = 16;
  155. ildp.x = prc->left - 7;
  156. ildp.y = prc->top - 4;
  157. ildp.fStyle = ILD_NORMAL;
  158. ildp.dwRop = SRCCOPY;
  159. ildp.xBitmap = 0;
  160. return ImageList_DrawIndirect(&ildp);
  161. }
  162. return FALSE;
  163. }
  164. void SkinnedHeader::DrawHeaderItem(LPNMCUSTOMDRAW pnmcd)
  165. {
  166. HPEN pen, penOld;
  167. HDC hdc;
  168. RECT *prc, rcText;
  169. INT textRight;
  170. INT ox, oy;
  171. hdc = pnmcd->hdc;
  172. prc = &pnmcd->rc;
  173. ox = (CDIS_SELECTED & pnmcd->uItemState) ? 1 : 0;
  174. oy = 0;
  175. SetBkColor(hdc, WADlg_getColor(WADLG_LISTHEADER_BGCOLOR));
  176. ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, prc, L"", 0, 0);
  177. pen = (HPEN)MlStockObjects_Get((CDIS_SELECTED & pnmcd->uItemState) ? HEADERBOTTOM_PEN : HEADERTOP_PEN);
  178. penOld = (HPEN)SelectObject(hdc, pen);
  179. MoveToEx(hdc, prc->left, prc->top, NULL);
  180. LineTo(hdc, prc->right, prc->top);
  181. MoveToEx(hdc, prc->left, prc->top, NULL);
  182. LineTo(hdc, prc->left, prc->bottom);
  183. if (0 == (CDIS_SELECTED & pnmcd->uItemState))
  184. {
  185. SelectObject(hdc, penOld);
  186. pen = (HPEN)MlStockObjects_Get(HEADERBOTTOM_PEN);
  187. penOld = (HPEN)SelectObject(hdc, pen);
  188. }
  189. MoveToEx(hdc, prc->right - 1, prc->top, NULL);
  190. LineTo(hdc, prc->right - 1, prc->bottom);
  191. MoveToEx(hdc, prc->right - 1, prc->bottom - 1, NULL);
  192. LineTo(hdc, prc->left - 1, prc->bottom - 1);
  193. if (0 == (CDIS_SELECTED & pnmcd->uItemState))
  194. {
  195. SelectObject(hdc, penOld);
  196. pen = (HPEN)MlStockObjects_Get(HEADERMIDDLE_PEN);
  197. penOld = (HPEN)SelectObject(hdc, pen);
  198. MoveToEx(hdc, prc->right - 2, prc->top + 1, NULL);
  199. LineTo(hdc, prc->right - 2, prc->bottom - 2);
  200. MoveToEx(hdc, prc->right - 2, prc->bottom - 2, NULL);
  201. LineTo(hdc, prc->left, prc->bottom - 2);
  202. }
  203. textRight = prc->right - 5 + ox;
  204. if (LOWORD(hdrFlags) == pnmcd->dwItemSpec || pnmcd->dwItemSpec == cloudColumn)
  205. {
  206. RECT r;
  207. DWORD arrowSize;
  208. int dividerArea;
  209. arrowSize = GetSortArrowSize();
  210. SetRect(&r, 0, 0, GET_X_LPARAM(arrowSize), GET_Y_LPARAM(arrowSize));
  211. dividerArea = 4*GetSystemMetrics(SM_CXEDGE);
  212. OffsetRect(&r, prc->right - r.right - dividerArea, (((prc->bottom - prc->top) - r.bottom) + 1)/2);
  213. if (pnmcd->dwItemSpec != cloudColumn && (r.left > (prc->left + 16) && r.top > (prc->top + 2)))
  214. {
  215. if (DrawSortArrow(hdc, &r,
  216. WADlg_getColor(WADLG_LISTHEADER_BGCOLOR),
  217. WADlg_getColor(WADLG_LISTHEADER_FONTCOLOR),
  218. (HIF_ASCENDING & hdrFlags))) textRight = r.left - 3;
  219. }
  220. else if (pnmcd->dwItemSpec == cloudColumn)
  221. {
  222. if ((prc->right - prc->left) >= MLCloudColumnI_GetMinWidth())
  223. {
  224. DrawCloudIcon(hdc, &r,
  225. WADlg_getColor(WADLG_LISTHEADER_BGCOLOR),
  226. WADlg_getColor(WADLG_LISTHEADER_FONTCOLOR));
  227. }
  228. }
  229. }
  230. if (pnmcd->dwItemSpec != cloudColumn && (textRight > (prc->left + 4 + ox)))
  231. {
  232. WCHAR buffer[128] = {0};
  233. HDITEMW item;
  234. item.mask = HDI_TEXT | HDI_FORMAT;
  235. item.pszText = buffer;
  236. item.cchTextMax = sizeof(buffer)/sizeof(wchar_t) -1;
  237. if (CallPrevWndProc(HDM_GETITEMW, (WPARAM)pnmcd->dwItemSpec, (LPARAM)&item))
  238. {
  239. DWORD format;
  240. SetBkMode(hdc, TRANSPARENT);
  241. SetTextColor(hdc, WADlg_getColor(WADLG_LISTHEADER_FONTCOLOR));
  242. SetRect(&rcText, prc->left + 5 + ox, prc->top + 2 + oy, textRight, prc->bottom - 2);
  243. format = DT_VCENTER | DT_SINGLELINE | DT_LEFT | DT_NOCLIP;
  244. switch(HDF_JUSTIFYMASK & item.fmt)
  245. {
  246. case HDF_RIGHT: format |= DT_RIGHT; break;
  247. case HDF_CENTER: format |= DT_CENTER; break;
  248. }
  249. // because we draw with DT_NOCLIP, make sure we don't overhang to the right
  250. RECT testRect = rcText;
  251. DrawTextW(hdc, item.pszText, -1, &testRect, format | DT_CALCRECT);
  252. if (testRect.right > textRight)
  253. {
  254. format &= ~(HDF_JUSTIFYMASK | DT_NOCLIP);
  255. format |= DT_LEFT;
  256. if ((testRect.right - textRight) > 6)
  257. format |= DT_END_ELLIPSIS;
  258. }
  259. DrawTextW(hdc, item.pszText, -1, &rcText, format);
  260. }
  261. }
  262. SelectObject(hdc, penOld);
  263. }
  264. BOOL SkinnedHeader::OnCustomDraw(HWND hwndFrom, NMCUSTOMDRAW *pnmcd, LRESULT *pResult)
  265. {
  266. switch(pnmcd->dwDrawStage)
  267. {
  268. case CDDS_PREPAINT:
  269. *pResult = (SWS_USESKINCOLORS & style) ?
  270. CDRF_NOTIFYITEMDRAW :
  271. CDRF_DODEFAULT;
  272. return TRUE;
  273. case CDDS_ITEMPREPAINT:
  274. DrawHeaderItem(pnmcd);
  275. *pResult = CDRF_SKIPDEFAULT;
  276. return TRUE;
  277. }
  278. return FALSE;
  279. }
  280. UINT SkinnedHeader::SizeRuleAdjustOne(HDITEMW *phdi, INT index, UINT uMsg)
  281. {
  282. UINT result, flags;
  283. flags = hdrFlags;
  284. hdrFlags |= HIF_REALCXY;
  285. result = 0;
  286. if (index < hdrSize.count)
  287. {
  288. INT delta;
  289. delta = phdi->cxy - hdrSize.pCXY[index];
  290. hdrSize.hdi.mask = HDI_WIDTH;
  291. phdi = &hdrSize.hdi;
  292. if (delta)
  293. {
  294. if(CallPrevWndProc(HDM_GETITEMW, index + 1, (LPARAM)phdi))
  295. {
  296. INT temp = phdi->cxy;
  297. phdi->cxy -= delta;
  298. if (CallPrevWndProc(HDM_SETITEMW, index + 1, (LPARAM)phdi)) delta = temp - phdi->cxy;
  299. else delta = 0;
  300. }
  301. hdrSize.pCXY[index] += delta;
  302. result = 1;
  303. }
  304. }
  305. hdrFlags = flags;
  306. return result;
  307. }
  308. UINT SkinnedHeader::SizeRuleProportional(HDITEMW *phdi, INT index, UINT uMsg)
  309. {
  310. UINT flags;
  311. INT o, delta;
  312. if (index >= hdrSize.count ||
  313. hdrSize.lastCXY == phdi->cxy ||
  314. 0 == (phdi->cxy - hdrSize.pCXY[index]))
  315. {
  316. return 0;
  317. }
  318. flags = hdrFlags;
  319. hdrFlags |= HIF_REALCXY;
  320. delta = phdi->cxy - hdrSize.pCXY[index];
  321. hdrSize.lastCXY = phdi->cxy;
  322. for (o = 0; o < hdrSize.count; o++)
  323. {
  324. if (hdrSize.pOrder[o] == index)
  325. break;
  326. }
  327. phdi = &hdrSize.hdi;
  328. phdi->mask = HDI_WIDTH;
  329. for(++o; o < hdrSize.count && 0 != delta; o++)
  330. {
  331. INT i = hdrSize.pOrder[o];
  332. INT r = delta / (hdrSize.count - o) + ((delta % (hdrSize.count - o)) ? ((delta >0) ? 1 : -1) : 0);
  333. if (0 == r)
  334. r = delta;
  335. phdi->cxy = hdrSize.pCXY[i] - r;
  336. INT temp = phdi->cxy;
  337. CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)phdi);
  338. delta -= r;
  339. // hdrSize.pCXY[i] = phdi->cxy;
  340. if (phdi->cxy != temp)
  341. delta += (phdi->cxy- temp);
  342. }
  343. hdrFlags = flags;
  344. return 1;
  345. }
  346. BOOL SkinnedHeader::OnBeginTrack(HWND hwndFrom, NMHEADERW *phdn, LRESULT *pResult)
  347. {
  348. if (HIF_DEFSIZERULE & hdrFlags) hdrSizeRule = GetDefaultSizeRule();
  349. KillTimer(hwnd, TIMER_ENDTRACK_ID);
  350. hdrSize.headerCXY = 0;
  351. hdrSize.lastCXY = -1;
  352. hdrSize.hwndParent = hwndFrom;
  353. hdrSize.count = (INT)CallPrevWndProc(HDM_GETITEMCOUNT, 0, 0L);
  354. if (hdrSize.count < 0) hdrSize.count = 0;
  355. if (hdrSize.count > 0)
  356. {
  357. HDITEMW item;
  358. if (hdrSize.count > hdrSize.allocated)
  359. {
  360. VOID *data;
  361. data = realloc(hdrSize.pCXY, sizeof(INT)*hdrSize.count*2);
  362. if (data)
  363. {
  364. hdrSize.pCXY = (INT*)data;
  365. hdrSize.pOrder = hdrSize.pCXY + hdrSize.count;
  366. hdrSize.allocated = hdrSize.count;
  367. }
  368. if (!data) hdrSize.count = 0;
  369. }
  370. if (hdrSize.count)
  371. {
  372. INT i;
  373. if (!CallPrevWndProc(HDM_GETORDERARRAY, hdrSize.count, (LPARAM)hdrSize.pOrder))
  374. {
  375. for (i = 0; i < hdrSize.count; i++) hdrSize.pOrder[i] = i;
  376. }
  377. item.mask = HDI_WIDTH;
  378. for (INT o = 0; o < hdrSize.count; o++)
  379. {
  380. i = hdrSize.pOrder[o];
  381. if (SendMessageW(hwnd, HDM_GETITEMW, i, (LPARAM)&item) && item.lParam)
  382. {
  383. hdrSize.pCXY[i] = item.cxy;
  384. hdrSize.headerCXY += item.cxy;
  385. }
  386. }
  387. }
  388. }
  389. return FALSE;
  390. }
  391. BOOL SkinnedHeader::OnEndTrack(HWND hwndFrom, NMHEADERW *phdn)
  392. {
  393. if (hdrSize.count)
  394. {
  395. BlockRedraw(FALSE, 0);
  396. hdrFlags &= ~(HIF_BLOCKCHANGING | HIF_BLOCKCHANGED);
  397. SetTimer(hwnd, TIMER_ENDTRACK_ID, TIMER_ENDTRACK_DELAY, NULL);
  398. }
  399. return FALSE;
  400. }
  401. BOOL SkinnedHeader::OnItemChanging(HWND hwndFrom, NMHEADERW *phdn, LRESULT *pResult)
  402. {
  403. if (HIF_BLOCKCHANGING & hdrFlags)
  404. {
  405. *pResult = FALSE;
  406. return TRUE;
  407. }
  408. if (0 != hdrSize.count &&
  409. 0 == (HIF_REALCXY & hdrFlags))
  410. {
  411. switch(hdrSizeRule)
  412. {
  413. case SHS_SIZERULE_ADJUSTONE:
  414. case SHS_SIZERULE_PROPORTIONAL:
  415. case SHS_SIZERULE_ADJUSTALL:
  416. BlockRedraw(TRUE, 10);
  417. break;
  418. }
  419. }
  420. return FALSE;
  421. }
  422. BOOL SkinnedHeader::OnItemChanged(HWND hwndFrom, NMHEADERW *phdn)
  423. {
  424. UINT result;
  425. if (HIF_BLOCKCHANGED & hdrFlags)
  426. return TRUE;
  427. if((HIF_REALCXY & hdrFlags) || !phdn->pitem || 0== (HDI_WIDTH & phdn->pitem->mask))
  428. return FALSE;
  429. hdrFlags |= HIF_BLOCKCHANGED;
  430. switch(hdrSizeRule)
  431. {
  432. case SHS_SIZERULE_ADJUSTONE: result = SizeRuleAdjustOne(phdn->pitem, phdn->iItem, phdn->hdr.code); break;
  433. case SHS_SIZERULE_PROPORTIONAL: result = SizeRuleProportional(phdn->pitem, phdn->iItem, phdn->hdr.code); break;
  434. case SHS_SIZERULE_ADJUSTALL: result = 0; break;
  435. default: result = 0; break;
  436. }
  437. hdrFlags &= ~HIF_BLOCKCHANGED;
  438. if (result)
  439. {
  440. if(hdrSize.count)
  441. {
  442. INT i;
  443. HDITEMW item;
  444. item.mask = HDI_WIDTH;
  445. i = hdrSize.pOrder[hdrSize.count - 1];
  446. if (CallPrevWndProc(HDM_GETITEMW, i, (LPARAM)&item))
  447. {
  448. long cxy = item.cxy;
  449. hdrFlags |= (HIF_BLOCKCHANGING | HIF_BLOCKCHANGED | HIF_REALCXY);
  450. item.cxy = cxy + 1;
  451. CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)&item);
  452. hdrFlags &= ~(HIF_BLOCKCHANGING | HIF_BLOCKCHANGED);
  453. item.cxy = cxy;
  454. CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)&item);
  455. hdrFlags &= ~HIF_REALCXY;
  456. }
  457. }
  458. BlockRedraw(FALSE, 0);
  459. if (NULL != hdrSize.hwndParent)
  460. {
  461. RedrawWindow(hdrSize.hwndParent, NULL, NULL,
  462. RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN/*| RDW_VALIDATE*/);
  463. }
  464. else
  465. RedrawWindow(hwnd, NULL, NULL,
  466. RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN/*| RDW_VALIDATE*/);
  467. return TRUE;
  468. }
  469. return FALSE;
  470. }
  471. BOOL SkinnedHeader::OnCursorNotify(HWND hwndFrom, NMMOUSE *pnm, LRESULT *pResult)
  472. {
  473. if (0 == ((HHT_ONDIVIDER | HHT_ONDIVOPEN)& pnm->dwHitInfo) && (SWS_USESKINCURSORS & style) && hcurNormal)
  474. {
  475. SetCursor(hcurNormal);
  476. *pResult = TRUE;
  477. return TRUE;
  478. }
  479. return FALSE;
  480. }
  481. BOOL SkinnedHeader::OnReflectedNotify(INT idCtrl, REFLECTPARAM *rParam)
  482. {
  483. if (rParam->hwndFrom != GetParent(hwnd)) return FALSE; // controls such as listview forward headers notifications to they parent.
  484. switch(((NMHDR*)(rParam->lParam))->code)
  485. {
  486. case NM_CUSTOMDRAW: return OnCustomDraw(rParam->hwndFrom, (NMCUSTOMDRAW*)rParam->lParam, &rParam->result);
  487. case HDN_ITEMCHANGINGA:
  488. case HDN_ITEMCHANGINGW: return OnItemChanging(rParam->hwndFrom, (NMHEADERW*)rParam->lParam, &rParam->result);
  489. case HDN_ITEMCHANGEDA:
  490. case HDN_ITEMCHANGEDW: return OnItemChanged(rParam->hwndFrom, (NMHEADERW*)rParam->lParam);
  491. case HDN_BEGINTRACKA:
  492. case HDN_BEGINTRACKW: return OnBeginTrack(rParam->hwndFrom, (NMHEADERW*)rParam->lParam, &rParam->result);
  493. case HDN_ENDTRACKA:
  494. case HDN_ENDTRACKW: return OnEndTrack(rParam->hwndFrom, (NMHEADERW*)rParam->lParam);
  495. case NM_SETCURSOR: return OnCursorNotify(rParam->hwndFrom, (NMMOUSE*)rParam->lParam, &rParam->result);
  496. }
  497. return FALSE;
  498. }
  499. void SkinnedHeader::OnPaint(void)
  500. {
  501. if (HIF_BLOCKREDRAW & hdrFlags)
  502. {
  503. ValidateRgn(hwnd, NULL);
  504. }
  505. else if (SWS_USESKINCOLORS & style)
  506. {
  507. //process the grey area with our color
  508. RECT rc, ri;
  509. int i;
  510. GetClientRect(hwnd, &rc);
  511. i = (INT)CallPrevWndProc(HDM_GETITEMCOUNT, 0, 0L);
  512. if(i > 0)
  513. {
  514. Header_GetItemRect(hwnd, (INT)CallPrevWndProc(HDM_ORDERTOINDEX, (i-1), 0L), &ri);
  515. rc.left = ri.right;
  516. }
  517. if(rc.left < rc.right && GetUpdateRect(hwnd, &ri, FALSE) && IntersectRect(&rc, &rc, &ri))
  518. {
  519. UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN |
  520. DCX_INTERSECTUPDATE | DCX_VALIDATE;
  521. HDC hdc = GetDCEx(hwnd, NULL, flags);
  522. if(hdc)
  523. {
  524. COLORREF rgbBkOld;
  525. rgbBkOld = SetBkColor(hdc, WADlg_getColor(WADLG_LISTHEADER_EMPTY_BGCOLOR));
  526. ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &rc, L"", 0, 0);
  527. SetBkColor(hdc, rgbBkOld);
  528. ReleaseDC(hwnd, hdc);
  529. ValidateRect(hwnd, &rc);
  530. }
  531. }
  532. }
  533. }
  534. void SkinnedHeader::OnTimer(UINT_PTR nIDEvent, TIMERPROC lpTimerFunc)
  535. {
  536. switch (nIDEvent)
  537. {
  538. case TIMER_UNBLOCKREDRAW_ID:
  539. BlockRedraw(FALSE, 0);
  540. return;
  541. case TIMER_ENDTRACK_ID:
  542. KillTimer(hwnd, TIMER_ENDTRACK_ID);
  543. hdrSize.count = 0;
  544. hdrSize.headerCXY = 0;
  545. hdrSize.lastCXY = -1;
  546. return;
  547. }
  548. __super::WindowProc(WM_TIMER, (WPARAM)nIDEvent, (LPARAM)lpTimerFunc);
  549. }
  550. void SkinnedHeader::SetHeight(INT nHeight)
  551. {
  552. RECT rw;
  553. GetWindowRect(hwnd, &rw);
  554. if (nHeight < 0)
  555. {
  556. HDC hdc;
  557. hdc = GetWindowDC(hwnd);
  558. if (hdc)
  559. {
  560. HFONT hfnt;
  561. hfnt = (HFONT)CallPrevWndProc(WM_GETFONT, 0, 0L);
  562. if (!hfnt) hfnt = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
  563. if (hfnt)
  564. {
  565. TEXTMETRICW tm = {0};
  566. HFONT hfntOld = (HFONT)SelectObject(hdc, hfnt);
  567. if (GetTextMetricsW(hdc, &tm)) nHeight = tm.tmHeight + 6/*Borders*/;
  568. SelectObject(hdc, hfntOld);
  569. }
  570. ReleaseDC(hwnd, hdc);
  571. }
  572. }
  573. if (nHeight != (rw.bottom - rw.top))
  574. {
  575. INT i;
  576. SetWindowPos(hwnd, NULL, 0, 0, rw.right - rw.left, nHeight, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
  577. if (HDS_HIDDEN & GetWindowLongPtrW(hwnd, GWL_STYLE)) return;
  578. i = (INT)CallPrevWndProc(HDM_GETITEMCOUNT, 0, 0L);
  579. if(i > 0)
  580. {
  581. HDITEMW item;
  582. i = (INT)CallPrevWndProc(HDM_ORDERTOINDEX, (i-1), 0L);
  583. item.mask = HDI_WIDTH;
  584. if (CallPrevWndProc(HDM_GETITEMW, i, (LPARAM)&item))
  585. {
  586. hdrFlags |= (HIF_BLOCKCHANGING | HIF_BLOCKCHANGED | HIF_REALCXY);
  587. item.cxy++; CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)&item);
  588. hdrFlags &= ~(HIF_BLOCKCHANGING | HIF_BLOCKCHANGED);
  589. item.cxy--; CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)&item);
  590. hdrFlags &= ~HIF_REALCXY;
  591. }
  592. }
  593. }
  594. }
  595. BOOL SkinnedHeader::OnLayout(HDLAYOUT *pLayout)
  596. {
  597. BOOL result;
  598. result = (BOOL)__super::WindowProc(HDM_LAYOUT, 0, (LPARAM)pLayout);
  599. if (0 == (HDS_HIDDEN & GetWindowLongPtrW(hwnd, GWL_STYLE)))
  600. {
  601. RECT rw;
  602. GetWindowRect(hwnd, &rw);
  603. OffsetRect(&rw, -rw.left, -rw.top);
  604. pLayout->pwpos->cy= rw.bottom;
  605. pLayout->prc->top = rw.bottom;
  606. if (GetClientRect(GetParent(hwnd), &rw))
  607. pLayout->pwpos->cx = (rw.right - rw.left) - pLayout->pwpos->x;
  608. }
  609. return result;
  610. }
  611. BOOL SkinnedHeader::OnSetCursor(HWND hwdCursor, UINT hitTest, UINT message)
  612. {
  613. static HDCURSOR hdrCursor;
  614. hdrCursor.hwndParent = GetParent(hwnd);
  615. if (hdrCursor.hwndParent)
  616. {
  617. hdrCursor.nm.hdr.code = NM_SETCURSOR;
  618. hdrCursor.nm.hdr.hwndFrom = hwnd;
  619. hdrCursor.nm.hdr.idFrom = GetDlgCtrlID(hwnd);
  620. hdrCursor.pts = GetMessagePos();
  621. POINTSTOPOINT(hdrCursor.nm.pt, hdrCursor.pts);
  622. hdrCursor.hitTest.pt = hdrCursor.nm.pt;
  623. MapWindowPoints(HWND_DESKTOP, hwnd, &hdrCursor.hitTest.pt, 1);
  624. CallPrevWndProc(HDM_HITTEST, 0, (LPARAM)&hdrCursor.hitTest);
  625. hdrCursor.nm.dwItemSpec = hdrCursor.hitTest.iItem;
  626. hdrCursor.nm.dwHitInfo = hdrCursor.hitTest.flags;
  627. if (SendMessage(hdrCursor.hwndParent, WM_NOTIFY, (WPARAM)hdrCursor.nm.hdr.code, (LPARAM)&hdrCursor.nm))
  628. return TRUE;
  629. }
  630. return (BOOL)__super::WindowProc(WM_SETCURSOR, (WPARAM)hwdCursor, MAKELPARAM(hitTest, message));
  631. }
  632. LRESULT SkinnedHeader::OnSetItem(INT iIndex, HDITEMW *phdItem, BOOL bUnicode)
  633. {
  634. if (NULL != phdItem &&
  635. 0 != (HDI_FORMAT & phdItem->mask))
  636. {
  637. DWORD newFlags = 0x0000FFFF | (hdrFlags & (0xFFFF0000 & ~HIF_ASCENDING));
  638. if (0 != ((HDF_SORTDOWN | HDF_SORTUP) & phdItem->fmt) &&
  639. iIndex >= 0 && iIndex < 0xFFFF)
  640. {
  641. newFlags = (newFlags & 0xFFFF0000) | (0xFFFF & iIndex);
  642. if (0 != (HDF_SORTUP & phdItem->fmt))
  643. newFlags |= HIF_ASCENDING;
  644. }
  645. if ((LOWORD(newFlags) != LOWORD(hdrFlags)) ||
  646. ((HIF_ASCENDING & newFlags) != (HIF_ASCENDING & hdrFlags)))
  647. {
  648. hdrFlags = newFlags;
  649. RECT rcItem;
  650. if (NULL != CallPrevWndProc(HDM_GETITEMRECT, (WPARAM)iIndex, (LPARAM)&rcItem))
  651. {
  652. InvalidateRect(hwnd, &rcItem, FALSE);
  653. }
  654. }
  655. }
  656. return __super::WindowProc(((bUnicode) ? HDM_SETITEMW : HDM_SETITEMA), (WPARAM)iIndex, (LPARAM)phdItem);
  657. }
  658. BOOL SkinnedHeader::OnMediaLibraryIPC(INT msg, INT_PTR param, LRESULT *pResult)
  659. {
  660. switch(msg)
  661. {
  662. case ML_IPC_SKINNEDHEADER_DISPLAYSORT:
  663. hdrFlags = (hdrFlags & 0xFFFF0000) | LOWORD(param);
  664. hdrFlags = (hdrFlags & ~HIF_ASCENDING) | ((HIWORD(param)) ? HIF_ASCENDING : 0);
  665. *pResult = 1;
  666. InvalidateRect(hwnd, NULL, FALSE);
  667. UpdateWindow(hwnd);
  668. return TRUE;
  669. case ML_IPC_SKINNEDHEADER_SETHEIGHT: SetHeight((INT)param); *pResult = TRUE; return TRUE;
  670. case ML_IPC_SKINNEDHEADER_GETSORT: *pResult = MAKELONG(LOWORD(hdrFlags), 0 != (HIF_ASCENDING & hdrFlags)); return TRUE;
  671. case ML_IPC_SKINNEDHEADER_SETCLOUDCOLUMN:
  672. cloudColumn = (INT)param;
  673. InvalidateRect(hwnd, NULL, FALSE);
  674. UpdateWindow(hwnd);
  675. return TRUE;
  676. }
  677. return __super::OnMediaLibraryIPC(msg, param, pResult);
  678. }
  679. LRESULT SkinnedHeader::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  680. {
  681. switch(uMsg)
  682. {
  683. case WM_ERASEBKGND: return 1;
  684. case WM_PAINT: OnPaint(); break;
  685. case WM_TIMER: OnTimer((UINT_PTR)wParam, (TIMERPROC)lParam); return 0;
  686. case WM_SETCURSOR: return OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  687. case WM_CAPTURECHANGED: InvalidateRect(hwnd, NULL, TRUE); break;
  688. case WM_WINDOWPOSCHANGING: if (HIF_BLOCKWNDPOS & hdrFlags) return TRUE;
  689. break;
  690. case REFLECTED_NOTIFY: return OnReflectedNotify((INT)wParam, (REFLECTPARAM*)lParam);
  691. case HDM_LAYOUT: return OnLayout((LPHDLAYOUT)lParam);
  692. case HDM_SETITEMA:
  693. case HDM_SETITEMW:
  694. return OnSetItem((INT)wParam, (HDITEMW*)lParam, (HDM_SETITEMW == uMsg));
  695. }
  696. return __super::WindowProc(uMsg, wParam, lParam);
  697. }