Sync with trunk.
[reactos.git] / dll / cpl / desk / background.c
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 #define MAX_BACKGROUNDS 100
14
15 #define PLACEMENT_CENTER 0
16 #define PLACEMENT_STRETCH 1
17 #define PLACEMENT_TILE 2
18
19 /* The values in these macros are dependant on the
20 * layout of the monitor image and they must be adjusted
21 * if that image will be changed.
22 */
23 #define MONITOR_LEFT 18
24 #define MONITOR_TOP 18
25 #define MONITOR_RIGHT 168
26 #define MONITOR_BOTTOM 128
27
28 #define MONITOR_WIDTH (MONITOR_RIGHT-MONITOR_LEFT)
29 #define MONITOR_HEIGHT (MONITOR_BOTTOM-MONITOR_TOP)
30
31 typedef struct
32 {
33 BOOL bWallpaper; /* Is this background a wallpaper */
34
35 TCHAR szFilename[MAX_PATH];
36 TCHAR szDisplayName[256];
37
38 } BackgroundItem;
39
40 typedef struct _DATA
41 {
42 BOOL bWallpaperChanged;
43 BOOL bClrBackgroundChanged;
44
45 BackgroundItem backgroundItems[MAX_BACKGROUNDS];
46
47 PDIBITMAP pWallpaperBitmap;
48
49 int placementSelection;
50 int backgroundSelection;
51
52 COLORREF custom_colors[16];
53
54 int listViewItemCount;
55
56 HBITMAP hBitmap;
57 int cxSource;
58 int cySource;
59 } DATA, *PDATA;
60
61 GLOBAL_DATA g_GlobalData;
62
63
64 /* Add the images in the C:\ReactOS directory and the current wallpaper if any */
65 static VOID
66 AddListViewItems(HWND hwndDlg, PDATA pData)
67 {
68 WIN32_FIND_DATA fd;
69 HANDLE hFind;
70 TCHAR szSearchPath[MAX_PATH];
71 TCHAR szFileTypes[MAX_PATH];
72 LV_ITEM listItem;
73 LV_COLUMN dummy;
74 RECT clientRect;
75 HKEY regKey;
76 SHFILEINFO sfi;
77 HIMAGELIST himl;
78 TCHAR wallpaperFilename[MAX_PATH];
79 DWORD bufferSize = sizeof(wallpaperFilename);
80 TCHAR buffer[MAX_PATH];
81 DWORD varType = REG_SZ;
82 LONG result;
83 UINT i = 0;
84 BackgroundItem *backgroundItem = NULL;
85 TCHAR separators[] = TEXT(";");
86 TCHAR *token;
87 HWND hwndBackgroundList;
88 TCHAR *p;
89
90 hwndBackgroundList = GetDlgItem(hwndDlg, IDC_BACKGROUND_LIST);
91
92 GetClientRect(hwndBackgroundList, &clientRect);
93
94 /* Add a new column to the list */
95 ZeroMemory(&dummy, sizeof(LV_COLUMN));
96 dummy.mask = LVCF_SUBITEM | LVCF_WIDTH;
97 dummy.iSubItem = 0;
98 dummy.cx = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL);
99 (void)ListView_InsertColumn(hwndBackgroundList, 0, &dummy);
100
101 /* Add the "None" item */
102 backgroundItem = &pData->backgroundItems[pData->listViewItemCount];
103 backgroundItem->bWallpaper = FALSE;
104 LoadString(hApplet,
105 IDS_NONE,
106 backgroundItem->szDisplayName,
107 sizeof(backgroundItem->szDisplayName) / sizeof(TCHAR));
108
109 ZeroMemory(&listItem, sizeof(LV_ITEM));
110 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
111 listItem.state = 0;
112 listItem.pszText = backgroundItem->szDisplayName;
113 listItem.iImage = -1;
114 listItem.iItem = pData->listViewItemCount;
115 listItem.lParam = pData->listViewItemCount;
116
117 (void)ListView_InsertItem(hwndBackgroundList, &listItem);
118 ListView_SetItemState(hwndBackgroundList,
119 pData->listViewItemCount,
120 LVIS_SELECTED,
121 LVIS_SELECTED);
122
123 pData->listViewItemCount++;
124
125 /* Add current wallpaper if any */
126 result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, &regKey);
127 if (result == ERROR_SUCCESS)
128 {
129 result = RegQueryValueEx(regKey, TEXT("Wallpaper"), 0, &varType, (LPBYTE)wallpaperFilename, &bufferSize);
130 if ((result == ERROR_SUCCESS) && (_tcslen(wallpaperFilename) > 0))
131 {
132 /* Allow environment variables in file name */
133 if (ExpandEnvironmentStrings(wallpaperFilename, buffer, MAX_PATH))
134 {
135 _tcscpy(wallpaperFilename, buffer);
136 }
137
138 himl = (HIMAGELIST)SHGetFileInfo(wallpaperFilename,
139 0,
140 &sfi,
141 sizeof(sfi),
142 SHGFI_SYSICONINDEX | SHGFI_SMALLICON |
143 SHGFI_DISPLAYNAME);
144
145 if (himl != NULL)
146 {
147 if (i++ == 0)
148 {
149 (void)ListView_SetImageList(hwndBackgroundList, himl, LVSIL_SMALL);
150 }
151
152 backgroundItem = &pData->backgroundItems[pData->listViewItemCount];
153
154 backgroundItem->bWallpaper = TRUE;
155
156 _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName);
157 p = _tcsrchr(backgroundItem->szDisplayName, _T('.'));
158 if (p)
159 *p = (TCHAR)0;
160 _tcscpy(backgroundItem->szFilename, wallpaperFilename);
161
162 ZeroMemory(&listItem, sizeof(LV_ITEM));
163 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
164 listItem.state = 0;
165 listItem.pszText = backgroundItem->szDisplayName;
166 listItem.iImage = sfi.iIcon;
167 listItem.iItem = pData->listViewItemCount;
168 listItem.lParam = pData->listViewItemCount;
169
170 (void)ListView_InsertItem(hwndBackgroundList, &listItem);
171 ListView_SetItemState(hwndBackgroundList,
172 pData->listViewItemCount,
173 LVIS_SELECTED,
174 LVIS_SELECTED);
175
176 pData->listViewItemCount++;
177 }
178 }
179
180 RegCloseKey(regKey);
181 }
182
183 /* Add all the images in the C:\ReactOS directory. */
184
185 LoadString(hApplet, IDS_SUPPORTED_EXT, szFileTypes, sizeof(szFileTypes) / sizeof(TCHAR));
186
187 token = _tcstok(szFileTypes, separators);
188 while (token != NULL)
189 {
190 GetWindowsDirectory(szSearchPath, MAX_PATH);
191 _tcscat(szSearchPath, TEXT("\\"));
192 _tcscat(szSearchPath, token);
193
194 hFind = FindFirstFile(szSearchPath, &fd);
195 while (hFind != INVALID_HANDLE_VALUE)
196 {
197 TCHAR filename[MAX_PATH];
198
199 GetWindowsDirectory(filename, MAX_PATH);
200
201 _tcscat(filename, TEXT("\\"));
202 _tcscat(filename, fd.cFileName);
203
204 /* Don't add any hidden bitmaps. Also don't add current wallpaper once more. */
205 if (((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) && (_tcscmp(wallpaperFilename, filename) != 0))
206 {
207 himl = (HIMAGELIST)SHGetFileInfo(filename,
208 0,
209 &sfi,
210 sizeof(sfi),
211 SHGFI_SYSICONINDEX | SHGFI_SMALLICON |
212 SHGFI_DISPLAYNAME);
213
214 if (himl == NULL)
215 break;
216
217 if (i++ == 0)
218 {
219 (void)ListView_SetImageList(hwndBackgroundList, himl, LVSIL_SMALL);
220 }
221
222 backgroundItem = &pData->backgroundItems[pData->listViewItemCount];
223
224 backgroundItem->bWallpaper = TRUE;
225
226 _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName);
227 p = _tcsrchr(backgroundItem->szDisplayName, _T('.'));
228 if (p)
229 *p = (TCHAR)0;
230 _tcscpy(backgroundItem->szFilename, filename);
231
232 ZeroMemory(&listItem, sizeof(LV_ITEM));
233 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
234 listItem.pszText = backgroundItem->szDisplayName;
235 listItem.state = 0;
236 listItem.iImage = sfi.iIcon;
237 listItem.iItem = pData->listViewItemCount;
238 listItem.lParam = pData->listViewItemCount;
239
240 (void)ListView_InsertItem(hwndBackgroundList, &listItem);
241
242 pData->listViewItemCount++;
243 }
244
245 if(!FindNextFile(hFind, &fd))
246 hFind = INVALID_HANDLE_VALUE;
247 }
248
249 token = _tcstok(NULL, separators);
250 }
251 }
252
253
254 static VOID
255 InitBackgroundDialog(HWND hwndDlg, PDATA pData)
256 {
257 TCHAR szString[256];
258 HKEY regKey;
259 TCHAR szBuffer[2];
260 DWORD bufferSize = sizeof(szBuffer);
261 DWORD varType = REG_SZ;
262 LONG result;
263 BITMAP bitmap;
264
265 AddListViewItems(hwndDlg, pData);
266
267 LoadString(hApplet, IDS_CENTER, szString, sizeof(szString) / sizeof(TCHAR));
268 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_INSERTSTRING, PLACEMENT_CENTER, (LPARAM)szString);
269
270 LoadString(hApplet, IDS_STRETCH, szString, sizeof(szString) / sizeof(TCHAR));
271 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_INSERTSTRING, PLACEMENT_STRETCH, (LPARAM)szString);
272
273 LoadString(hApplet, IDS_TILE, szString, sizeof(szString) / sizeof(TCHAR));
274 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_INSERTSTRING, PLACEMENT_TILE, (LPARAM)szString);
275
276 /* Load the default settings from the registry */
277 result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, &regKey);
278 if (result != ERROR_SUCCESS)
279 {
280 /* reg key open failed; maybe it does not exist? create it! */
281 DWORD dwDisposition = 0;
282 result = RegCreateKeyEx( HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, NULL, 0, KEY_ALL_ACCESS, NULL,
283 &regKey, &dwDisposition );
284 /* Now the key must be created & opened and regKey points to opened key */
285 /* On error result will not contain ERROR_SUCCESS. I don't know how to handle */
286 /* this case :( */
287 }
288
289 result = RegQueryValueEx(regKey, TEXT("WallpaperStyle"), 0, &varType, (LPBYTE)szBuffer, &bufferSize);
290 if (result == ERROR_SUCCESS)
291 {
292 if (_ttoi(szBuffer) == 0)
293 {
294 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_CENTER, 0);
295 pData->placementSelection = PLACEMENT_CENTER;
296 }
297
298 if (_ttoi(szBuffer) == 2)
299 {
300 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_STRETCH, 0);
301 pData->placementSelection = PLACEMENT_STRETCH;
302 }
303 }
304 else
305 {
306 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_CENTER, 0);
307 pData->placementSelection = PLACEMENT_CENTER;
308 }
309
310 result = RegQueryValueEx(regKey, TEXT("TileWallpaper"), 0, &varType, (LPBYTE)szBuffer, &bufferSize);
311 if (result == ERROR_SUCCESS)
312 {
313 if (_ttoi(szBuffer) == 1)
314 {
315 SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_SETCURSEL, PLACEMENT_TILE, 0);
316 pData->placementSelection = PLACEMENT_TILE;
317 }
318 }
319
320 RegCloseKey(regKey);
321
322 pData->hBitmap = (HBITMAP) LoadImage(hApplet, MAKEINTRESOURCE(IDC_MONITOR), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
323 if (pData->hBitmap != NULL)
324 {
325 GetObject(pData->hBitmap, sizeof(BITMAP), &bitmap);
326
327 pData->cxSource = bitmap.bmWidth;
328 pData->cySource = bitmap.bmHeight;
329 }
330 }
331
332
333 static VOID
334 OnColorButton(HWND hwndDlg, PDATA pData)
335 {
336 /* Load custom colors from Registry */
337 HKEY hKey = NULL;
338 LONG res = ERROR_SUCCESS;
339 CHOOSECOLOR cc;
340
341 res = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance"), 0, NULL, 0,
342 KEY_ALL_ACCESS, NULL, &hKey, NULL);
343 /* Now the key is either created or opened existing, if res == ERROR_SUCCESS */
344 if (res == ERROR_SUCCESS)
345 {
346 /* Key opened */
347 DWORD dwType = REG_BINARY;
348 DWORD cbData = sizeof(pData->custom_colors);
349 res = RegQueryValueEx(hKey, TEXT("CustomColors"), NULL, &dwType,
350 (LPBYTE)pData->custom_colors, &cbData);
351 RegCloseKey(hKey);
352 hKey = NULL;
353 }
354
355 /* Launch ChooseColor() dialog */
356
357 cc.lStructSize = sizeof(CHOOSECOLOR);
358 cc.hwndOwner = hwndDlg;
359 cc.hInstance = NULL;
360 cc.rgbResult = g_GlobalData.desktop_color;
361 cc.lpCustColors = pData->custom_colors;
362 cc.Flags = CC_ANYCOLOR | /* Causes the dialog box to display all available colors in the set of basic colors. */
363 CC_FULLOPEN | /* opens dialog in full size */
364 CC_RGBINIT ; /* init chosen color by rgbResult value */
365 cc.lCustData = 0;
366 cc.lpfnHook = NULL;
367 cc.lpTemplateName = NULL;
368 if (ChooseColor(&cc))
369 {
370 /* Save selected color to var */
371 g_GlobalData.desktop_color = cc.rgbResult;
372 pData->bClrBackgroundChanged = TRUE;
373
374 /* Apply button will be activated */
375 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
376
377 /* Window will be updated :) */
378 InvalidateRect(GetDlgItem(hwndDlg, IDC_BACKGROUND_PREVIEW), NULL, TRUE);
379
380 /* Save custom colors to reg. To this moment key must be created already. See above */
381 res = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance"), 0,
382 KEY_WRITE, &hKey);
383 if (res == ERROR_SUCCESS)
384 {
385 /* Key opened */
386 RegSetValueEx(hKey, TEXT("CustomColors"), 0, REG_BINARY,
387 (const BYTE *)pData->custom_colors, sizeof(pData->custom_colors));
388 RegCloseKey(hKey);
389 hKey = NULL;
390 }
391 }
392 }
393
394
395 /*
396 * ListView_FindItem() Macro: Searches for a list-view item with the specified
397 * characteristics. Returns the index of the item if successful, or -1 otherwise
398 */
399 static BOOL
400 CheckListViewFilenameExists(HWND hwndList, LPCTSTR tszFileName)
401 {
402 LVFINDINFO lvfi;
403 int retVal;
404
405 lvfi.flags = LVFI_STRING; /* Search item by EXACT string */
406 lvfi.psz = tszFileName; /* String to search */
407
408 /* Other items of this structure are not valid, besacuse flags are not set. */
409 retVal = ListView_FindItem(hwndList, -1, &lvfi);
410 if (retVal != -1)
411 return TRUE; /* item found! */
412
413 return FALSE; /* item not found. */
414 }
415
416
417 static VOID
418 OnBrowseButton(HWND hwndDlg, PDATA pData)
419 {
420 OPENFILENAME ofn;
421 TCHAR filename[MAX_PATH];
422 TCHAR fileTitle[256];
423 TCHAR filter[MAX_PATH];
424 BackgroundItem *backgroundItem = NULL;
425 SHFILEINFO sfi;
426 LV_ITEM listItem;
427 HWND hwndBackgroundList;
428 TCHAR *p;
429
430 hwndBackgroundList = GetDlgItem(hwndDlg, IDC_BACKGROUND_LIST);
431
432 ZeroMemory(&ofn, sizeof(OPENFILENAME));
433
434 ofn.lStructSize = sizeof(OPENFILENAME);
435 ofn.hwndOwner = hwndDlg;
436 ofn.lpstrFile = filename;
437
438 LoadString(hApplet, IDS_BACKGROUND_COMDLG_FILTER, filter, sizeof(filter) / sizeof(TCHAR));
439
440 /* Set lpstrFile[0] to '\0' so that GetOpenFileName does not
441 * use the contents of szFile to initialize itself */
442 ofn.lpstrFile[0] = TEXT('\0');
443 ofn.nMaxFile = MAX_PATH;
444 ofn.lpstrFilter = filter;
445 ofn.nFilterIndex = 0;
446 ofn.lpstrFileTitle = fileTitle;
447 ofn.nMaxFileTitle = 256;
448 ofn.lpstrInitialDir = NULL;
449 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
450
451 if (GetOpenFileName(&ofn) == TRUE)
452 {
453 /* Check if there is already a entry that holds this filename */
454 if (CheckListViewFilenameExists(hwndBackgroundList, ofn.lpstrFileTitle) == TRUE)
455 return;
456
457 if (pData->listViewItemCount > (MAX_BACKGROUNDS - 1))
458 return;
459
460 SHGetFileInfo(filename,
461 0,
462 &sfi,
463 sizeof(sfi),
464 SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_DISPLAYNAME);
465
466 backgroundItem = &pData->backgroundItems[pData->listViewItemCount];
467
468 backgroundItem->bWallpaper = TRUE;
469
470 _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName);
471 p = _tcsrchr(backgroundItem->szDisplayName, _T('.'));
472 if (p)
473 *p = (TCHAR)0;
474 _tcscpy(backgroundItem->szFilename, filename);
475
476 ZeroMemory(&listItem, sizeof(LV_ITEM));
477 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
478 listItem.state = 0;
479 listItem.pszText = backgroundItem->szDisplayName;
480 listItem.iImage = sfi.iIcon;
481 listItem.iItem = pData->listViewItemCount;
482 listItem.lParam = pData->listViewItemCount;
483
484 (void)ListView_InsertItem(hwndBackgroundList, &listItem);
485 ListView_SetItemState(hwndBackgroundList,
486 pData->listViewItemCount,
487 LVIS_SELECTED,
488 LVIS_SELECTED);
489 SendMessage(hwndBackgroundList, WM_VSCROLL, SB_BOTTOM, 0);
490
491 pData->listViewItemCount++;
492 }
493 }
494
495
496 static VOID
497 ListViewItemChanged(HWND hwndDlg, PDATA pData, int itemIndex)
498 {
499 BackgroundItem *backgroundItem = NULL;
500
501 pData->backgroundSelection = itemIndex;
502 backgroundItem = &pData->backgroundItems[pData->backgroundSelection];
503
504 if (pData->pWallpaperBitmap != NULL)
505 {
506 DibFreeImage(pData->pWallpaperBitmap);
507 pData->pWallpaperBitmap = NULL;
508 }
509
510 if (backgroundItem->bWallpaper == TRUE)
511 {
512 pData->pWallpaperBitmap = DibLoadImage(backgroundItem->szFilename);
513
514 if (pData->pWallpaperBitmap == NULL)
515 return;
516 }
517
518 pData->bWallpaperChanged = TRUE;
519
520 InvalidateRect(GetDlgItem(hwndDlg, IDC_BACKGROUND_PREVIEW),
521 NULL, TRUE);
522
523 EnableWindow(GetDlgItem(hwndDlg, IDC_PLACEMENT_COMBO),
524 backgroundItem->bWallpaper);
525
526 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
527 }
528
529
530 static VOID
531 DrawBackgroundPreview(LPDRAWITEMSTRUCT draw, PDATA pData)
532 {
533 float scaleX;
534 float scaleY;
535 int scaledWidth;
536 int scaledHeight;
537 int posX, desX;
538 int posY, desY;
539 HBRUSH hBrush;
540 int x;
541 int y;
542 HDC hDC;
543 HGDIOBJ hOldObj;
544 RECT rcItem = {
545 MONITOR_LEFT,
546 MONITOR_TOP,
547 MONITOR_RIGHT,
548 MONITOR_BOTTOM
549 };
550
551 hDC = CreateCompatibleDC(draw->hDC);
552 hOldObj = SelectObject(hDC, pData->hBitmap);
553
554 if (pData->backgroundItems[pData->backgroundSelection].bWallpaper == FALSE)
555 {
556 /* Update desktop background color image */
557 hBrush = CreateSolidBrush(g_GlobalData.desktop_color);
558 FillRect(hDC, &rcItem, hBrush);
559 DeleteObject(hBrush);
560 }
561 else
562 if (pData->pWallpaperBitmap != NULL)
563 {
564 scaleX = ((float)GetSystemMetrics(SM_CXSCREEN) - 1) / (float)MONITOR_WIDTH;
565 scaleY = ((float)GetSystemMetrics(SM_CYSCREEN) - 1) / (float)MONITOR_HEIGHT;
566
567 scaledWidth = (int)(pData->pWallpaperBitmap->width / scaleX);
568 scaledHeight = (int)(pData->pWallpaperBitmap->height / scaleY);
569
570 FillRect(hDC, &rcItem, GetSysColorBrush(COLOR_BACKGROUND));
571
572 SetStretchBltMode(hDC, COLORONCOLOR);
573
574 switch (pData->placementSelection)
575 {
576 case PLACEMENT_CENTER:
577 posX = (MONITOR_WIDTH - scaledWidth + 1) / 2;
578 posY = (MONITOR_HEIGHT - scaledHeight + 1) / 2;
579 desX = 0;
580 desY = 0;
581
582 if (posX < 0) { desX = -posX / 2; posX = 0; }
583 if (posY < 0) { desY = -posY / 2; posY = 0; }
584
585 if (scaledWidth > MONITOR_WIDTH)
586 scaledWidth = MONITOR_WIDTH;
587
588 if (scaledHeight > MONITOR_HEIGHT)
589 scaledHeight = MONITOR_HEIGHT;
590
591 StretchDIBits(hDC,
592 MONITOR_LEFT+posX,
593 MONITOR_TOP+posY,
594 scaledWidth,
595 scaledHeight,
596 desX,
597 desY,
598 pData->pWallpaperBitmap->width - (int)(desX * scaleX),
599 pData->pWallpaperBitmap->height - (int)(desY * scaleY),
600 pData->pWallpaperBitmap->bits,
601 pData->pWallpaperBitmap->info,
602 DIB_RGB_COLORS,
603 SRCCOPY);
604 break;
605
606 case PLACEMENT_STRETCH:
607 StretchDIBits(hDC,
608 MONITOR_LEFT,
609 MONITOR_TOP,
610 MONITOR_WIDTH,
611 MONITOR_HEIGHT,
612 0,
613 0,
614 pData->pWallpaperBitmap->width,
615 pData->pWallpaperBitmap->height,
616 pData->pWallpaperBitmap->bits,
617 pData->pWallpaperBitmap->info,
618 DIB_RGB_COLORS,
619 SRCCOPY);
620 break;
621
622 case PLACEMENT_TILE:
623 for (y = 0; y < MONITOR_HEIGHT; y += scaledHeight)
624 {
625 for (x = 0; x < MONITOR_WIDTH; x += scaledWidth)
626 {
627 if ((MONITOR_WIDTH-x) >= scaledWidth)
628 posX = scaledWidth;
629 else
630 posX = MONITOR_WIDTH-x;
631
632
633 if ((MONITOR_HEIGHT-y) >= scaledHeight)
634 posY = scaledHeight;
635 else
636 posY = MONITOR_HEIGHT-y;
637
638 StretchDIBits(hDC,
639 MONITOR_LEFT + x,
640 MONITOR_TOP + y,
641 posX,
642 posY,
643 0,
644 0,
645 pData->pWallpaperBitmap->width * posX / scaledWidth,
646 pData->pWallpaperBitmap->height * posY / scaledHeight,
647 pData->pWallpaperBitmap->bits,
648 pData->pWallpaperBitmap->info,
649 DIB_RGB_COLORS,
650 SRCCOPY);
651 }
652
653 }
654
655 break;
656 }
657 }
658
659 GdiTransparentBlt(draw->hDC,
660 draw->rcItem.left, draw->rcItem.top,
661 draw->rcItem.right-draw->rcItem.left+1,
662 draw->rcItem.bottom-draw->rcItem.top+1,
663 hDC,
664 0, 0,
665 pData->cxSource, pData->cySource,
666 0xFF00FF);
667
668 SelectObject(hDC, hOldObj);
669 DeleteDC(hDC);
670 }
671
672
673 static VOID
674 SetWallpaper(PDATA pData)
675 {
676 HKEY regKey;
677
678 RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, &regKey);
679
680 if (pData->placementSelection == PLACEMENT_TILE)
681 {
682 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("1"), sizeof(TCHAR) * 2);
683 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2);
684 }
685
686 if (pData->placementSelection == PLACEMENT_CENTER)
687 {
688 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2);
689 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2);
690 }
691
692 if (pData->placementSelection == PLACEMENT_STRETCH)
693 {
694 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2);
695 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("2"), sizeof(TCHAR) * 2);
696 }
697
698 RegCloseKey(regKey);
699
700 if (pData->backgroundItems[pData->backgroundSelection].bWallpaper == TRUE)
701 {
702 SystemParametersInfo(SPI_SETDESKWALLPAPER,
703 0,
704 pData->backgroundItems[pData->backgroundSelection].szFilename,
705 SPIF_UPDATEINIFILE);
706 }
707 else
708 {
709 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*) TEXT(""), SPIF_UPDATEINIFILE);
710 }
711 }
712
713
714 /* Change system color */
715 static VOID
716 SetDesktopBackColor(HWND hwndDlg, DATA *pData)
717 {
718 INT iElement = COLOR_BACKGROUND;
719 HKEY hKey;
720 LONG result;
721 TCHAR clText[16];
722 BYTE red, green, blue;
723 DWORD dwDispostion;
724
725 if( !SetSysColors( 1, &iElement, &g_GlobalData.desktop_color ) )
726 MessageBox(hwndDlg, TEXT("SetSysColor() failed!"), /* these error texts can need internationalization? */
727 TEXT("Error!"), MB_ICONSTOP );
728
729 result = RegCreateKeyEx( HKEY_CURRENT_USER, TEXT("Control Panel\\Colors"), 0, NULL, 0,
730 KEY_ALL_ACCESS, NULL, &hKey, &dwDispostion );
731 if (result != ERROR_SUCCESS)
732 {
733 red = GetRValue(g_GlobalData.desktop_color);
734 green = GetGValue(g_GlobalData.desktop_color);
735 blue = GetBValue(g_GlobalData.desktop_color);
736 /* Format string to be set to registry */
737 wsprintf(clText, TEXT("%d %d %d"), red, green, blue);
738 RegSetValueEx(hKey, TEXT("Background"), 0, REG_SZ, (BYTE *)clText,
739 (lstrlen(clText) + 1) * sizeof(TCHAR));
740 RegCloseKey(hKey);
741 }
742 }
743
744 INT_PTR CALLBACK
745 BackgroundPageProc(HWND hwndDlg,
746 UINT uMsg,
747 WPARAM wParam,
748 LPARAM lParam)
749 {
750 PDATA pData;
751
752 pData = (PDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
753
754 switch (uMsg)
755 {
756 case WM_INITDIALOG:
757 pData = (DATA*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DATA));
758 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pData);
759 InitBackgroundDialog(hwndDlg, pData);
760 break;
761
762 case WM_COMMAND:
763 {
764 DWORD controlId = LOWORD(wParam);
765 DWORD command = HIWORD(wParam);
766
767 switch (controlId)
768 {
769 case IDC_COLOR_BUTTON:
770 if (command == BN_CLICKED)
771 OnColorButton(hwndDlg, pData);
772 break;
773
774 case IDC_BROWSE_BUTTON:
775 if (command == BN_CLICKED)
776 OnBrowseButton(hwndDlg, pData);
777 break;
778
779 case IDC_PLACEMENT_COMBO:
780 if (command == CBN_SELCHANGE)
781 {
782 pData->placementSelection = (int)SendDlgItemMessage(hwndDlg, IDC_PLACEMENT_COMBO, CB_GETCURSEL, 0, 0);
783
784 InvalidateRect(GetDlgItem(hwndDlg, IDC_BACKGROUND_PREVIEW), NULL, TRUE);
785
786 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
787 }
788 break;
789 }
790 } break;
791
792 case WM_DRAWITEM:
793 {
794 LPDRAWITEMSTRUCT drawItem;
795 drawItem = (LPDRAWITEMSTRUCT)lParam;
796
797 if (drawItem->CtlID == IDC_BACKGROUND_PREVIEW)
798 {
799 DrawBackgroundPreview(drawItem, pData);
800 }
801
802 }
803 break;
804
805 case WM_NOTIFY:
806 {
807 LPNMHDR lpnm = (LPNMHDR)lParam;
808
809 switch(lpnm->code)
810 {
811 case PSN_APPLY:
812 if(pData->bWallpaperChanged)
813 SetWallpaper(pData);
814 if(pData->bClrBackgroundChanged)
815 SetDesktopBackColor(hwndDlg, pData);
816 SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)_T(""));
817 return TRUE;
818
819 case LVN_ITEMCHANGED:
820 {
821 LPNMLISTVIEW nm = (LPNMLISTVIEW)lParam;
822
823 if ((nm->uNewState & LVIS_SELECTED) == 0)
824 return FALSE;
825
826 ListViewItemChanged(hwndDlg, pData, nm->iItem);
827 }
828 break;
829 }
830 }
831 break;
832
833 case WM_DESTROY:
834 if (pData->pWallpaperBitmap != NULL)
835 DibFreeImage(pData->pWallpaperBitmap);
836
837 DeleteObject(pData->hBitmap);
838 HeapFree(GetProcessHeap(), 0, pData);
839 break;
840 }
841
842 return FALSE;
843 }