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