[NTOS:MM] Update a DPRINT string (#760)
[reactos.git] / dll / cpl / desk / background.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: dll/cpl/desk/background.c
5 * PURPOSE: Background property page
6 *
7 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
8 * Alexey Minnekhanov (minlexx@rambler.ru)
9 */
10
11 #include "desk.h"
12
13 #include <shellapi.h>
14 #include <shlwapi.h>
15
16 #define MAX_BACKGROUNDS 100
17
18 typedef enum
19 {
20 PLACEMENT_CENTER = 0,
21 PLACEMENT_STRETCH,
22 PLACEMENT_TILE,
23 PLACEMENT_FIT,
24 PLACEMENT_FILL
25 } PLACEMENT;
26
27 /* The tile placement is stored in different registry
28 * key, but due to a condition in win32k it needs to be
29 * zero when stored in the same key as others.
30 */
31 typedef enum
32 {
33 PLACEMENT_VALUE_CENTER = 0,
34 PLACEMENT_VALUE_STRETCH = 2,
35 PLACEMENT_VALUE_TILE = 0,
36 PLACEMENT_VALUE_FIT = 6,
37 PLACEMENT_VALUE_FILL = 10
38 } PLACEMENT_VALUE;
39
40 /* The values in these macros are dependent on the
41 * layout of the monitor image and they must be adjusted
42 * if that image will be changed.
43 */
44 #define MONITOR_LEFT 18
45 #define MONITOR_TOP 18
46 #define MONITOR_RIGHT 168
47 #define MONITOR_BOTTOM 128
48
49 #define MONITOR_WIDTH (MONITOR_RIGHT-MONITOR_LEFT)
50 #define MONITOR_HEIGHT (MONITOR_BOTTOM-MONITOR_TOP)
51
52 typedef struct
53 {
54 BOOL bWallpaper; /* Is this background a wallpaper */
55
56 TCHAR szFilename[MAX_PATH];
57 TCHAR szDisplayName[256];
58
59 } BackgroundItem;
60
61 typedef struct _BACKGROUND_DATA
62 {
63 BOOL bWallpaperChanged;
64 BOOL bClrBackgroundChanged;
65
66 BackgroundItem backgroundItems[MAX_BACKGROUNDS];
67
68 PDIBITMAP pWallpaperBitmap;
69
70 int placementSelection;
71 int backgroundSelection;
72
73 COLORREF custom_colors[16];
74
75 int listViewItemCount;
76
77 HBITMAP hBitmap;
78 int cxSource;
79 int cySource;
80
81 ULONG_PTR gdipToken;
82 } BACKGROUND_DATA, *PBACKGROUND_DATA;
83
84 GLOBAL_DATA g_GlobalData;
85
86
87 HRESULT
88 GdipGetEncoderClsid(PCWSTR MimeType, CLSID *pClsid)
89 {
90 UINT num;
91 UINT size;
92 UINT i;
93 ImageCodecInfo *codecInfo;
94
95 if (GdipGetImageEncodersSize(&num, &size) != Ok ||
96 size == 0)
97 {
98 return E_FAIL;
99 }
100
101 codecInfo = HeapAlloc(GetProcessHeap(), 0, size);
102 if (!codecInfo)
103 {
104 return E_OUTOFMEMORY;
105 }
106
107 if (GdipGetImageEncoders(num, size, codecInfo) != Ok)
108 {
109 HeapFree(GetProcessHeap(), 0, codecInfo);
110 return E_FAIL;
111 }
112
113 for (i = 0; i < num; i++)
114 {
115 if (!_wcsicmp(codecInfo[i].MimeType, MimeType))
116 {
117 *pClsid = codecInfo[i].Clsid;
118 HeapFree(GetProcessHeap(), 0, codecInfo);
119 return S_OK;
120 }
121 }
122
123 HeapFree(GetProcessHeap(), 0, codecInfo);
124 return E_FAIL;
125 }
126
127
128 LPWSTR
129 GdipGetSupportedFileExtensions(VOID)
130 {
131 ImageCodecInfo *codecInfo;
132 UINT num;
133 UINT size;
134 UINT i;
135 LPWSTR lpBuffer = NULL;
136
137 if (GdipGetImageDecodersSize(&num, &size) != Ok ||
138 size == 0)
139 {
140 return NULL;
141 }
142
143 codecInfo = HeapAlloc(GetProcessHeap(), 0, size);
144 if (!codecInfo)
145 {
146 return NULL;
147 }
148
149 if (GdipGetImageDecoders(num, size, codecInfo) != Ok)
150 {
151 HeapFree(GetProcessHeap(), 0, codecInfo);
152 return NULL;
153 }
154
155 size = 0;
156 for (i = 0; i < num; ++i)
157 {
158 size = size + (UINT)wcslen(codecInfo[i].FilenameExtension) + 1;
159 }
160
161 size = (size + 1) * sizeof(WCHAR);
162
163 lpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
164 if (!lpBuffer)
165 {
166 HeapFree(GetProcessHeap(), 0, codecInfo);
167 return NULL;
168 }
169
170 for (i = 0; i < num; ++i)
171 {
172 StringCbCatW(lpBuffer, size, codecInfo[i].FilenameExtension);
173 if (i < (num - 1))
174 {
175 StringCbCatW(lpBuffer, size, L";");
176 }
177 }
178
179 HeapFree(GetProcessHeap(), 0, codecInfo);
180
181 return lpBuffer;
182 }
183
184
185 static UINT
186 AddWallpapersFromDirectory(UINT uCounter, HWND hwndBackgroundList, BackgroundItem *backgroundItem, PBACKGROUND_DATA pData, LPCTSTR wallpaperFilename, LPCTSTR wallpaperDirectory)
187 {
188 WIN32_FIND_DATA fd;
189 HANDLE hFind;
190 TCHAR szSearchPath[MAX_PATH];
191 LPTSTR szFileTypes = NULL;
192 TCHAR separators[] = TEXT(";");
193 TCHAR *token;
194 HRESULT hr;
195 SHFILEINFO sfi;
196 UINT i = uCounter;
197 LV_ITEM listItem;
198 HIMAGELIST himl;
199
200 szFileTypes = GdipGetSupportedFileExtensions();
201 if (!szFileTypes)
202 {
203 return i;
204 }
205
206 token = _tcstok(szFileTypes, separators);
207 while (token != NULL)
208 {
209 if (!PathCombine(szSearchPath, wallpaperDirectory, token))
210 {
211 HeapFree(GetProcessHeap(), 0, szFileTypes);
212 return i;
213 }
214
215 hFind = FindFirstFile(szSearchPath, &fd);
216 while (hFind != INVALID_HANDLE_VALUE)
217 {
218 TCHAR filename[MAX_PATH];
219
220 if (!PathCombine(filename, wallpaperDirectory, fd.cFileName))
221 {
222 FindClose(hFind);
223 HeapFree(GetProcessHeap(), 0, szFileTypes);
224 return i;
225 }
226
227 /* Don't add any hidden bitmaps. Also don't add current wallpaper once more. */
228 if (((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) && (_tcsicmp(wallpaperFilename, filename) != 0))
229 {
230 himl = (HIMAGELIST)SHGetFileInfo(filename,
231 0,
232 &sfi,
233 sizeof(sfi),
234 SHGFI_SYSICONINDEX | SHGFI_SMALLICON |
235 SHGFI_DISPLAYNAME);
236 if (himl == NULL)
237 break;
238
239 if (i++ == 0)
240 {
241 (void)ListView_SetImageList(hwndBackgroundList, himl, LVSIL_SMALL);
242 }
243
244 backgroundItem = &pData->backgroundItems[pData->listViewItemCount];
245
246 backgroundItem->bWallpaper = TRUE;
247
248 hr = StringCbCopy(backgroundItem->szDisplayName, sizeof(backgroundItem->szDisplayName), sfi.szDisplayName);
249 if (FAILED(hr))
250 {
251 FindClose(hFind);
252 HeapFree(GetProcessHeap(), 0, szFileTypes);
253 return i;
254 }
255
256 PathRemoveExtension(backgroundItem->szDisplayName);
257
258 hr = StringCbCopy(backgroundItem->szFilename, sizeof(backgroundItem->szFilename), filename);
259 if (FAILED(hr))
260 {
261 FindClose(hFind);
262 HeapFree(GetProcessHeap(), 0, szFileTypes);
263 return i;
264 }
265
266 ZeroMemory(&listItem, sizeof(LV_ITEM));
267 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
268 listItem.pszText = backgroundItem->szDisplayName;
269 listItem.state = 0;
270 listItem.iImage = sfi.iIcon;
271 listItem.iItem = pData->listViewItemCount;
272 listItem.lParam = pData->listViewItemCount;
273
274 (void)ListView_InsertItem(hwndBackgroundList, &listItem);
275
276 pData->listViewItemCount++;
277 }
278
279 if (!FindNextFile(hFind, &fd))
280 break;
281 }
282
283 token = _tcstok(NULL, separators);
284 FindClose(hFind);
285 }
286
287 HeapFree(GetProcessHeap(), 0, szFileTypes);
288
289 return i;
290 }
291
292
293 /* Add the images in the C:\ReactOS, the wallpaper directory and the current wallpaper if any */
294 static VOID
295 AddListViewItems(HWND hwndDlg, PBACKGROUND_DATA pData)
296 {
297 TCHAR szSearchPath[MAX_PATH];
298 LV_ITEM listItem;
299 LV_COLUMN dummy;
300 RECT clientRect;
301 HKEY regKey;
302 SHFILEINFO sfi;
303 HIMAGELIST himl;
304 TCHAR wallpaperFilename[MAX_PATH];
305 TCHAR originalWallpaper[MAX_PATH];
306 DWORD bufferSize = sizeof(wallpaperFilename);
307 TCHAR buffer[MAX_PATH];
308 DWORD varType = REG_SZ;
309 LONG result;
310 UINT i = 0;
311 BackgroundItem *backgroundItem = NULL;
312 HWND hwndBackgroundList;
313 HRESULT hr;
314
315 hwndBackgroundList = GetDlgItem(hwndDlg, IDC_BACKGROUND_LIST);
316
317 GetClientRect(hwndBackgroundList, &clientRect);
318
319 /* Add a new column to the list */
320 ZeroMemory(&dummy, sizeof(LV_COLUMN));
321 dummy.mask = LVCF_SUBITEM | LVCF_WIDTH;
322 dummy.iSubItem = 0;
323 dummy.cx = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL);
324 (void)ListView_InsertColumn(hwndBackgroundList, 0, &dummy);
325
326 /* Add the "None" item */
327 backgroundItem = &pData->backgroundItems[pData->listViewItemCount];
328 backgroundItem->bWallpaper = FALSE;
329 LoadString(hApplet,
330 IDS_NONE,
331 backgroundItem->szDisplayName,
332 sizeof(backgroundItem->szDisplayName) / sizeof(TCHAR));
333
334 ZeroMemory(&listItem, sizeof(LV_ITEM));
335 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
336 listItem.state = 0;
337 listItem.pszText = backgroundItem->szDisplayName;
338 listItem.iImage = -1;
339 listItem.iItem = pData->listViewItemCount;
340 listItem.lParam = pData->listViewItemCount;
341
342 (void)ListView_InsertItem(hwndBackgroundList, &listItem);
343 ListView_SetItemState(hwndBackgroundList,
344 pData->listViewItemCount,
345 LVIS_SELECTED,
346 LVIS_SELECTED);
347
348 pData->listViewItemCount++;
349
350 /* Add current wallpaper if any */
351 result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_QUERY_VALUE, &regKey);
352 if (result == ERROR_SUCCESS)
353 {
354 result = RegQueryValueEx(regKey, TEXT("Wallpaper"), 0, &varType, (LPBYTE)wallpaperFilename, &bufferSize);
355 if ((result == ERROR_SUCCESS) && (_tcslen(wallpaperFilename) > 0))
356 {
357 bufferSize = sizeof(originalWallpaper);
358 result = RegQueryValueEx(regKey, TEXT("OriginalWallpaper"), 0, &varType, (LPBYTE)originalWallpaper, &bufferSize);
359
360 /* If Wallpaper and OriginalWallpaper are the same, try to retrieve ConvertedWallpaper and use it instead of Wallpaper */
361 if ((result == ERROR_SUCCESS) && (_tcslen(originalWallpaper) > 0) && (_tcsicmp(wallpaperFilename, originalWallpaper) == 0))
362 {
363 bufferSize = sizeof(originalWallpaper);
364 result = RegQueryValueEx(regKey, TEXT("ConvertedWallpaper"), 0, &varType, (LPBYTE)originalWallpaper, &bufferSize);
365
366 if ((result == ERROR_SUCCESS) && (_tcslen(originalWallpaper) > 0))
367 {
368 hr = StringCbCopy(wallpaperFilename, sizeof(wallpaperFilename), originalWallpaper);
369 if (FAILED(hr))
370 {
371 RegCloseKey(regKey);
372 return;
373 }
374 }
375 }
376
377 /* Allow environment variables in file name */
378 if (ExpandEnvironmentStrings(wallpaperFilename, buffer, MAX_PATH))
379 {
380 hr = StringCbCopy(wallpaperFilename, sizeof(wallpaperFilename), buffer);
381 if (FAILED(hr))
382 {
383 RegCloseKey(regKey);
384 return;
385 }
386 }
387
388 himl = (HIMAGELIST)SHGetFileInfo(wallpaperFilename,
389 0,
390 &sfi,
391 sizeof(sfi),
392 SHGFI_SYSICONINDEX | SHGFI_SMALLICON |
393 SHGFI_DISPLAYNAME);
394 if (himl != NULL)
395 {
396 if (i++ == 0)
397 {
398 (void)ListView_SetImageList(hwndBackgroundList, himl, LVSIL_SMALL);
399 }
400
401 backgroundItem = &pData->backgroundItems[pData->listViewItemCount];
402
403 backgroundItem->bWallpaper = TRUE;
404
405 hr = StringCbCopy(backgroundItem->szDisplayName, sizeof(backgroundItem->szDisplayName), sfi.szDisplayName);
406 if (FAILED(hr))
407 {
408 RegCloseKey(regKey);
409 return;
410 }
411
412 PathRemoveExtension(backgroundItem->szDisplayName);
413
414 hr = StringCbCopy(backgroundItem->szFilename, sizeof(backgroundItem->szFilename), wallpaperFilename);
415 if (FAILED(hr))
416 {
417 RegCloseKey(regKey);
418 return;
419 }
420
421 ZeroMemory(&listItem, sizeof(LV_ITEM));
422 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
423 listItem.state = 0;
424 listItem.pszText = backgroundItem->szDisplayName;
425 listItem.iImage = sfi.iIcon;
426 listItem.iItem = pData->listViewItemCount;
427 listItem.lParam = pData->listViewItemCount;
428
429 (void)ListView_InsertItem(hwndBackgroundList, &listItem);
430 ListView_SetItemState(hwndBackgroundList,
431 pData->listViewItemCount,
432 LVIS_SELECTED,
433 LVIS_SELECTED);
434
435 pData->listViewItemCount++;
436 }
437 }
438
439 RegCloseKey(regKey);
440 }
441
442 /* Add all the images in the C:\ReactOS directory. */
443 if (GetWindowsDirectory(szSearchPath, MAX_PATH))
444 {
445 i = AddWallpapersFromDirectory(i, hwndBackgroundList, backgroundItem, pData, wallpaperFilename, szSearchPath);
446 }
447
448 /* Add all the images in the wallpaper directory. */
449 if (SHRegGetPath(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"), TEXT("WallPaperDir"), szSearchPath, 0) == ERROR_SUCCESS)
450 {
451 i = AddWallpapersFromDirectory(i, hwndBackgroundList, backgroundItem, pData, wallpaperFilename, szSearchPath);
452 }
453 }
454
455
456 static VOID
457 InitBackgroundDialog(HWND hwndDlg, PBACKGROUND_DATA pData)
458 {
459 TCHAR szString[256];
460 HKEY regKey;
461 TCHAR szBuffer[3];
462 DWORD bufferSize = sizeof(szBuffer);
463 BITMAP bitmap;
464
465 AddListViewItems(hwndDlg, pData);
466
467 LoadString(hApplet, IDS_CENTER, szString, sizeof(szString) / sizeof(TCHAR));
468 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_INSERTSTRING, PLACEMENT_CENTER, (LPARAM)szString);
469
470 LoadString(hApplet, IDS_STRETCH, szString, sizeof(szString) / sizeof(TCHAR));
471 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_INSERTSTRING, PLACEMENT_STRETCH, (LPARAM)szString);
472
473 LoadString(hApplet, IDS_TILE, szString, sizeof(szString) / sizeof(TCHAR));
474 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_INSERTSTRING, PLACEMENT_TILE, (LPARAM)szString);
475
476 LoadString(hApplet, IDS_FIT, szString, sizeof(szString) / sizeof(TCHAR));
477 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_INSERTSTRING, PLACEMENT_FIT, (LPARAM)szString);
478
479 LoadString(hApplet, IDS_FILL, szString, sizeof(szString) / sizeof(TCHAR));
480 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_INSERTSTRING, PLACEMENT_FILL, (LPARAM)szString);
481
482 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_CENTER, 0);
483 pData->placementSelection = PLACEMENT_CENTER;
484
485 pData->hBitmap = (HBITMAP) LoadImage(hApplet, MAKEINTRESOURCE(IDC_MONITOR), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
486 if (pData->hBitmap != NULL)
487 {
488 GetObject(pData->hBitmap, sizeof(BITMAP), &bitmap);
489
490 pData->cxSource = bitmap.bmWidth;
491 pData->cySource = bitmap.bmHeight;
492 }
493
494 /* Load the default settings from the registry */
495 if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_QUERY_VALUE, &regKey) != ERROR_SUCCESS)
496 {
497 return;
498 }
499
500 if (RegQueryValueEx(regKey, TEXT("WallpaperStyle"), 0, NULL, (LPBYTE)szBuffer, &bufferSize) == ERROR_SUCCESS)
501 {
502 if (_ttoi(szBuffer) == PLACEMENT_VALUE_CENTER)
503 {
504 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_CENTER, 0);
505 pData->placementSelection = PLACEMENT_CENTER;
506 }
507
508 if (_ttoi(szBuffer) == PLACEMENT_VALUE_STRETCH)
509 {
510 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_STRETCH, 0);
511 pData->placementSelection = PLACEMENT_STRETCH;
512 }
513
514 if (_ttoi(szBuffer) == PLACEMENT_VALUE_FIT)
515 {
516 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_FIT, 0);
517 pData->placementSelection = PLACEMENT_FIT;
518 }
519
520 if (_ttoi(szBuffer) == PLACEMENT_VALUE_FILL)
521 {
522 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_FILL, 0);
523 pData->placementSelection = PLACEMENT_FILL;
524 }
525 }
526
527 if (RegQueryValueEx(regKey, TEXT("TileWallpaper"), 0, NULL, (LPBYTE)szBuffer, &bufferSize) == ERROR_SUCCESS)
528 {
529 if (_ttoi(szBuffer) == 1)
530 {
531 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_TILE, 0);
532 pData->placementSelection = PLACEMENT_TILE;
533 }
534 }
535
536 RegCloseKey(regKey);
537 }
538
539
540 static VOID
541 OnColorButton(HWND hwndDlg, PBACKGROUND_DATA pData)
542 {
543 /* Load custom colors from Registry */
544 HKEY hKey = NULL;
545 LONG res = ERROR_SUCCESS;
546 CHOOSECOLOR cc;
547
548 res = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance"), 0, NULL,
549 REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE, NULL, &hKey, NULL);
550 /* Now the key is either created or opened existing, if res == ERROR_SUCCESS */
551 if (res == ERROR_SUCCESS)
552 {
553 /* Key opened */
554 DWORD dwType = REG_BINARY;
555 DWORD cbData = sizeof(pData->custom_colors);
556 res = RegQueryValueEx(hKey, TEXT("CustomColors"), NULL, &dwType,
557 (LPBYTE)pData->custom_colors, &cbData);
558 RegCloseKey(hKey);
559 hKey = NULL;
560 }
561
562 /* Launch ChooseColor() dialog */
563
564 cc.lStructSize = sizeof(CHOOSECOLOR);
565 cc.hwndOwner = hwndDlg;
566 cc.hInstance = NULL;
567 cc.rgbResult = g_GlobalData.desktop_color;
568 cc.lpCustColors = pData->custom_colors;
569 cc.Flags = CC_ANYCOLOR | /* Causes the dialog box to display all available colors in the set of basic colors. */
570 CC_FULLOPEN | /* opens dialog in full size */
571 CC_RGBINIT ; /* init chosen color by rgbResult value */
572 cc.lCustData = 0;
573 cc.lpfnHook = NULL;
574 cc.lpTemplateName = NULL;
575 if (ChooseColor(&cc))
576 {
577 /* Save selected color to var */
578 g_GlobalData.desktop_color = cc.rgbResult;
579 pData->bClrBackgroundChanged = TRUE;
580
581 /* Apply button will be activated */
582 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
583
584 /* Window will be updated :) */
585 InvalidateRect(GetDlgItem(hwndDlg, IDC_BACKGROUND_PREVIEW), NULL, TRUE);
586
587 /* Save custom colors to reg. To this moment key must be created already. See above */
588 res = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance"), 0,
589 KEY_SET_VALUE, &hKey);
590 if (res == ERROR_SUCCESS)
591 {
592 /* Key opened */
593 RegSetValueEx(hKey, TEXT("CustomColors"), 0, REG_BINARY,
594 (LPBYTE)pData->custom_colors, sizeof(pData->custom_colors));
595 RegCloseKey(hKey);
596 hKey = NULL;
597 }
598 }
599 }
600
601
602 /*
603 * ListView_FindItem() Macro: Searches for a list-view item with the specified
604 * characteristics. Returns the index of the item if successful, or -1 otherwise
605 */
606 static BOOL
607 CheckListViewFilenameExists(HWND hwndList, LPCTSTR tszFileName)
608 {
609 LVFINDINFO lvfi;
610 int retVal;
611
612 lvfi.flags = LVFI_STRING; /* Search item by EXACT string */
613 lvfi.psz = tszFileName; /* String to search */
614
615 /* Other items of this structure are not valid, besacuse flags are not set. */
616 retVal = ListView_FindItem(hwndList, -1, &lvfi);
617 if (retVal != -1)
618 return TRUE; /* item found! */
619
620 return FALSE; /* item not found. */
621 }
622
623
624 static VOID
625 OnBrowseButton(HWND hwndDlg, PBACKGROUND_DATA pData)
626 {
627 OPENFILENAME ofn;
628 TCHAR filename[MAX_PATH];
629 TCHAR fileTitle[256];
630 LPTSTR filter;
631 LPTSTR extensions;
632 BackgroundItem *backgroundItem = NULL;
633 SHFILEINFO sfi;
634 LV_ITEM listItem;
635 HWND hwndBackgroundList;
636 TCHAR *p;
637 HRESULT hr;
638 TCHAR filterdesc[MAX_PATH];
639 TCHAR *c;
640 size_t sizeRemain;
641 SIZE_T buffersize;
642 BOOL success;
643
644 hwndBackgroundList = GetDlgItem(hwndDlg, IDC_BACKGROUND_LIST);
645
646 ZeroMemory(&ofn, sizeof(OPENFILENAME));
647
648 ofn.lStructSize = sizeof(OPENFILENAME);
649 ofn.hwndOwner = hwndDlg;
650 ofn.lpstrFile = filename;
651
652 LoadString(hApplet, IDS_BACKGROUND_COMDLG_FILTER, filterdesc, sizeof(filterdesc) / sizeof(TCHAR));
653
654 extensions = GdipGetSupportedFileExtensions();
655 if (!extensions)
656 {
657 return;
658 }
659
660 buffersize = (_tcslen(extensions) * 2 + 6) * sizeof(TCHAR) + sizeof(filterdesc);
661
662 filter = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffersize);
663 if (!filter)
664 {
665 HeapFree(GetProcessHeap(), 0, extensions);
666 return;
667 }
668
669 sizeRemain = buffersize;
670 c = filter;
671
672 if (FAILED(StringCbPrintfEx(c, sizeRemain, &c, &sizeRemain, 0, L"%ls (%ls)", filterdesc, extensions)))
673 {
674 HeapFree(GetProcessHeap(), 0, extensions);
675 HeapFree(GetProcessHeap(), 0, filter);
676 return;
677 }
678
679 c++;
680 sizeRemain -= sizeof(*c);
681
682 if (FAILED(StringCbPrintfEx(c, sizeRemain, &c, &sizeRemain, 0, L"%ls", extensions)))
683 {
684 HeapFree(GetProcessHeap(), 0, extensions);
685 HeapFree(GetProcessHeap(), 0, filter);
686 return;
687 }
688
689 HeapFree(GetProcessHeap(), 0, extensions);
690
691 /* Set lpstrFile[0] to '\0' so that GetOpenFileName does not
692 * use the contents of szFile to initialize itself */
693 ofn.lpstrFile[0] = TEXT('\0');
694 ofn.nMaxFile = MAX_PATH;
695 ofn.lpstrFilter = filter;
696 ofn.nFilterIndex = 0;
697 ofn.lpstrFileTitle = fileTitle;
698 ofn.nMaxFileTitle = 256;
699 ofn.lpstrInitialDir = NULL;
700 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
701
702 success = GetOpenFileName(&ofn);
703 HeapFree(GetProcessHeap(), 0, filter);
704
705 if (success)
706 {
707 /* Check if there is already a entry that holds this filename */
708 if (CheckListViewFilenameExists(hwndBackgroundList, ofn.lpstrFileTitle) != FALSE)
709 return;
710
711 if (pData->listViewItemCount > (MAX_BACKGROUNDS - 1))
712 return;
713
714 SHGetFileInfo(filename,
715 0,
716 &sfi,
717 sizeof(sfi),
718 SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_DISPLAYNAME);
719
720 backgroundItem = &pData->backgroundItems[pData->listViewItemCount];
721
722 backgroundItem->bWallpaper = TRUE;
723
724 hr = StringCbCopy(backgroundItem->szDisplayName, sizeof(backgroundItem->szDisplayName), sfi.szDisplayName);
725 if (FAILED(hr))
726 return;
727 p = _tcsrchr(backgroundItem->szDisplayName, _T('.'));
728 if (p)
729 *p = (TCHAR)0;
730 hr = StringCbCopy(backgroundItem->szFilename, sizeof(backgroundItem->szFilename), filename);
731 if (FAILED(hr))
732 return;
733
734 ZeroMemory(&listItem, sizeof(LV_ITEM));
735 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
736 listItem.state = 0;
737 listItem.pszText = backgroundItem->szDisplayName;
738 listItem.iImage = sfi.iIcon;
739 listItem.iItem = pData->listViewItemCount;
740 listItem.lParam = pData->listViewItemCount;
741
742 (void)ListView_InsertItem(hwndBackgroundList, &listItem);
743 ListView_SetItemState(hwndBackgroundList,
744 pData->listViewItemCount,
745 LVIS_SELECTED,
746 LVIS_SELECTED);
747 SendMessage(hwndBackgroundList, WM_VSCROLL, SB_BOTTOM, 0);
748
749 pData->listViewItemCount++;
750 }
751 }
752
753
754 static VOID
755 ListViewItemChanged(HWND hwndDlg, PBACKGROUND_DATA pData, int itemIndex)
756 {
757 BackgroundItem *backgroundItem = NULL;
758
759 pData->backgroundSelection = itemIndex;
760 backgroundItem = &pData->backgroundItems[pData->backgroundSelection];
761
762 if (pData->pWallpaperBitmap != NULL)
763 {
764 DibFreeImage(pData->pWallpaperBitmap);
765 pData->pWallpaperBitmap = NULL;
766 }
767
768 if (backgroundItem->bWallpaper != FALSE)
769 {
770 pData->pWallpaperBitmap = DibLoadImage(backgroundItem->szFilename);
771
772 if (pData->pWallpaperBitmap == NULL)
773 return;
774 }
775
776 pData->bWallpaperChanged = TRUE;
777
778 InvalidateRect(GetDlgItem(hwndDlg, IDC_BACKGROUND_PREVIEW),
779 NULL, TRUE);
780
781 EnableWindow(GetDlgItem(hwndDlg, IDC_PLACEMENT_COMBO),
782 backgroundItem->bWallpaper);
783
784 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
785 }
786
787
788 static VOID
789 DrawBackgroundPreview(LPDRAWITEMSTRUCT draw, PBACKGROUND_DATA pData)
790 {
791 float scaleX;
792 float scaleY;
793 int scaledWidth;
794 int scaledHeight;
795 int posX, desX;
796 int posY, desY;
797 int fitFillScaleNum, fitFillScaleDen;
798 int fitFillWidth, fitFillHeight;
799 HBRUSH hBrush;
800 int x;
801 int y;
802 HDC hDC;
803 HGDIOBJ hOldObj;
804 RECT rcItem = {
805 MONITOR_LEFT,
806 MONITOR_TOP,
807 MONITOR_RIGHT,
808 MONITOR_BOTTOM
809 };
810
811 hDC = CreateCompatibleDC(draw->hDC);
812 hOldObj = SelectObject(hDC, pData->hBitmap);
813
814 if (pData->backgroundItems[pData->backgroundSelection].bWallpaper == FALSE)
815 {
816 /* Update desktop background color image */
817 hBrush = CreateSolidBrush(g_GlobalData.desktop_color);
818 FillRect(hDC, &rcItem, hBrush);
819 DeleteObject(hBrush);
820 }
821 else
822 if (pData->pWallpaperBitmap != NULL)
823 {
824 scaleX = ((float)GetSystemMetrics(SM_CXSCREEN) - 1) / (float)MONITOR_WIDTH;
825 scaleY = ((float)GetSystemMetrics(SM_CYSCREEN) - 1) / (float)MONITOR_HEIGHT;
826
827 scaledWidth = (int)(pData->pWallpaperBitmap->width / scaleX);
828 scaledHeight = (int)(pData->pWallpaperBitmap->height / scaleY);
829
830 FillRect(hDC, &rcItem, GetSysColorBrush(COLOR_BACKGROUND));
831
832 SetStretchBltMode(hDC, COLORONCOLOR);
833
834 switch (pData->placementSelection)
835 {
836 case PLACEMENT_CENTER:
837 posX = (MONITOR_WIDTH - scaledWidth + 1) / 2;
838 posY = (MONITOR_HEIGHT - scaledHeight + 1) / 2;
839 desX = 0;
840 desY = 0;
841
842 if (posX < 0) { desX = -posX / 2; posX = 0; }
843 if (posY < 0) { desY = -posY / 2; posY = 0; }
844
845 if (scaledWidth > MONITOR_WIDTH)
846 scaledWidth = MONITOR_WIDTH;
847
848 if (scaledHeight > MONITOR_HEIGHT)
849 scaledHeight = MONITOR_HEIGHT;
850
851 StretchDIBits(hDC,
852 MONITOR_LEFT+posX,
853 MONITOR_TOP+posY,
854 scaledWidth,
855 scaledHeight,
856 desX,
857 desY,
858 pData->pWallpaperBitmap->width - (int)(desX * scaleX),
859 pData->pWallpaperBitmap->height - (int)(desY * scaleY),
860 pData->pWallpaperBitmap->bits,
861 pData->pWallpaperBitmap->info,
862 DIB_RGB_COLORS,
863 SRCCOPY);
864 break;
865
866 case PLACEMENT_STRETCH:
867 StretchDIBits(hDC,
868 MONITOR_LEFT,
869 MONITOR_TOP,
870 MONITOR_WIDTH,
871 MONITOR_HEIGHT,
872 0,
873 0,
874 pData->pWallpaperBitmap->width,
875 pData->pWallpaperBitmap->height,
876 pData->pWallpaperBitmap->bits,
877 pData->pWallpaperBitmap->info,
878 DIB_RGB_COLORS,
879 SRCCOPY);
880 break;
881
882 case PLACEMENT_TILE:
883 for (y = 0; y < MONITOR_HEIGHT; y += scaledHeight)
884 {
885 for (x = 0; x < MONITOR_WIDTH; x += scaledWidth)
886 {
887 if ((MONITOR_WIDTH-x) >= scaledWidth)
888 posX = scaledWidth;
889 else
890 posX = MONITOR_WIDTH-x;
891
892
893 if ((MONITOR_HEIGHT-y) >= scaledHeight)
894 posY = scaledHeight;
895 else
896 posY = MONITOR_HEIGHT-y;
897
898 StretchDIBits(hDC,
899 MONITOR_LEFT + x,
900 MONITOR_TOP + y,
901 posX,
902 posY,
903 0,
904 0,
905 pData->pWallpaperBitmap->width * posX / scaledWidth,
906 pData->pWallpaperBitmap->height * posY / scaledHeight,
907 pData->pWallpaperBitmap->bits,
908 pData->pWallpaperBitmap->info,
909 DIB_RGB_COLORS,
910 SRCCOPY);
911 }
912
913 }
914
915 break;
916
917 case PLACEMENT_FIT:
918 if ((MONITOR_WIDTH * scaledHeight) <= (MONITOR_HEIGHT * scaledWidth))
919 {
920 fitFillScaleNum = MONITOR_WIDTH;
921 fitFillScaleDen = scaledWidth;
922 }
923 else
924 {
925 fitFillScaleNum = MONITOR_HEIGHT;
926 fitFillScaleDen = scaledHeight;
927 }
928
929 fitFillWidth = MulDiv(scaledWidth, fitFillScaleNum, fitFillScaleDen);
930 fitFillHeight = MulDiv(scaledHeight, fitFillScaleNum, fitFillScaleDen);
931
932 posX = (MONITOR_WIDTH - fitFillWidth) / 2;
933 posY = (MONITOR_HEIGHT - fitFillHeight) / 2;
934
935 StretchDIBits(hDC,
936 MONITOR_LEFT + posX,
937 MONITOR_TOP + posY,
938 fitFillWidth,
939 fitFillHeight,
940 0,
941 0,
942 pData->pWallpaperBitmap->width,
943 pData->pWallpaperBitmap->height,
944 pData->pWallpaperBitmap->bits,
945 pData->pWallpaperBitmap->info,
946 DIB_RGB_COLORS,
947 SRCCOPY);
948 break;
949
950 case PLACEMENT_FILL:
951 if ((MONITOR_WIDTH * scaledHeight) > (MONITOR_HEIGHT * scaledWidth))
952 {
953 fitFillScaleNum = MONITOR_WIDTH;
954 fitFillScaleDen = scaledWidth;
955 }
956 else
957 {
958 fitFillScaleNum = MONITOR_HEIGHT;
959 fitFillScaleDen = scaledHeight;
960 }
961
962 fitFillWidth = MulDiv(scaledWidth, fitFillScaleNum, fitFillScaleDen);
963 fitFillHeight = MulDiv(scaledHeight, fitFillScaleNum, fitFillScaleDen);
964
965 desX = (((fitFillWidth - MONITOR_WIDTH) * pData->pWallpaperBitmap->width) / (2 * fitFillWidth));
966 desY = (((fitFillHeight - MONITOR_HEIGHT) * pData->pWallpaperBitmap->height) / (2 * fitFillHeight));
967
968 StretchDIBits(hDC,
969 MONITOR_LEFT,
970 MONITOR_TOP,
971 MONITOR_WIDTH,
972 MONITOR_HEIGHT,
973 desX,
974 desY,
975 (MONITOR_WIDTH * pData->pWallpaperBitmap->width) / fitFillWidth,
976 (MONITOR_HEIGHT * pData->pWallpaperBitmap->height) / fitFillHeight,
977 pData->pWallpaperBitmap->bits,
978 pData->pWallpaperBitmap->info,
979 DIB_RGB_COLORS,
980 SRCCOPY);
981 break;
982 }
983 }
984
985 GdiTransparentBlt(draw->hDC,
986 draw->rcItem.left, draw->rcItem.top,
987 draw->rcItem.right-draw->rcItem.left+1,
988 draw->rcItem.bottom-draw->rcItem.top+1,
989 hDC,
990 0, 0,
991 pData->cxSource, pData->cySource,
992 0xFF00FF);
993
994 SelectObject(hDC, hOldObj);
995 DeleteDC(hDC);
996 }
997
998
999 static VOID
1000 SetWallpaper(PBACKGROUND_DATA pData)
1001 {
1002 HKEY regKey;
1003 TCHAR szWallpaper[MAX_PATH];
1004 GpImage *image;
1005 CLSID encoderClsid;
1006 GUID guidFormat;
1007 size_t length = 0;
1008 GpStatus status;
1009
1010 if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, szWallpaper)))
1011 {
1012 return;
1013 }
1014
1015 if (FAILED(StringCbCat(szWallpaper, MAX_PATH, TEXT("\\Wallpaper1.bmp"))))
1016 {
1017 return;
1018 }
1019
1020 if (RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, NULL,
1021 REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &regKey, NULL) != ERROR_SUCCESS)
1022 {
1023 return;
1024 }
1025
1026 if (pData->placementSelection == PLACEMENT_TILE)
1027 {
1028 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (LPBYTE)TEXT("1"), sizeof(TCHAR) * 2);
1029 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (LPBYTE)TEXT("0"), sizeof(TCHAR) * 2);
1030 }
1031
1032 if (pData->placementSelection == PLACEMENT_CENTER)
1033 {
1034 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (LPBYTE)TEXT("0"), sizeof(TCHAR) * 2);
1035 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (LPBYTE)TEXT("0"), sizeof(TCHAR) * 2);
1036 }
1037
1038 if (pData->placementSelection == PLACEMENT_STRETCH)
1039 {
1040 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (LPBYTE)TEXT("0"), sizeof(TCHAR) * 2);
1041 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (LPBYTE)TEXT("2"), sizeof(TCHAR) * 2);
1042 }
1043
1044 if (pData->placementSelection == PLACEMENT_FIT)
1045 {
1046 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (LPBYTE)TEXT("0"), sizeof(TCHAR) * 2);
1047 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (LPBYTE)TEXT("6"), sizeof(TCHAR) * 2);
1048 }
1049
1050 if (pData->placementSelection == PLACEMENT_FILL)
1051 {
1052 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (LPBYTE)TEXT("0"), sizeof(TCHAR) * 2);
1053 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (LPBYTE)TEXT("10"), sizeof(TCHAR) * 3);
1054 }
1055
1056 if (pData->backgroundItems[pData->backgroundSelection].bWallpaper != FALSE)
1057 {
1058 GdipLoadImageFromFile(pData->backgroundItems[pData->backgroundSelection].szFilename, &image);
1059 if (!image)
1060 {
1061 RegCloseKey(regKey);
1062 return;
1063 }
1064
1065 GdipGetImageRawFormat(image, &guidFormat);
1066 if (IsEqualGUID(&guidFormat, &ImageFormatBMP))
1067 {
1068 GdipDisposeImage(image);
1069 RegCloseKey(regKey);
1070 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pData->backgroundItems[pData->backgroundSelection].szFilename, SPIF_UPDATEINIFILE);
1071 return;
1072 }
1073
1074 if (FAILED(GdipGetEncoderClsid(L"image/bmp", &encoderClsid)))
1075 {
1076 GdipDisposeImage(image);
1077 RegCloseKey(regKey);
1078 return;
1079 }
1080
1081 status = GdipSaveImageToFile(image, szWallpaper, &encoderClsid, NULL);
1082
1083 GdipDisposeImage(image);
1084
1085 if (status != Ok)
1086 {
1087 RegCloseKey(regKey);
1088 return;
1089 }
1090
1091 if (SUCCEEDED(StringCchLength(pData->backgroundItems[pData->backgroundSelection].szFilename, MAX_PATH, &length)))
1092 {
1093 RegSetValueEx(regKey,
1094 TEXT("ConvertedWallpaper"),
1095 0,
1096 REG_SZ,
1097 (LPBYTE)pData->backgroundItems[pData->backgroundSelection].szFilename,
1098 (DWORD)((length + 1) * sizeof(TCHAR)));
1099 }
1100
1101 if (SUCCEEDED(StringCchLength(szWallpaper, MAX_PATH, &length)))
1102 {
1103 RegSetValueEx(regKey,
1104 TEXT("OriginalWallpaper"),
1105 0,
1106 REG_SZ,
1107 (LPBYTE)szWallpaper,
1108 (DWORD)((length + 1) * sizeof(TCHAR)));
1109 }
1110
1111 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, szWallpaper, SPIF_UPDATEINIFILE);
1112 }
1113 else
1114 {
1115 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*) TEXT(""), SPIF_UPDATEINIFILE);
1116 }
1117
1118 RegCloseKey(regKey);
1119 }
1120
1121
1122 /* Change system color */
1123 static VOID
1124 SetDesktopBackColor(HWND hwndDlg, PBACKGROUND_DATA pData)
1125 {
1126 HKEY hKey;
1127 INT iElement = COLOR_BACKGROUND;
1128 TCHAR clText[16];
1129 BYTE red, green, blue;
1130
1131 if (!SetSysColors(1, &iElement, &g_GlobalData.desktop_color))
1132 {
1133 /* FIXME: these error texts can need internationalization? */
1134 MessageBox(hwndDlg, TEXT("SetSysColor() failed!"),
1135 TEXT("Error!"), MB_ICONSTOP );
1136 }
1137
1138 if (RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Colors"), 0, NULL,
1139 REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL) != ERROR_SUCCESS)
1140 {
1141 return;
1142 }
1143
1144 red = GetRValue(g_GlobalData.desktop_color);
1145 green = GetGValue(g_GlobalData.desktop_color);
1146 blue = GetBValue(g_GlobalData.desktop_color);
1147
1148 /* Format string to be set to registry */
1149 StringCbPrintf(clText, sizeof(clText), TEXT("%d %d %d"), red, green, blue);
1150 RegSetValueEx(hKey, TEXT("Background"), 0, REG_SZ, (LPBYTE)clText,
1151 (wcslen(clText) + 1) * sizeof(TCHAR));
1152
1153 RegCloseKey(hKey);
1154 }
1155
1156 INT_PTR CALLBACK
1157 BackgroundPageProc(HWND hwndDlg,
1158 UINT uMsg,
1159 WPARAM wParam,
1160 LPARAM lParam)
1161 {
1162 PBACKGROUND_DATA pData;
1163 struct GdiplusStartupInput gdipStartup;
1164
1165 pData = (PBACKGROUND_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1166
1167 switch (uMsg)
1168 {
1169 case WM_INITDIALOG:
1170 pData = (PBACKGROUND_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BACKGROUND_DATA));
1171 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pData);
1172 gdipStartup.GdiplusVersion = 1;
1173 gdipStartup.DebugEventCallback = NULL;
1174 gdipStartup.SuppressBackgroundThread = FALSE;
1175 gdipStartup.SuppressExternalCodecs = FALSE;
1176 GdiplusStartup(&pData->gdipToken, &gdipStartup, NULL);
1177 InitBackgroundDialog(hwndDlg, pData);
1178 break;
1179
1180 case WM_COMMAND:
1181 {
1182 DWORD controlId = LOWORD(wParam);
1183 DWORD command = HIWORD(wParam);
1184
1185 switch (controlId)
1186 {
1187 case IDC_COLOR_BUTTON:
1188 if (command == BN_CLICKED)
1189 OnColorButton(hwndDlg, pData);
1190 break;
1191
1192 case IDC_BROWSE_BUTTON:
1193 if (command == BN_CLICKED)
1194 OnBrowseButton(hwndDlg, pData);
1195 break;
1196
1197 case IDC_PLACEMENT_COMBO:
1198 if (command == CBN_SELCHANGE)
1199 {
1200 pData->placementSelection = (int)SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_GETCURSEL, 0, 0);
1201
1202 InvalidateRect(GetDlgItem(hwndDlg, IDC_BACKGROUND_PREVIEW), NULL, TRUE);
1203
1204 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1205 }
1206 break;
1207 }
1208 } break;
1209
1210 case WM_DRAWITEM:
1211 {
1212 LPDRAWITEMSTRUCT drawItem;
1213 drawItem = (LPDRAWITEMSTRUCT)lParam;
1214
1215 if (drawItem->CtlID == IDC_BACKGROUND_PREVIEW)
1216 {
1217 DrawBackgroundPreview(drawItem, pData);
1218 }
1219
1220 }
1221 break;
1222
1223 case WM_NOTIFY:
1224 {
1225 LPNMHDR lpnm = (LPNMHDR)lParam;
1226
1227 switch(lpnm->code)
1228 {
1229 case PSN_APPLY:
1230 if (pData->bWallpaperChanged)
1231 SetWallpaper(pData);
1232 if (pData->bClrBackgroundChanged)
1233 SetDesktopBackColor(hwndDlg, pData);
1234 SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)_T(""));
1235 return TRUE;
1236
1237 case LVN_ITEMCHANGED:
1238 {
1239 LPNMLISTVIEW nm = (LPNMLISTVIEW)lParam;
1240
1241 if ((nm->uNewState & LVIS_SELECTED) == 0)
1242 return FALSE;
1243
1244 ListViewItemChanged(hwndDlg, pData, nm->iItem);
1245 }
1246 break;
1247 }
1248 }
1249 break;
1250
1251 case WM_DESTROY:
1252 if (pData->pWallpaperBitmap != NULL)
1253 DibFreeImage(pData->pWallpaperBitmap);
1254
1255 DeleteObject(pData->hBitmap);
1256 GdiplusShutdown(pData->gdipToken);
1257 HeapFree(GetProcessHeap(), 0, pData);
1258 break;
1259 }
1260
1261 return FALSE;
1262 }