Leaked source code of windows server 2003
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.

1111 lines
26 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. extern HINSTANCE hInstDLL;
  30. extern OPTTYPE OptTypeNone;
  31. HICON
  32. MergeIcon(
  33. HINSTANCE hInst,
  34. ULONG_PTR IconResID,
  35. DWORD IntIconID,
  36. UINT cxIcon,
  37. UINT cyIcon
  38. )
  39. /*++
  40. Routine Description:
  41. This function load the IconResID and stretch it to the cxIcon/cyIcon size
  42. and optional merge the HIWORD(IntIconID) (32x32) in the position of
  43. IconRes1D's (0, 0)
  44. Arguments:
  45. hInst - Instance handle for the IconResID
  46. IconResID - Icon ID for the first Icon
  47. IntIconID - LOWORD(IntIconID) = the internal icon id if IconID is not
  48. avaliable
  49. HIWORD(IntIconID) = MIM_xxxx merge icon mode ID
  50. cxIcon - cx size of the icon want to create
  51. cyIcon - cy size of the icon want to create
  52. Return Value:
  53. HICON, the newly created and/or merged icon handle, NULL if failed, the
  54. caller must do DestroyIcon() after using it if it is not NULL.
  55. Author:
  56. 15-Aug-1995 Tue 13:27:34 created -by- Daniel Chou (danielc)
  57. Revision History:
  58. --*/
  59. {
  60. HICON hIcon1;
  61. HICON hIcon2;
  62. HICON hIconMerge;
  63. HICON hIcon1Caller;
  64. HDC hDCScreen;
  65. HDC hDCDst;
  66. HGDIOBJ hOldDst = NULL;
  67. BITMAP Bitmap;
  68. WORD MergeIconMode;
  69. WORD IconID;
  70. WORD IconIDSet[MIM_MAX_OVERLAY + 2];
  71. UINT IdxIconID;
  72. ICONINFO IconInfo1;
  73. hIcon1Caller = NULL;
  74. if (VALID_PTR(IconResID)) {
  75. if ((hIcon1 = GET_HICON(IconResID)) &&
  76. (GetIconInfo(hIcon1, &IconInfo1))) {
  77. hIcon1Caller = hIcon1;
  78. IconID = 0xFFFF;
  79. IconResID = 0xFFFF;
  80. } else {
  81. CPSUIERR(("MergeIcon: Passed Invalid hIcon=%08lx,", hIcon1));
  82. hIcon1 = NULL;
  83. }
  84. } else {
  85. hIcon1 = NULL;
  86. }
  87. if (!hIcon1) {
  88. IconIDSet[0] = GET_INTICONID(IntIconID);
  89. IconIDSet[1] = LOWORD(IconResID);
  90. IdxIconID = 2;
  91. while ((!hIcon1) && (IdxIconID--)) {
  92. if (IconID = IconIDSet[IdxIconID]) {
  93. hIcon1 = GETICON_SIZE(hInst, IconID, cxIcon, cyIcon);
  94. }
  95. }
  96. }
  97. if ((hIcon1) &&
  98. ((hIcon1Caller) || (GetIconInfo(hIcon1, &IconInfo1)))) {
  99. GetObject(IconInfo1.hbmMask, sizeof(BITMAP), &Bitmap);
  100. if ((hIcon1 == hIcon1Caller) ||
  101. (Bitmap.bmWidth != (LONG)cxIcon) ||
  102. (Bitmap.bmHeight != (LONG)cyIcon)) {
  103. CPSUIINT(("MergeIcon: hIcon1=%ld x %ld, Change to %u x %u",
  104. Bitmap.bmWidth, Bitmap.bmHeight, cxIcon, cyIcon));
  105. hIcon1 = CopyImage(hIcon2 = hIcon1, IMAGE_ICON, cxIcon, cyIcon, 0);
  106. //
  107. // Destroy Original Icon only if hIcon1 is not from the caller
  108. //
  109. if (hIcon1Caller != hIcon2) {
  110. DestroyIcon(hIcon2);
  111. }
  112. }
  113. } else {
  114. CPSUIERR(("MergeIcon: FAILED hIcon1=%08lx,", hIcon1));
  115. }
  116. if (!(MergeIconMode = GET_MERGEICONID(IntIconID))) {
  117. //
  118. // Nothing to be merged so just return the hIcon1, we do not need the
  119. // IconInfo1 information, so destroy the object before return
  120. //
  121. if (IconInfo1.hbmMask)
  122. {
  123. DeleteObject(IconInfo1.hbmMask);
  124. }
  125. if (IconInfo1.hbmColor)
  126. {
  127. DeleteObject(IconInfo1.hbmColor);
  128. }
  129. return(hIcon1);
  130. }
  131. IconIDSet[0] = (MergeIconMode & MIM_WARNING_OVERLAY) ?
  132. IDI_CPSUI_WARNING_OVERLAY : 0;
  133. IconIDSet[1] = (MergeIconMode & MIM_NO_OVERLAY) ? IDI_CPSUI_NO : 0;
  134. IconIDSet[2] = (MergeIconMode & MIM_STOP_OVERLAY) ? IDI_CPSUI_STOP : 0;
  135. IdxIconID = 3;
  136. //
  137. // Start creating the new icon, the IconInfo1 is the cx/cy Icon size
  138. // padded in and the IconInfo2 is the standard 32x32 icon
  139. //
  140. hDCDst = CreateCompatibleDC(hDCScreen = GetDC(NULL));
  141. if (hIcon1) {
  142. hOldDst = SelectObject(hDCDst, IconInfo1.hbmMask);
  143. }
  144. SetStretchBltMode(hDCDst, BLACKONWHITE);
  145. while (IdxIconID--) {
  146. if ((IconID = IconIDSet[IdxIconID]) &&
  147. (hIcon2 = GETICON_SIZE(hInst, IconID, cxIcon, cyIcon))) {
  148. if (hIcon1) {
  149. HDC hDCSrc;
  150. HGDIOBJ hOldSrc;
  151. ICONINFO IconInfo2;
  152. hDCSrc = CreateCompatibleDC(hDCScreen);
  153. GetIconInfo(hIcon2, &IconInfo2);
  154. hOldSrc = SelectObject(hDCSrc, IconInfo2.hbmMask);
  155. SelectObject(hDCDst, IconInfo1.hbmMask);
  156. StretchBlt(hDCDst,
  157. 0,
  158. 0,
  159. cxIcon,
  160. cyIcon,
  161. hDCSrc,
  162. 0,
  163. 0,
  164. cxIcon,
  165. cyIcon,
  166. SRCAND);
  167. //
  168. // clear the hIcon1's XOR color to leave room for the hIcon2
  169. //
  170. SelectObject(hDCDst, IconInfo1.hbmColor);
  171. StretchBlt(hDCDst,
  172. 0,
  173. 0,
  174. cxIcon,
  175. cyIcon,
  176. hDCSrc,
  177. 0,
  178. 0,
  179. cxIcon,
  180. cyIcon,
  181. SRCAND);
  182. //
  183. // Now add in the hIcon2's XOR color to the the hIcon1
  184. //
  185. SelectObject(hDCSrc, IconInfo2.hbmColor);
  186. StretchBlt(hDCDst,
  187. 0,
  188. 0,
  189. cxIcon,
  190. cyIcon,
  191. hDCSrc,
  192. 0,
  193. 0,
  194. cxIcon,
  195. cyIcon,
  196. SRCPAINT);
  197. //
  198. // de-select everything from the DC before the create/delete
  199. //
  200. SelectObject(hDCSrc, hOldSrc);
  201. DeleteDC(hDCSrc);
  202. DeleteObject(IconInfo2.hbmMask);
  203. DeleteObject(IconInfo2.hbmColor);
  204. DestroyIcon(hIcon2);
  205. } else {
  206. GetIconInfo(hIcon2, &IconInfo1);
  207. GetObject(IconInfo1.hbmMask, sizeof(BITMAP), &Bitmap);
  208. if ((Bitmap.bmWidth != (LONG)cxIcon) ||
  209. (Bitmap.bmHeight != (LONG)cyIcon)) {
  210. CPSUIINT(("MergeIcon: hIcon1=%ld x %ld, Change to %u x %u",
  211. Bitmap.bmWidth, Bitmap.bmHeight, cxIcon, cyIcon));
  212. hIcon1 = CopyImage(hIcon2, IMAGE_ICON, cxIcon, cyIcon, 0);
  213. DeleteObject(IconInfo1.hbmMask);
  214. DeleteObject(IconInfo1.hbmColor);
  215. DestroyIcon(hIcon2);
  216. GetIconInfo(hIcon1, &IconInfo1);
  217. } else {
  218. hIcon1 = hIcon2;
  219. }
  220. hOldDst = SelectObject(hDCDst, IconInfo1.hbmMask);
  221. }
  222. }
  223. }
  224. if (hOldDst) {
  225. SelectObject(hDCDst, hOldDst);
  226. }
  227. //
  228. // Create New Icon
  229. //
  230. if (hIcon1) {
  231. hIconMerge = CreateIconIndirect(&IconInfo1);
  232. //
  233. // Now Delete what we created
  234. //
  235. DeleteObject(IconInfo1.hbmMask);
  236. DeleteObject(IconInfo1.hbmColor);
  237. DestroyIcon(hIcon1);
  238. } else {
  239. hIconMerge = NULL;
  240. }
  241. DeleteDC(hDCDst);
  242. ReleaseDC(NULL, hDCScreen);
  243. return(hIconMerge);
  244. }
  245. DWORD
  246. GethIconChecksum(
  247. HICON hIcon
  248. )
  249. /*++
  250. Routine Description:
  251. Arguments:
  252. Return Value:
  253. Author:
  254. 15-Aug-1995 Tue 13:27:34 created -by- Daniel Chou (danielc)
  255. Revision History:
  256. --*/
  257. {
  258. ICONINFO IconInfo;
  259. HBITMAP *phBitmap;
  260. UINT chBitmap;
  261. DWORD Checksum = 0xFFFFFFFF;
  262. memset(&IconInfo, 0, sizeof(IconInfo));
  263. if (GetIconInfo(hIcon, &IconInfo)) {
  264. phBitmap = &(IconInfo.hbmMask);
  265. Checksum = 0xDC00DCFF;
  266. chBitmap = 2;
  267. while (chBitmap--) {
  268. LPDWORD pdw;
  269. LPBYTE pAllocMem;
  270. BITMAP BmpInfo;
  271. DWORD Count;
  272. GetObject(*phBitmap, sizeof(BITMAP), &BmpInfo);
  273. CPSUIDBG(DBG_ICONCHKSUM, ("hBitmap=%ld x %ld, Plane=%ld, bpp=%ld",
  274. BmpInfo.bmWidth, BmpInfo.bmHeight,
  275. BmpInfo.bmPlanes, BmpInfo.bmBitsPixel));
  276. pdw = (LPDWORD)&BmpInfo;
  277. Count = (DWORD)(sizeof(BITMAP) >> 2);
  278. while (Count--) {
  279. Checksum += *pdw++;
  280. }
  281. Count = (DWORD)(BmpInfo.bmWidthBytes * BmpInfo.bmHeight);
  282. if (pAllocMem = (LPBYTE)LocalAlloc(LPTR, Count)) {
  283. CPSUIDBG(DBG_ICONCHKSUM, ("hBitmap: Alloc(pBitmap)=%ld bytes", Count));
  284. pdw = (LPDWORD)pAllocMem;
  285. if (Count = (DWORD)GetBitmapBits(*phBitmap, Count, pAllocMem)) {
  286. Count >>= 2;
  287. while (Count--) {
  288. Checksum += *pdw++;
  289. }
  290. }
  291. LocalFree((HLOCAL)pAllocMem);
  292. }
  293. phBitmap++;
  294. }
  295. if (!HIWORD(Checksum)) {
  296. Checksum = MAKELONG(Checksum, 0xFFFF);
  297. }
  298. CPSUIDBG(DBG_ICONCHKSUM, ("GethIconChecksum(%08lx)=%08lx", hIcon, Checksum));
  299. } else {
  300. CPSUIERR(("GethIconChecksum(%08lx): Passed invalid hIcon", hIcon));
  301. }
  302. if (IconInfo.hbmMask)
  303. {
  304. DeleteObject(IconInfo.hbmMask);
  305. }
  306. if (IconInfo.hbmColor)
  307. {
  308. DeleteObject(IconInfo.hbmColor);
  309. }
  310. return(Checksum);
  311. }
  312. HICON
  313. CreateTVIcon(
  314. PTVWND pTVWnd,
  315. HICON hIcon,
  316. UINT IconYOff
  317. )
  318. /*++
  319. Routine Description:
  320. Arguments:
  321. Return Value:
  322. Author:
  323. 15-Aug-1995 Tue 13:27:34 created -by- Daniel Chou (danielc)
  324. Revision History:
  325. --*/
  326. {
  327. HICON hIconNew = NULL;
  328. HDC hDCScr;
  329. HDC hDCSrc;
  330. HDC hDCDst;
  331. HBITMAP hOldSrc;
  332. HBITMAP hOldDst;
  333. ICONINFO IconInfo;
  334. ICONINFO IconNew;
  335. BITMAP BmpInfo;
  336. UINT cyImage;
  337. hDCScr = GetDC(NULL);
  338. if (hDCScr)
  339. {
  340. hDCSrc = CreateCompatibleDC(hDCScr);
  341. hDCDst = CreateCompatibleDC(hDCScr);
  342. ReleaseDC(NULL, hDCScr);
  343. if (hDCSrc && hDCDst)
  344. {
  345. cyImage = (UINT)pTVWnd->cyImage;
  346. if (!IconYOff) {
  347. IconYOff = (UINT)((cyImage - CYICON) >> 1);
  348. }
  349. GetIconInfo(hIcon, &IconInfo);
  350. GetObject(IconInfo.hbmMask, sizeof(BITMAP), &BmpInfo);
  351. CPSUIDBG(DBG_CYICON | DBG_CTVICON, ("Mask=%ld x %ld, Plane=%ld, bpp=%ld",
  352. BmpInfo.bmWidth, BmpInfo.bmHeight,
  353. BmpInfo.bmPlanes, BmpInfo.bmBitsPixel));
  354. IconNew.fIcon = TRUE;
  355. IconNew.xHotspot = IconInfo.xHotspot + 1;
  356. IconNew.yHotspot = IconInfo.yHotspot + 1;
  357. IconNew.hbmMask = CreateBitmap(CXIMAGE,
  358. cyImage,
  359. BmpInfo.bmPlanes,
  360. BmpInfo.bmBitsPixel,
  361. NULL);
  362. GetObject(IconInfo.hbmColor, sizeof(BITMAP), &BmpInfo);
  363. CPSUIDBG(DBG_CTVICON, ("Color=%ld x %ld, Plane=%ld, bpp=%ld",
  364. BmpInfo.bmWidth, BmpInfo.bmHeight,
  365. BmpInfo.bmPlanes, BmpInfo.bmBitsPixel));
  366. IconNew.hbmColor = CreateBitmap(CXIMAGE,
  367. cyImage,
  368. BmpInfo.bmPlanes,
  369. BmpInfo.bmBitsPixel,
  370. NULL);
  371. SetStretchBltMode(hDCDst, BLACKONWHITE);
  372. //
  373. // Stretch the Mask bitmap
  374. //
  375. hOldSrc = SelectObject(hDCSrc, IconInfo.hbmMask);
  376. hOldDst = SelectObject(hDCDst, IconNew.hbmMask);
  377. CPSUIDBG(DBG_CYICON, ("bm=%ldx%ld, cyImage=%ld, IconYOff=%ld",
  378. BmpInfo.bmWidth, BmpInfo.bmHeight, cyImage, IconYOff));
  379. BitBlt(hDCDst, 0, 0, CXIMAGE, cyImage, NULL, 0, 0, WHITENESS);
  380. StretchBlt(hDCDst,
  381. ICON_X_OFF,
  382. IconYOff,
  383. CXICON,
  384. CYICON,
  385. hDCSrc,
  386. 0,
  387. 0,
  388. BmpInfo.bmWidth,
  389. BmpInfo.bmHeight,
  390. SRCCOPY);
  391. //
  392. // Stretch the color bitmap
  393. //
  394. SelectObject(hDCSrc, IconInfo.hbmColor);
  395. SelectObject(hDCDst, IconNew.hbmColor);
  396. BitBlt(hDCDst, 0, 0, CXIMAGE, cyImage, NULL, 0, 0, BLACKNESS);
  397. StretchBlt(hDCDst,
  398. ICON_X_OFF,
  399. IconYOff,
  400. CXICON,
  401. CYICON,
  402. hDCSrc,
  403. 0,
  404. 0,
  405. BmpInfo.bmWidth,
  406. BmpInfo.bmHeight,
  407. SRCCOPY);
  408. //
  409. // Deleselect everything from the DC
  410. //
  411. SelectObject(hDCSrc, hOldSrc);
  412. SelectObject(hDCDst, hOldDst);
  413. //
  414. // Create New Icon
  415. //
  416. hIconNew = CreateIconIndirect(&IconNew);
  417. //
  418. // Now Delete what we created
  419. //
  420. DeleteObject(IconInfo.hbmMask);
  421. DeleteObject(IconInfo.hbmColor);
  422. DeleteObject(IconNew.hbmMask);
  423. DeleteObject(IconNew.hbmColor);
  424. }
  425. if (hDCSrc)
  426. {
  427. DeleteDC(hDCSrc);
  428. }
  429. if (hDCDst)
  430. {
  431. DeleteDC(hDCDst);
  432. }
  433. }
  434. return(hIconNew);
  435. }
  436. HICON
  437. SetIcon(
  438. HINSTANCE hInst,
  439. HWND hCtrl,
  440. ULONG_PTR IconResID,
  441. DWORD IntIconID,
  442. UINT cxcyIcon
  443. )
  444. /*++
  445. Routine Description:
  446. This function set the large icon on the bottom of the treeview change
  447. window
  448. Arguments:
  449. hInst - Handle to the instance which load the IconResID
  450. hCtrl - Handle to the Icon control window to set the icon
  451. IconResID - Caller's IconResID, it the high word is not zero then it
  452. it assume it is a Icon handle, and if high word is 0xffff
  453. then it assume the low word is the icon handle
  454. IntIconID - LOWORD(IntIconID) = compstui Internal icon ID to be used if
  455. the IconResID is not available
  456. HIWORD(IntIconID) = compstui Internal icon ID to be use to
  457. overlay on top of the IconResID
  458. cxcyIcon - Icon cx, cy size
  459. Return Value:
  460. HICON handle to the icon which set to the bottom of the change window
  461. Author:
  462. 01-Aug-1995 Tue 11:12:13 created -by- Daniel Chou (danielc)
  463. 05-Oct-1995 Thu 13:53:21 updated -by- Daniel Chou (danielc)
  464. Updated to accomdate the 32-bit icon handle
  465. 11-Oct-1995 Wed 19:45:23 updated -by- Daniel Chou (danielc)
  466. Make it generic icon setter
  467. Revision History:
  468. --*/
  469. {
  470. HICON hIcon;
  471. HICON hIconOld;
  472. CPSUIINT(("SetIcon: IconResID=%08lx, IntIconID=%u:%u, cyxyIcon=%u",
  473. IconResID, LOWORD(IntIconID), HIWORD(IntIconID), cxcyIcon));
  474. hIcon = MergeIcon(hInst, IconResID, IntIconID, cxcyIcon, cxcyIcon);
  475. if (hIconOld = (HICON)SendMessage(hCtrl,
  476. STM_SETIMAGE,
  477. (WPARAM)IMAGE_ICON,
  478. (LPARAM)hIcon)) {
  479. DestroyIcon(hIconOld);
  480. }
  481. CPSUIDBG(DBG_SETTVICON, ("hIcon=%08lx, hIconOld=%08lx", hIcon, hIconOld));
  482. return(hIcon);
  483. }
  484. LONG
  485. CreateImageList(
  486. HWND hDlg,
  487. PTVWND pTVWnd
  488. )
  489. /*++
  490. Routine Description:
  491. Arguments:
  492. Return Value:
  493. Author:
  494. 06-Jul-1995 Thu 17:34:14 created -by- Daniel Chou (danielc)
  495. Revision History:
  496. --*/
  497. {
  498. HDC hDC;
  499. TEXTMETRIC tm;
  500. UINT cyImage;
  501. UINT uFlags;
  502. if (pTVWnd->himi) {
  503. return(0);
  504. }
  505. if (hDC = GetWindowDC(hDlg)) {
  506. GetTextMetrics(hDC, &tm);
  507. ReleaseDC(hDlg, hDC);
  508. cyImage = (UINT)((tm.tmHeight >= 18) ? 20 : 18);
  509. CPSUIDBG(DBG_CREATEIL,
  510. ("CreateImageList: cyFont =%ld, cyImage=%ld",
  511. tm.tmHeight, cyImage));
  512. } else {
  513. cyImage = 20;
  514. CPSUIDBG(DBG_CREATEIL,
  515. ("CreateImageList: GetWindowDC Failed, use cyImage=20"));
  516. }
  517. pTVWnd->cyImage = (BYTE)cyImage;
  518. uFlags = ILC_COLOR4 | ILC_MASK;
  519. if (GetWindowLongPtr(hDlg, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) {
  520. //
  521. // If the layout is right-to-left(RTL), we create the image list
  522. // by setting ILC_MIRROR, so the actual images will be the same
  523. // as US build
  524. //
  525. uFlags |= ILC_MIRROR;
  526. }
  527. if (pTVWnd->himi = ImageList_Create(CXIMAGE,
  528. cyImage,
  529. uFlags,
  530. COUNT_GROW_IMAGES,
  531. COUNT_GROW_IMAGES)) {
  532. GetIcon16Idx(pTVWnd, hInstDLL, IDI_CPSUI_EMPTY, IDI_CPSUI_EMPTY);
  533. pTVWnd->yLinesOff = (cyImage == 20) ? 0 : 1;
  534. return(0);
  535. } else {
  536. CPSUIERR(("\n!! AddOptionIcon16() FAILED !!\n"));
  537. CPSUIERR(("Count=%ld, pTVWnd->himi=%08lx",
  538. COUNT_GROW_IMAGES, pTVWnd->himi));
  539. return(ERR_CPSUI_CREATE_IMAGELIST_FAILED);
  540. }
  541. }
  542. WORD
  543. GetIcon16Idx(
  544. PTVWND pTVWnd,
  545. HINSTANCE hInst,
  546. ULONG_PTR IconResID,
  547. DWORD IntIconID
  548. )
  549. /*++
  550. Routine Description:
  551. This function return a WORD index of Imagelist which the icon should be
  552. used in the treeview
  553. Arguments:
  554. pTVWnd - Our instance handle
  555. hInst - The instance handle for the IconResID
  556. IconResID - Caller's IconResID, it the high word is not zero then it
  557. it assume it is a Icon handle, and if high word is 0xffff
  558. then it assume the low word is the icon handle
  559. IntIconID - compstui Internal icon ID to be used if the IconResID is
  560. not available
  561. Return Value:
  562. WORD, index to the image list, 0xFFFF if failed
  563. Author:
  564. 06-Jul-1995 Thu 17:49:06 created -by- Daniel Chou (danielc)
  565. Revision History:
  566. 01-Jul-1996 Mon 13:27:25 updated -by- Daniel Chou (danielc)
  567. Fix bug that we will first only search the IconResID and if not found
  568. then we try to find the IntIconID
  569. --*/
  570. {
  571. HICON hIconTV;
  572. HICON hIconToDestroy = NULL;
  573. HICON hIcon;
  574. LPDWORD pIcon16ID;
  575. LONG IntIconIdx = -1;
  576. DWORD IconID;
  577. DWORD IconChksum;
  578. WORD Index;
  579. WORD AddIdx;
  580. //
  581. // Find out if we have this 16x16 icon added already
  582. //
  583. if (VALID_PTR(IconResID)) {
  584. hIcon = GET_HICON(IconResID);
  585. IntIconID = 0;
  586. IconChksum = GethIconChecksum(hIcon);
  587. CPSUIDBG(DBG_GETICON16IDX,
  588. ("GetIcon16Index: User hIcon=%08lx, Chksum=%08lx",
  589. hIcon, IconChksum));
  590. } else {
  591. #if DO_IN_PLACE
  592. if ((IconResID == IDI_CPSUI_GENERIC_OPTION) ||
  593. (IconResID == IDI_CPSUI_GENERIC_ITEM)) {
  594. IconResID = IDI_CPSUI_EMPTY;
  595. }
  596. #endif
  597. hIcon = NULL;
  598. IconChksum = LODWORD(IconResID);
  599. }
  600. if (pIcon16ID = pTVWnd->pIcon16ID) {
  601. LPDWORD pIcon16IDEnd = pIcon16ID + pTVWnd->Icon16Added;
  602. //
  603. // Try to find the IconChksum first, and remember the IntIconID
  604. //
  605. while (pIcon16ID < pIcon16IDEnd) {
  606. if (IconID = *pIcon16ID++) {
  607. if ((IconID == IconChksum) || (IconID == IntIconID)) {
  608. Index = (WORD)(pIcon16ID - pTVWnd->pIcon16ID - 1);
  609. if (IconID == IconChksum) {
  610. //
  611. // Find the wanted IconChksum, return it now
  612. //
  613. CPSUIDBG(DBG_GETICON16IDX,
  614. ("GetIcon16Idx: hIcon=%08lx IconChksum=%08lx already exists in Index=%ld",
  615. hIcon, IconID, Index));
  616. return(Index);
  617. } else {
  618. //
  619. // We found the IntIconID now, save it for later if we
  620. // cannot find the IconChksum
  621. //
  622. IntIconIdx = (LONG)Index;
  623. }
  624. }
  625. }
  626. }
  627. }
  628. if (hIcon) {
  629. IconID = IconChksum;
  630. } else {
  631. if (!hInst) {
  632. hInst = pTVWnd->hInstCaller;
  633. }
  634. if (IconID = IconChksum) {
  635. hIcon = GETICON16(hInst, IconID);
  636. }
  637. if ((!hIcon) && (IconID = IntIconID)) {
  638. //
  639. // If we cannot load the IconChksum, and we have IntIconID plus the
  640. // IntIconIdx then return it now
  641. //
  642. if (IntIconIdx != -1) {
  643. CPSUIDBG(DBG_GETICON16IDX,
  644. ("GetIcon16Idx: hIcon=%08lx IconIntID=%08lx exists in Index=%ld",
  645. hIcon, IntIconID, IntIconIdx));
  646. return((WORD)IntIconIdx);
  647. }
  648. #if DO_IN_PLACE
  649. if ((IconID == IDI_CPSUI_GENERIC_OPTION) ||
  650. (IconID == IDI_CPSUI_GENERIC_ITEM)) {
  651. IconID = IDI_CPSUI_EMPTY;
  652. }
  653. #endif
  654. hIcon = GETICON16(hInst, IconID);
  655. }
  656. if (!hIcon) {
  657. CPSUIDBG(DBG_GETICON16IDX, ("GETICON16(%ld) FALIED", (DWORD)IconID));
  658. return(ICONIDX_NONE);
  659. }
  660. hIconToDestroy = hIcon;
  661. }
  662. //
  663. // Now Create TV Icon and added to the end of the list
  664. //
  665. if (hIconTV = CreateTVIcon(pTVWnd, hIcon, (pIcon16ID) ? 0 : 2)) {
  666. Index = (WORD)pTVWnd->Icon16Added;
  667. AddIdx = (WORD)ImageList_AddIcon(pTVWnd->himi, hIconTV);
  668. CPSUIDBG(DBG_FIRST_ICON,
  669. ("Add Icon Index=%ld, Add=%ld, ResID=%ld, IntID=%ld",
  670. Index, AddIdx, IconResID, IntIconID));
  671. CPSUIASSERT(0, "ImageList_AddIcon: Index mismatch (%ld)",
  672. Index == AddIdx, Index);
  673. if (AddIdx != 0xFFFF) {
  674. if (Index >= pTVWnd->Icon16Count) {
  675. LPDWORD pdwNew;
  676. DWORD OldSize;
  677. DWORD NewSize;
  678. //
  679. // The thing got full, let's realloc the memory object to
  680. // be bigger
  681. //
  682. OldSize = (DWORD)(pTVWnd->Icon16Count * sizeof(DWORD));
  683. NewSize = (DWORD)(OldSize +
  684. (COUNT_GROW_IMAGES + 2) * sizeof(DWORD));
  685. if (pdwNew = (LPDWORD)LocalAlloc(LPTR, NewSize)) {
  686. if (pTVWnd->pIcon16ID) {
  687. CopyMemory(pdwNew, pTVWnd->pIcon16ID, OldSize);
  688. LocalFree((HLOCAL)pTVWnd->pIcon16ID);
  689. }
  690. pTVWnd->pIcon16ID = pdwNew;
  691. pTVWnd->Icon16Count += COUNT_GROW_IMAGES;
  692. CPSUIDBG(DBG_REALLOC,
  693. ("LocalAlloc(%ld): pNew=%08lx", NewSize, pdwNew));
  694. } else {
  695. CPSUIERR(("ImageList_AddIcon: LocalReAlloc(%ld) FAILED",
  696. NewSize));
  697. }
  698. }
  699. *(pTVWnd->pIcon16ID + Index) = IconID;
  700. pTVWnd->Icon16Added++;
  701. CPSUIDBG(DBG_GETICON16IDX,
  702. ("Add Icon16: IconID=%ld, IconChksum=%ld, Index=%ld",
  703. (DWORD)IconID, (DWORD)IconChksum, (DWORD)Index));
  704. } else {
  705. Index = ICONIDX_NONE;
  706. CPSUIERR(("ImageList_AddIcon FAILED"));
  707. }
  708. //
  709. // Do not needed any more delete it
  710. //
  711. DestroyIcon(hIconTV);
  712. } else {
  713. Index = ICONIDX_NONE;
  714. CPSUIERR(("CreateTVIcon() FAILED"));
  715. }
  716. if (hIconToDestroy) {
  717. DestroyIcon(hIconToDestroy);
  718. }
  719. return(Index);
  720. }