listheader.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #include "main.h"
  2. #include <windowsx.h>
  3. #include "config.h"
  4. #include "../winamp/wa_dlg.h"
  5. static int m_column_resize=0; //0=normal, 1=selected item only, 2=proportional
  6. static int m_origsizes[32], m_origwidth;
  7. static float m_origperc[32];
  8. static void columnTrackStart(HWND hwnd, int item)
  9. {
  10. int l=Header_GetItemCount(hwnd);
  11. m_origwidth=0;
  12. int i;
  13. for(i=item+1;i<l;i++) {
  14. HD_ITEM hi;
  15. hi.mask = HDI_WIDTH;
  16. Header_GetItem(hwnd, i, &hi);
  17. m_origwidth+=hi.cxy;
  18. }
  19. for(i=item;i<l;i++) {
  20. if(i==-1) continue;
  21. HD_ITEM hi;
  22. hi.mask = HDI_WIDTH;
  23. Header_GetItem(hwnd, i, &hi);
  24. m_origsizes[i]=hi.cxy;
  25. if(m_origwidth==0)
  26. m_origperc[i]=0;
  27. else
  28. m_origperc[i]=(float)hi.cxy/(float)m_origwidth;
  29. }
  30. }
  31. static void columnAutoResizeProp(HWND hwnd, int item)
  32. {
  33. SendMessage(GetParent(hwnd),WM_SETREDRAW,FALSE,0);
  34. int l=Header_GetItemCount(hwnd);
  35. int width=0;
  36. int i;
  37. HD_ITEM hi;
  38. hi.mask = HDI_WIDTH;
  39. Header_GetItem(hwnd, item, &hi);
  40. width=m_origwidth-(hi.cxy-m_origsizes[item]);
  41. float rest=0;
  42. for(i=item+1;i<l;i++) {
  43. HD_ITEM hi;
  44. hi.mask = HDI_WIDTH;
  45. float l=m_origperc[i]*(float)width;
  46. l+=rest;
  47. rest=0;
  48. int l2=(int)l;
  49. rest+=l-(float)l2;
  50. hi.cxy=l2;
  51. Header_SetItem(hwnd, i, &hi);
  52. }
  53. SendMessage(GetParent(hwnd),WM_SETREDRAW,TRUE,0);
  54. }
  55. static void columnAutoResizeItem(HWND hwnd, int item)
  56. {
  57. HD_ITEM hi;
  58. hi.mask = HDI_WIDTH;
  59. Header_GetItem(hwnd, item, &hi);
  60. int diff=hi.cxy-m_origsizes[item];
  61. hi.mask = HDI_WIDTH;
  62. if(Header_GetItem(hwnd, item+1, &hi)) {
  63. SendMessage(GetParent(hwnd),WM_SETREDRAW,FALSE,0);
  64. hi.cxy-=diff;
  65. Header_SetItem(hwnd,item+1,&hi);
  66. SendMessage(GetParent(hwnd),WM_SETREDRAW,TRUE,0);
  67. }
  68. m_origsizes[item]+=diff;
  69. }
  70. static void size_autoResizeStart(HWND h)
  71. {
  72. RECT r;
  73. GetClientRect(h,&r);
  74. char tmp[128];
  75. wsprintf(tmp,"start:%i\n",r.right-r.left);
  76. OutputDebugString(tmp);
  77. }
  78. static void size_autoResizeProp(HWND h)
  79. {
  80. RECT r;
  81. GetClientRect(h,&r);
  82. char tmp[128];
  83. wsprintf(tmp,"prop:%i\n",r.right-r.left);
  84. OutputDebugString(tmp);
  85. }
  86. INT_PTR handleListViewHeaderMsgs(HWND hwndDlg,
  87. HWND headerWnd,
  88. HWND listWnd,
  89. UINT uMsg,
  90. WPARAM wParam,
  91. LPARAM lParam,
  92. BOOL sortShow,
  93. BOOL sortAscending,
  94. int sortIndex)
  95. {
  96. if (uMsg == WM_NOTIFY) {
  97. LPNMCUSTOMDRAW lpnmcd = (NMCUSTOMDRAW *)lParam;
  98. if(lpnmcd->hdr.code == NM_CUSTOMDRAW && lpnmcd->hdr.hwndFrom == headerWnd) {
  99. switch (lpnmcd->dwDrawStage) {
  100. // prior to painting
  101. case CDDS_PREPAINT:
  102. return CDRF_NOTIFYITEMDRAW; // tell windows we want individual notification of each item being drawn
  103. // notification of each item being drawn
  104. case CDDS_ITEMPREPAINT:
  105. {
  106. LOGBRUSH lb={BS_SOLID,WADlg_getColor(WADLG_LISTHEADER_BGCOLOR)};
  107. HBRUSH brush;
  108. brush=CreateBrushIndirect(&lb);
  109. HDC hdc=lpnmcd->hdc;
  110. RECT *rc=&lpnmcd->rc;
  111. FillRect(hdc,rc,brush);
  112. DeleteObject(brush);
  113. int selected=(lpnmcd->uItemState&CDIS_SELECTED)?1:0;
  114. HPEN pen;
  115. if (!selected) pen=CreatePen(PS_SOLID,1,WADlg_getColor(WADLG_LISTHEADER_FRAME_TOPCOLOR));
  116. else pen=CreatePen(PS_SOLID,1,WADlg_getColor(WADLG_LISTHEADER_FRAME_BOTTOMCOLOR));
  117. HGDIOBJ oldobj=SelectObject(hdc,pen);
  118. //SelectPen(hdc,pen);
  119. MoveToEx(hdc,rc->left,rc->top,NULL);
  120. LineTo(hdc,rc->right,rc->top);
  121. MoveToEx(hdc,rc->left,rc->top,NULL);
  122. LineTo(hdc,rc->left,rc->bottom);
  123. if (!selected)
  124. {
  125. SelectObject(hdc,oldobj);
  126. DeleteObject(pen);
  127. pen=CreatePen(PS_SOLID,1,WADlg_getColor(WADLG_LISTHEADER_FRAME_BOTTOMCOLOR));
  128. oldobj=SelectObject(hdc,pen);
  129. }
  130. MoveToEx(hdc,rc->right-1,rc->top,NULL);
  131. LineTo(hdc,rc->right-1,rc->bottom);
  132. MoveToEx(hdc,rc->right-1,rc->bottom-1,NULL);
  133. LineTo(hdc,rc->left-1,rc->bottom-1);
  134. SelectObject(hdc,oldobj);
  135. DeleteObject(pen);
  136. if(!selected) {
  137. pen=CreatePen(PS_SOLID,1,WADlg_getColor(WADLG_LISTHEADER_FRAME_MIDDLECOLOR));
  138. oldobj=SelectObject(hdc,pen);
  139. MoveToEx(hdc,rc->right-2,rc->top+1,NULL);
  140. LineTo(hdc,rc->right-2,rc->bottom-2);
  141. MoveToEx(hdc,rc->right-2,rc->bottom-2,NULL);
  142. LineTo(hdc,rc->left,rc->bottom-2);
  143. SelectObject(hdc,oldobj);
  144. DeleteObject(pen);
  145. }
  146. DWORD_PTR i=lpnmcd->dwItemSpec;
  147. char txt[128];
  148. LVCOLUMN lv={LVCF_TEXT,0,0,txt,sizeof(txt)-1,};
  149. ListView_GetColumn(listWnd,i,&lv);
  150. SetBkMode(hdc,TRANSPARENT);
  151. SetTextColor(hdc,WADlg_getColor(WADLG_LISTHEADER_FONTCOLOR));
  152. RECT rc2=*rc;
  153. rc2.left+=5; rc2.right-=3;
  154. rc2.top+=2; rc2.bottom-=2;
  155. if(selected) {
  156. rc2.left++;
  157. rc2.top++;
  158. }
  159. if (sortShow && (i == sortIndex) && ((rc->right - rc->left) > 40) )
  160. {
  161. rc2.right -= 14;
  162. HPEN penDark;
  163. pen=CreatePen(PS_SOLID,1,WADlg_getColor(WADLG_LISTHEADER_FRAME_TOPCOLOR));
  164. penDark=CreatePen(PS_SOLID,1,WADlg_getColor(WADLG_LISTHEADER_EMPTY_BGCOLOR));
  165. oldobj=SelectObject(hdc,pen);
  166. if (sortAscending)
  167. {
  168. //strcpy(txt, " /\\ ");
  169. // Draw triangle pointing upwards
  170. MoveToEx(hdc, rc->right - 10, rc->top + 5, NULL);
  171. LineTo(hdc, rc->right - 6, rc->bottom - 6);
  172. LineTo(hdc, rc->right - 15, rc->bottom - 6 );
  173. MoveToEx(hdc, rc->right - 14, rc->bottom - 7, NULL );
  174. SelectObject(hdc, penDark);
  175. LineTo(hdc, rc->right - 10, rc->top + 5);
  176. }
  177. else
  178. {
  179. // Draw triangle pointing downwords
  180. MoveToEx(hdc, rc->right - 7, rc->top + 7, NULL);
  181. LineTo(hdc, rc->right - 11, rc->bottom - 6 );
  182. MoveToEx(hdc, rc->right - 11, rc->bottom - 6, NULL);
  183. SelectObject(hdc, penDark);
  184. LineTo(hdc, rc->right - 15, rc->top + 6 );
  185. LineTo(hdc, rc->right - 6, rc->top + 6);
  186. }
  187. SelectObject(hdc,oldobj);
  188. DeleteObject(pen);
  189. DeleteObject(penDark);
  190. }
  191. DrawText(hdc,txt,-1,&rc2,DT_VCENTER|DT_SINGLELINE|DT_LEFT);
  192. }
  193. return CDRF_SKIPDEFAULT;
  194. }
  195. }
  196. HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam;
  197. if(pHDN->hdr.code == HDN_BEGINTRACKW || pHDN->hdr.code == HDN_BEGINTRACKA)
  198. {
  199. m_column_resize=g_config->ReadInt("column_resize_mode",m_column_resize);
  200. if(m_column_resize) columnTrackStart(pHDN->hdr.hwndFrom, pHDN->iItem);
  201. }
  202. if(pHDN->hdr.code==HDN_ENDTRACKW || pHDN->hdr.code==HDN_ENDTRACKA || pHDN->hdr.code==HDN_ITEMCHANGINGW || pHDN->hdr.code==HDN_ITEMCHANGINGA) {
  203. static int disable=0;
  204. if(disable) return FALSE;
  205. disable=1;
  206. if(m_column_resize==1) columnAutoResizeItem(pHDN->hdr.hwndFrom, pHDN->iItem);
  207. if(m_column_resize==2) columnAutoResizeProp(pHDN->hdr.hwndFrom, pHDN->iItem);
  208. disable=0;
  209. SendMessage(hwndDlg,WM_USER+0x3443,0,0); //update ScrollWnd
  210. }
  211. }
  212. /*if(uMsg==WM_WINDOWPOSCHANGING) {
  213. HWND h=ListView_GetHeader(hwndDlg);
  214. if(h) size_autoResizeStart(h);
  215. }
  216. if(uMsg==WM_SIZE) {
  217. HWND h=ListView_GetHeader(hwndDlg);
  218. if(h) size_autoResizeProp(h);
  219. }*/
  220. return 0;
  221. }
  222. static int RectInRect(RECT *rect1, RECT *rect2)
  223. {
  224. // this has a bias towards true
  225. // this could probably be optimized a lot
  226. return ((rect1->top >= rect2->top && rect1->top <= rect2->bottom) ||
  227. (rect1->bottom >= rect2->top && rect1->bottom <= rect2->bottom) ||
  228. (rect2->top >= rect1->top && rect2->top <= rect1->bottom) ||
  229. (rect2->bottom >= rect1->top && rect2->bottom <= rect1->bottom)) // vertical intersect
  230. &&
  231. ((rect1->left >= rect2->left && rect1->left <= rect2->right) ||
  232. (rect1->right >= rect2->left && rect1->right <= rect2->right) ||
  233. (rect2->left >= rect1->left && rect2->left <= rect1->right) ||
  234. (rect2->right >= rect1->left && rect2->right <= rect1->right)) // horiz intersect
  235. ;
  236. }
  237. INT_PTR handleListViewHeaderPaintMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  238. if(uMsg==WM_ERASEBKGND)
  239. {
  240. return 1; //we erase the background below
  241. }
  242. if(uMsg==WM_PAINT)
  243. {
  244. //process the grey area with our color
  245. RECT r;
  246. GetClientRect(hwndDlg,&r);
  247. int n=Header_GetItemCount(hwndDlg);
  248. if(n)
  249. {
  250. RECT r2;
  251. Header_GetItemRect(hwndDlg,n-1,&r2);
  252. r.left=r2.right;
  253. }
  254. RECT ur;
  255. GetUpdateRect(hwndDlg,&ur,FALSE);
  256. if(RectInRect(&r,&ur))
  257. {
  258. HDC hdc=GetDC(hwndDlg);
  259. HBRUSH b=CreateSolidBrush(WADlg_getColor(WADLG_LISTHEADER_EMPTY_BGCOLOR));
  260. FillRect(hdc,&r,b);
  261. DeleteObject(b);
  262. ReleaseDC(hwndDlg,hdc);
  263. ValidateRect(hwndDlg,&r);
  264. }
  265. }
  266. return 0;
  267. }