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.

340 lines
9.3 KiB

  1. /*
  2. * pickicon - Icon picker
  3. */
  4. #include "tweakui.h"
  5. /*
  6. * Instance info for the dialog.
  7. */
  8. typedef struct PIDI { /* PickIcon dialog instance */
  9. LPTSTR ptszIconPath; /* Which file? */
  10. UINT ctchIconPath;
  11. int iIconIndex; /* Which icon number? */
  12. int *piIconIndex;
  13. TCH tszCurFile[MAX_PATH]; /* The path in the list box */
  14. } PIDI, *PPIDI;
  15. #define cxIcon GetSystemMetrics(SM_CXICON)
  16. #define cyIcon GetSystemMetrics(SM_CYICON)
  17. /*****************************************************************************
  18. *
  19. * PickIcon_ppidiHdlg
  20. *
  21. * Extract the PPIDI from an hdlg.
  22. *
  23. *****************************************************************************/
  24. #define PickIcon_ppidiHdlg(hdlg) ((PPIDI)GetWindowLongPtr(hdlg, DWLP_USER))
  25. /*****************************************************************************
  26. *
  27. * PickIcon_OnMeasureItem
  28. *
  29. * Tell USER the size of each item.
  30. *
  31. *****************************************************************************/
  32. void PASCAL
  33. PickIcon_OnMeasureItem(HWND hdlg, LPMEASUREITEMSTRUCT lpmi, PPIDI ppidi)
  34. {
  35. lpmi->itemWidth = cxIcon + 12;
  36. lpmi->itemHeight = cyIcon + 4;
  37. }
  38. /*****************************************************************************
  39. *
  40. * PickIcon_OnDrawItem
  41. *
  42. * Draw an icon.
  43. *
  44. *****************************************************************************/
  45. void PASCAL
  46. PickIcon_OnDrawItem(HWND hdlg, LPDRAWITEMSTRUCT lpdi, PPIDI ppidi)
  47. {
  48. SetBkColor(lpdi->hDC, GetSysColor((lpdi->itemState & ODS_SELECTED) ?
  49. COLOR_HIGHLIGHT : COLOR_WINDOW));
  50. /* repaint the selection state */
  51. ExtTextOut(lpdi->hDC, 0, 0, ETO_OPAQUE, &lpdi->rcItem, NULL, 0, NULL);
  52. /* draw the icon centered in the rectangle */
  53. if ((int)lpdi->itemID >= 0) {
  54. DrawIcon(lpdi->hDC,
  55. (lpdi->rcItem.left + lpdi->rcItem.right - cxIcon) / 2,
  56. (lpdi->rcItem.bottom + lpdi->rcItem.top - cyIcon) / 2,
  57. (HICON)lpdi->itemData);
  58. }
  59. /* if it has the focus, draw the focus */
  60. if (lpdi->itemState & ODS_FOCUS) {
  61. DrawFocusRect(lpdi->hDC, &lpdi->rcItem);
  62. }
  63. }
  64. /*****************************************************************************
  65. *
  66. * PickIcon_OnDeleteItem
  67. *
  68. * USER is nuking an item. Clean it up.
  69. *
  70. *****************************************************************************/
  71. #define PickIcon_OnDeleteItem(hdlg, lpdi, ppidi) \
  72. DestroyIcon((HICON)(lpdi)->itemData)
  73. /*****************************************************************************
  74. *
  75. * PickIcon_FillIconList
  76. *
  77. * Fill in all the icons. If the user picks a bad place, we leave
  78. * garbage in the path (so he can edit the name) and leave the list
  79. * box blank.
  80. *
  81. *****************************************************************************/
  82. void PickIcon_FillIconList(HWND hdlg, PPIDI ppidi)
  83. {
  84. HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  85. HWND hwnd = GetDlgItem(hdlg, IDC_PICKICON);
  86. ListBox_SetColumnWidth(hwnd, cxIcon + 12);
  87. ListBox_ResetContent(hwnd);
  88. GetDlgItemText(hdlg, IDC_PICKPATH,
  89. ppidi->tszCurFile, cA(ppidi->tszCurFile));
  90. if (SearchPath(0, ppidi->tszCurFile, 0, cA(ppidi->tszCurFile),
  91. ppidi->tszCurFile, 0)) {
  92. int cIcons;
  93. SetDlgItemText(hdlg, IDC_PICKPATH, ppidi->tszCurFile);
  94. cIcons = ExtractIconEx(ppidi->tszCurFile, 0, 0, 0, 0);
  95. if (cIcons) {
  96. HICON *rgIcons = (HICON *)LocalAlloc(LPTR, cIcons * sizeof(HICON));
  97. if (rgIcons) {
  98. cIcons = (int)ExtractIconEx(ppidi->tszCurFile, 0,
  99. rgIcons, NULL, cIcons);
  100. if (cIcons) {
  101. int iicon;
  102. SendMessage(hwnd, WM_SETREDRAW, 0, 0);
  103. for (iicon = 0; iicon < cIcons; iicon++) {
  104. ListBox_AddString(hwnd, rgIcons[iicon]);
  105. }
  106. if (ListBox_SetCurSel(hwnd, ppidi->iIconIndex) == LB_ERR) {
  107. ListBox_SetCurSel(hwnd, 0);
  108. }
  109. SendMessage(hwnd, WM_SETREDRAW, 1, 0);
  110. } else { /* Mysteriously unable to extract */
  111. }
  112. LocalFree((HLOCAL)rgIcons);
  113. } else { /* Not enough memory to load icons */
  114. }
  115. } else { /* No icons in the file */
  116. }
  117. } else { /* File not found */
  118. }
  119. InvalidateRect(hwnd, 0, 1);
  120. SetCursor(hcurOld);
  121. }
  122. /*****************************************************************************
  123. *
  124. * PickIcon_OnInitDialog
  125. *
  126. * Dialog init. Populate the list box with what we came in with.
  127. *
  128. *****************************************************************************/
  129. void PASCAL
  130. PickIcon_OnInitDialog(HWND hdlg, PPIDI ppidi)
  131. {
  132. SetWindowLongPtr(hdlg, DWLP_USER, (LPARAM)ppidi);
  133. SetDlgItemText(hdlg, IDC_PICKPATH,
  134. lstrcpyn(ppidi->tszCurFile,
  135. ppidi->ptszIconPath, cA(ppidi->tszCurFile)));
  136. SendDlgItemMessage(hdlg, IDC_PICKPATH, EM_LIMITTEXT,
  137. ppidi->ctchIconPath, 0);
  138. PickIcon_FillIconList(hdlg, ppidi);
  139. }
  140. /*****************************************************************************
  141. *
  142. * PickIcon_OnBrowse
  143. *
  144. *****************************************************************************/
  145. void PASCAL
  146. PickIcon_OnBrowse(HWND hdlg, PPIDI ppidi)
  147. {
  148. DWORD dw;
  149. COFN cofn;
  150. InitOpenFileName(hdlg, &cofn, IDS_ICONFILES, ppidi->tszCurFile);
  151. dw = GetFileAttributes(ppidi->tszCurFile);
  152. if (dw == 0xFFFFFFFF || (dw & FILE_ATTRIBUTE_DIRECTORY)) {
  153. cofn.tsz[0] = '\0';
  154. }
  155. if (GetOpenFileName(&cofn.ofn)) {
  156. SetDlgItemText(hdlg, IDC_PICKPATH, cofn.tsz);
  157. SendMessage(hdlg, DM_SETDEFID, IDOK, 0);
  158. PickIcon_FillIconList(hdlg, ppidi);
  159. }
  160. }
  161. /*****************************************************************************
  162. *
  163. * PickIcon_NameChange
  164. *
  165. * Determine whether the thing in the edit control doesn't match the
  166. * thing whose icons we are showing.
  167. *
  168. *****************************************************************************/
  169. BOOL PASCAL
  170. PickIcon_NameChange(HWND hdlg, PPIDI ppidi)
  171. {
  172. TCH tszBuffer[MAX_PATH];
  173. GetDlgItemText(hdlg, IDC_PICKPATH, tszBuffer, cA(tszBuffer));
  174. return lstrcmpi(tszBuffer, ppidi->tszCurFile);
  175. }
  176. /*****************************************************************************
  177. *
  178. * PickIcon_OnOk
  179. *
  180. * If the name has changed, treat this as a "Okay, now reload
  181. * the icons" rather than "Okay, I'm finished".
  182. *
  183. *****************************************************************************/
  184. void PASCAL
  185. PickIcon_OnOk(HWND hdlg, PPIDI ppidi)
  186. {
  187. if (PickIcon_NameChange(hdlg, ppidi)) {
  188. PickIcon_FillIconList(hdlg, ppidi);
  189. } else {
  190. int iIconIndex = (int)SendDlgItemMessage(hdlg, IDC_PICKICON,
  191. LB_GETCURSEL, 0, 0L);
  192. if (iIconIndex >= 0) { /* We have an icon */
  193. *ppidi->piIconIndex = iIconIndex;
  194. lstrcpyn(ppidi->ptszIconPath, ppidi->tszCurFile,
  195. ppidi->ctchIconPath);
  196. EndDialog(hdlg, 1);
  197. } else { /* No icon, act like cancel */
  198. EndDialog(hdlg, 0);
  199. }
  200. }
  201. }
  202. /*****************************************************************************
  203. *
  204. * PickIcon_OnCommand
  205. *
  206. *****************************************************************************/
  207. void PASCAL
  208. PickIcon_OnCommand(HWND hdlg, int id, UINT codeNotify, PPIDI ppidi)
  209. {
  210. switch (id) {
  211. case IDOK: PickIcon_OnOk(hdlg, ppidi); break;
  212. case IDCANCEL: EndDialog(hdlg, 0); break;
  213. case IDC_PICKBROWSE: PickIcon_OnBrowse(hdlg, ppidi); break;
  214. /*
  215. * When the name changes, remove the selection highlight.
  216. */
  217. case IDC_PICKPATH:
  218. if (PickIcon_NameChange(hdlg, ppidi)) {
  219. SendDlgItemMessage(hdlg, IDC_PICKICON, LB_SETCURSEL, (WPARAM)-1, 0);
  220. }
  221. break;
  222. case IDC_PICKICON:
  223. if (PickIcon_NameChange(hdlg, ppidi)) {
  224. PickIcon_FillIconList(hdlg, ppidi);
  225. } else if (codeNotify == LBN_DBLCLK) {
  226. PickIcon_OnOk(hdlg, ppidi);
  227. }
  228. break;
  229. }
  230. }
  231. /*****************************************************************************
  232. *
  233. * PickIcon_DlgProc
  234. *
  235. * Dialog procedure.
  236. *
  237. *****************************************************************************/
  238. /*
  239. * The HANDLE_WM_* macros weren't designed to be used from a dialog
  240. * proc, so we need to handle the messages manually. (But carefully.)
  241. */
  242. INT_PTR EXPORT
  243. PickIcon_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  244. {
  245. PPIDI ppidi = PickIcon_ppidiHdlg(hdlg);
  246. switch (wm) {
  247. case WM_INITDIALOG: PickIcon_OnInitDialog(hdlg, (PPIDI)lParam); break;
  248. case WM_COMMAND:
  249. PickIcon_OnCommand(hdlg, (int)GET_WM_COMMAND_ID(wParam, lParam),
  250. (UINT)GET_WM_COMMAND_CMD(wParam, lParam),
  251. ppidi);
  252. break;
  253. case WM_DRAWITEM:
  254. PickIcon_OnDrawItem(hdlg, (LPDRAWITEMSTRUCT)lParam, ppidi);
  255. break;
  256. case WM_MEASUREITEM:
  257. PickIcon_OnMeasureItem(hdlg, (LPMEASUREITEMSTRUCT)lParam, ppidi);
  258. break;
  259. case WM_DELETEITEM:
  260. PickIcon_OnDeleteItem(hdlg, (LPDELETEITEMSTRUCT)lParam, ppidi);
  261. break;
  262. default: return 0; /* Unhandled */
  263. }
  264. return 1; /* Handled */
  265. }
  266. /*****************************************************************************
  267. *
  268. * PickIconDlg
  269. *
  270. * Ask the user to pick an icon.
  271. *
  272. * hwnd - owner window
  273. * ptszIconPath - (in) default icon file
  274. * (out) chosen icon file
  275. * ctchIconPath - size of ptszIconPath buffer
  276. * piIconIndex - (in) default icon index
  277. * (out) index of chosen icon
  278. *
  279. * If the dialog box is cancelled, then no values are changed.
  280. *
  281. *****************************************************************************/
  282. INT_PTR PASCAL
  283. PickIcon(HWND hwnd, LPTSTR ptszIconPath, UINT ctchIconPath, int *piIconIndex)
  284. {
  285. PIDI pidi;
  286. pidi.ptszIconPath = ptszIconPath;
  287. pidi.ctchIconPath = ctchIconPath;
  288. pidi.piIconIndex = piIconIndex;
  289. pidi.iIconIndex = *piIconIndex;
  290. return DialogBoxParam(hinstCur, MAKEINTRESOURCE(IDD_PICKICON), hwnd,
  291. PickIcon_DlgProc, (LPARAM)&pidi);
  292. }