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