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