Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

881 lines
26 KiB

  1. /* BACKDLG.C
  2. **
  3. ** Copyright (C) Microsoft, 1993, All Rights Reserved.
  4. **
  5. **
  6. ** History:
  7. **
  8. */
  9. #include "precomp.h"
  10. #include "shlwapi.h"
  11. #define MAX_RHS 256
  12. TCHAR g_szPattern[] = TEXT("pattern");
  13. TCHAR szDesktop[] = TEXT("desktop");
  14. TCHAR szWallpaper[] = TEXT("wallpaper");
  15. TCHAR szTileWall[] = TEXT("TileWallpaper");
  16. TCHAR szDotBMP[] = TEXT(".bmp");
  17. TCHAR szBMP[] = TEXT("\\*.bmp");
  18. TCHAR szDefExt[] = TEXT("bmp");
  19. BOOL g_bValidBitmap = FALSE; // the currently selected wallpaper is valid
  20. TCHAR g_szCurPattern[MAX_PATH];
  21. TCHAR g_szCurWallpaper[MAX_PATH];
  22. TCHAR g_szTempItem[MAX_PATH]; // which is more of a waste, stack or data?
  23. BOOL g_Back_bInit = TRUE; // assume we are in initialization process
  24. BOOL g_Back_bChanged = FALSE; // changes have been made
  25. static void NukeExt(LPTSTR sz);
  26. static LPTSTR NEAR PASCAL NiceName(LPTSTR sz);
  27. INT_PTR CALLBACK PatternDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
  28. #include "help.h"
  29. const static DWORD FAR aBckgrndHelpIds[] = {
  30. IDC_NO_HELP_1, IDH_COMM_GROUPBOX,
  31. IDC_NO_HELP_2, IDH_COMM_GROUPBOX,
  32. IDC_PATLIST, IDH_DSKTPBACKGROUND_PATTLIST,
  33. IDC_EDITPAT, IDH_DSKTPBACKGROUND_EDITPAT,
  34. IDC_WALLLIST, IDH_DSKTPBACKGROUND_WALLLIST,
  35. IDC_BROWSEWALL, IDH_DSKTPBACKGROUND_BROWSE,
  36. IDC_TXT_DISPLAY, IDH_DSKTPBACKGROUND_DISPLAY,
  37. IDC_TILE, IDH_DSKTPBACKGROUND_TILE,
  38. IDC_CENTER, IDH_DSKTPBACKGROUND_CENTER,
  39. IDC_BACKPREV, IDH_DSKTPBACKGROUND_MONITOR,
  40. 0, 0
  41. };
  42. static const TCHAR szRegStr_Desktop[] = REGSTR_PATH_DESKTOP;
  43. static const TCHAR szRegStr_Setup[] = REGSTR_PATH_SETUP TEXT("\\Setup");
  44. static const TCHAR szSharedDir[] = TEXT("SharedDir");
  45. // we're mainly trying to filter multilingual upgrade cases
  46. // where the text for "(None)" is unpredictable
  47. //
  48. BOOL NEAR PASCAL IsProbablyAValidPattern( LPCTSTR pat )
  49. {
  50. BOOL sawanumber = FALSE;
  51. while( *pat )
  52. {
  53. if( ( *pat < TEXT('0') ) || ( *pat > TEXT('9') ) )
  54. {
  55. // it's not a number, it better be a space
  56. if( *pat != TEXT(' ') )
  57. return FALSE;
  58. }
  59. else
  60. sawanumber = TRUE;
  61. // NOTE: we avoid the need for AnsiNext by only advancing on US TCHARs
  62. pat++;
  63. }
  64. // TRUE if we saw at least one digit and there were only digits and spaces
  65. return sawanumber;
  66. }
  67. #ifdef DEBUG
  68. #define REG_INTEGER 1000
  69. int fTraceRegAccess = 0;
  70. void NEAR PASCAL RegDetails(int iWrite, HKEY hk, LPCTSTR lpszSubKey,
  71. LPCTSTR lpszValueName, DWORD dwType, LPTSTR lpszString, int iValue)
  72. {
  73. TCHAR Buff[256];
  74. TCHAR far *lpszReadWrite[] = { TEXT("DESK.CPL:Read"), TEXT("DESK.CPL:Write") };
  75. if(!fTraceRegAccess)
  76. return;
  77. switch(dwType)
  78. {
  79. case REG_SZ:
  80. StringCchPrintf(Buff, ARRAYSIZE(Buff), TEXT("%s String:hk=%#08lx, %s:%s=%s\n\r"), lpszReadWrite[iWrite],
  81. hk, lpszSubKey, lpszValueName, lpszString);
  82. break;
  83. case REG_INTEGER:
  84. StringCchPrintf(Buff, ARRAYSIZE(Buff), TEXT("%s int:hk=%#08lx, %s:%s=%d\n\r"), lpszReadWrite[iWrite],
  85. hk, lpszSubKey, lpszValueName, iValue);
  86. break;
  87. case REG_BINARY:
  88. StringCchPrintf(Buff, ARRAYSIZE(Buff), TEXT("%s Binary:hk=%#08lx, %s:%s=%#0lx;DataSize:%d\r\n"), lpszReadWrite[iWrite],
  89. hk, lpszSubKey, lpszValueName, lpszString, iValue);
  90. break;
  91. }
  92. OutputDebugString(Buff);
  93. }
  94. #endif // DEBUG
  95. //---------------------------------------------------------------------------
  96. // GetIntFromSubKey
  97. // hKey is the handle to the subkey
  98. // (already pointing to the proper location).
  99. //---------------------------------------------------------------------------
  100. int NEAR PASCAL GetIntFromSubkey(HKEY hKey, LPCTSTR lpszValueName, int iDefault)
  101. {
  102. TCHAR szValue[20];
  103. DWORD dwSizeofValueBuff = sizeof(szValue);
  104. DWORD dwType;
  105. int iRetValue = iDefault;
  106. if((RegQueryValueEx(hKey, lpszValueName, NULL, &dwType,
  107. (LPBYTE)szValue,
  108. &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff)
  109. {
  110. // BOGUS: This handles only the string type entries now!
  111. if(dwType == REG_SZ)
  112. iRetValue = (int)StrToInt(szValue);
  113. #ifdef DEBUG
  114. else
  115. OutputDebugString(TEXT("String type expected from Registry\n\r"));
  116. #endif
  117. }
  118. #ifdef DEBUG
  119. RegDetails(0, hKey, TEXT(""), lpszValueName, REG_INTEGER, NULL, iRetValue);
  120. #endif
  121. return(iRetValue);
  122. }
  123. //---------------------------------------------------------------------------
  124. // GetIntFromReg()
  125. // Opens the given subkey and gets the int value.
  126. //---------------------------------------------------------------------------
  127. int NEAR PASCAL GetIntFromReg(HKEY hKey,
  128. LPCTSTR lpszSubkey,
  129. LPCTSTR lpszNameValue, int iDefault)
  130. {
  131. HKEY hk;
  132. int iRetValue = iDefault;
  133. // See if the key is present.
  134. if(RegOpenKeyEx(hKey, lpszSubkey, 0, KEY_READ, &hk) == ERROR_SUCCESS)
  135. {
  136. iRetValue = GetIntFromSubkey(hk, lpszNameValue, iDefault);
  137. RegCloseKey(hk);
  138. }
  139. return(iRetValue);
  140. }
  141. BOOL NEAR PASCAL GetStringFromReg(HKEY hKey,
  142. LPCTSTR lpszSubkey,
  143. LPCTSTR lpszValueName,
  144. LPCTSTR lpszDefault,
  145. LPTSTR lpszValue,
  146. DWORD cchSizeofValueBuff)
  147. {
  148. HKEY hk;
  149. DWORD dwType;
  150. BOOL fSuccess = FALSE;
  151. DWORD cbValueBuff = cchSizeofValueBuff * sizeof(TCHAR);
  152. // See if the key is present.
  153. if(RegOpenKeyEx(hKey, lpszSubkey, 0, KEY_READ, &hk) == ERROR_SUCCESS)
  154. {
  155. if((RegQueryValueEx(hk, lpszValueName, NULL, &dwType,
  156. (LPBYTE)lpszValue,
  157. &cbValueBuff) == ERROR_SUCCESS) && cbValueBuff)
  158. {
  159. // BOGUS: This handles only the string type entries now!
  160. #ifdef DEBUG
  161. if(dwType != REG_SZ)
  162. {
  163. OutputDebugString(TEXT("String type expected from Registry\n\r"));
  164. }
  165. else
  166. #endif
  167. fSuccess = TRUE;
  168. }
  169. RegCloseKey(hk);
  170. }
  171. // If failure, use the default string.
  172. if(!fSuccess && lpszDefault)
  173. {
  174. StringCchCopy(lpszValue, cchSizeofValueBuff, lpszDefault);
  175. }
  176. #ifdef DEBUG
  177. RegDetails(0, hKey, lpszSubkey, lpszValueName, REG_SZ, lpszValue, 0);
  178. #endif
  179. return(fSuccess);
  180. }
  181. //---------------------------------------------------------------------------
  182. //
  183. // UpdateRegistry:
  184. // This updates a given value of any data type at a given
  185. // location in the registry.
  186. //
  187. // The value name is passed in as an Id to a string in USER's String table.
  188. //
  189. //---------------------------------------------------------------------------
  190. BOOL FAR PASCAL UpdateRegistry(HKEY hKey,
  191. LPCTSTR lpszSubkey,
  192. LPCTSTR lpszValueName,
  193. DWORD dwDataType,
  194. LPVOID lpvData,
  195. DWORD dwDataSize)
  196. {
  197. HKEY hk;
  198. if (RegCreateKeyEx(hKey, lpszSubkey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hk, NULL) == ERROR_SUCCESS)
  199. {
  200. RegSetValueEx(hk, lpszValueName,
  201. 0L, dwDataType,
  202. (const UCHAR *) lpvData,
  203. dwDataSize);
  204. #ifdef DEBUG
  205. RegDetails(1, hKey, lpszSubkey, lpszValueName, dwDataType, (LPTSTR)lpvData, (int)dwDataSize);
  206. #endif
  207. RegCloseKey(hk);
  208. return(TRUE);
  209. }
  210. return(FALSE);
  211. }
  212. /*-------------------------------------------------------------
  213. ** force the update of the preview.
  214. **-------------------------------------------------------------*/
  215. void NEAR PASCAL UpdatePreview(HWND hDlg, WORD flags)
  216. {
  217. if (IsDlgButtonChecked(hDlg, IDC_TILE))
  218. flags |= BP_TILE;
  219. SendDlgItemMessage(hDlg, IDC_BACKPREV, WM_SETBACKINFO, flags, 0L);
  220. if (!g_Back_bInit && !g_Back_bChanged)
  221. {
  222. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  223. g_Back_bChanged = TRUE;
  224. }
  225. }
  226. /*------------------------------------------------------------------
  227. ** read in all of the entries (LHS only) in a section.
  228. **
  229. ** return: handle to local (fixed) memory containing names
  230. **------------------------------------------------------------------*/
  231. HANDLE PASCAL GetSection(LPTSTR lpIniFile, LPTSTR lpSection)
  232. {
  233. int nCount;
  234. int cchSize = 4096;
  235. int cbSize = (cchSize * sizeof(TCHAR));
  236. HANDLE hLocal, hTemp;
  237. if (!(hLocal = LocalAlloc(LPTR, cbSize)))
  238. return(NULL);
  239. while (1)
  240. {
  241. nCount = GetPrivateProfileString(lpSection, NULL, g_szNULL, (LPTSTR)hLocal, cchSize, lpIniFile);
  242. if (nCount < (cchSize-1))
  243. break;
  244. // need to grow the buffer
  245. cchSize += 2048;
  246. cbSize = (cchSize * sizeof(TCHAR));
  247. hTemp = hLocal;
  248. if (!(hLocal = LocalReAlloc(hTemp, cbSize, LMEM_MOVEABLE)))
  249. {
  250. LocalFree(hTemp);
  251. return(NULL);
  252. }
  253. }
  254. return(hLocal);
  255. }
  256. static void NukeExt(LPTSTR sz)
  257. {
  258. int len;
  259. len = lstrlen(sz);
  260. if (len > 4 && sz[len-4] == TEXT('.'))
  261. sz[len-4] = 0;
  262. }
  263. static void NameOnly(LPTSTR sz)
  264. {
  265. LPTSTR p = sz;
  266. LPTSTR s = NULL;
  267. while( *p )
  268. {
  269. if( ( *p == TEXT('\\') ) || ( *p == TEXT(':') ) )
  270. s = p;
  271. p++;
  272. }
  273. if( s )
  274. {
  275. p = sz;
  276. while( *s++ )
  277. {
  278. *p++ = *s;
  279. }
  280. }
  281. }
  282. static BOOL PathOnly(LPTSTR sz)
  283. {
  284. LPTSTR p = sz;
  285. LPTSTR s = NULL;
  286. while( *p )
  287. {
  288. if( *p == TEXT('\\') )
  289. {
  290. s = p;
  291. }
  292. else if( *p == TEXT(':') )
  293. {
  294. s = p + 1;
  295. }
  296. p++;
  297. }
  298. if( s )
  299. {
  300. if( s == sz )
  301. s++;
  302. *s = TEXT('\0');
  303. return TRUE;
  304. }
  305. return FALSE;
  306. }
  307. static LPTSTR NEAR PASCAL NiceName(LPTSTR sz)
  308. {
  309. NukeExt(sz);
  310. if (IsCharUpper(sz[0]) && IsCharUpper(sz[1]))
  311. {
  312. CharLower(sz);
  313. CharUpperBuff(sz, 1);
  314. }
  315. return sz;
  316. }
  317. int NEAR PASCAL AddAFileToLB( HWND hwndList, LPCTSTR szDir, LPTSTR szFile )
  318. {
  319. int index = LB_ERR;
  320. int nAlloc = MAX_PATH;
  321. LPTSTR szPath = (LPTSTR)LocalAlloc( LPTR, nAlloc * sizeof(TCHAR) );
  322. if( szPath )
  323. {
  324. if( szDir )
  325. {
  326. StringCchPrintf(szPath, nAlloc, TEXT("%s\\"), szDir);
  327. }
  328. else
  329. *szPath = TEXT('\0');
  330. StringCchCat( (LPTSTR)szPath, nAlloc, szFile );
  331. NameOnly( szFile );
  332. NiceName( szFile );
  333. index = (int)SendMessage( hwndList, LB_ADDSTRING, 0,
  334. (LPARAM)(LPTSTR)szFile );
  335. if( index >= 0 )
  336. {
  337. SendMessage( hwndList, LB_SETITEMDATA, (WPARAM)index,
  338. (LPARAM)(LPTSTR)szPath );
  339. }
  340. else
  341. LocalFree( (HANDLE)szPath );
  342. }
  343. return index;
  344. }
  345. void NEAR PASCAL AddFilesToLB(HWND hwndList, LPTSTR pszDir, LPTSTR szSpec)
  346. {
  347. WIN32_FIND_DATA fd;
  348. HANDLE h;
  349. TCHAR szBuf[MAX_PATH];
  350. StringCchPrintf(szBuf, ARRAYSIZE(szBuf), TEXT("%s%s"), pszDir, szSpec);
  351. h = FindFirstFile(szBuf, &fd);
  352. if (h != INVALID_HANDLE_VALUE)
  353. {
  354. do
  355. {
  356. AddAFileToLB(hwndList, pszDir, fd.cFileName);
  357. }
  358. while (FindNextFile(h, &fd));
  359. FindClose(h);
  360. }
  361. }
  362. /*-------------------------------------------------------------
  363. ** set a new wallpaper and notify the right places.
  364. **
  365. ** the new name is in g_szCurWallpaper
  366. **-------------------------------------------------------------*/
  367. void NEAR PASCAL SetNewWallpaper(HWND hDlg, LPTSTR szFile, int cchFile, BOOL bCanAdd)
  368. {
  369. HWND hwndList = GetDlgItem(hDlg, IDC_WALLLIST);
  370. if(!szFile || !lstrcmpi(szFile, g_szNone))
  371. szFile = TEXT("");
  372. if(szFile[1] == TEXT(':'))
  373. {
  374. TCHAR szDrive[3];
  375. TCHAR szNet[MAX_PATH];
  376. ULONG lenNet = ARRAYSIZE(szNet);
  377. StringCchCopy(szDrive, ARRAYSIZE(szDrive), szFile);
  378. if ((NO_ERROR == WNetGetConnection(szDrive, szNet, &lenNet)) &&
  379. (szNet[0] == TEXT('\\')) && (szNet[1] == TEXT('\\')))
  380. {
  381. StringCchCat(szNet, ARRAYSIZE(szNet), szFile+2);
  382. StringCchCopy(szFile, cchFile, szNet);
  383. }
  384. }
  385. StringCchCopy(g_szCurWallpaper, ARRAYSIZE(g_szCurWallpaper), szFile);
  386. UpdatePreview(hDlg, BP_NEWWALL);
  387. if(bCanAdd && *szFile && g_bValidBitmap)
  388. {
  389. TCHAR szName[MAX_PATH];
  390. int sel;
  391. StringCchCopy(szName, ARRAYSIZE(szName), szFile);
  392. NameOnly(szName);
  393. NiceName(szName);
  394. if ((sel = (int)SendMessage(hwndList, LB_FINDSTRINGEXACT, (WPARAM)-1,
  395. (LPARAM)(LPTSTR)szName)) == LB_ERR)
  396. {
  397. sel = AddAFileToLB(hwndList, NULL, szFile);
  398. }
  399. SendMessage(hwndList, LB_SETCURSEL, (WPARAM)sel, 0L);
  400. }
  401. BOOL bEnable = (*szFile) ? TRUE : FALSE;
  402. EnableWindow( GetDlgItem(hDlg, IDC_TXT_DISPLAY), bEnable );
  403. EnableWindow( GetDlgItem(hDlg, IDC_TILE), bEnable );
  404. EnableWindow( GetDlgItem(hDlg, IDC_CENTER), bEnable );
  405. }
  406. void NEAR PASCAL InitBackgroundDialog(HWND hDlg)
  407. {
  408. HANDLE hSection;
  409. HWND hwndList;
  410. LPTSTR pszBuffer;
  411. TCHAR szBuf[MAX_PATH];
  412. TCHAR szCurPatBits[MAX_PATH];
  413. g_szCurPattern[0] = 0;
  414. g_szCurWallpaper[0] = 0;
  415. g_Back_bChanged = FALSE;
  416. /*
  417. ** initialize the pattern list
  418. */
  419. // get the current pattern.
  420. szCurPatBits[0] = 0;
  421. GetStringFromReg(HKEY_CURRENT_USER, szRegStr_Desktop,
  422. g_szPattern, g_szNULL, szCurPatBits,
  423. ARRAYSIZE(szCurPatBits));
  424. if (!(*szCurPatBits))
  425. StringCchCopy(g_szCurPattern, ARRAYSIZE(g_szCurPattern), g_szNone);
  426. else
  427. *g_szCurPattern = 0;
  428. hwndList = GetDlgItem(hDlg, IDC_PATLIST);
  429. if (hSection = GetSection(g_szControlIni, g_szPatterns))
  430. {
  431. BOOL bAddedNone = FALSE;
  432. /* Put the patterns into the combo box. */
  433. for (pszBuffer = (LPTSTR) LocalLock(hSection); *pszBuffer; pszBuffer += (lstrlen(pszBuffer)+1))
  434. {
  435. if (GetPrivateProfileString(g_szPatterns, pszBuffer, g_szNULL, szBuf, ARRAYSIZE(szBuf), g_szControlIni))
  436. {
  437. BOOL bIsNone = !bAddedNone && !lstrcmpi( g_szNone, szBuf );
  438. /* if there's a right-hand side, add it to the list box */
  439. if( bIsNone || IsProbablyAValidPattern( szBuf ) )
  440. {
  441. if( bIsNone )
  442. bAddedNone = TRUE;
  443. SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pszBuffer);
  444. // if haven't found current pattern name, maybe this is it.
  445. if (!(*g_szCurPattern) && (!lstrcmpi(szBuf, szCurPatBits)))
  446. {
  447. // same pattern bits. we have a name
  448. StringCchCopy(g_szCurPattern, ARRAYSIZE(g_szCurPattern), pszBuffer);
  449. }
  450. }
  451. }
  452. }
  453. LocalUnlock(hSection);
  454. LocalFree(hSection);
  455. }
  456. // if our patternTEXT('s bits weren')t in the list, use a fake name
  457. if (!(*g_szCurPattern))
  458. LoadString(hInstance, IDS_UNLISTEDPAT, g_szCurPattern, ARRAYSIZE(g_szCurPattern));
  459. SendMessage(hwndList, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)g_szCurPattern);
  460. UpdatePreview(hDlg, BP_NEWPAT);
  461. // exclude TEXT("none") pattern
  462. if( (int)SendDlgItemMessage(hDlg,IDC_PATLIST,LB_GETCURSEL,0,0l) <= 0 )
  463. {
  464. HWND epat = GetDlgItem( hDlg, IDC_EDITPAT );
  465. if( GetFocus() == epat )
  466. {
  467. SendMessage( hDlg, WM_NEXTDLGCTL,
  468. (WPARAM)GetDlgItem( hDlg, IDC_PATLIST ), (LPARAM)TRUE );
  469. }
  470. EnableWindow( epat, FALSE );
  471. }
  472. /*
  473. ** initialize the tile/center buttons
  474. */
  475. if(GetIntFromReg(HKEY_CURRENT_USER, szRegStr_Desktop, szTileWall, 1))
  476. CheckRadioButton(hDlg, IDC_CENTER, IDC_TILE, IDC_TILE);
  477. else
  478. CheckRadioButton(hDlg, IDC_CENTER, IDC_TILE, IDC_CENTER);
  479. /*
  480. ** initialize the wallpaper list
  481. */
  482. hwndList = GetDlgItem(hDlg, IDC_WALLLIST);
  483. if (!GetWindowsDirectory(szBuf, ARRAYSIZE(szBuf)))
  484. {
  485. szBuf[0] = 0;
  486. }
  487. // override with net home dir on shared copies of windows
  488. GetStringFromReg(HKEY_LOCAL_MACHINE, szRegStr_Setup, szSharedDir, (LPTSTR)NULL, szBuf, ARRAYSIZE(szBuf));
  489. AddFilesToLB(hwndList, szBuf, szBMP);
  490. GetStringFromReg(HKEY_CURRENT_USER, szRegStr_Desktop, szWallpaper, g_szNone, szBuf, ARRAYSIZE(szBuf));
  491. SetNewWallpaper(hDlg, szBuf, ARRAYSIZE(szBuf), TRUE); // will add and select if not in list
  492. // and don't forget the 'none' option
  493. if (SendMessage(hwndList, LB_INSERTSTRING, 0, (LPARAM)(LPTSTR)g_szNone) !=
  494. LB_ERR)
  495. {
  496. int sel = (int)SendMessage(hwndList, LB_GETCURSEL, 0, 0L);
  497. if (sel == -1)
  498. sel = 0;
  499. SendMessage(hwndList, LB_SETCURSEL, (WPARAM)sel, 0L);
  500. if (!sel) {
  501. EnableWindow( GetDlgItem(hDlg, IDC_TILE), FALSE );
  502. EnableWindow( GetDlgItem(hDlg, IDC_CENTER), FALSE );
  503. EnableWindow( GetDlgItem(hDlg, IDC_TXT_DISPLAY), FALSE );
  504. }
  505. }
  506. // allow people to drag wallpapers to this page
  507. DragAcceptFiles(hDlg, TRUE);
  508. }
  509. //the intl tools cannot handle embedded nulls in strings
  510. //hack: use the vertical bar and convert
  511. void NEAR PASCAL
  512. ConvertPipesToNull(LPTSTR szFilter)
  513. {
  514. while (*szFilter)
  515. {
  516. LPTSTR p = CharNext(szFilter);
  517. if (*szFilter == TEXT('|'))
  518. *szFilter = TEXT('\0');
  519. szFilter = p;
  520. }
  521. }
  522. void NEAR PASCAL BrowseForWallpaper(HWND hDlg)
  523. {
  524. TCHAR szPath[MAX_PATH];
  525. static TCHAR szWorkDir[MAX_PATH] = TEXT("");
  526. OPENFILENAME ofn;
  527. TCHAR szTitle[CCH_MAX_STRING];
  528. TCHAR szFilter[CCH_MAX_STRING];
  529. LoadString(hInstance, IDS_BROWSETITLE, szTitle, ARRAYSIZE(szTitle));
  530. if (LoadString(hInstance, IDS_BROWSEFILTER, szFilter, ARRAYSIZE(szFilter)))
  531. ConvertPipesToNull(szFilter);
  532. if (!PathOnly(szWorkDir))
  533. {
  534. if (!GetWindowsDirectory(szWorkDir, ARRAYSIZE(szWorkDir)))
  535. {
  536. szWorkDir[0] = 0;
  537. }
  538. }
  539. szPath[0] = TEXT('\0');
  540. ofn.lStructSize = sizeof(ofn);
  541. ofn.hwndOwner = hDlg;
  542. ofn.hInstance = NULL;
  543. ofn.lpstrFilter = szFilter;
  544. ofn.lpstrCustomFilter = NULL;
  545. ofn.nFilterIndex = 1;
  546. ofn.nMaxCustFilter = 0;
  547. ofn.lpstrFile = szPath;
  548. ofn.nMaxFile = ARRAYSIZE(szPath);
  549. ofn.lpstrInitialDir = (szWorkDir[0] ? szWorkDir : NULL);
  550. ofn.lpstrTitle = szTitle;
  551. ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
  552. ofn.lpfnHook = NULL;
  553. ofn.lpstrDefExt = szDefExt;
  554. ofn.lpstrFileTitle = NULL;
  555. if (GetOpenFileName(&ofn) && (lstrcmpi(g_szCurWallpaper, szPath) != 0))
  556. {
  557. CharUpper(szPath); // will be nicenamed (best we can do...)
  558. SetNewWallpaper(hDlg, szPath, ARRAYSIZE(szPath), TRUE);
  559. }
  560. if (!GetCurrentDirectory(ARRAYSIZE(szWorkDir), szWorkDir))
  561. {
  562. szWorkDir[0] = 0;
  563. }
  564. }
  565. void NEAR PASCAL HandleWallpaperDrop(HWND hDlg, HDROP hDrop)
  566. {
  567. TCHAR szPath[MAX_PATH];
  568. if (DragQueryFile(hDrop, 1, szPath, ARRAYSIZE(szPath)) &&
  569. (lstrcmpi(g_szCurWallpaper, szPath) != 0))
  570. {
  571. int len = lstrlen(szPath);
  572. if (len > 4 && !lstrcmpi(szPath+len-4, szDotBMP))
  573. SetNewWallpaper(hDlg, szPath, ARRAYSIZE(szPath), TRUE);
  574. }
  575. DragFinish(hDrop);
  576. }
  577. INT_PTR APIENTRY BackgroundDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  578. {
  579. NMHDR FAR *lpnm;
  580. TCHAR szTiled[] = TEXT("0");
  581. TCHAR szBuf[MAX_PATH];
  582. TCHAR szBuf2[50];
  583. int iTemp;
  584. switch(message)
  585. {
  586. case WM_NOTIFY:
  587. lpnm = (NMHDR FAR *)lParam;
  588. switch(lpnm->code)
  589. {
  590. case PSN_APPLY: {
  591. DWORD dwRet = PSNRET_NOERROR;
  592. if (g_Back_bChanged)
  593. {
  594. HCURSOR old = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  595. HWND cover;
  596. if (!g_bValidBitmap)
  597. {
  598. LoadString(hInstance, IDS_BADWALLPAPER, szBuf, ARRAYSIZE(szBuf));
  599. GetWindowText(GetParent(hDlg), szBuf2, ARRAYSIZE(szBuf2));
  600. MessageBox(hDlg, szBuf, szBuf2, MB_OK | MB_ICONEXCLAMATION);
  601. dwRet = PSNRET_INVALID_NOCHANGEPAGE;
  602. }
  603. // do this after whimpering
  604. cover = CreateCoverWindow( COVER_NOPAINT );
  605. // need to write out tile first
  606. szTiled[0] += (TCHAR)IsDlgButtonChecked(hDlg, IDC_TILE);
  607. UpdateRegistry(HKEY_CURRENT_USER, szRegStr_Desktop,
  608. szTileWall, REG_SZ, szTiled, SIZEOF(TCHAR)*(lstrlen(szTiled)+1));
  609. if (g_bValidBitmap)
  610. {
  611. SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, g_szCurWallpaper,
  612. SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  613. }
  614. if (GetPrivateProfileString(g_szPatterns, g_szCurPattern, g_szNULL, szBuf, ARRAYSIZE(szBuf), g_szControlIni))
  615. {
  616. SystemParametersInfo(SPI_SETDESKPATTERN, 0, szBuf,
  617. SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  618. }
  619. // we're back to no changes
  620. g_Back_bChanged = FALSE;
  621. if( cover )
  622. PostMessage( cover, WM_CLOSE, 0, 0L );
  623. SetCursor( old );
  624. }
  625. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, dwRet );
  626. return TRUE;
  627. }
  628. case PSN_RESET:
  629. break;
  630. }
  631. break;
  632. case WM_INITDIALOG:
  633. g_Back_bInit = TRUE;
  634. InitBackgroundDialog(hDlg);
  635. g_Back_bInit = FALSE; // no longer initializing
  636. break;
  637. case WM_SYSCOLORCHANGE:
  638. case WM_DISPLAYCHANGE:
  639. g_Back_bInit = TRUE; // fake init so we don't do PSM_CHANGED
  640. UpdatePreview(hDlg, BP_REINIT | BP_NEWPAT );
  641. g_Back_bInit = FALSE;
  642. break;
  643. case WM_DESTROY:
  644. {
  645. int count = (int)SendDlgItemMessage(hDlg, IDC_WALLLIST,
  646. LB_GETCOUNT, 0, 0L);
  647. while (count--)
  648. {
  649. LPTSTR sz = (LPTSTR)SendDlgItemMessage(hDlg, IDC_WALLLIST,
  650. LB_GETITEMDATA, count, 0L);
  651. if (sz)
  652. LocalFree ((HANDLE)sz);
  653. }
  654. break;
  655. }
  656. case WM_HELP:
  657. WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, TEXT("display.hlp"),
  658. HELP_WM_HELP, (DWORD_PTR) (LPTSTR) aBckgrndHelpIds);
  659. return TRUE;
  660. case WM_CONTEXTMENU: // right mouse click
  661. WinHelp((HWND) wParam, TEXT("display.hlp"), HELP_CONTEXTMENU,
  662. (DWORD_PTR) (LPTSTR) aBckgrndHelpIds);
  663. return TRUE;
  664. case WM_DROPFILES:
  665. HandleWallpaperDrop(hDlg, (HDROP)wParam);
  666. return TRUE;
  667. case WM_QUERYNEWPALETTE:
  668. case WM_PALETTECHANGED:
  669. SendDlgItemMessage(hDlg, IDC_BACKPREV, message, wParam, lParam);
  670. return TRUE;
  671. case WM_COMMAND:
  672. switch(LOWORD(wParam))
  673. {
  674. case IDC_PATLIST:
  675. if(HIWORD(wParam) == LBN_SELCHANGE)
  676. {
  677. iTemp = (int)SendDlgItemMessage(hDlg,IDC_PATLIST,
  678. LB_GETCURSEL,0,0l);
  679. if(iTemp >= 0)
  680. {
  681. SendDlgItemMessage(hDlg, IDC_PATLIST, LB_GETTEXT,
  682. iTemp, (LPARAM)(LPTSTR)szBuf);
  683. if (lstrcmpi(szBuf, g_szCurPattern) == 0)
  684. break;
  685. StringCchCopy(g_szCurPattern, ARRAYSIZE(g_szCurPattern), szBuf);
  686. UpdatePreview(hDlg, BP_NEWPAT);
  687. }
  688. EnableWindow( GetDlgItem( hDlg, IDC_EDITPAT ),
  689. ( iTemp > 0 ) ); // exclude "none" pattern
  690. }
  691. break;
  692. case IDC_WALLLIST:
  693. if(HIWORD(wParam) == LBN_SELCHANGE)
  694. {
  695. LPTSTR pBuf = NULL;
  696. iTemp = (int)SendDlgItemMessage(hDlg,IDC_WALLLIST,
  697. LB_GETCURSEL,0,0l);
  698. if(iTemp >= 0)
  699. {
  700. pBuf = (LPTSTR)SendDlgItemMessage(hDlg,
  701. IDC_WALLLIST, LB_GETITEMDATA, iTemp, 0L);
  702. }
  703. SetNewWallpaper(hDlg, pBuf, pBuf ? MAX_PATH : 0, FALSE);
  704. }
  705. break;
  706. case IDC_CENTER:
  707. case IDC_TILE:
  708. if ((HIWORD(wParam) == BN_CLICKED) &&
  709. (!IsDlgButtonChecked(hDlg, LOWORD(wParam))))
  710. {
  711. CheckRadioButton(hDlg, IDC_CENTER, IDC_TILE, LOWORD(wParam));
  712. UpdatePreview(hDlg, 0);
  713. }
  714. break;
  715. case IDC_BROWSEWALL:
  716. BrowseForWallpaper(hDlg);
  717. break;
  718. }
  719. break;
  720. }
  721. return FALSE;
  722. }