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.

2551 lines
84 KiB

  1. /* ETCDLG.C
  2. Resident Code Segment // Tweak: make non-resident?
  3. Routines for Pointers/Sounds/Etc preview dialog
  4. Frosting: Master Theme Selector for Windows '95
  5. Copyright (c) 1994-1999 Microsoft Corporation. All rights reserved.
  6. */
  7. // ---------------------------------------------
  8. // Brief file history:
  9. // Alpha:
  10. // Beta:
  11. // Bug fixes
  12. // ---------
  13. //
  14. // ---------------------------------------------
  15. #define OEMRESOURCE 1 // for OBM_*
  16. #include "windows.h"
  17. #include "frost.h"
  18. #include "global.h"
  19. #include "prsht.h"
  20. #include "commdlg.h"
  21. #include "stdlib.h"
  22. #include "mmsystem.h"
  23. #include "..\inc\addon.h"
  24. #include "loadimag.h"
  25. #include "adutil.h"
  26. #include "schedule.h" // IsPlatformNT()
  27. // Local Routines
  28. BOOL EtcInit(void );
  29. void EtcDestroy(void );
  30. INT_PTR FAR PASCAL PtrsPageProc(HWND, UINT, WPARAM, LPARAM);
  31. INT_PTR FAR PASCAL SndsPageProc(HWND, UINT, WPARAM, LPARAM);
  32. INT_PTR FAR PASCAL PicsPageProc(HWND, UINT, WPARAM, LPARAM);
  33. void CreateDataStr(LPTSTR, LPTSTR, LPTSTR);
  34. void GetFileStr(LPTSTR, LPTSTR);
  35. void GetDisplayStr(LPTSTR, LPTSTR);
  36. HBITMAP PASCAL GetSoundBitmap(LPTSTR lpszFile);
  37. HANDLE PASCAL GetRiffAll(HMMIO hmmio, LPTSTR szText, int iLen);
  38. void PASCAL SetDlgItemFile(HWND, UINT, LPCTSTR);
  39. // stuff from DIB.C
  40. HPALETTE WINAPI bmfCreateDIBPalette(HANDLE);
  41. HBITMAP WINAPI bmfBitmapFromDIB(HANDLE, HPALETTE);
  42. HPALETTE CreateBIPalette (LPBITMAPINFOHEADER);
  43. DWORD WINAPI bmfDIBSize(HANDLE);
  44. WORD PaletteSize (VOID FAR *pv);
  45. WORD NumDIBColors (VOID FAR * pv);
  46. // globals
  47. HBITMAP hbmpCheck, hbmpQ;
  48. BITMAP bmCheck, bmQ;
  49. int iItemHeight; // height of listbox items
  50. int xTextOffset; // leave room for checkmark when drawing text
  51. RECT rPreview; // area of preview image
  52. HCURSOR hCurCursor = NULL;
  53. HBITMAP hbmpCurSnd = NULL;
  54. HANDLE hCurImage = NULL; // icon or bitmap
  55. TCHAR szCurPreviewFile[MAX_PATHLEN+1];
  56. #define bThemed (*szCurThemeFile)
  57. typedef struct {
  58. int idStr; // resource id of display string
  59. int indexF; // index into approp FROST_* struct
  60. } STR_TO_KEY;
  61. // stuff from DIB.C
  62. #define PALVERSION 0x300
  63. #define MAXPALETTE 256 /* max. # supported palette entries */
  64. #define WIDTHBYTES(i) (((i)+31)/32*4)
  65. //
  66. // These arrays match the resource string ids of the strings displayed in
  67. // the listboxes to the index into the appropriate FROST_* array -- to find
  68. // the theme-file key needed to retrieve the filename of the associated
  69. // cursor/icon/bitmap.
  70. //
  71. //
  72. // WARNING: keep indices current with any changes in fvCursors[] in keys.h!
  73. //
  74. // THIS ARRAY SHOWS THE ORDER THAT THE ITEMS APPEAR IN THE LISTBOX!
  75. STR_TO_KEY stkCursors[] = {
  76. {STR_CUR_ARROW, 0 },
  77. {STR_CUR_HELP, 1 },
  78. {STR_CUR_APPSTART, 2 },
  79. {STR_CUR_WAIT, 3 },
  80. {STR_CUR_CROSSHAIR, 8 },
  81. {STR_CUR_IBEAM, 9 },
  82. {STR_CUR_NWPEN, 4 },
  83. {STR_CUR_NO, 5 },
  84. {STR_CUR_SIZENS, 6 },
  85. {STR_CUR_SIZEWE, 7 },
  86. {STR_CUR_SIZENWSE, 10 },
  87. {STR_CUR_SIZENESW, 11 },
  88. {STR_CUR_SIZEALL, 12 },
  89. {STR_CUR_UPARROW, 13 }
  90. };
  91. //
  92. // WARNING: keep indices current with any changes in fsCurUser[] in keys.h!
  93. //
  94. // This listbox has its items sorted. Currently.
  95. STR_TO_KEY stkSounds[] = {
  96. {STR_SND_DEF, 2 },
  97. {STR_SND_GPF, 3 },
  98. {STR_SND_MAX, 4 },
  99. {STR_SND_MENUCMD, 5 },
  100. {STR_SND_MENUPOP, 6 },
  101. {STR_SND_MIN, 7 },
  102. {STR_SND_OPEN, 8 },
  103. {STR_SND_CLOSE, 9 },
  104. {STR_SND_MAILBEEP, 10 },
  105. {STR_SND_RESTDOWN, 11 },
  106. {STR_SND_RESTUP, 12 },
  107. {STR_SND_RINGIN, 13 },
  108. {STR_SND_RINGOUT, 14 },
  109. {STR_SND_SYSASTER, 15 },
  110. {STR_SND_SYSDEF, 16 },
  111. {STR_SND_SYSEXCL, 17 },
  112. {STR_SND_SYSEXIT, 18 },
  113. {STR_SND_SYSHAND, 19 },
  114. {STR_SND_SYSQUEST, 20 },
  115. {STR_SND_SYSSTART, 21 },
  116. {STR_SND_TOSSTRASH, 22 }
  117. };
  118. // WARNING: keep current with any changes in number of items in visuals dlg
  119. #define SCRSAV_NDX 6 // zero-based
  120. // max number of items is in the sound listbox
  121. #define MAX_ETC_ITEMS (sizeof(stkSounds)/sizeof(STR_TO_KEY))
  122. // this array is init'd with the listbox init to keep track of
  123. // which files actually exist
  124. BOOL bCursorExists[MAX_ETC_ITEMS+1];
  125. BOOL bSoundExists[MAX_ETC_ITEMS+1];
  126. BOOL bVisualExists[MAX_ETC_ITEMS+1];
  127. //
  128. // HELP CONTEXT ID to CONTROL ID pairings for context help
  129. //
  130. POPUP_HELP_ARRAY phaPtrsDlg[] = {
  131. { (DWORD)LB_PTRS , (DWORD)IDH_THEME_POINTERS_LIST},
  132. { (DWORD)RECT_PREVIEW , (DWORD)IDH_THEME_POINTERS_PREV},
  133. { (DWORD)TXT_FILENAME , (DWORD)IDH_THEME_POINTERS_FILE},
  134. { (DWORD)0, (DWORD)0 } // double-null terminator
  135. };
  136. POPUP_HELP_ARRAY phaSndsDlg[] = {
  137. { (DWORD)LB_SNDS , (DWORD)IDH_THEME_SOUNDS_LIST},
  138. { (DWORD)RECT_PREVIEW , (DWORD)IDH_THEME_SOUNDS_ICON_PREV},
  139. { (DWORD)PB_PLAY , (DWORD)IDH_THEME_SOUNDS_PLAYS},
  140. { (DWORD)TXT_FILENAME , (DWORD)IDH_THEME_SOUNDS_FILE},
  141. { (DWORD)0, (DWORD)0 } // double-null terminator
  142. };
  143. POPUP_HELP_ARRAY phaPicsDlg[] = {
  144. { (DWORD)LB_PICS , (DWORD)IDH_THEME_PICS_LIST},
  145. { (DWORD)RECT_PREVIEW , (DWORD)IDH_THEME_PICS_PREV},
  146. { (DWORD)TXT_FILENAME , (DWORD)IDH_THEME_PICS_FILE},
  147. { (DWORD)0, (DWORD)0 } // double-null terminator
  148. };
  149. //
  150. // DoEtcDlgs
  151. //
  152. // Sets up the property sheet for Pointers, Sounds, Pictures.
  153. //
  154. // Returns: BOOL success of setup.
  155. //
  156. INT_PTR FAR DoEtcDlgs(HWND hParent)
  157. {
  158. PROPSHEETPAGE psp[3];
  159. PROPSHEETHEADER psh;
  160. INT_PTR iret;
  161. //
  162. // Set up each of the three pages
  163. ZeroMemory(psp, sizeof(psp));
  164. psp[0].dwSize = sizeof(PROPSHEETPAGE);
  165. psp[0].dwFlags = PSP_USETITLE;
  166. psp[0].hInstance = hInstApp;
  167. psp[0].pszTemplate = MAKEINTRESOURCE(DLGPROP_PTRS);
  168. psp[0].pszIcon = (LPCTSTR)NULL;
  169. psp[0].pszTitle = MAKEINTRESOURCE(STR_TITLE_PTRS);
  170. psp[0].pfnDlgProc = PtrsPageProc;
  171. psp[0].lParam = (LPARAM)0;
  172. psp[0].pfnCallback = (LPFNPSPCALLBACK)0;
  173. psp[0].pcRefParent = (UINT FAR *)0;
  174. psp[1].dwSize = sizeof(PROPSHEETPAGE);
  175. psp[1].dwFlags = PSP_USETITLE;
  176. psp[1].hInstance = hInstApp;
  177. psp[1].pszTemplate = MAKEINTRESOURCE(DLGPROP_SNDS);
  178. psp[1].pszIcon = (LPCTSTR)NULL;
  179. psp[1].pszTitle = MAKEINTRESOURCE(STR_TITLE_SNDS);
  180. psp[1].pfnDlgProc = SndsPageProc;
  181. psp[1].lParam = (LPARAM)0;
  182. psp[1].pfnCallback = (LPFNPSPCALLBACK)0;
  183. psp[1].pcRefParent = (UINT FAR *)0;
  184. psp[2].dwSize = sizeof(PROPSHEETPAGE);
  185. psp[2].dwFlags = PSP_USETITLE;
  186. psp[2].hInstance = hInstApp;
  187. psp[2].pszTemplate = MAKEINTRESOURCE(DLGPROP_PICS);
  188. psp[2].pszIcon = (LPCTSTR)NULL;
  189. psp[2].pszTitle = MAKEINTRESOURCE(STR_TITLE_PICS);
  190. psp[2].pfnDlgProc = PicsPageProc;
  191. psp[2].lParam = (LPARAM)0;
  192. psp[2].pfnCallback = (LPFNPSPCALLBACK)0;
  193. psp[2].pcRefParent = (UINT FAR *)0;
  194. //
  195. // set up the property sheet info header
  196. psh.dwSize = sizeof(PROPSHEETHEADER);
  197. psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
  198. psh.hwndParent = hParent;
  199. psh.hInstance = hInstApp;
  200. psh.pszIcon = NULL;
  201. psh.pszCaption = MAKEINTRESOURCE(STR_TITLE_ETC);
  202. psh.nPages = sizeof(psp)/sizeof(PROPSHEETPAGE);
  203. psh.nStartPage = 0;
  204. psh.ppsp = (LPCPROPSHEETPAGE) &psp;
  205. //
  206. // object, etc init
  207. if (!EtcInit())
  208. return (FALSE); // couldn't initalize things EXIT
  209. //
  210. // create the property sheet and cleanup
  211. iret = PropertySheet( (LPCPROPSHEETHEADER) &psh);
  212. //
  213. // object, etc cleanup
  214. EtcDestroy();
  215. return (iret >= 0); // TRUE if successful
  216. }
  217. //
  218. // EtcInit/Destroy
  219. //
  220. // Init/Destroy things used in common by all three dialogs.
  221. //
  222. // Destroy returns: success
  223. //
  224. BOOL EtcInit(void)
  225. {
  226. BOOL bret = TRUE;
  227. // owner-draw listboxes' checkmark and question mark
  228. hbmpCheck = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_CHECK));
  229. hbmpQ = LoadBitmap(hInstApp, MAKEINTRESOURCE(BMP_QUESTION));
  230. if (hbmpCheck && hbmpQ) {
  231. // keep specs on bitmap
  232. GetObject(hbmpCheck, sizeof(BITMAP), (LPVOID)(LPBITMAP)&bmCheck);
  233. GetObject(hbmpQ, sizeof(BITMAP), (LPVOID)(LPBITMAP)&bmQ);
  234. }
  235. else
  236. bret = FALSE;
  237. // cleanup
  238. return (bret);
  239. }
  240. void EtcDestroy(void)
  241. {
  242. if (hbmpCheck) DeleteObject(hbmpCheck);
  243. hbmpCheck = NULL;
  244. if (hbmpQ) DeleteObject(hbmpQ);
  245. hbmpQ = NULL;
  246. if (hCurCursor) DestroyCursor(hCurCursor);
  247. hCurCursor = NULL;
  248. if (hbmpCurSnd) DeleteObject(hbmpCurSnd);
  249. hbmpCurSnd = NULL;
  250. if (hCurImage) DestroyCursor(hCurImage);
  251. hCurImage = NULL;
  252. }
  253. //
  254. // *PageProc
  255. //
  256. // Property sheet page procedures for the Etc preview sheet.
  257. //
  258. TCHAR szCursors[] = TEXT("Control Panel\\Cursors");
  259. INT_PTR FAR PASCAL PtrsPageProc(hDlg, message, wParam, lParam)
  260. HWND hDlg;
  261. UINT message;
  262. WPARAM wParam;
  263. LPARAM lParam;
  264. {
  265. switch (message) {
  266. // set up listbox, initial selection, etc.
  267. case WM_INITDIALOG:
  268. { // var scope
  269. int iter;
  270. extern FROST_VALUE fvCursors[]; // for theme file keys
  271. HWND hText, hLBox;
  272. RECT rText;
  273. TCHAR szDispStr[MAX_STRLEN+1];
  274. // just in first of these dialogs, need to init page OK to disabled
  275. EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), FALSE);
  276. SendMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, (WPARAM)0, (LPARAM)0);
  277. // just in first of these dialogs, need to init dialog title
  278. LoadString(hInstApp, STR_PREVIEWDLG, (LPTSTR)szMsg, MAX_MSGLEN);
  279. lstrcat((LPTSTR)szMsg,
  280. bThemed ? FileFromPath((LPTSTR)szCurThemeFile)
  281. : szCurSettings
  282. );
  283. TruncateExt((LPTSTR)szMsg);
  284. SetWindowText(GetParent(hDlg), (LPTSTR)szMsg);
  285. //
  286. // get metrics for drawitem size
  287. hText = GetDlgItem(hDlg, TXT_FILENAME); // 12 dialog box units high
  288. GetWindowRect(hText, (LPRECT)&rText);
  289. iItemHeight = ((rText.bottom - rText.top) * 8) / 12; // dialog font height
  290. xTextOffset = (iItemHeight * 3) / 2; // proportional spacing
  291. Assert(iItemHeight > 0, TEXT("didn't get positive text height for preview listbox!\n"));
  292. #if 0 // this is when we painted the cursor by ourself
  293. // other metrics, etc.
  294. xCursor = GetSystemMetrics(SM_CXCURSOR);
  295. yCursor = GetSystemMetrics(SM_CYCURSOR);
  296. //
  297. // save away preview rect area
  298. GetWindowRect(GetDlgItem(hDlg, RECT_PREVIEW), (LPRECT)&rPreview);
  299. GetWindowRect(hDlg, (LPRECT)&rText);
  300. OffsetRect((LPRECT)&rPreview, -rText.left, -rText.top);
  301. DestroyWindow(GetDlgItem(hDlg, RECT_PREVIEW));
  302. #endif
  303. //
  304. // init the listbox with combined strings
  305. // init
  306. hLBox = GetDlgItem(hDlg, LB_PTRS);
  307. Assert (sizeof(stkCursors)/sizeof(STR_TO_KEY) == NUM_CURSORS,
  308. TEXT("size mismatch stkCursors and NUM_CURSORS\n"));
  309. // for each cursor
  310. for (iter = 0; iter < NUM_CURSORS; iter++) {
  311. // get display string
  312. LoadString(hInstApp, stkCursors[iter].idStr,
  313. (LPTSTR)szDispStr, MAX_STRLEN);
  314. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  315. // get filename if any
  316. if (bThemed) {
  317. GetPrivateProfileString((LPTSTR)szCursors,
  318. (LPTSTR)( fvCursors[stkCursors[iter].indexF].szValName ),
  319. (LPTSTR)szNULL,
  320. (LPTSTR)szMsg, MAX_MSGLEN,
  321. (LPTSTR)szCurThemeFile);
  322. // expand filename string as necessary
  323. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  324. }
  325. else {
  326. // cur system settings
  327. HandGet(HKEY_CURRENT_USER,
  328. (LPTSTR)szCursors,
  329. (LPTSTR)( fvCursors[stkCursors[iter].indexF].szValName ),
  330. (LPTSTR)szMsg);
  331. }
  332. // store whether the file exists
  333. bCursorExists[iter] = szMsg[0] &&
  334. (CF_NOTFOUND != ConfirmFile(szMsg, FALSE)); // don't alter str
  335. // combine strings into data string to load up in
  336. // owner-draw hasstrings listbox!
  337. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  338. // now, finally, go ahead and assign string to listbox
  339. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  340. }
  341. // setup initial focus conditions
  342. SetFocus(hLBox);
  343. SendMessage(hLBox, LB_SETCURSEL, 0, 0);
  344. // need to ensure it gets initial update of cur file
  345. PostMessage(hDlg, WM_COMMAND, MAKEWPARAM(LB_PTRS, LBN_SELCHANGE),
  346. MAKELPARAM(0, 0) );
  347. } // var scope
  348. break;
  349. case WM_MEASUREITEM:
  350. {
  351. LPMEASUREITEMSTRUCT lpmis;
  352. /* Set the height of the list box items. */
  353. lpmis = (LPMEASUREITEMSTRUCT) lParam;
  354. // lpmis->itemHeight = iItemHeight;
  355. lpmis->itemHeight = 0; // DavidBa says they want these big default item hts
  356. // Assert(iItemHeight > 0, TEXT("set non-positive item height for preview listbox!\n"));
  357. // Assert(iItemHeight <= 0, TEXT("OK, set a positive item height for preview listbox!\n"));
  358. }
  359. break;
  360. case WM_DRAWITEM:
  361. { // var scope
  362. TEXTMETRIC tm;
  363. LPDRAWITEMSTRUCT lpdis;
  364. int yTextOffset;
  365. LPTSTR lpszFile;
  366. HDC hdcMem;
  367. HBITMAP hbmpOld;
  368. lpdis = (LPDRAWITEMSTRUCT) lParam;
  369. /* If there are no list box items, skip this message. */
  370. if (lpdis->itemID == -1) {
  371. break;
  372. } // jdk: well, what about focus rect in empty lbox?
  373. //
  374. // Inits
  375. // get the filename assoc with this item, if any
  376. SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
  377. (LPARAM)(LPTSTR)szMsg);
  378. GetDisplayStr((LPTSTR)szMsg, (LPTSTR)szMsg); // Ok src and dst same
  379. // you now have "displaystr\0filename" in szMsg[]
  380. lpszFile = (LPTSTR)(szMsg + lstrlen((LPTSTR)szMsg) + 1);
  381. //
  382. // draw right background color
  383. if (lpdis->itemState & ODS_SELECTED) {
  384. // if item is selected, draw highlight background here
  385. FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
  386. GetSysColorBrush(COLOR_HIGHLIGHT));
  387. // set text color to highlight text
  388. SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
  389. SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  390. }
  391. else { // not selected
  392. // need to do normal background fill to undo prev selection
  393. FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
  394. GetSysColorBrush(COLOR_WINDOW));
  395. // set text color to foreground
  396. SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
  397. SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
  398. }
  399. // if there is a file associated with this item
  400. if (*lpszFile) {
  401. HBITMAP hbmpLeading;
  402. BITMAP bmLeading;
  403. //
  404. // find the right leading bitmap: checkmark or question mark
  405. if (bCursorExists[lpdis->itemID]) {
  406. hbmpLeading = hbmpCheck;
  407. bmLeading = bmCheck;
  408. }
  409. else {
  410. hbmpLeading = hbmpQ;
  411. bmLeading = bmQ;
  412. }
  413. //
  414. // paint in the leading bitmap!
  415. hdcMem = CreateCompatibleDC(lpdis->hDC);
  416. if (hdcMem)
  417. {
  418. hbmpOld = SelectObject(hdcMem, hbmpLeading);
  419. // if item height is less than bitmap height
  420. if (lpdis->rcItem.bottom - lpdis->rcItem.top < bmLeading.bmHeight)
  421. {
  422. // stretch down bitmap size to fit
  423. StretchBlt(lpdis->hDC,
  424. lpdis->rcItem.left, lpdis->rcItem.top,
  425. lpdis->rcItem.bottom - lpdis->rcItem.top, // width = height
  426. lpdis->rcItem.bottom - lpdis->rcItem.top,
  427. hdcMem, 0, 0, bmLeading.bmWidth, bmLeading.bmHeight, SRCCOPY);
  428. }
  429. else // item height taller than checkmark bitmap
  430. {
  431. // just center vertically
  432. BitBlt(lpdis->hDC,
  433. lpdis->rcItem.left,
  434. lpdis->rcItem.top +
  435. (lpdis->rcItem.bottom - lpdis->rcItem.top - bmLeading.bmHeight)/2,
  436. bmLeading.bmWidth, bmLeading.bmHeight,
  437. hdcMem, 0, 0, SRCCOPY);
  438. }
  439. SelectObject(hdcMem, hbmpOld);
  440. DeleteDC(hdcMem);
  441. }
  442. // who cares
  443. // Assert(lpdis->rcItem.bottom - lpdis->rcItem.top == iItemHeight,
  444. // TEXT("MEASUREITEM and DRAWITEM have different heights!\n"));
  445. }
  446. //
  447. // now draw the display string for this item
  448. // figure y offset to vert center text in draw item
  449. GetTextMetrics(lpdis->hDC, &tm);
  450. yTextOffset = (lpdis->rcItem.bottom - lpdis->rcItem.top - tm.tmHeight) / 2;
  451. Assert(yTextOffset >= 0, TEXT("negative text vert offset in DRAWITEM\n"));
  452. if (yTextOffset < 0) yTextOffset = 0;
  453. // do the out
  454. SetBkMode(lpdis->hDC, TRANSPARENT);
  455. TextOut(lpdis->hDC,
  456. lpdis->rcItem.left + xTextOffset,
  457. lpdis->rcItem.top + yTextOffset,
  458. (LPTSTR)szMsg, lstrlen((LPTSTR)szMsg));
  459. //
  460. // if item is selected, draw a focus rect
  461. if (lpdis->itemState & ODS_FOCUS) {
  462. DrawFocusRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem));
  463. }
  464. } // var scope
  465. break;
  466. case WM_COMMAND:
  467. switch ((int)LOWORD(wParam)) {
  468. case LB_PTRS:
  469. // if new selection in listbox
  470. if (HIWORD(wParam) == LBN_SELCHANGE) {
  471. int iSeln, ilen;
  472. // get new selection if any
  473. iSeln = (int)SendDlgItemMessage(hDlg, LB_PTRS, LB_GETCURSEL, 0, 0);
  474. if (LB_ERR == iSeln)
  475. break; // no selection EXIT
  476. // get selection text
  477. SendDlgItemMessage(hDlg, LB_PTRS, LB_GETTEXT,
  478. (WPARAM)iSeln, (LPARAM)(LPTSTR)szMsg);
  479. // update global current filename string
  480. GetFileStr(szCurPreviewFile, szMsg);
  481. // reset dialog static text of filename string
  482. SetDlgItemFile(hDlg, TXT_FILENAME, szCurPreviewFile);
  483. // and scroll end into view
  484. ilen = lstrlen((LPTSTR)szCurPreviewFile);
  485. SendDlgItemMessage(hDlg, TXT_FILENAME, EM_SETSEL,
  486. (WPARAM)0, MAKELPARAM(-1, ilen));
  487. // update cursor
  488. if (hCurCursor) DestroyCursor(hCurCursor);
  489. hCurCursor = NULL;
  490. if (*szCurPreviewFile)
  491. {
  492. hCurCursor = LoadImage(NULL, szCurPreviewFile, IMAGE_CURSOR,
  493. 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
  494. }
  495. // set cursor to static, even if null: null clears prev
  496. SendDlgItemMessage(hDlg, RECT_PREVIEW, STM_SETICON,
  497. (WPARAM)hCurCursor, (LPARAM)0);
  498. #if 0 // this is when we painted the cursor by ourself
  499. // force repaint of preview area
  500. InvalidateRect(hDlg, (LPRECT)&rPreview, TRUE);
  501. #endif
  502. }
  503. break;
  504. // case PB_TEST:
  505. // break;
  506. }
  507. break;
  508. #if 0 // this is when we painted the cursor by ourself
  509. case WM_PAINT:
  510. BeginPaint(hDlg, &ps);
  511. //
  512. // preview area
  513. DrawEdge(ps.hdc, (LPRECT)&rPreview, EDGE_SUNKEN, BF_RECT); // always edge
  514. // if there's a file to preview
  515. if (*szCurPreviewFile) {
  516. // add the cursor
  517. if (hCurCursor)
  518. DrawIcon(ps.hdc,
  519. rPreview.left + (rPreview.right-rPreview.left-xCursor)/2,
  520. rPreview.top + (rPreview.bottom-rPreview.top-yCursor)/2,
  521. hCurCursor);
  522. }
  523. EndPaint(hDlg, &ps);
  524. break;
  525. #endif
  526. case WM_NOTIFY:
  527. switch ( ((NMHDR FAR *)lParam)->code) {
  528. // OK or Apply button pressed
  529. case PSN_APPLY:
  530. // apply any changes made on this page
  531. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); // accept changes
  532. break;
  533. // cancel button pressed
  534. case PSN_RESET:
  535. // don't accept any of the changes made on this page
  536. break;
  537. case PSN_SETACTIVE:
  538. break;
  539. case PSN_KILLACTIVE:
  540. // need to say that it's OK by us to lose the activation
  541. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); // OK to kill focus now
  542. break;
  543. }
  544. break;
  545. case WM_HELP:
  546. {
  547. LPHELPINFO lphi;
  548. lphi = (LPHELPINFO)lParam;
  549. if (lphi->iContextType == HELPINFO_WINDOW) {
  550. WinHelp(lphi->hItemHandle, (LPTSTR)szHelpFile, HELP_WM_HELP,
  551. (DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaPtrsDlg));
  552. }
  553. }
  554. break;
  555. case WM_CONTEXTMENU:
  556. WinHelp((HWND)wParam, (LPTSTR)szHelpFile, HELP_CONTEXTMENU,
  557. (DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaPtrsDlg));
  558. break;
  559. default:
  560. return(FALSE); // didn't process message
  561. break;
  562. }
  563. return TRUE; // processed message
  564. }
  565. INT_PTR FAR PASCAL SndsPageProc(hDlg, message, wParam, lParam)
  566. HWND hDlg;
  567. UINT message;
  568. WPARAM wParam;
  569. LPARAM lParam;
  570. {
  571. static BOOL gfWaveExists = FALSE;
  572. static HBITMAP hbmpPlay = NULL;
  573. BOOL bDoubleClick = FALSE;
  574. switch (message) {
  575. // set up listbox, initial selection, etc.
  576. case WM_INITDIALOG:
  577. { // var scope
  578. int iter;
  579. int iRet;
  580. extern FROST_SUBKEY fsCurUser[]; // for theme file keys
  581. HWND hText, hLBox;
  582. RECT rText;
  583. TCHAR szDispStr[MAX_STRLEN+1];
  584. extern FROST_SUBKEY fsCurUser[];
  585. WAVEOUTCAPS woCaps;
  586. // Taken right from the Sounds cpl.
  587. gfWaveExists = waveOutGetNumDevs() > 0 &&
  588. (waveOutGetDevCaps(0,&woCaps,sizeof(woCaps)) == 0) &&
  589. woCaps.dwFormats != 0L;
  590. if ((hbmpPlay = LoadBitmap(hInstApp, MAKEINTRESOURCE(PLAY_BITMAP))) !=
  591. NULL)
  592. SendDlgItemMessage(hDlg, PB_PLAY, BM_SETIMAGE, IMAGE_BITMAP,
  593. (LPARAM) hbmpPlay);
  594. //
  595. // get metrics for drawitem size
  596. hText = GetDlgItem(hDlg, TXT_FILENAME); // 12 dialog box units high
  597. GetWindowRect(hText, (LPRECT)&rText);
  598. iItemHeight = ((rText.bottom - rText.top) * 8) / 12; // dialog font height
  599. xTextOffset = (iItemHeight * 3) / 2; // proportional spacing
  600. Assert(iItemHeight > 0, TEXT("didn't get positive text height for preview listbox!\n"));
  601. //
  602. // init the listbox with combined strings
  603. // init
  604. hLBox = GetDlgItem(hDlg, LB_SNDS);
  605. Assert (sizeof(stkSounds)/sizeof(STR_TO_KEY) == NUM_SOUNDS,
  606. TEXT("size mismatch stkSounds and NUM_SOUNDS\n"));
  607. // for each sound
  608. for (iter = 0; iter < NUM_SOUNDS; iter++) {
  609. // get display string
  610. LoadString(hInstApp, stkSounds[iter].idStr,
  611. (LPTSTR)szDispStr, MAX_STRLEN);
  612. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  613. // get filename if any
  614. if (bThemed) {
  615. GetPrivateProfileString((LPTSTR)(fsCurUser[stkSounds[iter].indexF].szSubKey),
  616. (LPTSTR)FROST_DEFSTR,
  617. (LPTSTR)szNULL,
  618. (LPTSTR)szMsg, MAX_MSGLEN,
  619. (LPTSTR)szCurThemeFile);
  620. // expand filename string as necessary
  621. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  622. }
  623. else {
  624. // cur system settings
  625. HandGet(HKEY_CURRENT_USER,
  626. (LPTSTR)(fsCurUser[stkSounds[iter].indexF].szSubKey),
  627. (LPTSTR)szNULL,
  628. (LPTSTR)szMsg);
  629. }
  630. // combine strings into data string to load up in
  631. // owner-draw hasstrings listbox!
  632. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  633. // now, finally, go ahead and assign string to listbox
  634. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  635. }
  636. //
  637. // check them all for file existence. have to do here, LBOX IS SORTED!
  638. //
  639. for (iter = 0; iter < MAX_ETC_ITEMS; iter++) {
  640. // get this item's listbox string
  641. iRet = (int) SendMessage(hLBox, LB_GETTEXT, iter, (LPARAM)(LPTSTR)szMsg);
  642. if (iRet == LB_ERR)
  643. break; // past end of listbox items CONTINUE
  644. // get the filename assoc with this item, if any
  645. GetFileStr((LPTSTR)pValue, (LPTSTR)szMsg);
  646. // store whether the file exists
  647. bSoundExists[iter] = *pValue &&
  648. (CF_NOTFOUND != ConfirmFile((LPTSTR)pValue, FALSE));
  649. }
  650. // save away preview rect area
  651. GetWindowRect(GetDlgItem(hDlg, RECT_PREVIEW), (LPRECT)&rPreview);
  652. GetWindowRect(hDlg, (LPRECT)&rText);
  653. OffsetRect((LPRECT)&rPreview, -rText.left, -rText.top);
  654. // setup initial focus conditions
  655. SetFocus(hLBox);
  656. SendMessage(hLBox, LB_SETCURSEL, 0, 0);
  657. // need to ensure it gets initial update of cur file
  658. PostMessage(hDlg, WM_COMMAND, MAKEWPARAM(LB_SNDS, LBN_SELCHANGE),
  659. MAKELPARAM(0, 0) );
  660. } // var scope
  661. break;
  662. case WM_DESTROY:
  663. {
  664. if (hbmpPlay) {
  665. DeleteObject(hbmpPlay);
  666. hbmpPlay = NULL;
  667. }
  668. }
  669. break;
  670. case WM_MEASUREITEM:
  671. {
  672. LPMEASUREITEMSTRUCT lpmis;
  673. /* Set the height of the list box items. */
  674. lpmis = (LPMEASUREITEMSTRUCT) lParam;
  675. // lpmis->itemHeight = iItemHeight;
  676. lpmis->itemHeight = 0; // DavidBa says they want these big default item hts
  677. // Assert(iItemHeight > 0, TEXT("set non-positive item height for preview listbox!\n"));
  678. // Assert(iItemHeight <= 0, TEXT("OK, set a positive item height for preview listbox!\n"));
  679. }
  680. break;
  681. case WM_DRAWITEM:
  682. { // var scope
  683. TEXTMETRIC tm;
  684. LPDRAWITEMSTRUCT lpdis;
  685. int yTextOffset;
  686. LPTSTR lpszFile;
  687. HDC hdcMem;
  688. HBITMAP hbmpOld;
  689. lpdis = (LPDRAWITEMSTRUCT) lParam;
  690. /* If there are no list box items, skip this message. */
  691. if (lpdis->itemID == -1) {
  692. break;
  693. } // jdk: well, what about focus rect in empty lbox?
  694. //
  695. // Inits
  696. // get the filename assoc with this item, if any
  697. SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
  698. (LPARAM)(LPTSTR)szMsg);
  699. GetDisplayStr((LPTSTR)szMsg, (LPTSTR)szMsg); // Ok src and dst same
  700. // you now have "displaystr\0filename" in szMsg[]
  701. lpszFile = (LPTSTR)(szMsg + lstrlen((LPTSTR)szMsg) + 1);
  702. //
  703. // draw right background color
  704. if (lpdis->itemState & ODS_SELECTED) {
  705. // if item is selected, draw highlight background here
  706. FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
  707. GetSysColorBrush(COLOR_HIGHLIGHT));
  708. // set text color to highlight text
  709. SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
  710. SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  711. }
  712. else { // not selected
  713. // need to do normal background fill to undo prev selection
  714. FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
  715. GetSysColorBrush(COLOR_WINDOW));
  716. // set text color to foreground
  717. SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
  718. SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
  719. }
  720. // if there is a file associated with this item
  721. if (*lpszFile) {
  722. HBITMAP hbmpLeading;
  723. BITMAP bmLeading;
  724. //
  725. // find the right leading bitmap: checkmark or question mark
  726. if (bSoundExists[lpdis->itemID]) {
  727. hbmpLeading = hbmpCheck;
  728. bmLeading = bmCheck;
  729. }
  730. else {
  731. hbmpLeading = hbmpQ;
  732. bmLeading = bmQ;
  733. }
  734. //
  735. // paint in the leading bitmap!
  736. hdcMem = CreateCompatibleDC(lpdis->hDC);
  737. if (hdcMem)
  738. {
  739. hbmpOld = SelectObject(hdcMem, hbmpLeading);
  740. // if item height is less than bitmap height
  741. if (lpdis->rcItem.bottom - lpdis->rcItem.top < bmLeading.bmHeight)
  742. {
  743. // stretch down bitmap size to fit
  744. StretchBlt(lpdis->hDC,
  745. lpdis->rcItem.left, lpdis->rcItem.top,
  746. lpdis->rcItem.bottom - lpdis->rcItem.top, // width = height
  747. lpdis->rcItem.bottom - lpdis->rcItem.top,
  748. hdcMem, 0, 0, bmLeading.bmWidth, bmLeading.bmHeight, SRCCOPY);
  749. }
  750. else // item height taller than checkmark bitmap
  751. {
  752. // just center vertically
  753. BitBlt(lpdis->hDC,
  754. lpdis->rcItem.left,
  755. lpdis->rcItem.top +
  756. (lpdis->rcItem.bottom - lpdis->rcItem.top - bmLeading.bmHeight)/2,
  757. bmLeading.bmWidth, bmLeading.bmHeight,
  758. hdcMem, 0, 0, SRCCOPY);
  759. }
  760. SelectObject(hdcMem, hbmpOld);
  761. DeleteDC(hdcMem);
  762. }
  763. // who cares
  764. // Assert(lpdis->rcItem.bottom - lpdis->rcItem.top == iItemHeight,
  765. // TEXT("MEASUREITEM and DRAWITEM have different heights!\n"));
  766. }
  767. //
  768. // now draw the display string for this item
  769. // figure y offset to vert center text in draw item
  770. GetTextMetrics(lpdis->hDC, &tm);
  771. yTextOffset = (lpdis->rcItem.bottom - lpdis->rcItem.top - tm.tmHeight) / 2;
  772. Assert(yTextOffset >= 0, TEXT("negative text vert offset in DRAWITEM\n"));
  773. if (yTextOffset < 0) yTextOffset = 0;
  774. // do the out
  775. SetBkMode(lpdis->hDC, TRANSPARENT);
  776. TextOut(lpdis->hDC,
  777. lpdis->rcItem.left + xTextOffset,
  778. lpdis->rcItem.top + yTextOffset,
  779. (LPTSTR)szMsg, lstrlen((LPTSTR)szMsg));
  780. //
  781. // if item is selected, draw a focus rect
  782. if (lpdis->itemState & ODS_FOCUS) {
  783. DrawFocusRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem));
  784. }
  785. } // var scope
  786. break;
  787. case WM_COMMAND:
  788. switch ((int)LOWORD(wParam)) {
  789. case LB_SNDS:
  790. // if new selection in listbox
  791. if (HIWORD(wParam) == LBN_SELCHANGE) {
  792. int iSeln, ilen;
  793. // get new selection if any
  794. iSeln = (int)SendDlgItemMessage(hDlg, LB_SNDS, LB_GETCURSEL, 0, 0);
  795. if (LB_ERR == iSeln)
  796. break; // no selection EXIT
  797. // get selection text
  798. SendDlgItemMessage(hDlg, LB_SNDS, LB_GETTEXT,
  799. (WPARAM)iSeln, (LPARAM)(LPTSTR)szMsg);
  800. // update global current filename string
  801. GetFileStr(szCurPreviewFile, szMsg);
  802. // reset dialog static text of filename string
  803. SetDlgItemFile(hDlg, TXT_FILENAME, szCurPreviewFile);
  804. // and scroll end into view
  805. ilen = lstrlen((LPTSTR)szCurPreviewFile);
  806. SendDlgItemMessage(hDlg, TXT_FILENAME, EM_SETSEL,
  807. (WPARAM)0, MAKELPARAM(-1, ilen));
  808. // update snd file icon
  809. if (hbmpCurSnd) DeleteObject(hbmpCurSnd);
  810. hbmpCurSnd = NULL;
  811. if (*szCurPreviewFile)
  812. hbmpCurSnd = GetSoundBitmap((LPTSTR)szCurPreviewFile);
  813. // set snd file bmp to static
  814. if (hbmpCurSnd) {
  815. SendDlgItemMessage(hDlg, RECT_PREVIEW, STM_SETIMAGE,
  816. (WPARAM)IMAGE_BITMAP, (LPARAM)hbmpCurSnd);
  817. }
  818. else {
  819. // else need to clear it to empty
  820. SendDlgItemMessage(hDlg, RECT_PREVIEW, STM_SETIMAGE,
  821. (WPARAM)NULL, (LPARAM)NULL);
  822. InvalidateRect(hDlg, (LPRECT)&rPreview, TRUE);
  823. #ifdef SHOULDAWORKED
  824. InvalidateRect(GetDlgItem(hDlg, RECT_PREVIEW), (LPRECT)NULL, TRUE);
  825. UpdateWindow(GetDlgItem(hDlg, RECT_PREVIEW));
  826. #endif
  827. }
  828. // update play button
  829. EnableWindow(GetDlgItem(hDlg, PB_PLAY), *szCurPreviewFile &&
  830. bSoundExists[iSeln] && gfWaveExists);
  831. }
  832. // if just a selection, we're done here
  833. if (HIWORD(wParam) != LBN_DBLCLK)
  834. break;
  835. // else double-click means fall through and play
  836. bDoubleClick = TRUE;
  837. case PB_PLAY:
  838. if (((HIWORD(wParam) == BN_CLICKED) || bDoubleClick) && gfWaveExists) {
  839. int iSeln;
  840. // check that sound file exists
  841. iSeln = (int)SendDlgItemMessage(hDlg, LB_SNDS, LB_GETCURSEL, 0, 0);
  842. if (!bSoundExists[iSeln])
  843. break;
  844. if (*szCurPreviewFile) {
  845. // disable and wait
  846. EnableWindow((HWND)lParam, FALSE);
  847. WaitCursor();
  848. PlaySound((LPTSTR)szCurPreviewFile, NULL, SND_SYNC | SND_FILENAME);
  849. // reenable and normal
  850. EnableWindow((HWND)lParam, TRUE);
  851. NormalCursor();
  852. SetFocus((HWND)lParam);
  853. }
  854. }
  855. break;
  856. }
  857. break;
  858. case WM_NOTIFY:
  859. switch ( ((NMHDR FAR *)lParam)->code) {
  860. // OK or Apply button pressed
  861. case PSN_APPLY:
  862. // apply any changes made on this page
  863. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); // accept changes
  864. break;
  865. // cancel button pressed
  866. case PSN_RESET:
  867. // don't accept any of the changes made on this page
  868. break;
  869. case PSN_SETACTIVE:
  870. break;
  871. case PSN_KILLACTIVE:
  872. // need to say that it's OK by us to lose the activation
  873. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); // OK to kill focus now
  874. break;
  875. }
  876. break;
  877. case WM_HELP:
  878. {
  879. LPHELPINFO lphi;
  880. lphi = (LPHELPINFO)lParam;
  881. if (lphi->iContextType == HELPINFO_WINDOW) {
  882. WinHelp(lphi->hItemHandle, (LPTSTR)szHelpFile, HELP_WM_HELP,
  883. (DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaSndsDlg));
  884. }
  885. }
  886. break;
  887. case WM_CONTEXTMENU:
  888. WinHelp((HWND)wParam, (LPTSTR)szHelpFile, HELP_CONTEXTMENU,
  889. (DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaSndsDlg));
  890. break;
  891. default:
  892. return(FALSE); // didn't process message
  893. break;
  894. }
  895. return TRUE; // processed message
  896. }
  897. HBITMAP PASCAL GetSoundBitmap(LPTSTR lpszFile)
  898. {
  899. HANDLE hDib = NULL;
  900. HMMIO hmmio = NULL;
  901. TCHAR szValue[MAX_MSGLEN+1];
  902. // HPALETTE hPal;
  903. HBITMAP hbmpRet = NULL;
  904. if (!lpszFile || !*lpszFile)
  905. return ((HBITMAP)NULL);
  906. /* Open the file */
  907. hmmio = mmioOpen(lpszFile, NULL, MMIO_ALLOCBUF | MMIO_READ);
  908. // get the DIB
  909. if (hmmio) {
  910. szValue[0] = TEXT('\0');
  911. hDib = GetRiffAll(hmmio, szValue, sizeof(szValue));
  912. mmioClose(hmmio, 0);
  913. }
  914. if (hDib) {
  915. HPALETTE hPal;
  916. hPal = bmfCreateDIBPalette(hDib);
  917. if (hPal)
  918. {
  919. hbmpRet = bmfBitmapFromDIB(hDib, hPal); // hPal can be null
  920. DeleteObject(hPal);
  921. }
  922. GlobalFree(hDib);
  923. }
  924. return(hbmpRet);
  925. }
  926. // guessing that this is the right addition
  927. #define FOURCC_DISP mmioFOURCC('D', 'I', 'S', 'P')
  928. #define FOURCC_INFO mmioFOURCC('I', 'N', 'F', 'O')
  929. #define FOURCC_INAM mmioFOURCC('I', 'N', 'A', 'M')
  930. HANDLE PASCAL GetRiffAll(HMMIO hmmio, LPTSTR szText, int iLen)
  931. {
  932. MMCKINFO ck;
  933. MMCKINFO ckINFO;
  934. MMCKINFO ckRIFF;
  935. HANDLE h = NULL;
  936. LONG lSize;
  937. DWORD dw;
  938. mmioSeek(hmmio, 0, SEEK_SET);
  939. /* descend the input file into the RIFF chunk */
  940. if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0)
  941. goto error;
  942. if (ckRIFF.ckid != FOURCC_RIFF)
  943. goto error;
  944. while (!mmioDescend(hmmio, &ck, &ckRIFF, 0))
  945. {
  946. if (ck.ckid == FOURCC_DISP)
  947. {
  948. /* Read dword into dw, break if read unsuccessful */
  949. if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != sizeof(dw))
  950. goto error;
  951. /* Find out how much memory to allocate */
  952. lSize = ck.cksize - sizeof(dw);
  953. if ((int)dw == CF_DIB && h == NULL)
  954. {
  955. /* get a handle to memory to hold the description and
  956. lock it down */
  957. if ((h = GlobalAlloc(GHND, lSize+4)) == NULL)
  958. goto error;
  959. if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize)
  960. goto error;
  961. }
  962. else if ((int)dw == CF_TEXT && szText[0] == 0)
  963. {
  964. if (lSize > iLen-1)
  965. lSize = iLen-1;
  966. szText[lSize] = 0;
  967. if (mmioRead(hmmio, (LPVOID)szText, lSize) != lSize)
  968. goto error;
  969. }
  970. }
  971. else if (ck.ckid == FOURCC_LIST &&
  972. ck.fccType == FOURCC_INFO &&
  973. szText[0] == 0)
  974. {
  975. while (!mmioDescend(hmmio, &ckINFO, &ck, 0))
  976. {
  977. switch (ckINFO.ckid)
  978. {
  979. case FOURCC_INAM:
  980. // case FOURCC_ISBJ:
  981. lSize = ck.cksize;
  982. if (lSize > iLen-1)
  983. lSize = iLen-1;
  984. szText[lSize] = 0;
  985. if (mmioRead(hmmio, (LPVOID)szText, lSize) != lSize)
  986. goto error;
  987. break;
  988. }
  989. if (mmioAscend(hmmio, &ckINFO, 0))
  990. break;
  991. }
  992. }
  993. //
  994. // if we have both a picture and a title, then exit.
  995. //
  996. if (h != NULL && szText[0] != 0)
  997. break;
  998. /* Ascend so that we can descend into next chunk
  999. */
  1000. if (mmioAscend(hmmio, &ck, 0))
  1001. break;
  1002. }
  1003. goto exit;
  1004. error:
  1005. if (h)
  1006. GlobalFree(h);
  1007. h = NULL;
  1008. exit:
  1009. return h;
  1010. }
  1011. /***************************************************************************
  1012. *
  1013. * FUNCTION :bmfCreateDIBPalette(HANDLE hDib)
  1014. *
  1015. * PURPOSE :Creates a palette suitable for displaying hDib.
  1016. *
  1017. * RETURNS :A handle to the palette if successful, NULL otherwise.
  1018. *
  1019. ****************************************************************************/
  1020. HPALETTE WINAPI bmfCreateDIBPalette (HANDLE hDib)
  1021. {
  1022. HPALETTE hPal;
  1023. LPBITMAPINFOHEADER lpbi;
  1024. if (!hDib)
  1025. return NULL; //bail out if handle is invalid
  1026. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
  1027. if (!lpbi)
  1028. return NULL;
  1029. hPal = CreateBIPalette(lpbi);
  1030. GlobalUnlock(hDib);
  1031. return hPal;
  1032. }
  1033. /***************************************************************************
  1034. *
  1035. * FUNCTION :CreateBIPalette(LPBITMAPINFOHEADER lpbi)
  1036. *
  1037. * PURPOSE :Given a Pointer to a BITMAPINFO struct will create a
  1038. * a GDI palette object from the color table.
  1039. *
  1040. * RETURNS :A handle to the palette if successful, NULL otherwise.
  1041. *
  1042. ****************************************************************************/
  1043. HPALETTE CreateBIPalette (LPBITMAPINFOHEADER lpbi)
  1044. {
  1045. LPLOGPALETTE pPal;
  1046. HPALETTE hPal = NULL;
  1047. WORD nNumColors;
  1048. BYTE red;
  1049. BYTE green;
  1050. BYTE blue;
  1051. int i;
  1052. RGBQUAD FAR *pRgb;
  1053. HANDLE hMem;
  1054. if (!lpbi)
  1055. return NULL;
  1056. if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
  1057. return NULL;
  1058. /* Get a pointer to the color table and the number of colors in it */
  1059. pRgb = (RGBQUAD FAR *)((LPTSTR)lpbi + (WORD)lpbi->biSize);
  1060. nNumColors = NumDIBColors(lpbi);
  1061. if (nNumColors)
  1062. {
  1063. /* Allocate for the logical palette structure */
  1064. hMem = GlobalAlloc(GMEM_MOVEABLE,
  1065. sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  1066. if (!hMem)
  1067. return NULL;
  1068. pPal = (LPLOGPALETTE)GlobalLock(hMem);
  1069. if (!pPal)
  1070. {
  1071. GlobalFree(hMem);
  1072. return NULL;
  1073. }
  1074. pPal->palNumEntries = nNumColors;
  1075. pPal->palVersion = PALVERSION;
  1076. /* Fill in the palette entries from the DIB color table and
  1077. * create a logical color palette.
  1078. */
  1079. for (i = 0; (unsigned)i < nNumColors; i++)
  1080. {
  1081. pPal->palPalEntry[i].peRed = pRgb[i].rgbRed;
  1082. pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
  1083. pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue;
  1084. pPal->palPalEntry[i].peFlags = (BYTE)0;
  1085. }
  1086. hPal = CreatePalette(pPal);
  1087. /* note that a NULL return value for the above CreatePalette call
  1088. * is acceptable, since this value will be returned, and is not
  1089. * used again here
  1090. */
  1091. GlobalUnlock(hMem);
  1092. GlobalFree(hMem);
  1093. }
  1094. else if (lpbi->biBitCount == 24)
  1095. {
  1096. /* A 24 bitcount DIB has no color table entries so, set the number of
  1097. * to the maximum value (256).
  1098. */
  1099. nNumColors = MAXPALETTE;
  1100. hMem =GlobalAlloc(GMEM_MOVEABLE,
  1101. sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  1102. if (!hMem)
  1103. return NULL;
  1104. pPal = (LPLOGPALETTE)GlobalLock(hMem);
  1105. if (!pPal)
  1106. {
  1107. GlobalFree(hMem);
  1108. return NULL;
  1109. }
  1110. pPal->palNumEntries = nNumColors;
  1111. pPal->palVersion = PALVERSION;
  1112. red = green = blue = 0;
  1113. /* Generate 256 (= 8*8*4) RGB combinations to fill the palette
  1114. * entries.
  1115. */
  1116. for (i = 0; (unsigned)i < pPal->palNumEntries; i++)
  1117. {
  1118. pPal->palPalEntry[i].peRed = red;
  1119. pPal->palPalEntry[i].peGreen = green;
  1120. pPal->palPalEntry[i].peBlue = blue;
  1121. pPal->palPalEntry[i].peFlags = (BYTE)0;
  1122. if (!(red += 32))
  1123. if (!(green += 32))
  1124. blue += 64;
  1125. }
  1126. hPal = CreatePalette(pPal);
  1127. /* note that a NULL return value for the above CreatePalette call
  1128. * is acceptable, since this value will be returned, and is not
  1129. * used again here
  1130. */
  1131. GlobalUnlock(hMem);
  1132. GlobalFree(hMem);
  1133. }
  1134. return hPal;
  1135. }
  1136. /***************************************************************************
  1137. *
  1138. * FUNCTION :NumDIBColors(VOID FAR * pv)
  1139. *
  1140. * PURPOSE :Determines the number of colors in the DIB by looking at
  1141. * the BitCount field in the info block.
  1142. * For use only internal to DLL.
  1143. *
  1144. * RETURNS :The number of colors in the DIB.
  1145. *
  1146. ****************************************************************************/
  1147. WORD NumDIBColors (VOID FAR * pv)
  1148. {
  1149. int bits;
  1150. LPBITMAPINFOHEADER lpbi;
  1151. LPBITMAPCOREHEADER lpbc;
  1152. lpbi = ((LPBITMAPINFOHEADER)pv);
  1153. lpbc = ((LPBITMAPCOREHEADER)pv);
  1154. /* With the BITMAPINFO format headers, the size of the palette
  1155. * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
  1156. * is dependent on the bits per pixel ( = 2 raised to the power of
  1157. * bits/pixel).
  1158. */
  1159. if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  1160. {
  1161. if (lpbi->biClrUsed != 0)
  1162. return (WORD)lpbi->biClrUsed;
  1163. bits = lpbi->biBitCount;
  1164. }
  1165. else
  1166. bits = lpbc->bcBitCount;
  1167. switch (bits)
  1168. {
  1169. case 1:
  1170. return 2;
  1171. case 4:
  1172. return 16;
  1173. case 8:
  1174. return 256;
  1175. default:
  1176. /* A 24 bitcount DIB has no color table */
  1177. return 0;
  1178. }
  1179. }
  1180. /***************************************************************************
  1181. *
  1182. * FUNCTION :bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal)
  1183. *
  1184. * PURPOSE :Converts DIB information into a device-dependent BITMAP
  1185. * suitable for display on the current display device. hDib is
  1186. * a global handle to a memory block containing the DIB
  1187. * information in CF_DIB format. hPal is a handle to a palette
  1188. * to be used for displaying the bitmap. If hPal is NULL, the
  1189. * default system palette is used during the conversion.
  1190. *
  1191. * RETURNS :Returns a handle to a bitmap is successful, NULL otherwise.
  1192. *
  1193. * HISTORY:
  1194. * 92/08/29 - BUG 2123: (w-markd)
  1195. * Check if DIB is has a valid size, and bail out if not.
  1196. * If no palette is passed in, try to create one. If we
  1197. * create one, we must destroy it before we exit.
  1198. *
  1199. ****************************************************************************/
  1200. HBITMAP WINAPI bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal)
  1201. {
  1202. LPBITMAPINFOHEADER lpbi;
  1203. HPALETTE hPalT;
  1204. HDC hdc;
  1205. HBITMAP hBmp;
  1206. DWORD dwSize;
  1207. BOOL bMadePalette = FALSE;
  1208. if (!hDib)
  1209. return NULL; //bail out if handle is invalid
  1210. /* BUG 2123: (w-markd)
  1211. ** Check to see if we can get the size of the DIB. If this call
  1212. ** fails, bail out.
  1213. */
  1214. dwSize = bmfDIBSize(hDib);
  1215. if (!dwSize)
  1216. return NULL;
  1217. lpbi = (VOID FAR *)GlobalLock(hDib);
  1218. if (!lpbi)
  1219. return NULL;
  1220. /* prepare palette */
  1221. /* BUG 2123: (w-markd)
  1222. ** If the palette is NULL, we create one suitable for displaying
  1223. ** the dib.
  1224. */
  1225. if (!hPal)
  1226. {
  1227. hPal = bmfCreateDIBPalette(hDib);
  1228. if (!hPal)
  1229. {
  1230. GlobalUnlock(hDib);
  1231. #ifdef V101
  1232. #else
  1233. bMadePalette = TRUE;
  1234. #endif
  1235. return NULL;
  1236. }
  1237. #ifdef V101
  1238. /* BUGFIX: mikeroz 2123 - this flag was in the wrong place */
  1239. bMadePalette = TRUE;
  1240. #endif
  1241. }
  1242. hdc = GetDC(NULL);
  1243. hPalT = SelectPalette(hdc,hPal,FALSE);
  1244. RealizePalette(hdc); // GDI Bug...????
  1245. /* Create the bitmap. Note that a return value of NULL is ok here */
  1246. hBmp = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT,
  1247. (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
  1248. (LPBITMAPINFO)lpbi, DIB_RGB_COLORS );
  1249. /* clean up and exit */
  1250. /* BUG 2123: (w-markd)
  1251. ** If we made the palette, we need to delete it.
  1252. */
  1253. if (bMadePalette)
  1254. DeleteObject(SelectPalette(hdc,hPalT,FALSE));
  1255. else
  1256. SelectPalette(hdc,hPalT,FALSE);
  1257. ReleaseDC(NULL,hdc);
  1258. GlobalUnlock(hDib);
  1259. return hBmp;
  1260. }
  1261. /***************************************************************************
  1262. *
  1263. * FUNCTION :bmfDIBSize(HANDLE hDIB)
  1264. *
  1265. * PURPOSE :Return the size of a DIB.
  1266. *
  1267. * RETURNS :DWORD with size of DIB, include BITMAPINFOHEADER and
  1268. * palette. Returns 0 if failed.
  1269. *
  1270. * HISTORY:
  1271. * 92/08/13 - BUG 1642: (w-markd)
  1272. * Added this function so Quick Recorder could find out the
  1273. * size of a DIB.
  1274. * 92/08/29 - BUG 2123: (w-markd)
  1275. * If the biSizeImage field of the structure we get is zero,
  1276. * then we have to calculate the size of the image ourselves.
  1277. * Also, after size is calculated, we bail out if the
  1278. * size we calculated is larger than the size of the global
  1279. * object, since this indicates that the structure data
  1280. * we used to calculate the size was invalid.
  1281. *
  1282. ****************************************************************************/
  1283. DWORD WINAPI bmfDIBSize(HANDLE hDIB)
  1284. {
  1285. LPBITMAPINFOHEADER lpbi;
  1286. DWORD dwSize;
  1287. /* Lock down the handle, and cast to a LPBITMAPINFOHEADER
  1288. ** so we can read the fields we need
  1289. */
  1290. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1291. if (!lpbi)
  1292. return 0;
  1293. /* BUG 2123: (w-markd)
  1294. ** Since the biSizeImage could be zero, we may have to calculate
  1295. ** the size ourselves.
  1296. */
  1297. dwSize = lpbi->biSizeImage;
  1298. if (dwSize == 0)
  1299. dwSize = WIDTHBYTES((WORD)(lpbi->biWidth) * lpbi->biBitCount) *
  1300. lpbi->biHeight;
  1301. /* The size of the DIB is the size of the BITMAPINFOHEADER
  1302. ** structure (lpbi->biSize) plus the size of our palette plus
  1303. ** the size of the actual data (calculated above).
  1304. */
  1305. dwSize += lpbi->biSize + (DWORD)PaletteSize(lpbi);
  1306. /* BUG 2123: (w-markd)
  1307. ** Check to see if the size is greater than the size
  1308. ** of the global object. If it is, the hDIB is corrupt.
  1309. */
  1310. GlobalUnlock(hDIB);
  1311. if (dwSize > GlobalSize(hDIB))
  1312. return 0;
  1313. else
  1314. return(dwSize);
  1315. }
  1316. /***************************************************************************
  1317. *
  1318. * FUNCTION :PaletteSize(VOID FAR * pv)
  1319. *
  1320. * PURPOSE :Calculates the palette size in bytes. If the info. block
  1321. * is of the BITMAPCOREHEADER type, the number of colors is
  1322. * multiplied by 3 to give the palette size, otherwise the
  1323. * number of colors is multiplied by 4.
  1324. *
  1325. * RETURNS :Palette size in number of bytes.
  1326. *
  1327. ****************************************************************************/
  1328. WORD PaletteSize (VOID FAR *pv)
  1329. {
  1330. LPBITMAPINFOHEADER lpbi;
  1331. WORD NumColors;
  1332. lpbi = (LPBITMAPINFOHEADER)pv;
  1333. NumColors = NumDIBColors(lpbi);
  1334. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1335. return (NumColors * sizeof(RGBTRIPLE));
  1336. else
  1337. return (NumColors * sizeof(RGBQUAD));
  1338. }
  1339. //
  1340. // globals for PicsPageProc
  1341. //int xCursor, yCursor;
  1342. TCHAR szRMineIcon[] = TEXT("CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon");
  1343. TCHAR szRNhbdIcon[] = TEXT("CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon");
  1344. TCHAR szRTrashIcon[] = TEXT("CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon");
  1345. TCHAR szRMyDocsIcon[] = TEXT("CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon");
  1346. TCHAR szCUMineIcon[] = TEXT("Software\\Classes\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon");
  1347. TCHAR szCUNhbdIcon[] = TEXT("Software\\Classes\\CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon");
  1348. TCHAR szCUTrashIcon[] = TEXT("Software\\Classes\\CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon");
  1349. TCHAR szCUMyDocsIcon[] = TEXT("Software\\Classes\\CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon");
  1350. TCHAR szTrashFull[] = TEXT("full");
  1351. TCHAR szTrashEmpty[] = TEXT("empty");
  1352. INT_PTR FAR PASCAL PicsPageProc(hDlg, message, wParam, lParam)
  1353. HWND hDlg;
  1354. UINT message;
  1355. WPARAM wParam;
  1356. LPARAM lParam;
  1357. {
  1358. switch (message) {
  1359. // set up listbox, initial selection, etc.
  1360. case WM_INITDIALOG:
  1361. { // var scope
  1362. extern FROST_SUBKEY fsRoot[]; // for theme file/registry keys
  1363. extern FROST_SUBKEY fsCUIcons[]; // for theme file/registry keys
  1364. extern TCHAR c_szSoftwareClassesFmt[]; // for NT reg path/keys.h
  1365. int iter;
  1366. int iRet;
  1367. HWND hText, hLBox;
  1368. RECT rText;
  1369. TCHAR szDispStr[MAX_STRLEN+1];
  1370. extern TCHAR szCP_DT[];
  1371. extern TCHAR szWP[];
  1372. extern TCHAR szDT[];
  1373. extern TCHAR szSS_Section[];
  1374. extern TCHAR szSS_Key[];
  1375. extern TCHAR szSS_File[];
  1376. TCHAR szNTReg[MAX_PATH];
  1377. //
  1378. // get metrics for drawitem size
  1379. hText = GetDlgItem(hDlg, TXT_FILENAME); // 12 dialog box units high
  1380. GetWindowRect(hText, (LPRECT)&rText);
  1381. iItemHeight = ((rText.bottom - rText.top) * 8) / 12; // dialog font height
  1382. xTextOffset = (iItemHeight * 3) / 2; // proportional spacing
  1383. Assert(iItemHeight > 0, TEXT("didn't get positive text height for preview listbox!\n"));
  1384. #if 0 // to do own drawing for wallpaper and scr saver?
  1385. // other metrics, etc.
  1386. xCursor = GetSystemMetrics(SM_CXCURSOR);
  1387. yCursor = GetSystemMetrics(SM_CYCURSOR);
  1388. //
  1389. // save away preview rect area
  1390. GetWindowRect(GetDlgItem(hDlg, RECT_PREVIEW), (LPRECT)&rPreview);
  1391. GetWindowRect(hDlg, (LPRECT)&rText);
  1392. OffsetRect((LPRECT)&rPreview, -rText.left, -rText.top);
  1393. DestroyWindow(GetDlgItem(hDlg, RECT_PREVIEW));
  1394. #endif
  1395. //
  1396. // init the listbox with combined strings
  1397. // init
  1398. hLBox = GetDlgItem(hDlg, LB_PICS);
  1399. // unlike the ptrs and snds, have to do each item by hand here
  1400. // since they are three different types (actually four ways of
  1401. // retrieving associated file
  1402. //
  1403. // WALLPAPER BITMAP
  1404. // get display string
  1405. LoadString(hInstApp, STR_PIC_WALL,
  1406. (LPTSTR)szDispStr, MAX_STRLEN);
  1407. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  1408. // get filename if any
  1409. if (bThemed) { // get from theme
  1410. GetPrivateProfileString((LPTSTR)szCP_DT, (LPTSTR)szWP,
  1411. (LPTSTR)szNULL,
  1412. (LPTSTR)szMsg, MAX_MSGLEN,
  1413. (LPTSTR)szCurThemeFile);
  1414. // expand filename string as necessary
  1415. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1416. }
  1417. else { // get from system
  1418. // If ActiveDesktop is on we should query AD for this
  1419. // setting instead of reading from the registry.
  1420. if (IsActiveDesktopOn()) {
  1421. if (!GetADWallpaper(szMsg)) {
  1422. // Failed to read AD setting so get it from the registry
  1423. GetRegString(HKEY_CURRENT_USER, szCP_DT, szWP,
  1424. szNULL, szMsg, MAX_MSGLEN);
  1425. }
  1426. }
  1427. // ActiveDesktop is off so get the setting from the registry
  1428. else {
  1429. GetRegString(HKEY_CURRENT_USER, szCP_DT, szWP,
  1430. szNULL, szMsg, MAX_MSGLEN);
  1431. }
  1432. // If this isn't an HTM or HTML wallpaper file then we
  1433. // should extract the image title.
  1434. if ((lstrcmpi(FindExtension(szMsg), TEXT(".htm")) != 0) &&
  1435. (lstrcmpi(FindExtension(szMsg), TEXT(".html")) != 0)) {
  1436. // Not an HTM/L file so extract the image title
  1437. GetImageTitle(szMsg, szMsg, MAX_MSGLEN);
  1438. }
  1439. }
  1440. // combine strings into data string to load up in
  1441. // owner-draw hasstrings listbox!
  1442. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  1443. // now, finally, go ahead and assign string to listbox
  1444. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  1445. //
  1446. // MY COMPUTER ICON
  1447. LoadString(hInstApp, STR_PIC_MYCOMP,
  1448. (LPTSTR)szDispStr, MAX_STRLEN);
  1449. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  1450. // get filename if any
  1451. if (bThemed) { // get from theme
  1452. // Get the CURRENT_USER My Computer icon setting
  1453. GetPrivateProfileString((LPTSTR)szCUMineIcon, (LPTSTR)FROST_DEFSTR,
  1454. (LPTSTR)szNULL,
  1455. (LPTSTR)szMsg, MAX_MSGLEN,
  1456. (LPTSTR)szCurThemeFile);
  1457. // If the string is NULL, try the "old" style Win95
  1458. // CLASSES_ROOT setting instead
  1459. if (!*szMsg) {
  1460. GetPrivateProfileString((LPTSTR)szRMineIcon,
  1461. (LPTSTR)FROST_DEFSTR,
  1462. (LPTSTR)szNULL,
  1463. (LPTSTR)szMsg, MAX_MSGLEN,
  1464. (LPTSTR)szCurThemeFile);
  1465. }
  1466. // expand filename string as necessary
  1467. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1468. }
  1469. else { // get from system
  1470. // First try reading from the appropriate CURRENT_USER
  1471. // section for this platform.
  1472. szMsg[0] = TEXT('\0');
  1473. if (IsPlatformNT())
  1474. {
  1475. lstrcpy(szNTReg, c_szSoftwareClassesFmt);
  1476. lstrcat(szNTReg, szRMineIcon);
  1477. HandGet(HKEY_CURRENT_USER,
  1478. (LPTSTR)szNTReg,
  1479. (LPTSTR)szNULL, // null string for default value
  1480. (LPTSTR)szMsg);
  1481. }
  1482. else // Not NT
  1483. {
  1484. HandGet(HKEY_CURRENT_USER,
  1485. (LPTSTR)szCUMineIcon,
  1486. (LPTSTR)szNULL, // null string for default value
  1487. (LPTSTR)szMsg);
  1488. }
  1489. // If we didn't get a good string from CURRENT_USER branch
  1490. // try the CLASSES_ROOT branch instead.
  1491. if (!*szMsg) {
  1492. HandGet(HKEY_CLASSES_ROOT,
  1493. (LPTSTR)szRMineIcon,
  1494. (LPTSTR)szNULL, // null string for default value
  1495. (LPTSTR)szMsg);
  1496. }
  1497. }
  1498. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1499. // combine strings into data string to load up in
  1500. // owner-draw hasstrings listbox!
  1501. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  1502. // now, finally, go ahead and assign string to listbox
  1503. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  1504. //
  1505. // NETWORK NHBD ICON
  1506. LoadString(hInstApp, STR_PIC_NETHOOD,
  1507. (LPTSTR)szDispStr, MAX_STRLEN);
  1508. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  1509. // get filename if any
  1510. if (bThemed) { // get from theme
  1511. // Get the CURRENT_USER Net Neighborhood icon setting
  1512. GetPrivateProfileString((LPTSTR)szCUNhbdIcon, (LPTSTR)FROST_DEFSTR,
  1513. (LPTSTR)szNULL,
  1514. (LPTSTR)szMsg, MAX_MSGLEN,
  1515. (LPTSTR)szCurThemeFile);
  1516. // If the string is NULL, try the "old" style Win95
  1517. // CLASSES_ROOT setting instead
  1518. if (!*szMsg) {
  1519. GetPrivateProfileString((LPTSTR)szRNhbdIcon,
  1520. (LPTSTR)FROST_DEFSTR,
  1521. (LPTSTR)szNULL,
  1522. (LPTSTR)szMsg, MAX_MSGLEN,
  1523. (LPTSTR)szCurThemeFile);
  1524. }
  1525. // expand filename string as necessary
  1526. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1527. }
  1528. else { // get from system
  1529. // First try reading from the appropriate CURRENT_USER
  1530. // section for this platform.
  1531. szMsg[0] = TEXT('\0');
  1532. if (IsPlatformNT())
  1533. {
  1534. lstrcpy(szNTReg, c_szSoftwareClassesFmt);
  1535. lstrcat(szNTReg, szRNhbdIcon);
  1536. HandGet(HKEY_CURRENT_USER,
  1537. (LPTSTR)szNTReg,
  1538. (LPTSTR)szNULL, // null string for default value
  1539. (LPTSTR)szMsg);
  1540. }
  1541. else // Not NT
  1542. {
  1543. HandGet(HKEY_CURRENT_USER,
  1544. (LPTSTR)szCUNhbdIcon,
  1545. (LPTSTR)szNULL, // null string for default value
  1546. (LPTSTR)szMsg);
  1547. }
  1548. // If we didn't get a good string from CURRENT_USER branch
  1549. // try the CLASSES_ROOT branch instead.
  1550. if (!*szMsg) {
  1551. HandGet(HKEY_CLASSES_ROOT,
  1552. (LPTSTR)szRNhbdIcon,
  1553. (LPTSTR)szNULL, // null string for default value
  1554. (LPTSTR)szMsg);
  1555. }
  1556. }
  1557. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1558. // combine strings into data string to load up in
  1559. // owner-draw hasstrings listbox!
  1560. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  1561. // now, finally, go ahead and assign string to listbox
  1562. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  1563. //
  1564. // RECYCLE BIN FULL
  1565. LoadString(hInstApp, STR_PIC_RECBINFULL,
  1566. (LPTSTR)szDispStr, MAX_STRLEN);
  1567. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  1568. // get filename if any
  1569. if (bThemed) { // get from theme
  1570. // Get the CURRENT_USER Recycle Bin Full icon setting
  1571. GetPrivateProfileString((LPTSTR)szCUTrashIcon, (LPTSTR)szTrashFull,
  1572. (LPTSTR)szNULL,
  1573. (LPTSTR)szMsg, MAX_MSGLEN,
  1574. (LPTSTR)szCurThemeFile);
  1575. // If the string is NULL, try the "old" style Win95
  1576. // CLASSES_ROOT setting instead
  1577. if (!*szMsg) {
  1578. GetPrivateProfileString((LPTSTR)szRTrashIcon,
  1579. (LPTSTR)szTrashFull,
  1580. (LPTSTR)szNULL,
  1581. (LPTSTR)szMsg, MAX_MSGLEN,
  1582. (LPTSTR)szCurThemeFile);
  1583. }
  1584. // expand filename string as necessary
  1585. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1586. }
  1587. else { // get from system
  1588. // First try reading from the appropriate CURRENT_USER
  1589. // section for this platform.
  1590. szMsg[0] = TEXT('\0');
  1591. if (IsPlatformNT())
  1592. {
  1593. lstrcpy(szNTReg, c_szSoftwareClassesFmt);
  1594. lstrcat(szNTReg, szRTrashIcon);
  1595. HandGet(HKEY_CURRENT_USER,
  1596. (LPTSTR)szNTReg,
  1597. (LPTSTR)szTrashFull,
  1598. (LPTSTR)szMsg);
  1599. }
  1600. else // Not NT
  1601. {
  1602. HandGet(HKEY_CURRENT_USER,
  1603. (LPTSTR)szCUTrashIcon,
  1604. (LPTSTR)szTrashFull,
  1605. (LPTSTR)szMsg);
  1606. }
  1607. // If we didn't get a good string from CURRENT_USER branch
  1608. // try the CLASSES_ROOT branch instead.
  1609. if (!*szMsg) {
  1610. HandGet(HKEY_CLASSES_ROOT,
  1611. (LPTSTR)szRTrashIcon,
  1612. (LPTSTR)szTrashFull,
  1613. (LPTSTR)szMsg);
  1614. }
  1615. }
  1616. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1617. // combine strings into data string to load up in
  1618. // owner-draw hasstrings listbox!
  1619. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  1620. // now, finally, go ahead and assign string to listbox
  1621. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  1622. //
  1623. // RECYCLE BIN EMPTY
  1624. LoadString(hInstApp, STR_PIC_RECBINEMPTY,
  1625. (LPTSTR)szDispStr, MAX_STRLEN);
  1626. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  1627. // get filename if any
  1628. if (bThemed) { // get from theme
  1629. // Get the CURRENT_USER Recycle Bin Empty icon setting
  1630. GetPrivateProfileString((LPTSTR)szCUTrashIcon,
  1631. (LPTSTR)szTrashEmpty,
  1632. (LPTSTR)szNULL,
  1633. (LPTSTR)szMsg, MAX_MSGLEN,
  1634. (LPTSTR)szCurThemeFile);
  1635. // If the string is NULL, try the "old" style Win95
  1636. // CLASSES_ROOT setting instead
  1637. if (!*szMsg) {
  1638. GetPrivateProfileString((LPTSTR)szRTrashIcon,
  1639. (LPTSTR)szTrashEmpty,
  1640. (LPTSTR)szNULL,
  1641. (LPTSTR)szMsg, MAX_MSGLEN,
  1642. (LPTSTR)szCurThemeFile);
  1643. }
  1644. // expand filename string as necessary
  1645. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1646. }
  1647. else { // get from system
  1648. // First try reading from the appropriate CURRENT_USER
  1649. // section for this platform.
  1650. szMsg[0] = TEXT('\0');
  1651. if (IsPlatformNT())
  1652. {
  1653. lstrcpy(szNTReg, c_szSoftwareClassesFmt);
  1654. lstrcat(szNTReg, szRTrashIcon);
  1655. HandGet(HKEY_CURRENT_USER,
  1656. (LPTSTR)szNTReg,
  1657. (LPTSTR)szTrashEmpty,
  1658. (LPTSTR)szMsg);
  1659. }
  1660. else // Not NT
  1661. {
  1662. HandGet(HKEY_CURRENT_USER,
  1663. (LPTSTR)szCUTrashIcon,
  1664. (LPTSTR)szTrashEmpty,
  1665. (LPTSTR)szMsg);
  1666. }
  1667. // If we didn't get a good string from CURRENT_USER branch
  1668. // try the CLASSES_ROOT branch instead.
  1669. if (!*szMsg) {
  1670. HandGet(HKEY_CLASSES_ROOT,
  1671. (LPTSTR)szRTrashIcon,
  1672. (LPTSTR)szTrashEmpty,
  1673. (LPTSTR)szMsg);
  1674. }
  1675. }
  1676. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1677. // combine strings into data string to load up in
  1678. // owner-draw hasstrings listbox!
  1679. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  1680. // now, finally, go ahead and assign string to listbox
  1681. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  1682. //
  1683. // MY DOCUMENTS ICON
  1684. LoadString(hInstApp, STR_PIC_MYDOCS,
  1685. (LPTSTR)szDispStr, MAX_STRLEN);
  1686. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  1687. // get filename if any
  1688. if (bThemed) { // get from theme
  1689. // Get the CURRENT_USER My Documetns icon setting
  1690. GetPrivateProfileString((LPTSTR)szCUMyDocsIcon, (LPTSTR)FROST_DEFSTR,
  1691. (LPTSTR)szNULL,
  1692. (LPTSTR)szMsg, MAX_MSGLEN,
  1693. (LPTSTR)szCurThemeFile);
  1694. // If the string is NULL, try the "old" style Win95
  1695. // CLASSES_ROOT setting instead
  1696. if (!*szMsg) {
  1697. GetPrivateProfileString((LPTSTR)szRMyDocsIcon,
  1698. (LPTSTR)FROST_DEFSTR,
  1699. (LPTSTR)szNULL,
  1700. (LPTSTR)szMsg, MAX_MSGLEN,
  1701. (LPTSTR)szCurThemeFile);
  1702. }
  1703. // expand filename string as necessary
  1704. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1705. }
  1706. else { // get from system
  1707. // First try reading from the appropriate CURRENT_USER
  1708. // section for this platform.
  1709. szMsg[0] = TEXT('\0');
  1710. if (IsPlatformNT())
  1711. {
  1712. lstrcpy(szNTReg, c_szSoftwareClassesFmt);
  1713. lstrcat(szNTReg, szRMyDocsIcon);
  1714. HandGet(HKEY_CURRENT_USER,
  1715. (LPTSTR)szNTReg,
  1716. (LPTSTR)szNULL, // null string for default value
  1717. (LPTSTR)szMsg);
  1718. }
  1719. else // Not NT
  1720. {
  1721. HandGet(HKEY_CURRENT_USER,
  1722. (LPTSTR)szCUMyDocsIcon,
  1723. (LPTSTR)szNULL, // null string for default value
  1724. (LPTSTR)szMsg);
  1725. }
  1726. // If we didn't get a good string from CURRENT_USER branch
  1727. // try the CLASSES_ROOT branch instead.
  1728. if (!*szMsg) {
  1729. HandGet(HKEY_CLASSES_ROOT,
  1730. (LPTSTR)szRMyDocsIcon,
  1731. (LPTSTR)szNULL, // null string for default value
  1732. (LPTSTR)szMsg);
  1733. }
  1734. }
  1735. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1736. // combine strings into data string to load up in
  1737. // owner-draw hasstrings listbox!
  1738. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  1739. // now, finally, go ahead and assign string to listbox
  1740. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  1741. //
  1742. // SCREEN SAVER
  1743. LoadString(hInstApp, STR_PIC_SCRSAV,
  1744. (LPTSTR)szDispStr, MAX_STRLEN);
  1745. // CPLs don't check for success on LoadString in INITDIALOG, so OK!?
  1746. // get filename if any
  1747. if (bThemed) { // get from theme
  1748. GetPrivateProfileString((LPTSTR)szSS_Section, (LPTSTR)szSS_Key,
  1749. (LPTSTR)szNULL,
  1750. (LPTSTR)szMsg, MAX_MSGLEN,
  1751. (LPTSTR)szCurThemeFile);
  1752. // expand filename string as necessary
  1753. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  1754. // For NT with old (Plus95/98) theme files that refer to
  1755. // windows\system we should update string to say system32
  1756. if (IsPlatformNT()) ConfirmFile(szMsg, TRUE);
  1757. }
  1758. else { // get from system
  1759. GetPrivateProfileString((LPTSTR)szSS_Section, (LPTSTR)szSS_Key,
  1760. (LPTSTR)szNULL,
  1761. (LPTSTR)szMsg, MAX_MSGLEN,
  1762. (LPTSTR)szSS_File);
  1763. // make into nice long filename for display
  1764. if (FilenameToLong(szMsg, (LPTSTR)pValue))
  1765. lstrcpy(FileFromPath(szMsg), (LPTSTR)pValue);
  1766. }
  1767. // combine strings into data string to load up in
  1768. // owner-draw hasstrings listbox!
  1769. CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
  1770. // now, finally, go ahead and assign string to listbox
  1771. SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
  1772. //
  1773. // check them all for file existence. have to do here, no prev loop
  1774. //
  1775. for (iter = 0; iter < MAX_ETC_ITEMS; iter++) {
  1776. // get this item's listbox string
  1777. iRet = (int) SendMessage(hLBox, LB_GETTEXT, iter, (LPARAM)(LPTSTR)szMsg);
  1778. if (iRet == LB_ERR)
  1779. break; // past end of listbox items CONTINUE
  1780. // get the filename assoc with this item, if any
  1781. GetFileStr((LPTSTR)pValue, (LPTSTR)szMsg);
  1782. // store whether the file exists
  1783. bVisualExists[iter] = *pValue &&
  1784. (CF_NOTFOUND != ConfirmFile((LPTSTR)pValue, FALSE));
  1785. }
  1786. //
  1787. // setup initial focus conditions
  1788. SetFocus(hLBox);
  1789. SendMessage(hLBox, LB_SETCURSEL, 0, 0);
  1790. // need to ensure it gets initial update of cur file
  1791. PostMessage(hDlg, WM_COMMAND, MAKEWPARAM(LB_PICS, LBN_SELCHANGE),
  1792. MAKELPARAM(0, 0) );
  1793. } // var scope
  1794. break;
  1795. case WM_MEASUREITEM:
  1796. {
  1797. LPMEASUREITEMSTRUCT lpmis;
  1798. /* Set the height of the list box items. */
  1799. lpmis = (LPMEASUREITEMSTRUCT) lParam;
  1800. // lpmis->itemHeight = iItemHeight;
  1801. lpmis->itemHeight = 0; // DavidBa says they want these big default item hts
  1802. // Assert(iItemHeight > 0, TEXT("set non-positive item height for preview listbox!\n"));
  1803. // Assert(iItemHeight <= 0, TEXT("OK, set a positive item height for preview listbox!\n"));
  1804. }
  1805. break;
  1806. case WM_DRAWITEM:
  1807. { // var scope
  1808. TEXTMETRIC tm;
  1809. LPDRAWITEMSTRUCT lpdis;
  1810. int yTextOffset;
  1811. LPTSTR lpszFile;
  1812. HDC hdcMem;
  1813. HBITMAP hbmpOld;
  1814. lpdis = (LPDRAWITEMSTRUCT) lParam;
  1815. /* If there are no list box items, skip this message. */
  1816. if (lpdis->itemID == -1) {
  1817. break;
  1818. } // jdk: well, what about focus rect in empty lbox?
  1819. //
  1820. // Inits
  1821. // get the filename assoc with this item, if any
  1822. SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
  1823. (LPARAM)(LPTSTR)szMsg);
  1824. GetDisplayStr((LPTSTR)szMsg, (LPTSTR)szMsg); // Ok src and dst same
  1825. // you now have "displaystr\0filename" in szMsg[]
  1826. lpszFile = (LPTSTR)(szMsg + lstrlen((LPTSTR)szMsg) + 1);
  1827. //
  1828. // draw right background color
  1829. if (lpdis->itemState & ODS_SELECTED) {
  1830. // if item is selected, draw highlight background here
  1831. FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
  1832. GetSysColorBrush(COLOR_HIGHLIGHT));
  1833. // set text color to highlight text
  1834. SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
  1835. SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  1836. }
  1837. else { // not selected
  1838. // need to do normal background fill to undo prev selection
  1839. FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
  1840. GetSysColorBrush(COLOR_WINDOW));
  1841. // set text color to foreground
  1842. SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
  1843. SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
  1844. }
  1845. // if there is a file associated with this item
  1846. if (*lpszFile) {
  1847. HBITMAP hbmpLeading;
  1848. BITMAP bmLeading;
  1849. //
  1850. // find the right leading bitmap: checkmark or question mark
  1851. if (bVisualExists[lpdis->itemID]) {
  1852. hbmpLeading = hbmpCheck;
  1853. bmLeading = bmCheck;
  1854. }
  1855. else {
  1856. hbmpLeading = hbmpQ;
  1857. bmLeading = bmQ;
  1858. }
  1859. //
  1860. // paint in the leading bitmap!
  1861. hdcMem = CreateCompatibleDC(lpdis->hDC);
  1862. if (hdcMem)
  1863. {
  1864. hbmpOld = SelectObject(hdcMem, hbmpLeading);
  1865. // if item height is less than bitmap height
  1866. if (lpdis->rcItem.bottom - lpdis->rcItem.top < bmLeading.bmHeight)
  1867. {
  1868. // stretch down bitmap size to fit
  1869. StretchBlt(lpdis->hDC,
  1870. lpdis->rcItem.left, lpdis->rcItem.top,
  1871. lpdis->rcItem.bottom - lpdis->rcItem.top, // width = height
  1872. lpdis->rcItem.bottom - lpdis->rcItem.top,
  1873. hdcMem, 0, 0, bmLeading.bmWidth, bmLeading.bmHeight, SRCCOPY);
  1874. }
  1875. else // item height taller than checkmark bitmap
  1876. {
  1877. // just center vertically
  1878. BitBlt(lpdis->hDC,
  1879. lpdis->rcItem.left,
  1880. lpdis->rcItem.top +
  1881. (lpdis->rcItem.bottom - lpdis->rcItem.top - bmLeading.bmHeight)/2,
  1882. bmLeading.bmWidth, bmLeading.bmHeight,
  1883. hdcMem, 0, 0, SRCCOPY);
  1884. }
  1885. SelectObject(hdcMem, hbmpOld);
  1886. DeleteDC(hdcMem);
  1887. }
  1888. // who cares
  1889. // Assert(lpdis->rcItem.bottom - lpdis->rcItem.top == iItemHeight,
  1890. // TEXT("MEASUREITEM and DRAWITEM have different heights!\n"));
  1891. }
  1892. //
  1893. // now draw the display string for this item
  1894. // figure y offset to vert center text in draw item
  1895. GetTextMetrics(lpdis->hDC, &tm);
  1896. yTextOffset = (lpdis->rcItem.bottom - lpdis->rcItem.top - tm.tmHeight) / 2;
  1897. Assert(yTextOffset >= 0, TEXT("negative text vert offset in DRAWITEM\n"));
  1898. if (yTextOffset < 0) yTextOffset = 0;
  1899. // do the out
  1900. SetBkMode(lpdis->hDC, TRANSPARENT);
  1901. TextOut(lpdis->hDC,
  1902. lpdis->rcItem.left + xTextOffset,
  1903. lpdis->rcItem.top + yTextOffset,
  1904. (LPTSTR)szMsg, lstrlen((LPTSTR)szMsg));
  1905. //
  1906. // if item is selected, draw a focus rect
  1907. if (lpdis->itemState & ODS_FOCUS) {
  1908. DrawFocusRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem));
  1909. }
  1910. } // var scope
  1911. break;
  1912. case WM_COMMAND:
  1913. switch ((int)LOWORD(wParam)) {
  1914. case LB_PICS:
  1915. // if new selection in listbox
  1916. if (HIWORD(wParam) == LBN_SELCHANGE) {
  1917. int iSeln, ilen;
  1918. // get new selection if any
  1919. iSeln = (int)SendDlgItemMessage(hDlg, LB_PICS, LB_GETCURSEL, 0, 0);
  1920. if (LB_ERR == iSeln)
  1921. break; // no selection EXIT
  1922. // get selection text
  1923. SendDlgItemMessage(hDlg, LB_PICS, LB_GETTEXT,
  1924. (WPARAM)iSeln, (LPARAM)(LPTSTR)szMsg);
  1925. // update global current filename string
  1926. GetFileStr(szCurPreviewFile, szMsg);
  1927. // reset dialog static text of filename string
  1928. if (iSeln == SCRSAV_NDX) {
  1929. // if you can get a long filename, then use it
  1930. if (FilenameToLong((LPTSTR)szCurPreviewFile, (LPTSTR)szMsg))
  1931. lstrcpy(FileFromPath((LPTSTR)szCurPreviewFile), (LPTSTR)szMsg);
  1932. SetDlgItemFile(hDlg, TXT_FILENAME, szCurPreviewFile);
  1933. }
  1934. else
  1935. SetDlgItemFile(hDlg, TXT_FILENAME, szCurPreviewFile);
  1936. // and scroll end into view
  1937. ilen = lstrlen((LPTSTR)szCurPreviewFile);
  1938. SendDlgItemMessage(hDlg, TXT_FILENAME, EM_SETSEL,
  1939. (WPARAM)0, MAKELPARAM(-1, ilen));
  1940. //
  1941. // Update Image
  1942. //
  1943. // init by destroying old
  1944. if (hCurImage) DestroyCursor(hCurImage);
  1945. hCurImage = NULL;
  1946. // get new image...
  1947. if (*szCurPreviewFile) {
  1948. // ... unless the screen saver was selected
  1949. if (iSeln != SCRSAV_NDX) {
  1950. int index;
  1951. LPTSTR lpszIndex;
  1952. #ifdef UNICODE
  1953. char szTempA[10];
  1954. #endif
  1955. // load as icon; works for bmps too
  1956. // init: copy global filename to destructive-OK location
  1957. lstrcpy((LPTSTR)szMsg, (LPTSTR)szCurPreviewFile);
  1958. // may have index into file. format: "file,index"
  1959. lpszIndex = FindChar((LPTSTR)szMsg, TEXT(','));
  1960. if (*lpszIndex) { // if found a comma, then indexed icon
  1961. #ifdef UNICODE
  1962. wcstombs(szTempA, CharNext(lpszIndex), sizeof(szTempA));
  1963. index = latoi(szTempA);
  1964. #else
  1965. index = latoi(CharNext(lpszIndex));
  1966. #endif
  1967. *lpszIndex = 0; // got index then null term filename in szMsg
  1968. }
  1969. else { // just straight icon file or no index
  1970. index = 0;
  1971. }
  1972. // OK, now you can do the load!
  1973. ExtractPlusColorIcon(szMsg, index, &((HICON)hCurImage), 0, 0);
  1974. }
  1975. // else SCREEN SAVER: just leave hCurImage NULL for blank
  1976. }
  1977. // set image to static ctl, even if null: null clears prev
  1978. SendDlgItemMessage(hDlg, RECT_PREVIEW, STM_SETICON,
  1979. (WPARAM)hCurImage, (LPARAM)0);
  1980. // if it's the screen saver, then start up the preview
  1981. if (iSeln == SCRSAV_NDX) {
  1982. // TBA
  1983. }
  1984. #if 0 // this is when we painted the cursor by ourself
  1985. // force repaint of preview area
  1986. InvalidateRect(hDlg, (LPRECT)&rPreview, TRUE);
  1987. #endif
  1988. }
  1989. break;
  1990. // case PB_TEST:
  1991. // break;
  1992. }
  1993. break;
  1994. #if 0 // this is when we painted the cursor by ourself
  1995. case WM_PAINT:
  1996. BeginPaint(hDlg, &ps);
  1997. //
  1998. // preview area
  1999. DrawEdge(ps.hdc, (LPRECT)&rPreview, EDGE_SUNKEN, BF_RECT); // always edge
  2000. // if there's a file to preview
  2001. if (*szCurPreviewFile) {
  2002. // add the cursor
  2003. if (hCurCursor)
  2004. DrawIcon(ps.hdc,
  2005. rPreview.left + (rPreview.right-rPreview.left-xCursor)/2,
  2006. rPreview.top + (rPreview.bottom-rPreview.top-yCursor)/2,
  2007. hCurCursor);
  2008. }
  2009. EndPaint(hDlg, &ps);
  2010. break;
  2011. #endif
  2012. case WM_NOTIFY:
  2013. switch ( ((NMHDR FAR *)lParam)->code) {
  2014. // OK or Apply button pressed
  2015. case PSN_APPLY:
  2016. // apply any changes made on this page
  2017. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); // accept changes
  2018. break;
  2019. // cancel button pressed
  2020. case PSN_RESET:
  2021. // don't accept any of the changes made on this page
  2022. break;
  2023. case PSN_SETACTIVE:
  2024. break;
  2025. case PSN_KILLACTIVE:
  2026. // need to say that it's OK by us to lose the activation
  2027. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); // OK to kill focus now
  2028. break;
  2029. }
  2030. break;
  2031. case WM_HELP:
  2032. {
  2033. LPHELPINFO lphi;
  2034. lphi = (LPHELPINFO)lParam;
  2035. if (lphi->iContextType == HELPINFO_WINDOW) {
  2036. WinHelp(lphi->hItemHandle, (LPTSTR)szHelpFile, HELP_WM_HELP,
  2037. (DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaPicsDlg));
  2038. }
  2039. }
  2040. break;
  2041. case WM_CONTEXTMENU:
  2042. WinHelp((HWND)wParam, (LPTSTR)szHelpFile, HELP_CONTEXTMENU,
  2043. (DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaPicsDlg));
  2044. break;
  2045. default:
  2046. return(FALSE); // didn't process message
  2047. break;
  2048. }
  2049. return TRUE; // processed message
  2050. }
  2051. //
  2052. // CreateDataStr
  2053. // GetFileStr
  2054. // GetDisplayStr
  2055. //
  2056. // When initializing the owner-draw listbox in each of these dialogs,
  2057. // they are filled with strings of the form:
  2058. // displaystring;filename
  2059. // where "filename" is the associated full-path filename string AND CAN BE NULL
  2060. // and where "displaystring" is the string that appears in the listbox.
  2061. //
  2062. // CreateDataStr() puts the two pieces together into one string to store.
  2063. // The other two functions retrieve one of the pieces from the concatenated
  2064. // stored string.
  2065. //
  2066. TCHAR szSepStr[] = TEXT(";"); // separator character, as null-term str
  2067. // Input: file and display strings NON-DESTRUCTIVE TO INPUT
  2068. // Output: combined data string
  2069. void CreateDataStr(LPTSTR lpData, LPTSTR lpDisp, LPTSTR lpFile)
  2070. {
  2071. lstrcpy(lpData, lpDisp); // filename can be null
  2072. lstrcat(lpData, (LPTSTR)szSepStr);
  2073. lstrcat(lpData, lpFile);
  2074. }
  2075. // Input: combined data string NON-DESTRUCTIVE TO INPUT
  2076. // Output: display string
  2077. void GetDisplayStr(LPTSTR lpDisp, LPTSTR lpData)
  2078. {
  2079. LPTSTR lpScan, lpCopy;
  2080. // just do it all in a loop
  2081. for (lpScan = lpData, lpCopy = lpDisp;
  2082. *lpScan && // paranoid
  2083. (*lpScan != szSepStr[0]); // stop when you hit the sep char
  2084. lpScan++, lpCopy++) {
  2085. *lpCopy = *lpScan; // copy over chars one by one
  2086. }
  2087. // null term filename result to finish
  2088. *lpCopy = 0; // null filename yields lpDisp[0] = 0
  2089. }
  2090. // Input: combined data string NON-DESTRUCTIVE TO INPUT
  2091. // Output: file string
  2092. void GetFileStr(LPTSTR lpFile, LPTSTR lpData)
  2093. {
  2094. LPTSTR lpScan;
  2095. // just loop until you hit sep char
  2096. for (lpScan = lpData;
  2097. *lpScan && // paranoid
  2098. (*lpScan != szSepStr[0]); // stop when you hit the sep char
  2099. lpScan++) { } // do nothing
  2100. // now just take the rest of the string and return it
  2101. if (*lpScan) // paranoid
  2102. lstrcpy(lpFile, ++lpScan); // should never be nullstr, but that works too
  2103. else
  2104. *lpFile = 0; // 'impossible' error case
  2105. }
  2106. #ifdef FOOBAR
  2107. // Sets the dialog item to the path name as "prettied" by the shell.
  2108. // jdk 6/95: prev funtion just showed filename no path!
  2109. #endif
  2110. //
  2111. // SetDlgItemFile
  2112. //
  2113. // The whole point of these dialogs is to let the user see where the
  2114. // constituent resource files of a theme are, so we need to include the
  2115. // full pathnames. No reason not to pretty up the filename part, though.
  2116. //
  2117. // FUTURE: we can check here for indexed icon files, and make some
  2118. // more user-readable form of it.
  2119. // e.g. iconfile.dll,17 --> iconfile.dll [icon #17]
  2120. //
  2121. void PASCAL SetDlgItemFile(HWND hwnd, UINT DlgItem, LPCTSTR lpszPath)
  2122. {
  2123. TCHAR szFullPath[MAX_PATH+1];
  2124. TCHAR szPrettyFilename[MAX_PATH+1];
  2125. LPTSTR lpszFilename;
  2126. // inits
  2127. lstrcpy(szFullPath, lpszPath);
  2128. lpszFilename = FileFromPath(szFullPath);
  2129. // prettify via API if you can
  2130. if (*lpszPath != TEXT('\0')) {
  2131. // what does this do? it gives you the filename with the user's options
  2132. // e.g. Explorer View/Options Show/Don'tShow extensions
  2133. GetFileTitle(lpszPath, szPrettyFilename, ARRAYSIZE(szPrettyFilename));
  2134. lstrcpy(lpszFilename, szPrettyFilename);
  2135. }
  2136. // do it
  2137. SetDlgItemText(hwnd, DlgItem, szFullPath);
  2138. }