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 dependant 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(";");
183 szFileTypes
= GdipGetSupportedFileExtensions();
189 token
= _tcstok(szFileTypes
, separators
);
190 while (token
!= NULL
)
192 if (!PathCombine(szSearchPath
, wallpaperDirectory
, token
))
194 HeapFree(GetProcessHeap(), 0, szFileTypes
);
198 hFind
= FindFirstFile(szSearchPath
, &fd
);
199 while (hFind
!= INVALID_HANDLE_VALUE
)
201 TCHAR filename
[MAX_PATH
];
203 if (!PathCombine(filename
, wallpaperDirectory
, fd
.cFileName
))
206 HeapFree(GetProcessHeap(), 0, szFileTypes
);
210 /* Don't add any hidden bitmaps. Also don't add current wallpaper once more. */
211 if (((fd
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) == 0) && (_tcsicmp(wallpaperFilename
, filename
) != 0))
213 himl
= (HIMAGELIST
)SHGetFileInfo(filename
,
217 SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
|
225 (void)ListView_SetImageList(hwndBackgroundList
, himl
, LVSIL_SMALL
);
228 backgroundItem
= &pData
->backgroundItems
[pData
->listViewItemCount
];
230 backgroundItem
->bWallpaper
= TRUE
;
232 hr
= StringCbCopy(backgroundItem
->szDisplayName
, sizeof(backgroundItem
->szDisplayName
), sfi
.szDisplayName
);
236 HeapFree(GetProcessHeap(), 0, szFileTypes
);
240 PathRemoveExtension(backgroundItem
->szDisplayName
);
242 hr
= StringCbCopy(backgroundItem
->szFilename
, sizeof(backgroundItem
->szFilename
), filename
);
246 HeapFree(GetProcessHeap(), 0, szFileTypes
);
250 ZeroMemory(&listItem
, sizeof(LV_ITEM
));
251 listItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
252 listItem
.pszText
= backgroundItem
->szDisplayName
;
254 listItem
.iImage
= sfi
.iIcon
;
255 listItem
.iItem
= pData
->listViewItemCount
;
256 listItem
.lParam
= pData
->listViewItemCount
;
258 (void)ListView_InsertItem(hwndBackgroundList
, &listItem
);
260 pData
->listViewItemCount
++;
263 if(!FindNextFile(hFind
, &fd
))
267 token
= _tcstok(NULL
, separators
);
271 HeapFree(GetProcessHeap(), 0, szFileTypes
);
277 /* Add the images in the C:\ReactOS, the wallpaper directory and the current wallpaper if any */
279 AddListViewItems(HWND hwndDlg
, PDATA pData
)
281 TCHAR szSearchPath
[MAX_PATH
];
288 TCHAR wallpaperFilename
[MAX_PATH
];
289 TCHAR originalWallpaper
[MAX_PATH
];
290 DWORD bufferSize
= sizeof(wallpaperFilename
);
291 TCHAR buffer
[MAX_PATH
];
292 DWORD varType
= REG_SZ
;
295 BackgroundItem
*backgroundItem
= NULL
;
296 HWND hwndBackgroundList
;
299 hwndBackgroundList
= GetDlgItem(hwndDlg
, IDC_BACKGROUND_LIST
);
301 GetClientRect(hwndBackgroundList
, &clientRect
);
303 /* Add a new column to the list */
304 ZeroMemory(&dummy
, sizeof(LV_COLUMN
));
305 dummy
.mask
= LVCF_SUBITEM
| LVCF_WIDTH
;
307 dummy
.cx
= (clientRect
.right
- clientRect
.left
) - GetSystemMetrics(SM_CXVSCROLL
);
308 (void)ListView_InsertColumn(hwndBackgroundList
, 0, &dummy
);
310 /* Add the "None" item */
311 backgroundItem
= &pData
->backgroundItems
[pData
->listViewItemCount
];
312 backgroundItem
->bWallpaper
= FALSE
;
315 backgroundItem
->szDisplayName
,
316 sizeof(backgroundItem
->szDisplayName
) / sizeof(TCHAR
));
318 ZeroMemory(&listItem
, sizeof(LV_ITEM
));
319 listItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
321 listItem
.pszText
= backgroundItem
->szDisplayName
;
322 listItem
.iImage
= -1;
323 listItem
.iItem
= pData
->listViewItemCount
;
324 listItem
.lParam
= pData
->listViewItemCount
;
326 (void)ListView_InsertItem(hwndBackgroundList
, &listItem
);
327 ListView_SetItemState(hwndBackgroundList
,
328 pData
->listViewItemCount
,
332 pData
->listViewItemCount
++;
334 /* Add current wallpaper if any */
335 result
= RegOpenKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS
, ®Key
);
336 if (result
== ERROR_SUCCESS
)
338 result
= RegQueryValueEx(regKey
, TEXT("Wallpaper"), 0, &varType
, (LPBYTE
)wallpaperFilename
, &bufferSize
);
339 if ((result
== ERROR_SUCCESS
) && (_tcslen(wallpaperFilename
) > 0))
341 bufferSize
= sizeof(originalWallpaper
);
342 result
= RegQueryValueEx(regKey
, TEXT("OriginalWallpaper"), 0, &varType
, (LPBYTE
)originalWallpaper
, &bufferSize
);
344 /* If Wallpaper and OriginalWallpaper are the same, try to retrieve ConvertedWallpaper and use it instead of Wallpaper */
345 if ((result
== ERROR_SUCCESS
) && (_tcslen(originalWallpaper
) > 0) && (_tcsicmp(wallpaperFilename
, originalWallpaper
) == 0))
347 bufferSize
= sizeof(originalWallpaper
);
348 result
= RegQueryValueEx(regKey
, TEXT("ConvertedWallpaper"), 0, &varType
, (LPBYTE
)originalWallpaper
, &bufferSize
);
350 if ((result
== ERROR_SUCCESS
) && (_tcslen(originalWallpaper
) > 0))
352 hr
= StringCbCopy(wallpaperFilename
, sizeof(wallpaperFilename
), originalWallpaper
);
362 /* Allow environment variables in file name */
363 if (ExpandEnvironmentStrings(wallpaperFilename
, buffer
, MAX_PATH
))
365 hr
= StringCbCopy(wallpaperFilename
, sizeof(wallpaperFilename
), buffer
);
373 himl
= (HIMAGELIST
)SHGetFileInfo(wallpaperFilename
,
377 SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
|
384 (void)ListView_SetImageList(hwndBackgroundList
, himl
, LVSIL_SMALL
);
387 backgroundItem
= &pData
->backgroundItems
[pData
->listViewItemCount
];
389 backgroundItem
->bWallpaper
= TRUE
;
391 hr
= StringCbCopy(backgroundItem
->szDisplayName
, sizeof(backgroundItem
->szDisplayName
), sfi
.szDisplayName
);
398 PathRemoveExtension(backgroundItem
->szDisplayName
);
400 hr
= StringCbCopy(backgroundItem
->szFilename
, sizeof(backgroundItem
->szFilename
), wallpaperFilename
);
407 ZeroMemory(&listItem
, sizeof(LV_ITEM
));
408 listItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
410 listItem
.pszText
= backgroundItem
->szDisplayName
;
411 listItem
.iImage
= sfi
.iIcon
;
412 listItem
.iItem
= pData
->listViewItemCount
;
413 listItem
.lParam
= pData
->listViewItemCount
;
415 (void)ListView_InsertItem(hwndBackgroundList
, &listItem
);
416 ListView_SetItemState(hwndBackgroundList
,
417 pData
->listViewItemCount
,
421 pData
->listViewItemCount
++;
428 /* Add all the images in the C:\ReactOS directory. */
429 if (GetWindowsDirectory(szSearchPath
, MAX_PATH
))
431 i
= AddWallpapersFromDirectory(i
, hwndBackgroundList
, backgroundItem
, pData
, wallpaperFilename
, szSearchPath
);
434 /* Add all the images in the wallpaper directory. */
435 if (SHRegGetPath(HKEY_LOCAL_MACHINE
, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"), TEXT("WallPaperDir"), szSearchPath
, 0) == ERROR_SUCCESS
)
437 i
= AddWallpapersFromDirectory(i
, hwndBackgroundList
, backgroundItem
, pData
, wallpaperFilename
, szSearchPath
);
443 InitBackgroundDialog(HWND hwndDlg
, PDATA pData
)
448 DWORD bufferSize
= sizeof(szBuffer
);
451 AddListViewItems(hwndDlg
, pData
);
453 LoadString(hApplet
, IDS_CENTER
, szString
, sizeof(szString
) / sizeof(TCHAR
));
454 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_INSERTSTRING
, PLACEMENT_CENTER
, (LPARAM
)szString
);
456 LoadString(hApplet
, IDS_STRETCH
, szString
, sizeof(szString
) / sizeof(TCHAR
));
457 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_INSERTSTRING
, PLACEMENT_STRETCH
, (LPARAM
)szString
);
459 LoadString(hApplet
, IDS_TILE
, szString
, sizeof(szString
) / sizeof(TCHAR
));
460 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_INSERTSTRING
, PLACEMENT_TILE
, (LPARAM
)szString
);
462 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_SETCURSEL
, PLACEMENT_CENTER
, 0);
463 pData
->placementSelection
= PLACEMENT_CENTER
;
465 pData
->hBitmap
= (HBITMAP
) LoadImage(hApplet
, MAKEINTRESOURCE(IDC_MONITOR
), IMAGE_BITMAP
, 0, 0, LR_DEFAULTCOLOR
);
466 if (pData
->hBitmap
!= NULL
)
468 GetObject(pData
->hBitmap
, sizeof(BITMAP
), &bitmap
);
470 pData
->cxSource
= bitmap
.bmWidth
;
471 pData
->cySource
= bitmap
.bmHeight
;
474 /* Load the default settings from the registry */
475 if (RegOpenKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Desktop"), 0, KEY_QUERY_VALUE
, ®Key
) != ERROR_SUCCESS
)
480 if (RegQueryValueEx(regKey
, TEXT("WallpaperStyle"), 0, NULL
, (LPBYTE
)szBuffer
, &bufferSize
) == ERROR_SUCCESS
)
482 if (_ttoi(szBuffer
) == 0)
484 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_SETCURSEL
, PLACEMENT_CENTER
, 0);
485 pData
->placementSelection
= PLACEMENT_CENTER
;
488 if (_ttoi(szBuffer
) == 2)
490 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_SETCURSEL
, PLACEMENT_STRETCH
, 0);
491 pData
->placementSelection
= PLACEMENT_STRETCH
;
495 if (RegQueryValueEx(regKey
, TEXT("TileWallpaper"), 0, NULL
, (LPBYTE
)szBuffer
, &bufferSize
) == ERROR_SUCCESS
)
497 if (_ttoi(szBuffer
) == 1)
499 SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_SETCURSEL
, PLACEMENT_TILE
, 0);
500 pData
->placementSelection
= PLACEMENT_TILE
;
509 OnColorButton(HWND hwndDlg
, PDATA pData
)
511 /* Load custom colors from Registry */
513 LONG res
= ERROR_SUCCESS
;
516 res
= RegCreateKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Appearance"), 0, NULL
, 0,
517 KEY_ALL_ACCESS
, NULL
, &hKey
, NULL
);
518 /* Now the key is either created or opened existing, if res == ERROR_SUCCESS */
519 if (res
== ERROR_SUCCESS
)
522 DWORD dwType
= REG_BINARY
;
523 DWORD cbData
= sizeof(pData
->custom_colors
);
524 res
= RegQueryValueEx(hKey
, TEXT("CustomColors"), NULL
, &dwType
,
525 (LPBYTE
)pData
->custom_colors
, &cbData
);
530 /* Launch ChooseColor() dialog */
532 cc
.lStructSize
= sizeof(CHOOSECOLOR
);
533 cc
.hwndOwner
= hwndDlg
;
535 cc
.rgbResult
= g_GlobalData
.desktop_color
;
536 cc
.lpCustColors
= pData
->custom_colors
;
537 cc
.Flags
= CC_ANYCOLOR
| /* Causes the dialog box to display all available colors in the set of basic colors. */
538 CC_FULLOPEN
| /* opens dialog in full size */
539 CC_RGBINIT
; /* init chosen color by rgbResult value */
542 cc
.lpTemplateName
= NULL
;
543 if (ChooseColor(&cc
))
545 /* Save selected color to var */
546 g_GlobalData
.desktop_color
= cc
.rgbResult
;
547 pData
->bClrBackgroundChanged
= TRUE
;
549 /* Apply button will be activated */
550 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
552 /* Window will be updated :) */
553 InvalidateRect(GetDlgItem(hwndDlg
, IDC_BACKGROUND_PREVIEW
), NULL
, TRUE
);
555 /* Save custom colors to reg. To this moment key must be created already. See above */
556 res
= RegOpenKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Appearance"), 0,
558 if (res
== ERROR_SUCCESS
)
561 RegSetValueEx(hKey
, TEXT("CustomColors"), 0, REG_BINARY
,
562 (const BYTE
*)pData
->custom_colors
, sizeof(pData
->custom_colors
));
571 * ListView_FindItem() Macro: Searches for a list-view item with the specified
572 * characteristics. Returns the index of the item if successful, or -1 otherwise
575 CheckListViewFilenameExists(HWND hwndList
, LPCTSTR tszFileName
)
580 lvfi
.flags
= LVFI_STRING
; /* Search item by EXACT string */
581 lvfi
.psz
= tszFileName
; /* String to search */
583 /* Other items of this structure are not valid, besacuse flags are not set. */
584 retVal
= ListView_FindItem(hwndList
, -1, &lvfi
);
586 return TRUE
; /* item found! */
588 return FALSE
; /* item not found. */
593 OnBrowseButton(HWND hwndDlg
, PDATA pData
)
596 TCHAR filename
[MAX_PATH
];
597 TCHAR fileTitle
[256];
600 BackgroundItem
*backgroundItem
= NULL
;
603 HWND hwndBackgroundList
;
606 TCHAR filterdesc
[MAX_PATH
];
612 hwndBackgroundList
= GetDlgItem(hwndDlg
, IDC_BACKGROUND_LIST
);
614 ZeroMemory(&ofn
, sizeof(OPENFILENAME
));
616 ofn
.lStructSize
= sizeof(OPENFILENAME
);
617 ofn
.hwndOwner
= hwndDlg
;
618 ofn
.lpstrFile
= filename
;
620 LoadString(hApplet
, IDS_BACKGROUND_COMDLG_FILTER
, filterdesc
, sizeof(filterdesc
) / sizeof(TCHAR
));
622 extensions
= GdipGetSupportedFileExtensions();
628 buffersize
= (_tcslen(extensions
) * 2 + 6) * sizeof(TCHAR
) + sizeof(filterdesc
);
630 filter
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buffersize
);
633 HeapFree(GetProcessHeap(), 0, extensions
);
637 sizeRemain
= buffersize
;
640 if (FAILED(StringCbPrintfEx(c
, sizeRemain
, &c
, &sizeRemain
, 0, L
"%ls (%ls)", filterdesc
, extensions
)))
642 HeapFree(GetProcessHeap(), 0, extensions
);
643 HeapFree(GetProcessHeap(), 0, filter
);
648 sizeRemain
-= sizeof(*c
);
650 if (FAILED(StringCbPrintfEx(c
, sizeRemain
, &c
, &sizeRemain
, 0, L
"%ls", extensions
)))
652 HeapFree(GetProcessHeap(), 0, extensions
);
653 HeapFree(GetProcessHeap(), 0, filter
);
657 HeapFree(GetProcessHeap(), 0, extensions
);
659 /* Set lpstrFile[0] to '\0' so that GetOpenFileName does not
660 * use the contents of szFile to initialize itself */
661 ofn
.lpstrFile
[0] = TEXT('\0');
662 ofn
.nMaxFile
= MAX_PATH
;
663 ofn
.lpstrFilter
= filter
;
664 ofn
.nFilterIndex
= 0;
665 ofn
.lpstrFileTitle
= fileTitle
;
666 ofn
.nMaxFileTitle
= 256;
667 ofn
.lpstrInitialDir
= NULL
;
668 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_FILEMUSTEXIST
| OFN_HIDEREADONLY
;
670 success
= GetOpenFileName(&ofn
);
671 HeapFree(GetProcessHeap(), 0, filter
);
675 /* Check if there is already a entry that holds this filename */
676 if (CheckListViewFilenameExists(hwndBackgroundList
, ofn
.lpstrFileTitle
) == TRUE
)
679 if (pData
->listViewItemCount
> (MAX_BACKGROUNDS
- 1))
682 SHGetFileInfo(filename
,
686 SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
| SHGFI_DISPLAYNAME
);
688 backgroundItem
= &pData
->backgroundItems
[pData
->listViewItemCount
];
690 backgroundItem
->bWallpaper
= TRUE
;
692 hr
= StringCbCopy(backgroundItem
->szDisplayName
, sizeof(backgroundItem
->szDisplayName
), sfi
.szDisplayName
);
695 p
= _tcsrchr(backgroundItem
->szDisplayName
, _T('.'));
698 hr
= StringCbCopy(backgroundItem
->szFilename
, sizeof(backgroundItem
->szFilename
), filename
);
702 ZeroMemory(&listItem
, sizeof(LV_ITEM
));
703 listItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
705 listItem
.pszText
= backgroundItem
->szDisplayName
;
706 listItem
.iImage
= sfi
.iIcon
;
707 listItem
.iItem
= pData
->listViewItemCount
;
708 listItem
.lParam
= pData
->listViewItemCount
;
710 (void)ListView_InsertItem(hwndBackgroundList
, &listItem
);
711 ListView_SetItemState(hwndBackgroundList
,
712 pData
->listViewItemCount
,
715 SendMessage(hwndBackgroundList
, WM_VSCROLL
, SB_BOTTOM
, 0);
717 pData
->listViewItemCount
++;
723 ListViewItemChanged(HWND hwndDlg
, PDATA pData
, int itemIndex
)
725 BackgroundItem
*backgroundItem
= NULL
;
727 pData
->backgroundSelection
= itemIndex
;
728 backgroundItem
= &pData
->backgroundItems
[pData
->backgroundSelection
];
730 if (pData
->pWallpaperBitmap
!= NULL
)
732 DibFreeImage(pData
->pWallpaperBitmap
);
733 pData
->pWallpaperBitmap
= NULL
;
736 if (backgroundItem
->bWallpaper
== TRUE
)
738 pData
->pWallpaperBitmap
= DibLoadImage(backgroundItem
->szFilename
);
740 if (pData
->pWallpaperBitmap
== NULL
)
744 pData
->bWallpaperChanged
= TRUE
;
746 InvalidateRect(GetDlgItem(hwndDlg
, IDC_BACKGROUND_PREVIEW
),
749 EnableWindow(GetDlgItem(hwndDlg
, IDC_PLACEMENT_COMBO
),
750 backgroundItem
->bWallpaper
);
752 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
757 DrawBackgroundPreview(LPDRAWITEMSTRUCT draw
, PDATA pData
)
777 hDC
= CreateCompatibleDC(draw
->hDC
);
778 hOldObj
= SelectObject(hDC
, pData
->hBitmap
);
780 if (pData
->backgroundItems
[pData
->backgroundSelection
].bWallpaper
== FALSE
)
782 /* Update desktop background color image */
783 hBrush
= CreateSolidBrush(g_GlobalData
.desktop_color
);
784 FillRect(hDC
, &rcItem
, hBrush
);
785 DeleteObject(hBrush
);
788 if (pData
->pWallpaperBitmap
!= NULL
)
790 scaleX
= ((float)GetSystemMetrics(SM_CXSCREEN
) - 1) / (float)MONITOR_WIDTH
;
791 scaleY
= ((float)GetSystemMetrics(SM_CYSCREEN
) - 1) / (float)MONITOR_HEIGHT
;
793 scaledWidth
= (int)(pData
->pWallpaperBitmap
->width
/ scaleX
);
794 scaledHeight
= (int)(pData
->pWallpaperBitmap
->height
/ scaleY
);
796 FillRect(hDC
, &rcItem
, GetSysColorBrush(COLOR_BACKGROUND
));
798 SetStretchBltMode(hDC
, COLORONCOLOR
);
800 switch (pData
->placementSelection
)
802 case PLACEMENT_CENTER
:
803 posX
= (MONITOR_WIDTH
- scaledWidth
+ 1) / 2;
804 posY
= (MONITOR_HEIGHT
- scaledHeight
+ 1) / 2;
808 if (posX
< 0) { desX
= -posX
/ 2; posX
= 0; }
809 if (posY
< 0) { desY
= -posY
/ 2; posY
= 0; }
811 if (scaledWidth
> MONITOR_WIDTH
)
812 scaledWidth
= MONITOR_WIDTH
;
814 if (scaledHeight
> MONITOR_HEIGHT
)
815 scaledHeight
= MONITOR_HEIGHT
;
824 pData
->pWallpaperBitmap
->width
- (int)(desX
* scaleX
),
825 pData
->pWallpaperBitmap
->height
- (int)(desY
* scaleY
),
826 pData
->pWallpaperBitmap
->bits
,
827 pData
->pWallpaperBitmap
->info
,
832 case PLACEMENT_STRETCH
:
840 pData
->pWallpaperBitmap
->width
,
841 pData
->pWallpaperBitmap
->height
,
842 pData
->pWallpaperBitmap
->bits
,
843 pData
->pWallpaperBitmap
->info
,
849 for (y
= 0; y
< MONITOR_HEIGHT
; y
+= scaledHeight
)
851 for (x
= 0; x
< MONITOR_WIDTH
; x
+= scaledWidth
)
853 if ((MONITOR_WIDTH
-x
) >= scaledWidth
)
856 posX
= MONITOR_WIDTH
-x
;
859 if ((MONITOR_HEIGHT
-y
) >= scaledHeight
)
862 posY
= MONITOR_HEIGHT
-y
;
871 pData
->pWallpaperBitmap
->width
* posX
/ scaledWidth
,
872 pData
->pWallpaperBitmap
->height
* posY
/ scaledHeight
,
873 pData
->pWallpaperBitmap
->bits
,
874 pData
->pWallpaperBitmap
->info
,
885 GdiTransparentBlt(draw
->hDC
,
886 draw
->rcItem
.left
, draw
->rcItem
.top
,
887 draw
->rcItem
.right
-draw
->rcItem
.left
+1,
888 draw
->rcItem
.bottom
-draw
->rcItem
.top
+1,
891 pData
->cxSource
, pData
->cySource
,
894 SelectObject(hDC
, hOldObj
);
900 SetWallpaper(PDATA pData
)
903 TCHAR szWallpaper
[MAX_PATH
];
911 if (FAILED(SHGetFolderPath(NULL
, CSIDL_LOCAL_APPDATA
| CSIDL_FLAG_CREATE
, NULL
, 0, szWallpaper
)))
916 if (FAILED(StringCbCat(szWallpaper
, MAX_PATH
, TEXT("\\Wallpaper1.bmp"))))
921 RegOpenKeyEx(HKEY_CURRENT_USER
, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS
, ®Key
);
923 if (pData
->placementSelection
== PLACEMENT_TILE
)
925 RegSetValueEx(regKey
, TEXT("TileWallpaper"), 0, REG_SZ
, (BYTE
*)TEXT("1"), sizeof(TCHAR
) * 2);
926 RegSetValueEx(regKey
, TEXT("WallpaperStyle"), 0, REG_SZ
, (BYTE
*)TEXT("0"), sizeof(TCHAR
) * 2);
929 if (pData
->placementSelection
== PLACEMENT_CENTER
)
931 RegSetValueEx(regKey
, TEXT("TileWallpaper"), 0, REG_SZ
, (BYTE
*)TEXT("0"), sizeof(TCHAR
) * 2);
932 RegSetValueEx(regKey
, TEXT("WallpaperStyle"), 0, REG_SZ
, (BYTE
*)TEXT("0"), sizeof(TCHAR
) * 2);
935 if (pData
->placementSelection
== PLACEMENT_STRETCH
)
937 RegSetValueEx(regKey
, TEXT("TileWallpaper"), 0, REG_SZ
, (BYTE
*)TEXT("0"), sizeof(TCHAR
) * 2);
938 RegSetValueEx(regKey
, TEXT("WallpaperStyle"), 0, REG_SZ
, (BYTE
*)TEXT("2"), sizeof(TCHAR
) * 2);
941 if (pData
->backgroundItems
[pData
->backgroundSelection
].bWallpaper
== TRUE
)
943 GdipLoadImageFromFile(pData
->backgroundItems
[pData
->backgroundSelection
].szFilename
, &image
);
950 GdipGetImageRawFormat(image
, &guidFormat
);
951 if (IsEqualGUID(&guidFormat
, &ImageFormatBMP
))
953 GdipDisposeImage(image
);
955 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, pData
->backgroundItems
[pData
->backgroundSelection
].szFilename
, SPIF_UPDATEINIFILE
);
959 if (FAILED(GdipGetEncoderClsid(L
"image/bmp", &encoderClsid
)))
961 GdipDisposeImage(image
);
966 status
= GdipSaveImageToFile(image
, szWallpaper
, &encoderClsid
, NULL
);
968 GdipDisposeImage(image
);
976 if (SUCCEEDED(StringCchLength(pData
->backgroundItems
[pData
->backgroundSelection
].szFilename
, MAX_PATH
, &length
)))
978 RegSetValueEx(regKey
,
979 TEXT("ConvertedWallpaper"),
982 (BYTE
*)pData
->backgroundItems
[pData
->backgroundSelection
].szFilename
,
983 (DWORD
)((length
+ 1) * sizeof(TCHAR
)));
986 if (SUCCEEDED(StringCchLength(szWallpaper
, MAX_PATH
, &length
)))
988 RegSetValueEx(regKey
,
989 TEXT("OriginalWallpaper"),
993 (DWORD
)((length
+ 1) * sizeof(TCHAR
)));
996 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, szWallpaper
, SPIF_UPDATEINIFILE
);
1000 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, (void*) TEXT(""), SPIF_UPDATEINIFILE
);
1003 RegCloseKey(regKey
);
1007 /* Change system color */
1009 SetDesktopBackColor(HWND hwndDlg
, DATA
*pData
)
1011 INT iElement
= COLOR_BACKGROUND
;
1015 BYTE red
, green
, blue
;
1018 if( !SetSysColors( 1, &iElement
, &g_GlobalData
.desktop_color
) )
1019 MessageBox(hwndDlg
, TEXT("SetSysColor() failed!"), /* these error texts can need internationalization? */
1020 TEXT("Error!"), MB_ICONSTOP
);
1022 result
= RegCreateKeyEx( HKEY_CURRENT_USER
, TEXT("Control Panel\\Colors"), 0, NULL
, 0,
1023 KEY_ALL_ACCESS
, NULL
, &hKey
, &dwDispostion
);
1024 if (result
!= ERROR_SUCCESS
)
1026 red
= GetRValue(g_GlobalData
.desktop_color
);
1027 green
= GetGValue(g_GlobalData
.desktop_color
);
1028 blue
= GetBValue(g_GlobalData
.desktop_color
);
1029 /* Format string to be set to registry */
1030 StringCbPrintf(clText
, sizeof(clText
), TEXT("%d %d %d"), red
, green
, blue
);
1031 RegSetValueEx(hKey
, TEXT("Background"), 0, REG_SZ
, (BYTE
*)clText
,
1032 (lstrlen(clText
) + 1) * sizeof(TCHAR
));
1038 BackgroundPageProc(HWND hwndDlg
,
1044 struct GdiplusStartupInput gdipStartup
;
1046 pData
= (PDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
1051 pData
= (DATA
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DATA
));
1052 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pData
);
1053 gdipStartup
.GdiplusVersion
= 1;
1054 gdipStartup
.DebugEventCallback
= NULL
;
1055 gdipStartup
.SuppressBackgroundThread
= FALSE
;
1056 gdipStartup
.SuppressExternalCodecs
= FALSE
;
1057 GdiplusStartup(&pData
->gdipToken
, &gdipStartup
, NULL
);
1058 InitBackgroundDialog(hwndDlg
, pData
);
1063 DWORD controlId
= LOWORD(wParam
);
1064 DWORD command
= HIWORD(wParam
);
1068 case IDC_COLOR_BUTTON
:
1069 if (command
== BN_CLICKED
)
1070 OnColorButton(hwndDlg
, pData
);
1073 case IDC_BROWSE_BUTTON
:
1074 if (command
== BN_CLICKED
)
1075 OnBrowseButton(hwndDlg
, pData
);
1078 case IDC_PLACEMENT_COMBO
:
1079 if (command
== CBN_SELCHANGE
)
1081 pData
->placementSelection
= (int)SendDlgItemMessage(hwndDlg
, IDC_PLACEMENT_COMBO
, CB_GETCURSEL
, 0, 0);
1083 InvalidateRect(GetDlgItem(hwndDlg
, IDC_BACKGROUND_PREVIEW
), NULL
, TRUE
);
1085 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1093 LPDRAWITEMSTRUCT drawItem
;
1094 drawItem
= (LPDRAWITEMSTRUCT
)lParam
;
1096 if (drawItem
->CtlID
== IDC_BACKGROUND_PREVIEW
)
1098 DrawBackgroundPreview(drawItem
, pData
);
1106 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1111 if(pData
->bWallpaperChanged
)
1112 SetWallpaper(pData
);
1113 if(pData
->bClrBackgroundChanged
)
1114 SetDesktopBackColor(hwndDlg
, pData
);
1115 SendMessage(HWND_BROADCAST
, WM_SETTINGCHANGE
, 0, (LPARAM
)_T(""));
1118 case LVN_ITEMCHANGED
:
1120 LPNMLISTVIEW nm
= (LPNMLISTVIEW
)lParam
;
1122 if ((nm
->uNewState
& LVIS_SELECTED
) == 0)
1125 ListViewItemChanged(hwndDlg
, pData
, nm
->iItem
);
1133 if (pData
->pWallpaperBitmap
!= NULL
)
1134 DibFreeImage(pData
->pWallpaperBitmap
);
1136 DeleteObject(pData
->hBitmap
);
1137 GdiplusShutdown(pData
->gdipToken
);
1138 HeapFree(GetProcessHeap(), 0, pData
);