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