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
7 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
8 * Alexey Minnekhanov (minlexx@rambler.ru)
16 #define MAX_BACKGROUNDS 100
18 #define PLACEMENT_CENTER 0
19 #define PLACEMENT_STRETCH 1
20 #define PLACEMENT_TILE 2
22 /* The values in these macros are dependent on the
23 * layout of the monitor image and they must be adjusted
24 * if that image will be changed.
26 #define MONITOR_LEFT 18
27 #define MONITOR_TOP 18
28 #define MONITOR_RIGHT 168
29 #define MONITOR_BOTTOM 128
31 #define MONITOR_WIDTH (MONITOR_RIGHT-MONITOR_LEFT)
32 #define MONITOR_HEIGHT (MONITOR_BOTTOM-MONITOR_TOP)
36 BOOL bWallpaper
; /* Is this background a wallpaper */
38 TCHAR szFilename
[MAX_PATH
];
39 TCHAR szDisplayName
[256];
45 BOOL bWallpaperChanged
;
46 BOOL bClrBackgroundChanged
;
48 BackgroundItem backgroundItems
[MAX_BACKGROUNDS
];
50 PDIBITMAP pWallpaperBitmap
;
52 int placementSelection
;
53 int backgroundSelection
;
55 COLORREF custom_colors
[16];
57 int listViewItemCount
;
66 GLOBAL_DATA g_GlobalData
;
70 GdipGetEncoderClsid(PCWSTR MimeType
, CLSID
*pClsid
)
75 ImageCodecInfo
*codecInfo
;
77 if (GdipGetImageEncodersSize(&num
, &size
) != Ok
||
83 codecInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
89 if (GdipGetImageEncoders(num
, size
, codecInfo
) != Ok
)
91 HeapFree(GetProcessHeap(), 0, codecInfo
);
95 for (i
= 0; i
< num
; i
++)
97 if (!_wcsicmp(codecInfo
[i
].MimeType
, MimeType
))
99 *pClsid
= codecInfo
[i
].Clsid
;
100 HeapFree(GetProcessHeap(), 0, codecInfo
);
105 HeapFree(GetProcessHeap(), 0, codecInfo
);
111 GdipGetSupportedFileExtensions(VOID
)
113 ImageCodecInfo
*codecInfo
;
117 LPWSTR lpBuffer
= NULL
;
119 if (GdipGetImageDecodersSize(&num
, &size
) != Ok
||
125 codecInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
131 if (GdipGetImageDecoders(num
, size
, codecInfo
) != Ok
)
133 HeapFree(GetProcessHeap(), 0, codecInfo
);
138 for (i
= 0; i
< num
; ++i
)
140 size
= size
+ (UINT
)wcslen(codecInfo
[i
].FilenameExtension
) + 1;
143 size
= (size
+ 1) * sizeof(WCHAR
);
145 lpBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
148 HeapFree(GetProcessHeap(), 0, codecInfo
);
152 for (i
= 0; i
< num
; ++i
)
154 StringCbCatW(lpBuffer
, size
, codecInfo
[i
].FilenameExtension
);
157 StringCbCatW(lpBuffer
, size
, L
";");
161 HeapFree(GetProcessHeap(), 0, codecInfo
);
168 AddWallpapersFromDirectory(UINT uCounter
, HWND hwndBackgroundList
, BackgroundItem
*backgroundItem
, PDATA pData
, LPCTSTR wallpaperFilename
, LPCTSTR wallpaperDirectory
)
172 TCHAR szSearchPath
[MAX_PATH
];
173 LPTSTR szFileTypes
= NULL
;
174 TCHAR separators
[] = TEXT(";");
182 szFileTypes
= GdipGetSupportedFileExtensions();
188 token
= _tcstok(szFileTypes
, separators
);
189 while (token
!= NULL
)
191 if (!PathCombine(szSearchPath
, wallpaperDirectory
, token
))
193 HeapFree(GetProcessHeap(), 0, szFileTypes
);
197 hFind
= FindFirstFile(szSearchPath
, &fd
);
198 while (hFind
!= INVALID_HANDLE_VALUE
)
200 TCHAR filename
[MAX_PATH
];
202 if (!PathCombine(filename
, wallpaperDirectory
, fd
.cFileName
))
205 HeapFree(GetProcessHeap(), 0, szFileTypes
);
209 /* Don't add any hidden bitmaps. Also don't add current wallpaper once more. */
210 if (((fd
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) == 0) && (_tcsicmp(wallpaperFilename
, filename
) != 0))
212 himl
= (HIMAGELIST
)SHGetFileInfo(filename
,
216 SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
|
223 (void)ListView_SetImageList(hwndBackgroundList
, himl
, LVSIL_SMALL
);
226 backgroundItem
= &pData
->backgroundItems
[pData
->listViewItemCount
];
228 backgroundItem
->bWallpaper
= TRUE
;
230 hr
= StringCbCopy(backgroundItem
->szDisplayName
, sizeof(backgroundItem
->szDisplayName
), sfi
.szDisplayName
);
234 HeapFree(GetProcessHeap(), 0, szFileTypes
);
238 PathRemoveExtension(backgroundItem
->szDisplayName
);
240 hr
= StringCbCopy(backgroundItem
->szFilename
, sizeof(backgroundItem
->szFilename
), filename
);
244 HeapFree(GetProcessHeap(), 0, szFileTypes
);
248 ZeroMemory(&listItem
, sizeof(LV_ITEM
));
249 listItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
250 listItem
.pszText
= backgroundItem
->szDisplayName
;
252 listItem
.iImage
= sfi
.iIcon
;
253 listItem
.iItem
= pData
->listViewItemCount
;
254 listItem
.lParam
= pData
->listViewItemCount
;
256 (void)ListView_InsertItem(hwndBackgroundList
, &listItem
);
258 pData
->listViewItemCount
++;
261 if (!FindNextFile(hFind
, &fd
))
265 token
= _tcstok(NULL
, separators
);
269 HeapFree(GetProcessHeap(), 0, szFileTypes
);
275 /* Add the images in the C:\ReactOS, the wallpaper directory and the current wallpaper if any */
277 AddListViewItems(HWND hwndDlg
, PDATA pData
)
279 TCHAR szSearchPath
[MAX_PATH
];
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
;
293 BackgroundItem
*backgroundItem
= NULL
;
294 HWND hwndBackgroundList
;
297 hwndBackgroundList
= GetDlgItem(hwndDlg
, IDC_BACKGROUND_LIST
);
299 GetClientRect(hwndBackgroundList
, &clientRect
);
301 /* Add a new column to the list */
302 ZeroMemory(&dummy
, sizeof(LV_COLUMN
));
303 dummy
.mask
= LVCF_SUBITEM
| LVCF_WIDTH
;
305 dummy
.cx
= (clientRect
.right
- clientRect
.left
) - GetSystemMetrics(SM_CXVSCROLL
);
306 (void)ListView_InsertColumn(hwndBackgroundList
, 0, &dummy
);
308 /* Add the "None" item */
309 backgroundItem
= &pData
->backgroundItems
[pData
->listViewItemCount
];
310 backgroundItem
->bWallpaper
= FALSE
;
313 backgroundItem
->szDisplayName
,
314 sizeof(backgroundItem
->szDisplayName
) / sizeof(TCHAR
));
316 ZeroMemory(&listItem
, sizeof(LV_ITEM
));
317 listItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
319 listItem
.pszText
= backgroundItem
->szDisplayName
;
320 listItem
.iImage
= -1;
321 listItem
.iItem
= pData
->listViewItemCount
;
322 listItem
.lParam
= pData
->listViewItemCount
;
324 (void)ListView_InsertItem(hwndBackgroundList
, &listItem
);
325 ListView_SetItemState(hwndBackgroundList
,
326 pData
->listViewItemCount
,
330 pData
->listViewItemCount
++;
332 /* Add current wallpaper if any */
333 result
= RegOpenKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Desktop"), 0, KEY_QUERY_VALUE
, ®Key
);
334 if (result
== ERROR_SUCCESS
)
336 result
= RegQueryValueEx(regKey
, TEXT("Wallpaper"), 0, &varType
, (LPBYTE
)wallpaperFilename
, &bufferSize
);
337 if ((result
== ERROR_SUCCESS
) && (_tcslen(wallpaperFilename
) > 0))
339 bufferSize
= sizeof(originalWallpaper
);
340 result
= RegQueryValueEx(regKey
, TEXT("OriginalWallpaper"), 0, &varType
, (LPBYTE
)originalWallpaper
, &bufferSize
);
342 /* If Wallpaper and OriginalWallpaper are the same, try to retrieve ConvertedWallpaper and use it instead of Wallpaper */
343 if ((result
== ERROR_SUCCESS
) && (_tcslen(originalWallpaper
) > 0) && (_tcsicmp(wallpaperFilename
, originalWallpaper
) == 0))
345 bufferSize
= sizeof(originalWallpaper
);
346 result
= RegQueryValueEx(regKey
, TEXT("ConvertedWallpaper"), 0, &varType
, (LPBYTE
)originalWallpaper
, &bufferSize
);
348 if ((result
== ERROR_SUCCESS
) && (_tcslen(originalWallpaper
) > 0))
350 hr
= StringCbCopy(wallpaperFilename
, sizeof(wallpaperFilename
), originalWallpaper
);
359 /* Allow environment variables in file name */
360 if (ExpandEnvironmentStrings(wallpaperFilename
, buffer
, MAX_PATH
))
362 hr
= StringCbCopy(wallpaperFilename
, sizeof(wallpaperFilename
), buffer
);
370 himl
= (HIMAGELIST
)SHGetFileInfo(wallpaperFilename
,
374 SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
|
380 (void)ListView_SetImageList(hwndBackgroundList
, himl
, LVSIL_SMALL
);
383 backgroundItem
= &pData
->backgroundItems
[pData
->listViewItemCount
];
385 backgroundItem
->bWallpaper
= TRUE
;
387 hr
= StringCbCopy(backgroundItem
->szDisplayName
, sizeof(backgroundItem
->szDisplayName
), sfi
.szDisplayName
);
394 PathRemoveExtension(backgroundItem
->szDisplayName
);
396 hr
= StringCbCopy(backgroundItem
->szFilename
, sizeof(backgroundItem
->szFilename
), wallpaperFilename
);
403 ZeroMemory(&listItem
, sizeof(LV_ITEM
));
404 listItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
406 listItem
.pszText
= backgroundItem
->szDisplayName
;
407 listItem
.iImage
= sfi
.iIcon
;
408 listItem
.iItem
= pData
->listViewItemCount
;
409 listItem
.lParam
= pData
->listViewItemCount
;
411 (void)ListView_InsertItem(hwndBackgroundList
, &listItem
);
412 ListView_SetItemState(hwndBackgroundList
,
413 pData
->listViewItemCount
,
417 pData
->listViewItemCount
++;
424 /* Add all the images in the C:\ReactOS directory. */
425 if (GetWindowsDirectory(szSearchPath
, MAX_PATH
))
427 i
= AddWallpapersFromDirectory(i
, hwndBackgroundList
, backgroundItem
, pData
, wallpaperFilename
, szSearchPath
);
430 /* Add all the images in the wallpaper directory. */
431 if (SHRegGetPath(HKEY_LOCAL_MACHINE
, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"), TEXT("WallPaperDir"), szSearchPath
, 0) == ERROR_SUCCESS
)
433 i
= AddWallpapersFromDirectory(i
, hwndBackgroundList
, backgroundItem
, pData
, wallpaperFilename
, szSearchPath
);
439 InitBackgroundDialog(HWND hwndDlg
, PDATA pData
)
444 DWORD bufferSize
= sizeof(szBuffer
);
447 AddListViewItems(hwndDlg
, pData
);
449 LoadString(hApplet
, IDS_CENTER
, szString
, sizeof(szString
) / sizeof(TCHAR
));
450 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_INSERTSTRING
, PLACEMENT_CENTER
, (LPARAM
)szString
);
452 LoadString(hApplet
, IDS_STRETCH
, szString
, sizeof(szString
) / sizeof(TCHAR
));
453 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_INSERTSTRING
, PLACEMENT_STRETCH
, (LPARAM
)szString
);
455 LoadString(hApplet
, IDS_TILE
, szString
, sizeof(szString
) / sizeof(TCHAR
));
456 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_INSERTSTRING
, PLACEMENT_TILE
, (LPARAM
)szString
);
458 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_SETCURSEL
, PLACEMENT_CENTER
, 0);
459 pData
->placementSelection
= PLACEMENT_CENTER
;
461 pData
->hBitmap
= (HBITMAP
) LoadImage(hApplet
, MAKEINTRESOURCE(IDC_MONITOR
), IMAGE_BITMAP
, 0, 0, LR_DEFAULTCOLOR
);
462 if (pData
->hBitmap
!= NULL
)
464 GetObject(pData
->hBitmap
, sizeof(BITMAP
), &bitmap
);
466 pData
->cxSource
= bitmap
.bmWidth
;
467 pData
->cySource
= bitmap
.bmHeight
;
470 /* Load the default settings from the registry */
471 if (RegOpenKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Desktop"), 0, KEY_QUERY_VALUE
, ®Key
) != ERROR_SUCCESS
)
476 if (RegQueryValueEx(regKey
, TEXT("WallpaperStyle"), 0, NULL
, (LPBYTE
)szBuffer
, &bufferSize
) == ERROR_SUCCESS
)
478 if (_ttoi(szBuffer
) == 0)
480 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_SETCURSEL
, PLACEMENT_CENTER
, 0);
481 pData
->placementSelection
= PLACEMENT_CENTER
;
484 if (_ttoi(szBuffer
) == 2)
486 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_SETCURSEL
, PLACEMENT_STRETCH
, 0);
487 pData
->placementSelection
= PLACEMENT_STRETCH
;
491 if (RegQueryValueEx(regKey
, TEXT("TileWallpaper"), 0, NULL
, (LPBYTE
)szBuffer
, &bufferSize
) == ERROR_SUCCESS
)
493 if (_ttoi(szBuffer
) == 1)
495 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_SETCURSEL
, PLACEMENT_TILE
, 0);
496 pData
->placementSelection
= PLACEMENT_TILE
;
505 OnColorButton(HWND hwndDlg
, PDATA pData
)
507 /* Load custom colors from Registry */
509 LONG res
= ERROR_SUCCESS
;
512 res
= RegCreateKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Appearance"), 0, NULL
,
513 REG_OPTION_NON_VOLATILE
, KEY_QUERY_VALUE
, NULL
, &hKey
, NULL
);
514 /* Now the key is either created or opened existing, if res == ERROR_SUCCESS */
515 if (res
== ERROR_SUCCESS
)
518 DWORD dwType
= REG_BINARY
;
519 DWORD cbData
= sizeof(pData
->custom_colors
);
520 res
= RegQueryValueEx(hKey
, TEXT("CustomColors"), NULL
, &dwType
,
521 (LPBYTE
)pData
->custom_colors
, &cbData
);
526 /* Launch ChooseColor() dialog */
528 cc
.lStructSize
= sizeof(CHOOSECOLOR
);
529 cc
.hwndOwner
= hwndDlg
;
531 cc
.rgbResult
= g_GlobalData
.desktop_color
;
532 cc
.lpCustColors
= pData
->custom_colors
;
533 cc
.Flags
= CC_ANYCOLOR
| /* Causes the dialog box to display all available colors in the set of basic colors. */
534 CC_FULLOPEN
| /* opens dialog in full size */
535 CC_RGBINIT
; /* init chosen color by rgbResult value */
538 cc
.lpTemplateName
= NULL
;
539 if (ChooseColor(&cc
))
541 /* Save selected color to var */
542 g_GlobalData
.desktop_color
= cc
.rgbResult
;
543 pData
->bClrBackgroundChanged
= TRUE
;
545 /* Apply button will be activated */
546 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
548 /* Window will be updated :) */
549 InvalidateRect(GetDlgItem(hwndDlg
, IDC_BACKGROUND_PREVIEW
), NULL
, TRUE
);
551 /* Save custom colors to reg. To this moment key must be created already. See above */
552 res
= RegOpenKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Appearance"), 0,
553 KEY_SET_VALUE
, &hKey
);
554 if (res
== ERROR_SUCCESS
)
557 RegSetValueEx(hKey
, TEXT("CustomColors"), 0, REG_BINARY
,
558 (LPBYTE
)pData
->custom_colors
, sizeof(pData
->custom_colors
));
567 * ListView_FindItem() Macro: Searches for a list-view item with the specified
568 * characteristics. Returns the index of the item if successful, or -1 otherwise
571 CheckListViewFilenameExists(HWND hwndList
, LPCTSTR tszFileName
)
576 lvfi
.flags
= LVFI_STRING
; /* Search item by EXACT string */
577 lvfi
.psz
= tszFileName
; /* String to search */
579 /* Other items of this structure are not valid, besacuse flags are not set. */
580 retVal
= ListView_FindItem(hwndList
, -1, &lvfi
);
582 return TRUE
; /* item found! */
584 return FALSE
; /* item not found. */
589 OnBrowseButton(HWND hwndDlg
, PDATA pData
)
592 TCHAR filename
[MAX_PATH
];
593 TCHAR fileTitle
[256];
596 BackgroundItem
*backgroundItem
= NULL
;
599 HWND hwndBackgroundList
;
602 TCHAR filterdesc
[MAX_PATH
];
608 hwndBackgroundList
= GetDlgItem(hwndDlg
, IDC_BACKGROUND_LIST
);
610 ZeroMemory(&ofn
, sizeof(OPENFILENAME
));
612 ofn
.lStructSize
= sizeof(OPENFILENAME
);
613 ofn
.hwndOwner
= hwndDlg
;
614 ofn
.lpstrFile
= filename
;
616 LoadString(hApplet
, IDS_BACKGROUND_COMDLG_FILTER
, filterdesc
, sizeof(filterdesc
) / sizeof(TCHAR
));
618 extensions
= GdipGetSupportedFileExtensions();
624 buffersize
= (_tcslen(extensions
) * 2 + 6) * sizeof(TCHAR
) + sizeof(filterdesc
);
626 filter
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buffersize
);
629 HeapFree(GetProcessHeap(), 0, extensions
);
633 sizeRemain
= buffersize
;
636 if (FAILED(StringCbPrintfEx(c
, sizeRemain
, &c
, &sizeRemain
, 0, L
"%ls (%ls)", filterdesc
, extensions
)))
638 HeapFree(GetProcessHeap(), 0, extensions
);
639 HeapFree(GetProcessHeap(), 0, filter
);
644 sizeRemain
-= sizeof(*c
);
646 if (FAILED(StringCbPrintfEx(c
, sizeRemain
, &c
, &sizeRemain
, 0, L
"%ls", extensions
)))
648 HeapFree(GetProcessHeap(), 0, extensions
);
649 HeapFree(GetProcessHeap(), 0, filter
);
653 HeapFree(GetProcessHeap(), 0, extensions
);
655 /* Set lpstrFile[0] to '\0' so that GetOpenFileName does not
656 * use the contents of szFile to initialize itself */
657 ofn
.lpstrFile
[0] = TEXT('\0');
658 ofn
.nMaxFile
= MAX_PATH
;
659 ofn
.lpstrFilter
= filter
;
660 ofn
.nFilterIndex
= 0;
661 ofn
.lpstrFileTitle
= fileTitle
;
662 ofn
.nMaxFileTitle
= 256;
663 ofn
.lpstrInitialDir
= NULL
;
664 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_FILEMUSTEXIST
| OFN_HIDEREADONLY
;
666 success
= GetOpenFileName(&ofn
);
667 HeapFree(GetProcessHeap(), 0, filter
);
671 /* Check if there is already a entry that holds this filename */
672 if (CheckListViewFilenameExists(hwndBackgroundList
, ofn
.lpstrFileTitle
) == TRUE
)
675 if (pData
->listViewItemCount
> (MAX_BACKGROUNDS
- 1))
678 SHGetFileInfo(filename
,
682 SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
| SHGFI_DISPLAYNAME
);
684 backgroundItem
= &pData
->backgroundItems
[pData
->listViewItemCount
];
686 backgroundItem
->bWallpaper
= TRUE
;
688 hr
= StringCbCopy(backgroundItem
->szDisplayName
, sizeof(backgroundItem
->szDisplayName
), sfi
.szDisplayName
);
691 p
= _tcsrchr(backgroundItem
->szDisplayName
, _T('.'));
694 hr
= StringCbCopy(backgroundItem
->szFilename
, sizeof(backgroundItem
->szFilename
), filename
);
698 ZeroMemory(&listItem
, sizeof(LV_ITEM
));
699 listItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
701 listItem
.pszText
= backgroundItem
->szDisplayName
;
702 listItem
.iImage
= sfi
.iIcon
;
703 listItem
.iItem
= pData
->listViewItemCount
;
704 listItem
.lParam
= pData
->listViewItemCount
;
706 (void)ListView_InsertItem(hwndBackgroundList
, &listItem
);
707 ListView_SetItemState(hwndBackgroundList
,
708 pData
->listViewItemCount
,
711 SendMessage(hwndBackgroundList
, WM_VSCROLL
, SB_BOTTOM
, 0);
713 pData
->listViewItemCount
++;
719 ListViewItemChanged(HWND hwndDlg
, PDATA pData
, int itemIndex
)
721 BackgroundItem
*backgroundItem
= NULL
;
723 pData
->backgroundSelection
= itemIndex
;
724 backgroundItem
= &pData
->backgroundItems
[pData
->backgroundSelection
];
726 if (pData
->pWallpaperBitmap
!= NULL
)
728 DibFreeImage(pData
->pWallpaperBitmap
);
729 pData
->pWallpaperBitmap
= NULL
;
732 if (backgroundItem
->bWallpaper
== TRUE
)
734 pData
->pWallpaperBitmap
= DibLoadImage(backgroundItem
->szFilename
);
736 if (pData
->pWallpaperBitmap
== NULL
)
740 pData
->bWallpaperChanged
= TRUE
;
742 InvalidateRect(GetDlgItem(hwndDlg
, IDC_BACKGROUND_PREVIEW
),
745 EnableWindow(GetDlgItem(hwndDlg
, IDC_PLACEMENT_COMBO
),
746 backgroundItem
->bWallpaper
);
748 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
753 DrawBackgroundPreview(LPDRAWITEMSTRUCT draw
, PDATA pData
)
773 hDC
= CreateCompatibleDC(draw
->hDC
);
774 hOldObj
= SelectObject(hDC
, pData
->hBitmap
);
776 if (pData
->backgroundItems
[pData
->backgroundSelection
].bWallpaper
== FALSE
)
778 /* Update desktop background color image */
779 hBrush
= CreateSolidBrush(g_GlobalData
.desktop_color
);
780 FillRect(hDC
, &rcItem
, hBrush
);
781 DeleteObject(hBrush
);
784 if (pData
->pWallpaperBitmap
!= NULL
)
786 scaleX
= ((float)GetSystemMetrics(SM_CXSCREEN
) - 1) / (float)MONITOR_WIDTH
;
787 scaleY
= ((float)GetSystemMetrics(SM_CYSCREEN
) - 1) / (float)MONITOR_HEIGHT
;
789 scaledWidth
= (int)(pData
->pWallpaperBitmap
->width
/ scaleX
);
790 scaledHeight
= (int)(pData
->pWallpaperBitmap
->height
/ scaleY
);
792 FillRect(hDC
, &rcItem
, GetSysColorBrush(COLOR_BACKGROUND
));
794 SetStretchBltMode(hDC
, COLORONCOLOR
);
796 switch (pData
->placementSelection
)
798 case PLACEMENT_CENTER
:
799 posX
= (MONITOR_WIDTH
- scaledWidth
+ 1) / 2;
800 posY
= (MONITOR_HEIGHT
- scaledHeight
+ 1) / 2;
804 if (posX
< 0) { desX
= -posX
/ 2; posX
= 0; }
805 if (posY
< 0) { desY
= -posY
/ 2; posY
= 0; }
807 if (scaledWidth
> MONITOR_WIDTH
)
808 scaledWidth
= MONITOR_WIDTH
;
810 if (scaledHeight
> MONITOR_HEIGHT
)
811 scaledHeight
= MONITOR_HEIGHT
;
820 pData
->pWallpaperBitmap
->width
- (int)(desX
* scaleX
),
821 pData
->pWallpaperBitmap
->height
- (int)(desY
* scaleY
),
822 pData
->pWallpaperBitmap
->bits
,
823 pData
->pWallpaperBitmap
->info
,
828 case PLACEMENT_STRETCH
:
836 pData
->pWallpaperBitmap
->width
,
837 pData
->pWallpaperBitmap
->height
,
838 pData
->pWallpaperBitmap
->bits
,
839 pData
->pWallpaperBitmap
->info
,
845 for (y
= 0; y
< MONITOR_HEIGHT
; y
+= scaledHeight
)
847 for (x
= 0; x
< MONITOR_WIDTH
; x
+= scaledWidth
)
849 if ((MONITOR_WIDTH
-x
) >= scaledWidth
)
852 posX
= MONITOR_WIDTH
-x
;
855 if ((MONITOR_HEIGHT
-y
) >= scaledHeight
)
858 posY
= MONITOR_HEIGHT
-y
;
867 pData
->pWallpaperBitmap
->width
* posX
/ scaledWidth
,
868 pData
->pWallpaperBitmap
->height
* posY
/ scaledHeight
,
869 pData
->pWallpaperBitmap
->bits
,
870 pData
->pWallpaperBitmap
->info
,
881 GdiTransparentBlt(draw
->hDC
,
882 draw
->rcItem
.left
, draw
->rcItem
.top
,
883 draw
->rcItem
.right
-draw
->rcItem
.left
+1,
884 draw
->rcItem
.bottom
-draw
->rcItem
.top
+1,
887 pData
->cxSource
, pData
->cySource
,
890 SelectObject(hDC
, hOldObj
);
896 SetWallpaper(PDATA pData
)
899 TCHAR szWallpaper
[MAX_PATH
];
906 if (FAILED(SHGetFolderPath(NULL
, CSIDL_LOCAL_APPDATA
| CSIDL_FLAG_CREATE
, NULL
, 0, szWallpaper
)))
911 if (FAILED(StringCbCat(szWallpaper
, MAX_PATH
, TEXT("\\Wallpaper1.bmp"))))
916 if (RegCreateKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Desktop"), 0, NULL
,
917 REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, ®Key
, NULL
) != ERROR_SUCCESS
)
922 if (pData
->placementSelection
== PLACEMENT_TILE
)
924 RegSetValueEx(regKey
, TEXT("TileWallpaper"), 0, REG_SZ
, (LPBYTE
)TEXT("1"), sizeof(TCHAR
) * 2);
925 RegSetValueEx(regKey
, TEXT("WallpaperStyle"), 0, REG_SZ
, (LPBYTE
)TEXT("0"), sizeof(TCHAR
) * 2);
928 if (pData
->placementSelection
== PLACEMENT_CENTER
)
930 RegSetValueEx(regKey
, TEXT("TileWallpaper"), 0, REG_SZ
, (LPBYTE
)TEXT("0"), sizeof(TCHAR
) * 2);
931 RegSetValueEx(regKey
, TEXT("WallpaperStyle"), 0, REG_SZ
, (LPBYTE
)TEXT("0"), sizeof(TCHAR
) * 2);
934 if (pData
->placementSelection
== PLACEMENT_STRETCH
)
936 RegSetValueEx(regKey
, TEXT("TileWallpaper"), 0, REG_SZ
, (LPBYTE
)TEXT("0"), sizeof(TCHAR
) * 2);
937 RegSetValueEx(regKey
, TEXT("WallpaperStyle"), 0, REG_SZ
, (LPBYTE
)TEXT("2"), sizeof(TCHAR
) * 2);
940 if (pData
->backgroundItems
[pData
->backgroundSelection
].bWallpaper
== TRUE
)
942 GdipLoadImageFromFile(pData
->backgroundItems
[pData
->backgroundSelection
].szFilename
, &image
);
949 GdipGetImageRawFormat(image
, &guidFormat
);
950 if (IsEqualGUID(&guidFormat
, &ImageFormatBMP
))
952 GdipDisposeImage(image
);
954 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, pData
->backgroundItems
[pData
->backgroundSelection
].szFilename
, SPIF_UPDATEINIFILE
);
958 if (FAILED(GdipGetEncoderClsid(L
"image/bmp", &encoderClsid
)))
960 GdipDisposeImage(image
);
965 status
= GdipSaveImageToFile(image
, szWallpaper
, &encoderClsid
, NULL
);
967 GdipDisposeImage(image
);
975 if (SUCCEEDED(StringCchLength(pData
->backgroundItems
[pData
->backgroundSelection
].szFilename
, MAX_PATH
, &length
)))
977 RegSetValueEx(regKey
,
978 TEXT("ConvertedWallpaper"),
981 (LPBYTE
)pData
->backgroundItems
[pData
->backgroundSelection
].szFilename
,
982 (DWORD
)((length
+ 1) * sizeof(TCHAR
)));
985 if (SUCCEEDED(StringCchLength(szWallpaper
, MAX_PATH
, &length
)))
987 RegSetValueEx(regKey
,
988 TEXT("OriginalWallpaper"),
992 (DWORD
)((length
+ 1) * sizeof(TCHAR
)));
995 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, szWallpaper
, SPIF_UPDATEINIFILE
);
999 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, (void*) TEXT(""), SPIF_UPDATEINIFILE
);
1002 RegCloseKey(regKey
);
1006 /* Change system color */
1008 SetDesktopBackColor(HWND hwndDlg
, DATA
*pData
)
1011 INT iElement
= COLOR_BACKGROUND
;
1013 BYTE red
, green
, blue
;
1015 if (!SetSysColors(1, &iElement
, &g_GlobalData
.desktop_color
))
1017 /* FIXME: these error texts can need internationalization? */
1018 MessageBox(hwndDlg
, TEXT("SetSysColor() failed!"),
1019 TEXT("Error!"), MB_ICONSTOP
);
1022 if (RegCreateKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Colors"), 0, NULL
,
1023 REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
1028 red
= GetRValue(g_GlobalData
.desktop_color
);
1029 green
= GetGValue(g_GlobalData
.desktop_color
);
1030 blue
= GetBValue(g_GlobalData
.desktop_color
);
1032 /* Format string to be set to registry */
1033 StringCbPrintf(clText
, sizeof(clText
), TEXT("%d %d %d"), red
, green
, blue
);
1034 RegSetValueEx(hKey
, TEXT("Background"), 0, REG_SZ
, (LPBYTE
)clText
,
1035 (wcslen(clText
) + 1) * sizeof(TCHAR
));
1041 BackgroundPageProc(HWND hwndDlg
,
1047 struct GdiplusStartupInput gdipStartup
;
1049 pData
= (PDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1054 pData
= (DATA
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DATA
));
1055 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pData
);
1056 gdipStartup
.GdiplusVersion
= 1;
1057 gdipStartup
.DebugEventCallback
= NULL
;
1058 gdipStartup
.SuppressBackgroundThread
= FALSE
;
1059 gdipStartup
.SuppressExternalCodecs
= FALSE
;
1060 GdiplusStartup(&pData
->gdipToken
, &gdipStartup
, NULL
);
1061 InitBackgroundDialog(hwndDlg
, pData
);
1066 DWORD controlId
= LOWORD(wParam
);
1067 DWORD command
= HIWORD(wParam
);
1071 case IDC_COLOR_BUTTON
:
1072 if (command
== BN_CLICKED
)
1073 OnColorButton(hwndDlg
, pData
);
1076 case IDC_BROWSE_BUTTON
:
1077 if (command
== BN_CLICKED
)
1078 OnBrowseButton(hwndDlg
, pData
);
1081 case IDC_PLACEMENT_COMBO
:
1082 if (command
== CBN_SELCHANGE
)
1084 pData
->placementSelection
= (int)SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_GETCURSEL
, 0, 0);
1086 InvalidateRect(GetDlgItem(hwndDlg
, IDC_BACKGROUND_PREVIEW
), NULL
, TRUE
);
1088 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1096 LPDRAWITEMSTRUCT drawItem
;
1097 drawItem
= (LPDRAWITEMSTRUCT
)lParam
;
1099 if (drawItem
->CtlID
== IDC_BACKGROUND_PREVIEW
)
1101 DrawBackgroundPreview(drawItem
, pData
);
1109 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1114 if (pData
->bWallpaperChanged
)
1115 SetWallpaper(pData
);
1116 if (pData
->bClrBackgroundChanged
)
1117 SetDesktopBackColor(hwndDlg
, pData
);
1118 SendMessage(HWND_BROADCAST
, WM_SETTINGCHANGE
, 0, (LPARAM
)_T(""));
1121 case LVN_ITEMCHANGED
:
1123 LPNMLISTVIEW nm
= (LPNMLISTVIEW
)lParam
;
1125 if ((nm
->uNewState
& LVIS_SELECTED
) == 0)
1128 ListViewItemChanged(hwndDlg
, pData
, nm
->iItem
);
1136 if (pData
->pWallpaperBitmap
!= NULL
)
1137 DibFreeImage(pData
->pWallpaperBitmap
);
1139 DeleteObject(pData
->hBitmap
);
1140 GdiplusShutdown(pData
->gdipToken
);
1141 HeapFree(GetProcessHeap(), 0, pData
);