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