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.

1532 lines
33 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. image.c
  5. Abstract:
  6. This module contains all the function to manuplate the image list
  7. Author:
  8. 06-Jul-1995 Thu 17:10:40 created -by- Daniel Chou (danielc)
  9. [Environment:]
  10. NT Windows - Common Printer Driver UI DLL.
  11. [Notes:]
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #define DBG_CPSUIFILENAME DbgImage
  17. #define DBG_CTVICON 0x00000001
  18. #define DBG_SETTVICON 0x00000002
  19. #define DBG_CIL 0x00000004
  20. #define DBG_GETICON16IDX 0x00000008
  21. #define DBG_REALLOC 0x00000010
  22. #define DBG_MTVICON 0x00000020
  23. #define DBG_SAVEICON 0x00000040
  24. #define DBG_ICONCHKSUM 0x00000080
  25. #define DBG_FIRST_ICON 0x00000100
  26. #define DBG_CREATEIL 0x00000200
  27. #define DBG_CYICON 0x00000400
  28. DEFINE_DBGVAR(0);
  29. #define BFT_ICON 0x4349 /* 'IC' */
  30. #define BFT_BITMAP 0x4d42 /* 'BM' */
  31. #define BFT_CURSOR 0x5450 /* 'PT' */
  32. #define ISDIB(bft) ((bft) == BFT_BITMAP)
  33. extern HINSTANCE hInstDLL;
  34. extern OPTTYPE OptTypeNone;
  35. #if 0
  36. typedef struct _BMIGRAY {
  37. BITMAPINFOHEADER bmh;
  38. RGBQUAD rgbq[2];
  39. DWORD Bits[8];
  40. } BMIGRAY, *PBMIGRAY;
  41. static BMIGRAY bmiGray = {
  42. { sizeof(BITMAPINFOHEADER), 32, 8, 1, 1, BI_RGB, 0, 0, 0, 2, 2 },
  43. {
  44. { 0x00, 0x00, 0x00, 0 },
  45. { 0xFF, 0xFF, 0xFF, 0 }
  46. },
  47. { 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa,
  48. 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa }
  49. };
  50. #endif
  51. #if DBG
  52. #define DBG_SAVE_ICON_BMP 0
  53. #else
  54. #define DBG_SAVE_ICON_BMP 0
  55. #endif
  56. #if DBG_SAVE_ICON_BMP
  57. #define SBTF_NAME 0
  58. #define SBTF_MASK -1
  59. #define SBTF_CLR -2
  60. HANDLE
  61. BMPToDIB(
  62. HBITMAP hBitmap
  63. )
  64. {
  65. HANDLE hDIB = NULL;
  66. LPBITMAPINFO pbi;
  67. HDC hDC;
  68. BITMAP Bmp;
  69. DWORD BIMode;
  70. DWORD Colors;
  71. DWORD SizeH;
  72. DWORD SizeI;
  73. GetObject(hBitmap, sizeof(BITMAP), &Bmp);
  74. if (Bmp.bmPlanes == 1) {
  75. switch(Bmp.bmBitsPixel) {
  76. case 1:
  77. case 4:
  78. case 8:
  79. BIMode = BI_RGB;
  80. Colors = (DWORD)(1L << Bmp.bmBitsPixel);
  81. break;
  82. case 16:
  83. BIMode = BI_BITFIELDS;
  84. Colors = 3;
  85. break;
  86. case 24:
  87. BIMode = BI_RGB;
  88. Colors = 0;
  89. break;
  90. default:
  91. return(NULL);
  92. }
  93. SizeH = (DWORD)sizeof(BITMAPINFOHEADER) +
  94. (DWORD)(Colors * sizeof(RGBQUAD));
  95. SizeI = (DWORD)ALIGN_DW(Bmp.bmWidth, Bmp.bmBitsPixel) *
  96. (DWORD)Bmp.bmHeight;
  97. if (hDIB = GlobalAlloc(GHND, (SizeH + SizeI))) {
  98. pbi = GlobalLock(hDIB);
  99. pbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  100. pbi->bmiHeader.biWidth = Bmp.bmWidth;
  101. pbi->bmiHeader.biHeight = Bmp.bmHeight;
  102. pbi->bmiHeader.biPlanes = 1;
  103. pbi->bmiHeader.biBitCount = Bmp.bmBitsPixel;
  104. pbi->bmiHeader.biCompression = BIMode;
  105. pbi->bmiHeader.biSizeImage = SizeI;
  106. pbi->bmiHeader.biXPelsPerMeter = 0;
  107. pbi->bmiHeader.biYPelsPerMeter = 0;
  108. hDC = GetDC(NULL);
  109. GetDIBits(hDC,
  110. hBitmap,
  111. 0,
  112. Bmp.bmHeight,
  113. (LPBYTE)pbi + SizeH,
  114. pbi,
  115. DIB_RGB_COLORS);
  116. pbi->bmiHeader.biClrUsed =
  117. pbi->bmiHeader.biClrImportant = Colors;
  118. GlobalUnlock(hDIB);
  119. ReleaseDC(NULL, hDC);
  120. }
  121. }
  122. return(hDIB);
  123. }
  124. BOOL
  125. SaveBmpToFile(
  126. HBITMAP hBmp,
  127. LPVOID pIconID,
  128. INT Mode
  129. )
  130. /*++
  131. Routine Description:
  132. Arguments:
  133. Return Value:
  134. Author:
  135. 20-Sep-1995 Wed 22:58:10 created -by- Daniel Chou (danielc)
  136. Revision History:
  137. --*/
  138. {
  139. HANDLE hDIB;
  140. HANDLE hFile;
  141. BITMAPFILEHEADER bfh;
  142. DWORD cbWritten;
  143. BOOL Ok = FALSE;
  144. WCHAR Buf[80];
  145. UINT Count;
  146. if (!(DBG_CPSUIFILENAME & DBG_SAVEICON)) {
  147. return(TRUE);
  148. }
  149. Count = wsprintf(Buf, L"d:/IconDIB/");
  150. switch(Mode) {
  151. case SBTF_NAME:
  152. wnsprintf(&Buf[Count], ARRAYSIZE(Buf) - Count - 1, L"%hs.dib", (LPTSTR)pIconID);
  153. break;
  154. case SBTF_MASK:
  155. case SBTF_CLR:
  156. wsprintf(&Buf[Count], L"%lu%s.dib",
  157. (DWORD)pIconID, (Mode == SBTF_MASK) ? L"Msk" : L"Clr");
  158. break;
  159. default:
  160. wsprintf(&Buf[Count], L"_%lu.dib", (DWORD)Mode);
  161. break;
  162. }
  163. if ((hDIB = BMPToDIB(hBmp)) &&
  164. ((hFile = CreateFile(Buf,
  165. GENERIC_WRITE,
  166. 0,
  167. NULL,
  168. CREATE_ALWAYS,
  169. FILE_FLAG_WRITE_THROUGH,
  170. NULL)) != INVALID_HANDLE_VALUE)) {
  171. LPBITMAPINFOHEADER pbih;
  172. DWORD HeaderSize;
  173. pbih = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  174. HeaderSize = PBIH_HDR_SIZE(pbih);
  175. bfh.bfType = (WORD)BFT_BITMAP;
  176. bfh.bfOffBits = (DWORD)sizeof(bfh) + HeaderSize;
  177. bfh.bfSize = bfh.bfOffBits + pbih->biSizeImage;
  178. bfh.bfReserved1 =
  179. bfh.bfReserved2 = (WORD)0;
  180. WriteFile(hFile,
  181. &bfh,
  182. sizeof(bfh),
  183. &cbWritten,
  184. NULL);
  185. WriteFile(hFile,
  186. pbih,
  187. pbih->biSizeImage + HeaderSize,
  188. &cbWritten,
  189. NULL);
  190. CloseHandle(hFile);
  191. GlobalUnlock(hDIB);
  192. Ok = TRUE;
  193. }
  194. if (hDIB) {
  195. hDIB = GlobalFree(hDIB);
  196. }
  197. return(Ok);
  198. }
  199. VOID
  200. SaveIconToFile(
  201. HICON hIcon,
  202. DWORD IconID
  203. )
  204. {
  205. if (hIcon) {
  206. ICONINFO IconInfo;
  207. GetIconInfo(hIcon, &IconInfo);
  208. SaveBmpToFile(IconInfo.hbmMask, (LPVOID)IconID, SBTF_MASK);
  209. SaveBmpToFile(IconInfo.hbmColor, (LPVOID)IconID, SBTF_CLR);
  210. DeleteObject(IconInfo.hbmMask);
  211. DeleteObject(IconInfo.hbmColor);
  212. }
  213. }
  214. #endif // DBG_SAVE_ICON_BMP
  215. #if 0
  216. HBRUSH
  217. CreateGrayBrush(
  218. COLORREF Color
  219. )
  220. /*++
  221. Routine Description:
  222. Arguments:
  223. Return Value:
  224. Author:
  225. 13-Oct-1995 Fri 12:58:15 created -by- Daniel Chou (danielc)
  226. Revision History:
  227. --*/
  228. {
  229. HBRUSH hBrush = NULL;
  230. HGLOBAL hGlobal;
  231. if (hGlobal = GlobalAlloc(GMEM_FIXED, sizeof(BMIGRAY))) {
  232. PBMIGRAY pbmiGray;
  233. CopyMemory(pbmiGray = (PBMIGRAY)GlobalLock(hGlobal),
  234. &bmiGray,
  235. sizeof(BMIGRAY));
  236. pbmiGray->rgbq[1].rgbRed = GetRValue(Color);
  237. pbmiGray->rgbq[1].rgbGreen = GetGValue(Color);
  238. pbmiGray->rgbq[1].rgbBlue = GetBValue(Color);
  239. GlobalUnlock(hGlobal);
  240. if (!(hBrush = CreateDIBPatternBrush(hGlobal, DIB_RGB_COLORS))) {
  241. GlobalFree(hGlobal);
  242. }
  243. }
  244. return(hBrush);
  245. }
  246. VOID
  247. DestroyGrayBrush(
  248. HBRUSH hBrush
  249. )
  250. /*++
  251. Routine Description:
  252. Arguments:
  253. Return Value:
  254. Author:
  255. 13-Oct-1995 Fri 13:21:40 created -by- Daniel Chou (danielc)
  256. Revision History:
  257. --*/
  258. {
  259. LOGBRUSH LogBrush;
  260. if (hBrush) {
  261. if ((GetObject(hBrush, sizeof(LOGBRUSH), &LogBrush)) &&
  262. (LogBrush.lbStyle == BS_DIBPATTERN)) {
  263. GlobalFree((HGLOBAL)LogBrush.lbHatch);
  264. }
  265. DeleteObject(hBrush);
  266. }
  267. }
  268. #endif
  269. HICON
  270. MergeIcon(
  271. HINSTANCE hInst,
  272. ULONG_PTR IconResID,
  273. DWORD IntIconID,
  274. UINT cxIcon,
  275. UINT cyIcon
  276. )
  277. /*++
  278. Routine Description:
  279. This function load the IconResID and stretch it to the cxIcon/cyIcon size
  280. and optional merge the HIWORD(IntIconID) (32x32) in the position of
  281. IconRes1D's (0, 0)
  282. Arguments:
  283. hInst - Instance handle for the IconResID
  284. IconResID - Icon ID for the first Icon
  285. IntIconID - LOWORD(IntIconID) = the internal icon id if IconID is not
  286. avaliable
  287. HIWORD(IntIconID) = MIM_xxxx merge icon mode ID
  288. cxIcon - cx size of the icon want to create
  289. cyIcon - cy size of the icon want to create
  290. Return Value:
  291. HICON, the newly created and/or merged icon handle, NULL if failed, the
  292. caller must do DestroyIcon() after using it if it is not NULL.
  293. Author:
  294. 15-Aug-1995 Tue 13:27:34 created -by- Daniel Chou (danielc)
  295. Revision History:
  296. --*/
  297. {
  298. HICON hIcon1;
  299. HICON hIcon2;
  300. HICON hIconMerge;
  301. HICON hIcon1Caller;
  302. HDC hDCScreen;
  303. HDC hDCDst;
  304. HGDIOBJ hOldDst = NULL;
  305. BITMAP Bitmap;
  306. WORD MergeIconMode;
  307. WORD IconID;
  308. WORD IconIDSet[MIM_MAX_OVERLAY + 2];
  309. UINT IdxIconID;
  310. ICONINFO IconInfo1;
  311. hIcon1Caller = NULL;
  312. if (VALID_PTR(IconResID)) {
  313. if ((hIcon1 = GET_HICON(IconResID)) &&
  314. (GetIconInfo(hIcon1, &IconInfo1))) {
  315. hIcon1Caller = hIcon1;
  316. IconID = 0xFFFF;
  317. IconResID = 0xFFFF;
  318. } else {
  319. CPSUIERR(("MergeIcon: Passed Invalid hIcon=%08lx,", hIcon1));
  320. hIcon1 = NULL;
  321. }
  322. } else {
  323. hIcon1 = NULL;
  324. }
  325. if (!hIcon1) {
  326. IconIDSet[0] = GET_INTICONID(IntIconID);
  327. IconIDSet[1] = LOWORD(IconResID);
  328. IdxIconID = 2;
  329. while ((!hIcon1) && (IdxIconID--)) {
  330. if (IconID = IconIDSet[IdxIconID]) {
  331. hIcon1 = GETICON_SIZE(hInst, IconID, cxIcon, cyIcon);
  332. }
  333. }
  334. }
  335. if ((hIcon1) &&
  336. ((hIcon1Caller) || (GetIconInfo(hIcon1, &IconInfo1)))) {
  337. GetObject(IconInfo1.hbmMask, sizeof(BITMAP), &Bitmap);
  338. if ((hIcon1 == hIcon1Caller) ||
  339. (Bitmap.bmWidth != (LONG)cxIcon) ||
  340. (Bitmap.bmHeight != (LONG)cyIcon)) {
  341. CPSUIINT(("MergeIcon: hIcon1=%ld x %ld, Change to %u x %u",
  342. Bitmap.bmWidth, Bitmap.bmHeight, cxIcon, cyIcon));
  343. hIcon1 = CopyImage(hIcon2 = hIcon1, IMAGE_ICON, cxIcon, cyIcon, 0);
  344. //
  345. // Destroy Original Icon only if hIcon1 is not from the caller
  346. //
  347. if (hIcon1Caller != hIcon2) {
  348. DestroyIcon(hIcon2);
  349. }
  350. }
  351. } else {
  352. CPSUIERR(("MergeIcon: FAILED hIcon1=%08lx,", hIcon1));
  353. }
  354. #if DBG_SAVE_ICON_BMP
  355. SaveIconToFile(hIcon1, IconID);
  356. #endif
  357. if (!(MergeIconMode = GET_MERGEICONID(IntIconID))) {
  358. //
  359. // Nothing to be merged so just return the hIcon1, we do not need the
  360. // IconInfo1 information, so destroy the object before return
  361. //
  362. if (IconInfo1.hbmMask)
  363. {
  364. DeleteObject(IconInfo1.hbmMask);
  365. }
  366. if (IconInfo1.hbmColor)
  367. {
  368. DeleteObject(IconInfo1.hbmColor);
  369. }
  370. return(hIcon1);
  371. }
  372. IconIDSet[0] = (MergeIconMode & MIM_WARNING_OVERLAY) ?
  373. IDI_CPSUI_WARNING_OVERLAY : 0;
  374. IconIDSet[1] = (MergeIconMode & MIM_NO_OVERLAY) ? IDI_CPSUI_NO : 0;
  375. IconIDSet[2] = (MergeIconMode & MIM_STOP_OVERLAY) ? IDI_CPSUI_STOP : 0;
  376. IdxIconID = 3;
  377. //
  378. // Start creating the new icon, the IconInfo1 is the cx/cy Icon size
  379. // padded in and the IconInfo2 is the standard 32x32 icon
  380. //
  381. hDCDst = CreateCompatibleDC(hDCScreen = GetDC(NULL));
  382. if (hIcon1) {
  383. hOldDst = SelectObject(hDCDst, IconInfo1.hbmMask);
  384. }
  385. SetStretchBltMode(hDCDst, BLACKONWHITE);
  386. while (IdxIconID--) {
  387. if ((IconID = IconIDSet[IdxIconID]) &&
  388. (hIcon2 = GETICON_SIZE(hInst, IconID, cxIcon, cyIcon))) {
  389. #if DBG_SAVE_ICON_BMP
  390. SaveIconToFile(hIcon2, IconID);
  391. #endif
  392. if (hIcon1) {
  393. HDC hDCSrc;
  394. HGDIOBJ hOldSrc;
  395. ICONINFO IconInfo2;
  396. hDCSrc = CreateCompatibleDC(hDCScreen);
  397. GetIconInfo(hIcon2, &IconInfo2);
  398. hOldSrc = SelectObject(hDCSrc, IconInfo2.hbmMask);
  399. SelectObject(hDCDst, IconInfo1.hbmMask);
  400. StretchBlt(hDCDst,
  401. 0,
  402. 0,
  403. cxIcon,
  404. cyIcon,
  405. hDCSrc,
  406. 0,
  407. 0,
  408. cxIcon,
  409. cyIcon,
  410. SRCAND);
  411. //
  412. // clear the hIcon1's XOR color to leave room for the hIcon2
  413. //
  414. SelectObject(hDCDst, IconInfo1.hbmColor);
  415. StretchBlt(hDCDst,
  416. 0,
  417. 0,
  418. cxIcon,
  419. cyIcon,
  420. hDCSrc,
  421. 0,
  422. 0,
  423. cxIcon,
  424. cyIcon,
  425. SRCAND);
  426. //
  427. // Now add in the hIcon2's XOR color to the the hIcon1
  428. //
  429. SelectObject(hDCSrc, IconInfo2.hbmColor);
  430. StretchBlt(hDCDst,
  431. 0,
  432. 0,
  433. cxIcon,
  434. cyIcon,
  435. hDCSrc,
  436. 0,
  437. 0,
  438. cxIcon,
  439. cyIcon,
  440. SRCPAINT);
  441. //
  442. // de-select everything from the DC before the create/delete
  443. //
  444. SelectObject(hDCSrc, hOldSrc);
  445. DeleteDC(hDCSrc);
  446. DeleteObject(IconInfo2.hbmMask);
  447. DeleteObject(IconInfo2.hbmColor);
  448. DestroyIcon(hIcon2);
  449. } else {
  450. GetIconInfo(hIcon2, &IconInfo1);
  451. GetObject(IconInfo1.hbmMask, sizeof(BITMAP), &Bitmap);
  452. if ((Bitmap.bmWidth != (LONG)cxIcon) ||
  453. (Bitmap.bmHeight != (LONG)cyIcon)) {
  454. CPSUIINT(("MergeIcon: hIcon1=%ld x %ld, Change to %u x %u",
  455. Bitmap.bmWidth, Bitmap.bmHeight, cxIcon, cyIcon));
  456. hIcon1 = CopyImage(hIcon2, IMAGE_ICON, cxIcon, cyIcon, 0);
  457. DeleteObject(IconInfo1.hbmMask);
  458. DeleteObject(IconInfo1.hbmColor);
  459. DestroyIcon(hIcon2);
  460. GetIconInfo(hIcon1, &IconInfo1);
  461. } else {
  462. hIcon1 = hIcon2;
  463. }
  464. hOldDst = SelectObject(hDCDst, IconInfo1.hbmMask);
  465. }
  466. }
  467. }
  468. if (hOldDst) {
  469. SelectObject(hDCDst, hOldDst);
  470. }
  471. //
  472. // Create New Icon
  473. //
  474. if (hIcon1) {
  475. hIconMerge = CreateIconIndirect(&IconInfo1);
  476. #if DBG_SAVE_ICON_BMP
  477. SaveBmpToFile(IconInfo1.hbmMask, (LPVOID)"FinalMsk", SBTF_NAME);
  478. SaveBmpToFile(IconInfo1.hbmColor, (LPVOID)"FinalClr", SBTF_NAME);
  479. SaveIconToFile(hIconMerge, 0);
  480. #endif
  481. //
  482. // Now Delete what we created
  483. //
  484. DeleteObject(IconInfo1.hbmMask);
  485. DeleteObject(IconInfo1.hbmColor);
  486. DestroyIcon(hIcon1);
  487. } else {
  488. hIconMerge = NULL;
  489. }
  490. DeleteDC(hDCDst);
  491. ReleaseDC(NULL, hDCScreen);
  492. return(hIconMerge);
  493. }
  494. DWORD
  495. GethIconChecksum(
  496. HICON hIcon
  497. )
  498. /*++
  499. Routine Description:
  500. Arguments:
  501. Return Value:
  502. Author:
  503. 15-Aug-1995 Tue 13:27:34 created -by- Daniel Chou (danielc)
  504. Revision History:
  505. --*/
  506. {
  507. ICONINFO IconInfo;
  508. HBITMAP *phBitmap;
  509. UINT chBitmap;
  510. DWORD Checksum = 0xFFFFFFFF;
  511. memset(&IconInfo, 0, sizeof(IconInfo));
  512. if (GetIconInfo(hIcon, &IconInfo)) {
  513. phBitmap = &(IconInfo.hbmMask);
  514. Checksum = 0xDC00DCFF;
  515. chBitmap = 2;
  516. while (chBitmap--) {
  517. LPDWORD pdw;
  518. LPBYTE pAllocMem;
  519. BITMAP BmpInfo;
  520. DWORD Count;
  521. GetObject(*phBitmap, sizeof(BITMAP), &BmpInfo);
  522. CPSUIDBG(DBG_ICONCHKSUM, ("hBitmap=%ld x %ld, Plane=%ld, bpp=%ld",
  523. BmpInfo.bmWidth, BmpInfo.bmHeight,
  524. BmpInfo.bmPlanes, BmpInfo.bmBitsPixel));
  525. pdw = (LPDWORD)&BmpInfo;
  526. Count = (DWORD)(sizeof(BITMAP) >> 2);
  527. while (Count--) {
  528. Checksum += *pdw++;
  529. }
  530. Count = (DWORD)(BmpInfo.bmWidthBytes * BmpInfo.bmHeight);
  531. if (pAllocMem = (LPBYTE)LocalAlloc(LPTR, Count)) {
  532. CPSUIDBG(DBG_ICONCHKSUM, ("hBitmap: Alloc(pBitmap)=%ld bytes", Count));
  533. pdw = (LPDWORD)pAllocMem;
  534. if (Count = (DWORD)GetBitmapBits(*phBitmap, Count, pAllocMem)) {
  535. Count >>= 2;
  536. while (Count--) {
  537. Checksum += *pdw++;
  538. }
  539. }
  540. LocalFree((HLOCAL)pAllocMem);
  541. }
  542. phBitmap++;
  543. }
  544. if (!HIWORD(Checksum)) {
  545. Checksum = MAKELONG(Checksum, 0xFFFF);
  546. }
  547. CPSUIDBG(DBG_ICONCHKSUM, ("GethIconChecksum(%08lx)=%08lx", hIcon, Checksum));
  548. } else {
  549. CPSUIERR(("GethIconChecksum(%08lx): Passed invalid hIcon", hIcon));
  550. }
  551. if (IconInfo.hbmMask)
  552. {
  553. DeleteObject(IconInfo.hbmMask);
  554. }
  555. if (IconInfo.hbmColor)
  556. {
  557. DeleteObject(IconInfo.hbmColor);
  558. }
  559. return(Checksum);
  560. }
  561. HICON
  562. CreateTVIcon(
  563. PTVWND pTVWnd,
  564. HICON hIcon,
  565. UINT IconYOff
  566. )
  567. /*++
  568. Routine Description:
  569. Arguments:
  570. Return Value:
  571. Author:
  572. 15-Aug-1995 Tue 13:27:34 created -by- Daniel Chou (danielc)
  573. Revision History:
  574. --*/
  575. {
  576. HICON hIconNew = NULL;
  577. HDC hDCScr;
  578. HDC hDCSrc;
  579. HDC hDCDst;
  580. HBITMAP hOldSrc;
  581. HBITMAP hOldDst;
  582. ICONINFO IconInfo;
  583. ICONINFO IconNew;
  584. BITMAP BmpInfo;
  585. UINT cyImage;
  586. hDCScr = GetDC(NULL);
  587. if (hDCScr)
  588. {
  589. hDCSrc = CreateCompatibleDC(hDCScr);
  590. hDCDst = CreateCompatibleDC(hDCScr);
  591. ReleaseDC(NULL, hDCScr);
  592. if (hDCSrc && hDCDst)
  593. {
  594. cyImage = (UINT)pTVWnd->cyImage;
  595. if (!IconYOff) {
  596. IconYOff = (UINT)((cyImage - CYICON) >> 1);
  597. }
  598. GetIconInfo(hIcon, &IconInfo);
  599. GetObject(IconInfo.hbmMask, sizeof(BITMAP), &BmpInfo);
  600. CPSUIDBG(DBG_CYICON | DBG_CTVICON, ("Mask=%ld x %ld, Plane=%ld, bpp=%ld",
  601. BmpInfo.bmWidth, BmpInfo.bmHeight,
  602. BmpInfo.bmPlanes, BmpInfo.bmBitsPixel));
  603. IconNew.fIcon = TRUE;
  604. IconNew.xHotspot = IconInfo.xHotspot + 1;
  605. IconNew.yHotspot = IconInfo.yHotspot + 1;
  606. IconNew.hbmMask = CreateBitmap(CXIMAGE,
  607. cyImage,
  608. BmpInfo.bmPlanes,
  609. BmpInfo.bmBitsPixel,
  610. NULL);
  611. GetObject(IconInfo.hbmColor, sizeof(BITMAP), &BmpInfo);
  612. CPSUIDBG(DBG_CTVICON, ("Color=%ld x %ld, Plane=%ld, bpp=%ld",
  613. BmpInfo.bmWidth, BmpInfo.bmHeight,
  614. BmpInfo.bmPlanes, BmpInfo.bmBitsPixel));
  615. IconNew.hbmColor = CreateBitmap(CXIMAGE,
  616. cyImage,
  617. BmpInfo.bmPlanes,
  618. BmpInfo.bmBitsPixel,
  619. NULL);
  620. SetStretchBltMode(hDCDst, BLACKONWHITE);
  621. //
  622. // Stretch the Mask bitmap
  623. //
  624. hOldSrc = SelectObject(hDCSrc, IconInfo.hbmMask);
  625. hOldDst = SelectObject(hDCDst, IconNew.hbmMask);
  626. CPSUIDBG(DBG_CYICON, ("bm=%ldx%ld, cyImage=%ld, IconYOff=%ld",
  627. BmpInfo.bmWidth, BmpInfo.bmHeight, cyImage, IconYOff));
  628. BitBlt(hDCDst, 0, 0, CXIMAGE, cyImage, NULL, 0, 0, WHITENESS);
  629. StretchBlt(hDCDst,
  630. ICON_X_OFF,
  631. IconYOff,
  632. CXICON,
  633. CYICON,
  634. hDCSrc,
  635. 0,
  636. 0,
  637. BmpInfo.bmWidth,
  638. BmpInfo.bmHeight,
  639. SRCCOPY);
  640. //
  641. // Stretch the color bitmap
  642. //
  643. SelectObject(hDCSrc, IconInfo.hbmColor);
  644. SelectObject(hDCDst, IconNew.hbmColor);
  645. BitBlt(hDCDst, 0, 0, CXIMAGE, cyImage, NULL, 0, 0, BLACKNESS);
  646. StretchBlt(hDCDst,
  647. ICON_X_OFF,
  648. IconYOff,
  649. CXICON,
  650. CYICON,
  651. hDCSrc,
  652. 0,
  653. 0,
  654. BmpInfo.bmWidth,
  655. BmpInfo.bmHeight,
  656. SRCCOPY);
  657. //
  658. // Deleselect everything from the DC
  659. //
  660. SelectObject(hDCSrc, hOldSrc);
  661. SelectObject(hDCDst, hOldDst);
  662. //
  663. // Create New Icon
  664. //
  665. hIconNew = CreateIconIndirect(&IconNew);
  666. //
  667. // Now Delete what we created
  668. //
  669. DeleteObject(IconInfo.hbmMask);
  670. DeleteObject(IconInfo.hbmColor);
  671. DeleteObject(IconNew.hbmMask);
  672. DeleteObject(IconNew.hbmColor);
  673. }
  674. if (hDCSrc)
  675. {
  676. DeleteDC(hDCSrc);
  677. }
  678. if (hDCDst)
  679. {
  680. DeleteDC(hDCDst);
  681. }
  682. }
  683. return(hIconNew);
  684. }
  685. HICON
  686. SetIcon(
  687. HINSTANCE hInst,
  688. HWND hCtrl,
  689. ULONG_PTR IconResID,
  690. DWORD IntIconID,
  691. UINT cxcyIcon
  692. )
  693. /*++
  694. Routine Description:
  695. This function set the large icon on the bottom of the treeview change
  696. window
  697. Arguments:
  698. hInst - Handle to the instance which load the IconResID
  699. hCtrl - Handle to the Icon control window to set the icon
  700. IconResID - Caller's IconResID, it the high word is not zero then it
  701. it assume it is a Icon handle, and if high word is 0xffff
  702. then it assume the low word is the icon handle
  703. IntIconID - LOWORD(IntIconID) = compstui Internal icon ID to be used if
  704. the IconResID is not available
  705. HIWORD(IntIconID) = compstui Internal icon ID to be use to
  706. overlay on top of the IconResID
  707. cxcyIcon - Icon cx, cy size
  708. Return Value:
  709. HICON handle to the icon which set to the bottom of the change window
  710. Author:
  711. 01-Aug-1995 Tue 11:12:13 created -by- Daniel Chou (danielc)
  712. 05-Oct-1995 Thu 13:53:21 updated -by- Daniel Chou (danielc)
  713. Updated to accomdate the 32-bit icon handle
  714. 11-Oct-1995 Wed 19:45:23 updated -by- Daniel Chou (danielc)
  715. Make it generic icon setter
  716. Revision History:
  717. --*/
  718. {
  719. HICON hIcon;
  720. HICON hIconOld;
  721. CPSUIINT(("SetIcon: IconResID=%08lx, IntIconID=%u:%u, cyxyIcon=%u",
  722. IconResID, LOWORD(IntIconID), HIWORD(IntIconID), cxcyIcon));
  723. hIcon = MergeIcon(hInst, IconResID, IntIconID, cxcyIcon, cxcyIcon);
  724. if (hIconOld = (HICON)SendMessage(hCtrl,
  725. STM_SETIMAGE,
  726. (WPARAM)IMAGE_ICON,
  727. (LPARAM)hIcon)) {
  728. DestroyIcon(hIconOld);
  729. }
  730. CPSUIDBG(DBG_SETTVICON, ("hIcon=%08lx, hIconOld=%08lx", hIcon, hIconOld));
  731. return(hIcon);
  732. }
  733. LONG
  734. CreateImageList(
  735. HWND hDlg,
  736. PTVWND pTVWnd
  737. )
  738. /*++
  739. Routine Description:
  740. Arguments:
  741. Return Value:
  742. Author:
  743. 06-Jul-1995 Thu 17:34:14 created -by- Daniel Chou (danielc)
  744. Revision History:
  745. --*/
  746. {
  747. HDC hDC;
  748. TEXTMETRIC tm;
  749. UINT cyImage;
  750. UINT uFlags;
  751. if (pTVWnd->himi) {
  752. return(0);
  753. }
  754. if (hDC = GetWindowDC(hDlg)) {
  755. GetTextMetrics(hDC, &tm);
  756. ReleaseDC(hDlg, hDC);
  757. cyImage = (UINT)((tm.tmHeight >= 18) ? 20 : 18);
  758. CPSUIDBG(DBG_CREATEIL,
  759. ("CreateImageList: cyFont =%ld, cyImage=%ld",
  760. tm.tmHeight, cyImage));
  761. } else {
  762. cyImage = 20;
  763. CPSUIDBG(DBG_CREATEIL,
  764. ("CreateImageList: GetWindowDC Failed, use cyImage=20"));
  765. }
  766. pTVWnd->cyImage = (BYTE)cyImage;
  767. #if 0
  768. if (!pTVWnd->hbrGray) {
  769. pTVWnd->hbmGray = CreateBitmap(bmiGray.bmh.biWidth,
  770. bmiGray.bmh.biHeight,
  771. bmiGray.bmh.biBitCount,
  772. bmiGray.bmh.biPlanes,
  773. (LPBYTE)bmiGray.Bits);
  774. pTVWnd->hbrGray = CreatePatternBrush(pTVWnd->hbmGray);
  775. }
  776. #endif
  777. uFlags = ILC_COLOR4 | ILC_MASK;
  778. if (GetWindowLongPtr(hDlg, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) {
  779. //
  780. // If the layout is right-to-left(RTL), we create the image list
  781. // by setting ILC_MIRROR, so the actual images will be the same
  782. // as US build
  783. //
  784. uFlags |= ILC_MIRROR;
  785. }
  786. if (pTVWnd->himi = ImageList_Create(CXIMAGE,
  787. cyImage,
  788. uFlags,
  789. COUNT_GROW_IMAGES,
  790. COUNT_GROW_IMAGES)) {
  791. GetIcon16Idx(pTVWnd, hInstDLL, IDI_CPSUI_EMPTY, IDI_CPSUI_EMPTY);
  792. pTVWnd->yLinesOff = (cyImage == 20) ? 0 : 1;
  793. return(0);
  794. } else {
  795. CPSUIERR(("\n!! AddOptionIcon16() FAILED !!\n"));
  796. CPSUIERR(("Count=%ld, pTVWnd->himi=%08lx",
  797. COUNT_GROW_IMAGES, pTVWnd->himi));
  798. return(ERR_CPSUI_CREATE_IMAGELIST_FAILED);
  799. }
  800. }
  801. WORD
  802. GetIcon16Idx(
  803. PTVWND pTVWnd,
  804. HINSTANCE hInst,
  805. ULONG_PTR IconResID,
  806. DWORD IntIconID
  807. )
  808. /*++
  809. Routine Description:
  810. This function return a WORD index of Imagelist which the icon should be
  811. used in the treeview
  812. Arguments:
  813. pTVWnd - Our instance handle
  814. hInst - The instance handle for the IconResID
  815. IconResID - Caller's IconResID, it the high word is not zero then it
  816. it assume it is a Icon handle, and if high word is 0xffff
  817. then it assume the low word is the icon handle
  818. IntIconID - compstui Internal icon ID to be used if the IconResID is
  819. not available
  820. Return Value:
  821. WORD, index to the image list, 0xFFFF if failed
  822. Author:
  823. 06-Jul-1995 Thu 17:49:06 created -by- Daniel Chou (danielc)
  824. Revision History:
  825. 01-Jul-1996 Mon 13:27:25 updated -by- Daniel Chou (danielc)
  826. Fix bug that we will first only search the IconResID and if not found
  827. then we try to find the IntIconID
  828. --*/
  829. {
  830. HICON hIconTV;
  831. HICON hIconToDestroy = NULL;
  832. HICON hIcon;
  833. LPDWORD pIcon16ID;
  834. LONG IntIconIdx = -1;
  835. DWORD IconID;
  836. DWORD IconChksum;
  837. WORD Index;
  838. WORD AddIdx;
  839. //
  840. // Find out if we have this 16x16 icon added already
  841. //
  842. if (VALID_PTR(IconResID)) {
  843. hIcon = GET_HICON(IconResID);
  844. IntIconID = 0;
  845. IconChksum = GethIconChecksum(hIcon);
  846. CPSUIDBG(DBG_GETICON16IDX,
  847. ("GetIcon16Index: User hIcon=%08lx, Chksum=%08lx",
  848. hIcon, IconChksum));
  849. } else {
  850. #if DO_IN_PLACE
  851. if ((IconResID == IDI_CPSUI_GENERIC_OPTION) ||
  852. (IconResID == IDI_CPSUI_GENERIC_ITEM)) {
  853. IconResID = IDI_CPSUI_EMPTY;
  854. }
  855. #endif
  856. hIcon = NULL;
  857. IconChksum = LODWORD(IconResID);
  858. }
  859. if (pIcon16ID = pTVWnd->pIcon16ID) {
  860. LPDWORD pIcon16IDEnd = pIcon16ID + pTVWnd->Icon16Added;
  861. //
  862. // Try to find the IconChksum first, and remember the IntIconID
  863. //
  864. while (pIcon16ID < pIcon16IDEnd) {
  865. if (IconID = *pIcon16ID++) {
  866. if ((IconID == IconChksum) || (IconID == IntIconID)) {
  867. Index = (WORD)(pIcon16ID - pTVWnd->pIcon16ID - 1);
  868. if (IconID == IconChksum) {
  869. //
  870. // Find the wanted IconChksum, return it now
  871. //
  872. CPSUIDBG(DBG_GETICON16IDX,
  873. ("GetIcon16Idx: hIcon=%08lx IconChksum=%08lx already exists in Index=%ld",
  874. hIcon, IconID, Index));
  875. return(Index);
  876. } else {
  877. //
  878. // We found the IntIconID now, save it for later if we
  879. // cannot find the IconChksum
  880. //
  881. IntIconIdx = (LONG)Index;
  882. }
  883. }
  884. }
  885. }
  886. }
  887. if (hIcon) {
  888. IconID = IconChksum;
  889. } else {
  890. if (!hInst) {
  891. hInst = pTVWnd->hInstCaller;
  892. }
  893. if (IconID = IconChksum) {
  894. hIcon = GETICON16(hInst, IconID);
  895. }
  896. if ((!hIcon) && (IconID = IntIconID)) {
  897. //
  898. // If we cannot load the IconChksum, and we have IntIconID plus the
  899. // IntIconIdx then return it now
  900. //
  901. if (IntIconIdx != -1) {
  902. CPSUIDBG(DBG_GETICON16IDX,
  903. ("GetIcon16Idx: hIcon=%08lx IconIntID=%08lx exists in Index=%ld",
  904. hIcon, IntIconID, IntIconIdx));
  905. return((WORD)IntIconIdx);
  906. }
  907. #if DO_IN_PLACE
  908. if ((IconID == IDI_CPSUI_GENERIC_OPTION) ||
  909. (IconID == IDI_CPSUI_GENERIC_ITEM)) {
  910. IconID = IDI_CPSUI_EMPTY;
  911. }
  912. #endif
  913. hIcon = GETICON16(hInst, IconID);
  914. }
  915. if (!hIcon) {
  916. CPSUIDBG(DBG_GETICON16IDX, ("GETICON16(%ld) FALIED", (DWORD)IconID));
  917. return(ICONIDX_NONE);
  918. }
  919. hIconToDestroy = hIcon;
  920. }
  921. //
  922. // Now Create TV Icon and added to the end of the list
  923. //
  924. if (hIconTV = CreateTVIcon(pTVWnd, hIcon, (pIcon16ID) ? 0 : 2)) {
  925. Index = (WORD)pTVWnd->Icon16Added;
  926. AddIdx = (WORD)ImageList_AddIcon(pTVWnd->himi, hIconTV);
  927. CPSUIDBG(DBG_FIRST_ICON,
  928. ("Add Icon Index=%ld, Add=%ld, ResID=%ld, IntID=%ld",
  929. Index, AddIdx, IconResID, IntIconID));
  930. CPSUIASSERT(0, "ImageList_AddIcon: Index mismatch (%ld)",
  931. Index == AddIdx, Index);
  932. if (AddIdx != 0xFFFF) {
  933. if (Index >= pTVWnd->Icon16Count) {
  934. LPDWORD pdwNew;
  935. DWORD OldSize;
  936. DWORD NewSize;
  937. //
  938. // The thing got full, let's realloc the memory object to
  939. // be bigger
  940. //
  941. OldSize = (DWORD)(pTVWnd->Icon16Count * sizeof(DWORD));
  942. NewSize = (DWORD)(OldSize +
  943. (COUNT_GROW_IMAGES + 2) * sizeof(DWORD));
  944. if (pdwNew = (LPDWORD)LocalAlloc(LPTR, NewSize)) {
  945. if (pTVWnd->pIcon16ID) {
  946. CopyMemory(pdwNew, pTVWnd->pIcon16ID, OldSize);
  947. LocalFree((HLOCAL)pTVWnd->pIcon16ID);
  948. }
  949. pTVWnd->pIcon16ID = pdwNew;
  950. pTVWnd->Icon16Count += COUNT_GROW_IMAGES;
  951. CPSUIDBG(DBG_REALLOC,
  952. ("LocalAlloc(%ld): pNew=%08lx", NewSize, pdwNew));
  953. } else {
  954. CPSUIERR(("ImageList_AddIcon: LocalReAlloc(%ld) FAILED",
  955. NewSize));
  956. }
  957. }
  958. *(pTVWnd->pIcon16ID + Index) = IconID;
  959. pTVWnd->Icon16Added++;
  960. CPSUIDBG(DBG_GETICON16IDX,
  961. ("Add Icon16: IconID=%ld, IconChksum=%ld, Index=%ld",
  962. (DWORD)IconID, (DWORD)IconChksum, (DWORD)Index));
  963. } else {
  964. Index = ICONIDX_NONE;
  965. CPSUIERR(("ImageList_AddIcon FAILED"));
  966. }
  967. //
  968. // Do not needed any more delete it
  969. //
  970. DestroyIcon(hIconTV);
  971. } else {
  972. Index = ICONIDX_NONE;
  973. CPSUIERR(("CreateTVIcon() FAILED"));
  974. }
  975. if (hIconToDestroy) {
  976. DestroyIcon(hIconToDestroy);
  977. }
  978. return(Index);
  979. }