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