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