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