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