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.

506 lines
16 KiB

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