Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
12 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <malloc.h>
  4. #include <string.h>
  5. #include "hierdraw.h"
  6. VOID HierDraw_DrawTerm(LPHEIRDRAWSTRUCT lpHierDrawStruct) {
  7. if (lpHierDrawStruct->hbmIcons) {
  8. if (lpHierDrawStruct->hbmMem)
  9. SelectObject(lpHierDrawStruct->hdcMem,lpHierDrawStruct->hbmMem);
  10. lpHierDrawStruct->hbmMem = NULL;
  11. DeleteObject(lpHierDrawStruct->hbmIcons);
  12. lpHierDrawStruct->hbmIcons = NULL;
  13. }
  14. if ( lpHierDrawStruct->hdcMem ) {
  15. DeleteDC(lpHierDrawStruct->hdcMem);
  16. lpHierDrawStruct->hdcMem = NULL;
  17. }
  18. } // HierDraw_DrawTerm
  19. VOID HierDraw_DrawCloseAll(LPHEIRDRAWSTRUCT lpHierDrawStruct ) {
  20. lpHierDrawStruct->NumOpened= 0;
  21. if ( lpHierDrawStruct->Opened ) {
  22. _ffree(lpHierDrawStruct->Opened);
  23. }
  24. lpHierDrawStruct->Opened = NULL;
  25. } // HierDraw_DrawCloseAll
  26. VOID HierDraw_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT FAR* lpMeasureItem,
  27. LPHEIRDRAWSTRUCT lpHierDrawStruct) {
  28. lpMeasureItem->itemHeight = max(lpHierDrawStruct->nBitmapHeight,
  29. lpHierDrawStruct->nTextHeight);
  30. } // HierDraw_OnMeasureItem
  31. VOID HierDraw_DrawSetTextHeight (HWND hwndList, HFONT hFont, LPHEIRDRAWSTRUCT lpHierDrawStruct ) {
  32. TEXTMETRIC TextMetrics;
  33. HANDLE hOldFont=NULL;
  34. HDC hdc;
  35. //
  36. // This sure looks like a lot of work to find the character height
  37. //
  38. hdc = GetDC(hwndList);
  39. hOldFont = SelectObject(hdc, hFont);
  40. GetTextMetrics(hdc, &TextMetrics);
  41. SelectObject(hdc, hOldFont);
  42. ReleaseDC(hwndList, hdc);
  43. lpHierDrawStruct->nTextHeight = TextMetrics.tmHeight;
  44. lpHierDrawStruct->nLineHeight =
  45. max(lpHierDrawStruct->nBitmapHeight, lpHierDrawStruct->nTextHeight);
  46. if ( hwndList != NULL )
  47. SendMessage(hwndList, LB_SETITEMHEIGHT, 0,
  48. MAKELPARAM(lpHierDrawStruct->nLineHeight, 0));
  49. } // HierDraw_DrawSetTextHeight
  50. static DWORD near RGB2BGR(DWORD rgb) {
  51. return RGB(GetBValue(rgb),GetGValue(rgb),GetRValue(rgb));
  52. } // RGB2BGR
  53. /*
  54. * Creates the objects used while drawing the tree. This may be called
  55. * repeatedly in the event of a WM_SYSCOLORCHANGED message.
  56. *
  57. * WARNING: the Tree icons bitmap is assumed to be a 16 color DIB!
  58. */
  59. BOOL HierDraw_DrawInit(HINSTANCE hInstance,
  60. int nBitmap,
  61. int nRows,
  62. int nColumns,
  63. BOOL bLines,
  64. LPHEIRDRAWSTRUCT lpHierDrawStruct,
  65. BOOL bInit) {
  66. HANDLE hRes;
  67. HANDLE hResMem;
  68. LPBITMAPINFOHEADER lpbiReadOnly;
  69. LPBITMAPINFOHEADER lpbiReadWrite;
  70. DWORD *lpColorTable;
  71. LPSTR lpBits;
  72. int biSize;
  73. int bc;
  74. HDC hDC;
  75. if ( bInit ) {
  76. lpHierDrawStruct->NumOpened = 0;
  77. lpHierDrawStruct->Opened = NULL;
  78. lpHierDrawStruct->bLines = bLines;
  79. }
  80. //
  81. // If the Memory DC is not created yet do that first.
  82. //
  83. if (!lpHierDrawStruct->hdcMem) {
  84. //
  85. // get a screen DC
  86. //
  87. hDC = GetDC(NULL);
  88. //
  89. // Create a memory DC compatible with the screen
  90. //
  91. lpHierDrawStruct->hdcMem = CreateCompatibleDC(hDC);
  92. //
  93. // Release the Screen DC
  94. ReleaseDC(NULL,hDC);
  95. if (!lpHierDrawStruct->hdcMem)
  96. return FALSE;
  97. lpHierDrawStruct->hbmMem = NULL;
  98. }
  99. //
  100. // (Re)Load the Bitmap ( original from disk )
  101. //
  102. // Use the FindResource,LoadResource,LockResource since it makes
  103. // it easy to get the pointer to the BITMAPINFOHEADER we need.
  104. //
  105. //
  106. hRes = FindResource(hInstance, MAKEINTRESOURCE(nBitmap), RT_BITMAP);
  107. if (!hRes)
  108. return FALSE;
  109. hResMem = LoadResource(hInstance, hRes);
  110. if (!hResMem)
  111. return FALSE;
  112. // Now figure out the bitmaps background color.
  113. // This code assumes the lower left corner is a
  114. // bit in the background color.
  115. lpbiReadOnly = (LPBITMAPINFOHEADER)LockResource(hResMem);
  116. if (!lpbiReadOnly)
  117. return FALSE;
  118. // Determine size of bitmap information header plus color table entries
  119. biSize = lpbiReadOnly->biSize + ((1 << (lpbiReadOnly->biBitCount)) * sizeof(RGBQUAD));
  120. // Allocate copy of the bitmap information to munge on
  121. lpbiReadWrite = (LPBITMAPINFOHEADER)GlobalAlloc(GPTR, biSize);
  122. if (!lpbiReadWrite)
  123. return FALSE;
  124. memcpy(lpbiReadWrite, lpbiReadOnly, biSize);
  125. // Color table immediately follows bitmap information header
  126. lpColorTable = (DWORD FAR *)((LPBYTE)lpbiReadWrite + lpbiReadWrite->biSize);
  127. // No need to munge bits so use original
  128. lpBits = (LPBYTE)lpbiReadOnly + biSize;
  129. bc = (lpBits[0] & 0xF0) >> 4; // ASSUMES LOWER LEFT CORNER IS BG!!
  130. lpColorTable[bc] = RGB2BGR(GetSysColor(COLOR_WINDOW));
  131. hDC = GetDC(NULL);
  132. lpHierDrawStruct->hbmIcons = CreateDIBitmap(
  133. hDC,
  134. lpbiReadWrite,
  135. CBM_INIT,
  136. lpBits,
  137. (LPBITMAPINFO)lpbiReadWrite,
  138. DIB_RGB_COLORS
  139. );
  140. ReleaseDC(NULL,hDC);
  141. lpHierDrawStruct->nBitmapHeight = (WORD)lpbiReadWrite->biHeight / nRows;
  142. lpHierDrawStruct->nBitmapWidth = (WORD)lpbiReadWrite->biWidth / nColumns;
  143. lpHierDrawStruct->nLineHeight =
  144. max(lpHierDrawStruct->nBitmapHeight, lpHierDrawStruct->nTextHeight);
  145. GlobalFree(lpbiReadWrite);
  146. UnlockResource(hResMem);
  147. FreeResource(hResMem);
  148. if (!lpHierDrawStruct->hbmIcons)
  149. return FALSE;
  150. lpHierDrawStruct->hbmMem = SelectObject(lpHierDrawStruct->hdcMem,lpHierDrawStruct->hbmIcons);
  151. if (!lpHierDrawStruct->hbmMem)
  152. return FALSE;
  153. return TRUE;
  154. } // HierDraw_DrawInit
  155. VOID HierDraw_OnDrawItem(HWND hwnd,
  156. const DRAWITEMSTRUCT FAR* lpDrawItem,
  157. int nLevel,
  158. DWORD dwConnectLevel,
  159. TCHAR *szText,
  160. int nRow,
  161. int nColumn,
  162. LPHEIRDRAWSTRUCT lpHierDrawStruct) {
  163. HDC hDC;
  164. WORD wIndent, wTopBitmap, wTopText;
  165. RECT rcTemp;
  166. if ( lpDrawItem->itemID == (UINT)-1 )
  167. return ;
  168. hDC = lpDrawItem->hDC;
  169. CopyRect(&rcTemp, &lpDrawItem->rcItem);
  170. wIndent = (WORD)(rcTemp.left + ((int)(nLevel) * lpHierDrawStruct->nBitmapWidth) + XBMPOFFSET);
  171. rcTemp.left = wIndent + lpHierDrawStruct->nBitmapWidth;
  172. wTopText = (WORD)(rcTemp.top + ((rcTemp.bottom - rcTemp.top) / 2) - (lpHierDrawStruct->nTextHeight / 2));
  173. wTopBitmap = (WORD)(rcTemp.top + ((rcTemp.bottom - rcTemp.top) / 2) - (lpHierDrawStruct->nBitmapHeight / 2));
  174. if (lpDrawItem->itemAction == ODA_FOCUS)
  175. goto DealWithFocus;
  176. else if (lpDrawItem->itemAction == ODA_SELECT)
  177. goto DealWithSelection;
  178. //
  179. // Draw some lions, if we like lions
  180. //
  181. if (lpHierDrawStruct->bLines && nLevel)
  182. {
  183. DWORD dwMask = 1;
  184. int nTempLevel;
  185. int x,y;
  186. // draw lines in text color
  187. SetBkColor(hDC,GetSysColor(COLOR_WINDOWTEXT));
  188. //
  189. // Draw a series of | lines for outer levels
  190. //
  191. x = lpHierDrawStruct->nBitmapWidth/2 + XBMPOFFSET;
  192. for ( nTempLevel = 0; nTempLevel < nLevel ; nTempLevel++)
  193. {
  194. if ( dwConnectLevel & dwMask )
  195. FastRect(hDC,x,rcTemp.top,1,rcTemp.bottom - rcTemp.top);
  196. x += lpHierDrawStruct->nBitmapWidth;
  197. dwMask *= 2;
  198. }
  199. //
  200. // Draw the short vert line up towards the parent
  201. //
  202. nTempLevel = nLevel-1;
  203. dwMask *= 2;
  204. x = nTempLevel * lpHierDrawStruct->nBitmapWidth + lpHierDrawStruct->nBitmapWidth / 2 + XBMPOFFSET;
  205. if ( dwConnectLevel & dwMask )
  206. y = rcTemp.bottom;
  207. else
  208. y = rcTemp.bottom - lpHierDrawStruct->nLineHeight / 2;
  209. FastRect(hDC,x,rcTemp.top,1,y-rcTemp.top);
  210. //
  211. // Draw short horiz bar to right
  212. //
  213. FastRect(hDC,x,rcTemp.bottom-lpHierDrawStruct->nLineHeight/2,lpHierDrawStruct->nBitmapWidth/2,1);
  214. }
  215. //
  216. // Draw the selected bitmap
  217. //
  218. BitBlt(hDC,
  219. wIndent,wTopBitmap,
  220. lpHierDrawStruct->nBitmapWidth,lpHierDrawStruct->nBitmapHeight,
  221. lpHierDrawStruct->hdcMem,
  222. nColumn*lpHierDrawStruct->nBitmapWidth,
  223. nRow*lpHierDrawStruct->nBitmapHeight,
  224. SRCCOPY);
  225. DealWithSelection:
  226. if (lpDrawItem->itemState & ODS_SELECTED)
  227. {
  228. SetBkColor(hDC,GetSysColor(COLOR_HIGHLIGHT));
  229. SetTextColor(hDC,GetSysColor(COLOR_HIGHLIGHTTEXT));
  230. }
  231. else
  232. {
  233. SetBkColor(hDC,GetSysColor(COLOR_WINDOW));
  234. SetTextColor(hDC,GetSysColor(COLOR_WINDOWTEXT));
  235. }
  236. ExtTextOut(hDC, rcTemp.left + 1, wTopText, ETO_CLIPPED|ETO_OPAQUE,
  237. &rcTemp,szText,lstrlen(szText), NULL);
  238. if (lpDrawItem->itemState & ODS_FOCUS && lpDrawItem->itemAction != ODA_SELECT) {
  239. DealWithFocus:
  240. DrawFocusRect(hDC, &rcTemp);
  241. }
  242. } // HierDraw_OnDrawItem
  243. //
  244. // draw a solid color rectangle quickly
  245. //
  246. static VOID near FastRect(HDC hDC, int x, int y, int cx, int cy) {
  247. RECT rc;
  248. rc.left = x;
  249. rc.right = x+cx;
  250. rc.top = y;
  251. rc.bottom = y+cy;
  252. ExtTextOut(hDC,x,y,ETO_OPAQUE,&rc,NULL,0,NULL);
  253. } // FastRect
  254. BOOL HierDraw_IsOpened(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD_PTR dwData) {
  255. // For Now just a dumb search
  256. //
  257. int Count;
  258. for ( Count = 0; Count < lpHierDrawStruct->NumOpened; Count++ ) {
  259. if ( lpHierDrawStruct->Opened[Count] == dwData ) {
  260. return TRUE;
  261. }
  262. }
  263. return FALSE;
  264. } // HierDraw_IsOpened
  265. VOID HierDraw_OpenItem(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD_PTR dwData) {
  266. lpHierDrawStruct->NumOpened++;
  267. if (lpHierDrawStruct->Opened == NULL )
  268. lpHierDrawStruct->Opened =
  269. (DWORD_PTR *)_fmalloc(sizeof(DWORD_PTR)*lpHierDrawStruct->NumOpened);
  270. else
  271. lpHierDrawStruct->Opened =
  272. (DWORD_PTR *)_frealloc(lpHierDrawStruct->Opened,
  273. sizeof(DWORD_PTR)*lpHierDrawStruct->NumOpened);
  274. lpHierDrawStruct->Opened[lpHierDrawStruct->NumOpened-1] = dwData;
  275. } // HierDraw_OpenItem
  276. VOID HierDraw_CloseItem(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD_PTR dwData) {
  277. // For Now just a dumb search
  278. //
  279. int Count;
  280. for ( Count = 0; Count < lpHierDrawStruct->NumOpened; Count++ ) {
  281. if ( lpHierDrawStruct->Opened[Count] == dwData ) {
  282. if (--lpHierDrawStruct->NumOpened == 0 ) {
  283. _ffree(lpHierDrawStruct->Opened);
  284. lpHierDrawStruct->Opened = NULL;
  285. }
  286. else {
  287. if ( Count < lpHierDrawStruct->NumOpened ) {
  288. _fmemmove(&(lpHierDrawStruct->Opened[Count]),
  289. &(lpHierDrawStruct->Opened[Count+1]),
  290. sizeof(DWORD)*(lpHierDrawStruct->NumOpened-Count));
  291. }
  292. lpHierDrawStruct->Opened =
  293. (DWORD_PTR *)_frealloc(lpHierDrawStruct->Opened,
  294. sizeof(DWORD_PTR)*lpHierDrawStruct->NumOpened);
  295. }
  296. }
  297. }
  298. } // HierDraw_CloseItem
  299. VOID HierDraw_ShowKids(LPHEIRDRAWSTRUCT lpHierDrawStruct,
  300. HWND hwndList, WORD wCurrentSelection, WORD wKids) {
  301. WORD wBottomIndex;
  302. WORD wTopIndex;
  303. WORD wNewTopIndex;
  304. WORD wExpandInView;
  305. RECT rc;
  306. wTopIndex = (WORD)SendMessage(hwndList, LB_GETTOPINDEX, 0, 0L);
  307. GetClientRect(hwndList, &rc);
  308. wBottomIndex = (WORD)(wTopIndex + (rc.bottom+1) / lpHierDrawStruct->nLineHeight);
  309. wExpandInView = (wBottomIndex - wCurrentSelection);
  310. if (wKids >= wExpandInView) {
  311. wNewTopIndex = min(wCurrentSelection, wTopIndex + wKids - wExpandInView + 1);
  312. SendMessage(hwndList, LB_SETTOPINDEX, (WORD)wNewTopIndex, 0L);
  313. }
  314. } // HierDraw_ShowKids