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.

857 lines
28 KiB

  1. /*
  2. * ICON.C
  3. *
  4. * Implements the OleUIChangeIcon function which invokes the complete
  5. * Change Icon dialog.
  6. *
  7. * Copyright (c)1992 Microsoft Corporation, All Right Reserved
  8. */
  9. #define STRICT 1
  10. #include "ole2ui.h"
  11. #include "common.h"
  12. #include "utility.h"
  13. #include "icon.h"
  14. #include "geticon.h"
  15. /*
  16. * OleUIChangeIcon
  17. *
  18. * Purpose:
  19. * Invokes the standard OLE Change Icon dialog box allowing the user
  20. * to select an icon from an icon file, executable, or DLL.
  21. *
  22. * Parameters:
  23. * lpCI LPOLEUIChangeIcon pointing to the in-out structure
  24. * for this dialog.
  25. *
  26. * Return Value:
  27. * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise
  28. * an error value.
  29. */
  30. STDAPI_(UINT) OleUIChangeIcon(LPOLEUICHANGEICON lpCI)
  31. {
  32. UINT uRet;
  33. HGLOBAL hMemDlg=NULL;
  34. uRet=UStandardValidation((LPOLEUISTANDARD)lpCI, sizeof(OLEUICHANGEICON)
  35. , &hMemDlg);
  36. if (OLEUI_SUCCESS!=uRet)
  37. return uRet;
  38. #if defined( OBSOLETE )
  39. if (NULL==lpCI->hMetaPict)
  40. uRet=OLEUI_CIERR_MUSTHAVECURRENTMETAFILE;
  41. #endif
  42. if (lpCI->dwFlags & CIF_USEICONEXE)
  43. {
  44. if ( (NULL == lpCI->szIconExe)
  45. || (IsBadReadPtr(lpCI->szIconExe, lpCI->cchIconExe))
  46. || (IsBadWritePtr(lpCI->szIconExe, lpCI->cchIconExe)) )
  47. uRet = OLEUI_CIERR_SZICONEXEINVALID;
  48. }
  49. // REVIEW: how do we validate the CLSID?
  50. /*
  51. if ('\0'==*((LPSTR)&lpCI->clsid))
  52. uRet=OLEUI_CIERR_MUSTHAVECLSID;
  53. */
  54. if (OLEUI_ERR_STANDARDMIN <= uRet)
  55. {
  56. if (NULL!=hMemDlg)
  57. FreeResource(hMemDlg);
  58. return uRet;
  59. }
  60. //Now that we've validated everything, we can invoke the dialog.
  61. return UStandardInvocation(ChangeIconDialogProc, (LPOLEUISTANDARD)lpCI
  62. , hMemDlg, MAKEINTRESOURCE(IDD_CHANGEICON));
  63. }
  64. /*
  65. * ChangeIconDialogProc
  66. *
  67. * Purpose:
  68. * Implements the OLE Change Icon dialog as invoked through the
  69. * OleUIChangeIcon function.
  70. *
  71. * Parameters:
  72. * Standard
  73. *
  74. * Return Value:
  75. * Standard
  76. */
  77. BOOL CALLBACK EXPORT ChangeIconDialogProc(HWND hDlg, UINT iMsg
  78. , WPARAM wParam, LPARAM lParam)
  79. {
  80. LPCHANGEICON lpCI;
  81. HICON hIcon;
  82. HGLOBAL hMetaPict;
  83. BOOL fOK=FALSE;
  84. UINT uRet=0;
  85. LPTSTR psz;
  86. TCHAR szTemp[OLEUI_CCHPATHMAX];
  87. //Declare Win16/Win32 compatible WM_COMMAND parameters.
  88. COMMANDPARAMS(wID, wCode, hWndMsg);
  89. lpCI=(LPCHANGEICON)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
  90. //If the hook processed the message, we're done.
  91. if (0!=uRet)
  92. return uRet;
  93. //Process the temination message
  94. if (iMsg==uMsgEndDialog)
  95. {
  96. //Insure that icons are properly destroyed.
  97. SendDlgItemMessage(hDlg, ID_ICONLIST, LB_RESETCONTENT, 0, 0L);
  98. StandardCleanup(lpCI, hDlg);
  99. EndDialog(hDlg, wParam);
  100. return TRUE;
  101. }
  102. switch (iMsg)
  103. {
  104. case WM_INITDIALOG:
  105. FChangeIconInit(hDlg, wParam, lParam);
  106. return TRUE;
  107. case WM_MEASUREITEM:
  108. {
  109. LPMEASUREITEMSTRUCT lpMI=(LPMEASUREITEMSTRUCT)lParam;
  110. //All icons are system metric+padding in width and height
  111. lpMI->itemWidth =GetSystemMetrics(SM_CXICON)+CXICONPAD;
  112. lpMI->itemHeight=GetSystemMetrics(SM_CYICON)+CYICONPAD;
  113. }
  114. break;
  115. case WM_DRAWITEM:
  116. return FDrawListIcon((LPDRAWITEMSTRUCT)lParam);
  117. case WM_DELETEITEM:
  118. //Free the GDI object for the item
  119. DestroyIcon((HICON)LOWORD(((LPDELETEITEMSTRUCT)lParam)->itemData));
  120. break;
  121. case WM_COMMAND:
  122. switch (wID)
  123. {
  124. case ID_CURRENT:
  125. case ID_DEFAULT:
  126. case ID_FROMFILE:
  127. UpdateResultIcon(lpCI, hDlg, wID);
  128. break;
  129. case ID_LABELEDIT:
  130. //When the edit loses focus, update the result display
  131. if (EN_KILLFOCUS==wCode)
  132. {
  133. GetDlgItemText(hDlg, ID_LABELEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR));
  134. SetDlgItemText(hDlg, ID_RESULTLABEL, szTemp);
  135. }
  136. break;
  137. case ID_FROMFILEEDIT:
  138. //If the text changed, remove any selection in the list.
  139. GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR));
  140. if (lpCI && lstrcmpi(szTemp, lpCI->szFile))
  141. {
  142. SendDlgItemMessage(hDlg, ID_ICONLIST, LB_SETCURSEL
  143. , (WPARAM)-1, 0);
  144. //Also force selection of ID_FROMFILE
  145. CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_FROMFILE);
  146. }
  147. break;
  148. case ID_ICONLIST:
  149. switch (wCode)
  150. {
  151. case LBN_SETFOCUS:
  152. //If we got the focus, see about updating.
  153. GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp
  154. , sizeof(szTemp)/sizeof(TCHAR));
  155. //Check if file changed and update the list if so
  156. if (lpCI && 0!=lstrcmpi(szTemp, lpCI->szFile))
  157. {
  158. lstrcpy(lpCI->szFile, szTemp);
  159. UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile);
  160. UpdateResultIcon(lpCI, hDlg, ID_FROMFILE);
  161. }
  162. break;
  163. case LBN_SELCHANGE:
  164. UpdateResultIcon(lpCI, hDlg, ID_FROMFILE);
  165. break;
  166. case LBN_DBLCLK:
  167. //Same as pressing OK.
  168. SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
  169. break;
  170. }
  171. break;
  172. case ID_BROWSE:
  173. {
  174. DWORD dwOfnFlags;
  175. /*
  176. * To allow the hook to customize the browse dialog, we
  177. * send OLEUI_MSG_BROWSE. If the hook returns FALSE
  178. * we use the default, otherwise we trust that it retrieved
  179. * a filename for us. This mechanism prevents hooks from
  180. * trapping ID_BROWSE to customize the dialog and from
  181. * trying to figure out what we do after we have the name.
  182. */
  183. //Copy for reference
  184. LSTRCPYN(szTemp, lpCI->szFile, sizeof(szTemp)/sizeof(TCHAR));
  185. uRet=UStandardHook(lpCI, hDlg, uMsgBrowse, OLEUI_CCHPATHMAX_SIZE
  186. , (LONG)(LPSTR)lpCI->szFile);
  187. dwOfnFlags = OFN_FILEMUSTEXIST;
  188. if (lpCI->lpOCI->dwFlags & CIF_SHOWHELP)
  189. dwOfnFlags |= OFN_SHOWHELP;
  190. if (0==uRet)
  191. uRet=(BOOL)Browse(hDlg, lpCI->szFile, NULL, OLEUI_CCHPATHMAX_SIZE, IDS_ICONFILTERS, dwOfnFlags);
  192. /*
  193. * Only reinitialize if the file changed, so if we got
  194. * TRUE from the hook but the user hit Cancel, we don't
  195. * spend time unecessarily refilling the list.
  196. */
  197. if (0!=uRet && 0!=lstrcmpi(szTemp, lpCI->szFile))
  198. {
  199. CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_FROMFILE);
  200. SetDlgItemText(hDlg, ID_FROMFILEEDIT, lpCI->szFile);
  201. UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile);
  202. UpdateResultIcon(lpCI, hDlg, ID_FROMFILE);
  203. }
  204. }
  205. break;
  206. case IDOK:
  207. /*
  208. * If the user pressed enter, compare the current file
  209. * and the one we have stored. If they match, then
  210. * refill the listbox instead of closing down. This is
  211. * so the user can press Enter in the edit control as
  212. * they would expect to be able to do.
  213. */
  214. GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR));
  215. //Check if the file changed at all.
  216. if (0!=lstrcmpi(szTemp, lpCI->szFile))
  217. {
  218. lstrcpy(lpCI->szFile, szTemp);
  219. UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile);
  220. UpdateResultIcon(lpCI, hDlg, ID_FROMFILE);
  221. //Eat this message to prevent focus change.
  222. return TRUE;
  223. }
  224. // Check if the file name is valid
  225. // (if FromFile is enabled)
  226. if (ID_FROMFILE & lpCI->dwFlags)
  227. {
  228. OFSTRUCT of;
  229. HWND hWnd;
  230. if (HFILE_ERROR==DoesFileExist(lpCI->szFile, &of))
  231. {
  232. OpenFileError(hDlg, of.nErrCode, lpCI->szFile);
  233. hWnd = GetDlgItem(hDlg, ID_FROMFILEEDIT);
  234. SetFocus(hWnd);
  235. SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
  236. return TRUE; // eat this message
  237. }
  238. }
  239. if ((HWND)LOWORD(lParam) != GetFocus())
  240. SetFocus((HWND)LOWORD(lParam));
  241. /*
  242. * On closing, create a new metafilepict with the
  243. * current icon and label, destroying the old structure.
  244. *
  245. * Since we make a copy of the icon by placing it into
  246. * the metafile, we have to make sure we delete the
  247. * icon in the current field. When the listbox is
  248. * destroyed WM_DELETEITEMs will clean it up appropriately.
  249. */
  250. hIcon=(HICON)SendDlgItemMessage(hDlg, ID_RESULTICON
  251. , STM_GETICON, 0, 0L);
  252. /*
  253. * If default is selected then we get the source
  254. * information from registrion database for the
  255. * current class to put in the metafile. If current
  256. * is selected the we just retrieve the original file
  257. * again and recreate the metafile. If from file is
  258. * selected we use the current filename from the
  259. * control and the current listbox selection.
  260. */
  261. psz=lpCI->szFile;
  262. if (lpCI->dwFlags & CIF_SELECTDEFAULT)
  263. {
  264. psz=lpCI->szDefIconFile;
  265. lpCI->iIcon=lpCI->iDefIcon;
  266. hIcon=lpCI->hDefIcon;
  267. }
  268. if (lpCI->dwFlags & CIF_SELECTCURRENT)
  269. {
  270. //Go get the current icon source back.
  271. OleUIMetafilePictExtractIconSource(lpCI->lpOCI->hMetaPict
  272. , psz, &lpCI->iIcon);
  273. }
  274. if (lpCI->dwFlags & CIF_SELECTFROMFILE)
  275. {
  276. GetDlgItemText(hDlg, ID_FROMFILEEDIT, psz, OLEUI_CCHPATHMAX);
  277. lpCI->iIcon=(UINT)SendDlgItemMessage(hDlg
  278. , ID_ICONLIST, LB_GETCURSEL, 0, 0L);
  279. }
  280. //Get the label and go create the metafile
  281. GetDlgItemText(hDlg, ID_LABELEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR));
  282. //If psz is NULL (default) we get no source comments.
  283. #ifdef OLE201
  284. hMetaPict=OleUIMetafilePictFromIconAndLabel(hIcon,
  285. szTemp, psz, lpCI->iIcon);
  286. #endif
  287. //Clean up the current icon that we extracted.
  288. hIcon=(HICON)SendDlgItemMessage(hDlg, ID_CURRENTICON
  289. , STM_GETICON, 0, 0L);
  290. DestroyIcon(hIcon);
  291. //Clean up the default icon
  292. DestroyIcon(lpCI->hDefIcon);
  293. // Remove the prop set on our parent
  294. RemoveProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG);
  295. if (NULL==hMetaPict)
  296. SendMessage(hDlg, uMsgEndDialog, OLEUI_FALSE, 0L);
  297. OleUIMetafilePictIconFree(lpCI->lpOCI->hMetaPict);
  298. lpCI->lpOCI->hMetaPict=hMetaPict;
  299. lpCI->lpOCI->dwFlags = lpCI->dwFlags;
  300. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  301. break;
  302. case IDCANCEL:
  303. //Clean up the current icon that we extracted.
  304. hIcon=(HICON)SendDlgItemMessage(hDlg, ID_CURRENTICON
  305. , STM_GETICON, 0, 0L);
  306. DestroyIcon(hIcon);
  307. //Clean up the default icon
  308. DestroyIcon(lpCI->hDefIcon);
  309. // Remove the prop set on our parent
  310. RemoveProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG);
  311. //We leave hMetaPict intact on Cancel; caller's responsibility
  312. SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
  313. break;
  314. case ID_OLEUIHELP:
  315. PostMessage(lpCI->lpOCI->hWndOwner, uMsgHelp,
  316. (WPARAM)hDlg, MAKELPARAM(IDD_CHANGEICON, 0));
  317. break;
  318. }
  319. break;
  320. default:
  321. {
  322. if (lpCI && iMsg == lpCI->nBrowseHelpID) {
  323. PostMessage(lpCI->lpOCI->hWndOwner, uMsgHelp,
  324. (WPARAM)hDlg, MAKELPARAM(IDD_CHANGEICONBROWSE, 0));
  325. }
  326. }
  327. break;
  328. }
  329. return FALSE;
  330. }
  331. /*
  332. * FChangeIconInit
  333. *
  334. * Purpose:
  335. * WM_INITIDIALOG handler for the Change Icon dialog box.
  336. *
  337. * Parameters:
  338. * hDlg HWND of the dialog
  339. * wParam WPARAM of the message
  340. * lParam LPARAM of the message
  341. *
  342. * Return Value:
  343. * BOOL Value to return for WM_INITDIALOG.
  344. */
  345. BOOL FChangeIconInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
  346. {
  347. LPCHANGEICON lpCI;
  348. LPOLEUICHANGEICON lpOCI;
  349. HFONT hFont;
  350. HWND hList;
  351. UINT cyList;
  352. RECT rc, rcG;
  353. UINT uID;
  354. //1. Copy the structure at lParam into our instance memory.
  355. lpCI=(LPCHANGEICON)LpvStandardInit(hDlg, sizeof(CHANGEICON), TRUE, &hFont);
  356. //PvStandardInit send a termination to us already.
  357. if (NULL==lpCI)
  358. return FALSE;
  359. //Save the original pointer and copy necessary information.
  360. lpOCI=(LPOLEUICHANGEICON)lParam;
  361. lpCI->lpOCI =lpOCI;
  362. lpCI->dwFlags=lpOCI->dwFlags;
  363. //Go extract the icon source from the metafile.
  364. OleUIMetafilePictExtractIconSource(lpOCI->hMetaPict, lpCI->szFile, &lpCI->iIcon);
  365. //Go extract the icon and the label from the metafile
  366. OleUIMetafilePictExtractLabel(lpOCI->hMetaPict, lpCI->szLabel, OLEUI_CCHLABELMAX_SIZE, NULL);
  367. lpCI->hCurIcon=OleUIMetafilePictExtractIcon(lpOCI->hMetaPict);
  368. //2. If we got a font, send it to the necessary controls.
  369. if (NULL!=hFont)
  370. {
  371. SendDlgItemMessage(hDlg, ID_RESULTLABEL, WM_SETFONT
  372. , (WPARAM)hFont, 0L);
  373. }
  374. //3. Show or hide the help button
  375. if (!(lpCI->dwFlags & CIF_SHOWHELP))
  376. StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
  377. /*
  378. * 4. Set text limits and initial control values. If we're given
  379. * an intial label we set it in the edit and static controls.
  380. * If we don't, then we copy the default contents of the static
  381. * control into the edit control, meaning that only the default
  382. * static control string need be localized.
  383. */
  384. SendDlgItemMessage(hDlg, ID_LABELEDIT, EM_LIMITTEXT, OLEUI_CCHLABELMAX, 0L);
  385. SendDlgItemMessage(hDlg, ID_FROMFILEEDIT, EM_LIMITTEXT, OLEUI_CCHPATHMAX, 0L);
  386. SetDlgItemText(hDlg, ID_FROMFILEEDIT, lpCI->szFile);
  387. //Copy the label text into the edit and static controls.
  388. SetDlgItemText(hDlg, ID_LABELEDIT, lpCI->szLabel);
  389. SetDlgItemText(hDlg, ID_RESULTLABEL, lpCI->szLabel);
  390. lpCI->hDefIcon = NULL;
  391. if (lpCI->dwFlags & CIF_USEICONEXE)
  392. {
  393. lpCI->hDefIcon = ExtractIcon(ghInst, lpCI->lpOCI->szIconExe, 0);
  394. if (NULL != lpCI->hDefIcon)
  395. {
  396. lstrcpy(lpCI->szDefIconFile, lpCI->lpOCI->szIconExe);
  397. lpCI->iDefIcon = 0;
  398. }
  399. }
  400. if (NULL == lpCI->hDefIcon)
  401. {
  402. HGLOBAL hMetaPict;
  403. #ifdef OLE201
  404. hMetaPict = GetIconOfClass(ghInst,
  405. &lpCI->lpOCI->clsid,
  406. NULL,
  407. TRUE);
  408. #endif
  409. lpCI->hDefIcon = OleUIMetafilePictExtractIcon(hMetaPict);
  410. OleUIMetafilePictExtractIconSource(hMetaPict,
  411. lpCI->szDefIconFile,
  412. &lpCI->iDefIcon);
  413. OleUIMetafilePictIconFree(hMetaPict);
  414. }
  415. //Initialize all the icon displays.
  416. SendDlgItemMessage(hDlg, ID_CURRENTICON, STM_SETICON
  417. , (WPARAM)lpCI->hCurIcon, 0L);
  418. SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_SETICON
  419. , (WPARAM)lpCI->hDefIcon, 0L);
  420. SendDlgItemMessage(hDlg, ID_RESULTICON, STM_SETICON
  421. , (WPARAM)lpCI->hCurIcon, 0L);
  422. /*
  423. * 5. Since we cannot predict the size of icons on any display,
  424. * we have to resize the icon listbox to the size of an icon
  425. * (plus padding), a scrollbar, and two borders (top & bottom).
  426. */
  427. cyList=GetSystemMetrics(SM_CYICON)+GetSystemMetrics(SM_CYHSCROLL)
  428. +GetSystemMetrics(SM_CYBORDER)*2+CYICONPAD;
  429. hList=GetDlgItem(hDlg, ID_ICONLIST);
  430. GetClientRect(hList, &rc);
  431. SetWindowPos(hList, NULL, 0, 0, rc.right, cyList
  432. , SWP_NOMOVE | SWP_NOZORDER);
  433. //Set the columns in this multi-column listbox to hold one icon
  434. SendMessage(hList, LB_SETCOLUMNWIDTH
  435. , GetSystemMetrics(SM_CXICON)+CXICONPAD,0L);
  436. /*
  437. * 5a. If the listbox expanded below the group box, then size
  438. * the groupbox down, move the label static and exit controls
  439. * down, and expand the entire dialog appropriately.
  440. */
  441. GetWindowRect(hList, &rc);
  442. GetWindowRect(GetDlgItem(hDlg, ID_GROUP), &rcG);
  443. if (rc.bottom > rcG.bottom)
  444. {
  445. //Calculate amount to move things down.
  446. cyList=(rcG.bottom-rcG.top)-(rc.bottom-rc.top-cyList);
  447. //Expand the group box.
  448. rcG.right -=rcG.left;
  449. rcG.bottom-=rcG.top;
  450. SetWindowPos(GetDlgItem(hDlg, ID_GROUP), NULL, 0, 0
  451. , rcG.right, rcG.bottom+cyList
  452. , SWP_NOMOVE | SWP_NOZORDER);
  453. //Expand the dialog box.
  454. GetClientRect(hDlg, &rc);
  455. SetWindowPos(hDlg, NULL, 0, 0, rc.right, rc.bottom+cyList
  456. , SWP_NOMOVE | SWP_NOZORDER);
  457. //Move the label and edit controls down.
  458. GetClientRect(GetDlgItem(hDlg, ID_LABEL), &rc);
  459. SetWindowPos(GetDlgItem(hDlg, ID_LABEL), NULL, 0, cyList
  460. , rc.right, rc.bottom, SWP_NOSIZE | SWP_NOZORDER);
  461. GetClientRect(GetDlgItem(hDlg, ID_LABELEDIT), &rc);
  462. SetWindowPos(GetDlgItem(hDlg, ID_LABELEDIT), NULL, 0, cyList
  463. , rc.right, rc.bottom, SWP_NOSIZE | SWP_NOZORDER);
  464. }
  465. /*
  466. * 6. Select Current, Default, or From File radiobuttons appropriately.
  467. * The CheckRadioButton call sends WM_COMMANDs which handle
  468. * other actions. Note that if we check From File, which
  469. * takes an icon from the list, we better fill the list.
  470. * This will also fill the list even if default is selected.
  471. */
  472. if (0!=UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile))
  473. {
  474. //If szFile worked, then select the source icon in the listbox.
  475. SendDlgItemMessage(hDlg, ID_ICONLIST, LB_SETCURSEL, lpCI->iIcon, 0L);
  476. }
  477. if (lpCI->dwFlags & CIF_SELECTCURRENT)
  478. CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_CURRENT);
  479. else
  480. {
  481. uID=(lpCI->dwFlags & CIF_SELECTFROMFILE) ? ID_FROMFILE : ID_DEFAULT;
  482. CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, uID);
  483. }
  484. //7. Give our parent window access to our hDlg (via a special SetProp).
  485. // The PasteSpecial dialog may need to force our dialog down if the
  486. // clipboard contents change underneath it. if so it will send
  487. // us a IDCANCEL command.
  488. SetProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG, hDlg);
  489. lpCI->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING);
  490. //8. Call the hook with lCustData in lParam
  491. UStandardHook(lpCI, hDlg, WM_INITDIALOG, wParam, lpOCI->lCustData);
  492. return TRUE;
  493. }
  494. /*
  495. * UFillIconList
  496. *
  497. * Purpose:
  498. * Given a listbox and a filename, attempts to open that file and
  499. * read all the icons that exist therein, adding them to the listbox
  500. * hList as owner-draw items. If the file does not exist or has no
  501. * icons, then you get no icons and an appropriate warning message.
  502. *
  503. * Parameters:
  504. * hDlg HWND of the dialog containing the listbox.
  505. * idList UINT identifier of the listbox to fill.
  506. * pszFile LPSTR of the file from which to extract icons.
  507. *
  508. * Return Value:
  509. * UINT Number of items added to the listbox. 0 on failure.
  510. */
  511. UINT UFillIconList(HWND hDlg, UINT idList, LPTSTR pszFile)
  512. {
  513. HWND hList;
  514. UINT i;
  515. UINT cIcons=0;
  516. HCURSOR hCur;
  517. HICON hIcon;
  518. OFSTRUCT of;
  519. if (NULL==hDlg || !IsWindow(hDlg) || NULL==pszFile)
  520. return 0;
  521. hList=GetDlgItem(hDlg, idList);
  522. if (NULL==hList)
  523. return 0;
  524. //Clean out the listbox.
  525. SendMessage(hList, LB_RESETCONTENT, 0, 0L);
  526. //If we have an empty string, just exit leaving the listbox empty as well
  527. if (0==lstrlen(pszFile))
  528. return 0;
  529. //Turn on the hourglass
  530. hCur=HourGlassOn();
  531. //Check if the file is valid.
  532. if (HFILE_ERROR!=DoesFileExist(pszFile, &of))
  533. {
  534. #ifdef EXTRACTICONWORKS
  535. //Get the icon count for this file.
  536. cIcons=(UINT)ExtractIcon(ghInst, pszFile, (UINT)-1);
  537. #else
  538. /*
  539. * ExtractIcon in Windows 3.1 with -1 eats a selector, leaving an
  540. * extra global memory object around for this applciation. Since
  541. * changing icons may happen very often with all OLE apps in
  542. * the system, we have to work around it. So we'll say we
  543. * have lots of icons and just call ExtractIcon until it
  544. * fails. We check if there's any around by trying to get
  545. * the first one.
  546. */
  547. cIcons=0xFFFF;
  548. hIcon=ExtractIcon(ghInst, pszFile, 0);
  549. //Fake a failure with cIcons=0, or cleanup hIcon from this test.
  550. if (32 > (UINT)hIcon)
  551. cIcons=0;
  552. else
  553. DestroyIcon(hIcon);
  554. #endif
  555. if (0!=cIcons)
  556. {
  557. SendMessage(hList, WM_SETREDRAW, FALSE, 0L);
  558. for (i=0; i<cIcons; i++)
  559. {
  560. hIcon=ExtractIcon(ghInst, pszFile, i);
  561. if (32 < (UINT)hIcon)
  562. SendMessage(hList, LB_ADDSTRING, 0, (LONG)(UINT)hIcon);
  563. #ifndef EXTRACTICONWORKS
  564. else
  565. {
  566. //ExtractIcon failed, so let's leave now.
  567. break;
  568. }
  569. #endif
  570. }
  571. //Force complete repaint
  572. SendMessage(hList, WM_SETREDRAW, TRUE, 0L);
  573. InvalidateRect(hList, NULL, TRUE);
  574. //Select an icon
  575. SendMessage(hList, LB_SETCURSEL, 0, 0L);
  576. }
  577. else
  578. ErrorWithFile(hDlg, ghInst, IDS_CINOICONSINFILE, pszFile, MB_OK);
  579. }
  580. else
  581. OpenFileError(hDlg, of.nErrCode, pszFile);
  582. HourGlassOff(hCur);
  583. return cIcons;
  584. }
  585. /*
  586. * FDrawListIcon
  587. *
  588. * Purpose:
  589. * Handles WM_DRAWITEM for the icon listbox.
  590. *
  591. * Parameters:
  592. * lpDI LPDRAWITEMSTRUCT from WM_DRAWITEM
  593. *
  594. * Return Value:
  595. * BOOL TRUE if we did anything, FALSE if there are no items
  596. * in the list.
  597. */
  598. BOOL FDrawListIcon(LPDRAWITEMSTRUCT lpDI)
  599. {
  600. COLORREF cr;
  601. /*
  602. * If there are no items in the list, then itemID is negative according
  603. * to the Win3.1 SDK. Unfortunately DRAWITEMSTRUCT has an unsigned int
  604. * for this field, so we need the typecast to do a signed comparison.
  605. */
  606. if ((int)lpDI->itemID < 0)
  607. return FALSE;
  608. /*
  609. * For selection or draw entire case we just draw the entire item all
  610. * over again. For focus cases, we only call DrawFocusRect.
  611. */
  612. if (lpDI->itemAction & (ODA_SELECT | ODA_DRAWENTIRE))
  613. {
  614. //Clear background and draw the icon.
  615. if (lpDI->itemState & ODS_SELECTED)
  616. cr=SetBkColor(lpDI->hDC, GetSysColor(COLOR_HIGHLIGHT));
  617. else
  618. cr=SetBkColor(lpDI->hDC, GetSysColor(COLOR_WINDOW));
  619. //Draw a cheap rectangle.
  620. ExtTextOut(lpDI->hDC, 0, 0, ETO_OPAQUE, &lpDI->rcItem
  621. , NULL, 0, NULL);
  622. DrawIcon(lpDI->hDC, lpDI->rcItem.left+(CXICONPAD/2)
  623. , lpDI->rcItem.top+(CYICONPAD/2)
  624. , (HICON)LOWORD(lpDI->itemData));
  625. //Restore original background for DrawFocusRect
  626. SetBkColor(lpDI->hDC, cr);
  627. }
  628. //Always change focus on the focus action.
  629. if (lpDI->itemAction & ODA_FOCUS || lpDI->itemState & ODS_FOCUS)
  630. DrawFocusRect(lpDI->hDC, &lpDI->rcItem);
  631. return TRUE;
  632. }
  633. /*
  634. * UpdateResultIcon
  635. *
  636. * Purpose:
  637. * Updates the result icon using the current icon in the default display
  638. * or the icon listbox depending on fFromDefault.
  639. *
  640. * Parameters:
  641. * lpCI LPCHANGEICON containing dialog flags.
  642. * hDlg HWND of the dialog
  643. * uID UINT identifying the radiobutton selected.
  644. *
  645. * Return Value:
  646. * None
  647. */
  648. void UpdateResultIcon(LPCHANGEICON lpCI, HWND hDlg, UINT uID)
  649. {
  650. UINT iSel;
  651. LONG lTemp=LB_ERR;
  652. lpCI->dwFlags &= ~(CIF_SELECTCURRENT | CIF_SELECTDEFAULT | CIF_SELECTFROMFILE);
  653. switch (uID)
  654. {
  655. case ID_CURRENT:
  656. lTemp=SendDlgItemMessage(hDlg, ID_CURRENTICON, STM_GETICON, 0, 0L);
  657. lpCI->dwFlags |= CIF_SELECTCURRENT;
  658. break;
  659. case ID_DEFAULT:
  660. lTemp=SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_GETICON, 0, 0L);
  661. lpCI->dwFlags |= CIF_SELECTDEFAULT;
  662. break;
  663. case ID_FROMFILE:
  664. //Get the selected icon from the list and place it in the result
  665. lpCI->dwFlags |= CIF_SELECTFROMFILE;
  666. iSel=(UINT)SendDlgItemMessage(hDlg, ID_ICONLIST, LB_GETCURSEL, 0, 0L);
  667. if ((UINT)LB_ERR==iSel)
  668. lTemp=SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_GETICON, 0, 0L);
  669. else
  670. SendDlgItemMessage(hDlg, ID_ICONLIST, LB_GETTEXT, iSel
  671. , (LPARAM)(LPLONG)&lTemp);
  672. break;
  673. }
  674. if ((LONG)LB_ERR!=lTemp)
  675. SendDlgItemMessage(hDlg, ID_RESULTICON, STM_SETICON, LOWORD(lTemp), 0L);
  676. return;
  677. }
  678. 
  679.